我目前正在尝试播放我在一系列 UDP 数据包中收到的音频。这些被解码为具有以下属性的 PCM 帧:
- 2个频道
- 交错的
- 单个通道中每个样本 2 个字节(因此每帧 4 个字节)
- 采样率为 48000。
每个 UDP 数据包包含 480 帧,因此缓冲区的大小为 480 * 2(channels) * 2(bytes per channel)。
我需要设置一个音频单元来播放这些数据包。所以,我的第一个问题是,我应该如何为音频单元设置 AudioStreamBasicDescription 结构?查看文档我什至不确定交错 PCM 是否是可接受的格式。
这是我到目前为止所得到的:
struct AudioStreamBasicDescription {
Float64 mSampleRate; //48000
UInt32 mFormatID; //?????
UInt32 mFormatFlags; //?????
UInt32 mBytesPerPacket; //Not sure what "packet" means here
UInt32 mFramesPerPacket; //Same as above
UInt32 mBytesPerFrame; //Same
UInt32 mChannelsPerFrame; //2?
UInt32 mBitsPerChannel; //16?
UInt32 mReserved; //???
};
typedef struct AudioStreamBasicDescription AudioStreamBasicDescription;
其次,设置后,我不确定如何从 UDP 回调中获取帧到实际的音频单元渲染函数。
我目前有一个来自套接字侦听器的回调函数,我在其中生成包含我要播放的音频的 int16 * 缓冲区。据我了解,我还必须为以下形式的音频单元实现渲染回调:
OSStatus RenderFrames(
void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData)
{
//No idea what I should do here.
return noErr;
}
综上所述,我认为我的套接字接收回调应该做的是解码帧,并将它们放在缓冲区结构中,以便 RenderFrames 回调可以从该缓冲区中获取帧,并播放它们。这个对吗?如果是这样,一旦我在 RenderFrames 函数中获取下一帧,我如何实际“提交”以进行播放?