Meyda Features (Audioplayer-Version) -> Mikrophon-Version

play stop

Feature Wert Bedeutung
RMS-Amplitude:
0
(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

  • Chroma (= Tonhöhenklassen),
  • MFCCs (Mel-frequency Cepstral Coefficients als Indikatoren für Klangfarbenähnlichkeit)
  • und Lautheit (auf der Basis von Frequenzgruppenbreiten).

In der Meyda-Vorlage werden alle Features von Meyda als Variablen und Arrays für den Einsatz in P5 zur Verfügung gestellt:

- Vorlage für Meyda/P5 in Verbindung mit dem AudioPlayer
- Vorlage für Meyda/P5 in Verbindung mit dem Mikrofoneingang

Mehr Informationen über die Features von Meyda gibt es auch unter
https://meyda.js.org/audio-features.

 

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:

<html>
<head>
<script src="header/meyda.min.js"></script>
</head>

<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:

<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

Darunter werden via <DIV>-Tags die Stellen markiert, an denen die Werte für die einzelnen Timbrefeatures ausgegeben werden

- RMS-Amplitude <DIV id="levelNumber"> 0 </DIV>
- Spectral Centroid <DIV id="centroidNumber"> 0 </DIV>
- Zero Crossing Rate <DIV id="zcrNumber"> 0 </DIV>
- Specteal Flatness <DIV id="spectralFlatnessNumber"> 0 </DIV>
- Energy <DIV id="energyNumber"> 0 </DIV>
- Spectral Slope <DIV id="spectralSlopeNumber"> 0 </DIV>
- Specral Rolloff <DIV id="spectralRolloffNumber"> 0 </DIV>
- Specral Spread <DIV id="spectralSpreadNumber"> 0 </DIV>
- Specral Skewness <DIV id="spectralSkewnessNumber"> 0 </DIV>
- Specral Kurtosis <DIV id="spectralKurtosisNumber"> 0 </DIV>
- Perceptual Spread <DIV id="perceptualSpreadNumber"> 0 </DIV>
- Perceptual Sharpness <DIV id="perceptualSharpnessNumber"> 0 </DIV>

 

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:

 

<head>
<script src="header/meyda.min.js"></script>

<script>
var schalter = 0;

function spielAudio() {
schalter = 1;
var meinplayer = document.getElementById('audio');
meinplayer.play();
}

function stopAudio() {
schalter = 0;
var meinplayer = document.getElementById('audio');
meinplayer.pause();
meinplayer.currentTime = 0;
}

var meinplayer = document.getElementById('audio');
meinplayer.onended = function() {
schalter = 0;
document.getElementById("levelNumber").innerHTML= "0";
document.getElementById("centroidNumber").innerHTML= "0";
document.getElementById("zcrNumber").innerHTML= "0";
document.getElementById("spectralFlatnessNumber").innerHTML= "0";
document.getElementById("energyNumber").innerHTML= "0";
document.getElementById("spectralSlopeNumber").innerHTML= "0";
document.getElementById("spectralRolloffNumber").innerHTML= "0";
document.getElementById("spectralSpreadNumber").innerHTML= "0";
document.getElementById("spectralSkewnessNumber").innerHTML= "0";
document.getElementById("spectralKurtosisNumber").innerHTML= "0";
document.getElementById("perceptualSpreadNumber").innerHTML= "0";
document.getElementById("perceptualSharpnessNumber").innerHTML= "0";
}
</script>

</head>
<body text="#000000" bgcolor="#FFFFFF">

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

- RMS-Amplitude <DIV id="levelNumber"> 0 </DIV>
- Spectral Centroid <DIV id="centroidNumber"> 0 </DIV>
- Zero Crossing Rate <DIV id="zcrNumber"> 0 </DIV>
- Specteal Flatness <DIV id="spectralFlatnessNumber"> 0 </DIV>
- Energy <DIV id="energyNumber"> 0 </DIV>
- Spectral Slope <DIV id="spectralSlopeNumber"> 0 </DIV>
- Specral Rolloff <DIV id="spectralRolloffNumber"> 0 </DIV>
- Specral Spread <DIV id="spectralSpreadNumber"> 0 </DIV>
- Specral Skewness <DIV id="spectralSkewnessNumber"> 0 </DIV>
- Specral Kurtosis <DIV id="spectralKurtosisNumber"> 0 </DIV>
- Perceptual Spread <DIV id="perceptualSpreadNumber"> 0 </DIV>
- Perceptual Sharpness <DIV id="perceptualSharpnessNumber"> 0 </DIV>

<script defer>
const audioContext = new AudioContext();
const htmlAudioElement = document.getElementById("audio");
const source = audioContext.createMediaElementSource(htmlAudioElement);
source.connect(audioContext.destination);
csfaktor = audioContext.sampleRate/512;

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", "spectralCentroid", "zcr", "spectralFlatness", "energy", "spectralSlope", "spectralRolloff", "spectralSpread", "spectralSkewness", "spectralKurtosis", "perceptualSpread", "perceptualSharpness"],
"callback": features => {
if (schalter ==1){
document.getElementById("levelNumber").innerHTML= Math.round(features.rms * 1000)/1000;
document.getElementById("centroidNumber").innerHTML= Math.round(features.spectralCentroid*csfaktor);
document.getElementById("zcrNumber").innerHTML= Math.round(features.zcr * 1000)/1000;
document.getElementById("spectralFlatnessNumber").innerHTML= Math.round(features.spectralFlatness * 1000)/1000;
document.getElementById("energyNumber").innerHTML= Math.round(features.energy * 1000)/1000;
document.getElementById("spectralSlopeNumber").innerHTML= Math.round(features.spectralSlope * 1000000000)/1000000000;
document.getElementById("spectralRolloffNumber").innerHTML= Math.round(features.spectralRolloff * 1000)/1000;
document.getElementById("spectralSpreadNumber").innerHTML= Math.round(features.spectralSpread * 1)/1;
document.getElementById("spectralSkewnessNumber").innerHTML= Math.round(features.spectralSkewness * 1000)/1000;
document.getElementById("spectralKurtosisNumber").innerHTML= Math.round(features.spectralKurtosis * 1000)/1000;
document.getElementById("perceptualSpreadNumber").innerHTML= Math.round(features.perceptualSpread * 1000)/1000;
document.getElementById("perceptualSharpnessNumber").innerHTML= Math.round(features.perceptualSharpness * 1000)/1000;
} else {
document.getElementById("levelNumber").innerHTML= "0";
document.getElementById("centroidNumber").innerHTML= "0";
document.getElementById("zcrNumber").innerHTML= "0";
document.getElementById("spectralFlatnessNumber").innerHTML= "0";
document.getElementById("energyNumber").innerHTML= "0";
document.getElementById("spectralSlopeNumber").innerHTML= "0";
document.getElementById("spectralRolloffNumber").innerHTML= "0";
document.getElementById("spectralSpreadNumber").innerHTML= "0";
document.getElementById("spectralSkewnessNumber").innerHTML= "0";
document.getElementById("spectralKurtosisNumber").innerHTML= "0";
document.getElementById("perceptualSpreadNumber").innerHTML= "0";
document.getElementById("perceptualSharpnessNumber").innerHTML= "0";
}
}
});
analyzer.start();
}
</script>

</body>