Resample аудио-буфер от 44100 до 16000

У меня есть аудиоданные в формате data-uri, после чего я преобразовал этот data-uri в буфер теперь мне нужны данные буфера в новом семплере, в настоящее время аудиоданные находятся в 44.1khz, и мне нужны данные в 16khz, а If Я записал аудио с использованием RecordRTC API, и если я записываю звук с низкой частотой дискретизации, тогда я получил искаженный звуковой голос, поэтому я не получаю, как переконфигурировать свой звуковой буфер,

Если у вас есть какая-либо идея относительно этого, пожалуйста, помогите мне.

Заранее спасибо:)

Ответ 1

Вы можете использовать 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();

Ответ 2

Нет правильных ответов. Вот идеальный код.

// '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

Это просто копия ответа от 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 передаются в ffmpeg с помощью таких трансляций udp, как этот

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

Таким образом, сервер веб-сокетов просто получает закодированные в base64 данные pcm, декодирует строку base64 и просто транслирует через udp. Результат воспроизводится ffmpeg на динамике.

Ответ 4

Более простой способ состоит в том, чтобы иметь отдельный вызов для повторной выборки, который просто берет входной аудио-буфер, входную частоту дискретизации, выходную частоту дискретизации и возвращает выходной буфер. Я нашел эту ссылку, чтобы сделать это: ресэмплинг аудио

Это работает довольно хорошо (не много шума, вводимого в диапазонах звуковых частот..). Спасибо автору.