iOS 主要提供以下了几种播放音频的方法:
System Sound Services
AVAudioPlayer 类
Audio Queue Services
OpenAL
1. System Sound Services
System Sound Services 是最底层也是最简单的声音播放服务,调用 AudioServicesPlaySystemSound 这个方法就可以播放一些简单的音频文件,使用此方法只适合播放一些很小的提示或者警告音,因为它有很多限制:
(1)声音长度要小于 30 秒
(2)In linear PCM 或者 IMA4 (IMA/ADPCM) 格式的
(3)打包成 .caf, .aif, 或者 .wav 的文件
(4)不能控制播放的进度
(5)调用方法后立即播放声音
(6)没有循环播放和立体声控制
另外,它还可以调用系统的震动功能,方法也很简单。具体的代码可以参考官方的示例 SysSound,但是官方的示例只有一些简单的用法,从文档中我们发现可以通过 AudioServicesAddSystemSoundCompletion 方法为音频播放添加 CallBack 函数,有了 CallBack 函数我们可以解决不少问题,比如可以克服 System Sound Services 本身不支持循环播放的问题。
2. AVAudioPlayer类
AVAudioPlayer 是 AVFoundation.framework 中定义的一个类,所以使用要先在工程中引入 AVFoundation.framework。我们可以把 AVAudioPlayer 看作是一个高级的播放器,它支持广泛的音频格式,主要是以下这些格式:
(1)AAC
(2)AMR(AdaptiveMulti-Rate, aformatforspeech)
(3)ALAC(AppleLossless)(4)iLBC(internetLowBitrateCodec, anotherformatforspeech)
(5)IMA4(IMA/ADPCM)
(6)linearPCM(uncompressed)
(7)µ-lawanda-law
(8)MP3(MPEG-1audiolayer3
3. Audio Queue Services
如果以上两种音频播放的解决方案都无法满足你的需求,那么我想你肯定需要使用 Audio Queue Services。使用 Audio Queue Services 对音频进行播放,你可以完全实现对声音的控制。例如,你可以在声音数据从文件读到内存缓冲区后对声音进行一定处理再进行播放,从而实现对音频的快速/慢速 播放的功能。
4. OpenAL
OpenAL 是一套跨平台的开源的音频处理接口,与图形处理的 OpenGL 类似,它为音频播放提供了一套更加优化的方案。它最适合开发游戏的音效,用法也与其他平台下相同。
下面主要介绍 System Sound Services和 AVAudioPlayer类
(1) ViewController.h
//
// ViewController.h
// MediaDemo
//
// Created by 555chy on 6/26/16.
// Copyright © 2016 555chy. All rights reserved.
//
#import <UIKit/UIKit.h>
//(1)System Sound Services 需要添加 AudioToolbox.framework
#import <AudioToolbox/AudioToolbox.h>
//(2)AVAudioPlayer 需要添加 AVFoundation.framework
#import <AVFoundation/AVFoundation.h>
@interface ViewController : UIViewController<AVAudioPlayerDelegate>
@end
(2) ViewController.m
//
// ViewController.m
// MediaDemo
//
// Created by 555chy on 6/26/16.
// Copyright © 2016 555chy. All rights reserved.
//
#import "ViewController.h"
@interface ViewController ()
//播放音频
@property AVAudioPlayer *avAudioPlayer;
//播放视频
@property AVPlayerItem *avPlayerItem;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)loadView {
UIView *view = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds];
view.backgroundColor = [UIColor whiteColor];
self.view = view;
UIButton *btn1 = [[UIButton alloc] initWithFrame:CGRectMake(100, 50, 200, 50)];
[btn1 setTitle: @"System Sound Services" forState:UIControlStateNormal];
[btn1 setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
[btn1 addTarget:self action:@selector(btn1DidClick) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn1];
UIButton *btn2 = [[UIButton alloc] initWithFrame:CGRectMake(100, 100, 200, 50)];
[btn2 setTitle: @"AVAudioPlayer" forState:UIControlStateNormal];
[btn2 setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
[btn2 addTarget:self action:@selector(btn2DidClick) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn2];
}
-(void)btn1DidClick {
[self playSystemSoundServices];
}
-(void)btn2DidClick {
[self playAVAudioPlayer];
}
-(void)btn3DidClick {
[self playAVPlayer];
}
/*
System Sound Services是最底层也是最简单的音频播放服务
调用AudioServicesPlaySystemSound这个方法只可以播放一些很小的提升或警告音
震动功能可以通过一个特殊的systemSoundID-kSystemSoundID_Vibrate来实现,不过只有iphone才能震动,ipod和ipad都无法整栋
限制如下:
(1)声音长度要小于30秒
(2)In linear PCM 或 IMA4(IMA/ADPCM)格式的
(3)打包成*.caf、*.aif、*.wav文件
(4)不能控制播放的进度
(5)调用方法后立即播放声音
(6)没有循环播放和立体声控制
*/
- (void)playSystemSoundServices {
NSString *path = [[NSBundle mainBundle] pathForResource:@"183" ofType:@"wav"];
NSURL *url = [NSURL fileURLWithPath:path];
SystemSoundID systemSoundID;
AudioServicesCreateSystemSoundID((__bridge CFURLRef)url, &systemSoundID);
NSLog(@"AudioServicesCreateSystemSoundID, id = %d", systemSoundID);
//This function will be deprecated in a future release. Use AudioServicesPlayAlertSoundWithCompletion
//AudioServicesAddSystemSoundCompletion(systemSoundID, NULL, NULL, finishPlaySystemSoundServicesCallback, NULL);
/*
(1)播放音频加震动
This function will be deprecated in a future release. Use AudioServicesPlayAlertSoundWithCompletion instead.
*/
//AudioServicesPlayAlertSound(systemSoundID);
/*
(2)播放音频
This function will be deprecated in a future release. Use AudioServicesPlaySystemSoundWithCompletion instead.
*/
//AudioServicesPlaySystemSound(systemSoundID);
//(3)播放震动
//AudioServicesDisposeSystemSoundID(kSystemSoundID_Vibrate);
AudioServicesPlayAlertSoundWithCompletion(systemSoundID, ^{
AudioServicesDisposeSystemSoundID(systemSoundID);
NSLog(@"AudioServicesDisposeSystemSoundID, id = %d", systemSoundID);
});
}
//void finishPlaySystemSoundServicesCallback(SystemSoundID systemSoundID, void* userData) {
// AudioServicesDisposeSystemSoundID(systemSoundID);
//}
/*
AVAudioPlayer可以看作是一个高级的播放器(注意:AVAudioPlayer定义为局部变量是不会有声音的)
支持格式如下:
(1)AAC
(2)AMR(AdaptiveMuti-Rate,aformatforspeech)
(3)ALAC(AppleLossless)
(4)iLBC(internetLowBitrateCodec,anotherformatforspeech)
(5)IMA4(IMA/ADPCM)
(6)linearPCM(uncompressed)
(7)u-lawanda-law
(9)MP3(MPEG-1audiolayer3)
*/
- (void)playAVAudioPlayer {
NSString *path = [[NSBundle mainBundle] pathForResource:@"183" ofType:@"wav"];
NSURL *url = [NSURL fileURLWithPath:path];
self.avAudioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
/*
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag;
- (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError * __nullable)error;
- (void)audioPlayerBeginInterruption:(AVAudioPlayer *)player NS_DEPRECATED_IOS(2_2, 8_0);
- (void)audioPlayerEndInterruption:(AVAudioPlayer *)player withOptions:(NSUInteger)flags NS_DEPRECATED_IOS(6_0, 8_0);
- (void)audioPlayerEndInterruption:(AVAudioPlayer *)player withFlags:(NSUInteger)flags NS_DEPRECATED_IOS(4_0, 6_0);
- (void)audioPlayerEndInterruption:(AVAudioPlayer *)player NS_DEPRECATED_IOS(2_2, 6_0);
*/
self.avAudioPlayer.delegate = self;
//The volume for the sound. The nominal range is from 0.0 to 1.0
self.avAudioPlayer.volume = 1.0;
//循环次数,-1为无限循环
self.avAudioPlayer.numberOfLoops = 1;
//设置当前播放时间
self.avAudioPlayer.currentTime = 0;
BOOL result;
result = [self.avAudioPlayer prepareToPlay];
NSLog(@"AVAudioPlayer prepareToPlay = %@", result?@"succ":@"fail");
result = [self.avAudioPlayer play];
NSLog(@"AVAudioPlayer play = %@", result?@"succ":@"fail");
//[avAudioPlayer pause];
//[avAudioPlayer stop];
}
- (void)audioProgressChange {
NSLog(@"audioProgressChange");
}
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
NSLog(@"audioPlayerDidFinishPlaying = %@", flag?@"succ":@"fail");
}
- (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError * __nullable)error {
NSLog(@"audioPlayerDecodeErrorDidOccur error = %@", error);
}
-(void)avPlayerDidEnd {
NSLog(@"avPlayerDidEnd");
}
@end