AVAudioPlayer 在 Mac 和 iOS 系统经常被作为实现音频播放的最佳选择。
1.AVAudioPlayer的创建
有两种方法可创建一个 AVAudioPlayer,使用包含要播放音频的内存版本的 NSData,或者本地音频文件的 NSURL。如果基于 iOS 系统,URL 必须在应用程序沙盒之内或者该 URL 一定是用户 iPod 库中的一个元素。
@property(nonatomic, strong) AVAudioPlayer *player;
NSURL *fileURl = [[NSBundle mainBundle] URLForResource:@"lcn" withExtension:@"mp3"];
self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURl error:nil];
// 取得需要的音频硬件并预加载 Audio Queue 的缓冲区, 降低调用 play 方法和听到声音输出之间的延时
[self.player prepareToPlay];
2.对播放进行控制
// 开始播放
[self.player play];
// 暂停播放
[self.player pause];
// 停止播放,对用户来说效果是相同的,不同在于调用 stop 方法时,会撤销调用 prepareToPlay 时所做的设置
[self.player stop];
其他方法
1>修改播放器的音量:播放器的音量独立于系统的音量,我们可以通过对播放器音量的处理实现很多效果,比如声音的渐隐效果。音量或播放增益定义为0.0(静音)到1.0(最大音量)之间的浮点值。
2>修改播放器的 pan 值:允许使用立体声播放声音:播放器的 pan 值由一个浮点数表示,范围从-1.0(极左)到1.0(极右)。默认值为0.0(居中)
3>调整播放率:iOS5之后允许用户在不改变音调的情况下调整播放率,范围从0.5(半速)到2.0(2倍速)。
4>通过设置 numberOfLoops 属性实现音频无缝循环:给这个属性设置一个大于0的数,可以实现播放器 n 次循环播放。设置 -1 会无限循环。
3.配置音频会话
在 AppDelegate.m 中
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// 获取会话
AVAudioSession *session = [AVAudioSession sharedInstance];
NSError *error;
// 指定 AVAudioSessionCategoryPlayback 分类
if (![session setCategory:AVAudioSessionCategoryPlayback error:&error]) {
// 处理错误...
NSLog(@"%@", error.localizedDescription);
}
if (![session setActive:YES error:&error]) {
// 处理错误...
NSLog(@"%@", error.localizedDescription);
}
return YES;
}
另,在 info.plist 中配置 Required background modes 数组,添加 App plays audio or streams audio/video using AirPlay 选项
此时,当切换手机侧面的”铃声/静音“开关,或点击设备的 Lock 按钮后,player 会继续播放音频,不会再中断。
4.中断事件
当中断事件发生时,播放中的音频会慢慢消失和暂停,但是当中断事件结束后,音频播放不会恢复。
- (void)viewDidLoad {
[super viewDidLoad];
// 注册通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleInterruption:) name:AVAudioSessionInterruptionNotification object:[AVAudioSession sharedInstance]];
}
- (void)dealloc {
// 移除通知
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)handleInterruption:(NSNotification *)notification {
NSDictionary *info = notification.userInfo;
AVAudioSessionInterruptionType type = [info[AVAudioSessionInterruptionTypeKey] unsignedIntegerValue];
if (type == AVAudioSessionInterruptionTypeBegan) {
// AVAudioSessionInterruptionTypeBegan
// 发生中断事件,暂停播放..
} else {
// AVAudioSessionInterruptionTypeEnded
// 中断事件结束,恢复播放
}
}
5.对线路改变的响应
在 iOS 设备上添加或移除音频输入、输出线路时,会发生线路改变。音频播放之后,用户插入耳机,音频输出线路变为耳机插孔并继续播放;用户断开耳机连接,音频线路回到设备的内置扬声器,音频继续播放,按照苹果公司的相关文档,此时应处于静音状态。
- (void)viewDidLoad {
[super viewDidLoad];
// 注册通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleRouteChange:) name:AVAudioSessionInterruptionNotification object:[AVAudioSession sharedInstance]];
}
- (void)dealloc {
// 移除通知
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)handleRouteChange:(NSNotification *)notification {
NSDictionary *info = notification.userInfo;
AVAudioSessionRouteChangeReason reason = [info[AVAudioSessionRouteChangeReasonKey] unsignedIntegerValue];
if (reason == AVAudioSessionRouteChangeReasonOldDeviceUnavailable) {
AVAudioSessionRouteDescription *previousRoute = info[AVAudioSessionRouteChangePreviousRouteKey];
AVAudioSessionPortDescription *previousOutput = previousRoute.outputs[0];
NSString *portType = previousOutput.portType;
if ([portType isEqualToString:AVAudioSessionPortHeadphones]) {
// 停止播放
}
}
}