我正在尝试分离从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])

具有不同类型的字符,例如Float32ArrayUint8ArrayUint16ArrayInt16Array但是结果是一样的。
我已经使用以下命令测试了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/

10-11 04:34