-
Notifications
You must be signed in to change notification settings - Fork 61
/
mic.js
124 lines (112 loc) · 4.16 KB
/
mic.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
var spawn = require('child_process').spawn;
var isMac = require('os').type() == 'Darwin';
var isWindows = require('os').type().indexOf('Windows') > -1;
var IsSilence = require('./silenceTransform.js');
var PassThrough = require('stream').PassThrough;
var mic = 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 fileType = options.fileType || 'raw';
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) {
if(isWindows){
audioProcess = spawn('sox', ['-b', bitwidth, '--endian', endian,
'-c', channels, '-r', rate, '-e', encoding,
'-t', 'waveaudio', 'default', '-p'],
audioProcessOptions)
}
else if(isMac){
audioProcess = spawn('rec', ['-b', bitwidth, '--endian', endian,
'-c', channels, '-r', rate, '-e', encoding,
'-t', fileType, '-'], audioProcessOptions)
}
else {
audioProcess = spawn('arecord', ['-t', fileType, '-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("Microphone 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;
}
module.exports = mic;