停止 AUGraph 的口吃

Posted

技术标签:

【中文标题】停止 AUGraph 的口吃【英文标题】:Stop AUGraph's stuttering 【发布时间】:2014-02-16 06:58:10 【问题描述】:

当我第一次启动 AUGraph 并播放带有 kAudioUnitSubType_AudioFilePlayer 组件的歌曲时,我收到了结结巴巴的声音。口吃大约是 3 秒,但这足以让我感到困扰,而且我注意到音乐有时会在播放时停止一瞬间(我猜是缓冲?)。我尝试将kAudioUnitProperty_ScheduledFilePrime 更改为随机值,但没有发现任何变化。

我应该改变哪些变量或值来消除这个缺陷?这是流格式的问题吗?

我正在使用来自 https://github.com/ronaldmannak/YBAudioFramework/tree/master/YBAudioUnit 的 YBAudioUnit

代码:

YBAudioFilePlayer:

- (void)setFileURL:(NSURL *)fileURL typeHint:(AudioFileTypeID)typeHint 
    if (_fileURL) 
        // Release old file:
        AudioFileClose(_audioFileID);
    

    _fileURL = fileURL;

    if (_fileURL) 
        YBAudioThrowIfErr(AudioFileOpenURL((__bridge CFURLRef)fileURL, kAudioFileReadPermission, typeHint, &_audioFileID));
        YBAudioThrowIfErr(AudioUnitSetProperty(_auAudioUnit, kAudioUnitProperty_ScheduledFileIDs, kAudioUnitScope_Global, 0, &_audioFileID, sizeof(AudioFileID)));

        // Get number of audio packets in the file:
        UInt32 propsize = sizeof(_filePacketsCount);
        YBAudioThrowIfErr(AudioFileGetProperty(_audioFileID, kAudioFilePropertyAudioDataPacketCount, &propsize, &_filePacketsCount));

        // Get file's asbd:
        propsize = sizeof(_fileASBD);
        YBAudioThrowIfErr(AudioFileGetProperty(_audioFileID, kAudioFilePropertyDataFormat, &propsize, &_fileASBD));

        // Get unit's asbd:
        propsize = sizeof(_fileASBD);
        AudioUnitGetProperty(_auAudioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &_unitASBD, &propsize);

        if (_fileASBD.mSampleRate > 0 && _unitASBD.mSampleRate > 0) 
            _sampleRateRatio = _unitASBD.mSampleRate / _fileASBD.mSampleRate;
         else 
            _sampleRateRatio = 1.;
        
    

为了播放,我在 YBAudioFilePlayer 上调用这些方法:

[player1 setFileURL:item.url typeHint:0];
[player1 scheduleEntireFilePrimeAndStartImmediately];
[graph start];//On a YBAudioUnitGraph which is really just a basic AUGraph

【问题讨论】:

这是在模拟器上吗?装置?还是两者兼而有之? 你在使用回调吗?如果是,您可以发布代码吗? @Merlevede 我已经更新了代码,但我没有使用回调。它是一个附加的 AUNode。 @kdogisthebest 当您说音频单元时,我认为您使用的是苹果的音频单元,不幸的是我不熟悉您使用的 API。只是为了好奇,为什么不使用苹果的 API? @Merlevede 它是 Apple 音频单元的包装器。它仍然发生相同的事情,我仍然能够访问相同的对象:AudioUnit、AUGraph、AUNode。就像 YBAudioUnitGraph 是一个由 NSObject 控制的后台 AUGraph。 【参考方案1】:

这不仅仅是一个答案,而是一个评论,但它相当大,所以我会在这里发布。

我没有时间和耐心研究 YB.. API 中的代码。但是我想到了一些事情。

首先我记得我尝试过音频单元(使用 Apple 的 API),但我遇到了很多口吃。我解决了在将数据提供给我的 AUGraph 的回调中删除所有 Objective-C 调用的问题(好吧,除了我无法摆脱的一个之外,我删除了所有的调用)。我用纯 C 和 C++ 调用替换了所有 Objective-c 调用。示例:

... this is the render callback
int i = [myClass someProperty];  // obj-c
int i = myClass->someVarialbe;  // c, c++

这只是一个例子,但它得到了显着改善,我摆脱了口吃。或许你可以看一下YBXX API的实现,看看回调中是否有很多obj-c调用,如果有,我就不使用API​​了。

第二次观察。似乎您只是在尝试播放音频文件,而拥有 AudioGraph 的开销很大,您可以使用没有 Graph 的单个 IO 音频单元。

【讨论】:

没有回调,一切都通过了。我知道第二个对我不起作用。我实际上正在使用效果器和带有两条轨道的多通道混音器。我不会说音频路由的复杂性会成为问题,因为我只是在进行基本设置时遇到了这个问题。【参考方案2】:

有很多问题要问:

首先,您使用的是压缩音频文件吗?如果是这样,您可能需要考虑填充帧 (kAudioFilePropertyPacketTableInfo) 以获取文件中的实际音频帧数。不妨试试 AIFF、CAF 或 WAV 文件。

您确定没有其他音频应用在后台运行吗?

有日志消息吗?

您是否尝试过在 github 上发布到他们的问题页面?

最后一个问题是您为什么要尝试使用他们的框架(两年未更新)。我会推荐The Amazing Audio Engine。它是由 ios 上一些最优秀的音频专家积极开发的。

【讨论】:

以上是关于停止 AUGraph 的口吃的主要内容,如果未能解决你的问题,请参考以下文章

Java KeyListener 口吃

在数字字段中停止双重句点

在IOS核心音频中,如何找到文件播放器音频单元的真实当前播放头位置?

NAudio ASIO Playback 在某些设备上挂起

AUGraph 在 iOS 上被弃用了吗?如果是这样,啥时候?

如何编辑 AUGraph 的默认工具?