-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Rick Waldron <waldron.rick@gmail.com>
- Loading branch information
Showing
8 changed files
with
356 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
``` | ||
Usage: arecord [OPTION]... [FILE]... | ||
-h, --help help | ||
--version print current version | ||
-l, --list-devices list all soundcards and digital audio devices | ||
-L, --list-pcms list device names | ||
-D, --device=NAME select PCM by name | ||
-q, --quiet quiet mode | ||
-t, --file-type TYPE file type (voc, wav, raw or au) | ||
-c, --channels=# channels | ||
-f, --format=FORMAT sample format (case insensitive) | ||
-r, --rate=# sample rate | ||
-d, --duration=# interrupt after # seconds | ||
-M, --mmap mmap stream | ||
-N, --nonblock nonblocking mode | ||
-F, --period-time=# distance between interrupts is # microseconds | ||
-B, --buffer-time=# buffer duration is # microseconds | ||
--period-size=# distance between interrupts is # frames | ||
--buffer-size=# buffer duration is # frames | ||
-A, --avail-min=# min available space for wakeup is # microseconds | ||
-R, --start-delay=# delay for automatic PCM start is # microseconds | ||
(relative to buffer size if <= 0) | ||
-T, --stop-delay=# delay for automatic PCM stop is # microseconds from xrun | ||
-v, --verbose show PCM structure and setup (accumulative) | ||
-V, --vumeter=TYPE enable VU meter (TYPE: mono or stereo) | ||
-I, --separate-channels one file for each channel | ||
-i, --interactive allow interactive operation from stdin | ||
-m, --chmap=ch1,ch2,.. Give the channel map to override or follow | ||
--disable-resample disable automatic rate resample | ||
--disable-channels disable automatic channel conversions | ||
--disable-format disable automatic format conversions | ||
--disable-softvol disable software volume control (softvol) | ||
--test-position test ring buffer position | ||
--test-coef=# test coefficient for ring buffer position (default 8) | ||
expression for validation is: coef * (buffer_size / 2) | ||
--test-nowait do not wait for ring buffer - eats whole CPU | ||
--max-file-time=# start another output file when the old file has recorded | ||
for this many seconds | ||
--process-id-file write the process ID here | ||
--use-strftime apply the strftime facility to the output file name | ||
--dump-hw-params dump hw_params of the device | ||
--fatal-errors treat all errors as fatal | ||
Recognized sample formats are: S8 U8 S16_LE S16_BE U16_LE U16_BE S24_LE S24_BE U24_LE U24_BE S32_LE S32_BE U32_LE U32_BE FLOAT_LE FLOAT_BE FLOAT64_LE FLOAT64_BE IEC958_SUBFRAME_LE IEC958_SUBFRAME_BE MU_LAW A_LAW IMA_ADPCM MPEG GSM SPECIAL S24_3LE S24_3BE U24_3LE U24_3BE S20_3LE S20_3BE U20_3LE U20_3BE S18_3LE S18_3BE U18_3LE U18_3BE G723_24 G723_24_1B G723_40 G723_40_1B DSD_U8 DSD_U16_LE | ||
Some of these may not be available on selected hardware | ||
The available format shortcuts are: | ||
-f cd (16 bit little endian, 44100, stereo) | ||
-f cdr (16 bit big endian, 44100, stereo) | ||
-f dat (16 bit little endian, 48000, stereo) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,204 @@ | ||
// Dependencies: Built-in | ||
var cp = require('child_process'); | ||
var Emitter = require('events').EventEmitter; | ||
|
||
// Dependencies: Internal | ||
var CaptureStream = require('./capture-stream'); | ||
|
||
// Program specific | ||
var priv = new WeakMap(); | ||
|
||
function Microphone(options) { | ||
Emitter.call(this); | ||
|
||
options = options || {}; | ||
|
||
var state = { | ||
arecord: null, | ||
aplay: null, | ||
currentTime: 0, | ||
isListening: false, | ||
interval: null, | ||
cs: new CaptureStream(), | ||
time: null, | ||
}; | ||
|
||
priv.set(this, state); | ||
|
||
Object.defineProperties(this, { | ||
currentTime: { | ||
get: () => Number(state.currentTime.toFixed(3)), | ||
}, | ||
isListening: { | ||
get: () => state.isListening, | ||
}, | ||
}); | ||
} | ||
|
||
Microphone.prototype = Object.create(Emitter.prototype, { | ||
constructor: { | ||
value: Microphone | ||
} | ||
}); | ||
|
||
var defaults = ['-f', 'cd', '-c', '1', '-r', '41100', '-D', 'plughw:0,0']; | ||
|
||
Microphone.prototype.listen = function(options) { | ||
var state = priv.get(this); | ||
var args = []; | ||
var offset = null; | ||
var time = 0; | ||
|
||
if (state.isListening) { | ||
return state.cs; | ||
} | ||
|
||
options = options || {}; | ||
|
||
if (Array.isArray(options)) { | ||
// mic.listen(['-f', 'cd', '-c', 1, '-r', 41100 ]); | ||
args = options; | ||
} else { | ||
// Don't need to check for null, since those are handled above | ||
if (typeof options === 'object') { | ||
// mic.listen({ | ||
// ... | ||
// }); | ||
// | ||
args = Object.keys(options).reduce((accum, key) => { | ||
var value = options[key]; | ||
var option = ''; | ||
|
||
if (key.length === 1) { | ||
// mic.listen({ | ||
// c: 1, | ||
// f: 'cd', | ||
// }); | ||
// | ||
option = '-'; | ||
} | ||
|
||
// mic.listen({ | ||
// '-c': 1, | ||
// '-f': 'cd', | ||
// }); | ||
// | ||
option += key; | ||
|
||
accum.push(option, value); | ||
|
||
return accum; | ||
}, []); | ||
} | ||
} | ||
|
||
if (args.length === 0) { | ||
args = defaults.slice(); | ||
} | ||
|
||
if (state.arecord === null) { | ||
state.isListening = true; | ||
state.currentTime = 0; | ||
state.startTime = Date.now(); | ||
state.interval = setInterval(() => { | ||
var now = Date.now(); | ||
if (offset === null) { | ||
offset = now - state.startTime; | ||
} | ||
state.currentTime = time + (now - state.startTime - offset) / 1000; | ||
|
||
this.emit('timeupdate', this.currentTime); | ||
}, 100); | ||
|
||
// Apply some reasonable defaults... | ||
Object.keys(arecord.options).forEach(key => { | ||
if (!args.includes(key)) { | ||
args.push(key, arecord.options[key]); | ||
} | ||
}); | ||
|
||
state.arecord = cp.spawn('arecord', args); | ||
|
||
if (this.debug) { | ||
state.arecord.stderr.on('data', (data) => { | ||
var lines = data.toString().split('\n').filter(Boolean).map(line => line.trim()); | ||
lines.forEach(line => { | ||
console.error(line); | ||
}); | ||
}); | ||
} | ||
|
||
state.arecord.stdout.on('data', (data) => { | ||
state.cs.push(data); | ||
this.emit('data', data); | ||
this.emit('timeupdate', this.currentTime); | ||
}); | ||
|
||
state.arecord.on('close', (code, signal) => { | ||
if (code !== null && signal === null) { | ||
if (state.interval) { | ||
clearInterval(state.interval); | ||
} | ||
state.arecord = null; | ||
state.currentTime = 0; | ||
state.startTime = 0; | ||
state.isListening = false; | ||
|
||
this.emit('close'); | ||
} | ||
}); | ||
|
||
this.emit('listen'); | ||
} | ||
|
||
return state.cs; | ||
}; | ||
|
||
Microphone.prototype.monitor = function(catpureStream) { | ||
var state = priv.get(this); | ||
|
||
if (state.isListening) { | ||
state.aplay = cp.spawn('aplay', ['-D', 'plughw:0,0']); | ||
} | ||
|
||
if (catpureStream) { | ||
return catpureStream.pipe(state.aplay.stdin); | ||
} else { | ||
return state.cs.pipe(state.aplay.stdin); | ||
} | ||
}; | ||
|
||
Microphone.prototype.stop = function() { | ||
var state = priv.get(this); | ||
if (!state.isListening) { | ||
return this; | ||
} | ||
state.isListening = false; | ||
if (state.interval) { | ||
clearInterval(state.interval); | ||
} | ||
if (state.arecord) { | ||
state.arecord.kill('SIGTERM'); | ||
state.arecord = null; | ||
} | ||
if (state.aplay) { | ||
state.aplay.kill('SIGTERM'); | ||
state.aplay = null; | ||
} | ||
this.emit('stop'); | ||
return this; | ||
}; | ||
|
||
|
||
var arecord = { | ||
options: { | ||
'-f': 'cd', | ||
'-c': 1, | ||
'-r': 41100, | ||
'-D': 'plughw:0,0', | ||
}, | ||
}; | ||
|
||
arecord.keys = Object.keys(arecord.options); | ||
|
||
module.exports = Microphone; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.