音頻播放(iOS開發)
音頻處理
一.錄音
- 錄音應用場景
- 錄音功能實現
- 導入AVFoundation框架
- 做用:一些多媒體的處理,基本上都是用這個框架
- #import <AVFoundation/AVFoundation.h>
- 使用AVAudioRecorder進行錄音
- 建立錄音文件存放路徑
- 設置錄音附加設置項
- #import <AVFoundation/AVAudioSettings.h>
- 錄音參數設置,保存到字典中,不須要掌握,固定的設置
- 設置編碼格式:AVFormatIDKey
- 採樣率:AVSampleRateKey
- 通道數:AVNumberOfChannelsKey
- 音頻質量,採樣質量:AVEncoderAudioQualityKey
- 根據路徑以及設置項,建立錄音對象
- _audioRecorder = [[AVAudioRecorder alloc] initWithURL:url settings:recordSettings error:nil];
- 準備錄音
- [self.audioRecorder prepareToRecord];
- 開始錄音
- [self.audioRecorder record];
- 中止錄音
- [self.audioRecorder stop];
- 概念補充
- 編碼
- 概念:編碼是信息從一種形式轉換爲另外一種形式的過程
- 編碼格式:
- 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
- 開發經驗
- caf文件格式,由於某些編碼設置,文件可能會很大,並且caf格式並非很通用,因此在開發過程當中,通常會進行壓縮轉碼爲MP3格式
- lame靜態庫
- 簡介
- LAME是一個開源的MP3音頻壓縮軟件
- LAME是一個遞歸縮寫,來自LAME Ain't an MP3 Encoder(LAME不是MP3編碼器)
- 它自1998年以來由一個開源社區開發,目前是公認有損品質MP3中壓縮效果最好的編碼器
- 提高權限
- 下載lame的最新版本並解壓
- http://sourceforge.net/projects/lame/files/lame/3.99/
- 生成靜態庫
- 下載build的腳本
- https://github.com/kewlbear/lame-ios-build
- 修改腳本權限(全部人有可執行權限)
- 執行腳本
- 導入靜態庫到工程,開始使用
- 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,開始播放音效
- 根據音效文件,生成SystemSoundID
- 獲取URL
- CFURLRef urlRef = (__bridge CFURLRef)([[NSBundle mainBundle] URLForResource:@"m_16.wav" withExtension:nil]);
- 建立保存soundID的變量
- 經過URL和SoundID的地址,接收對應的音效SoundID
- AudioServicesCreateSystemSoundID(urlRef, &soundID);
- 播放音效
- AudioServicesPlaySystemSound(soundID);
- AudioServicesPlayAlertSound(soundID);
- AudioServicesPlaySystemSoundWithCompletion(soundID,block);
- 根據SoundID釋放內存
- AudioServicesDisposeSystemSoundID(soundID);
- 代碼優化,播放工具類的封裝
- 優化SoundID的生成,不須要每次都建立一遍
- 封裝播放邏輯,供多處調用
三.音樂播放
1.音樂播放
- 導入AVFoundation框架
- 使用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 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;
- 監聽播放事件
- 後臺播放
- 注意:模擬器測試不許確,以真機爲準
- 勾選後臺模式
- 激活音頻播放會話
- 在iOS中每一個應用都有一個音頻會話,這個會話就能夠經過AVAudioSessiion來表示
- AVAudioSession一樣存在於AVFoundation框架中,它是單例模式設計,經過sharedInstance進行訪問
- 音頻會話類型簡介
- AVAudioSessionCategoryAmbient
- AVAudioSessionCategorySoloAmbient
- AVAudioSessionCategoryPlayback
- AVAudioSessionCategoryRecord
- AVAudioSessionCategoryPlayAndRecord
- AVAudioSessionCategoryProcessing
- AVAudioSessionCategoryMultiRoute
- 代碼實現
- 獲取音頻會話
- AVAudioSession *session = [AVAudioSession sharedInstace];
- 設置會話分類
- [session setCategory: AVAudioSessionCategoryPlayback error:nil];
- 激活會話
- [session setActive:YES error:nil];
- 代碼封裝重構(注意容錯處理)
- 使用須知
- 每個AVPlayer對象對應一個音頻播放,若是想播放多個音頻,就須要建立多個AVPlayer
- 使用AVAudioPlayer類,只能播放本地資源,不能播放遠程音樂
- 測試環境
2.模仿QQ音樂
- 搭建項目結構
- 劃分項目功能模塊,建立文件夾結構
- 音樂列表
- 主要負責展現音樂列表,當點擊某一個音樂時,就播放對應音樂,中止其餘音樂播放
- 音樂詳情
- 主要負責展現音樂詳情,包含音樂名稱/歌手/專輯圖片/歌詞/進度以及控制邏輯
- 拖入必要的資源和工具類,以及第三方框架(可使用時再拖入)
- 根據界面跳轉邏輯,搭建Storyboard,並建立好對應的控制器
- 導航控制器爲初始控制器,其根控制器爲UITableViewController(QQ音樂列表控制器)
- 當點擊QQ音樂列表控制器某一行時,跳轉到詳情控制愛UIViewController
- 實現音樂列表功能
- 界面基本設置
- 加載QQ列表數據
- 經驗:千萬不要把獲取數據的實現邏輯寫在控制器中,不利於維護和重用,也不利於後期擴展
- 建立數據模型
- 根據音樂列表plist文件內容,建立對應的音樂數據模型xxxMusicModel
- 建立數據操做工具類
- 主要負責數據的獲取,和之後數據的操做
- 此處提供,供外界調用的獲取數據的接口
- 請使用block將數據傳遞出去,不要直接返回一個數組(由於後期若是改成從網絡獲取列表,由於網絡獲取數據是異步的,因此返回的結果可能爲nil)
- 獲取全部音樂列表的接口以下:
- getMusicModelsWithResultBlock:block
- 在表格控制器內,調用數據操做類提供的接口,加載數據並顯示
- 音樂列表界面展現
- 預留好對接接口
- 經驗:知道到時候在哪裏調用真正的外接播放接口/中止接口,爲了統一管理
- 播放接口
- 中止播放接口
- 實現音樂播放功能
- 經驗:千萬不要把播放的業務實現邏輯直接寫在控制器裏面,應當抽取一個工具類
- 高級經驗:針對於音樂播放功能,建議分爲兩層
- 最底層負責單個音樂的播放/暫停/中止等操做
- 上層則負責播放的業務邏輯,好比上一首/下一首/隨機播放/順序播放等
- 這樣易於維護,重用和擴展
- 封裝單個音樂文件操做的工具類(xxxAudioTool)
- 接口1:根據音頻名稱播放音頻
- 接口2:暫停音頻
- 接口3:中止音頻
- 封裝多個音樂文件操做的工具類(xxxMusicOperationTool)
- 接口1:根據音樂數據模型,播放一首音樂
- 接口2:暫停當前音樂
- 接口3:中止當前音樂
- 重要建議:
- 將此工具類設計成爲一個單例
- 由於會有不少界面使用,並且多個界面操做的數據一致
- 功能測試
- 在預留接口中,調用工具類的對應接口,而後測試
- 音樂列表功能開發結束
- 詳情界面實現
- 音樂詳情界面搭建
- 分析界面結構,選擇合適控件搭建界面
- 注意將同一組子控件使用一個父控件進行包裝,方便添加約束佈局
- 稍微很差構思的地方在於歌詞界面和專輯界面的切換,須要藉助UIScrollView
- 關聯屬性和方法到對應的詳情控制器,方便後續的動畫和賦值操做
- 擴展音樂播放工具類接口,實現播放業務邏輯,並展現音樂詳情
- 擴展多個音樂操做的工具類(xxxMusicOperationTool)的上一首/下一首等接口
- 在控制器對應的關聯方法中,調用不一樣的播放接口,進行測試
- 將須要展現的數據按"刷新頻率"進行分類,分別提供"單次刷新"和"實時刷新"方法
- 須要根據不一樣的數據刷新頻率,採用不一樣的刷新策略
- 若是實時刷新,就可使用NSTimer,使用定時任務不斷刷新,展現最新數據,好比播放進度,就須要不斷刷新
- 而歌曲圖片和做者,只須要刷新一次
- 彙總全部須要刷新的字段,根據字段,建立歌曲播放信息數據模型(此數據模型由多個音樂操做的工具類同一提供)
- 不要很是零散的單獨獲取,處處拼湊
- 之因此由工具類統一提供歌曲播放信息數據模型,主要緣由
- 由於此功能,應該劃分到此類的業務邏輯中
- 只有這個類,最瞭解當前音樂的播放信息
- 直接從控制器預留的"單次刷新"和"實時刷新"刷新方法中,從多個音樂操做的工具類中獲取最新的音樂播放數據
- 實時更新歌詞,並實現進度展現
- 建立歌詞數據模型(xxxLrcModel)
- 屬性列表
- 每一句歌詞開始時間
- @property (nonatomic, assign) double beginTime;
- 每一句歌詞結束時間
- @property (nonatomic, assign) double endTime;
- 每一句歌詞的內容
- @property (nonatomic, copy) NSString *lrcText;
- 建立歌詞解析工具類(xxxLrcTool),負責解析不一樣歌曲對應的歌詞文件
- 根據歌詞文件名稱,解析歌詞
- 根據某個時間點,獲取歌詞模型數組中對應的歌詞模型
- getLrcModelInModels:withTime:
- 使用UITableView展現歌詞
- 根據當前播放進度,實時滾動切換歌詞
- 根據每句歌詞的播放進度,經過顏色展現單句歌詞進度
- 自定義集成自UILabel的子類
- 重寫drawRect:方法
- CGRect fillRect = CGRectMake(0,0,rect.size.width*self.progress,rect.size.height);
- [[UIColor greenColor] set];
- UIRectFillUsingBlendMode(fillRect,kCGBlendModeSourceIn);
- 後臺播放實現
- 顯示鎖屏界面,並接收遠程事件
- 顯示鎖屏信息
- 獲取鎖屏信息中心
- MPNowPlayingInfoCenter *playInfoCenter = [MPNowPlayingInfoCenter defaultCenter];
- 建立鎖屏信息(信息從多音樂操做工具類中獲取,並保存到可變字典dic中)
- 設置鎖屏信息
- playInfoCenter.nowPlayingInfo = dic;
- 接收遠程控制事件
- [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
- 接收遠程事件
- 能夠監聽遠程事件的前提
- 必須啓動遠程事件接收
- 必須能夠成爲第一響應者
- 應用程序必須是該事件的控制者
- 在控制器中須要實現的方法
- remoteControlReceivedWithEvent:
- 補充:事件類型對應的含義
- UIEventSubtypeNone
- UIEventSubtypeMotionShake
- 遠程控制自事件類型(從iOS4.0開始支持遠程控制事件)
- UIEventSubtypeRemoteControlPlay
- 播放事件(操做:停滯狀態下,按二級線控中間按鈕一下)
- UIEventSubtypeRemoteControlPause
- UIEventSubtypeRemoteControlStop
- UIEventSubtypeRemoteControlTogglePlayPause
- 播放或暫停切換(操做:播放或暫停狀態下,按耳機線控中間按鈕一下)
- UIEventSubtypeRemoteControlNextTrack
- UIEventSubtypeRemoteControlPreviousTrack
- UIEventSubtypeRemoteControlBeginSeekingBackward
- UIEventSubtypeRemoteControlEndSeekingBackward
- 快退中止(操做:按耳機線控中間按鈕三下到了快退的位置鬆開)
- UIEventSubtypeRemoteControlBeginSeekingForward
- UIEventSubtypeRemoteControlEndSeekingForward
- 快進中止(操做:按耳機線控中間按鈕兩下到了快進的位置鬆開)
- 鎖屏界面顯示歌詞
- 實現方案:利用鎖屏顯示圖片設置項,實時的將歌詞繪製到圖片上,組成一個新的圖片,設置爲鎖屏的圖片
- 繪製步驟
- 開啓圖形上下文
- 繪製背景圖片
- 獲取歌詞信息,並繪製
- 從圖形上下文中獲取混合圖片
- 關閉圖形上下文
- 注意:效率優化
- 功能完善,細節處理
- 經過進度條拖拽,控制播放進度
- 經過點擊進度條某個位置,控制播放進度
- 自動播放下一首
- 列表歌詞頁的歌詞進度展現
- iOS9.0新推出的Storyboard Reference
3.播放遠程音樂
- 使用AVPlayer來播放遠程音樂
- 方案1:
- 根據URL,建立AVPlayer
- self.player = [[AVPlayer alloc] initWithURL:remoteURL];
- 播放
- 方案2:
- 根據AVPlayerItem,建立AVPlayer
- NSURL *remoteURL = [NSURL URLWithString:remoteURL];
- AVPlayerItem *playerItem = [AVPlayerItem playerItemWihtURL:remoteURL];
- self.player = [[AVPlayer alloc] initWithPlayerItem:playerItem];
- 播放
- 方案對比
- 若是經過方案1播放某個遠程音頻,那麼後面若是想要更改音樂,則須要從新建立AVPlayer對象
- 方案2就能夠直接經過更改播放項來間接更換播放遠程音樂
歡迎關注本站公眾號,獲取更多信息