OSX CoreAudio:提前获取 inNumberFrames - 在初始化时?

OSX CoreAudio: Getting inNumberFrames in advance - on initialization?

我正在尝试用 C 语言编写一个简单的基于单 AU 播放的(几乎)无延迟 跟踪相位声码器 原型。它是一个独立的程序。我想知道单个渲染回调可以安全地承受多少处理负载,所以我更喜欢远离异步 DSP。

我的想法是只有一个预定值,即window step,或hop size or decimation factor文献来源)。这个数字等于 inNumberFrames,这在某种程度上取决于 设备采样率 (还有什么?)。所有其他参数,例如 window sizeFFT size 将根据 window 步骤设置。这似乎是将所有内容保留在一个回调中的最简单方法。

在实际渲染开始之前,即在调用 AudioOutputUnitStart() 之前,是否有一种安全的方法可以独立于机器安全地猜测或查询可能是 inNumberFrames

相位声码器算法大部分是标准的并且非常简单,使用 vDSP 函数进行 FFT,加上自定义相位积分,我没有遇到任何问题。

其他调试信息

此代码正在监视输入回调中的计时:

static Float64 prev_stime;  //prev. sample time
static UInt64  prev_htime;  //prev. host time        
printf("inBus: %d\tframes: %d\tHtime: %lld\tStime: %7.2lf\n",
       (unsigned int)inBusNumber,
       (unsigned int)inNumberFrames,
       inTimeStamp->mHostTime   - prev_htime,
       inTimeStamp->mSampleTime - prev_stime);
prev_htime = inTimeStamp->mHostTime;
prev_stime = inTimeStamp->mSampleTime;

奇怪的是,TimeStamp->mSampleTime 中的参数实际上显示了渲染帧的数量(参数名称似乎有些误导)。这个数字总是 512,无论是否在运行时通过 AudioMIDISetup.app 重新设置了另一个采样率,就好像该值已经以编程方式硬编码一样.一方面,

inTimeStamp->mHostTime - prev_htime

间隔根据以数学上清晰的方式设置的采样率动态变化。只要采样率值匹配 44100Hz 的倍数,就会进行实际渲染。另一方面,48kHz 的倍数产生渲染 error -10863 ( = kAudioUnitErr_CannotDoInCurrentContext )。我一定错过了很重要的一点。

假设 audioUnit 是一个输入音频单元:

UInt32 inNumberFrames = 0;
UInt32 propSize = sizeof(UInt32);
AudioUnitGetProperty(audioUnit, 
                     kAudioDevicePropertyBufferFrameSize, 
                     kAudioUnitScope_Global, 
                     0, 
                     &inNumberFrames, 
                     &propSize);

帧数通常是采样率乘以缓冲持续时间。有一个音频单元 API 请求采样率和首选缓冲持续时间(例如 44100 和 5.8 毫秒导致 256 帧),但并非所有 OS 版本上的所有硬件都支持所有请求的缓冲持续时间或采样率。

This number would equal inNumberFrames, which somehow depends on the device sampling rate (and what else?)

这取决于您尝试将其设置为什么。你可以设置它。

// attempt to set duration
NSTimeInterval _preferredDuration = ...
NSError* err;
[[AVAudioSession sharedInstance]setPreferredIOBufferDuration:_preferredDuration error:&err];


// now get the actual duration it uses

NSTimeInterval _actualBufferDuration;
_actualBufferDuration = [[AVAudioSession sharedInstance] IOBufferDuration];

它会使用一个大致在您设置的首选值附近的值。实际使用的值是基于2的幂和当前采样率的时间间隔。

如果您正在寻找跨设备的一致性,请选择 10 毫秒左右的值。性能最差的合理现代设备是 iOS 没有后置摄像头的 iPod touch 16gb。但是,此设备可以毫无问题地执行大约 10 毫秒的回调。在某些设备上,您 "can" 将持续时间设置得非常低并获得非常快的回调,但通常它会破裂,因为在下一次回调发生之前回调中的处理尚未完成。