首页 > 代码库 > 【iOS开发-118】AVFoundation框架:AudioServices...音效,AVAudioPlayer音乐,AVAudioRecord录音

【iOS开发-118】AVFoundation框架:AudioServices...音效,AVAudioPlayer音乐,AVAudioRecord录音

(1)音效播放,核心代码,主要是创建一个播放器,然后播放。

#import "WPSound.h"
#import <AVFoundation/AVFoundation.h>

@implementation WPSound
static NSMutableDictionary *_soundIDDict;
+(void)initialize{
    _soundIDDict=[NSMutableDictionary dictionary];
}
//不能用懒加载,因为给用户使用的时类方法,所以需要在上面的类初始化中设置
//-(NSMutableDictionary *)soundIDDict{
//    if (_soundIDDict==nil) {
//        _soundIDDict=[NSMutableDictionary dictionary];
//    }
//    return _soundIDDict;
//}

+(void)soundPlay:(NSString *)fileName{
    if (!fileName) return;
    //取出soundID
    SystemSoundID soundID=[_soundIDDict[fileName] unsignedIntValue];
    if (!soundID) {
        NSURL *url=[[NSBundle mainBundle]URLForResource:fileName withExtension:nil];
        if (!url) return;
        AudioServicesCreateSystemSoundID((__bridge CFURLRef)url, &soundID);
        //放入字典
        _soundIDDict[fileName]=@(soundID);
    }
    AudioServicesPlaySystemSound(soundID);
}

+(void)soundDispose:(NSString *)fileName{
    if (fileName) return;
    SystemSoundID soundID=[_soundIDDict[fileName] unsignedIntValue];
    if (!soundID) return;
    AudioServicesDisposeSystemSoundID(soundID);
    //从字典中移除
    [_soundIDDict removeObjectForKey:fileName];
}
@end


(2)音乐播放,核心代码。需要注意的是创建的播放器需要是全局变量。

#import "MusicTool.h"

@implementation MusicTool
static NSMutableDictionary *_audioPlayerDict;
static AVAudioPlayer *_audioPlayer;

+(void)initialize{
    _audioPlayerDict=[NSMutableDictionary dictionary];
    //设置会话类型
    AVAudioSession *session=[AVAudioSession sharedInstance];
    [session setCategory:AVAudioSessionCategorySoloAmbient error:nil];
    [session setActive:YES error:nil];
}

+(AVAudioPlayer *)musicPlay:(NSString *)fileName{
    if (!fileName) return nil;
    //取出播放器
    AVAudioPlayer *audioPlayer=_audioPlayerDict[fileName];
    if (!audioPlayer) {
        NSURL *url=[[NSBundle mainBundle]URLForResource:fileName withExtension:nil];
        if (!url) return nil;
        //创建audioPlayer
        AVAudioPlayer *audioPlayer=[[AVAudioPlayer alloc]initWithContentsOfURL:url error:NULL];
        _audioPlayer=audioPlayer;
        [_audioPlayer prepareToPlay];
        _audioPlayer.enableRate=YES;
        //以下设置播放速度,可以测试用
//        _audioPlayer.rate=10;
//        _audioPlayerDict[fileName]=audioPlayer;
    }
    if (!_audioPlayer.isPlaying) {
        [_audioPlayer play];
    }
    return _audioPlayer;
}

+(void)musicPause:(NSString *)fileName{
    if (!fileName) return;
    AVAudioPlayer *audioPlayer=_audioPlayerDict[fileName];
    if (audioPlayer.isPlaying) {
        [audioPlayer pause];
    }
}

+(void)musicStop:(NSString *)fileName{
    if (!fileName) return;
    AVAudioPlayer *audioPlayer=_audioPlayerDict[fileName];
    if (audioPlayer.isPlaying) {
        [audioPlayer stop];
        [_audioPlayerDict removeObjectForKey:fileName];
    }
}

+(AVAudioPlayer *)currentPlayingAudioPlayer{
    for (NSString *fileName in _audioPlayerDict) {
        AVAudioPlayer *audioPlayer=_audioPlayerDict[fileName];
        if (audioPlayer.isPlaying) {
            return audioPlayer;
        }
    }
    return nil;
}
@end

(3)录音,核心代码。

#import "ViewController.h"
#import <AVFoundation/AVFoundation.h>

@interface ViewController ()
@property(nonatomic,strong) AVAudioRecorder *recorder;
@property(nonatomic,strong) CADisplayLink *link;
@property(nonatomic,assign) float silentDuration;
- (IBAction)recordStart:(id)sender;
- (IBAction)recordStop:(id)sender;
@end

@implementation ViewController

-(CADisplayLink *)link{
    if (_link==nil) {
        _link=[CADisplayLink displayLinkWithTarget:self selector:@selector(update)];
    }
    return _link;
}

-(void)update{
    //更新录音器的测量值
    [self.recorder updateMeters];
    //获得平均分贝
    float power=[self.recorder averagePowerForChannel:0];
    
    if (power<-30) {
        self.silentDuration+=self.link.duration;
        if (self.silentDuration>=2) {
            [self.recorder stop];
            [self.link invalidate];
            self.link=nil;
        }
    }else{
        self.silentDuration=0;
    }
}

- (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.
}

- (IBAction)recordStart:(id)sender {
    NSString *path=[[NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"test.caf"];
    NSURL *url=[NSURL fileURLWithPath:path];
    NSMutableDictionary *setting=[NSMutableDictionary dictionary];
    //音频格式
    setting[AVFormatIDKey]=@(kAudioFormatAppleIMA4);
    //音频采样率
    setting[AVSampleRateKey]=@(8000.0);
    //音频通道数
    setting[AVNumberOfChannelsKey]=@(1);
    //线性音频位深度
    setting[AVLinearPCMBitDepthKey]=@(8);
    
    AVAudioRecorder *recorder=[[AVAudioRecorder alloc]initWithURL:url settings:setting error:nil];
    
    //允许测量分贝
    recorder.meteringEnabled=YES;
    
    //缓冲
    [recorder prepareToRecord];
    //录音
    [recorder record];
    
    self.recorder=recorder;
    
    //开启定时器
    self.silentDuration=0;
    [self.link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
}

- (IBAction)recordStop:(id)sender {
    [self.link invalidate];
    self.link=nil;
    [self.recorder stop];
}
@end

(3)后台播放音乐,设置3处地方。

——在AppDelegate.m中设置

- (void)applicationDidEnterBackground:(UIApplication *)application {
    [application beginBackgroundTaskWithExpirationHandler:nil];
}

——在info.plist中设置

技术分享

——还有一个在程序中设置音频会话类型(可省略)

+(void)initialize{
    _audioPlayerDict=[NSMutableDictionary dictionary];
    //设置会话类型
    AVAudioSession *session=[AVAudioSession sharedInstance];
    [session setCategory:AVAudioSessionCategorySoloAmbient error:nil];
    [session setActive:YES error:nil];
}


【iOS开发-118】AVFoundation框架:AudioServices...音效,AVAudioPlayer音乐,AVAudioRecord录音