生命的伊始,嬰兒用明亮的哭聲宣告一個新生命的誕生,睜開雙眼之前,一雙小耳朵已經開始聆聽這個世界。在如今的用戶體驗領域,幾乎所有公司都會有視覺設計師,卻鮮有注重聽覺交互的公司。隨着各大廠商對HTML5支持的日漸完善,前端工程師其實早已可以擺弄各種音波,讓復合型開發走得更遠。
聲波是一種機械波,通過波的物理屬性我們可以做很多事情。比如,利用聲波的頻率編碼進行數據傳遞,分析頻域或者時域的數據進行可視化應用,或者結合光波的特性做些視聽聯動。通過HTML5中的Web Auido規范,以上所有都能實現。我在自己的github里面建立了一個項目,整理了之前寫的一些web audio相關的東西,歡迎互相學習交流。
千里之行始於足下,這系列的開篇,我會從基本的如何使用HTML5發出do,ri,mi開始。
所謂的音樂是由時值和音高組成,這里每一個音高都有自己頻率。在web audio中,可以通過oscillator節點,產生指定頻率的聲音。代碼如下:
1 var context = new webkitAudioContext(), 2 osc = context.createOscillator(); 3 osc.frequency.value = 440; 4 osc.connect(context.destination); 5 osc.start(0);
通過osc對象frequency屬性的value值,上面的代碼產生了一個440HZ的音。運行代碼瀏覽器就會持續發出440HZ的音,在12平均律中這就是A1的音高。有了這個基准音,我們就能推斷出其他音的頻率,讓瀏覽器發出不同音高的聲音。至於各中關系,就需要首先介紹一下12平均律。
在樂理中,每組音由12個音組成,音名分別是C,C#,D,D#,E,F,F#,G,G#,A,A#,B,每2個音之間相差半個音程,同時每相鄰半音的頻率比值為2^(1/12)。B之后就是C,進入下一個循環,A1就是小字1組中A的頻率值。根據半音頻率的比值,小字1組中A#的頻率就是440*2^(1/12) HZ。
因為這些音的音高是一定的,且數量有限,所以我們可以預先計算出這些音對應的頻率值並儲存起來,避免重復計算。讀者可根據個人需要決定要初始化的音高數目。
var MusicalAlphabet = ['C','C#','D','D#','E','F','F#','G','G#','A','A#','B'], freqChat={}, freqRange=3,//C1-B3 i,j,base; for(i=1;i<freqRange;i++){ freqChat[i]={}; base = (i-1)*12; for(j=0;j<12;j++){ //A1=440 freqChat[i][MusicalAlphabet[j]]=440*Math.pow(2,(base+j-9)/12); } }
在自然C大調中,我們選取C,D,E,F,G,A,B構成一組音。其唱名便對應do,ri,mi,fa,so,la,si。音高只和音名對應,和唱名無關。有了各音高的頻率,我們可以很方便地初始化各種調式,不懂音律的同學可以自行搜索學習。
有了音高,接下來需要學習的就是時值了。要控制一個音符發聲的長短,最直接的方法就是調用oscillator節點start和end方法。代碼如下:
1 var context = new webkitAudioContext(); 2 var osc = context.createOscillator(); 3 osc.frequency.value = 440; 4 osc.connect(context.destination); 5 var _c = context.currentTime; 6 osc.start(_c); 7 osc.stop(_c+1);
需要注意的是,web audio有自己的時間軸,通過context對象的currentTime屬性可以獲取當前時間。根據W3C規范,這是一個只讀的屬性。oscillator的start和end方法的參數都是double型,所以這里 osc.stop(_c+1)表示的是在當前時間1秒后停止。常見的節拍器上的數字,表示的是一分鍾多少拍,這里簡單除下就可以得出各個每一拍的物理時間了。
有了最基本的音高和時值,我們就可以動手寫寫最簡單的譜子了。當然,滑音、顫音、推弦等演奏技巧,失真、混響等效果還需要別的web audio節點的輔助才能完成,這些節點以及開篇講到的一些技術我都會在以后的博文中慢慢講述。