音频播放,后台播放,锁频控制

这篇博客主要介绍了在iOS平台上实现短音频和长音频的播放,包括使用C语言方法和AVFoundation库。还讨论了音频播放器的控制,如播放、暂停、停止,并解释了prepareToPlay和stop方法的区别。此外,提到了后台播放设置和音频中断的处理方法。最后,简述了录音功能的实现步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我的博客:http://blog.csdn.net/nsydianzi


1.短音频


C语言方法:导入AudioToolbox/AudioToolbox.h

思路步骤:

第一步:获取音频文件的url,并且定义一个音频ID(SystemSoundID由系统自动提供)

第二步:加载对应的音频文件到内存,并对应上音频ID

第三步:播放音频

 
 
  1. //音频文件的URL

  2. NSURL *soundUrl = [[NSBundle mainBundle] URLForResource:@"/plane.bundle/enemy1_down.mp3" withExtension:nil];

  3. //音频ID,一个音频文件对应一个soundID

  4. SystemSoundID soundId;

  5. NSLog(@"%d",soundId);

  6. //加载了音频文件到内存

  7. AudioServicesCreateSystemSoundID((__bridge CFURLRef)soundUrl, &soundId);

  8. //播放音频

  9. AudioServicesPlaySystemSound(soundId);


可以抽取一个播放类,用来播放音乐,这个类最好是一个单例,不然音频文件加载太多次,会有内存问题

 
 
  1. +(void)initialize{    //加载这个类时,自动将短音频加载进内存

  2.    //1.加载所有音频文件

  3.    //1.1 遍历plane.bundle的所有音频文件

  4.    NSFileManager *manager = [NSFileManager defaultManager];

  5.    

  6.    //1.2获取plane.bundle的路径

  7.    NSString *planePath = [[NSBundle mainBundle] pathForResource:@"plane.bundle" ofType:nil];

  8.    

  9.    NSError *error = nil;

  10.    NSArray *contents = [manager contentsOfDirectoryAtPath:planePath error:&error];

  11.    NSLog(@"%@",contents);

  12.    

  13.    //1.3 遍历里面的mp3文件,创建SystemSoundID

  14.    NSMutableDictionary *soundDictM = [NSMutableDictionary dictionary];

  15.    for (NSString *mp3Name in contents) {

  16.        //音频文件的URL

  17.        NSString *soundUrlStr = [planePath stringByAppendingPathComponent:mp3Name];

  18.        NSURL *soundUrl = [NSURL fileURLWithPath:soundUrlStr];

  19.        

  20.        //音频ID,一个音频文件对应一个soundID

  21.        SystemSoundID soundId;

  22.        

  23.        AudioServicesCreateSystemSoundID((__bridge CFURLRef)(soundUrl), &soundId);

  24.        

  25.        //1.4通过字典存储soundID @{"enemy1_down.mp3":11111,"enemy2_down.mp3",11112}

  26.        soundDictM[mp3Name] = @(soundId);

  27.        

  28.    }

  29.    

  30.    NSLog(@"%@",soundDictM);

  31.    soundDict = soundDictM;

  32. }

 
 
  1. //2.给一个方法播放音频文件

  2. -(void)playMp3WithName:(NSString *)mp3Name{    //调用这个公开的方法播放音乐

  3.    //通过键值获取soundId

  4.    SystemSoundID soundId =  [soundDict[mp3Name] unsignedIntValue];

  5.    

  6.    //播放

  7.    AudioServicesPlaySystemSound(soundId);

  8.    

  9.    //振动

  10.    //AudioServicesPlayAlertSound(<#SystemSoundID inSystemSoundID#>)

  11. }


2.长音频播放

使用系统提供的OC库,AVFoundation

播放思路:

1. 从mainBundle中获取音频的url

    创建一个AVAdioPlayer对象,这就是一个播放器对象,音频的播放由这个对象控制

2.player对象准备播放,调用prepareToPlay播放

3.播放,暂停,停止

[self.player play];    //播放

[self.player pause];   //暂停

[self.player stop];    //停止,停止方法需要将播放的当前时间置0.//self.player.currentTime = 0;

  • 这里解释pause和stop方法的区别,调用stop之后虽然是要将当前的时间置为0,但是他们的底层调用方法是不一样的,调用stop方法是会撤销prepareToPlay做的设置,而调用pause方法不会撤销。
  • 说明白点就是,调用stop之后,要重新播放音乐的话需要重新设置prepareToPlay方法。而pause不是的。


@property BOOL enableRate;//如果你想设置音频播放的速率,你应该将这个属性设置为yes,并且你必须在发送

prepareToPlay这个消息之前.这句是我直接翻译的苹果官方的解释,但是我发现即使我在prepareToPlay方法后面设置也没问题,不知是什么原因.


  • 2016-1-23 AVFoudation开发秘籍   第24页
  • 解释:
  • prepareToPlay  AVAdioPlayer调用paly这个方法的时候会隐性的调用prepareToPlay这个方法,但是如果自己显式的调用这个方法  可以降低调用play方法时和听到输出声音之间的延时。



@property NSInteger numberOfLoops;//设置音频要播放的次数,如果你设置为0,就会播放1次,设置为1,就会播放2次.并且如果是负数,将会一直播放,知道你停止这段音频;

@property NSTimeInterval currentTime;//音频当前播放的时间


//监听音乐的中断

AVAudioSession *session = [AVAudioSession sharedInstance];

[[NSNotificationCenter defaultCenteraddObserver:selfselector:@selector(handleInterruption:)name:AVAudioSessionInterruptionNotification object:session];

-(void)handleInterruption:(NSNotification *)noti

{

    NSLog(@"%@",noti.userInfo);

}

//    AVAudioSessionInterruptionTypeKey = 1 //开始中断

//    AVAudioSessionInterruptionTypeKey = 0 //结束中断

 
 
  1. #import "ViewController.h"
  2. #import <AVFoundation/AVFoundation.h>
  3. @interface ViewController ()<AVAudioPlayerDelegate>
  4. @property (weak, nonatomic) IBOutlet UISlider *timeSlider;
  5. @property(nonatomic,strong)AVAudioPlayer *player;
  6. @end
  7. @implementation ViewController
  8. - (void)viewDidLoad {
  9.    [super viewDidLoad];
  10.    // Do any additional setup after loading the view, typically from a nib.
  11.    
  12.    //获取mp3路径
  13.    NSURL *mp3Url = [[NSBundle mainBundle] URLForResource:@"bbqne.mp3" withExtension:nil];
  14.    
  15.    //播放音乐
  16.    NSError *error = nil;
  17.    // 1.创建一个音乐播放器
  18.    AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithContentsOfURL:mp3Url error:&error];
  19.    if (error) {
  20.        NSLog(@"%@",error);
  21.    }
  22.    
  23.    // 2.准备播放
  24.    [player prepareToPlay];
  25.    
  26.    // 打开可以改变速度的开头
  27.    player.enableRate = YES;
  28.    
  29.    // 播放次数
  30.    player.numberOfLoops = 0;//0代表播放一次 1代表播放2次
  31.    
  32.    
  33.    player.delegate = self;
  34.    
  35.    self.player = player;
  36.    
  37.    //设置timeSlider的最大值
  38.    self.timeSlider.maximumValue = self.player.duration;
  39.    
  40.    //监听音乐的中断
  41.    AVAudioSession *session = [AVAudioSession sharedInstance];
  42.    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleInterruption:) name:AVAudioSessionInterruptionNotification object:session];
  43.    
  44. }
  45. /**
  46. *  处理中断
  47. */
  48. -(void)handleInterruption:(NSNotification *)noti{
  49.    NSLog(@"%@",noti.userInfo);
  50. }
  51. - (IBAction)stopBtnClick:(id)sender {
  52.    
  53.    [self.player stop];
  54.    
  55.    //自己指定播放的时候到0的位置
  56.    self.player.currentTime = 0;
  57. }
  58. - (IBAction)playBtnClick:(id)sender {
  59.    
  60.    
  61.    // 3.播放
  62.    [self.player play];
  63. }
  64. - (IBAction)pauseBtnClick:(id)sender {
  65.    
  66.    [self.player pause];
  67. }
  68. /**
  69. *  播放时间变化
  70. *
  71. */
  72. - (IBAction)timeChange:(UISlider *)sender {
  73.    
  74.    NSLog(@"时间变化:%f",sender.value);
  75.    
  76.    self.player.currentTime = sender.value;
  77. }
  78. /**
  79. *  播放速度变化
  80. *
  81. */
  82. - (IBAction)rateChange:(UISlider *)sender {
  83.    
  84.    self.player.rate = sender.value;
  85. }
  86. /*
  87. *播放音量的改变
  88. */
  89. - (IBAction)volumnChange:(UISlider *)sender {
  90.    
  91.    self.player.volume = sender.value;
  92. }
  93. #pragma mark - AVAuidoPalyer的代理
  94. #pragma mark 音乐播放完成后调用
  95. -(void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag{
  96.    NSLog(@"%s",__func__);
  97. }
  98. @end

如果要做歌词显示,这里提供个思路

1.首先设置一个定时器,这里可以用懒加载,给定时器关联一个方法.

2.关联的方法中倒序遍历歌词,判断当前时间是否是大于歌词模型中的播放时间,如果是的话,执行选中cell的方法.

3.将定时器加入到当前的runloop中

4.音频播放完成后,将定时器移除.


@property(nonatomic,strong)CADisplayLink *link;//定时器

-(CADisplayLink *)link{

    if (!_link) {

        _link = [CADisplayLink displayLinkWithTarget:selfselector:@selector(update)];

    }

    

    return _link;

}


[self.link addToRunLoop:[NSRunLoop mainRunLoop]forMode:NSDefaultRunLoopMode];


/**

 *  刷新诗词  的进度

 */

-(void)update{

    double  currentTime = self.wordsPlayer.currentTime;

    NSLog(@"当前播放的时间 %lf",currentTime);

    

    //倒序遍历诗词

    //self.words -> CZWord

    //总的"句数"

    NSInteger numberOfWord = self.words.count;


    //诗词最大的索引

    NSInteger maxIndex = numberOfWord - 1;

    for (NSInteger i = maxIndex; i >=0 ; i--) {

        //获取遍历的诗词

        CZWord *word = self.words[i];

        if (currentTime >= word.time) {

            NSLog(@"当前诗词的索引为 %ld",i);

            [self selectedCellWithIndex:i];

            break;

        }

        

    }

}

/**

 *  选中表格

 *

 */

-(void)selectedCellWithIndex:(NSInteger)index{

    

    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:indexinSection:0];

    //选中

    [self.tableView selectRowAtIndexPath:indexPath animated:NOscrollPosition:UITableViewScrollPositionMiddle];

}

#pragma mark AudioPlayer代理

-(void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag{

    //当诗词播放完成后,背景音乐停止

    [self.bgMusicPalyer stop];

    

    //定时器也要移除

    [self.link removeFromRunLoop:[NSRunLoop mainRunLoop]forMode:NSDefaultRunLoopMode];

}

录音Record

同样要用到AVFoundation中的对象AVAudioRecorder

步骤也简单:

1:设置音频文件保存的路径

2:创建一个字典对象,将录音的设置保存进去,例如,音频编码格式,采样频率,音频频道,线性音频的位深度

 
 
  1. //setting 录音时的设置
  2. NSMutableDictionary *settings = [NSMutableDictionary dictionary];
  3. //音频编码格式
  4. settings[AVFormatIDKey] = @(kAudioFormatAppleIMA4);
  5. //音频采样频率
  6. settings[AVSampleRateKey] = @(8000.0);
  7. //音频频道
  8. settings[AVNumberOfChannelsKey] = @(1);
  9. //音频线性音频的位深度
  10. settings[AVLinearPCMBitDepthKey] = @(8);

3.创建录音器对象AVAudioRecorder,将路径和设置初始化

4.准备录音和开始录音

5.结束录音

 
 
  1. /**
  2. *  开始录音
  3. *
  4. */
  5. - (IBAction)startRecord:(UIButton *)sender {
  6.    NSLog(@"%s",__func__);
  7.    
  8.    //1.创建录音器
  9.    
  10.    //1.1URL 是录音文件保存的地址
  11.    //音频文件保存在沙盒 document/20150228171912.caf
  12.    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
  13.    dateFormatter.dateFormat = @"yyyyMMddHHmmss";
  14.    NSString *timeStr = [dateFormatter stringFromDate:[NSDate date]];
  15.    
  16.    //音频文件名
  17.    NSString *audioName = [timeStr stringByAppendingString:@".caf"];
  18.    
  19.    //doc目录
  20.    NSString *doc = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
  21.    
  22.    //拼接音频URL
  23.    NSString *fileURL = [doc stringByAppendingPathComponent:audioName];
  24.    NSLog(@"%@",fileURL);
  25.    
  26.   //保存文件路径到数组
  27.    [self.data addObject:fileURL];
  28.    
  29.    //setting 录音时的设置
  30.    NSMutableDictionary *settings = [NSMutableDictionary dictionary];
  31.    //音频编码格式
  32.    settings[AVFormatIDKey] = @(kAudioFormatAppleIMA4);
  33.    //音频采样频率
  34.    settings[AVSampleRateKey] = @(8000.0);
  35.    //音频频道
  36.    settings[AVNumberOfChannelsKey] = @(1);
  37.    //音频线性音频的位深度
  38.    settings[AVLinearPCMBitDepthKey] = @(8);
  39.    
  40.    self.recorder = [[AVAudioRecorder alloc] initWithURL:[NSURL fileURLWithPath:fileURL] settings:settings error:nil];
  41.    
  42.    //录音的准备
  43.    [self.recorder prepareToRecord];
  44.    
  45.    //录音
  46.    [self.recorder record];
  47.  
  48. }


设置音乐的后台播放需要如下设置

1.在didFinishLaunching方法激活音频的会话类型即可 

   
   
  1. - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  2.    // Override point for customization after application launch.
  3.    
  4.    //设置音乐后台播放的会话类型
  5.    AVAudioSession *session = [AVAudioSession sharedInstance];
  6.    [session setCategory:AVAudioSessionCategoryPlayback error:nil];
  7.    [session setActive:YES error:nil];
  8.    
  9.    return YES;
  10. }

2.在applicationDidEnterBackground方法开始后台任务,代码如下 

  
  
  1. - (void)applicationDidEnterBackground:(UIApplication *)application {
  2.    //开启后台任务
  3.    [application beginBackgroundTaskWithExpirationHandler:nil];
  4. }

3.在info.plist中添加'Required background modes'选向,然后再添加'App plays audio or streams audio/video using AirPlay' 






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值