在 iPhone 应用或者是游戏的开发过程中,对声音的支持是必不可少的。在我做过的几个应用中,每个都涉及到音效,所以在这里做个简单的归纳,很多都是引用自《iPhone Application Programming Guide》(需要有 Apple ID 才能打开链接),加了一些实际使用的经验。

iPhone OS 主要提供以下了几种播放音频的方法:

  • System Sound Services
  • AVAudioPlayer 类
  • Audio Queue Services
  • OpenAL

关于System Sound Services

AudioServicesPlaySystemSound

声音长度要小于 30 秒

■ In linear PCM 或者 IMA4 (IMA/ADPCM) 格式的

■ 打包成 .caf, .aif, 或者 .wav 的文件

■ 不能控制播放的进度

■ 调用方法后立即播放声音

■ 没有循环播放和立体声控制

另外,它还可以调用系统的震动功能,方法也很简单。具体的代码可以参考官方的示例 SysSound,但是官方的示例只有一些简单的用法,从文档中我们发现可以通过 AudioServicesAddSystemSoundCompletion


static  void  completionCallback (SystemSoundID  mySSID) {
     // Play again after sound play completion 
     AudioServicesPlaySystemSound(mySSID);
 }
 - (void ) playSound {
     // Get the main bundle for the app 
     CFBundleRef mainBundle;
     SystemSoundID soundFileObject;
     mainBundle = CFBundleGetMainBundle ();
     
     // Get the URL to the sound file to play 
     CFURLRef soundFileURLRef  = CFBundleCopyResourceURL (
                                                          mainBundle,
                                                          CFSTR ("background" ),
                                                          CFSTR ("wav" ),
                                                          NULL 
                                                          );
     // Create a system sound object representing the sound file 
     AudioServicesCreateSystemSoundID (
                                       soundFileURLRef,
                                       &soundFileObject
                                       );
     // Add sound completion callback 
     AudioServicesAddSystemSoundCompletion (soundFileObject, NULL , NULL ,
                                            completionCallback,
                                            (void *) self );
     // Play the audio 
     AudioServicesPlaySystemSound(soundFileObject);
     
 }



另外一段:



#include <AudioToolbox/AudioToolbox.h>
 #include <CoreFoundation/CoreFoundation.h>
 // Define a callback to be called when the sound is finished
 // playing. Useful when you need to free memory after playing.
 static void MyCompletionCallback (
     SystemSoundID  mySSID,
     void * myURLRef
 ) {
         AudioServicesDisposeSystemSoundID (mySSID);
CFRelease (myURLRef);    //CFURLCreateWithFileSystemPath()创建的需释放

         CFRunLoopStop (CFRunLoopGetCurrent());
 }
 int main (int argc, const char * argv[]) {
     // Set up the pieces needed to play a sound.
     SystemSoundID    mySSID;
     CFURLRef        myURLRef;
     myURLRef = CFURLCreateWithFileSystemPath (
         kCFAllocatorDefault,
         CFSTR (""),
         kCFURLPOSIXPathStyle,
         FALSE
     );
     // create a system sound ID to represent the sound file
     OSStatus error = AudioServicesCreateSystemSoundID (myURLRef,
 &mySSID);
     // Register the sound completion callback.
     // Again, useful when you need to free memory after playing.
     AudioServicesAddSystemSoundCompletion (
         mySSID,
         NULL,
         NULL,
         MyCompletionCallback,
         (void *) myURLRef
     );
     // Play the sound file.
     AudioServicesPlaySystemSound (mySSID);
   // Invoke a run loop on the current thread to keep the application
     // running long enough for the sound to play; the sound completion
     // callback later stops this run loop.
     CFRunLoopRun ();
     return 0;
 }



除了对简单音频的限制外,你对于音频播放的方式也基本无法控制。一旦音频播放就会立即开始,而且是当前电话使用者设置的音量播放。你将无法循环播放声音,也无法控制立体声效果。不过你还是可以设置一个回调函数,在音频播放结束时被调用,这样你就可以对音频对象做清理工作,以及通知你的程序播放结束。


个人觉得这个音频服务功能不是很强,但是某种情况下十分适用,比如我们要播放一个自定义的警告音或者消息提示,用音频服务肯定比其他的方法节省资源。