function mic(options) { options = options || {}; var that = {}; var endian = options.endian || 'little'; var bitwidth = options.bitwidth || '16'; var encoding = options.encoding || 'signed-integer'; var rate = options.rate || '16000'; var channels = options.channels || '1'; var device = options.device || 'plughw:1,0'; var exitOnSilence = options.exitOnSilence || 0; var debug = options.debug || false; var format, formatEndian, formatEncoding; var audioProcess = null; var infoStream = new PassThrough; var audioStream = new IsSilence({debug: debug}); var audioProcessOptions = { stdio: ['ignore', 'pipe', 'ignore'] }; if(debug) { audioProcessOptions.stdio[2] = 'pipe'; } // Setup format variable for arecord call if(endian === 'big') { formatEndian = 'BE'; } else { formatEndian = 'LE'; } if(encoding === 'unsigned-integer') { formatEncoding = 'U'; } else { formatEncoding = 'S'; } format = formatEncoding + bitwidth + '_' + formatEndian; audioStream.setNumSilenceFramesExitThresh(parseInt(exitOnSilence, 10)); that.start = function start() { if(audioProcess === null) { audioProcess = isMac ? spawn('rec', ['-b', bitwidth, '--endian', endian, '-c', channels, '-r', rate, '-e', encoding, '-t', 'raw', '-'], audioProcessOptions ) : spawn('arecord', ['-c', channels, '-r', rate, '-f', format, '-D', device], audioProcessOptions); audioProcess.on('exit', function(code, sig) { if(code != null && sig === null) { audioStream.emit('audioProcessExitComplete'); if(debug) console.log("recording audioProcess has exited with code = %d", code); } }); audioProcess.stdout.pipe(audioStream); if(debug) { audioProcess.stderr.pipe(infoStream); } audioStream.emit('startComplete'); } else { if(debug) { throw new Error("Duplicate calls to start(): Microphone already started!"); } } }; that.stop = function stop() { if(audioProcess != null) { audioProcess.kill('SIGTERM'); audioProcess = null; audioStream.emit('stopComplete'); if(debug) console.log("Microhphone stopped"); } }; that.pause = function pause() { if(audioProcess != null) { audioProcess.kill('SIGSTOP'); audioStream.pause(); audioStream.emit('pauseComplete'); if(debug) console.log("Microphone paused"); } }; that.resume = function resume() { if(audioProcess != null) { audioProcess.kill('SIGCONT'); audioStream.resume(); audioStream.emit('resumeComplete'); if(debug) console.log("Microphone resumed"); } } that.getAudioStream = function getAudioStream() { return audioStream; } if(debug) { infoStream.on('data', function(data) { console.log("Received Info: " + data); }); infoStream.on('error', function(error) { console.log("Error in Info Stream: " + error); }); } return that; }
n/a
function IsSilence(options) { var that = this; if (options && options.debug) { that.debug = options.debug; delete options.debug; } Transform.call(that, options); var consecSilenceCount = 0; var numSilenceFramesExitThresh = 0; that.getNumSilenceFramesExitThresh = function getNumSilenceFramesExitThresh() { return numSilenceFramesExitThresh; }; that.getConsecSilenceCount = function getConsecSilenceCount() { return consecSilenceCount; }; that.setNumSilenceFramesExitThresh = function setNumSilenceFramesExitThresh(numFrames) { numSilenceFramesExitThresh = numFrames; return; }; that.incrConsecSilenceCount = function incrConsecSilenceCount() { consecSilenceCount++; return consecSilenceCount; }; that.resetConsecSilenceCount = function resetConsecSilenceCount() { consecSilenceCount = 0; return; }; }
n/a
function IsSilence(options) { var that = this; if (options && options.debug) { that.debug = options.debug; delete options.debug; } Transform.call(that, options); var consecSilenceCount = 0; var numSilenceFramesExitThresh = 0; that.getNumSilenceFramesExitThresh = function getNumSilenceFramesExitThresh() { return numSilenceFramesExitThresh; }; that.getConsecSilenceCount = function getConsecSilenceCount() { return consecSilenceCount; }; that.setNumSilenceFramesExitThresh = function setNumSilenceFramesExitThresh(numFrames) { numSilenceFramesExitThresh = numFrames; return; }; that.incrConsecSilenceCount = function incrConsecSilenceCount() { consecSilenceCount++; return consecSilenceCount; }; that.resetConsecSilenceCount = function resetConsecSilenceCount() { consecSilenceCount = 0; return; }; }
n/a
function Transform(options) { if (!(this instanceof Transform)) return new Transform(options); Duplex.call(this, options); this._transformState = new TransformState(this); var stream = this; // start out asking for a readable event once data is transformed. this._readableState.needReadable = true; // we have implemented the _read method, and done the other things // that Readable wants before the first _read call, so unset the // sync guard flag. this._readableState.sync = false; if (options) { if (typeof options.transform === 'function') this._transform = options.transform; if (typeof options.flush === 'function') this._flush = options.flush; } // When the writable side finishes, then flush out anything remaining. this.once('prefinish', function() { if (typeof this._flush === 'function') this._flush(function(er) { done(stream, er); }); else done(stream); }); }
n/a
_transform = function (chunk, encoding, callback) { var i; var speechSample; var silenceLength = 0; var self = this; var debug = self.debug; var consecutiveSilence = self.getConsecSilenceCount(); var numSilenceFramesExitThresh = self.getNumSilenceFramesExitThresh(); var incrementConsecSilence = self.incrConsecSilenceCount; var resetConsecSilence = self.resetConsecSilenceCount; if(numSilenceFramesExitThresh) { for(i=0; i<chunk.length; i=i+2) { if(chunk[i+1] > 128) { speechSample = (chunk[i+1] - 256) * 256; } else { speechSample = chunk[i+1] * 256; } speechSample += chunk[i]; if(Math.abs(speechSample) > 2000) { if (debug) { console.log("Found speech block"); } resetConsecSilence(); break; } else { silenceLength++; } } if(silenceLength == chunk.length/2) { consecutiveSilence = incrementConsecSilence(); if (debug) { console.log("Found silence block: %d of %d", consecutiveSilence, numSilenceFramesExitThresh); } //emit 'silence' only once each time the threshold condition is met if( consecutiveSilence === numSilenceFramesExitThresh) { self.emit('silence'); } } } this.push(chunk); callback(); }
n/a