2019/04/09 – AudioContext

終於有幸把 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)

難題:圖中有兩個功能

  1. 切換裝置
  2. 將 audio 建立 audioContext,並將聲音數據視覺化

一進到頁面就會自動播放音樂,並將數據視覺化。

  1. 切換裝置時,如果沒有將 audio 及 audioContext 重置,會拋出 abortError 錯誤
  2. 重置時需注意,若 <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.
  3. 避免上述情況,採用 v-if 讓 element 重置,但仍無法正常切換裝置..(若沒有視覺化繪圖則可以正確切換)

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *