音乐播放学习

2020-04-19  本文已影响0人  冷武橘

一、常见音频格式

WAV文件,WAV文件格式是一种由微软和IBM联合开发的用于音频 数字存储的标准,WAV文件的格式灵活,可以储存多种类型的音频数据。由于文件较大不太适合于移动设备这些存储容量小的设备。

MP3(MPEG Audio Layer 3)文件,是现在非常流行,MP3是一种有损压缩格式,它尽可能地去掉人耳无法感觉的部分和不敏感的部分。

CAFF(Core Audio File Format)文件,是苹果开发的专门用于Mac OSX和iOS系统无压缩音频格式。它被设计来替换老的WAV格式。

AIFF(Audio Interchange File Format)文件,是苹果开发的专门用于Mac OS X系统,是专业的音频文件格式。AIFF的压缩格式是AIFF-C(或AIFC),将数据以4:1压缩率进行压缩,应用于Mac OS X和iOS系统。

硬件解码器一次只能对一个音频文件解码。在实际应用中通常使用非压缩的音频格式(AIFF)或者CAF音频格式,从而减低系统在音频解码上的消耗,达到省电的目的

二、播放基本音效

  {
// 1.获得音效文件的路径
    NSURL *url = [[NSBundle mainBundle] URLForResource:@"m_03.aff" withExtension:nil];
    SystemSoundID soundID = 0;

    //2.创建一个sourceID
    AudioServicesCreateSystemSoundID((__bridge CFURLRef _Nonnull)(url), &soundID);

//如果需要在播放完之后执行某些操作,可以调用如下方法注册一个播放完成回调函数
    AudioServicesAddSystemSoundCompletion(soundID, NULL, NULL, soundCompleteCallback, NULL);

    //3.播放音效
    AudioServicesPlaySystemSound(soundID);
注意:一个SoundID对应一个音频文件,如果你想播放多个音频文件,需要多个SoundID
}
void soundCompleteCallback(SystemSoundID soundID,void * clientData){
    NSLog(@"播放完成...");
}
//封装一个音效播放工具
- (void)playSoundWithSoundname:(NSString *)soundname{
    SystemSoundID soundID = 0;
    soundID=[[self.soundIDdictionry objectForKey:soundname]unsignedIntValue];
    if (soundID==0) {
    NSURL *url = [[NSBundle mainBundle] URLForResource:soundname withExtension:nil];
        AudioServicesCreateSystemSoundID(CFBridgingRetain(url), &soundID);
        [self.soundIDdictionry setObject:@(soundID) forKey:soundname];
    }
    // 3.播放音效
    AudioServicesPlaySystemSound(soundID);
}

使用AudioServicesPlaySystemSound时需要注意:

1、No longer than 30 seconds in duration
音频不要超过30s

2、In linear PCM or IMA4 (IMA/ADPCM) format
数据必须是PCM或者IMA4格式

3、Packaged in a .caf, .aif, or .wav file
音频文件必须打包成.caf、.aif、.wav中的一种

三、播放音乐

AVAudioPlayer 是 AVFoundation.framework 中定义的一个类,所以使用要先在工程中引入AVFoundation.framework。我们可以把 AVAudioPlayer看作是一个高级的播放器,它支持广泛的音频格式,主要是以下这些格式:
AAC、AMR(AdaptiveMulti-Rate, aformatforspeech)、ALAC(AppleLossless)、iLBC(internetLowBitrateCodec, anotherformatforspeech)、 IMA4(IMA/ADPCM)、linearPCM(uncompressed)、 µ-lawanda-law、 MP3(MPEG-1audiolayer3

//01加载播放路径
    NSURL *url=[[NSBundle mainBundle]URLForResource:@"1201111234.mp3" withExtension:nil];
    NSError *erron=nil;
//02创建播放器
   self.audionplayer=[[AVAudioPlayer alloc]initWithContentsOfURL:url error:&erron];
//注意:audioPlayer一定要设置成全局变量,局部变量会被释放

   // 03准备播放(缓冲,提高播放的流畅性)
    [self.audionplayer prepareToPlay];

   // 04播放音乐
    [self.audionplayer play];

 //[self.audioPlayer stop];停止播放  [self.audioPlayer pause];暂停播放

    NSLog(@"%@",erron);

1、AVAudioPlayer一次只能播放一个音频文件,所有上一曲、下一曲其实可以通过创建多个播放器对象来完成。
2、AVAudioPlayer对象需要作为属性或成员变量,要不然会被释放掉。
3、 [self.audioPlayer stop];停止后,再播放不会从头开始播放。因此需要[self.audioPlayer=nil;手动清空一下
4、AVAudioPlayer只能播放本地音乐,不能播放网络音乐。

//封装音乐播放器
#pragma mark - 播放音乐
- (void)playMusicWithMusicName:(NSString *)musicName{
    AVAudioPlayer *player=[self.audiodictionry objectForKey:musicName];
    if (player==nil) {//如果取出出来是空,则对应创建对应的播放器
        NSURL *url=[[NSBundle mainBundle]URLForResource:@"1201111234.mp3" withExtension:nil];
        if (url==nil)return;
        NSError *erron=nil;
        //02创建播放器
        player=[[AVAudioPlayer alloc]initWithContentsOfURL:url error:&erron];
        [self.audiodictionry setObject:player forKey:musicName];
    }
    // 03准备播放(缓冲,提高播放的流畅性)
    [player prepareToPlay];
    
    // 04播放音乐
    [player play];
}

#pragma mark - 暂停音乐
- (void)pauseMusicWithMusicName:(NSString *)musicName{
     AVAudioPlayer *player=[self.audiodictionry objectForKey:musicName];
    if (player) {
     [player pause];
    }
}
#pragma mark - 停止音乐
- (void)stopMusicWithMusicName:(NSString *)musicName{
     AVAudioPlayer *player=[self.audiodictionry objectForKey:musicName];
    if (player) {
        [player stop];
        player=nil;
        [self.audiodictionry removeObjectForKey:musicName];
    }
}

四、简单音乐播放器的实现(关键代码)

@interface AVAudioPlayer: NSObject
@property(readonly) NSTimeInterval duration; //声音的总时长
@property NSTimeInterval currentTime;//已播放过的声音时长

    UISlider *slider=[[UISlider alloc]init];
    [self.view addSubview:slider];
    self.progressSlider=slider;
    //设置滑块的背景图
    [slider setThumbImage:[UIImage imageNamed:@"player_slider_playback_thumb"] forState:UIControlStateNormal];
    //监听开始拖动
    [slider addTarget:self action:@selector(startchange) forControlEvents:UIControlEventTouchDown];

    //监听拖动
    [slider addTarget:self action:@selector(valuechange) forControlEvents:UIControlEventValueChanged];
    
    //监听结束拖动
    [slider addTarget:self action:@selector(endchange:) forControlEvents:UIControlEventTouchUpInside];

#pragma mark - 开始拖动
- (void)startchange{
    //让之前的定时器失效
    [self.progressTimer invalidate];
    self.progressTimer=nil;
}

#pragma mark - 拖动滑块调节歌曲进度
- (void)valuechange{
    // 设置当前播放文字显示的内容
    self.currentTimeLabel.text = [self stringWithTime:self.progressSlider.value * self.currentplayer.duration];
}

#pragma mark - 结束拖动
- (void)endchange:(UISlider *)slider{
  //更新播放的时间
  self.currentplayer.currentTime=slider.value*self.currentplayer.duration;
    
   //更新滑块的位置和当前的播放时间显示
  [self updateProgressInfo];
    
  //添加定时器
  [self addProgressTimer];
}


#pragma mark - 添加定时器
- (void)addProgressTimer
{
    self.progressTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateProgressInfo) userInfo:nil repeats:YES];
    [[NSRunLoop mainRunLoop] addTimer:self.progressTimer forMode:NSRunLoopCommonModes];
}

#pragma mark - 更新进度信息
- (void)updateProgressInfo
{
    // 1.更新当前时间的Label
    self.currentTimeLabel.text = [self stringWithTime:self.currentplayer.currentTime];
    
    // 2.更新滑块的位置
    self.progressSlider.value = self.currentplayer.currentTime / self.currentplayer.duration;
}

#pragma mark - 时间格式处理
-(NSString*)stringWithTime:(NSTimeInterval)time
{
    NSInteger min = time / 60;
    NSInteger second = (NSInteger)time % 60;
    
    return [NSString stringWithFormat:@"%02ld:%02ld", min, second];
}
#pragma mark - 后台播放
- (void)applicationWillResignActive:(UIApplication *)application {
    
    // 1.获取音频回话
    AVAudioSession *session = [AVAudioSession sharedInstance];
    
    // 2.设置后台播放类别
    [session setCategory:AVAudioSessionCategoryPlayback error:nil];
    
    // 3.激活回话
    [session setActive:YES error:nil];
}

//开始接收远程事件
 [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];

#pragma mark - 实现远程事件的方法
// 监听远程事件
- (void)remoteControlReceivedWithEvent:(UIEvent *)event
{
    switch (event.subtype) {
        case UIEventSubtypeRemoteControlPlay:
        case UIEventSubtypeRemoteControlPause:
            [self playorpause];
            break;
            
        case UIEventSubtypeRemoteControlNextTrack:
            [self nextmusic];
            break;
            
        case UIEventSubtypeRemoteControlPreviousTrack:
            [self lastmusic];
            break;
            
        default:
            break;
    }
}

#pragma mark - 设置锁屏界面的信息
 - (void)setupLockScreenInfo
 {
 // 1.获取锁屏界面中心
 MPNowPlayingInfoCenter *playingInfoCenter = [MPNowPlayingInfoCenter defaultCenter];
 
 // 2.设置展示的信息
 NSMutableDictionary *playingInfo = [NSMutableDictionary dictionary];
 [playingInfo setObject:_playingMusic.name forKey:MPMediaItemPropertyAlbumTitle];
 [playingInfo setObject:_playingMusic.singer forKey:MPMediaItemPropertyArtist];
 MPMediaItemArtwork *artWork = [[MPMediaItemArtwork alloc] initWithImage:[UIImage imageNamed:_playingMusic.icon]];
 [playingInfo setObject:artWork forKey:MPMediaItemPropertyArtwork];
     [playingInfo setObject:@(self.currentplayer.duration) forKey:MPMediaItemPropertyPlaybackDuration];
 playingInfoCenter.nowPlayingInfo = playingInfo;

 }
上一篇下一篇

猜你喜欢

热点阅读