#分享 關於「音樂與音訊工程」在網站開發上的實戰應用:Web Audio 多波形合成、即時轉調與「聲學頻譜可視化」
大家好!
想跟大家分享一個結合「數位樂器手動演奏」與「前端 Web Audio 實作」的個人專案。
先說結論:這是一個用左手+右手大拇指在手機螢幕上「純手工硬幹出來」的血汗結晶,也是一個探索前端音訊工程與數位訊號處理(DSP)的互動實驗室 😂。
🔗 線上互動體驗網址:
(建議使用電腦瀏覽體驗最佳;若用手機瀏覽請務必切換為響鈴模式,文末會說明原因!)
🌐 為什麼要在網頁上搞音樂?Web 開發中的音訊應用場景
在進入硬核採譜之前,先聊聊很多人好奇的問題:「學 Web 音訊處理能幹嘛?」
過去網頁音訊大多只是放個 <audio> 標籤播 MP3,但現代瀏覽器底層早就內建了具備專業錄音室等級的 Web Audio API,應用場景非常廣泛:
1. 網頁遊戲與互動娛樂(Web Games):不需載入笨重的大型音效檔,直接靠程式碼產生動態爆炸聲、打擊音效與空間 3D 環繞音(Spatial Audio)。
2. 微互動與使用者體驗(UI Micro-interactions):按鈕點擊、拖曳成功時的輕脆提示音,透過程式即時調配頻率與衰減,大幅增加操作體感。
3. 線上音樂教育與數位工作站(Web DAW / EdTech):像是 Soundtrap、BandLab,或是即時視唱練耳、互動指法教學工具。
4. 數據可視化與聲音化(Data Sonification):將股票走勢、地震波或科學數據轉換為聲音頻率,讓使用者「用聽的」感受數據變化。
這個專案,就是把瀏覽器當成一台可程式化的硬體合成器、頻譜分析儀與播放工作站!
🎶 Part 1:獵奇又跨界的龐大神曲庫(持續收錄中)
打開我的曲目清單,大家可能會以為走錯棚,因為題材跨度實在太大:
1. 港片殭屍情懷(林正英道長宇宙):
《一眉道人》、《殭屍先生》、《殭屍家族》(超催淚的溫馨小殭屍配樂)、《新殭屍先生》(沒錯,就是紅白雙煞迎親那段超詭異的《百鬼霧林》!)
2. 生活迷因與時代記憶:
全家便利商店進門新鈴聲、台灣路上每天都在聽的「資源回收車配樂」(其實是台語老歌《收酒矸》)、Samsung 經典手機鈴聲《Homecoming》。
3. 熱血特攝與經典動漫宇宙:
《鎧甲勇士》系列(光的戰役、戰鬥-通往勝利、帝皇再臨、不敗的英雄)、初代到令和的《超人力霸王》(迪卡、高斯、梅比斯、捷德等)、《忍風戰隊》、《假面騎士 Build》(Be The One)、《魔彈戰記龍劍道》、《灌籃高手》、《犬夜叉》。
清單裡目前收錄的 41 首曲目,全部是我戴著耳機聽音抓歌(耳コピ採譜),完全沒有用網路上現成的死板 MIDI,而是純靠兩隻大拇指在手機 Perfect Piano 上一鍵一鍵彈奏錄製成 MIDI,再用原生 JavaScript、@tonejs/midi 與 Tone.js 架構刻出來的互動網頁!
🎹 Part 2:設備受限下的「雙拇指極限挑戰」
其實,如果有條件的話,最完美的做法是外接一台具備 MIDI 錄製功能的實體電子鋼琴。實體琴鍵完全符合人體工學,能靠十根手指靈活彈奏,不僅能同時兼顧複雜的多指和弦與飽滿的低音伴奏,演奏時的手感也流暢得多。
但殘酷的現實是——我家裡根本沒有那種昂貴的實體電鋼琴 🥲。
沒有實體樂器,就只能靠手邊現有的工具硬上!我只能在手機小小的螢幕上,完全依賴「左手大拇指+右手大拇指」在 Perfect Piano 上一鍵一鍵敲出來:
1. 配樂不得不單純化:手指數量有限,無法像十指連彈那樣鋪出華麗的多聲部對位伴奏,只能將重心放在精準的主旋律與核心節奏上。
2. 高速曲目的手指抽筋地獄:要在玻璃小螢幕上用兩隻拇指彈奏 BPM 130 以上的曲子(像《假面騎士 Build》或《龍劍道》),鍵位密密麻麻,黑白鍵交錯極容易按錯,手指真的彈到快抽筋!
但也正是因為這個硬體限制,逼出了一個工程師的硬核解法:
既然手指在手機黑白鍵上轉不過來,那我何不把曲子全部先改編成最順手、只有白鍵的 C 大調來彈奏錄製,到了網頁端,再靠自己寫的演算法幫聽眾即時還原成原曲調性?
💡 Part 3:JavaScript 轉調演算法怎麼做?
在 MIDI 數位通訊協定中,每個音高都是一個 0~127 的整數(例如中央 C,即 C4 是 60)。
轉調的本質,在程式底層其實就是純量數學加減:
const targetMidiNote = note.midi + transpose;
synth.triggerAttackRelease(
Tone.Frequency(targetMidiNote, "midi"),
event.duration,
time,
event.velocity
);
例如《不敗的英雄》原曲是 B 大調,我在手機上用雙拇指錄製時,先用最好按的 C 大調(60)錄音;到了網頁上,使用者只要在選單切換 -1,音訊引擎就會在發聲瞬間換算成對應的物理頻率(Hz),完美還原原曲調性!
這就是程式設計的魅力:當硬體設備有限制時,就用演算法把它補回來!
🤔 Part 4:聲學物理冷知識:為什麼要選「-1」,千萬不能選「+11」?
在純樂理計算上,「降 1 個半音(-1)」和「升 11 個半音(+11)」,算出來的音名都是 B。
但如果你真的在程式裡把音符 +11,聽覺上會發生災難性的音域暴走失真(Octave Displacement)!
如果選 +11:等於把整首歌往上硬拔了接近一個完整的八度,原本在中低音區熱血沉穩的英雄戰鬥曲,瞬間變成尖銳刺耳的蚊子叫。
改選 -1:音符僅向下微幅平移半音,牢牢鎖在原本演奏的同一個八度區間,保留飽滿的基頻。
這是我在寫這個專案時深刻體會到的一點:數學上的等價,不等於聲學物理與人耳體感上的等價!
🔊 Part 5:波形合成(Oscillator)與 ADSR 包絡線
除了轉調,我還加入了 4 種基礎振盪器(Oscillator)波形切換,讓網頁透過計算產生不同音色:
1. 圓潤鋼琴風 (Triangle):三角波諧波衰減快,搭配短 Attack、長 Release 的包絡線,模擬實體打擊樂器的餘音。
2. 明亮電子琴 (Sawtooth):鋸齒波包含豐富連續諧波,一秒還原昭和特攝的復古電子合成器感!
3. 復古 8-bit (Square):方波滿滿奇數諧波,秒回紅白機時代。
4. 柔和純音 (Sine):乾淨平滑的正弦波。
📊 Part 6:聲學數據可視化與時間軸排程控制
為了讓使用者在聆聽時不只是被動接收聲音,專案中實作了雙畫布的可視化與完整的播放控制引擎:
1. 示波器波形圖(Tone.Waveform):
以每秒數十次的頻率採樣時域振幅(-1.0 ~ 1.0),透過 Canvas 2D 即時繪製。切換鋸齒波或方波時,畫面上會直接跳出對應的物理幾何稜角!
2. 頻譜分析儀(Tone.FFT):
透過快速傅立葉變換將訊號拆解為頻率能量分貝值(dB),線性歸一化渲染出跳動的能量柱。重低音撞擊與高音泛音的能量分佈一目了然。
3. Tone.Transport 與 Tone.Part 時間軸控制:
為了避免將音符直接死鎖在硬體時鐘上,我將 MIDI 數據封裝進 Tone.Part,並由 Tone.Transport 全域時鐘統一排程。支援播放、暫停、停止、以及任意拖曳進度條(Seek),隨時跳轉到想聽的段落且不漏拍。
📱 Part 7:行動端踩坑血淚(iOS 實體靜音鍵之謎)
做完丟到手機上測試時,我一度懷疑人生:「為什麼手機上播完全沒聲音?但電腦上好好的?」
最後查底層規範才抓到兇手:
在 iOS(Safari / WebKit)的機制中,網頁端使用 AudioContext 即時合成的聲音,預設被歸類在 Ambient(環境音) 類別。
當你的 iPhone 側邊撥動開關切在「靜音模式」時,系統為了不打擾使用者,會硬生生攔截所有 Ambient 音訊輸出(這就是為什麼 YouTube 影片有聲音,但很多網頁遊戲會沒聲音的原因)!
因此,手機瀏覽時記得一定要切換成響鈴模式喔!
🛠️ 結語與心得
這個專案結合了耳聽採譜、手機拇指體感彈奏、MIDI 數據解析、AudioContext 時間軸排程校準,到前端音訊物理特性的控制與 Canvas 聲學可視化。
雖然沒有專業的實體電鋼琴與十指連彈的華麗伴奏,但在受限的環境下用兩根手指硬幹出來的旋律,再搭配程式演算法去克服痛點,整個過程讓我更深刻體會到科技與音樂交織的樂趣。
網頁前端遠不只是排版與打 API,透過 Web Audio API,瀏覽器完全有能力成為強大的音訊處理工作站。每一首親手彈出的音符,搭配程式碼的即時運算,讓科技與音樂產生了最純粹的共鳴。
大家平常寫 Web 或 Side Project 時,也嘗試過將音樂、聲音或可視化元素整合進自己的專案中嗎?歡迎一起在留言區交流討論!


