ресамплировать / повышать частоту кадров от 8 до 48 кГц (Java / Android) - PullRequest
5 голосов
/ 16 июля 2010

Приложение, которое я пытаюсь разработать для andriod, записывает кадры с частотой 48 кГц (PCM 16 бит и моно) и отправляет их в сеть. Кроме того, есть входящий поток аудио на 8 кГц. Итак, я получаю сэмплы с частотой 8 кГц и воспроизводлю их (мой объект AudioTrack установлен на 8 кГц), но при их воспроизведении все работает, но задержка огромна. Это займет около 3 секунд, пока вы не услышите что-то.

Я думаю, что если я увеличу частоту дискретизации полученных кадров с 8 кГц до 48 кГц и воспроизведу их, не будет такой большой задержки воспроизведения. На самом деле, когда я записываю и играю кадры с одинаковой скоростью, задержка действительно низкая. Плохо то, что я вынужден сделать это так: отправить на 48 кГц и получить на 8 кГц.

Как объяснялось ранее, я пытаюсь увеличить частоту звукового кадра (16 бит / мин) с 8 до 48 кГц. Кто-нибудь знает какую-нибудь подпрограмму / библиотеку / API в Java, которая делает это ???

Я знаю основы о повышении дискретности дискретного сигнала, но считаю, что спроектировать и реализовать свой собственный FIR-фильтр и объединить его с аудиопотоком ... это слишком много. Кроме того, все кончено моим знанием.

Так ... кто-нибудь может мне помочь с этим ?? Кто-нибудь знает какую-нибудь библиотеку / рутину в Java, которую я могу использовать ?? Любые предложения или альтернативы?

Ответы [ 3 ]

5 голосов
/ 16 июля 2010

Быстрое и грязное решение - линейная интерполяция.Поскольку вы всегда делаете выборку в шесть раз, это действительно легко сделать:

Это работает примерно так (C-код, и не проверено, и я не обращаюсь с последней итерацией должным образом, ноэто показывает идею, которую я думаю).

void resample (short * output, short * input, int n)
{
  // output ought to be 6 times as large as input (48000/8000).

  int i;
  for (i=0; i<n-1; i++)
  {
    output[i*6+0] = input[i]*6/6 + input[i+1]*0/6;
    output[i*6+1] = input[i]*5/6 + input[i+1]*1/6;
    output[i*6+2] = input[i]*4/6 + input[i+1]*2/6;
    output[i*6+3] = input[i]*3/6 + input[i+1]*3/6;
    output[i*6+4] = input[i]*2/6 + input[i+1]*4/6;
    output[i*6+5] = input[i]*1/6 + input[i+1]*5/6;
  }

Линейная интерполяция не даст вам отличного качества звука, но это дешево и быстро.Вы можете улучшить это, используя кубическую интерполяцию, если хотите.

Если вы хотите быструю и качественную повторную выборку, я предлагаю вам скомпилировать библиотеку ac, например libresample, с помощью Android-NDK и вызывать ее из java, используя JNI.Это будет намного быстрее.Написание кода JNI - это то, от чего большинство людей уклоняется, но это довольно просто ... У NDK есть много примеров для этого.

http://www.mega -nerd.com / SRC / index.html

2 голосов
/ 28 февраля 2013

Линейная интерполяция вводит артефакты.Есть хорошая библиотека java с высококачественной повторной выборкой - JSSRC (http://jssrc.khadkevich.org/).

Код теперь доступен на Github: https://github.com/hutm/JSSRC

0 голосов
/ 13 июня 2019

Мне не удалось заставить работать большинство библиотек (https://github.com/hutm/JSSRC, https://github.com/simingweng/android-pcm-resample, https://github.com/ashqal/android-libresample). Все они имеют проблемы либо с результирующим звуком, либо просто не удалось преобразовать с 48000 Гц в 44100 Гц (этото, что мне было нужно).

Хотя этот работает отлично: https://github.com/JorenSix/TarsosDSP

Это большая библиотека на чистом Java, которая работает на Android (без зависимостей javax.sound) и способна на многиено если вы просто возьмете классы FilterKit, Resampler и SampelBuffers в пакете be.tarsos.dsp.resample, он будет работать очень хорошо и прост в использовании.

...