Linear PCM
在介紹Core Audio之前,先介紹一下最常用的非壓縮數字音頻格式Linear PCM(線性脈沖編碼調制)。在計算機錄音的過程中,他會每隔一定的時間會來抽樣獲取現實中的音頻信號的強度并且將獲取到的數據轉換成一個數值。CD音頻通常的抽樣的頻率是44.1kHz(sample rate),每個抽樣用一個16bit的整數來表示(bit depth)。
一個抽樣代表的是對一個音頻通道的數字量化值。
幀(frame)是一系列抽樣的集合。例如,一個立體聲的聲音文件中,每一幀會有2個抽樣,一個是左聲道的抽樣,一個是右聲道的。
Package是一系列幀的集合。在Linear PCM中,每個package總是包含一幀。在壓縮的音頻格式中,一個package可能有更多的幀。Package對已一個給定的音頻數據格式來說,是最小的有意義的集合。
在Linear PCM中,一個抽樣的大小和他所表示的信號的強度成線性關系。一個16位的標準CD音頻可以表示從靜音到最高的聲音總共65,536種可能的值。相鄰的兩個數值之間的信號的強度的差別總是相等的。
Core Audio在他的數據結構中可以表示任何采樣率和位深的Linear PCM。
Core audio
Core audio是ios系統中用于處理和音頻相關的框架。下圖是Core audio的架構。
Audio Queue Service主要負責聲音的錄制播放。
System sounds使用來播放系統的聲音和用戶界面的聲音效果
AVAudioPlayer提供了一個簡單的OC接口的音頻播放器。
Audio File
Services主要負責來讀取和寫入音頻數據和文件。
Audio Session
Services主要是用來管理你的app在移動設備中的聲音的行為
Audio units包含一系列的底層的音頻處理插件,可以處理混音、均衡、實時的錄音和播放等
Audio File
Stream Services主要負責處理流媒體的音頻文件的播放
OpenAL主要是游戲開發中使用的比較多,主要是根據標準實現了位置性的音源功能
Codecs主要是對音頻文件進行編解碼,也就是對ios平臺支持的壓縮格式的編解碼
音頻的數據格式
系統使用AudioStreamBasicDescription和AudioStreamPacketDescription描述音頻的格式。他們的結構如下所示:
struct AudioStreamBasicDescription {
Float64 mSampleRate;
UInt32mFormatID;
UInt32mFormatFlags;
UInt32mBytesPerPacket;
UInt32mFramesPerPacket;
UInt32mBytesPerFrame;
UInt32mChannelsPerFrame;
UInt32mBitsPerChannel;
UInt32mReserved;
};
typedef structAudioStreamBasicDescriptionAudioStreamBasicDescription;
structAudioStreamPacketDescription {
SInt64mStartOffset;
UInt32mVariableFramesInPacket;
UInt32mDataByteSize;
};
typedef struct AudioStreamPacketDescriptionAudioStreamPacketDescription;
獲取文件的數據格式
你可以手動的填充音頻格式這個數據結構,也可以從系統中獲取。
- (void) openPlaybackFile: (CFURLRef)soundFile {
AudioFileOpenURL (
(CFURLRef) self.audioFileURL,
0x01,// readonly
kAudioFileCAFType,
&audioFileID
);
UInt32 sizeOfPlaybackFormatASBDStruct =sizeof ([self audioFormat]);
AudioFileGetProperty (
[self audioFileID],
kAudioFilePropertyDataFormat,
&sizeOfPlaybackFormatASBDStruct,
&audioFormat// thesound file's ASBD is returned here
);
}
標準音頻數據格式
對于不同的平臺,Core
Audio有一兩個標準的音頻格式,這種格式會:
1.在音頻格式轉化過程中,被指定為中間格式
2.在Core Audio中被特殊優化過
3.當你沒有設置音頻格式的時候,會作為默認的格式
CoreAudio的標準格式是:
[if !supportLists]1.[endif]ios輸入輸出Linear PCM格式,并且位深是16bit
[if !supportLists]2.[endif]iOS audio units和其他的音頻處理使用linear PCM,并且使用8.24-bit定點數采樣
下面是一個雙聲道,標準的iPhone audio unit格式,采樣頻率是44.1 kHz的音頻格式結構
structAudioStreamBasicDescription {
mSampleRate= 44100.0;
mFormatID= kAudioFormatLinearPCM;
mFormatFlags= kAudioFormatFlagsAudioUnitCanonical;
mBitsPerChannel= 8 * sizeof (AudioUnitSampleType);// 32 bits
mChannelsPerFrame = 2;
mBytesPerFrame= mChannelsPerFrame * sizeof(AudioUnitSampleType);// 8 bytes
mFramesPerPacket= 1;
mBytesPerPacket= mFramesPerPacket * mBytesPerFrame;// 8 bytes
mReserved= 0;
};
Magic Cookies
在Core Audio的實現中,magic
cookie是對于壓縮音頻數據的一個不透明元數據。這個元數據給解碼器足夠的信息讓他來對音頻文件進行解碼。你可以把magic
cookie當作一個黑盒子,依靠Core Audio的函數來復制讀取和使用它。
下面是一個例子:
- (void) copyMagicCookieToQueue:(AudioQueueRef) queue fromFile: (AudioFileID) file {
UInt32 propertySize = sizeof (UInt32);
OSStatus result = AudioFileGetPropertyInfo (
file,
kAudioFilePropertyMagicCookieData,
&propertySize,
NULL
);
if (!result && propertySize) {
char *cookie = (char *) malloc (propertySize);
AudioFileGetProperty (
file,
kAudioFilePropertyMagicCookieData,
&propertySize,
cookie
);
AudioQueueSetProperty (
queue,
kAudioQueueProperty_MagicCookie,
cookie,
propertySize
);
free (cookie);
}
}
音頻數據包
Package是一系列幀的集合。對于音頻數據來說,他是最小的有意義的單元。因此他是最好的表示一個音頻文件中某一個時間內的數據集合。Core Audio中的同步就是通過數package來實現的。你可以使用package來計算音頻數據的緩存大小。
對于不同的數據類型有三種包:
[if !supportLists]1.[endif]CBR(固定比特率),例如linear PCM和IMA/ADPCM,所有的package的大小都一樣
[if !supportLists]2.[endif]VBR(浮動比特率),例如AAC, Apple Lossless,和MP3,所有的package包含的frame的數量一樣,但是每個frame的大小可能不同
[if !supportLists]3.[endif]VFR(浮動幀率),package有不同的數量的幀。這種類型少見
如果要使用VBR或者VFR你需要使用stream packet description結構體,每一個結構體表示一個package。如果要播放或者錄制,你需要一個這個結構體的數字來表示其中的每一個package。
Audio File Services和Audio File
Stream會讓你使用package來進行文件操作。AudioFileReadPackets從文件中讀取一個package到內存中。同時,他會給你一個AudioStreamPacketDescription的數組,來表示package。
對于CBR and VBR,每秒鐘讀取的package的數目是不一定的。下面的方法可以幫助你計算出音頻文件緩存的大?。?/p>
- (void) calculateSizesFor: (Float64) seconds {
UInt32 maxPacketSize;
UInt32 propertySize =sizeof (maxPacketSize);
AudioFileGetProperty (
audioFileID,
kAudioFilePropertyPacketSizeUpperBound,
&propertySize,
&maxPacketSize
);
static const intmaxBufferSize = 0x10000;// limitmaximum size to 64K
static const intminBufferSize = 0x4000;// limitminimum size to 16K
if (audioFormat.mFramesPerPacket){
Float64numPacketsForTime =
audioFormat.mSampleRate / audioFormat.mFramesPerPacket * seconds;
[selfsetBufferByteSize: numPacketsForTime * maxPacketSize];
} else {
// if frames perpacket is zero, then the codec doesn't know the
// relationshipbetween packets and time. Return a default buffer size
[selfsetBufferByteSize:
maxBufferSize >maxPacketSize ? maxBufferSize : maxPacketSize];
}
// clamp buffer size to ourspecified range
if (bufferByteSize >maxBufferSize && bufferByteSize > maxPacketSize) {
[selfsetBufferByteSize: maxBufferSize];
} else {
if (bufferByteSize< minBufferSize) {
[selfsetBufferByteSize: minBufferSize];
}
}
[self setNumPacketsToRead:self.bufferByteSize / maxPacketSize];
}
數據格式轉換
你可以使用格式轉換器來進行數據的格式轉換。你可以進行PCM的采樣率的轉換或者將壓縮格式和PCM直接任意轉換。一共有三種轉化:
[if !supportLists]1.[endif]將一個音頻格式解碼為linear PCM
[if !supportLists]2.[endif]將linear PCM轉換為另外一個音頻格式
[if !supportLists]3.[endif]linear PCM之間的轉化
當你使用了AudioQueue Services,你會自動的獲取到相應的編碼器。
聲音文件
你可以使用Audio File Services來和app中的音頻文件交互。它對獲取音頻文件和創建音頻文件有很有用的抽象。
你可以使用Audio File Services來獲取系統參數。AudioFileGetGlobalInfoSize來讓你分配足夠的內存空間來保存數據,AudioFileGetGlobalInfo來獲取真正的數據。你可以在AudioFile.h文件中查看,你可以獲取到那些信息:
[if !supportLists]1.[endif]可讀的文件類型
[if !supportLists]2.[endif]可寫的文件類型
[if !supportLists]3.[endif]對于每一種可寫的類型,你可以寫入的音頻數據的格式
另外還有其他的兩種技術:
[if !supportLists]1.[endif]Audio
File Stream Services讓可以讀取硬盤或者流中的文件數據
[if !supportLists]2.[endif]Extended
Audio File Services他封裝了file和stream接口,讓你使用的更容易
創建一個新的聲音文件
為了創建一個新的聲音文件,你需要:
[if !supportLists]1.[endif]這個文件的系統路徑,以CFURL或者NSURL對象類型
[if !supportLists]2.[endif]你想要創建的文件的類型,例如CAF文件你需要設定為kAudioFileCAFType
[if !supportLists]3.[endif]你將要寫入到文件中的音頻數據的audio stream basic description。在很多情況下,你可以設置一部分,然后讓系統幫你決定另一部分。
你將這三個參數給AudioFileCreateWithURL,它會創建一個文件,并返回AudioFileID對象。你可以使用它來作為后面進一步交互的對象。
AudioFileCreateWithURL(
audioFileURL,
kAudioFileCAFType,
&audioFormat,
kAudioFileFlags_EraseFile,
&audioFileID// the function provides the new file objecthere
);
打開一個音頻文件
你可以使用AudioFileOpenURL來打開一個文件。你可以給他一個URL,一個文件類型的提示還有一個你想使用的文件權限,然后他就會返回一個ID。
你可以使用這個ID和AudioFileGetPropertyInfo和AudioFileGetProperty來獲取文件的各種信息。通常你需要知道的信息包括:kAudioFilePropertyFileFormat,kAudioFilePropertyDataFormat,kAudioFilePropertyMagicCookieData,kAudioFilePropertyChannelLayout。
對于一個VBR的長文件,你讀取所有的package可能需要很長時間,這兩個參數有幫助kAudioFilePropertyPacketSizeUpperBound和kAudioFilePropertyEstimatedDuration。他可以預估出package的大小和時長。
讀寫一個音頻文件
Ios中通常使用Audio File Services來讀和寫文件。除非必要都使用package來讀和寫。因為,對于VBR你只能使用package來讀寫,并且使用基于package的讀寫也更加簡單。
iPhone可以支持的音頻文件格式
Format nameFormat filename extensions
AIFF.aif,.aiff
CAF.caf
MPEG-1, layer 3.mp3
MPEG-2 or MPEG-4 ADTS.aac
MPEG-4.m4a,.mp4
WAV.wav
AC-3 (Dolby Digital).ac3
Enhanced AC-3 (Dolby Digital? Plus).ec3
CAF文件
Ios和osx有自己的音頻文件格式叫做Core Audio Format (或者CAF)。他可以包含平臺支持的所有的音頻數據格式。
音頻流
Audio File Stream Services主要用來對音頻流進行解析。你創建一個audio file stream的對象AudioFileStreamID。他作為你和音頻流相互的代理。因為audio file stream Services主要負責對音頻流進行解析,那么你的app就需要解析后的各種信息和數據進行交互和反饋。你通過兩個回調函數來對這些信息最反饋。
首先你需要有一個回調來對音頻流的屬性變化做反饋。至少你需要對屬性kAudioFileStreamProperty_ReadyToProducePackets的變化有反饋。通常使用這個屬性的場景如下:
[if !supportLists]1.[endif]用戶按下開始播放按鈕,或者請求這個音頻流來播放
[if !supportLists]2.[endif]Audio
File Stream Services開始解析音頻流
[if !supportLists]3.[endif]當足夠多的package被解析并發送到你的app中,Audio File
Stream Services會將屬相kAudioFileStreamProperty_ReadyToProducePackets的值設置為1
[if !supportLists]4.[endif]Audio
File Stream Services會回調你的回調函數,并且回調的屬性ID是kAudioFileStreamProperty_ReadyToProducePackets
[if !supportLists]5.[endif]你的回調開始負責做后續的操作,例如建立一個audio queue對象來負責播放這個音頻流
其次,你需要一個回調來處理音頻數據。每當Audio File Stream Services獲取到一系列完整的音頻package,他就會回調你的函數。你的回調需要處理收到的數據。通常,你需要立即將他們發送給Audio Queue Services來播放。
Audio Sessions:與Core Audio相互合作
audio
session是你的app和ios系統的中間人。每個app都只有一個audio session,你通過他來表達你的app的音頻的用處。你必須首先回答幾個關于你的app如何表現的問題:
[if !supportLists]1.[endif]你的app如何對打斷作反應,例如一個電話?
[if !supportLists]2.[endif]你想要你的app的聲音和其他聲音混合播放嗎,或者你想要讓別的app靜音?
[if !supportLists]3.[endif]你的app對音頻通道的變化如何反應,當用戶插入或者拔出他的二級
當你想好了答案,你可以使用audio session的接口來設置你的接口和應用。下面提供了三種特性,你可以通過變成來設置他們.
Audio session featureDescription
CategoriesA category is a key that? identifies a set of audio behaviors for your application. By setting a? category, you indicate your audio intentions to iOS, such as whether your? audio should continue when the screen locks.
Interruptions and route? changesYour audio session posts? notifications when your audio is interrupted, when an interruption ends, and? when the hardware audio route changes. These notifications let you respond to? changes in the larger audio environment—such as an interruption due to in an? incoming phone call—gracefully.
Hardware characteristicsYou can query the audio session? to discover characteristics of the device your application is running on,? such as hardware sample rate, number of hardware channels, and whether audio? input is available.
Audio Sessiond的默認行為
[if !supportLists]1.[endif]當用戶通過靜音按鈕來靜音,你的聲音將會被靜音
[if !supportLists]2.[endif]當設備進入鎖屏或者待機狀態,你的聲音將被靜音。
[if !supportLists]3.[endif]當你的聲音開始,其他的聲音將會被停止
這些行為是由它的默認類別kAudioSessionCategory_SoloAmbientSound所決定的。Ios提供了很多類別來滿足你的需求,你可以在應用啟動或者在你的app運行的時候來設置
Audio session的默認行為對于ios的音頻開發足夠了。除非你有自己的特殊需求,下面會討論。
打斷:激活和非激活
一個audio session的默認行為中缺少他在打斷結束后重新激活自己的能力。audio session主要有兩個狀態:激活和非激活。你只有在激活狀態下,才能對你的音頻進行操作。
在啟動時,你的默認的audio
session就被激活。但是,如果電話來了,你的audio session會成為非激活狀態,并且聲音被打斷。這叫做打斷,如果用戶選擇忽略這個電話,你的應用會繼續運行,但是你的audio session已經處于非激活狀態,他不能繼續播放了。
如果你的app中使用OpenAL,
I/O audio unit,或者Audio Queue Services,你必須寫一個打斷的回調函數,并且在打斷結束的時候,顯式的重新激活你的audio session。
如果你使用AVAudioPlayer類,他自己會幫你處理好。
判斷你的音頻輸入是否有效
在你錄音前,你必須首先知道你的ios音頻錄入設備是否有效,因為在ipod
touch(2代)中,他只有當其他的輸入設備接入的時候,才能進行語音的輸入。你可以使用kAudioSessionProperty_AudioInputAvailable屬性來判斷。下面是一個例子:
UInt32 audioInputIsAvailable;
UInt32 propertySize = sizeof (audioInputIsAvailable);
AudioSessionGetProperty (
kAudioSessionProperty_AudioInputAvailable,
&propertySize,
&audioInputIsAvailable // A nonzero value on output means that
// audio input isavailable
);
使用你的Audio Session
在同一時刻,你的app只能有一個audio
session的類別。你的所有的音頻特性都遵守這個類別的特性。(除了System Sound Services,她總是使用最低優先級的audio
session列別)。
你必須在真機上測試你的audio session的行為。
使用AVAudioPlayer類播放聲音
AVAudioPlayer提供了一個簡單的oc的類來播放音頻。如果你的app不需要立體聲或者準確的同步,并且不是從網絡上獲取音頻來播放。蘋果推薦你使用這個類來播放音樂。
使用它來播放音樂你可以:
[if !supportLists]1.[endif]播放任何時長的聲音
[if !supportLists]2.[endif]從文件或者內存中播放聲音
[if !supportLists]3.[endif]循環播放
[if !supportLists]4.[endif]同時播放多個聲音
[if !supportLists]5.[endif]控制你播放的每個聲音的音量
[if !supportLists]6.[endif]獲取文件的某一個特定的點,這個可以支持快進或者快退
[if !supportLists]7.[endif]獲取聲音的音量數據
AVAudioPlayer不需要你使用Audio Session Services,但是他的默認行為不符合你的要求,你可以使用默認的audio session。
為了使用AVAudioPlayer,你首先給他一個音頻文件,準備播放,并且設置一個代理,例子如下:
NSString*soundFilePath =
[[NSBundle mainBundle]pathForResource: @"sound"
ofType: @"wav"];
NSURL *fileURL =[[NSURL alloc] initFileURLWithPath: soundFilePath];
AVAudioPlayer*newPlayer =
[[AVAudioPlayer alloc]initWithContentsOfURL: fileURL
error: nil];
[fileURLrelease];
self.player =newPlayer;
[newPlayerrelease];
[self.playerprepareToPlay];
[self.playersetDelegate: self];
你使用一個代理來處理打斷和更新用戶界面當聲音播放結束。下面實現了一個簡單代理方法的實現,這個嗲嗎更新了開始和暫停按鈕的標題,當聲音完成播放。
- (void) audioPlayerDidFinishPlaying:(AVAudioPlayer *) player
successfully: (BOOL)flag {
if(flag == YES) {
[self.button setTitle: @"Play" forState:UIControlStateNormal];
}
}
為了播放、暫停或者停止一個AVAudioPlayer對象,調用他的播放控制方法。你可以使用playing屬性來獲取聲音是否在播放。下面是簡單的一個實現了點擊播放暫停按鈕來更新按鈕的標題:
- (IBAction) playOrPause: (id) sender {
// ifalready playing, then pause
if(self.player.playing) {
[self.button setTitle: @"Play" forState:UIControlStateHighlighted];
[self.button setTitle: @"Play" forState:UIControlStateNormal];
[self.player pause];
// ifstopped or paused, start playing
} else{
[self.button setTitle: @"Pause" forState: UIControlStateHighlighted];
[self.button setTitle: @"Pause" forState:UIControlStateNormal];
[self.player play];
}
}
AVAudioPlayer使用oc的方式聲明一個屬性并且管理聲音。你可以使用下面的方法來設置音頻的聲音:
[self.player setVolume: 1.0];// available range is 0.0 through 1.0
使用Audio Queue Services來錄制或者播放音頻
AudioQueue Services使用了一個很直接的并且足夠低層的方式來錄制或者播放聲音。他可以使你的app使用硬件來錄制或者播放聲音(例如麥克風或者音像)而不用知道硬件的細節。他可以讓你使用復雜的編碼而不用知道編碼是如何工作的。
盡管他是一個高層的接口,Audio
Queue Services支持一些高級特性。他提供細粒度的時間控制來支持定時播放和同步。你可以使用它來同步多個audio queue的播放來使這些聲音同步播放,來單獨控制多個聲音的聲音大小,并且來重復播放。Audio Queue Services和AVAudioPlayer是唯一的兩種方式來播放壓縮的音頻。
通常你使用Audio Queue Services時,需要和Audio File Services或者Audio File Stream Services相配合。
Audio Queue錄音和播放的回調函數
就和Audio File Stream Services一樣,你需要使用回調和屬性來和audio queue對象交互。錄音時,你實現一個回調來接手音頻數據緩存并且寫到硬盤中。你的audio queue會在每次新的緩存被寫滿的時候會調用你的回調。下面是一個簡單的示例:
對于播放,你的回調處于一個相反的過程。當你的audio queue需要有一個新的內存數據來播放的時候,會回調你。你的回調讀取一定數量的音頻package,并且將他們交給audio queue的緩存中。然后audioqueue開始播放,如下圖示例:
創建一個Audio Queue對象
為了使用Audio Queue Services,你需要首先創建一個Audio Queue Services。對于播放和錄音,創建的方式不同:
[if !supportLists]1.[endif]使用AudioQueueNewInput來創建錄音Audio Queue
[if !supportLists]2.[endif]使用AudioQueueNewOutput來創建播放Audio Queue
為了創建一個播放的Audio Queue,你需要實現以下三步:
[if !supportLists]1.[endif]創建一個結構體來管理Audio Queue需要的信息,例如你所播放的數據的音頻格式
[if !supportLists]2.[endif]定義一個回調來處理Audio Queue的緩存。回調使用Audio File Services來讀取文件播放
[if !supportLists]3.[endif]使用AudioQueueNewOutput來來初始化AudioQueue
示例如下:
static const int kNumberBuffers = 3;
// Create a data structure to manage informationneeded by the audio queue
struct myAQStruct {
AudioFileIDmAudioFile;
CAStreamBasicDescriptionmDataFormat;
AudioQueueRefmQueue;
AudioQueueBufferRefmBuffers[kNumberBuffers];
SInt64mCurrentPacket;
UInt32mNumPacketsToRead;
AudioStreamPacketDescription*mPacketDescs;
boolmDone;
};
// Define a playback audio queue callbackfunction
static void AQTestBufferCallback(
void*inUserData,
AudioQueueRefinAQ,
AudioQueueBufferRefinCompleteAQBuffer
) {
myAQStruct*myInfo = (myAQStruct *)inUserData;
if(myInfo->mDone) return;
UInt32numBytes;
UInt32nPackets = myInfo->mNumPacketsToRead;
AudioFileReadPackets (
myInfo->mAudioFile,
false,
&numBytes,
myInfo->mPacketDescs,
myInfo->mCurrentPacket,
&nPackets,
inCompleteAQBuffer->mAudioData
);
if(nPackets > 0) {
inCompleteAQBuffer->mAudioDataByteSize = numBytes;
AudioQueueEnqueueBuffer (
inAQ,
inCompleteAQBuffer,
(myInfo->mPacketDescs ? nPackets : 0),
myInfo->mPacketDescs
);
myInfo->mCurrentPacket += nPackets;
} else{
AudioQueueStop (
myInfo->mQueue,
false
);
myInfo->mDone = true;
}
}
// Instantiate an audio queue object
AudioQueueNewOutput (
&myInfo.mDataFormat,
AQTestBufferCallback,
&myInfo,
CFRunLoopGetCurrent(),
kCFRunLoopCommonModes,
0,
&myInfo.mQueue
);
控制Audio Queue的播放音量
有兩種方式,一種是使用AudioQueueSetParameter直接設置kAudioQueueParam_Volume的參數。音量會立即生效:
Float32 volume = 1;
AudioQueueSetParameter (
myAQstruct.audioQueueObject,
kAudioQueueParam_Volume,
volume
);
你也可以使用AudioQueueEnqueueBufferWithParameters來控制音量。這個繪制在你將這個緩存插入到Audio
Queue中的時候生鮮。在這兩種情況下,直到你更改音量之前,audio
queue都會保持你這次設置的音量。
獲取Audio Queue播放音量
你可以使用kAudioQueueProperty_CurrentLevelMeterDB來獲取當前播放的音量。這個返回是一個包含著AudioQueueLevelMeterState結構體的數組,每一個代表一個聲道。如下圖所示:
typedef struct AudioQueueLevelMeterState {
Float32mAveragePower;
Float32mPeakPower;
};AudioQueueLevelMeterState
同時播放多個音樂
為了同時播放多個因為,為每一個音樂創建一個audio queue。對于每一個audio queue,讓他們的音頻的第一個緩存同時播放,使用AudioQueueEnqueueBufferWithParameters。
音頻的格式對于同時播放是很重要的。有些壓縮的音頻格式十分的消耗硬件編碼。下面的格式同時只能播放一個實例:
[if !supportLists]·[endif]AAC
[if !supportLists]·[endif]ALAC (Apple Lossless)
[if !supportLists]·[endif]MP3
為了同時播放高音質的音樂,使用PCM or IMA4格式。
1.Linear PCM和IMA/ADPCM (IMA4)音頻。你可以同時播放多個PCM或者IMA4格式的音樂而不會產生CPU資源問題.
2.AAC, MP3,和Apple Lossless
(ALAC)音頻播放AAC, MP3,和Apple Lossless (ALAC)會很消耗資源,你同時只能播放一個。
使用OpenAL來播放
OpenAL是最適合用來在游戲中播放音樂。
系統聲音:提醒和聲音效果
如果你播放的聲音不需要控制音量,位置,audio session或者其他的控制,使用System Sound Services。這個接口最適合播放一個短的簡單的方式來播放聲音。在ios中,System Sound Services最多只能播放30秒鐘
可以使用AudioServicesPlaySystemSound來立即播放系統聲音。AudioServicesPlayAlertSound可以使用它來提醒用戶。每一個方法都會在用戶靜音的時候產生振動。
你可以使用AudioServicesPlaySystemSound并且傳入kSystemSoundID_Vibrate參數來直接來觸發振動。
使用AudioServicesPlaySystemSound來播放聲音,你首先通過創建一個sound ID來注冊這個聲音效果文件。然后你可以播放這個聲音。通常,會播放只播放一次或者重復的播放的情景,你需要持有這個sound ID直到你的app不再使用他。如果你只是使用一次,你可以在它播放完之后,立即釋放他。
下面是一個實例:
#include
#include
// Define a callback to be called when the soundis finished
// playing. Useful when you need to free memoryafter playing.
static void MyCompletionCallback (
SystemSoundIDmySSID,
void * myURLRef
) {
AudioServicesDisposeSystemSoundID (mySSID);
CFRelease (myURLRef);
CFRunLoopStop (CFRunLoopGetCurrent());
}
int main (int argc, const char * argv[]) {
// Setup the pieces needed to play a sound.
SystemSoundIDmySSID;
CFURLRefmyURLRef;
myURLRef = CFURLCreateWithFileSystemPath (
kCFAllocatorDefault,
CFSTR ("../../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
);
// Playthe 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 ();
return0;
}
Core Audio插件: Audio Units和Codecs
Core Audio有插件的機制來處理音頻數據。在ios中,系統提供這些插件。Osx中,有系統內置的,你也可以創建你自己的。
Audio Units
在ios中,audio
units給app提供一個低延時的輸入輸出方案。他同樣提供一些DSP的特性。
iOSaudio units的輸入輸出使用8.24-bit固定小數的linear PCM音頻格式。Ios的audio units是:
[if !supportLists]1.[endif]3D混音
[if !supportLists]2.[endif]多通道混音器
[if !supportLists]3.[endif]轉換器
[if !supportLists]4.[endif]I/O器
[if !supportLists]5.[endif]iPod均衡器
?xV??h?