kramann.info
© Guido Kramann

Login: Passwort:










6.1.3 Einfache Umsetzung zur Tonerkennung

6.1.3 Simple implementation for sound recognition (EN google-translate)

6.1.3 Prosta implementacja do rozpoznawania dźwięku (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 6.1.3-1: Minimalsistischer Code zur Tonerkennung.

Kennzahl 1 =

Kennzahl 2 =

Kennzahl 3 =

Erkannt wird: