一个简单的混音播放器,处理中断
简单的来说其实就是创建多个播放器,分别设置播放器的声道,音量,速率,已达到混音的效果,难度不大,简单的封装一下。
文件目录如下
AppDelegate
- (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(@"Category Error : %@", [error localizedDescription]); } // Override point for customization after application launch. return YES; }
封装的类
// // SiPlayerController.h // Player // // Created by Silence on 16/1/26. // Copyright © 2016年 Silence. All rights reserved. // #import <Foundation/Foundation.h> @protocol SiPlayerControllerDelegate <NSObject> - (void)playbackStop; - (void)playbackBegan; @end @interface SiPlayerController : NSObject @property (nonatomic, readonly, getter=isPlaying) BOOL playing; @property (nonatomic, weak) id <SiPlayerControllerDelegate> delegate; //方法 - (void)play; - (void)stop; //播放速率 - (void)adjustRate:(float)rate; //对player环绕声设置,取值范围(-1.0极左 ~ 1.0极有右,0.0中间) - (void)adjustPan:(float)pan forPlayerAtIndex:(NSUInteger)index; //音量大小设置 - (void)adjustVolume:(float)volume forPlayerAtIndex:(NSUInteger)index; @end
// // SiPlayerController.m // Player // // Created by Silence on 16/1/26. // Copyright © 2016年 Silence. All rights reserved. // #import "SiPlayerController.h" #import <AVFoundation/AVFoundation.h> @interface SiPlayerController() @property (nonatomic) BOOL playing; @property (nonatomic, strong) NSArray * playersArray; @end @implementation SiPlayerController - (instancetype)init { self = [super init]; if (self) { AVAudioPlayer * play1 = [self playForFile:@"1"]; AVAudioPlayer * play2 = [self playForFile:@"2"]; _playersArray = @[play1, play2]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleInterruption:) name:AVAudioSessionInterruptionNotification object:[AVAudioSession sharedInstance]]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleRouteChanged:) name:AVAudioSessionRouteChangeNotification object:[AVAudioSession sharedInstance]]; } return self; } - (void)dealloc{ [[NSNotificationCenter defaultCenter] removeObserver:self]; } - (void)handleRouteChanged:(NSNotification *)notification{ NSDictionary * dict = notification.userInfo; AVAudioSessionRouteChangeReason reason = [dict[AVAudioSessionRouteChangeReasonKey] unsignedIntegerValue]; if (reason == AVAudioSessionRouteChangeReasonOldDeviceUnavailable) { AVAudioSessionRouteDescription * previousRoute = dict[AVAudioSessionRouteChangePreviousRouteKey]; AVAudioSessionPortDescription * previousOutput = previousRoute.outputs[0]; NSString * portType = previousOutput.portType; if ([portType isEqualToString:AVAudioSessionPortHeadphones]) { [self stop]; [self.delegate playbackStop]; } } } - (void)handleInterruption:(NSNotification *)notification{ NSDictionary * dict = notification.userInfo; AVAudioSessionInterruptionType type = [dict[AVAudioSessionInterruptionTypeKey] unsignedIntegerValue]; if (type == AVAudioSessionInterruptionTypeBegan) { //处理中断开始 [self stop]; if (self.delegate) { [self.delegate playbackStop]; } }else{ //处理中断结束 AVAudioSessionInterruptionOptions options = [dict[AVAudioSessionInterruptionTypeKey] unsignedIntegerValue]; if (options == AVAudioSessionInterruptionOptionShouldResume) { [self play]; if (self.delegate) { [self.delegate playbackBegan]; } } } } - (AVAudioPlayer *)playForFile:(NSString *)name{ NSURL * url = [[NSBundle mainBundle] URLForResource:name withExtension:@"mp3"]; NSError * error; AVAudioPlayer * player = [[AVAudioPlayer alloc]initWithContentsOfURL:url error:&error]; if (player) { //循环计数为-1 player.numberOfLoops = -1; //可以对播放熟虑进行设置 player.enableRate = YES; [player prepareToPlay]; }else{ NSLog(@"Create Player Error: %@", [error localizedDescription]); } return player; } - (void)play{ if (!self.playing) { NSTimeInterval delayTime = [self.playersArray[0] deviceCurrentTime] + 0.01; for (AVAudioPlayer * player in self.playersArray) { [player playAtTime:delayTime]; } self.playing = YES; } } - (void)stop{ if (self.playing) { for (AVAudioPlayer * player in self.playersArray) { [player stop]; player.currentTime = 0.0f; } self.playing = NO; } } - (void)adjustRate:(float)rate{ for (AVAudioPlayer * player in self.playersArray) { player.rate = rate; } } - (BOOL)isValidIndex:(NSUInteger)index{ return index == 0 || index < self.playersArray.count; } - (void)adjustPan:(float)pan forPlayerAtIndex:(NSUInteger)index{ if ([self isValidIndex:index]) { AVAudioPlayer * player = self.playersArray[index]; player.pan = pan; } } - (void)adjustVolume:(float)volume forPlayerAtIndex:(NSUInteger)index{ if ([self isValidIndex:index]) { AVAudioPlayer * player = self.playersArray[index]; player.volume = volume; } } @end
ViewController
// // ViewController.m // Player // // Created by Silence on 16/1/26. // Copyright © 2016年 Silence. All rights reserved. // #import "ViewController.h" #import "SiPlayerController.h" @interface ViewController () @property (nonatomic, strong)SiPlayerController * player; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; _player = [[SiPlayerController alloc]init]; // Do any additional setup after loading the view, typically from a nib. } - (IBAction)playerOnePan:(UISlider *)sender { [_player adjustPan:sender.value forPlayerAtIndex:0]; } - (IBAction)playerTwoPan:(UISlider *)sender { [_player adjustPan:sender.value forPlayerAtIndex:1]; } - (IBAction)playerOneVolume:(UISlider *)sender { [_player adjustVolume:sender.value forPlayerAtIndex:0]; } - (IBAction)playerTwoVolume:(UISlider *)sender { [_player adjustVolume:sender.value forPlayerAtIndex:1]; } - (IBAction)playButtonDidClick:(id)sender { [_player play]; } - (IBAction)stopButtonDidClick:(id)sender { [_player stop]; } - (IBAction)changeRate:(UISlider *)sender { [_player adjustRate:sender.value]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end
StoryBoard
在Info.Plist中添加
这样一个简单的播放器就实现了,同时能处理一些中断的事件