音頻播放(iOS開發)

音頻處理

一.錄音

  1. 錄音應用場景
    • 語音聊天
      • 即時通信軟件中,都包含語音發送功能
    • 語音備忘錄
      • 錄一段音頻,來記錄某件事情
  2. 錄音功能實現
    • 導入AVFoundation框架
      • 做用:一些多媒體的處理,基本上都是用這個框架
      • #import <AVFoundation/AVFoundation.h>
    • 使用AVAudioRecorder進行錄音
      1. 建立錄音文件存放路徑
      2. 設置錄音附加設置項
        • #import <AVFoundation/AVAudioSettings.h>
        • 錄音參數設置,保存到字典中,不須要掌握,固定的設置
        • 設置編碼格式:AVFormatIDKey
        • 採樣率:AVSampleRateKey
        • 通道數:AVNumberOfChannelsKey
        • 音頻質量,採樣質量:AVEncoderAudioQualityKey
      3. 根據路徑以及設置項,建立錄音對象
        • _audioRecorder = [[AVAudioRecorder alloc] initWithURL:url settings:recordSettings error:nil];
      4. 準備錄音
        • [self.audioRecorder prepareToRecord];
      5. 開始錄音
        • [self.audioRecorder record];
      6. 中止錄音
        • [self.audioRecorder stop];
  3. 概念補充
    • 編碼
      • 概念:編碼是信息從一種形式轉換爲另外一種形式的過程
      • 編碼格式:
        • PCM:脈衝編碼調製,是一種非壓縮音頻數字化技術,是一種未壓縮的原音重現,數字模式下,音頻的廚師信號是PCM
        • MP3
        • AAC:AAC實際上是"高級音頻編碼(advanced audio coding)"的縮寫,它是被設計用來取代MP3格式的
        • HE-AAC:HE-AAC是AAC的一個超集,這個"HE"表明的是"high efficiency",HE-AAC是專門爲低比特率所優化的一種音頻編碼格式
        • AMR:AMR全稱是"adaptive multi-rate"的縮寫,它也是專門爲低比特率所優化的一種音頻編碼格式
        • ALAC:它全稱是"Apple Lossless",這是一種沒有任何質量損失的音頻編碼方式,也就是咱們說的無損壓縮
        • IMA4:這是一個在16bit音頻文件下按照4:1的壓縮比來進行壓縮的格式
    • 文件格式(不一樣的文件格式,可保存不一樣的編碼格式編碼的文件)
      • wav
        • 特色:音質最好的格式,對應PCM編碼
        • 適用:多媒體開發/保存音樂/音效素材
      • mp3
        • 特色:音質好,壓縮比比較高,被大量軟件和硬件支持
        • 適用:適合用於比較高要求的音樂欣賞
      • caf
        • 特色:適用於幾乎iOS中全部的編碼格式
  4. 開發經驗
    • caf文件格式,由於某些編碼設置,文件可能會很大,並且caf格式並非很通用,因此在開發過程當中,通常會進行壓縮轉碼爲MP3格式
  5. lame靜態庫
    • 簡介
      • LAME是一個開源的MP3音頻壓縮軟件
      • LAME是一個遞歸縮寫,來自LAME Ain't an MP3 Encoder(LAME不是MP3編碼器)
      • 它自1998年以來由一個開源社區開發,目前是公認有損品質MP3中壓縮效果最好的編碼器
    • 提高權限
      • sudo -s
    • 下載lame的最新版本並解壓
      • http://sourceforge.net/projects/lame/files/lame/3.99/
    • 生成靜態庫
      • 下載build的腳本
        • https://github.com/kewlbear/lame-ios-build
      • 修改腳本權限(全部人有可執行權限)
        • chmod a+x 腳本名稱
      • 執行腳本
        • ./腳本名稱
    • 導入靜態庫到工程,開始使用
      • http://stackoverflow.com/questions/2495420/is-there-any-lame-c-wraper-simplifier-working-on-linux-mac-and-win-from-pure

二.音效播放

1.音效概念簡介

  • 音效和音樂的區別
    • 其實並無嚴格意義上的限定,通常在開發中,將時間比較短,播放頻率比較高的,當作音效處理
    • 將播放時間比較長,須要監聽播放進度,控制播放速率等操做的音頻當作音樂處理

2.導入AVFoundation框架

  • 其實音效處理對應的框架是AudioToolbox,只不過AVFoundation框架包含了此框架

3.使用對應的API,開始播放音效

  1. 根據音效文件,生成SystemSoundID
    • 獲取URL
      • CFURLRef urlRef = (__bridge CFURLRef)([[NSBundle mainBundle] URLForResource:@"m_16.wav" withExtension:nil]);
    • 建立保存soundID的變量
      • SystemSoundID soundID;
    • 經過URL和SoundID的地址,接收對應的音效SoundID
      • AudioServicesCreateSystemSoundID(urlRef, &soundID);
  2. 播放音效
    • AudioServicesPlaySystemSound(soundID);
      • 效果:直接播放,沒有震動效果
    • AudioServicesPlayAlertSound(soundID);
      • 效果:直接播放,有震動效果
    • AudioServicesPlaySystemSoundWithCompletion(soundID,block);
      • 效果:帶有播放完成回調代碼塊
  3. 根據SoundID釋放內存
    • AudioServicesDisposeSystemSoundID(soundID);
  4. 代碼優化,播放工具類的封裝
    • 優化SoundID的生成,不須要每次都建立一遍
    • 封裝播放邏輯,供多處調用

三.音樂播放

1.音樂播放

  1. 導入AVFoundation框架
  2. 使用AVAudioPlayer類,進行播放音樂
    • 根據音頻文件URL,建立AVAudioPlayer對象
      • 獲取資源URL
        • NSURL *url = [[NSBundle mainBundle] URLForResource:@"test.mp3" withExtension:nil];
      • 根據資源URL,建立AVAudioPlayer對象
        • AVAuioPlayer audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
    • 準備播放
      • [self.audioPlayer prepareToPlay];
    • 開始播放
      • [self.audioPlayer play];
  3. 附加設置
    • 暫停
      • [self.audioPlayer pause];
    • 中止
      • [self.audioPlayer stop];
        • 中止某個音樂,下次再播放,會從當前位置開始播放
      • self.audioPlayer.currentTime = 0;
        • 重置當前播放時間
    • 快進
      • 系統已經對currentTime作了容錯處理,不用擔憂事件爲負數或者大於音樂總時長
      • self.audioPlayer.currentTime += 5;
    • 倍速播放
      • 1.0爲正常
      • 設置容許調整播放速率,注意,此方法必須設置在準備播放以前(經測試,在播放前也能夠)
      • self.audioPlayer = nil;
      • self.audioPlayer.enableRate = YES;
      • self.audioPlayer.rate = 2.0;
    • 音量調節
      • 音量調節範圍:0.0~1.0
      • self.audioPlayer.volume = slider.value;
    • 監聽播放事件
      • 設置代理
      • 實現代理方法
  4. 後臺播放
    • 注意:模擬器測試不許確,以真機爲準
    • 勾選後臺模式
    • 激活音頻播放會話
      • 在iOS中每一個應用都有一個音頻會話,這個會話就能夠經過AVAudioSessiion來表示
      • AVAudioSession一樣存在於AVFoundation框架中,它是單例模式設計,經過sharedInstance進行訪問
      • 音頻會話類型簡介
        • AVAudioSessionCategoryAmbient
          • 混音播放,能夠與其餘音頻應用同時播放
        • AVAudioSessionCategorySoloAmbient
          • 獨佔播放
        • AVAudioSessionCategoryPlayback
          • 後臺播放,也是獨佔的
        • AVAudioSessionCategoryRecord
          • 錄音模式,用於錄音時使用
        • AVAudioSessionCategoryPlayAndRecord
          • 播放和錄音,此時能夠錄音也能夠播放
        • AVAudioSessionCategoryProcessing
          • 硬件解碼音頻,此時不能播放和錄製
        • AVAudioSessionCategoryMultiRoute
          • 多種輸入輸出,例如能夠耳機/USB設備同時播放
    • 代碼實現
      • 獲取音頻會話
        • AVAudioSession *session = [AVAudioSession sharedInstace];
      • 設置會話分類
        • [session setCategory: AVAudioSessionCategoryPlayback error:nil];
      • 激活會話
        • [session setActive:YES error:nil];
  5. 代碼封裝重構(注意容錯處理)
    • 結合QQ音樂案例進行封裝
  6. 使用須知
    • 每個AVPlayer對象對應一個音頻播放,若是想播放多個音頻,就須要建立多個AVPlayer
    • 使用AVAudioPlayer類,只能播放本地資源,不能播放遠程音樂
  7. 測試環境
    • 後臺播放,須要使用真機進行測試,模擬器測試不許確

2.模仿QQ音樂

  1. 搭建項目結構
    • 劃分項目功能模塊,建立文件夾結構
      • 音樂列表
        • 主要負責展現音樂列表,當點擊某一個音樂時,就播放對應音樂,中止其餘音樂播放
      • 音樂詳情
        • 主要負責展現音樂詳情,包含音樂名稱/歌手/專輯圖片/歌詞/進度以及控制邏輯
    • 拖入必要的資源和工具類,以及第三方框架(可使用時再拖入)
    • 根據界面跳轉邏輯,搭建Storyboard,並建立好對應的控制器
      • 導航控制器爲初始控制器,其根控制器爲UITableViewController(QQ音樂列表控制器)
      • 當點擊QQ音樂列表控制器某一行時,跳轉到詳情控制愛UIViewController
  2. 實現音樂列表功能
    • 界面基本設置
      • 背景圖片
      • 隱藏導航欄
      • 狀態欄設置爲白色
    • 加載QQ列表數據
      • 經驗:千萬不要把獲取數據的實現邏輯寫在控制器中,不利於維護和重用,也不利於後期擴展
      • 建立數據模型
        • 根據音樂列表plist文件內容,建立對應的音樂數據模型xxxMusicModel
      • 建立數據操做工具類
        • 主要負責數據的獲取,和之後數據的操做
        • 此處提供,供外界調用的獲取數據的接口
        • 請使用block將數據傳遞出去,不要直接返回一個數組(由於後期若是改成從網絡獲取列表,由於網絡獲取數據是異步的,因此返回的結果可能爲nil)
        • 獲取全部音樂列表的接口以下:
          • getMusicModelsWithResultBlock:block
      • 在表格控制器內,調用數據操做類提供的接口,加載數據並顯示
    • 音樂列表界面展現
      • 使用自定義cell,以便後期擴充
    • 預留好對接接口
      • 經驗:知道到時候在哪裏調用真正的外接播放接口/中止接口,爲了統一管理
      • 播放接口
      • 中止播放接口
    • 實現音樂播放功能
      • 經驗:千萬不要把播放的業務實現邏輯直接寫在控制器裏面,應當抽取一個工具類
      • 高級經驗:針對於音樂播放功能,建議分爲兩層
        • 最底層負責單個音樂的播放/暫停/中止等操做
        • 上層則負責播放的業務邏輯,好比上一首/下一首/隨機播放/順序播放等
        • 這樣易於維護,重用和擴展
      • 封裝單個音樂文件操做的工具類(xxxAudioTool)
        • 接口1:根據音頻名稱播放音頻
          • playAudioWithName:
        • 接口2:暫停音頻
          • pauseCurrentAudio
        • 接口3:中止音頻
          • stopCurrentAudio
      • 封裝多個音樂文件操做的工具類(xxxMusicOperationTool)
        • 接口1:根據音樂數據模型,播放一首音樂
          • playMusicWithMusicModel:
        • 接口2:暫停當前音樂
          • pauseCurrentMusic
        • 接口3:中止當前音樂
          • stopCurrentMusic
      • 重要建議:
        • 將此工具類設計成爲一個單例
        • 由於會有不少界面使用,並且多個界面操做的數據一致
    • 功能測試
      • 在預留接口中,調用工具類的對應接口,而後測試
      • 音樂列表功能開發結束
  3. 詳情界面實現
    • 音樂詳情界面搭建
      1. 分析界面結構,選擇合適控件搭建界面
      2. 注意將同一組子控件使用一個父控件進行包裝,方便添加約束佈局
      3. 稍微很差構思的地方在於歌詞界面和專輯界面的切換,須要藉助UIScrollView
      4. 關聯屬性和方法到對應的詳情控制器,方便後續的動畫和賦值操做
    • 擴展音樂播放工具類接口,實現播放業務邏輯,並展現音樂詳情
      1. 擴展多個音樂操做的工具類(xxxMusicOperationTool)的上一首/下一首等接口
        • 接口1:播放上一首音樂
          • preMusic
        • 接口2:播放下一首音樂
          • nextMusic
      2. 在控制器對應的關聯方法中,調用不一樣的播放接口,進行測試
      3. 將須要展現的數據按"刷新頻率"進行分類,分別提供"單次刷新"和"實時刷新"方法
        • 須要根據不一樣的數據刷新頻率,採用不一樣的刷新策略
        • 若是實時刷新,就可使用NSTimer,使用定時任務不斷刷新,展現最新數據,好比播放進度,就須要不斷刷新
        • 而歌曲圖片和做者,只須要刷新一次
      4. 彙總全部須要刷新的字段,根據字段,建立歌曲播放信息數據模型(此數據模型由多個音樂操做的工具類同一提供)
        • 不要很是零散的單獨獲取,處處拼湊
        • 之因此由工具類統一提供歌曲播放信息數據模型,主要緣由
          • 由於此功能,應該劃分到此類的業務邏輯中
          • 只有這個類,最瞭解當前音樂的播放信息
      5. 直接從控制器預留的"單次刷新"和"實時刷新"刷新方法中,從多個音樂操做的工具類中獲取最新的音樂播放數據
    • 實時更新歌詞,並實現進度展現
      • 建立歌詞數據模型(xxxLrcModel)
        • 屬性列表
        • 每一句歌詞開始時間
          • @property (nonatomic, assign) double beginTime;
        • 每一句歌詞結束時間
          • @property (nonatomic, assign) double endTime;
        • 每一句歌詞的內容
          • @property (nonatomic, copy) NSString *lrcText;
      • 建立歌詞解析工具類(xxxLrcTool),負責解析不一樣歌曲對應的歌詞文件
        • 根據歌詞文件名稱,解析歌詞
          • getLrcModelsWithLrcName:
        • 根據某個時間點,獲取歌詞模型數組中對應的歌詞模型
          • getLrcModelInModels:withTime:
      • 使用UITableView展現歌詞
        • 單獨抽離一個控制器,負責管理歌詞
      • 根據當前播放進度,實時滾動切換歌詞
      • 根據每句歌詞的播放進度,經過顏色展現單句歌詞進度
        • 自定義集成自UILabel的子類
        • 重寫drawRect:方法
          • CGRect fillRect = CGRectMake(0,0,rect.size.width*self.progress,rect.size.height);
          • [[UIColor greenColor] set];
          • UIRectFillUsingBlendMode(fillRect,kCGBlendModeSourceIn);
  4. 後臺播放實現
    • 勾選後臺模式->音頻播放
    • 激活音頻播放會話
      • 獲取音頻會話
      • 設置會話分類
      • 激活會話
  5. 顯示鎖屏界面,並接收遠程事件
    • 顯示鎖屏信息
      • 獲取鎖屏信息中心
        • MPNowPlayingInfoCenter *playInfoCenter = [MPNowPlayingInfoCenter defaultCenter];
      • 建立鎖屏信息(信息從多音樂操做工具類中獲取,並保存到可變字典dic中)
      • 設置鎖屏信息
        • playInfoCenter.nowPlayingInfo = dic;
      • 接收遠程控制事件
        • [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
    • 接收遠程事件
      • 能夠監聽遠程事件的前提
        • 必須啓動遠程事件接收
        • 必須能夠成爲第一響應者
        • 應用程序必須是該事件的控制者
      • 在控制器中須要實現的方法
        • remoteControlReceivedWithEvent:
      • 補充:事件類型對應的含義
        • UIEventSubtypeNone
          • 不包含任何字事件類型
        • UIEventSubtypeMotionShake
          • 搖晃事件(從iOS3.0開始支持此事件)
        • 遠程控制自事件類型(從iOS4.0開始支持遠程控制事件)
        • UIEventSubtypeRemoteControlPlay
          • 播放事件(操做:停滯狀態下,按二級線控中間按鈕一下)
        • UIEventSubtypeRemoteControlPause
          • 暫停事件
        • UIEventSubtypeRemoteControlStop
          • 中止事件
        • UIEventSubtypeRemoteControlTogglePlayPause
          • 播放或暫停切換(操做:播放或暫停狀態下,按耳機線控中間按鈕一下)
        • UIEventSubtypeRemoteControlNextTrack
          • 下一曲(操做:按耳機線控中間按鈕兩下)
        • UIEventSubtypeRemoteControlPreviousTrack
          • 上一曲(操做:按耳機線控中間按鈕三下)
        • UIEventSubtypeRemoteControlBeginSeekingBackward
          • 快退開始(操做:按耳機線控中間按鈕三下不要鬆開)
        • UIEventSubtypeRemoteControlEndSeekingBackward
          • 快退中止(操做:按耳機線控中間按鈕三下到了快退的位置鬆開)
        • UIEventSubtypeRemoteControlBeginSeekingForward
          • 快進開始(操做:按耳機線控中間按鈕兩下不要鬆開)
        • UIEventSubtypeRemoteControlEndSeekingForward
          • 快進中止(操做:按耳機線控中間按鈕兩下到了快進的位置鬆開)
  6. 鎖屏界面顯示歌詞
    • 實現方案:利用鎖屏顯示圖片設置項,實時的將歌詞繪製到圖片上,組成一個新的圖片,設置爲鎖屏的圖片
    • 繪製步驟
      1. 開啓圖形上下文
      2. 繪製背景圖片
      3. 獲取歌詞信息,並繪製
      4. 從圖形上下文中獲取混合圖片
      5. 關閉圖形上下文
    • 注意:效率優化
  7. 功能完善,細節處理
    1. 經過進度條拖拽,控制播放進度
    2. 經過點擊進度條某個位置,控制播放進度
    3. 自動播放下一首
    4. 列表歌詞頁的歌詞進度展現
    5. iOS9.0新推出的Storyboard Reference

3.播放遠程音樂

  • 使用AVPlayer來播放遠程音樂
  • 方案1:
    • 根據URL,建立AVPlayer
      • self.player = [[AVPlayer alloc] initWithURL:remoteURL];
    • 播放
      • [self.player play];
  • 方案2:
    • 根據AVPlayerItem,建立AVPlayer
      • NSURL *remoteURL = [NSURL URLWithString:remoteURL];
      • AVPlayerItem *playerItem = [AVPlayerItem playerItemWihtURL:remoteURL];
      • self.player = [[AVPlayer alloc] initWithPlayerItem:playerItem];
    • 播放
      • [self.player play];
  • 方案對比
    • 若是經過方案1播放某個遠程音頻,那麼後面若是想要更改音樂,則須要從新建立AVPlayer對象
    • 方案2就能夠直接經過更改播放項來間接更換播放遠程音樂
相關文章
相關標籤/搜索