圖解之 音頻)
第16章 HarmonyOs開發(fā)圖解之 音頻HarmonyOS 學(xué)習(xí)系統(tǒng) | 階段三高級深耕期學(xué)習(xí)目標(biāo)序號能力1理解音頻采樣的基本原理采樣率、位深度、聲道2掌握 AudioRenderer音頻播放和 AudioCapturer音頻采集的使用3能夠使用 SoundPlayer 播放短音效核心圖解內(nèi)容講解16.1 音頻基礎(chǔ)概念生活化類比音頻采樣就像電影膠片的幀聲音是連續(xù)的聲波就像連續(xù)的河流。我們無法記錄整條河流所以每隔一小段距離取一個(gè)水樣——這就是采樣。采樣率如 44100Hz就像每秒拍 44100 張照片的幀率幀率越高還原越精確。44100Hz 意味著每秒從聲波中取 44100 個(gè)快照。人耳能聽到 20Hz~20kHz 的聲音根據(jù)奈奎斯特定理采樣率至少要是最高頻率的 2 倍所以 44100Hz 能完美還原 22.05kHz 以下的聲音。PCM脈沖編碼調(diào)制就是把這些快照轉(zhuǎn)換成數(shù)字的過程。16.2 音頻播放 AudioRendererAudioRenderer 是 HarmonyOS 音頻播放的核心類支持流式播放模式邊讀邊播和靜態(tài)播放模式一次加載完整播放。// 初始化 AudioRendererAudioRendererInfoaudioRendererInfonewAudioRendererInfo.Builder().contentType(AudioRendererInfo.ContentType.CONTENT_TYPE_MUSIC).usage(AudioRendererInfo.StreamUsage.STREAM_USAGE_MUSIC).build();AudioRendereraudioRenderernewAudioRenderer(audioRendererInfo,PlayMode.MODE_STREAM);// 讀取音頻文件并播放在后臺線程中執(zhí)行g(shù)etGlobalTaskDispatcher(TaskPriority.DEFAULT).asyncDispatch(()-{InputStreamisgetResourceManager().getResource(MediaTable.INPUT);byte[]datanewbyte[4096];while(is.available()0){intreadLenis.read(data);audioRenderer.write(data,0,readLen);}audioRenderer.release();});// 控制播放audioRenderer.start();audioRenderer.pause();audioRenderer.stop();16.3 音頻采集 AudioCapturerAudioCapturer 用于從麥克風(fēng)采集音頻數(shù)據(jù)適合錄音、語音識別等場景。// 初始化 AudioCapturerAudioCapturerInfocapturerInfonewAudioCapturerInfo.Builder().contentType(AudioCapturerInfo.ContentType.CONTENT_TYPE_SPEECH).usage(AudioCapturerInfo.StreamUsage.STREAM_USAGE_VOICE_COMMUNICATION).build();AudioCaptureraudioCapturernewAudioCapturer(capturerInfo);// 讀取音頻數(shù)據(jù)audioCapturer.start();byte[]buffernewbyte[4096];while(isRecording){intreadLenaudioCapturer.read(buffer,0,buffer.length);// 處理采集到的音頻數(shù)據(jù)...}audioCapturer.release();16.4 短音效播放 SoundPlayerSoundPlayer 適合播放簡短的音效如按鈕點(diǎn)擊聲、通知聲資源占用更少。// 加載短音資源SoundPlayersoundPlayernewSoundPlayer(context);intsoundIdsoundPlayer.createSound(ResourceTable.Media_button_click);// 播放soundPlayer.play(soundId);// 釋放soundPlayer.release();代碼速查卡API功能示例new AudioRenderer(info, mode)創(chuàng)建音頻播放器new AudioRenderer(info, MODE_STREAM)write(byte[], offset, size)寫入音頻數(shù)據(jù)renderer.write(data, 0, len)start() / pause() / stop()控制播放狀態(tài)renderer.start()new AudioCapturer(info)創(chuàng)建音頻采集器new AudioCapturer(info)read(byte[], offset, size)讀取音頻數(shù)據(jù)capturer.read(buf, 0, buf.length)SoundPlayer.createSound(id)加載短音資源player.createSound(soundId)soundPlayer.play(soundId)播放短音player.play(soundId)getMinBufferSize(rate, fmt, mask)獲取最小緩沖區(qū)大小AudioRenderer.getMinBufferSize(44100, ...)與 Android/iOS 對比特性HarmonyOSAndroidiOS音頻播放AudioRendererAudioTrack / MediaPlayerAVAudioPlayer音頻采集AudioCapturerAudioRecordAVAudioEngine短音效SoundPlayerSoundPoolAudioServicesPlaySystemSound音頻焦點(diǎn)AudioManagerAudioManagerAVAudioSession采樣率配置AudioRendererInfo 中設(shè)置AudioFormat.BuilderAVAudioFormat?? 踩坑回憶錄為什么播放出來的聲音像滋滋電流聲因?yàn)椴蓸勇什黄ヅ湮以O(shè)置了 48000Hz 的 AudioRenderer但音頻文件本身是 44100Hz 的結(jié)果播放出來就像快進(jìn)的磁帶——聲音又快又尖。解決方案播放前先查詢音頻文件的實(shí)際采樣率然后讓 AudioRenderer 的采樣率與之匹配??梢杂肁udioManager.getDevices()查詢設(shè)備支持的格式和采樣率。另外AudioRenderer用完必須release()否則音頻焦點(diǎn)會被一直占用其他 App 就播放不了聲音了。我曾在調(diào)試時(shí)忘記 release結(jié)果整個(gè)手機(jī)的音效系統(tǒng)都啞了重啟才恢復(fù)。必做實(shí)操任務(wù)序號任務(wù)難度1實(shí)現(xiàn)一個(gè)簡單的音頻播放器支持播放/暫停/停止中2使用 AudioCapturer 錄制音頻并保存為 PCM 文件高3使用 SoundPlayer 為按鈕添加點(diǎn)擊音效低4查詢設(shè)備支持的音頻采樣率和格式低5實(shí)現(xiàn)一個(gè)錄音 回放的 Demo高學(xué)習(xí)檢查清單能解釋采樣率、位深度、聲道數(shù)的基本概念能使用 AudioRenderer 播放音頻文件能使用 AudioCapturer 錄制音頻知道為什么 AudioRenderer 采樣率必須與音頻文件匹配能使用 SoundPlayer 播放短音效能在后臺線程中執(zhí)行音頻讀寫操作知道為什么必須手動(dòng) release 音頻資源理解 MODE_STREAM 和 MODE_STATIC 的區(qū)別進(jìn)階方向結(jié)合第 17 章媒體會話實(shí)現(xiàn)后臺音樂播放并顯示系統(tǒng)通知欄控制學(xué)習(xí)音頻編解碼AAC、MP3實(shí)現(xiàn)格式轉(zhuǎn)換探索音頻可視化將音頻數(shù)據(jù)轉(zhuǎn)換為頻譜圖必須手動(dòng) release 音頻資源理解 MODE_STREAM 和 MODE_STATIC 的區(qū)別進(jìn)階方向結(jié)合第 17 章媒體會話實(shí)現(xiàn)后臺音樂播放并顯示系統(tǒng)通知欄控制學(xué)習(xí)音頻編解碼AAC、MP3實(shí)現(xiàn)格式轉(zhuǎn)換探索音頻可視化將音頻數(shù)據(jù)轉(zhuǎn)換為頻譜圖