P5
und P5.sound - Equalizer in Echtzeit
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>
Beim Equalizer-Modul
lassen sich 3-8 Frequenzbereiche einstellen, die im Script vorab mit Hilfe
eines Arrays und eriner Variable für den Index für das Array
definiert werden sollten:
var eq_Band_Frequenzen_Array
= [63, 125, 250, 500, 1000, 2000, 4000, 8000]; //
Array mit Frequenzbändern definieren
var eq_Band_Index = 0; // Index für
das Array definieren
Danach ist
das 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'); //
Audio vorausladen
}
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
eq = new p5.EQ(eq_Band_Frequenzen_Array.length);//
Equalizer 3-8 Bandpassfiltern erstellen, die im eq_Band_Frequenzen_Array
definiert sind.
sound.disconnect(); // geladenen Klang
(sound) von der direkten Audioausgabe trennen
eq.process(sound); // geladenen Klang (sound)
an Filter anschließen
}
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 eq_Band_Index =
round(map(mouseX, width-100, 100, 7, 0)); //
skaliere
//
die X-Koordinate der Maus
zwischen 0 und der Weite des Canvas (-100) auf einen Wertebereich
//
zwischen 7 und 0 und weise
die Zahl der Variablen für den EQ-Band-Index zu.
if (eq_Band_Index<0){eq_Band_Index=0;}
//
Falls der Wert <0 ist,
setze ihn auf 0.
if (eq_Band_Index>7){eq_Band_Index=7;}
//
Falls
der Wert >7 ist, setze ihn auf 7.
var resonanz = map(mouseY, height,
0, 0, 5); //
skaliere die Y-Koordinate der Maus
// zwischen 0 und der Höhe des Canvas auf einen Wertebereich zwischen
0 und 5 und weise die Zahl
// der Variablen für Filter-Resonanz des jeweiligen Freqenzbands
zu.
noStroke(); //
keine Strichfarbe
fill(188, 48,
47); // Füllfarbe auf ein dunkles
rot setzen
text("Filterband: "+ eq_Band_Frequenzen_Array[eq_Band_Index]
+' Hz', 20, 20);
// Frequenz des gewählten Filterbands
ausgeben
text("Resonanz: "+ round(resonanz), 20, 40);
// Resonanz des gewählten Filterbands
// ausgeben
for (let i = 0; i < eq.bands.length; i++) {
// Schleife für alle Filterbänder:
eq.bands[i].gain(-20);
// verringere
ihren Wert auf -20.
}
// für das jeweils ausgewälte
Filterband stelle folgendes ein:
eq.bands[eq_Band_Index].setType("peaking"); //
stelle das Filterband auf
// spitzflankingen Bandpass ein (andere Möglichkeiten: "lowpass",
"highpass", "bandpass",
// "lowshelf", "highshelf", "notch" und
"allpass")
eq.bands[eq_Band_Index].gain(60); // verstärke
das ausgewählte Filterband um 60 Einheiten.
eq.bands[eq_Band_Index].freq(eq_Band_Frequenzen_Array[eq_Band_Index]);
// wähle über eq_Band_Index die entsprechende Filterfrequenz
aus dem Array (-> mouseX).
eq.bands[eq_Band_Index].res(resonanz);
// stelle die ausgewählte Resonanzfrequenz
ein (-> mouseY)
var waveform = fft.waveform();
// hole aus dem Klang alle Pegelwerte und
schreibe sie
// ins Array waveform
noFill(); //
keine Formen farblich ausfüllen (keine Füllfarbe)
beginShape(); // das Zeichnen einer Form
beginnen
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 x = map( i, 0, waveform.length, 0, width); //
skaliere die aufsteigend
// gezählten Zahlen i (von 0 bis Ende des waveform Arrays) so, dass
sie von 0 bis zur Weite des
// Canvas dargestellt werden und weise sie der Variablen x zu (Zeit auf
der X-Achse).
var y = map( waveform[i], -1, 1, 0, height);//
skaliere jeden Wert aus dem
// Array waveform, der zwischen -1 und 1 liegt, so, dass er zwischen 0
und der Höhe des Canvas
// dargestellt wird, und weise ihn dem Wert y zu (Amplitude auf der Y-Achse)
vertex(x,y-100); // weise x und y als Koordinaten
eines Punkts zu, der einen Eckpunkt der
// dazustellenden Gesamtform (via beginshape(); s.o.) beschreibt.
}
endShape(); //
Schließe die Gesamtform ab, in ihr ist dann ein Ausschnitt der Wellenform
pro
// Frame dargestellt.
var spectrum = fft.analyze();
// mache eine Spektralanalyse in der Länge
des aktuellen
// Frames und schreibe sie ins Array spectrum
noStroke(); //
keine Striche farblich ausfüllen (keine Strichfarbe)
fill(188, 48, 47); // Füllfarbe auf
ein dunkles rot setzen
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>
var eq_Band_Index = 0;
var eq_Band_Frequenzen_Array = [63, 125, 250, 500, 1000, 2000, 4000,
8000];
function preload()
{
sound = loadSound('klang/fagott_toene.mp3');
}
function setup() {
var container = createCanvas(800,400);
container.parent('p5container');
container.mousePressed(toggleSound);
fft = new p5.FFT();
sound.amp(0.5);
eq = new p5.EQ(eq_Band_Frequenzen_Array.length);
sound.disconnect();
eq.process(sound);
}
function draw() {
background(255,255,255);
var eq_Band_Index = round(map(mouseX, width-100, 100, 7, 0));
if (eq_Band_Index<0){eq_Band_Index=0;}
if (eq_Band_Index>7){eq_Band_Index=7;}
var resonanz = map(mouseY, height, 0, 0, 5);
noStroke();
fill(188, 48, 47);
text("Filterband: "+ eq_Band_Frequenzen_Array[eq_Band_Index]
+' Hz', 20, 20);
text("Resonanz: "+ round(resonanz), 20, 40);
for (let i = 0; i
< eq.bands.length; i++) {
eq.bands[i].gain(-20);
}
eq.bands[eq_Band_Index].setType("peaking");
eq.bands[eq_Band_Index].gain(60);
eq.bands[eq_Band_Index].freq(eq_Band_Frequenzen_Array[eq_Band_Index]);
eq.bands[eq_Band_Index].res(resonanz);
var waveform = fft.waveform();
noFill();
beginShape();
for (let i = 0; i < waveform.length; i++){
stroke(225, 225, 225);
var x = map(i, 0, waveform.length, 0, width);
var y = map( waveform[i], -1, 1, 0, height);
vertex(x,y-100);
}
endShape();
var spectrum = fft.analyze();
noStroke();
fill(188, 48, 47);
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 toggleSound()
{
if (!sound.isPlaying()) {
sound.play();
} else {
sound.pause();
}
}
</script>
<DIV id="p5container"
style="width:800;border: 1px solid #333;box-shadow: 8px 8px 5px
#444;padding: 8px 12px;background-color:ffffff"></DIV>
|