iOS: 使用音频单元播放 RTP 数据包

iOS: Playing RTP packets using audio unit

我正在开发 VoIP 应用程序,需要播放服务器每 20 毫秒发送一次的 RTP 数据包中的数据。

我有一个缓冲区,用于累积来自 RTP 数据包的样本。音频单元渲染回调从该缓冲区读取数据。

问题是我无法将音频单元与 RTP 流同步。首选 IO 缓冲持续时间不能精确设置为 20 毫秒。并且渲染回调请求的帧数也不能设置为数据包的样本数。

因此,有两种可能的情况(取决于采样率和IO缓冲持续时间):

a) 音频单元从我的缓冲区中读取的速度比从 RTP 数据包中填充的速度快;在这种情况下,缓冲区周期性地不包含请求的样本数量,我得到的声音失真;

b) 缓冲区的填充速度比音频单元从中读取的速度快;在这种情况下,缓冲区会定期溢出,并且新 RTP 数据包中的样本会丢失。

我应该怎么做才能避免这个问题?

如果您正在接收音频

尝试让客户端定期(例如每秒)自动请求服务器根据缓冲区大小和连接速度发送特定比特率的音频。

例如,如果缓冲区中有 20 个样本和 15000kbit/s 的速度,并且 increase/decrease 音频样本比特率根据需要动态设置,则每个音频样本都为 300kbits。

如果您要发送音频

做同样的事情,但相反。让服务器定期请求客户端更改音频比特率。

如果您可以控制数据包速率,这通常是通过 "leaky bucket" 算法完成的。循环 FIFO/buffer 可以容纳传入数据的 "bucket",并且需要在 FIFO/buffer 中保留一定数量的填充以覆盖网络速率和延迟的变化。如果桶太满,你要求数据包发送者放慢速度等

在音频播放端,如果超过足够的缓冲区填充阈值,可以使用各种音频隐藏方法(PSOLA time-pitch modification等)稍微拉伸或收缩数据以适应。