在 iPhone 應用或者是遊戲的開發過程中,對聲音的支援是必不可少的。在我做過的幾個應用中,每個都涉及到音效,所以在這裡做個簡單的歸納,很多都是引用自《iPhone
Application Programming Guide》 (需要有 Apple ID 才能開啟連結),加了一些實際使用的經驗。
iPhone OS 主要提供以下了幾種播放音訊方法:
- System Sound Services
- AVAudioPlayer 類
- Audio Queue Services
- OpenAL
關於System Sound Services
System Sound Services 是最底層也是最簡單的聲音播放服務,調用 AudioServicesPlaySystemSound 這個方法就可以播放一些簡單的音頻檔案,使用此方法只適合播放一些很小的提示或者警告音,因為它有很多限制:
■
聲音長度要小於 30 秒
■ In linear PCM 或者 IMA4 (IMA/ADPCM) 格式的
■ 打包成 .caf, .aif, 或者 .wav 的檔案
■ 不能控制播放的進度
■ 調用方法後立即播放聲音
■ 沒有迴圈播放和立體聲控制
另外,它還可以調用系統的震動功能,方法也很簡單。具體的代碼可以參考官方的樣本 SysSound,但是官方的樣本只有一些簡單的用法,從文檔中我們發現可以通過 AudioServicesAddSystemSoundCompletion 方法為音頻播放添加
CallBack 函數,有了 CallBack 函數我們可以解決不少問題,比如可以克服 System Sound Services 本身不支援迴圈播放的問題。以下代碼可以實現一個在程式中迴圈播放的背景音樂:
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 ("http://www.cnblogs.com/ComedyHorns.aif"), 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; }
除了對簡單音訊限制外,你對於音頻播放的方式也基本無法控制。一旦音頻播放就會立即開始,而且是當前電話使用者設定的音量播放。你將無法迴圈播放聲音,也無法控制立體聲效果。不過你還是可以設定一個回呼函數,在音頻播放結束時被調用,這樣你就可以對音頻對象做清理工作,以及通知你的程式播放結束。
個人覺得這個音頻服務功能不是很強,但是某種情況下十分適用,比如我們要播放一個自訂的警告音或者訊息提示,用音頻服務肯定比其他的方法節省資源。