1

我的一个应用程序使用 NSSound 播放 10 秒 AAC 编码的预先录制的白噪声循环,我几乎已经完成了白噪声功能的工作。

[sound setLoops: YES]

应该是所有需要的,对吧?

它就像一个魅力,但我注意到在声音文件完成和重新启动之间有一个可听见的停顿......一种“扑通”的声音。这在循环原始声音文件时不存在,经过一个小时左右的时间试图弄清楚这一点,我得出的结论是 NSSound 很烂,并且可听见的暂停是私有后台线程同步的产物播放声音。它似乎以某种方式依赖于主运行循环,这会导致声音结束和重新开始之间的可听间隙。

我对声音知之甚少,这是一个非常次要的功能,所以我不想深入 CoreAudio 只是为了播放循环 10 秒的声音片段.. 所以我去追求一个不错的选择,但似乎什么都没有非常适合:

  • Core Audio:完全矫枉过正,但至少是标准框架
  • AudioQueue:复杂,带有 C++ 示例代码!?
  • MusicKit/ SndKit:也是巨大的学习曲线,基于大量开源的东西等。

我看到 iOS 4 上的 AVFoundation 将是播放声音的好方法,但这只计划用于 Mac OS X 10.7..

在 Mac OS X 10.5+ 上是否有任何易于使用的可靠循环声音的方法?

是否有任何用于 AudioQueue 或 Core Audio 的示例代码可以减轻在 Objective-C 应用程序中使用它们的痛苦?

任何帮助将不胜感激..

最好的祝福,

坦率

4

3 回答 3

2

使用 QTKit。为声音创建一个QTMovie,将其设置为循环,然后继续播放。

于 2010-08-24T14:37:56.307 回答
2

只是为了存档。

QTKit 还受到一个播放结束和下一个播放开始之间的差距的影响。它似乎与以某种方式重新初始化数据(也许从磁盘重新读取它?)有关。使用小得多但高度压缩的 m4a 格式比播放未压缩的 aiff 文件时明显得多,但即便如此,它仍然存在。

我找到的解决方案是使用音频队列服务:

http://developer.apple.com/mac/library/documentation/MusicAudio/Conceptual/AudioQueueProgrammingGuide/AQPlayback/PlayingAudio.html#//apple_ref/doc/uid/TP40005343-CH3-SW1

http://developer.apple.com/mac/library/samplecode/AudioQueueTools/Listings/aqplay_cpp.html#//apple_ref/doc/uid/DTS10004380-aqplay_cpp-DontLinkElementID_4

音频队列调用一个回调函数来准备下一个缓冲区并将其排入队列,因此当您到达当前文件的末尾时,您需要从头开始重新开始。这提供了完全无间隙的播放。

文档中的示例代码中有两个陷阱。

第一个是一个实际的错误(我会就此联系 DTS,以便他们更正它)。在分配和启动音频缓冲区之前,自定义结构必须打开播放,否则音频缓冲区永远不会被启动并且什么都不会播放:

    aqData.mIsRunning = 1;

第二个问题是代码不是在 Cocoa 中运行,而是作为独立工具运行,因此代码将音频队列连接到一个新的运行循环,并且实际上将运行循环本身实现为程序的最后一步。

无需传递 CFRunLoopGetCurrent(),只需传递 NULL,这会导致 AudioQueue 在其自己的运行循环中运行。

result = AudioQueueNewOutput (                                // 1
                     &aqData.mDataFormat,                             // 2
                     HandleOutputBuffer,                              // 3
                     &aqData,                                         // 4
                     NULL, //CFRunLoopGetCurrent (),                          // 5
                     kCFRunLoopCommonModes,                           // 6
                     0,                                               // 7
                     &aqData.mQueue                                   // 8
                     );

我希望这可以为那些试图在未来做同样事情的可怜虫节省一点时间:-)

于 2010-08-26T08:46:00.027 回答
0

可悲的是,在 OS X 上开发音频应用程序时有很多痛苦。学习曲线非常陡峭,因为文档相当稀疏。

如果您不介意 Objective-C++,我已经为这种事情编写了一个框架:SFBAudioEngine。如果你想用我的代码播放声音,你可以这样做:

DSPAudioPlayer *player = new DSPAudioPlayer();
player->Enqueue((CFURLRef)audioURL);
player->Play();

循环也是可能的。

于 2010-08-24T13:50:05.400 回答