在JavaScript中对PCM音频缓冲区进行下采样

9

我试图降低从audioContext获取的采样率。我相信它是以44100的速率进行的,而我希望它变成11025。我认为我可以只平均每3个样本,然后以正确的速率播放回来,但音调太高了,就像我们都在使用氦气一样。

降低float32Array从44100到11025采样率的正确方法是什么?

var context = new Flash.audioContext();
var audioInput = context.createMediaStreamSource(stream);
var recorder = context.createScriptProcessor(null, 1, 1);
recorder.onaudioprocess = onAudio;
audioInput.connect(recorder);
recorder.connect(context.destination);

var onAudio = function (e) {
    var left = e.inputBuffer.getChannelData(0);
    bStream.write(Flash.convertFloat32ToInt16(left));
}

var convertFloat32ToInt16 = function(buffer) {
    var l = buffer.length;
    var point = Math.floor(l/3);
    var buf = new Int16Array(point);
    for (var x = l; x > 0;) {
        var average = (buffer[x] + buffer[x-1] +  buffer[x-2]) / 3;
        buf[point] = average*0x7FFF;
        point -= 1;
        x -= 3;
    }
    return buf.buffer;
}
1个回答

21

对于其他需要答案的人。

var downsampleBuffer = function (buffer, sampleRate, outSampleRate) {
    if (outSampleRate == sampleRate) {
        return buffer;
    }
    if (outSampleRate > sampleRate) {
        throw "downsampling rate show be smaller than original sample rate";
    }
    var sampleRateRatio = sampleRate / outSampleRate;
    var newLength = Math.round(buffer.length / sampleRateRatio);
    var result = new Int16Array(newLength);
    var offsetResult = 0;
    var offsetBuffer = 0;
    while (offsetResult < result.length) {
        var nextOffsetBuffer = Math.round((offsetResult + 1) * sampleRateRatio);
        var accum = 0, count = 0;
        for (var i = offsetBuffer; i < nextOffsetBuffer && i < buffer.length; i++) {
            accum += buffer[i];
            count++;
        }

        result[offsetResult] = Math.min(1, accum / count)*0x7FFF;
        offsetResult++;
        offsetBuffer = nextOffsetBuffer;
    }
    return result.buffer;
}

这将返回一个比传入的采样率更小的示例速率,同时将其转换为int16Array而不是float32。


感谢上帝有这篇文章。它帮了我很多,你无法想象。 - Koby Douek
很高兴它能帮助到某个人 :) 那真是一个难题。 - Neablis
1
我发现用这种方法转换的声音有很多噪音。 - jz1108
3
这个解决方案是4年前编写的,自那以后整个音频库已经发生了变化。不要假设它会像以前那样工作。 - Neablis
不是最好的输出,但在紧急情况下它能够工作。我现在在许多样本/演示中看到它。 - hasan
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接