(Root
Mean Square = Quadratwurzel-)Amplitude zwischen 0 und 1
Spektral
Centroid:
0
Spektraler
Schwerpunkt in Hz
Zero
Crossing Rate:
0
Anzahl
der Nulldurchgänge pro Sekunde (-> Helligkeit)
Spektral
Flatness:
0
Spektrale
Ebenheit zwischen 0 und 1 = Wie "flach" oder verrauscht
ein Spektrum ist: 0 = purer Sinus, 1 = weißes Rauschen
Energy:
0
Integral
über die Amplitude (-> Lautstärkeeindrruck)
Spectral
Slope:
0
Neigung
des Spektrums zwischen 0 und 1 = wie geneigt die Hüllkurve über
das Spektrum ist (-> Aufschluss über den Energieanteil hoher
Frequenzen)
Spectral
Rolloff:
0
Frequenz, unter der 99% der Energie des Spektrums enthalten ist in
Hz
SpectralSpread:
0
Verteilung
des Frequenzinhalts über das Spektrum zwischen 0 und der Hälfte
der FFT-Buffer-Größe (default: 512) = ob das Spektrum mehr
tonal (niedrige Werte) oder verrauscht ist (hohe Werte).
SpectralSkewness:
0
Schräglage des Spektrums: Zeigt an, ob das Spektrum relativ zu
seinem Mittelwert in Richtung eines bestimmten Wertebereichs verzerrt
ist oder nicht:
negative Werte: Spektrum ist eher nach rechts vom Mittelwert verschoben
positive Werte: Spektrum ist eher nach links vom Mittelwert verschoben.
SpectralKurtosis:
0
Spektrale
Spitzheit zwischen 0 und 1, Gegenteil von Spectral Flatness: 0 = weißes
Rauschen, 1 = purer Sinus.
Perceptual
Spread:
0
Berechnet
die Streuung der spezifischen Lautheitskoeffizienten über die
Barkskala zwischen 0 und 1, Indikator für Vollheit/Reichheit
des Klangs:
0 = "leerer Klang", 1 = "voller Klang"
Perceptual
Sharpness:
0
Wahrgenommen
Schärfe eines Klangs (basierend auf der Lautheitsberechnung)
zwischen 0 und 1: 0 = stumpf/weich, 1 = scharf
Meyda ist
eine Javascript-Signalanalyse-Library, mit deren Hilfe man in Echtzeit
und online Audio Features berechnen kann.
Zusätzlich
zu den oben angegebenen Features gibt es die Berechnung von
Um mit Meyda
zu arbeiten, muss die dazu gehörende Javascript-Library unter https://unpkg.com/meyda/dist/web/meyda.min.js
heruntergeladen werden und in den Header der jeweiligen html-Seite eingebunden
werden.
Die mit Meyda
erstellten Scripte benötigen eine Server-Umgebung, um lauffähig
zu sein, d.h. das Ergebnis kann man erst sehen, wenn man alles auf einen
Server geladen hat. Unter https://glitch.com/
gibt es eine online-Umgebung, um Scripte direkt auszuprobieren.
Im folgenden
Beispiel befindet sich die Datei meyda.min.js
in dem Ordner "header", der sich am gleichen Ort wie die index.htm-Datei
befindet. Das Grundgerüst der index.htm-Datei sieht dann folgendermaßen
aus:
<body bgcolor="#FFFFFF" text="#000000"> (hier kommt dann der im Browser sichtbare Inhalt hin)
</body>
</html>
Eine typische
Meyda-Anwendung hat meist 5 Abschnitte,
die sich folgendermaßen auf einer html-Seite verteilen:
<html>
<head> // 1. Einbettung der Meyda-Library <script
src="header/meyda.min.js"></script>
// 2. Script zur Steuerung eines Audioplayers <script>
function spielAudio() { ...}
function stopAudio() {... } </script>
</head>
<body bgcolor="#FFFFFF" text="#000000">
//
3. Einbettung eines Audioplayers mit id und Steuerungsmöglichkeit <audio
id="audio" src="klang/fagott_toene.mp3"> </audio> <a
onClick=spielAudio(); style=cursor:pointer><u><b>play</b></u></a>
<a onClick=stopAudio(); style=cursor:pointer><u><b>stop</b></u></a>
// 4. Ausgabe der von Meyda ermittelten Werte
(z.B. RMS-Amplitude)
<DIV id="levelNumber"> 0 </DIV>
//
5. Ganz am Ende der Seite: Eigentliches Script um das WebAudioApi des
// Browsers zu starten und mit Meyda für die Analyse zu verbinden
// (z.B. um die RMS-Amplitude zu ermitteln) <script
defer> const audioContext = new AudioContext();
const htmlAudioElement = document.getElementById("audio");
const source = audioContext.createMediaElementSource(htmlAudioElement);
source.connect(audioContext.destination);
if (typeof Meyda === "undefined") {
alert("Meyda konnte nicht gefunden werden, wurde die Library nicht
eingebunden?");
} else {
const analyzer = Meyda.createMeydaAnalyzer({
"audioContext": audioContext,
"source": source,
"bufferSize": 512,
"featureExtractors": ["rms"],
"callback": features => {
if (schalter ==1){
document.getElementById("levelNumber").innerHTML= Math.round(features.rms
* 1000)/1000;
} else {
document.getElementById("levelNumber").innerHTML= "0";
}
}
});
analyzer.start();
}
</script>
</body>
</html>
In dieser
Seite wurden die Werte für die Audiodatei folgendermaßen ermittelt:
1. Einbettung der Meyda-Library
Zunächst
wird im <head> der
Seite die Meyda-Javascript-Bibliothek eingebettet:
<script src="header/meyda.min.js"></script>
2.
Script zur Steuerung eines Audioplayers
Dann wird
im <head> der Seite
ein Script zur Steuerung des Audioplayers angelegt:
<script>
var schalter = 0; // Variable für
einen Schalter anlegen, der immer dann auf 1 gestellt wird,
// sobald die Audio-Datei im Player gespielt wird (sonst auf 0).
function spielAudio()
{ // Funktion zum Abspielen des Audioplayers
schalter = 1; // stelle den Schalter auf
1
var meinplayer = document.getElementById('audio'); //
finde über
// getElementById() den Audioplayer mit der id "audio" und übergebe
ihn an die Variable meinPlayer.
meinplayer.play(); // starte den so gefundenen
Audioplayer
}
function stopAudio()
{ // Funktion zum Stoppen des Audioplayers
schalter = 0; // stelle den Schalter auf
0
var meinplayer = document.getElementById('audio'); //
finde über
// getElementById() den Audioplayer mit der id "audio" und übergebe
ihn an die Variable meinPlayer.
meinplayer.pause(); // pausiere den Player
meinplayer.currentTime = 0; // setze ihn
auf den Anfang des Stücks
}
var meinplayer = document.getElementById('audio');
// finde über
// getElementById() den Audioplayer mit der id "audio" und übergebe
ihn an die Variable meinPlayer.
meinplayer.onended = function() { // Sobald der Player geendet hat:
schalter = 0; // // stelle den Schalter
auf 0
document.getElementById("levelNumber").innerHTML= "0";
// Suche das Element
// "levelNumber" via getElementById() und setze die Ausgabe
via innerHTML auf 0.
document.getElementById("centroidNumber").innerHTML= "0";
// Suche das Element
// "centroidNumber"
via getElementById() und setze die Ausgabe via innerHTML auf 0.
document.getElementById("zcrNumber").innerHTML= "0";
// Suche das Element
// "zcrNumber"
via getElementById() und setze die Ausgabe via innerHTML auf 0.
document.getElementById("spectralFlatnessNumber").innerHTML=
"0"; // Suche // das Element
"spectralFlatnessNumber"
via getElementById() und setze die Ausgabe via innerHTML auf
// 0.
document.getElementById("energyNumber").innerHTML= "0";
// Suche das Element
// "energyNumber"
via getElementById() und setze die Ausgabe via innerHTML auf 0.
document.getElementById("spectralSlopeNumber").innerHTML= "0";
// Suche das // Element "spectralSlopeNumber"
via getElementById() und setze die Ausgabe via innerHTML auf 0.
document.getElementById("spectralRolloffNumber").innerHTML=
"0";// Suche das // Element "spectralRolloffNumber"
via getElementById() und setze die Ausgabe via innerHTML auf 0.
document.getElementById("spectralSpreadNumber").innerHTML= "0";//
Suche das // Element "spectralSpreadNumber"
via getElementById() und setze die Ausgabe via innerHTML auf 0.
document.getElementById("spectralSkewnessNumber").innerHTML=
"0"; // Suche
// das Element "spectralSkewnessNumber"
via getElementById() und setze die Ausgabe via innerHTML auf
// 0.
document.getElementById("spectralKurtosisNumber").innerHTML=
"0"; // Suche
// das Element "spectralKurtosisNumber"
via getElementById() und setze die Ausgabe via innerHTML auf
// 0.
document.getElementById("perceptualSpreadNumber").innerHTML=
"0"; // Suche
// das Element "perceptualSpreadNumber"
via getElementById() und setze die Ausgabe via innerHTML auf
// 0.
document.getElementById("perceptualSharpnessNumber").innerHTML=
"0";
// Suche das Element "perceptualSharpnessNumber"
via getElementById() und setze die Ausgabe via
// innerHTML auf 0.
}
</script>
3.
Einbettung eines Audioplayers mit id und Steuerungsmöglichkeit
Im <body>
der Seite wird der Player angelegt sowie die Auslöser zum Starten
und Stoppen des Players:
5.
Starten des WebAudioApi und Audio-Analyse mit Meyda
Ganz am Ende
der Seite wird das Script für die Analyse eingebaut.
<script defer> bedeutet, dass das Script nicht seriell im
Seitenaufbau eingebaut ist, sondern parallel zu den anderen Scripten und
Funktionen auf der Seite passiert:
<script defer>
const audioContext = new AudioContext(); //
erzeuge einen Audiokontext (ähnlich wie
// einen Canvas) für das WebAudioApi
const htmlAudioElement = document.getElementById("audio"); //
suche den
// Audioplayer via getElementById() und weise ihn der Variablen htmlAudioElement
zu.
const source = audioContext.createMediaElementSource(htmlAudioElement);
// füge den Audioplayer über
die Variable htmlAudioElement als Mediaquelle dem audioContext hinzu.
source.connect(audioContext.destination); //
verbinde den audioContext mit der
// Soundausgabe des Browsers/Computers.
csfaktor = audioContext.sampleRate/512*2; //
errechne über die Samplerate (geteilt
// durch 2 wegen Nyquist-Theorem) und den Audiobuffer (defaultmäßig
bei 512) einen Faktor
// (csfaktor), mit dem die Zahl für den SpectralCentroid multipliziert
werden muss, damit sie passt.
if (typeof Meyda ===
"undefined") { // falls die Meyda-Library
nicht erkannt wird:
alert("Meyda konnte nicht gefunden werden, wurde die Library nicht
eingebunden?"); // gebe eine Fehlermeldung
aus
} else { // in allen anderen Fällen:
const analyzer = Meyda.createMeydaAnalyzer({ //
erstelle einen Analyzer mit
// folgenden Eigenschaften:
"audioContext": audioContext, // audioContext,
auf den sich der Analyzer bezieht
"source": source, // Quelle auf
die sich der Analyzer bezieht (= der Audioplayer)
"bufferSize": 512, // Buffergröße
"featureExtractors": ["rms", "spectralCentroid",
"zcr", "spectralFlatness", "energy", "spectralSlope",
"spectralRolloff", "spectralSpread", "spectralSkewness",
"spectralKurtosis", "perceptualSpread", "perceptualSharpness"],
// Array (Liste) von zu analysierenden
// Eigenschaften
"callback": features => { //
Ausgabe der ermittelten Features
if (schalter ==1){ // sobald der Schalter
auf 1 steht (= Audioplayer spielt)
document.getElementById("levelNumber").innerHTML= Math.round(features.rms
* 1000)/1000; // Ausgabe der RMS-Amplitude
(auf 3 Stellen
// gerundet)
document.getElementById("centroidNumber").innerHTML= Math.round(features.spectralCentroid*csfaktor);
// Ausgabe des Spectral Centroids
// (multipliziert mit dem oben errechneten cf-Faktor und gerundet)
document.getElementById("zcrNumber").innerHTML= Math.round(features.zcr
* 1000)/1000; // Ausgabe der Zero Crossing
Rate (auf 3 Stellen gerundet)
document.getElementById("spectralFlatnessNumber").innerHTML=
Math.round(features.spectralFlatness * 1000)/1000; //
Ausgabe der Spectral
// Flatness (auf 3 Stellen gerundet)
document.getElementById("energyNumber").innerHTML= Math.round(features.energy
* 1000)/1000; // Ausgabe der Energy (auf
3 Stellen
// gerundet)
document.getElementById("spectralSlopeNumber").innerHTML= Math.round(features.spectralSlope
* 1000000000)/1000000000; // Ausgabe der
// Spectral Slope (auf 10 Stellen gerundet)
document.getElementById("spectralRolloffNumber").innerHTML=
Math.round(features.spectralRolloff * 1000)/1000; //
Ausgabe des Spectral
// Rolloffs (auf 3 Stellen gerundet)
document.getElementById("spectralSpreadNumber").innerHTML= Math.round(features.spectralSpread
* 1)/1; // Ausgabe der Spectral Spreads
document.getElementById("spectralSkewnessNumber").innerHTML=
Math.round(features.spectralSkewness * 1000)/1000; //
Ausgabe der Spectral
// Skewness (auf 3 Stellen gerundet)
document.getElementById("spectralKurtosisNumber").innerHTML=
Math.round(features.spectralKurtosis * 1000)/1000; //
Ausgabe der Spectral
// Kurtosis (auf 3 Stellen gerundet)
document.getElementById("perceptualSpreadNumber").innerHTML=
Math.round(features.perceptualSpread * 1000)/1000; //
Ausgabe des Perceptual
// Spreads (auf 3 Stellen gerundet)
document.getElementById("perceptualSharpnessNumber").innerHTML=
Math.round(features.perceptualSharpness * 1000)/1000; //
Ausgabe der Perceptual
// Sharpness (auf 3 Stellen gerundet)
} else { // falls der Schalter auf 0 steht:
document.getElementById("levelNumber").innerHTML= "0";
// Suche das Element
// "levelNumber" via getElementById() und setze die Ausgabe
via innerHTML auf 0.
document.getElementById("centroidNumber").innerHTML= "0";
// Suche das Element
// "centroidNumber"
via getElementById() und setze die Ausgabe via innerHTML auf 0.
document.getElementById("zcrNumber").innerHTML= "0";
// Suche das Element
// "zcrNumber"
via getElementById() und setze die Ausgabe via innerHTML auf 0.
document.getElementById("spectralFlatnessNumber").innerHTML=
"0"; // Suche // das Element
"spectralFlatnessNumber"
via getElementById() und setze die Ausgabe via innerHTML auf
// 0.
document.getElementById("energyNumber").innerHTML= "0";
// Suche das Element
// "energyNumber"
via getElementById() und setze die Ausgabe via innerHTML auf 0.
document.getElementById("spectralSlopeNumber").innerHTML= "0";
// Suche das // Element "spectralSlopeNumber"
via getElementById() und setze die Ausgabe via innerHTML auf 0.
document.getElementById("spectralRolloffNumber").innerHTML=
"0";// Suche das // Element "spectralRolloffNumber"
via getElementById() und setze die Ausgabe via innerHTML auf 0.
document.getElementById("spectralSpreadNumber").innerHTML= "0";//
Suche das // Element "spectralSpreadNumber"
via getElementById() und setze die Ausgabe via innerHTML auf 0.
document.getElementById("spectralSkewnessNumber").innerHTML=
"0"; // Suche
// das Element "spectralSkewnessNumber"
via getElementById() und setze die Ausgabe via innerHTML auf
// 0.
document.getElementById("spectralKurtosisNumber").innerHTML=
"0"; // Suche
// das Element "spectralKurtosisNumber"
via getElementById() und setze die Ausgabe via innerHTML auf
// 0.
document.getElementById("perceptualSpreadNumber").innerHTML=
"0"; // Suche
// das Element "perceptualSpreadNumber"
via getElementById() und setze die Ausgabe via innerHTML auf
// 0.
document.getElementById("perceptualSharpnessNumber").innerHTML=
"0";
// Suche das Element "perceptualSharpnessNumber"
via getElementById() und setze die Ausgabe via
// innerHTML auf 0.
}
}
});
analyzer.start(); // starte den Analyzer
}
</script>
Insgesamt
sieht das Script dann folgendermaßen aus: