Einfache Umsetzung zur Tonerkennung
(EN google-translate)
(PL google-translate)
- Methode: Der aktuelle Input-Puffer wird von sich selber phasenverschoben abgezogen.
- Dies geschieht für die drei Sample-Phasen 63,42 und 28.
- Werden die quadrierten Differenzen aufsummiert, so würde idealerweise dann wenn der erste Ton erklingt die erste Summe Null werden, beim zweiten die zweite, beim dritten die dritte.
|
- ACHTUNG: Auch diese Anwendung funktioniert nur mit Opera oder Chrome. Dagegen stoppt Firefox die Aufzeichnung nach ein paar Sekunden.
|
<!DOCTYPE html>
<html>
<head lang="de">
<meta charset="iso-8859-1">
<script language:javascript>
//Um für andere Anwendungen je einen Strereo-In- und Output frei zu halten,
//wird Stereo-Duplex angefordert, aber nur je ein Eingangs und ein Ausgangskanal benutzt.
var ZAEHLER = 0;
//Samplingrate: 44100
//Periode für 700Hz entspricht DZ=63 Zählschritten.
//Periode für 1050Hz entspricht DZ=42 Zählschritten.
//Periode für 1575Hz entspricht DZ=28 Zählschritten.
var DZ = 63;
//var DZ = 42;
//var DZ = 28;
var malkontext = null;
//Idee zur Frequenzerkennung:
//Zieht man das aktuelle Signal um die erwartete Periode phasenverschoben ab,
//ergibt sich im Idealfall 0.
//Dies wird für die drei möglichen Perioden als Kennzahl berechnet:
var kennzahl = [0,0,0];
var kennzahl_phase = [63,42,28];
var signal_nummer = 0; //0==kein Signal, 1==Ton 1, 2==Ton2, 3==Ton3
var SCHWELLE = 5;
function prozess(e)
{
var data_in = e.inputBuffer.getChannelData(1);
var data_out = e.outputBuffer.getChannelData(1);
malkontext.fillStyle = "#000000";
malkontext.fillRect(0,0,1024,1000);
malkontext.strokeStyle="#ffffff";
malkontext.beginPath();
var x1 = 0;
var y1 = data_in[0]*200+200;
malkontext.moveTo(x1,y1);
for (var i = 0; i < data_in.length; i++)
{
var x2 = i;
var y2 = data_in[i]*200+200;
malkontext.lineTo(x2,y2);
}
malkontext.stroke();
for (var i = 0; i < data_out.length; ++i)
{
if(ZAEHLER<14)
data_out[i] = 0.5;
else
data_out[i] = 0.0;
ZAEHLER++;
ZAEHLER%=DZ;
}
//Berechnung der drei Kennzahlen:
for(var k=0;k<kennzahl.length;k++)
{
kennzahl[k]=0;
var phase = kennzahl_phase[k];
var wert = 0;
for(var i=0;i<data_in.length;i++)
{
wert = data_in[i] - data_in[(i+phase)%data_in.length];
wert = wert*wert;
kennzahl[k]+=wert;
}
document.getElementById("K"+(k+1)).innerHTML=""+kennzahl[k];
}
//Signalnummer aus Kennzahl bestimmen:
if(kennzahl[1]/kennzahl[0]>SCHWELLE && kennzahl[2]/kennzahl[0]>SCHWELLE)
signal_nummer = 1;
else if(kennzahl[0]/kennzahl[1]>SCHWELLE && kennzahl[2]/kennzahl[1]>SCHWELLE)
signal_nummer = 2;
else if(kennzahl[0]/kennzahl[2]>SCHWELLE && kennzahl[1]/kennzahl[2]>SCHWELLE)
signal_nummer = 3;
else
signal_nummer = 0;
if(signal_nummer==0)
document.getElementById("SIGNALNUMMER").innerHTML="KEIN TON";
else if(signal_nummer==1)
document.getElementById("SIGNALNUMMER").innerHTML="TON 1";
else if(signal_nummer==2)
document.getElementById("SIGNALNUMMER").innerHTML="TON 2";
else if(signal_nummer==3)
document.getElementById("SIGNALNUMMER").innerHTML="TON 3";
}
function tonwechsel()
{
if(DZ==63)
DZ=42;
else if(DZ==42)
DZ=28;
else if(DZ==28)
DZ=500; //Ungültiger Ton / Geräusch
else
DZ=63;
}
function initialisieren(e)
{
malkontext = document.getElementById("grafik").getContext("2d");
var context = new (window.AudioContext || window.webkitAudioContext)();
var volume = context.createGain(); //Ohne Volume-Knoten bleibt der Eingang stumm!
var audioInput = context.createMediaStreamSource(e);
audioInput.connect(volume);
//1. Param.: Erlaubte Puffergroessen: 256, 512, 1024, 2048, 4096, 8192, 16384
//2. Param.: Anzahl der Input-Kanaele
//3. Param.: Anzahl der Output-Kanaele
var node = context.createScriptProcessor(1024, 2, 2);
node.onaudioprocess = function(e) { prozess(e) };
volume.connect (node);
volume.gain.value=1.0;
node.connect(context.destination); //"record"
setInterval(tonwechsel,2000);
}
if (!navigator.getUserMedia)
{
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia || navigator.msGetUserMedia;
}
if (navigator.getUserMedia)
{
//Mikrofon-Zugriff beim Benutzer anfordern
navigator.getUserMedia({audio:true}, initialisieren, function(e) {
alert('Error capturing audio.');
});
}
else
{
alert('getUserMedia not supported in this browser.');
}
</script>
</head>
<body>
<canvas id="grafik" width="1024" height="400"></canvas>
<h2>Kennzahl 1 = <span id="K1"></span></h2>
<h2>Kennzahl 2 = <span id="K2"></span></h2>
<h2>Kennzahl 3 = <span id="K3"></span></h2>
<h2>Erkannt wird: <span id="SIGNALNUMMER"></span></h2>
</body>
</html>
Code 0-1: Minimalsistischer Code zur Tonerkennung.
Kennzahl 1 =
Kennzahl 2 =
Kennzahl 3 =
Erkannt wird: