function IMRecorder() { var me = this; var recorded = false; //------------------------------------------------------------ // Destroy all //------------------------------------------------------------ terminate = function () { reset(); // Chronometer me.recorder && me.recorder.stop(); me.recorder && me.recorder.clear() && delete me.recorder; if(me.wavesurfer.isPlaying()) { me.wavesurfer.pause(); }; me.wavesurfer.empty(); me.microphone.stop(); delete me.microphone; delete me.wavesurfer; //document.body.innerHTML = ''; | Elimina el html del grabador. //window.location.replace('about:blank'); | Carga una pantalla en blanco. }; this.terminate = function() { terminate(); }; //------------------------------------------------------------ // Open wav from server arrayBuffer //------------------------------------------------------------ this.openFromArrayBuffer = function(arrayBuffer) { Ciseaux.from(arrayBuffer).then(function(tape) { tape.render().then(function(audiobuffer) { me.wavesurfer.loadDecodedBuffer(audiobuffer); me.oldtape = tape; set(tottime()); // Chronometer }); }, function(error) { console.log('El archivo solicitado no existe o está corrupto.'); //terminate(); if(afterLoad !== null) afterLoad(); }); } //------------------------------------------------------------ // Load wav from server //------------------------------------------------------------ this.load = function (url, afterLoad) { Ciseaux.from(url).then(function(tape) { if(afterLoad !== null) afterLoad(); tape.render().then(function(audiobuffer) { me.wavesurfer.loadDecodedBuffer(audiobuffer); me.oldtape = tape; set(tottime()); // Chronometer }); }, function(error) { console.log('El archivo solicitado no existe o está corrupto.'); //terminate(); if(afterLoad !== null) afterLoad(); }); } //------------------------------------------------------------ // Quit recording. //------------------------------------------------------------ var out = function () { var q = confirm("Si desea salir sin grabar, pulse Ok.\nEn caso contrario, pulse Cancel."); if (q == true) { terminate(); } }; //------------------------------------------------------------ // Save wav to server //------------------------------------------------------------ this.save = function (url, aOnProgress, aOnDone) { if(recorded === false) { // Saliendo sin guardar audio. aOnDone(); return; }; // Guardando audio. // // primero obtenemos "oldtape" como audiobuffer var progr = aOnProgress; var ondone = aOnDone; me.oldtape.render().then(function(audiobuffer) { // una vez obtenido el buffer generamos el wav // código obtenido desde: http://stackoverflow.com/questions/22560413/html5-web-audio-convert-audio-buffer-into-wav-file // start a new worker // we can't use Recorder directly, since it doesn't support what we're trying to do var worker = new Worker('js/recorderWorker.js'); // initialize the new worker worker.postMessage({ command: 'init', config: { numChannels: me.recorder.config.numChannels, sampleRate: me.recorder.context.sampleRate } }); // callback for "exportWAV" worker.onmessage = function( e ) { var blob = e.data; // this is would be your WAV blob // por último enviamos el wav a destino var xhr = new XMLHttpRequest(); xhr.open('POST', url, true); xhr.upload.onprogress = progr; xhr.onload = function () { if (xhr.status === 200) { aOnDone(); } else { alert('An error occurred while uploading recording!'); } }; xhr.send(blob); }; // send the channel data from our buffer to the worker worker.postMessage({ command: 'record', buffer: [ audiobuffer.getChannelData(0) //audiobuffer.getChannelData(1) ] }); // ask the worker for a WAV worker.postMessage({ command: 'exportWAV', type: 'audio/wav' }); }); //terminate(); }; //------------------------------------------------------------ // Save wav to websocket //------------------------------------------------------------ // La función está asignada a la propiedad onmessage del WebSocket, //lo que significa que se ejecutará cada vez que el WebSocket reciba un mensaje. // El mensaje recibido es un objeto Blob de audio, que se procesa con la función exportWAV del objeto recorder. // Esta función devuelve un objeto Blob con el audio codificado en formato WAV. // El objeto Blob se convierte a una matriz de bytes (ArrayBuffer) con la ayuda del objeto FileReader. // Finalmente, se envía la matriz de bytes a través del WebSocket con el método send. this.save1 = function () { // me.ws.onmessage = function() { // // Aquí puedes procesar el mensaje recibido y hacer algo con él // const audioBlob = me.recorder.exportWAV( // function(blob) { // me.url = URL.createObjectURL(blob); // me.myblob = blob; // Ciseaux.from(me.url).then(function(tape) { // var lPos = me.seekpos; // var lDur = tape.tracks[0].duration; // me.oldtape = me.oldtape.replace(lPos, lDur, tape); // me.oldtape.render().then(function(audiobuffer){ // me.ws.binaryType = "blob"; // me.recorder.clear(); // me.wavesurfer.empty(); // me.wavesurfer.loadDecodedBuffer(audiobuffer); // me.wavesurfer.skip(lPos + lDur); // }); // }); // } // ); // const reader = new FileReader(); // reader.onload = function() { // me.ws = new WebSocket("ws://localhost:8000"); // me.ws.send(reader.result); // }; // }; me.ws.onmessage = function(event) { console.log(event.data) var audioData = me.wavesurfer.microphone.getAudioData(); var binaryAudioData = new Float32Array(audioData); var buffer = new ArrayBuffer(binaryAudioData.length * 4); var view = new Float32Array(buffer); for (var i = 0; i < binaryAudioData.length; i++) { view[i] = binaryAudioData[i]; } var ws = new WebSocket('ws://localhost:8000'); ws.binaryType = 'arraybuffer'; ws.onopen = function() { ws.send(buffer); }; }; terminate(); }; //------------------------------------------------------------ // Calculate total blob duration on wavesurfer canvas //------------------------------------------------------------ totlen = function () { var ini = new Date().getTime(); var num = Math.ceil(me.wavesurfer.getDuration() * 1000); var fin = ini + num; var lap = fin - ini; totpos = lap / 1000; } //------------------------------------------------------------ // Calculate partial blob duration on wavesurfer canvas //------------------------------------------------------------ parlen = function () { var ini = new Date().getTime(); var num = Math.ceil(me.wavesurfer.getCurrentTime() * 1000); var fin = ini + num; var lap = fin - ini; me.seekpos = lap / 1000; } //------------------------------------------------------------ // Calculate total blob duration on stopwatch display //------------------------------------------------------------ tottime = function () { var ini = new Date().getTime(); var num = Math.ceil(me.wavesurfer.getDuration() * 1000); var fin = ini + num; var lap = fin - ini; return lap; } //------------------------------------------------------------ // Calculate partial blob duration on stopwatch display //------------------------------------------------------------ partime = function () { var ini = new Date().getTime(); var num = Math.ceil(me.wavesurfer.getCurrentTime() * 1000); var fin = ini + num; var lap = fin - ini; return lap; } //------------------------------------------------------------ // Create empty blob //------------------------------------------------------------ emptyBlob = function () { me.oldtape = new Ciseaux.Tape(); me.recorder && me.recorder.clear(); } //------------------------------------------------------------ // Generate blob //------------------------------------------------------------ createBlob = function () { me.recorder.exportWAV(function(blob) { me.url = URL.createObjectURL(blob); me.myblob = blob; Ciseaux.from(me.url).then(function(tape) { var lPos = me.seekpos; var lDur = tape.tracks[0].duration; me.oldtape = me.oldtape.replace(lPos, lDur, tape); me.oldtape.render().then(function(audiobuffer){ me.recorder.clear(); me.wavesurfer.empty(); me.wavesurfer.loadDecodedBuffer(audiobuffer); me.wavesurfer.skip(lPos + lDur); }); }); }); } //------------------------------------------------------------ // PLAY/STOP on button click //------------------------------------------------------------ this.play_stop = function() { me.wavesurfer.playPause(); }; //------------------------------------------------------------ // RECORD on button click //------------------------------------------------------------ record = function() { start(); // Chronometer me.microphone.play(); me.recorder.record(function() { console.log("here"); }); recorded = true; } //------------------------------------------------------------ // PAUSE on button click //------------------------------------------------------------ this.pause = function(){ stop(); // Chronometer me.microphone.pause(); me.recorder.stop(); createBlob(); } //------------------------------------------------------------ // REVIEW on button click //------------------------------------------------------------ this.review = function() { me.wavesurfer.skipBackward(me.wavesurfer.getDuration() / 5); }; //------------------------------------------------------------ // CUE on button click //------------------------------------------------------------ this.cue = function() { me.wavesurfer.skipForward(me.wavesurfer.getDuration() / 5); }; //------------------------------------------------------------ // Get voiceRecognitionBuffer //------------------------------------------------------------ this.processVoiceRecognition = function(voiceRecognitionAudioBlob) { if(!me.recorder) return; // Web Socket is connected, send data using send() var d = { "config": { "sample_rate": 44100 } }; me.ws.send(JSON.stringify(d)); me.ws.binaryType = "blob"; me.ws.send(voiceRecognitionAudioBlob); }; //------------------------------------------------------------ // CLEAR on button click //------------------------------------------------------------ this.clear_rec = function() { var r = confirm("Para borrar la grabación y crear una nueva, pulse Ok.\nPara continuar, pulse Cancel."); if (r == true) { reset(); // Chronometer me.recorder && me.recorder.clear(); me.wavesurfer.empty(); emptyBlob(); } }; //------------------------------------------------------------ // QUIT on button click //------------------------------------------------------------ quit_click = function() { out(); }; //------------------------------------------------------------ // START/STOP mic on button click or start recording //------------------------------------------------------------ this.rec_pause_toggle = function() { if( me.recstate === undefined ) { // esto abre la ventana de solicitud de habilitación del micrófono me.microphone.start(); } else if( me.recstate === "REC" ) { me.recstate = "PAUSED"; this.pause(); } else { me.recstate = "REC"; record(); } }; //------------------------------------------------------------ // STOP mic on button click //------------------------------------------------------------ this.rec_pause = function() { if( me.recstate === "REC" ) { me.recstate = "PAUSED"; this.pause(); } }; //------------------------------------------------------------ // STOP play on button click //------------------------------------------------------------ this.play_pause = function() { if(me.wavesurfer.isPlaying()) { me.wavesurfer.pause(); }; }; //------------------------------------------------------------ // voiceRecognitionAudioBlobCallback //------------------------------------------------------------ this.voiceRecognitionAudioBlobCallback = function(blob) { var audioBlob = new Blob([blob], { type: 'audio/wav' }); me.processVoiceRecognition(audioBlob); }; //------------------------------------------------------------ // Initialize object //------------------------------------------------------------ init = function () { //------------------------------------------------------------ // General global variables //------------------------------------------------------------ me.recorder; me.recstate = undefined; // Primera pasada (sólo para incializar el micrófono me.newtape; me.oldtape; me.totpos = 0; me.seekpos = 0; me.url = null; me.recContext; recContext = new AudioContext; //------------------------------------------------------------ // Options for playing canvas //------------------------------------------------------------ me.optplay = { container : '#waveform', waveColor : 'darkorange', progressColor : 'purple', height : 40, interact : true, hideScrollbar : true, cursorColor : 'darkgray', cursorWidth : 1, normalize : true, audioRate : 1 }; //------------------------------------------------------------ // Create a wavesurfer instance //------------------------------------------------------------ me.wavesurfer = Object.create(WaveSurfer); me.wavesurfer.init(me.optplay); // Init wavesurfer for recording //------------------------------------------------------------ // Wavesurfer events //------------------------------------------------------------ me.wavesurfer.on('seek', function () { set(partime()); // Chronometer totlen(); parlen(); }); me.wavesurfer.on('play', function () { set(partime()); // Chronometer start(); // Chronometer }); me.wavesurfer.on('pause', function () { stop(); // Chronometer }); me.wavesurfer.on('ready', function () { // }); //------------------------------------------------------------ // Create new audio context and blank tape //------------------------------------------------------------ var cisContext = new AudioContext(); Ciseaux.context = cisContext; emptyBlob(); show(); // muestra el timer //------------------------------------------------------------ // Init Microphone plugin //------------------------------------------------------------ me.microphone = Object.create(WaveSurfer.Microphone); me.microphone.init({wavesurfer: me.wavesurfer}); me.microphone.on('deviceReady', function(stream) { var mic_input = recContext.createMediaStreamSource(stream); me.recorder = new Recorder(mic_input, {numChannels: 1}, me.voiceRecognitionAudioBlobCallback); me.recstate = "REC"; record(); }); me.microphone.on('deviceError', function(code) { console.warn('Device error: ' + code); }); me.ws = new WebSocket("ws://localhost:8000"); me.ws.onopen = function() { console.log("conectado"); me.wsoen = true; }; me.ws.onclose = function() { // websocket is closed. console.log("desconectado"); }; }; // init method is called fron within object // no need to be called from the outside init(); };