P5 und P5.sound - Nachhall



Zunächst werden im <head> der Seite die beiden Scripte für P5 und P5.sound eingebunden:

<script src="header/p5.js"></script>
<script src="header/p5.sound.js"></script>

Dann wird im <body> der Seite ein Container mit einer eindeutigen id mithilfe von DIV-Tags angelegt, in dem alles angezeigt werden soll. Dies geschieht via

<DIV id="p5container"></DIV>

über Style-Eigenschaften kann man diesen noch weiter im Aussehen verändern, z.B.

<DIV id="p5container" style="width:800;border: 1px solid #333;box-shadow: 8px 8px 5px #444;padding: 8px 12px;background-color:ffffff"></DIV>

Das dazugehörende Script ist wie fast alle P5 Scripte aufgebaut:
Erst werden über die Funktion preload() größere Dateien vorausgeladen:

function preload(){
sound = loadSound('klang/fagott_toene.mp3');
}

Dann werden in der Funktion setup() die Grundkomponenten festgelegt:

function setup(){
var container = createCanvas(800,400); // Canvas erstellen
container.parent('p5container'); // an DIV-Container anhängen
container.mouseClicked(togglePlay); // auf Klick auf Canvas reagieren
fft = new p5.FFT(); // Fouriertransformation des Signals ermöglichen
sound.amp(0.5); // Amplitude des vorausgeladenen Klangs "sound" auf die Hälfte reduzieren
sound.disconnect(); // geladenen Klang (sound) von der direkten Audioausgabe trennen

reverb = new p5.Reverb(); // Reverb erstellen
reverb.process(sound, 3, 2); //Nachhall zum Audiobeispiel "sound" hinzufügen mit 3 Sekunden Nachhallzeit (reverbTime) und einer Abstiegsflanke von 2% (decayRate).
}

Daraufhin wird in der Funktion draw() beschrieben, was im Canvas dargestellt werden soll:

function draw(){
background(255, 255, 255); //zeichne weißen Hintergrund

cursor(HAND); // zeige den Cursor als Hand

var dryWet = map(mouseY, 0, height, 1, 0); // skaliere die Y-Koordinate der Maus
// zwischen 0 und der Höhe des Canvas auf einen Wertebereich zwischen 1 und 0 und weise die Zahl
// der Variablen für das Verhältnis zwischen Effekt und "trockenen" Audiokanal zu (1 = nur
// Nachhall, 0 = kein Nachhall).
reverb.drywet(dryWet);
// bestimme den Anteil zwischen Nachhall und trockenem Audiokanal.

var waveform = fft.waveform(); // hole aus dem Klang alle Pegelwerte und schreibe sie
// ins Array waveform

for (var i = 0; i < waveform.length; i++){ // hole in einer Schleife in der Länge
// des Arrays waveform jeden einzelnen Wert i aus dem Array

var y = map( waveform[i], -1, 1, 0, height*2);// skaliere jeden Wert aus dem
// Array waveform, der zwischen -1 und 1 liegt, so, dass er zwischen 0 und der doppelten Höhe des
// Canvas dargestellt wird, und weise ihn dem Wert y zu (Durchmesser des Kreises)

ellipse(mouseX, mouseY, y-400, y-400);// Zeichne einen Kreis an der Mausposition
// (x,y) und lasse seinen Durchmesser vom eben ermittelten Pegel (y) bestimmen.

noStroke(); // keine Strichfarbe = keinen Rand für den Kreis
fill(188, 48, 47); // Dunkelrot als Füllfarbe
}

text('Nachhall: ', 10, 20); // Schreibe "Nachhall: "
text('Anteil: '+dryWet, 10, 40); //gebe den Wert des Nachhall-Anteils aus.
}

Schließlich wird mit der Funktion togglePlay() beschrieben, was passieren soll, wenn auf den Canvas geklickt wird

function togglePlay() {
if (sound.isPlaying()) { // wenn der Klang "sound" gespielt wird
sound.pause(); // stoppe ihn
} else { // in allen anderen Fällen
sound.play(); // spiele ihn ab.
}
}

Insgesamt sieht das Script dann folgendermaßen aus:

<script src="header/p5.js"></script>
<script src="header/p5.sound.js"></script>

<script>
function preload(){
sound = loadSound('klang/fagott_toene.mp3');
}

function setup(){
var container = createCanvas(800,400);
container.parent('p5canvas1');
container.mouseClicked(togglePlay);
fft = new p5.FFT();
sound.amp(0.5);
sound.disconnect();
reverb = new p5.Reverb();
reverb.process(sound, 3, 2); //3 second reverbTime, decayRate of 2%
}

function draw(){
background(255, 255, 255);
cursor(HAND);
var dryWet = map(mouseY, 0, height, 1, 0);
reverb.drywet(dryWet);

var waveform = fft.waveform();
for (var i = 0; i < waveform.length; i++){
var y = map( waveform[i], -1, 1, 0, height*2);
ellipse(mouseX, mouseY, y-400, y-400);
noStroke();
fill(188, 48, 47);
}
text('Nachhall: ', 10, 20);
text('Anteil: '+dryWet, 10, 40);
}

function togglePlay() {
if (sound.isPlaying()) {
sound.pause();
} else {
sound.play();
}
}
</script>

<DIV id="p5container" style="width:800;border: 1px solid #333;box-shadow: 8px 8px 5px #444;padding: 8px 12px;background-color:ffffff"></DIV>