Blog

【創意編程】使用網頁讀取麥克風聲音

mic2vis

前陣子在兩廳院駐館的呈現中,我們嘗試使用網頁讀入環境的聲音,做為控制、觸發作品走向的條件。今天就來分享從網頁使用 Javascript 讀取麥克風聲音的簡單概念吧!

 

網頁難道一直在收音嗎?

回想一下,當你打開新下載的 APP ,有時會跳出「是否同意使用相簿」、「是否同意使用行事曆」或「是否同意使用麥克風」等各種詢問視窗。對網頁而言亦是如此:故事的起頭得從要求權限開始。

網頁跳出允許視窗

首先使用 WebRTC(Web Real-Time Communication)中的 API getUserMedia() 要求使用用戶裝置的音訊。在用戶點選同意後,API 會回傳一筆麥克風的資料(stream)。

const handleMic = (stream) => {
	// handle stream here
}
navigator.mediaDevices.getUserMedia({audio: true}).then(handleMic);

得到麥克風的資料以後,再使用 Web Audio API 來處理資料。

 

在網頁蓋一個聲音工廠

Web Audio API 是一套幫助開發者在網頁上操作與處理音訊的程式介面。要使用 Web Audio API,必須先創建一個 AudioContext。AudioContext 就像一座聲音工廠,這座工廠中有多個單位或設備協力產出目標產品(聲音或相關資料)。

// global variable
let AudioContext = window.AudioContext||window.webkitAudioContext;
let context = new AudioContext();

創立了聲音工廠(AudioContext)後,可以選擇適合的單位或設備,並因應需求設計操作與執行的步驟。在 Web Audio API 裡,每個單位及設備被稱作一個 AudioNode。由於今天的目的是讀取麥克風資料,我們使用 createMediaStreamSource()createAnalyser() 得到兩個需要的工廠單位(AudioContext): MediaStreamAudioSourceNodeAnalyserNode

// in Handle Mic function
microphone = context.createMediaStreamSource(stream);
analyser = context.createAnalyser();

其中,MediaStreamAudioSourceNode 是個音訊來源。在聲音工廠中,它負責接收工廠外部的物料,再將物料(音訊)傳遞給後續處理的單位。而 AnalyserNode 主責分析,它不改造與加工音訊,但能分析音訊、提供相關數據。

AnalyserNode 示意圖 ( 圖片來源:https://developer.mozilla.org/en-US/docs/Web/API/AnalyserNode ).

創造出工廠單位後,接著使用 connect() 函式建立溝通管道——讓接收物料的窗口把音訊傳遞給分析單位。

microphone.connect(analyser);

做到這裡,聲音工廠的大致架構就完成了!目前有了一個小工廠,單位部門、工作流程都設計妥當。除了還不會發生任何事。

 

所以我說那個數據呢?

最後階段是跟分析單位(AnalyserNode)要資料。AnalyserNode 可以提供即時的時域(time-domain)頻域(frequency-domain)數據。

在得到數據以前,我們需要先給定 AnalyserNode 的 fftSize。由於 fftSize 牽涉到域轉頻域的數學運算,這裡不多做解釋。只要先記得 fftSize 需要設定成 2 的倍數,數字越大,代表頻域的數據被切分得越細。選定 fftSize 後,創造一個長度為 frequencyBinCount (frequencyBinCount 是 fftSize 數量的一半)、空的 Uint8 陣列,作為未來讀取數據的容器。

接著,如果需要時域數據,可以使用:

analyser.getByteTimeDomainData(dataArray);

得到 dataArray 陣列中存著各個 frame 的音訊數值。

或在需要頻域時使用:

analyser.getByteFrequencyData(dataArray);

將各頻率區間的數值大小存入 dataArray 陣列。

如此一來,音訊數據到手,除了可以應用在視覺化上,也可以從陣列中提取其他資訊(音量、頻率⋯⋯)啦!更多 AnalyserNode 介紹可以參考:WebAudioApi Analysis and Visualization

Write a comment