AVF 2 - 音频播放

AVF 2 - 音频播放

文章目录

  • AVF 2 - 音频播放
      • 简要说明
      • 音频播放代码实现
      • 多个播放器
      • iOS 中的中断监听
      • AVAudioSession 设置


简要说明

iOS 系统提供了一个可管理的音频环境(managed audio environment),通过音频会话(audio session)来实现。

AVAudioSession 在 Mac 上不可用


AVAudioPlayer 构建于 Core Audio 中的 C-based Audio Queue Services 的最顶层。 Audio Queue Services 中的 播放、循环 甚至音频计量功能,都可以通过 AVAudioPlayer 来以 OC 实现。


音频播放代码实现

#import "AudioPlay.h"
#import 

@interface AudioPlay () <AVAudioPlayerDelegate>

@property (nonatomic, getter = isPlaying) BOOL playing;
@property (nonatomic, strong) AVAudioPlayer *player;

@end

@implementation AudioPlay

- (void)setupPlayer{
    
    NSString *fileName = @"Drums.m4a";
    NSURL *fileURL = [[NSBundle mainBundle] URLForResource:fileName
                                             withExtension:nil];
    if (!fileURL) {
        NSLog(@"fileURL 为空");
        return ;
    }
    NSLog(@"fileURL : %@", fileURL);
    
    NSError *error;
    AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL
                                                                   error:&error];
    self.player = player;
    
    if (error) {
        NSLog(@"error : %@",error);
    }
    
    player.delegate = self;
    if (player) {
        player.numberOfLoops = 1; // -1 : 无限循环; 1-播放两遍,2-播放三遍
        player.enableRate = YES; //
        [player prepareToPlay];

        NSLog(@"duration : %f", self.player.duration);
        
    } else {
        NSLog(@"Error creating player: %@", [error localizedDescription]);
    }
    
    [self.player play];
//    [self play];
}

#pragma mark - Global playback control methods

- (void)play {
    
    if (!self.playing) {
        NSTimeInterval delayTime = [self.player  deviceCurrentTime] + 0.01;
        
        if (delayTime > self.player.duration) {
            delayTime = 0;
        }
        
        [self.player playAtTime:delayTime];
        
        self.playing = YES;
    }
}

- (void)stop {
    if (self.playing) {
        [self.player stop];
        self.player.currentTime = 0.0f;
    }
    self.playing = NO;
    
}

- (void)adjustRate:(float)rate {
    
    self.player.rate = rate;
    
}


#pragma mark - Player-specific methods

- (void)adjustPan:(float)pan {
    self.player.pan = pan;
    
}

- (void)adjustVolume:(float)volume {
    self.player.volume = volume;
}


#pragma mark - AVAudioPlayerDelegate
// numberOfLoops 的次数都播放完成后调用,如果 numberOfLoops = -1,可能永远不会调用
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag{
    
    NSLog(@"-- audioPlayerDidFinishPlaying successfully : %d",flag);
}

/* if an error occurs while decoding it will be reported to the delegate. */
- (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError * __nullable)error{
    
    NSLog(@"-- audioPlayerDecodeErrorDidOccur error : %@",error);
}

#if TARGET_OS_IPHONE


/* AVAudioPlayer INTERRUPTION NOTIFICATIONS ARE DEPRECATED - Use AVAudioSession instead. */

/* audioPlayerBeginInterruption: is called when the audio session has been interrupted while the player was playing. The player will have been paused. */
- (void)audioPlayerBeginInterruption:(AVAudioPlayer *)player{
    
    NSLog(@"-- audioPlayerBeginInterruption ");
}

/* audioPlayerEndInterruption:withOptions: is called when the audio session interruption has ended and this player had been interrupted while playing. */
/* Currently the only flag is AVAudioSessionInterruptionFlags_ShouldResume. */
- (void)audioPlayerEndInterruption:(AVAudioPlayer *)player withOptions:(NSUInteger)flags{
    
    NSLog(@"-- audioPlayerEndInterruption ");
}

- (void)audioPlayerEndInterruption:(AVAudioPlayer *)player withFlags:(NSUInteger)flags{
    
    NSLog(@"-- audioPlayerEndInterruption ");
}

/* audioPlayerEndInterruption: is called when the preferred method, audioPlayerEndInterruption:withFlags:, is not implemented. */
- (void)audioPlayerEndInterruption:(AVAudioPlayer *)player{
    
    NSLog(@"-- audioPlayerEndInterruption ");
}
#endif

多个播放器


AVAudioPlayer *guitarPlayer = [self playerForFile:@"guitar"];
AVAudioPlayer *bassPlayer = [self playerForFile:@"bass"];
AVAudioPlayer *drumsPlayer = [self playerForFile:@"drums"];

guitarPlayer.delegate = self;

_players = @[guitarPlayer, bassPlayer, drumsPlayer];

iOS 中的中断监听

NSNotificationCenter *nsnc = [NSNotificationCenter defaultCenter];
[nsnc addObserver:self
         selector:@selector(handleRouteChange:)
             name:AVAudioSessionRouteChangeNotification
           object:[AVAudioSession sharedInstance]];

#pragma mark - Interruption Handlers

//
// The following two methods have been deprecated.
// Replace with AVAudioSession notification handlers in your production code.
//

- (void)audioPlayerBeginInterruption:(AVAudioPlayer *)player {
    [self stop];
    if (self.delegate) {
        [self.delegate playbackStopped];
    }
}

- (void)audioPlayerEndInterruption:(AVAudioPlayer *)player
                       withOptions:(NSUInteger)options {

    if (options == AVAudioSessionInterruptionOptionShouldResume) {
        [self play];
        if (self.delegate) {
            [self.delegate playbackBegan];
        }
    }
}

#pragma mark - Route Change Handler

- (void)handleRouteChange:(NSNotification *)notification {

    NSDictionary *info = notification.userInfo;

    AVAudioSessionRouteChangeReason reason =
        [info[AVAudioSessionRouteChangeReasonKey] unsignedIntValue];

    if (reason == AVAudioSessionRouteChangeReasonOldDeviceUnavailable) {

        AVAudioSessionRouteDescription *previousRoute =
            info[AVAudioSessionRouteChangePreviousRouteKey];

        AVAudioSessionPortDescription *previousOutput = previousRoute.outputs[0];
        NSString *portType = previousOutput.portType;

        if ([portType isEqualToString:AVAudioSessionPortHeadphones]) {
            [self stop];
            [self.delegate playbackStopped];
        }
    }
}

AVAudioSession 设置

只需要初始化一次,后面也可以修改。

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]);
}   

你可能感兴趣的:(AVF 2 - 音频播放)