gpt4 book ai didi

ios - 使用 AudioUnit 的精确定时器

转载 作者:行者123 更新时间:2023-11-28 21:43:20 28 4
gpt4 key购买 nike

我正在尝试制作一个准确的计时器来分析输入。我希望能够测量 ~200ms 信号中 1% 的偏差。我的理解是使用 AudioUnit 可以获得 <1ms。我尝试实现 Stefan Popp's example 中的代码在更新了一些东西以使其在 xcode 6.3 上运行后,我已经可以运行该示例了,但是:

  1. 虽然我最终确实想要捕获音频,但我认为应该有一些方法来获取通知,比如 NSTimer,所以我尝试了 AudioUnitAddRenderNotify,但它完全按照它说的去做 - 即它与渲染,而不仅仅是一个任意的计时器。有什么方法可以在不录制或播放的情况下触发回调吗?

  2. 当我检查 mSampleTime 时,我发现切片之间的间隔与 inNumberFrames - 512 - 相匹配,计算结果为 11.6 毫秒。我看到录制和播放的时间间隔相同。我需要比这更高的分辨率。

我尝试使用 kAudioSessionProperty_PreferredHardwareIOBufferDuration,但我能找到的所有示例都使用已弃用的 AudioSessions,因此我尝试转换为 AudioUnits:

Float32 preferredBufferSize = .001; // in seconds
status = AudioUnitSetProperty(audioUnit, kAudioSessionProperty_PreferredHardwareIOBufferDuration, kAudioUnitScope_Output, kOutputBus, &preferredBufferSize, sizeof(preferredBufferSize));

但我得到 OSStatus -10879,kAudioUnitErr_InvalidProperty。

然后我尝试使用值为 128 和 256 的 kAudioUnitProperty_MaximumFramesPerSlice,但 inNumberFrames 始终为 512。

UInt32 maxFrames = 128;
status = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &maxFrames, sizeof(maxFrames));

[编辑]我正在尝试将输入的时间(用户选择的 MIDI 或麦克风)与应该的时间进行比较。具体来说,乐器是在节拍/节拍器之前还是之后演奏的,演奏了多少?这是为音乐家准备的,而不是游戏,因此需要精确。

[编辑]答案似乎对事件有反应。也就是说,他们让我准确地看到什么时候发生了什么,但是我不明白我是如何准确地做某事的。我的错是不清楚。我的应用程序也需要成为节拍器 - 同步播放节拍上的点击并在节拍上闪烁一个点 - 然后我可以分析用户的 Action 以比较时间。但如果我不能准确地演奏节拍,其余的就会分崩离析。也许我应该录制音频 - 即使我不想要它 - 只是为了从回调中获取 inTimeStamp?

[编辑]目前我的节拍器是:

- (void) setupAudio
{
AVAudioPlayer *audioPlayer;
NSString *path = [NSString stringWithFormat:@"%@/click.mp3", [[NSBundle mainBundle] resourcePath]];
NSURL *soundUrl = [NSURL fileURLWithPath:path];
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:soundUrl error:nil];
[audioPlayer prepareToPlay];

CADisplayLink *syncTimer;
syncTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(syncFired:)];
syncTimer.frameInterval = 30;
[syncTimer addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
}

-(void)syncFired:(CADisplayLink *)displayLink
{
[audioPlayer play];
}

最佳答案

您应该使用循环缓冲区,并在与您自己的计时器上所需帧数相匹配的 block 中对信号进行分析。为此,您需要设置渲染回调,然后将回调中的输入音频提供给循环缓冲区。然后您设置自己的计时器,该计时器将从缓冲区的尾部提取并进行分析。通过这种方式,您可以每 0.23 秒向缓冲区提供 1024 帧,并且您的分析计时器可能每 0.000725 秒触发一次并分析 32 个样本。 Here是一个关于循环缓冲区的相关问题。

编辑

要使用环形缓冲区获得精确计时,您还可以存储与音频缓冲区对应的时间戳。我用 TPCircularBuffer因为这样做。 TPCircularBufferPrepareEmptyAudioBufferList、TPCircularBufferProduceAudioBufferList 和 TPCircularBufferNextBufferList 将在环形缓冲区中复制和检索音频缓冲区和时间戳。然后,当您进行分析时,每个缓冲区都会有一个时间戳,从而无需在渲染线程中完成所有工作,并允许您挑选分析窗口。

关于ios - 使用 AudioUnit 的精确定时器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31234127/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com