iOS的kAudioDevicePropertyBufferFrameSize替代方案

3

我尝试设置音频单元来渲染音乐(而不是使用对我的目的太模糊不清的音频队列),iOS没有这个属性 kAudioDevicePropertyBufferFrameSize,你有什么想法如何推导出这个值来设置我的IO单元的缓冲区大小?

我发现这篇文章很有趣,它询问使用kAudioSessionProperty_CurrentHardwareIOBufferDurationkAudioSessionProperty_CurrentHardwareOutputLatency音频会话属性的组合是否可能确定该值,但没有答案,有任何想法吗?

2个回答

5
您可以使用 kAudioSessionProperty_CurrentHardwareIOBufferDuration 属性来表示缓冲区大小(以秒为单位)。将此乘以从 kAudioSessionProperty_CurrentHardwareSampleRate 得到的采样率,即可得到应该缓冲的样本数。
得到的缓冲区大小应该是2的倍数。我认为您可能会得到512或4096,但您应该始终基于从 AudioSessionGetProperty 返回的值进行计算。
例如:
Float64 sampleRate;
UInt32 propSize = sizeof(Float64);
AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareSampleRate, 
                        &propSize,
                        &sampleRate);

Float32 bufferDuration;
propSize = sizeof(Float32);
AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareIOBufferDuration, 
                        &propSize,
                        &bufferDuration);

UInt32 bufferLengthInFrames = sampleRate * bufferDuration;

下一步是找出你要发送音频的单元的输入流格式。根据你的描述,我假设你正在编程生成音频并将其发送到扬声器。这段代码假定“unit”是你要发送音频的“AudioUnit”,无论是RemoteIO还是类似效果音频单元。
AudioStreamBasicDescription inputASBD;
UInt32 propSize = sizeof(AudioStreamBasicDescription);
AudioUnitGetProperty(unit,
                     kAudioUnitProperty_StreamFormat,
                     kAudioUnitScope_Input,
                     0,
                     &inputASBD,
                     &propSize);

此后,inputASBD.mFormatFlags将成为一个位字段,对应于unit所期望的音频流格式。最可能的两组标志是kAudioFormatFlagsCanonicalkAudioFormatFlagsAudioUnitCanonical。这两个都有相应的样本类型AudioSampleTypeAudioUnitSampleType,您可以根据此计算大小。
另外,AudioSampleType通常代表来自麦克风或目标扬声器的样本,而AudioUnitSampleType通常用于旨在处理的样本(例如,由音频单元)。目前在iOS上,AudioSampleType是SInt16,AudioUnitSampleType是存储在SInt32容器中的固定8.24数字。这里是Core Audio邮件列表上关于这个设计选择的帖子 我不建议像“只使用Float32,它会起作用”的做法,因为如果Apple觉得合适,流的实际位表示可能会发生更改。

所以我假设 bufferSizeBytes 将等于 sampleRate * bufferDuration * sizeof(Float32)(假设单个样本值为4字节)?还有一件我有点模糊的事情,但是你能说 bufferLengthInSamples = bufferLengthInFrames 吗(即使我们使用立体声音频,即1帧=2个样本)? - abbood
好的观点,更正确的称呼应该是 bufferLengthInFrames。关于字节数的样本大小,你不应该假定它们将以什么格式出现。不同的音频单元将具有不同的兼容输入/输出格式。我会更新我的答案反映下一步。 - admsyn
一种现代化的方法是使用AVAudioSession来替代第一个已弃用的部分:[[AVAudioSession sharedInstance] sampleRate] * [[AVAudioSession sharedInstance] IOBufferDuration]; - Ráfagan

1
音频单元本身决定实际缓冲区大小,因此应用程序的音频单元回调必须能够处理任何合理的大小。您可以建议和轮询kAudioSessionProperty_CurrentHardwareIOBufferDuration属性,但请注意,该值可能会在应用程序无法控制的情况下(尤其是在屏幕锁定或通话中断等情况下)发生变化。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接