我正在尝试为andriod开发的应用程序,以48Khz(PCM 16位和单声道)记录帧并将它们发送到网络。此外,还有一个8Khz的传入音频流。所以,我接收8Khz采样帧并播放它们(我的AudioTrack对象设置为8Khz),但是当它们播放时,一切正常,但延迟是巨大的。你听到的东西大约需要3秒钟。
我认为如果我将接收到的帧从8Khz上采样到48Khz并播放它们,那么播放延迟就不会那么大了。事实上,当我以相同的速率录制和播放帧时,延迟非常低。不好的是我被迫这样做:发送到48Khz并接收到8Khz。
如前所述,我正在尝试将声音帧(16位PCM)从8Khz上采样到48Khz。有人知道Java中的任何例程/库/ API吗?
我知道关于对一个谨慎信号进行上采样的基础知识,但我认为设计和实现我自己的FIR滤波器并将其与音频流进行卷积....太过分了。另外,这是我所知道的。
所以...有人可以帮助我吗?有没有人知道我可以使用Java中的任何库/例程?任何建议或替代方案??
答案 0 :(得分:6)
快速而肮脏的解决方案是线性插值。由于你总是以6倍的方式取样,这很容易做到:
它有点像这样(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;
}
线性插值不会给您带来出色的音质,但它便宜又快捷。如果您愿意,可以使用三次插值来改善这一点。
如果你想要快速和高质量的重新采样,我建议你使用Android-NDK编译一个像libresample这样的c重采样库,并使用JNI从java中调用它。那会更快。编写JNI代码是大多数人回避的事情,但它很容易...... NDK有很多例子。
答案 1 :(得分:2)
线性插值引入了伪像。有一个很好的java库,高质量的重新采样 - JSSRC(http://jssrc.khadkevich.org/)。
现在可以在Github上找到代码: https://github.com/hutm/JSSRC
答案 2 :(得分:0)
我无法使大多数库正常工作(https://github.com/hutm/JSSRC,https://github.com/simingweng/android-pcm-resample,https://github.com/ashqal/android-libresample)。它们都在产生的音频中存在问题,或者只是无法从48000Hz转换为44100Hz(这就是我所需要的)。
尽管这很完美: https://github.com/JorenSix/TarsosDSP
这是一个大型的纯Java库,可在Android上运行(没有javax.sound依赖项),并且能够执行许多操作,但是如果您只将beutsos.dsp.resample包中的FilterKit,Resampler和SampelBuffers类用作,它的效果非常好,而且易于使用。
答案 3 :(得分:0)
TarsosDPS库太重了,无法满足我的需要,但是我发现重采样工具最初是作为较轻的3类库发布的:https://github.com/dnault/libresample4j
对于TarsosDPS,不需要Javax