iOS 音頻

iOS 音頻播放

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

iPod 音樂(lè)

  • iPod 歌曲的讀取
    • MPMediaPickerController 系統(tǒng)封裝的, 包括 UI
    • MPMediaLibrary + MPMediaQuery 系統(tǒng)封裝的讀取類(lèi), 不包含 UI
  • iPod 歌曲的讀取權(quán)限
    • 權(quán)限相關(guān)接口: iOS 9.3+
    • iPod 讀取權(quán)限彈窗: iOS 9.3+ 暫時(shí)不會(huì)直接提醒彈窗權(quán)限, 在 iOS10 加入了彈窗
    • 權(quán)限用途的說(shuō)明文案: iOS 10+; Xcode 8+ 必須要在 info.plist 寫(xiě)明 NSAppleMusicUsageDescription
  • 使用 MPMediaPickerController 讀取
@interface MPMediaPickerController : UIViewController

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

@interface MPMediaItem : MPMediaEntity
  • [musicPlayer prepareToPlay] 將選中的音樂(lè)放進(jìn)播放列表中

    • 直接調(diào)用 play 方法也可以達(dá)到將歌曲放入播放列表中的效果
  • 播放狀態(tài)

      /*** MPMusicPlaybackState ***/
      MPMusicPlaybackStateStopped
      MPMusicPlaybackStatePlaying         // 播放
      MPMusicPlaybackStatePaused          // 暫停
      MPMusicPlaybackStateInterrupted     // 中斷狀態(tài)
      MPMusicPlaybackStateSeekingForward  // 線控時(shí)播放狀態(tài)
      MPMusicPlaybackStateSeekingBackword // 線控時(shí)播放狀態(tài)
    
  • 播放狀態(tài)的通知

      MPMusicPlayerControllerPlaybackStateDidChangeNotification
    
  • 播放進(jìn)度

  • 切歌

    @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

    • 都是調(diào)用系統(tǒng)的音樂(lè) app 進(jìn)行播放
    • 不同
      • applicationMusicPlayer 不會(huì)改變系統(tǒng)正在播放的歌曲
      • systemMusicPlayer 會(huì)改變系統(tǒng)自動(dòng)播放的歌曲, 相當(dāng)于直接在系統(tǒng)音樂(lè)中進(jìn)行播放

優(yōu)勢(shì)

- 接口完全封裝, 使用簡(jiǎn)單
- 不關(guān)心播放模式, 播放列表的維護(hù)
- 不關(guān)心其他的問(wèn)題, 例如打斷

問(wèn)題

- 只能播放 iPod 歌曲
- 不是自己的 app 在后臺(tái)播放, 而是調(diào)用系統(tǒng)的音樂(lè) app 在播放
- 進(jìn)入系統(tǒng)選歌界面或者使用 MPMediaLibrary 歌曲會(huì)停止, 播放列表會(huì)清空

自行實(shí)現(xiàn) iPod 歌曲選擇

  • MPMediaLibrary
類(lèi)型 資源 類(lèi)
在線音頻流 音頻 URL AVURLAsset
本地音頻文件 音頻文件 AVURLAsset
iPod 歌曲 Music.app 中的歌曲 MPMediaItem
  • Metadata

    • 音頻信息
      • 歌名
      • 專(zhuān)輯
      • 歌手
      • 封面圖
    • 音頻數(shù)據(jù) - 聽(tīng)到的音樂(lè)
  • commonMetadata & metadata

    • commonMetadata 共有格式的數(shù)據(jù)內(nèi)容
    • metadata 不一定通用的格式

AVPlayer

  • 在線
  • 本地
  • iPod

AVPlayerItem

  • 代表一個(gè)播放對(duì)象
  • 加載狀態(tài)
  • 播放總時(shí)長(zhǎng)
  • 進(jìn)行 seek 操作

AVQueuePlayer

初始化

  • 在線歌曲不能獲取 metadata, 所以對(duì)于在線歌曲就不獲取 metadata
  • 使用 rate 控制播放狀態(tài)
  • 使用在線音頻的時(shí)候不能直接做立即播放

AudioSession

后臺(tái)播放

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

管理輸入輸出設(shè)備

NowPlayingCenter


錄音

AudioSession

  1. 獲取錄音權(quán)限 + 填寫(xiě)使用理由
    • 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. 處理打斷或設(shè)備更換

AVAudioRecorder

#import <AVFoundation/AVFoundation.h>
NSString *const AVNumberOfChannelsKey; // 聲道數(shù)
NSString *const AVSampleRateKey; // 采樣率
NSString *const AVLinearPCMBitDepthKey; // 位聲
NSString *const AVFormatIDKey;
/* ------ AVFormatIDKey ------
kAudioFormatLinearPCM     = 'lpcm'
kAudioFormatApplelMA4     = 'ima4'
kAudioFormatMPEG4AAc      = 'aac'
kAudioFormatULaw          = 'ulaw'
kAudioFormatALaw          = 'alaw'
kAudioFormatAppleLossless = 'alac'
*/
  • PCM 文件: 最原始的未經(jīng)過(guò)處理的錄音文件
    • 等同于: WAV
    • 壓縮成: AAC, MP3(有損壓縮), FLAC(無(wú)損壓縮), ...
    • 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];

創(chuàng)建文件

開(kāi)始錄音

- (BOOL)preparedToRecord;
- (BOOL)record;
- (BOOL)recordAtTime:(NSTimeInterval)time; // 開(kāi)始時(shí)間
- (BOOL)recordForDuration:(NSTimeInterval)duration; // 錄音時(shí)長(zhǎng)
- (BOOL)recordAtTime:(NSTimeInterval)time forDuration:(NSTimeInterval)duration;

錄音停止和文件操作

- (void)pause;
- (void)stop;
- (BOOL)deleteRecording;
@property BOOL recording;
@property NSURL *url;
@property NSTimeInterval currentTime; // 當(dāng)前錄音進(jìn)行的時(shí)間

AVAudioPlayer

  • 不支持播放模式
  • 調(diào)整左右聲道
  • 調(diào)整播放器內(nèi)部的音量
  • 調(diào)整播放速率
  • 讀取播放歌曲的數(shù)據(jù)參數(shù), 例如采樣率
  • 讀取某個(gè)時(shí)間點(diǎn)的歌曲聲音大小

資源類(lèi)型

類(lèi)型 資源 類(lèi)
在線音頻流 音頻 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 后提供了兩個(gè)初始化方法
// 提供 URL 屬性的訪問(wèn)
// 提供 metadata 的讀取

Metadata

  • 音頻數(shù)據(jù) : 聽(tīng)到的音樂(lè)
  • 音頻信息 : 歌名, 專(zhuān)輯, 歌手, 封面 等

創(chuàng)建 AVURLAsset

  • 三種資源轉(zhuǎn)換成 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 作為參數(shù), 盡量讓其帶有后綴名, 例如: xxx.mp3
    • 使用 URL 作為參數(shù)時(shí)只能是本地文件的 URL, 不能是網(wǎng)絡(luò) URL 地址
@interface AVAudioPlayer : NSObject

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

- initWithContentOfURL: fileTypeHint: error: ; // 表示單個(gè)歌曲
- initWithData: fileTypeHint: error: ;
  • fileTypeHint : 文件類(lèi)型的判斷, 幫助解碼器判斷, 使得解碼不容易出錯(cuò)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容