播放和錄制音頻
學(xué)習使用AVAudioPlayer和AVAudioRecorder類的實現(xiàn)音頻播放和錄制功能.
1. iOS的音頻環(huán)境
當你在iPhone上聽音樂時,音頻從內(nèi)置??中播放出來,此時有電話撥入,音樂會立即暫停,轉(zhuǎn)而聽到手機鈴聲. 當你掛掉電話, 音樂又將恢復(fù). 這都是程序通過 audio session 來管理和音頻硬件的交互來實現(xiàn)的. 所有的應(yīng)用程序都有音頻會話, 無論你是否使用.默認音頻會話有很多合適的預(yù)配置,例如,手機設(shè)置靜音則所有應(yīng)用的音頻都會出于靜音狀態(tài).
在大部分應(yīng)用程序中,使用默認的即可,如果你有特殊要求, 使用AVAudioSession對應(yīng)的分類來配置.
- 音頻會話分類
分類 | 作用 | 是否允許跟其他應(yīng)用混音 | 支持音頻輸入 | 支持音頻輸出 |
---|---|---|---|---|
AVAudioSessionCategoryAmbient | 一般app應(yīng)用 | ?? | ?? | |
...SoloAmbient (默認) | 一般app應(yīng)用 | ?? | ||
...Playback | 音頻播放器 | 可選 | ?? | |
...Record | 錄音機,音頻捕捉 | ?? | ||
...PlayAndRecord | VoIp,語音聊天 | 可選 | ?? | ?? |
...AudioProcessing | 離線會話和處理(僅需要用到編解碼處理功能的) | |||
...MultiRoute | 使用外設(shè)硬件的應(yīng)用 | ?? | ?? |
其中一些分類可以使用option和modes進行進一步配置.
- 音頻會話的配置: audio session 在應(yīng)用程序的整個生命周期是可以修改的,通常只需要在應(yīng)用啟動時配置一次.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
AVAudioSession *session = [AVAudioSession sharedInstance];
NSError *error;
if (![session setCategory:AVAudioSessionCategoryPlayback error:&error]) { // 選擇音頻會話類型
NSLog(@"Category Error: %@", [error localizedDescription]);
}
if (![session setActive:YES error:&error]) { // 開啟音頻會話
NSLog(@"Activation Error: %@", [error localizedDescription]);
}
return YES;
}
2. 使用AVAudioPlayer 播放音頻
AVAudioPlayer類提供了從基本的文本或內(nèi)存播放音頻的接口.以及對播發(fā)器音量的控制,Pan值(左右聲道,立體聲), 播放速率, 音頻循環(huán), 音頻計量(用于提供可視化).audio session選用合適的分類配置完成后,我們就可以使用AVAudioPlayer了.
//導(dǎo)入AVFoundation框架.
//1. 為聲音文件創(chuàng)建AVAudioPlayer實例
NSURL *fileURL = [[NSBundle mainBundle] URLForResource:name
withExtension:@"caf"];
NSError *error;
AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL
error:&error];
// 2. 配置
if (!player) {
NSLog(@"Error creating player: %@", [error localizedDescription]);
return ;
}
player.numberOfLoops = -1; // 循環(huán)次數(shù).
player.enableRate = YES; // 允許設(shè)置播放速率
[player prepareToPlay];
// 3. 控制部分.
// 開始 [player play];
// 暫停 [player pause];
// 停止 [player stop];
// 調(diào)整速率 player.rate = xx;
// 調(diào)整音量 player.volume = xx;
// 調(diào)整聲道 player.pan = xx;
如果要應(yīng)用后臺播放不僅要設(shè)置合適的音頻會話分類, 還需要在info.plist中配置Required background modes.
2.1 音頻事件處理.
- 系統(tǒng)中斷事件:例如,電話,鬧鐘等. 這類事件發(fā)生時,系統(tǒng)會自動中斷應(yīng)用的音頻并在結(jié)束后繼續(xù). 如果有額外需求(例如更新UI)可監(jiān)聽
AVAudioSessionInterruptionNotification
通知,它的info信息中AVAudioSessionInterruptionType
確定音頻中斷類型并做相應(yīng)處理. - 線路改變事件:例如插拔耳機,斷開USB麥克風等音頻輸入或輸出線路變化.通過監(jiān)聽
AVAudioSessionRouteChangeNotification
額外處理(例如插拔耳機系統(tǒng)會自動變化輸出線路,但用戶拔出耳機時并不是想直接外音播放.),通過info信息中AVAudioSessionRouteChangeReason
確定線路變化類型并做相應(yīng)處理.
3. 使用AVAudioRecorder錄制音頻.
通過AVAudioRecorder來從麥克風等音頻設(shè)備進行錄制.同樣的,程序啟動時先配置Audio Session分類; 之后創(chuàng)建AVAudioRecorder時需要提供一些額外信息:
- 要寫入的本地文件URL
- 用于配置錄音的NSDictionary對象.
- 捕捉錯誤的NSError指針.
//導(dǎo)入AVFoundation框架.
//1. 創(chuàng)建 AVAudioRecorder
NSString *tmpDir = NSTemporaryDirectory();
NSString *filePath = [tmpDir stringByAppendingPathComponent:@"memo.caf"];
NSURL *fileURL = [NSURL fileURLWithPath:filePath];
NSDictionary *settings = @{ // 這些配置根據(jù)錄制格式考慮質(zhì)量和文件大小的平衡來決定
AVFormatIDKey : @(kAudioFormatAppleIMA4), // 錄制格式
AVSampleRateKey : @44100.0f, // 采樣率
AVNumberOfChannelsKey : @1, // 通道數(shù)
AVEncoderBitDepthHintKey : @16, 位深
AVEncoderAudioQualityKey : @(AVAudioQualityMedium)
};
NSError *error;
self.recorder = [[AVAudioRecorder alloc] initWithURL:fileURL settings:settings error:&error];
if (!self.recorder) {
NSLog(@"Error: %@", [error localizedDescription]);
return;
}
self.recorder.delegate = self; // 監(jiān)聽錄制狀態(tài)
self.recorder.meteringEnabled = YES;
[self.recorder prepareToRecord];
//2 .錄制
[ self.recorder record];
meteringEnabled 開啟音頻計量,允許讀取音頻計量數(shù)值,在錄制時就可以讓用戶聲音大小可視化.
// 讀取平均分貝
float avgPower = [self.recorder averagePowerForChannel:0];
// 讀取峰值分貝
float peakPower = [self.recorder peakPowerForChannel:0];
// 數(shù)據(jù)進行合適處理后使用Quartz或OpenGL ES繪制.