AVAudioEngine 不正确的时间管理和 AVAudioPlayerNode 回调

Posted

技术标签:

【中文标题】AVAudioEngine 不正确的时间管理和 AVAudioPlayerNode 回调【英文标题】:AVAudioEngine incorrect time management and callback for AVAudioPlayerNode 【发布时间】:2015-03-27 10:54:09 【问题描述】:

ios8 中的新音频引擎存在严重问题。我有一个应用程序,它是用 AVAudioPlayer 构建的,我正试图找出一种迁移到新架构的方法,但是我遇到了以下问题(我相信你会同意,这是一个严重的基本障碍) :

我的头文件:

AVAudioEngine *engine;
AVAudioMixerNode *mainMixer;
AVAudioPlayerNode *player;

我的 m 文件(在 viewDidLoad 内):

engine = [[AVAudioEngine alloc] init];
player = [[AVAudioPlayerNode alloc] init];

[engine attachNode:player];

NSURL *fileUrl = [[NSURL alloc] initFileURLWithPath:[[NSBundle mainBundle] pathForResource:@"test" ofType:@"mp3"]];

AVAudioFile *file = [[AVAudioFile alloc] initForReading:fileUrl error:nil];

NSLog(@"duration: %.2f", file.length / file.fileFormat.sampleRate);

[player scheduleFile:file atTime:nil completionHandler:^
    AVAudioTime *nodeTime = player.lastRenderTime;
    AVAudioTime *playerTime = [player playerTimeForNodeTime:nodeTime];

    float secs = (float)playerTime.sampleTime / file.fileFormat.sampleRate;

    NSLog(@"finished at: %.2f", secs);
];

mainMixer = [engine mainMixerNode];

[engine connect:player to:mainMixer format:file.processingFormat];
[engine startAndReturnError:nil];

[player play];

上面的代码初始化引擎和一个节点,然后开始播放我正在使用的任何文件。首先它打印出音乐文件的时长,然后在播放完成后,在回调函数中打印播放器的当前时间。这两个应该是相同的,或者在最坏的情况下,非常非常接近,但事实并非如此,这两个值之间的差异非常大,例如

duration: 148.51
finished at: 147.61

我做错了吗?这应该很简单,我尝试过不同的文件格式、文件长度、数十个音乐文件,但差异总是在 1 秒左右或不到 1 秒。

【问题讨论】:

【参考方案1】:

更新:

从 iOS 11 开始,您可以指定 completionCallbackType: AVAudioPlayerNodeCompletionCallbackType

数据消耗: 指示缓冲区或文件数据已被播放器消耗的完成处理程序。

数据渲染: 播放器已渲染的缓冲区或文件数据。

dataPlayedBack: 指示缓冲区或文件已完成播放的完成处理程序。

更多信息:Documentation

原文:

根据 Apple 的 scheduleFile:atTime:completionHandler 文档:

完成处理程序可以在渲染之前被调用 开始或在文件完全播放之前。

【讨论】:

以上是关于AVAudioEngine 不正确的时间管理和 AVAudioPlayerNode 回调的主要内容,如果未能解决你的问题,请参考以下文章

AVAudioEngine 是不是支持递归路由?

匹配 AVAudioEngine 的输入和输出硬件设置

AVAudioEngine 寻找歌曲的时间

如何指定 AVAudioEngine Mic-Input 的格式?

设置 AVAudioEngine 输入和输出设备

AVAudioEngine.connect 上的 CoreAudio 错误和崩溃