iOS 音频

iOS 音频播放

  • 本地音频文件 AVPlayer / AVAudioPlayer
  • 在线音频流 AVPlayer
  • iPod 歌曲 AVPlayer / AVAudioPlayer / MPMusicPlayerController
  • 音效 AudioServices

iPod 音乐

  • iPod 歌曲的读取
    • MPMediaPickerController 系统封装的, 包括 UI
    • MPMediaLibrary + MPMediaQuery 系统封装的读取类, 不包含 UI
  • iPod 歌曲的读取权限
    • 权限相关接口: iOS 9.3+
    • iPod 读取权限弹窗: iOS 9.3+ 暂时不会直接提醒弹窗权限, 在 iOS10 加入了弹窗
    • 权限用途的说明文案: iOS 10+; Xcode 8+ 必须要在 info.plist 写明 NSAppleMusicUsageDescription
  • 使用 MPMediaPickerController 读取
@interface MPMediaPickerController : UIViewController

@property (nonatomic, readonly) MPMediaType mediaTypes;
@property (nonatomic, weak, nullable) id delegate;
@property (nonatomic) BOOL allowsPickingMultipleItems;
@property (nonatomic) BOOL showsCloudItems;
@property (nonatomic) BOOL showsItemsWithProtectedAssets;
@property (nonatomic, copy, mullable) NSString *prompt; 
@protocol MPMediaPickerControllerDelegate 
- (void)mediaPicker:(MPMediaPickerController *)mediaPicker didPickMediaItems:(MPMediaItemCollection *)mediaItemCollection;
- (void)mediaPickerDidCancel:(MPMediaPickerController *)mediaPicker;
@interface MPMediaItemCollection : MPMediaEntity

@interface MPMediaItem : MPMediaEntity
  • [musicPlayer prepareToPlay] 将选中的音乐放进播放列表中

    • 直接调用 play 方法也可以达到将歌曲放入播放列表中的效果
  • 播放状态

      /*** MPMusicPlaybackState ***/
      MPMusicPlaybackStateStopped
      MPMusicPlaybackStatePlaying         // 播放
      MPMusicPlaybackStatePaused          // 暂停
      MPMusicPlaybackStateInterrupted     // 中断状态
      MPMusicPlaybackStateSeekingForward  // 线控时播放状态
      MPMusicPlaybackStateSeekingBackword // 线控时播放状态
    
  • 播放状态的通知

      MPMusicPlayerControllerPlaybackStateDidChangeNotification
    
  • 播放进度

  • 切歌

    @interface MPMusicPlayerController (MPPlaybackControl)
    - (void)skipToNextItem;     // 下一曲
    - (void)skipToPreviousItem; // 上一曲
    
  • 播放模式

      repeatMode
          MPMusicRepeatModeDefault
          MPMusicRepeatModeNone
          MPMusicRepeatModeOne
          MPMusicRepeatModeAll        
      shuffleMode
          MPMusicShuffleModeDefault
          MPMusicShuffleModeOff
          MPMusicShuffleModeSongs
          MPMusicShuffleModeAlbums
    
  • 定义自己的播放模式

    typedef NS_ENUM (NSUInteger, AudioPlayerMode) {
        AudioPlayerModeRepeat,
        AudioPlayerModeSingle,
        AudioPlayerModeRandom,
    }
    - (void)setMode:(AudioPlayerMode)mode {
        _mode = mode;
        if (mode == AudioPlayerModeRepeat) {
            _musicPlayer.repeatMode  =  MPMusicRepeatModeAll;
            _musicPlayer.shuffleMode =  MPMusicShuffleModeOff;
        } else if (mode == AudioPlayerModeSingle) {
            _musicPlayer.repeatMode  =  MPMusicRepeatModeOne;
            _musicPlayer.shuffleMode =  MPMusicShuffleModeOff;
        } else if (mode == AudioPlayerModeRandom) {
            _musicPlayer.repeatMode  =  MPMusicRepeatModeAll;
            _musicPlayer.shuffleMode =  MPMusicShuffleModeSongs;
        }
    }
    
  • applicationMusicPlayer & systemMusicPlayer

    • 都是调用系统的音乐 app 进行播放
    • 不同
      • applicationMusicPlayer 不会改变系统正在播放的歌曲
      • systemMusicPlayer 会改变系统自动播放的歌曲, 相当于直接在系统音乐中进行播放

优势

- 接口完全封装, 使用简单
- 不关心播放模式, 播放列表的维护
- 不关心其他的问题, 例如打断

问题

- 只能播放 iPod 歌曲
- 不是自己的 app 在后台播放, 而是调用系统的音乐 app 在播放
- 进入系统选歌界面或者使用 MPMediaLibrary 歌曲会停止, 播放列表会清空

自行实现 iPod 歌曲选择

  • MPMediaLibrary
类型 资源
在线音频流 音频 URL AVURLAsset
本地音频文件 音频文件 AVURLAsset
iPod 歌曲 Music.app 中的歌曲 MPMediaItem
  • Metadata

    • 音频信息
      • 歌名
      • 专辑
      • 歌手
      • 封面图
    • 音频数据 - 听到的音乐
  • commonMetadata & metadata

    • commonMetadata 共有格式的数据内容
    • metadata 不一定通用的格式

AVPlayer

  • 在线
  • 本地
  • iPod

AVPlayerItem

  • 代表一个播放对象
  • 加载状态
  • 播放总时长
  • 进行 seek 操作

AVQueuePlayer

初始化

  • 在线歌曲不能获取 metadata, 所以对于在线歌曲就不获取 metadata
  • 使用 rate 控制播放状态
  • 使用在线音频的时候不能直接做立即播放

AudioSession

后台播放

  1. Set AudioSession Category & Active
  2. Set App Background Mode
  3. [[UIApplication sharedApplication] beginReceivingRemoteControlEvents]

管理输入输出设备

NowPlayingCenter


录音

AudioSession

  1. 获取录音权限 + 填写使用理由
    • AVAudioSessionRecordPermission permission = [[AVAudioSession sharedInstance] recordPermission];
  2. set Category
    • [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryRecord error:nil];
    • [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
  3. set Active
    • [[AVAudioSession sharedInstance] setActive:YES error:nil];
  4. 处理打断或设备更换

AVAudioRecorder

#import 
NSString *const AVNumberOfChannelsKey; // 声道数
NSString *const AVSampleRateKey; // 采样率
NSString *const AVLinearPCMBitDepthKey; // 位声
NSString *const AVFormatIDKey;
/* ------ AVFormatIDKey ------
kAudioFormatLinearPCM     = 'lpcm'
kAudioFormatApplelMA4     = 'ima4'
kAudioFormatMPEG4AAc      = 'aac'
kAudioFormatULaw          = 'ulaw'
kAudioFormatALaw          = 'alaw'
kAudioFormatAppleLossless = 'alac'
*/
  • PCM 文件: 最原始的未经过处理的录音文件
    • 等同于: WAV
    • 压缩成: AAC, MP3(有损压缩), FLAC(无损压缩), ...
    • iOS 不能直接录制成 MP3 格式
NSString *filePath = [NSTemporaryDirectory() stringByAppendingFileComponent:@"tempRecord.aac"];
NSDictionary *settings = @{
    AVNumberOfChannelsKey : @1,
    AVSampleRateKey : @8000,
    AVLinearPCMBitDepthKey : @16,
    AVFormatIDKey : @(kAudioFormatMPEG4AAC)
};
NSError *error = nil;
// 生成 recorder
_recorder = [[AVAudioRecorder alloc] initWithURL:[NSURL fileURLWithPath:filePath] settings:settings error:&error];

创建文件

开始录音

- (BOOL)preparedToRecord;
- (BOOL)record;
- (BOOL)recordAtTime:(NSTimeInterval)time; // 开始时间
- (BOOL)recordForDuration:(NSTimeInterval)duration; // 录音时长
- (BOOL)recordAtTime:(NSTimeInterval)time forDuration:(NSTimeInterval)duration;

录音停止和文件操作

- (void)pause;
- (void)stop;
- (BOOL)deleteRecording;
@property BOOL recording;
@property NSURL *url;
@property NSTimeInterval currentTime; // 当前录音进行的时间

AVAudioPlayer

  • 不支持播放模式
  • 调整左右声道
  • 调整播放器内部的音量
  • 调整播放速率
  • 读取播放歌曲的数据参数, 例如采样率
  • 读取某个时间点的歌曲声音大小

资源类型

类型 资源
在线音频流 音频 URL AVURLAsset
本地音频文件 音频文件 AVURLAsset
iPod歌曲 Music.app中的歌曲 MPMediaItem

AVURLAsset �: AVAsset

/*  AVAsset  */
@interface AVAsset : NSObject
+ assetWithURL:(NSURL *)URL;
@property (notatomic, readonly) CMTime duration;

@property NSArray *commomMetadata;
@property NSArray *metadata;
/*  AVURLAsset  */
@interface AVURLAsset : AVAsset
+ URLAssetWithURL: options: ;
- initWithURL: options: ;

@property NSURL *URL;
// 继承子 AVAsset 后提供了两个初始化方法
// 提供 URL 属性的访问
// 提供 metadata 的读取

Metadata

  • 音频数据 : 听到的音乐
  • 音频信息 : 歌名, 专辑, 歌手, 封面 等

创建 AVURLAsset

  • 三种资源转换成 AVURLAsset
// 在线音频
NSURL *audioURL = [NSURL URLWithString:@"http://xxx.com/music.mp3"];
AVURLAsset *audioAsset = [AVURLAsset assetWithURL:audioURL];

// 本地音频
NSString *filePath = [[NSBundle mainBundle] pathForResources:@"music" ofType:@"mp3"];
NSURL *fileURL = [NSURL fireURLWithPath:filePath];
AVURLAsset *fileAsset = [AVURLAsset assetWithURL:fileURL];

// iPod 音频
MPMediaQuery *query = [MPMediaQuery songsQuery];
if (query.items.count > 0) {
    MPMediaItem *item = query.item[0];
    AVURLAsset *iPodAsset = [AVURLAsset assetWithURL:item.assetURL];
}

AVAudioPlayer

  • 初始化方法
    • 尽量使用带有 fileTypeHint 的初始化方法, 并填入 hint
    • 如果使用 URL 作为参数, 尽量让其带有后缀名, 例如: xxx.mp3
    • 使用 URL 作为参数时只能是本地文件的 URL, 不能是网络 URL 地址
@interface AVAudioPlayer : NSObject

- initWithContentOfURL: error: ;
- initWithData: error: ;

- initWithContentOfURL: fileTypeHint: error: ; // 表示单个歌曲
- initWithData: fileTypeHint: error: ;
  • fileTypeHint : 文件类型的判断, 帮助解码器判断, 使得解码不容易出错

你可能感兴趣的:(iOS 音频)