Kombination
von P5 und Plotly
Zunächst
werden im <head>
der Seite sowohl das Script für Plotly als auch die beiden Scripte
für P5 und P5.sound eingebunden:
<script src="header/plotly-latest.min.js"></script>
<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>
In diesen
Container wird der Anzeige-Container für Plotly eingebettet:
<DIV id="p5container"
>
<div id="AnzeigeDiv" >
</div>
</DIV>
über
Style-Eigenschaften kann man diesen noch weiter im Aussehen verändern,
z.B.
<DIV id="p5container"
>
<div id="AnzeigeDiv" style="width:800;height:400;border:
1px solid #333;box-shadow: 8px 8px 5px #444;padding: 8px 12px;background-color:ffffff;">
</div>
</DIV>
Das dazugehörende
Script ist eine Mischung aus P5- und Plotly-Script: zunächst werden
zwei Arrays definiert:
var zeit_array = [];
// Array für die Samplepositionen
(Zeit)
var peaks_array =[]; // Array für
die Samplewerte (Amplituden)
Dann wird
in der Funktion preload()
das Audiobeispiel vorausgeladen und mit sound_fertiggeladen
bestimmt, was passieren soll, sobald das Audio komplett geladen ist.
function preload() {
sound = loadSound('klang/fagott_toene.mp3', sound_fertiggeladen);
// lade einen Klang, übergebe ihn an die Variable "sound",
und sobald er fertig geladen ist, führe
// die Funktion sound_fertiggeladen() aus.
}
Dann wird
in der Funktion setup() der
Canvas erstellt und an das DIV "p5container"
angehängt:
function setup() {
var container = createCanvas(1,1); // Canvas
erstellen, muss nur 1 Pixel groß sein
container.parent('p5container'); //
an DIV-Container anhängen
}
Danacg wird
in der Funktion sound_fertiggeladen()
beschrieben,
was passieren soll, sobald der Klang fertig geladen ist:
function sound_fertiggeladen(){
samplepunkte = round(sound.sampleRate()/2 * sound.duration()); //
ermittle
// aus der Hälfte der Sample-Rate (wegen Nyquist-Theorem) und der
Dauer des Klangs die Anzahl der
// Samplepunkte innerhalb der Datei
peaks_array = sound.getPeaks(samplepunkte); //
hole via getPeaks() für alle
// Samplepunkte
die Amplitudenwerte
und schreibe sie in das Array peaks
for (i = 0; i < peaks_array.length; i++){
// für jeden Punkt im Array peaks:
zeit_array.push(i); // gibt einen Wert
i ins Array Zeit (=Reihenfolge der Samplepunkte)
}
Aus den nun
gefüllten Arrays für Zeit und Peaks, kann das Trace für
Plotly erstellt werden (s. Anleitung für Plotly-Scripte):
var trace1 = {
x: zeit_array,
y: peaks_array,
mode: 'lines',
type: 'scatter' ,
name: 'Amplitude',
marker: {
color: 'rgba(188, 48, 47, 0.8)',
line: {
color: 'rgba(188, 48, 47, 1.0)',
width: 1,
},
},
text: zeit_array,
};
Diese Trace
wird dem Data-Array zugewiesen
var data = [ trace1,];
Dann wird
das Layout bestimmt:
var layout = {
showlegend: true,
xaxis: {
title: 'Samples',
},
yaxis: {
title: 'Amplitude',
},
legend: {
font: { family: 'Verdana, sans-serif', size: 10, color: 'black', }
},
title: 'Oszillogramm',
};
Und die Darstellung
der Wellenform ausgeplottet:
Plotly.plot('AnzeigeDiv',
data, layout, {displayModeBar: false});
Für
die Audio-Synchronisierung holt man sich via document.getElementById();
die Ausgabe des Plotly-Plots auf der Seite (AnzeigeDiv)
und beschreibt, was bei einem MouseOver (plotly_hover)
passieren soll und was bei einem MouseOut (plotyl_unhover):
myPlot = document.getElementById('AnzeigeDiv');
// hole die Ausgabe von Plotly
// auf der html-Seite
myPlot.on('plotly_hover', function(data){ //
bei einem MouseOver suche im Array
// data ...
var ausgabe = data.points.map(function(d){ //
... die folgenden Eigenschaften des Punkts d (= Datenpunkt, über
dem die Maus gerade ist):
indexTrace = d.curveNumber; // die Nummer
der Kurve, zu der der Punkt gehört
indexNummer = d.pointNumber; // die Position
des Punkts auf der gefundenen Kurve
audiofaktor = zeit_array.length / sound.duration(); //
ermittle mit Hilfe der
// Dauer des Klangbeispiels und der Länge des zeit-Arrays einen Teilungsfaktor,
durch den die
// Position des Punkts auf der gefundenen Kurve auf die zeitliche Position
im Audiobeispiel
// übertragen werden kann.
sound.play(); // spiele das Audiobeispiel
ab und ...
sound.jump(indexNummer/audiofaktor); //...
springe zur entsprechenden Stelle im
// Audiobeispiel
}); // Ende der funktion(d)
}) // Ende der function(data)
.on('plotly_unhover', function(data){ //
bei einem MouseOut ...
sound.pause(); // ... pausiere das Audiobeispiel
});
} //
die letzte Klammer schließt die Funktion sound_fertiggeladen()
Insgesamt
sieht das Script dann folgendermaßen aus:
<script src="header/plotly-latest.min.js"></script>
<script src="header/p5.js"></script>
<script src="header/p5.sound.js"></script>
var zeit_array = [];
var peaks_array =[];
function preload()
{
sound = loadSound('klang/fagott_toene.mp3', sound_fertiggeladen);
}
function setup() {
var container = createCanvas(1,1);
container.parent('p5container');
}
function sound_fertiggeladen(){
samplepunkte = round(sound.sampleRate()/2 * sound.duration());
peaks_array = sound.getPeaks(samplepunkte);
for (i = 0; i < peaks_array.length; i++){
zeit_array.push(i);
}
//Ab hier eine Trace für Plotly erstellen
var trace1 = {
x: zeit_array,
y: peaks_array,
mode: 'lines',
type: 'scatter' ,
name: 'Amplitude',
marker: {
color: 'rgba(188, 48, 47, 0.8)',
line: {
color: 'rgba(188, 48, 47, 1.0)',
width: 1,
},
},
text: zeit_array,
};
var data = [ trace1,];
var layout = {
showlegend: true,
xaxis: {
title: 'Samples',
},
yaxis: {
title: 'Amplitude',
},
legend: {
font: { family: 'Verdana, sans-serif', size: 10, color: 'black', }
},
title: 'Oszillogramm',
};
Plotly.plot('AnzeigeDiv',
data, layout, {displayModeBar: false});
myPlot = document.getElementById('AnzeigeDiv');
myPlot.on('plotly_hover', function(data){
var ausgabe = data.points.map(function(d){
indexTrace = d.curveNumber;
indexNummer = d.pointNumber;
audiofaktor = zeit_array.length / sound.duration();
sound.play();
sound.jump(indexNummer/audiofaktor);
});
})
.on('plotly_unhover', function(data){
sound.pause();
});
}
</script>
<DIV id="p5container"
>
<div id="AnzeigeDiv" style="width:800;height:400;border:
1px solid #333;box-shadow: 8px 8px 5px #444;padding: 8px 12px;background-color:ffffff;">
</div>
</DIV>
|