Hinzufügen der Empfangs-Funktionalität
(EN google-translate)
(PL google-translate)
03_empfangen.zip - Projektdateien.function Audiotransfer() { const TONDAUER_PROZ_ZYKLEN = 20; //Hiervon hängt die Geschwindigkeit der Datenübertragung ab. const SCHWELLE = 5; //Faktor zwischen kennzahlen von gefundenem und nicht gefundenem Ton const AUDIO_PUFFER_GROESSE = 2048; const TOENE = [500,63,42,28]; var audiopuffer = new Array(AUDIO_PUFFER_GROESSE); var DATA_IN = null; var ZAEHLER = 0; var DURCHLAUF = 0; // Anzahl Durchläaufe von prozess(e) wg. tonwechsel() var DZ = TOENE[0]; 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 sendepuffer = new Array(); var merker = new Array(8); //Hilfsvariable für sendeZahl() //********************************************************************************** //Variablen im Zusammenhang mit dem Empfang von Zeichen: var zahl_empfangen = 0; //Wert der aktuell empfangenen Zahl var empfangspuffer = new Array(); //Puffer mit empfangenen Zahlen var EMPFANGSZUSTAND = 0; //0==KEIN TON, //1==1. Teil von Bit 7, 2==2. Teil von Bit 7, //3==erster Teil von Bit 6 usw. //erlaubt: 0, 1,2, 3,4 5,6, 7,8, 9,10, 11,12, 13,14, 15,16 const TIMEOUT_PROZ_ZYKLEN = TONDAUER_PROZ_ZYKLEN; //nach so vielen process(e)-Zyklen muß der jeweils nächste Zustand erreicht sein. var WARTE_ZYKLUS = 0; //so oft wurde bereits auf den nächsten erwarteten Zustand gewartet. var EMPFANG_OK = true; //Bei Timeout auf false setzen! var NULL_PHASE=0; //BESONDERHEIT: Es wird immer nur auf dasjenige ereignis gewartet, das zu erwarten ist. //BESONDERHEIT2: läuft auch bei Fehler alle Bits durch, jedoch in halbem Tempo! //Darum sollte der KEIN TON Bereich 2x so lange sein, wie der Sendebereich //********************************************************************************** //************************************* //*** Funktionen zu Wartungszwecken *** //************************************* //Um den Audiopuffer zu visualiseren: this.holeAudiopuffer = function() { if(DATA_IN!=null && DATA_IN.length==AUDIO_PUFFER_GROESSE) { for(var i=0;i<DATA_IN.length;i++) audiopuffer[i] = DATA_IN[i]; } return audiopuffer; } //..um bei langsamem Verlauf den aktuell erkannten Ton anzeigen zu können. this.holeSignalnummer = function() { return signal_nummer; } //..Empfangszustand abrufen this.holeEMPFANGSZUSTAND = function() { return EMPFANGSZUSTAND; } //..Empfangszustand abrufen this.holeZAHLEMPFANGEN = function() { return zahl_empfangen; } //************************** //*** Private Funktionen *** //************************** function tonwechsel() { //Falls mehr als 0 Einträge in sendepuffer, //Dann ersten Toneintrag übernehmen und löschen. //andernfalls KEIN TON senden. if(sendepuffer!=null && sendepuffer.length>0) { DZ = sendepuffer[0]; sendepuffer.shift(); //entfernt erstes Element, vergl. http://www.w3schools.com/jsref/jsref_shift.asp } else { DZ = TOENE[0]; //KEIN (DEFINIERTER) TON } } function prozess(e) { var data_in = e.inputBuffer.getChannelData(1); var data_out = e.outputBuffer.getChannelData(1); //Um den Audiopuffer zu visualiseren: DATA_IN = data_in; 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; } } //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; //EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE //EMPFANGS-BEREICH: Verarbeiten der signal_nummer abhängig von EMPFANGSZUSTAND //Immer zurücksetzen, bei längerer 0-Phase: if(signal_nummer==0) { NULL_PHASE++; } else { NULL_PHASE=0; } if(NULL_PHASE>=TONDAUER_PROZ_ZYKLEN*2) { NULL_PHASE=0; WARTE_ZYKLUS=0; EMPFANGSZUSTAND=0; } if(EMPFANGSZUSTAND>=16) { if(EMPFANG_OK==true) { empfangspuffer.push(zahl_empfangen); } WARTE_ZYKLUS=0; EMPFANGSZUSTAND=0; } else if(EMPFANGSZUSTAND==0) { //es wird signal_nummer==1 erwartet //hier stets reinitialisieren: WARTE_ZYKLUS=0; zahl_empfangen=0; if(signal_nummer==1) { EMPFANGSZUSTAND++; } } else if(EMPFANGSZUSTAND>0 && EMPFANGSZUSTAND%2==1) //1 3 5 7 9 11 13 15 { if(WARTE_ZYKLUS>TIMEOUT_PROZ_ZYKLEN) { EMPFANG_OK=false; WARTE_ZYKLUS=0; zahl_empfangen*=2; EMPFANGSZUSTAND++; } else if(signal_nummer==2) { zahl_empfangen*=2; WARTE_ZYKLUS=0; EMPFANGSZUSTAND++; } else if(signal_nummer==3) { zahl_empfangen*=2; zahl_empfangen++; WARTE_ZYKLUS=0; EMPFANGSZUSTAND++; } else { WARTE_ZYKLUS++; } } else //if(EMPFANGSZUSTAND>0 && EMPFANGSZUSTAND<16 && EMPFANGSZUSTAND%2==0) //2 4 6 8 10 12 14 { if(WARTE_ZYKLUS>TIMEOUT_PROZ_ZYKLEN) { EMPFANG_OK=false; WARTE_ZYKLUS=0; EMPFANGSZUSTAND++; } else if(signal_nummer==1) { WARTE_ZYKLUS=0; EMPFANGSZUSTAND++; } } //EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE if(DURCHLAUF>=TONDAUER_PROZ_ZYKLEN) { tonwechsel(); DURCHLAUF=0; } DURCHLAUF++; } function init(e) { 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); var node = context.createScriptProcessor(AUDIO_PUFFER_GROESSE, 2, 2); node.onaudioprocess = function(e) { prozess(e) }; volume.connect (node); volume.gain.value=1.0; node.connect(context.destination); } //***************************************************** //*** Funktionen der Programmierschnittstelle (API) *** //***************************************************** this.sendeZahl = function(zahl) { if(zahl==null || typeof(zahl)!="number" || zahl<0 || zahl>255) { return false; } else { zahl = Math.floor(zahl); //sicherheitshalber nachkommastellen abschneiden. //sendepuffer[sendepuffer.length] = zahl; //besser: //Zahl gleich in Tonfolgen zerlegen und diese in sendepuffer ablegen: for(var i=7;i>=0;i--) { merker[i] = zahl%2; zahl/=2; zahl = Math.floor(zahl); } //sendepuffer[sendepuffer.length] = .. //besser: sendepuffer.push(TOENE[0]); //Länger KEIN TON sendepuffer.push(TOENE[0]); //for(var i=0;i<32;i++) //zur Sicherheit!!!! (sollte unbedingt verjkleinert werden!) // sendepuffer.push(TOENE[0]); //Dann Bits senden, also in Puffer Tonwechselfolge eintragen: for(var i=0;i<merker.length;i++) { sendepuffer.push(TOENE[1]); if(merker[i]==0) sendepuffer.push(TOENE[2]); else sendepuffer.push(TOENE[3]); } sendepuffer.push(TOENE[0]); //Länger KEIN TON sendepuffer.push(TOENE[0]); return true; } } this.sendeText = function(text) { if(text==null || typeof(text)!="string" || text.length==0) { return true; } else { for(var i=0;i<text.length;i++) { this.sendeZahl(text.charCodeAt(i)); } } } this.holeZahl = function() { if(empfangspuffer== null || empfangspuffer.length==0) { return -1; } else { var zahl = empfangspuffer[0]; empfangspuffer.shift(); return zahl; } } this.zahlLiegtVor = function() { if(empfangspuffer== null || empfangspuffer.length==0) { return false; } else { return true; } } this.holeZeichen = function() { var zahl = this.holeZahl(); if(zahl==-1) { return ""; } else { return String.fromCharCode(zahl); } } this.holeText = function() { var text = ""; while(this.zahlLiegtVor()) text = text+this.holeZeichen(); return text; } this.initialisieren = function() { 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}, init, function(e) { alert('Error capturing audio.'); }); } else { alert('getUserMedia not supported in this browser.'); } } }
Code 0-1: Klasse Audiotransfer in Datei Audiotransfer.js
<!DOCTYPE html> <html> <head lang="de"> <meta charset="iso-8859-1"> <script type="text/javascript" src="Audiotransfer.js"></script> <script language:javascript> var audiotransfer = null; var malkontext = null; function senden() { var text = document.getElementById("sendetext").value; audiotransfer.sendeText(text); } function zeigeAudiopuffer() { var data_in = audiotransfer.holeAudiopuffer(); 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(); document.getElementById("SIGNALNUMMER").innerHTML=audiotransfer.holeSignalnummer(); //Prüfen, ob etwas empfangen wurde, ggf. anfügen: //var text = audiotransfer.holeText(); //erzeugt Seiteneffekt auf den Empfangszyklus!!! var text = audiotransfer.holeZeichen(); if(text!="") { var text_bisher = document.getElementById("EMPFANGEN").value; if(text_bisher!=null && text_bisher.length>0) document.getElementById("EMPFANGEN").value = text_bisher+"\n"+text; else document.getElementById("EMPFANGEN").value = text; } //Zur Kontrolle den Empfangszustand darstellen: document.getElementById("EMPFANGSZUSTAND").innerHTML=audiotransfer.holeEMPFANGSZUSTAND(); document.getElementById("empfangene_zahl").innerHTML=audiotransfer.holeZAHLEMPFANGEN(); } function initialisieren() { malkontext = document.getElementById("grafik").getContext("2d"); audiotransfer = new Audiotransfer(); audiotransfer.initialisieren(); setInterval(zeigeAudiopuffer,50); } </script> </head> <body onload="javascript:initialisieren()"> <canvas id="grafik" width="1024" height="400"></canvas> <h2>Erkannt wird Signalnummer: <span id="SIGNALNUMMER"></span></h2> <h2>EMPFANGSZUSTAND: <span id="EMPFANGSZUSTAND"></span></h2> <h2>empfangene_zahl: <span id="empfangene_zahl"></span></h2> <br/> <fieldset> <input id="sendetext" type="text" style="width:200px;" value=""/> <input id="senden" type="button" value="SENDEN" onclick="javascript:senden();"/> <br/> <p>Bisher empfangener Text:</p> <br/> <textarea id="EMPFANGEN" cols="40" rows="12"></textarea> <br/> </fieldset> </body> </html>
Code 0-2: Anwendungsteil in Datei Teste_Audiotransfer.html