終於有幸把 AudioContext 玩個了遍,JS 原來能對一個個音訊取資料外,還能把他們修改再丟出去,實現變聲器的效果!不過取到的資料到底是什麼,頻率啊 FFT 格式,我真心看不懂了 QAQ
但稍稍地提升了雀躍程度!(跳
以下是隨筆,稍微紀錄一下。
https://ithelp.ithome.com.tw/articles/10200609
MediaDevices 是一個物件,可以取得與本機連結的麥克風、鏡頭、甚至螢幕等裝置。方法:ondevicechange, enumerateDevices(), getUserMedia()enumerateDevices(): 列舉 devices 如 audioinput、audiooutput、videoinput 等getUserMedia(): 從裝置取得資料並轉為指定格式的 MediaStream
MediaStream 是一個表示影音串流的物件,其包含了零至數個 MediaStreamTrack (影音軌),每個 MediaStreamTrack 包含一至數個 Channel (聲道)。eg. [getUserMedia] ==> MediaStream ==> [<audio>, <video>]
- 一首歌曲存放於 MediaStream
- 有人聲、吉他、鋼琴三種聲音,分別是三個 MediaStreamTrack
- 人聲是 Stereo 立體聲道 (2 Channels)、吉他鋼琴是 Mono 單聲道 (分別 1 Channel)
方法:addTrack(), removeTrack(), getTracks() …
https://developer.mozilla.org/zh-CN/docs/Web/API/AudioContext
AudioContext 可以想像成是音頻的容器,由很多模組和節點(AudioNode)組成。
- AudioContext.createMediaElementSource()透過 HTML 元素來獲取(<audio>, <video>)
- AudioContext.createMediaStreamSource()透過串流媒體來獲取(如麥克風)
- AudioContext.createScriptProcessor()https://ithelp.ithome.com.tw/articles/10206210?sc=iThelpR
- 讓使用者可以透過 Javascript 對音樂訊號做進一步處理的節點。
- bufferSize:處理節點內的 Buffer 大小
- input:可輸入的頻道數
- ouput:輸出的頻道數
- 建構出來的實例只有一個監聽事件的方法:onaudioprocess()
AudioNode
- AudioNode.connect(AudioParam)節點可以連結到其他節點或參數。
https://www.oxxostudio.tw/articles/201601/web-audio-api-Analyser.html
AnalyserNode 賦予節點提供即時的訊息,可以獲取生成數據,以視覺化資料。
- AnalyserNode.fftSize一個二進位值,FFT (快速傅立葉轉換) 的大小
- AnalyserNode.frequencyBinCountfftSize 的一半,通常用來視覺化的資料數量
- AnalyserNode.getByteFrequencyData()將當前頻域數據拷貝進Uint8Array數組(無符號字節數組)(Unit8Array = 8bit 2次方長度陣列)
HTMLMediaElement.setSinkId(deviceId)https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/setSinkIdhttps://guidou.github.io/setsinkid-demo.html
可以改變 audio / video 的 output device需考慮:
- 裝置 ID 是否有對應
- 是否向使用者取得授權 (getUserMedia audio)
難題:圖中有兩個功能
- 切換裝置
- 將 audio 建立 audioContext,並將聲音數據視覺化
一進到頁面就會自動播放音樂,並將數據視覺化。
- 切換裝置時,如果沒有將 audio 及 audioContext 重置,會拋出 abortError 錯誤
- 重置時需注意,若 <audio> 已經連結,則無法再次使用。(有人說是 chrome 的 issue)this.audioContext.createMediaElementSource(this.$refs.audioMusic);
Uncaught DOMException: Failed to execute ‘createMediaElementSource’ on ‘AudioContext’: HTMLMediaElement already connected previously to a different MediaElementSourceNode. - 避免上述情況,採用 v-if 讓 element 重置,但仍無法正常切換裝置..(若沒有視覺化繪圖則可以正確切換)