重新采样音频缓冲区从44100到16000

时间:2014-12-22 07:24:53

标签: node.js audio buffer web-audio

我有data-uri格式的音频数据,然后我把这个数据uri转换成缓冲区现在我需要新的samplerate中的这个缓冲区数据,目前音频数据是44.1khz,我需要16khz的数据,如果我使用RecordRTC API录制音频,如果我以低采样率录制音频,那么我的音频语音失真,所以我无法重新采样音频缓冲区,

如果您对此有任何疑问,请帮助我。

提前致谢:)

5 个答案:

答案 0 :(得分:12)

您可以使用OfflineAudioContext进行重新采样,但您需要先将data-uri转换为ArrayBuffer。此解决方案适用于浏览器,而不是服务器,因为最好在网络上发送较低质量的音频(较低的采样率),而不是在服务器上发送大量数据和重新采样。

// `source` is an AudioBuffer instance of the source audio
// at the original sample rate.

var TARGET_SAMPLE_RATE = 16000;

var offlineCtx = new OfflineAudioContext(source.numberOfChannels, source.duration * source.numberOfChannels * TARGET_SAMPLE_RATE, TARGET_SAMPLE_RATE);

var buffer = offlineCtx.createBuffer(source.numberOfChannels, buffer.length, buffer.sampleRate);

// Copy the source data into the offline AudioBuffer
for (var channel = 0; channel < buffer.numberOfChannels; channel++) {
    resampledBuffer.copyToChannel(buffer.getChannelData(channel), channel);
}

// Play it from the beginning.
var source = offlineCtx.createBufferSource();
source.buffer = buffer;
source.connect(offlineCtx.destination);
source.start(0);
offlineCtx.oncomplete = function(resampled) {
    // `resampled` contains an AudioBuffer resampled at 16000Hz.
    // use resampled.getChannelData(x) to get an Float32Array for channel x.
}

o.startRendering();

答案 1 :(得分:0)

这只是padenot答案的一个副本,我对其进行了更新,以避免对可能会发现此帖子并且对缺少变量定义或如何获取最终重新采样的float32array有问题的其他人感到困惑。这在firefox Quantum 64.0中对我有效:

  var sourceAudioBuffer = e.inputBuffer;  // directly received by the audioprocess event from the microphone in the browser

  var TARGET_SAMPLE_RATE = 8000;
  var offlineCtx = new OfflineAudioContext(sourceAudioBuffer.numberOfChannels, sourceAudioBuffer.duration * sourceAudioBuffer.numberOfChannels * TARGET_SAMPLE_RATE, TARGET_SAMPLE_RATE);
  var buffer = offlineCtx.createBuffer(sourceAudioBuffer.numberOfChannels, sourceAudioBuffer.length, sourceAudioBuffer.sampleRate);
  // Copy the source data into the offline AudioBuffer
  for (var channel = 0; channel < sourceAudioBuffer.numberOfChannels; channel++) {
      buffer.copyToChannel(sourceAudioBuffer.getChannelData(channel), channel);
  }
  // Play it from the beginning.
  var source = offlineCtx.createBufferSource();
  source.buffer = sourceAudioBuffer;
  source.connect(offlineCtx.destination);
  source.start(0);
  offlineCtx.oncomplete = function(e) {
    // `resampled` contains an AudioBuffer resampled at 16000Hz.
    // use resampled.getChannelData(x) to get an Float32Array for channel x.
    var resampled = e.renderedBuffer;
    var leftFloat32Array = resampled.getChannelData(0);
    // use this float32array to send the samples to the server or whatever
  }
  offlineCtx.startRendering();

就我而言,原始的重新采样的8000 pcm数据通过udp广播通过管道传输到ffmpeg中

ffmpeg -fflags nobuffer -analyzeduration 1M -f f32le -ar 8000 -ac 1 -i udp://127.0.0.1:12000 -ar 44100 -ac 2 -f alsa hw:0

因此,websocket服务器仅接收base64编码的pcm数据,对base64字符串进行解码,然后通过udp进行广播。结果由扬声器上的ffmpeg播放。

答案 2 :(得分:0)

没有正确答案。这是完美的代码。

// `sourceAudioBuffer` is an AudioBuffer instance of the source audio
// at the original sample rate.
const DESIRED_SAMPLE_RATE = 16000;
const offlineCtx = new OfflineAudioContext(sourceAudioBuffer.numberOfChannels, sourceAudioBuffer.duration * DESIRED_SAMPLE_RATE, DESIRED_SAMPLE_RATE);
const cloneBuffer = offlineCtx.createBuffer(sourceAudioBuffer.numberOfChannels, sourceAudioBuffer.length, sourceAudioBuffer.sampleRate);
// Copy the source data into the offline AudioBuffer
for (let channel = 0; channel < sourceAudioBuffer.numberOfChannels; channel++) {
    cloneBuffer.copyToChannel(sourceAudioBuffer.getChannelData(channel), channel);
}
// Play it from the beginning.
const source = offlineCtx.createBufferSource();
source.buffer = cloneBuffer;
source.connect(offlineCtx.destination);
offlineCtx.oncomplete = function(e) {
  // `resampledAudioBuffer` contains an AudioBuffer resampled at 16000Hz.
  // use resampled.getChannelData(x) to get an Float32Array for channel x.
  const resampledAudioBuffer = e.renderedBuffer;
}
offlineCtx.startRendering();
source.start(0);

答案 3 :(得分:0)

一种简单的方法是进行一个独立的重采样调用,该调用简单地获取一个输入音频缓冲区,一个输入采样率,一个输出采样率,然后返回输出缓冲区。我发现此链接可以做到这一点: audio resampling

这很好用(在音频范围内不会引入太多噪声。)。感谢作者。

答案 4 :(得分:0)

如果您使用的是Chrome浏览器,则可以直接在AudioContext中指定采样率。

1。您可以直接通过麦克风录制声音。

var context = new AudioContext({
    sampleRate: 16000,
});

2。如果已经有文件或ArrayBuffer,则可以使用相同的音频上下文对其重新采样

    const fileReader = new FileReader();
    fileReader.readAsArrayBuffer(target.files[0]);
    
    fileReader.onload =  (e) => {
        //e.target.result is an ArrayBuffer
        context.decodeAudioData(e.target.result, async function(buffer) {
        console.log(buffer)
    })