类似 NSSound 的框架可以工作,但不需要处理陡峭的学习曲线
我已经基本完成了我的一个应用程序的白噪声功能工作,使用 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 应用程序中使用它们的痛苦?
任何帮助将非常感激..
最诚挚的问候,
弗兰克
I've pretty much finished work on a white noise feature for one of my applications using NSSound to play a loop of 10 second AAC-encoded pre-recorded white noise.
[sound setLoops: YES]
should be all that's required, right?
It works like a charm but I've noticed that there is an audible pause between the sound file finishing and restarting.. a sort of "plop" sound. This isn't present when looping the original sound files and after an hour or so of trying to figure this out, I've come to the conclusion that NSSound sucks and that the audible pause is an artefact of the synchronisation of the private background thread playing the sound. It seems to be dependent on the main run loop somehow and this causes the audible gap between the end and restarting of the sound.
I know very little about sound stuff and this is a very minor feature, so I don't want to get into the depths of CoreAudio just to play a looping 10s sound fragment.. so I went chasing after a nice alternative, but nothing seems to quite fit:
- Core Audio: total overkill, but at least a standard framework
- AudioQueue: complicated, with C++ sample code!?
- MusicKit/ SndKit: also huge learning curve, based on lots of open source stuff, etc.
I saw that AVFoundation on iOS 4 would be a nice way to play sounds, but that's only scheduled for Mac OS X 10.7..
Is there any easy-to-use way of reliably looping sound on Mac OS X 10.5+?
Is there any sample code for AudioQueue or Core Audio that takes the pain out of using them from an Objective-C application?
Any help would be very much appreciated..
Best regards,
Frank
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
使用 QTKit。为声音创建一个
QTMovie
,将其设置为循环,然后让它继续播放。Use QTKit. Create a
QTMovie
for the sound, set it to loop, and leave it playing.只是为了档案。
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 解决这个问题,以便他们可以纠正它)。在分配和启动音频缓冲区之前,自定义结构必须打开播放,否则音频缓冲区永远不会启动并且不会播放任何内容:
第二个问题是代码不在 Cocoa 中运行,而是作为独立工具运行,因此代码连接音频队列到一个新的运行循环,并实际上将运行循环本身实现为程序的最后一步。
无需传递 CFRunLoopGetCurrent(),只需传递 NULL,这会导致 AudioQueue 在其自己的运行循环中运行。
我希望这可以为将来尝试做同样事情的可怜人节省一些时间:-)
Just for the sake of the archives.
QTKit also suffers from a gap between the end of one play through and start of the next one. It seems to be linked with re-initializing the data (perhaps re-reading it from disk?) in some way. It's a lot more noticeable when using the much smaller but highly compressed m4a format than when playing uncompressed aiff files but it's still there even so.
The solution I've found is to use Audio Queue Services:
http://developer.apple.com/mac/library/documentation/MusicAudio/Conceptual/AudioQueueProgrammingGuide/AQPlayback/PlayingAudio.html#//apple_ref/doc/uid/TP40005343-CH3-SW1
and
http://developer.apple.com/mac/library/samplecode/AudioQueueTools/Listings/aqplay_cpp.html#//apple_ref/doc/uid/DTS10004380-aqplay_cpp-DontLinkElementID_4
The Audio Queue calls a callback function which prepares and enqueues the next buffer, so when you reach the end of the current file you need to start again from the beginning. This gives completely gapless playback.
There's two gotchas in the sample code in the documentation.
The first is an actual bug (I'll contact DTS about this so they can correct it). Before allocating and priming the audio buffers, the custom structure must switch on playback otherwise the audio buffer never get primed and nothing is played:
The second gotcha is that the code doesn't run in Cocoa but as a standalone tool, so the code connects the audio queue to a new run loop and actually implements the run loop itself as the last step of the program.
Instead of passing CFRunLoopGetCurrent(), just pass NULL which causes the AudioQueue to run in its own run loop.
I hope this can save the poor wretches trying to do this same thing in the future a bit of time :-)
遗憾的是,在 OS X 上开发音频应用程序时会遇到很多痛苦。学习曲线非常陡峭,因为文档相当稀疏。
如果你不介意 Objective-C++,我已经为这种事情编写了一个框架: SFBAudioEngine 。如果你想用我的代码播放声音,你可以这样做:
循环也是可能的。
Sadly, there is a lot of pain when developing audio applications on OS X. The learning curve is very steep because the documentation is fairly sparse.
If you don't mind Objective-C++ I've written a framework for this kind of thing: SFBAudioEngine. If you wanted to play a sound with my code here is how you could do it:
Looping is also possible.