从Buffer nodejs

时间:2018-04-23 10:23:52

标签: node.js audio buffer channels

我正在尝试从4-mic阵列ReSpeaker中分离我收到的Buffer中的4个通道。我正在使用nodejs,目前我使用的是spawn命令:

spawn('arecord -r16000 -fS16_LE -traw -c4 -Dac108')

然后在变换器中输出输出,我在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],...]

此外,我不明白为什么,如果我遵循的模式不正确,2个通道成功分开。 我还尝试将这些块转换成其他类似的东西:

let source = new Int8Array(chunk);

然后在for cicle:

channels[i%4].push(source[i])

使用不同的类型,例如Float32ArrayUint8ArrayUint16ArrayInt16Array 但结果是一样的。 我已经使用命令测试了4mic是否正常工作:

arecord -r16000 -fS16_LE -traw -c4 -Dac108 -I ch1 ch2 ch3 ch4

生成包含每个频道的预期4个文件。

对于每次测试,我会在说话时每隔几秒用mi手指在麦克风上阻挡,这样我就能分辨出每个通道之间的区别。

任何人都可以帮助我吗?或者有一些提示? 谢谢!

1 个答案:

答案 0 :(得分:0)

好的,我想出了问题所在。 基本上我用bitWidth = 16进行录制,而Node中的Buffer对象是Uint8Array的一个实例,所以我跟随的模式确实是正确的,但由于8bitArray我必须分配2每个频道的元素。导致8位阵列的格式为:

[[ch1],[ch1],[ch2],[ch2],[ch3],[ch3],[ch4],[ch4],...]

同样强制转换数组也没用,因为生成的16bitArray没有合并2 8bit元素来创建16bit元素,而是每个8bit元素创建最后一个8bit元素{1}} 16bit元素的{1}},其中前8位为0,如下所示:

8bitArray=[[11111111],[11111111],[2222222],[22222222],...]
16bitArray Casted= [[0000000011111111],[0000000011111111],[0000000022222222],...]

所以我创建了一个方法,将8bitArray合并到正确的数组中,以便根据您正在录制的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++;
        }
    }
}