我有一个48 kHz PCM流,想把它流式传输到44.1 kHz兼容播放器(Apple的AirPlay)。
有人知道这是否"只是工作,因为某些字节会丢失",还是我之前必须进行转换/下采样?
如果它不是"正常工作",那么在java中执行此操作有什么技巧吗?
编辑:
它不仅会起作用,因为声音会断断续续("信息溢出")。我必须对 pcm 流重新采样/下采样。
因为在这种情况下(48 kHz 到 44.1 kHz)这不是那么微不足道,所以我应该使用一个库来做到这一点:
我想我会尝试自由样本。因为我使用的是Android,所以我可以使用本机实现或Java实现。
你认为Java实现的性能足够好吗?
在您的案例中,所需的过程称为"按理性因子进行下采样"。这不是一个微不足道的问题,所以我建议你使用一个库来做到这一点 - 自己实现它需要大量的DSP知识。你可以改用libresample,一个C库,你必须为它编写JNI绑定。
要进行非常粗略的近似,您可以创建一个新的缓冲区,在其中复制大部分旧样本,但每 10 个样本丢弃一次。它不会完全是 44.1 kHZ,但比按原样播放要好。
好的,最简单的方法是每 48/44.1
个样本取一次(等于每 12 个样本踢出一次)。你最终将不得不这样做。
这样做的问题是混叠。如果你的下采样,你实际上是将下采样率之外的频谱镜像到你的样本中(请参阅这个维基页面以获得很好的解释),这称为混叠。你显然不希望这样(你可以尝试一下,看看你的音频会发生什么)。
那么我们如何才能防止这种情况发生呢?最常见的方法是以某种方式降低这些镜像频率块的频谱幅度。这样,它们被镜像,但不再那么重要,因为它们的振幅非常低。这可以通过使用截止频率接近采样比的低通滤波器来完成。所以步骤将是:
- 低通滤波您的样本以消除超过44.1kHz的高频幅度(注意不要摆脱低于该频率的东西)
- 对数据进行子采样(在您的情况下,每 12 个样本踢出一次)
那么该过滤器的要求是什么?其中一个重要要求是不应触及低于截止频率的频率幅度,因此非常低的通带纹波和1的通带增益会很好。然后应尽可能阻尼止动带。这显然取决于您的数据。我不知道特殊的音频处理,但通常在DSP中,使用的低通滤波器是FIR
或IIR
。当然还有许多其他方法,但这些都非常容易实现,并且在某种程度上甚至能够处理实时约束。
所以我建议你读两个过滤器实现(或者只关注FIR
)。如果你真的对我刚刚写的内容感到困惑,那么也许最好只使用具有某种低通滤波能力的给定库。但是如果你经常使用那些东西,那么我建议阅读这个问题,这真的有助于理解发生了什么...... ;)
您需要对输入信号应用抽取。首先,您需要通过低通滤波器传递输入(将此视为抗混叠)。
然后,您需要按合理因子进行缩减采样。互联网上有很多关于这两个过程的文章。所以如果你真的能胜任这项任务,那就去做一些研究吧。
例如,一种简单的低通滤波器方法是使用两个样本的平均值作为输出样本。也就是说,y(n)=(x(n)+x(n-1))/2;其中 y - 是输出,x - 输入,n - 当前样本位置。