#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
@interface MainViewController : UIViewController<AVAudioPlayerDelegate>
@end
// AVAudioPlayer是AVFoundation.framework里面最基本的一个音频播放器的类。它与MPMediaPlayerController在一些基本操作功能上是类同的,比如play,pause,volume等等。不一样的地方在于AVAudioPlayer没有队列这个东西,也就是说它只能播放一个指定路径的音频。要播放多个音频,可以通过创建多个AVAudioPlayer来实现。在AVFoundation里面,有另外一个功能强大的类AVQueuePlayer,基本上要做音乐播放器要靠它,什么QQ音乐,酷狗应该都是使用AVQueuePlayer。
// 要记住,使用AVFoundation的东西播放音频,肯定要先对Audio Session进行设置,除非你使用默认的设置
// AVAudioPlayer能实现的功能类似于System Audio Services,播放单一音频,但它不同的地方在于它可以控制播放的次数,播放的时间。比如用它可以很方便的实现重复播放。另外,它还有一个很强大的功能,就是可以很方便的调节左右声道的音量,从而实现很酷的立体声效果。从这个角度看,AVAudioPlayer很适用于游戏中的音频播放。
// AVAudioPlayer有一个重要的property就是pan,用它可以来调节音频播放时左右声道的大小,如果值是-1.0为完全左声道发生,如果是1.0则为完全右声道发音。另外,还有一个很强大的功能,就是可以测量音频播放时实时声道的功率大小,这个功能可以用于辅助显示声音的波浪,很多电脑上的播放器都有的。当然,如果用它来进行声波的分析,我想也是可以的
/* // audioPlayerOne 为一个AVAudioPlayer的对象
self.audioPlayerOne.meteringEnabled = YES; // 允许测量
[self.audioPlayerOne updateMeters]; // 更新数据
[self.averagePowerChannelOne setValue:[self.audioPlayerOne averagePowerForChannel:0] animated:YES]; // 将获取的数据赋予相关的控件
[self.averagePowerChannelTwo setValue:[self.audioPlayerOne averagePowerForChannel:1] animated:YES];
*/
#import "MainViewController.h"
#import <AVFoundation/AVFoundation.h>
@interface MainViewController ()
@property(nonatomic,retain)AVAudioPlayer * audioPlayer;// 音频播放器
@property(nonatomic,retain)UISlider * volumeSlider;// 声音控制slider
@property(nonatomic,retain)UISlider * progrssSlider;// 音频进度sliser
@property(nonatomic,retain)NSTimer * timer; // 用NSTimer监控音频播放进度
@property(nonatomic,retain)UIProgressView * audioProgressView;// 播放进度条
@property(nonatomic,retain)UILabel * progressLabel; // 进度显示框
@property(nonatomic,retain)UISegmentedControl * segmentControl; // 播放选择segmentControl
@property(nonatomic,retain)UISwitch * swich; // 静音开关
@end
@implementation MainViewController
- (void)dealloc
{
self.audioPlayer = nil;
self.volumeSlider = nil;
self.progrssSlider = nil;
self.audioProgressView = nil;
self.progressLabel = nil;
self.segmentControl = nil;
self.swich = nil;
[super dealloc];
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.title = @"AVAudioPlayer";
// 初始化一个audioplayer
[self creatAnAudioPlayer];
// 视图布局
[self setUpView];
// 初始化NSTimer 监控音频播放进度
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(playProgress) userInfo:nil repeats:YES];
}
// 创建视图
- (void)setUpView
{
// UISegmentedControl自己的初始化方法
self.segmentControl =[[[UISegmentedControl alloc] initWithItems:@[@"play",@"pause",@"stop"]] autorelease];
// UISegmentedControl在UIControlEventValueChanged触发响应事件
[_segmentControl addTarget:self action:@selector(didClickSegmentControlAction:) forControlEvents:(UIControlEventValueChanged)];
_segmentControl.frame = CGRectMake(10, 80, 300, 40);
[self.view addSubview:_segmentControl];
// 创建UIProgressView 自己的初始化方法
self.audioProgressView = [[[UIProgressView alloc] initWithProgressViewStyle:(UIProgressViewStyleBar)] autorelease];
// 进度条显示的数据由NSTimer监督显示(实时变化)
_audioProgressView.frame = CGRectMake(10, 180, 300, 40);
_audioProgressView.backgroundColor = [UIColor yellowColor];
[self.view addSubview:_audioProgressView];
// 播放进度显示框
self.progressLabel = [[[UILabel alloc] initWithFrame:CGRectMake(10, 130, 300, 40)] autorelease];
// 显示的数据由NSTimer监督显示(实时变化)
_progressLabel.backgroundColor = [UIColor cyanColor];
_progressLabel.textAlignment = NSTextAlignmentCenter;
[self.view addSubview:_progressLabel];
// 声音调控UISlider
self.volumeSlider = [[[[UISlider alloc] initWithFrame:CGRectMake(10, 200, 300, 30)] autorelease] autorelease];
_volumeSlider.minimumValue = 0;
_volumeSlider.maximumValue = 1.0;
_volumeSlider.value = 0.5;
[_volumeSlider addTarget:self action:@selector(handleVolumeSlider:) forControlEvents:(UIControlEventValueChanged)];
[self.view addSubview:_volumeSlider];
// 音频播放进度调控UISlider
self.progrssSlider = [[[UISlider alloc] initWithFrame:CGRectMake(10, 230, 300, 30)] autorelease];
_progrssSlider.minimumValue = 0;
_progrssSlider.maximumValue = 1.0;
[_progrssSlider addTarget:self action:@selector(handleProgreeSlider:) forControlEvents:(UIControlEventValueChanged)];
[self.view addSubview:_progrssSlider];
// 声音开关控件
self.swich = [[[UISwitch alloc] initWithFrame:CGRectMake(10, 280, 60, 30)] autorelease];
[_swich addTarget:self action:@selector(onOrOff:) forControlEvents:UIControlEventValueChanged];
// 默认状态为开
_swich.on = YES;
[self.view addSubview:_swich];
}
- (void)playProgress
{
// 实时数据显示
_audioProgressView.progress = [self audioPlayerProgress];
_progressLabel.text = [NSString stringWithFormat:@"进度 :%.2f",[self audioPlayerProgress]];
}
// 声音开关(是否静音)
- (void)onOrOff:(UISwitch *)sender{
_audioPlayer.volume = sender.on;
}
// 设置播放进度
- (void)handleProgreeSlider:(UISlider *)slider
{
// pause the Player
[_audioPlayer pause];
// 计算新的时间
_audioPlayer.currentTime= slider.value * _audioPlayer.duration;
_segmentControl.selectedSegmentIndex = 1;
}
// 设置音量
- (void)handleVolumeSlider:(UISlider *)slider
{
if (_swich.on == YES) {
_audioPlayer.volume = slider.value;
}else{
_audioPlayer.volume = 0;
}
}
// 音频播放进度
- (CGFloat)audioPlayerProgress
{
CGFloat progress = _audioPlayer.currentTime/_audioPlayer.duration;
return progress;
}
// 点击segmentControl的响应时间
- (void)didClickSegmentControlAction:(UISegmentedControl *)segmentControl
{
if (0 == segmentControl.selectedSegmentIndex) {
[_audioPlayer play];
}else if (1 == segmentControl.selectedSegmentIndex){
[_audioPlayer pause];
}else{
[_audioPlayer stop];
_audioPlayer.currentTime = 0;
_progrssSlider.value = 0;
}
}
// 初始化一个audioPlayer
- (void)creatAnAudioPlayer
{ // 异步加载音频
dispatch_queue_t dispatchQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
dispatch_async(dispatchQueue, ^{
// 在本地读取
NSString * path = [[NSBundle mainBundle] pathForResource:@"谈何容易" ofType:@"mp3"];
NSError * error;
NSData * data = [NSData dataWithContentsOfFile:path];
self.audioPlayer = [[AVAudioPlayer alloc] initWithData:data error:&error];
/*
// initWithData:error:他使用一个指向内存中一些音频数据的NSData对象. 这种形式对于已经把音频数据下载到缓冲区的情形很有用.
// initWithContentsOfURL:error NSURL 它只能从file://格式的URL装入音频数据不支持流式音频及HTTP流和网络流
NSURL * url = [[NSURL alloc] initFileURLWithPath:path];
self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
*/
if (error) {
NSLog(@"error = %@",[error localizedDescription]);
}
[_audioPlayer prepareToPlay];
// delegate
_audioPlayer.delegate = self;
// -1为循环播放
_audioPlayer.numberOfLoops = -1;
[_audioPlayer setRate:2.0]; // 设置播放速度
[_audioPlayer setPan:0.5]; // 设置左右声道
});
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - AVAudioPlayerDelegate
// 音频播放完成时
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag{
// 音频播放完成时,调用该方法。
// 参数flag:如果音频播放无法解码时,该参数为NO。
// 当音频被终端时,该方法不被调用。而会调用audioPlayerBeginInterruption方法
// 和audioPlayerEndInterruption方法
[_timer invalidate]; // NSTimer暂停
}
// 解码错误
- (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError *)error
{
NSLog(@"解码错误!");
}
// 当音频播放过程中被中断时
- (void)audioPlayerBeginInterruption:(AVAudioPlayer *)player
{
// 当音频播放过程中被中断时,执行该方法。比如:播放音频时,电话来了!
// 这时候,音频播放将会被暂停。
}
// 当中断结束时
- (void)audioPlayerEndInterruption:(AVAudioPlayer *)player withOptions:(NSUInteger)flags{
NSLog(@"中断结束,恢复播放");
if (flags == AVAudioSessionInterruptionOptionShouldResume && player != nil){
[player play];
}
}