P5
und P5.sound - Spektrum mit Spectral Centroid
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
spectralCentroid = fft.getCentroid(); //
Spectral Centroid (in Hz) holen
mean_freq_index = spectralCentroid/sound.sampleRate()/2/spectrum.length;
// über die Samplerate/2 (wegen Nyquist-Theorem) und die spektrale
Auflösung (spectrum.length) die
// Postion des Spectral Centroids in der Darstellung ermitteln.
centroidplot = map(mean_freq_index, 0, spectrum.length, 0, width);
//
//
Frequenz des Spectral Centroids
von 0 bis maximaler Frequenz des Spektrums auf 0 bis maximale
//
Weite des Canvas skalieren
und den Wert als x-Koordinate für die Plotanzeige an centroidplot
// zurückgeben.
stroke(0,0,0);
// Strichfarbe auf schwarz setzen
fill(188, 48, 47); // Füllfarbe auf
Dunkelrot setzen
rect(centroidplot*8, 100, width / spectrum.length, height-100); //
Rechteck
//
zeichnen mit centroidplot
als x-Koordinate (mal 8, da das Spektrum auch mal 8 genommen wird,
//
s.u.), 100 als y-Koordinate,
der Weite geteilt durch die spektrale Auflösung als Breite und
//
einer Höhe 100 Pixel
unter dem oberen Rand des Canvas als Höhe.
noStroke(); // keine Strichfarbe
text('Spectral Centroid: ', 10, 20); //
Text bei den Koordinanten 10,20 schreiben
text(round(spectralCentroid)+' Hz', 10, 40); //
mathematisch gerundeten Wert des
//
Spectral Centroid ausgeben
noStroke(); // keine Strichfarbe
for (var i = 0; i< spectrum.length; i++){ //
hole in einer Schleife in der Länge
// des Arrays spectrum jeden einzelnen Wert i aus dem Array (= jeden Frequenzbereich)
var x = map(i, 0, spectrum.length, 0, width*8); //
skaliere die aufsteigend
// gezählten Zahlen i (von 0 bis Ende des spectrum Arrays) so, dass
sie von 0 bis zur achtfachen
// Weite des Canvas dargestellt werden (da in den höheren Frequenzanteilen
so gut wie keine
// Amplituden sind) und weise sie der Variablen x zu (Frequenz auf der
X-Achse).
var h = -height + map(spectrum[i], 0, 255, height, 0);
// skaliere jeden Wert
// aus dem Array spectrum, 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 Frequenzen auf der Y-Achse)
rect(x, height, width / spectrum.length, h ); //
zeichne pro Frequenz ein Rechteck
// mit den Ausgangskoordinaten x und der Höhe des Canvas (= an der
untere Kante), einer Breite, die
// unabhängig von der Größe des spektralen Arrays (spectrum)
immer die richtige ist, um insgesamt
// den Canvas in der Breite zu füllen, 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,80);
cursor(HAND);
var spectrum = fft.analyze();
spectralCentroid = fft.getCentroid();
var mean_freq_index = spectralCentroid/sound.sampleRate()/2/spectrum.length;
centroidplot = map(mean_freq_index, 0, spectrum.length, 0, width);
stroke(0,0,0);
fill(188, 48, 47);
rect(centroidplot*8, 100, width / spectrum.length, height-100);
noStroke();
text('Spectral Centroid: ', 10, 20);
text(round(spectralCentroid)+' Hz', 10, 40);
noStroke();
for (let i = 0; i< spectrum.length; i++){
let x = map(i, 0, spectrum.length, 0, width*8);
let h = -height + map(spectrum[i], 0, 255, height, 0);
rect(x, height, width / spectrum.length, 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>
|