我正在尝试分离从4麦克风阵列ReSpeaker接收的缓冲区中的4通道。我正在使用nodejs,目前我使用的是spawn命令,例如:spawn('arecord -r16000 -fS16_LE -traw -c4 -Dac108')
然后将输出通过管道传输到变压器中,在这里我将Buffer分成4个通道,并将它们保存到单独的文件中以检查结果
const stream = require("stream");
const fs = require('fs');
class ChannelTransformer extends stream.Transform {
constructor(options) {
var write_1 = fs.createWriteStream('ch1', {encoding: 'binary'});
var write_2 = fs.createWriteStream('ch2', {encoding: 'binary'});
var write_3 = fs.createWriteStream('ch3', {encoding: 'binary'});
var write_4 = fs.createWriteStream('ch4', {encoding: 'binary'});
options.readableObjectMode = true;
options.writableObjectMode = true;
options.highWaterMark = 20000;
options.transform = (chunk, encoding, callback) => {
let channels = [[],[],[],[]];
for(let i=0; i<source.length;i++ ){
channels[i%4].push(chunk[i])
}
write_1.write(new Uint8Array(channels[0]));
write_2.write(new Uint8Array(channels[1]));
write_3.write(new Uint8Array(channels[2]));
write_4.write(new Uint8Array(channels[3]));
callback();
};
super(options);
}
}
作为此代码的结果,我得到了4个文件,如果我用Audacity导入它们,我发现ch2和ch4文件已正确分离,而ch1和ch3损坏并导致白噪声文件。
我在分居中缺少什么吗?我认为音频存储在模式中:
[[ch1_0],[ch2_0],[ch3_0],[ch4_0],[ch1_1],[ch2_1],...]
另外我不明白为什么,如果我遵循的模式不正确,则成功分离两个通道中的两个。
我还尝试过将块放入其他类似内容中:
let source = new Int8Array(chunk);
然后在
for
cicle中:channels[i%4].push(source[i])
具有不同类型的字符,例如
Float32Array
,Uint8Array
,Uint16Array
,Int16Array
但是结果是一样的。我已经使用以下命令测试了4mic是否正常工作:
arecord -r16000 -fS16_LE -traw -c4 -Dac108 -I ch1 ch2 ch3 ch4
它将按预期产生包含每个通道的4个文件。
对于每项测试,我都会在讲话时每隔几秒钟用mi手指挡住麦克风,以便我能分辨出每个声道之间的差异。
谁能帮我?或有一些提示?
谢谢!
最佳答案
好吧,我想出了什么问题。
基本上我是用bitWidth = 16
录制的,而Node中的Buffer
对象是Uint8Array
的一个实例,因此我遵循的模式确实是正确的,但是由于8bitArray,我必须为每个通道分配2个元素。因为8bit阵列的格式为:
[[ch1],[ch1],[ch2],[ch2],[ch3],[ch3],[ch4],[ch4],...]
同样,转换数组也没有用,因为产生的
16bitArray
不会合并2 8bit
元素来创建16bit
元素,但是每个8bit
元素都会创建8bit
元素的最后16bit
,其中前8位是0
,如下所示:8bitArray=[[11111111],[11111111],[2222222],[22222222],...]
16bitArray Casted= [[0000000011111111],[0000000011111111],[0000000022222222],...]
所以我创建了一个方法,将
8bitArray
合并到正确的Array中,以根据要记录的bitWidth
正确处理:var bitMultipler = bitWidth/8; //so i can handle any bitWidth with the same code
let channelsMap = new Map<number, Array<any>>();
for (let channel: number = 0; channel < totalChannels; channel++) {
channelsMap.set(channel, new Array())
}
/**
For each channel i push as many element as needed based on the bitMultipler
*/
let i = 0
while (i < chunk.length) {
for (let channel = 0; channel < totalChannels; channel++) {
for (let indexMultipler = 0; indexMultipler < bitMultipler; indexMultipler++) {
channelsMap.get(channel).push(chunk[i]);
i++;
}
}
}
关于node.js - 将4个 channel 与Buffer Node.js分开,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49978749/