P5 und P5.sound - Oktavbänder



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 ide 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
}

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 spectrum = fft.analyze(); // mache eine Spektralanalyse in der Länge des aktuellen
// Frames und schreibe sie ins Array spectrum
var baender = map(mouseX, 0, width, 1, 31);//falls die Anzahl der Bänder von
// der Mausposition abhängig gemacht werden sollen (sonst einfach eine Zahl für baender einsetzen)

if (baender<1){baender=1;}
// damit die Anzal der Bänder nicht kleiner 1 wird
var baender_array = fft.logAverages(fft.getOctaveBands(baender));
// Den
// Mittelwert über die Oktavbänder und deren Unterteilungen in das Array baender_array übergeben

noStroke(); // keine Strichfarbe
fill(188, 48, 47); // Füllfarbe auf dunkelrot festlegen
text('Bandbreite: 1/'+ round(baender) +'-Oktave', 10, 20);
// Text mit der
// Anzeige, in wieviele Bänder pro Oktave das Spektrum unterteilt wird

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

var x = map(i, 0, baender_array.length, 0, width);// skaliere die aufsteigend
// gezählten Zahlen i (von 0 bis Ende des spectrum baender_array) so, dass sie von 0 bis zur
// Weite des Canvas dargestellt werden und weise sie der Variablen x zu (Frequenz auf der X-Achse).

var h = -height + map(baender_array[i], 0, 255, height, 0); // skaliere jeden
// Wert aus dem Array
baender_array, der zwischen 0 und 255 liegt, so, dass er zwischen der Höhe
// des Canvas und 0 dargestellt wird, und ziehe ihn von der Höhe des Canvas ab (damit die
// Amplitudenwerte für die einzelnen Frequenzen nicht auf dem Kopf dargestellt werden). Weise ihn
// dann dem Wert y zu (Amplituden der einzelnen Frequenzbänder auf der Y-Achse)

rect(x, height, 5, h ); // zeichne pro Frequenzbereih ein Rechteck mit den
// Ausgangskoordinaten x und der Höhe des Canvas (= an der untere Kante), einer Breite von 5 Pixeln // und einer Höhe h.

}
}

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('p5container');
container.mouseClicked(togglePlay);
fft = new p5.FFT();
sound.amp(0.5);
}

function draw(){
background(255, 255, 255);
cursor(HAND);
var spectrum = fft.analyze();
var baender = map(mouseX, 0, width, 1, 31);
if (baender<1){baender=1;}
var baender_array = fft.logAverages(fft.getOctaveBands(baender));
noStroke();
fill(188, 48, 47);
text('Bandbreite: 1/'+ round(baender) +'-Oktave', 10, 20);
for (var i = 0; i< baender_array.length; i++){
var x = map(i, 0, baender_array.length, 0, width);
var h = -height + map(baender_array[i], 0, 255, height, 0);
rect(x, height, 5, h );
}
}

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>