2010年9月16日 星期四

FlashPlayer10 SampleDataEvent的音調及音色


大家都知道FlashPlayer10開始可以利用SampleDataEvent事件來產生8-bit的聲音。
雖然我相信真的會去發出8-bit聲音的機會很低(因為真的很難聽),但還是記錄一下如何抓取音程及改變音色。

大略講一下聲音跟波的概念。
基本上音調的高低是由聲音的頻率所決定的,即使是不同的東西振盪空氣造成不同的聲波,只要它們的頻率是一樣的,那麼聽起來也許音色不同,但會是同一個音調,頻率越大音調就越高越尖,頻率越短則音調就越低越沉。
而聲音的大小則是由振幅所決定的,振幅越大聲音就越大聲。
至於聲音的音色則是由波形來決定的。
以一個正弦波來講的話,X軸的部份當波形再次重覆時這段距離是波長,頻率基本上跟波長是倒數,頻率越大波長越短,Y軸的大小就是振幅,它的形狀就是它的波形。




大概就是這樣,接下來就講一下怎麼把音階給抓出來。
一般我們使用樂器時,跟普遍大家唱歌習慣直接用Do(音名C)來抓第一個音是不太一樣的,通常在幫一個樂器調音時應該都是從基準音A(唱名是La)來調音,A的頻率剛好是440Hz,但一些古典樂器,例如小提琴的話,它們的A是442Hz而不是440Hz,但基本上差異不大,所以還是先用440Hz來寫。
而,一個八度的音,剛好也是相差440Hz,也就是說「A」跟「高音A」的頻率剛好分別是440Hz及880Hz。
但是這所謂的八度音並不是平均分配在440~880之間,而且八度音不是真的只有八個音,應該拆成半音來看。


看一下鋼琴琴鍵就比較容易瞭解,在一個八度裡其實一共有12個半音(白鍵加黑鍵),並不是每兩個音之間都是全音,例如E跟F就是半個音程而已,也就是說升E就等於F,降F也等於E,B跟C之間也是半個音程,所以全部才會是12個半音不是14個。
而每個半音之間的頻率則是「等比數列」不是「等差數列」,因此我們要先算出這個等比數列的公比值是多少,例如A要升12個半音才會到達高音A,因此就等於440Hz要承上12次的公比才會到達880Hz:
440x(公比的12次方) = 880

公比真正的值並沒有必要算出來,我們只要知道這個關係就好。
從這個關係我們就可以得到每個音階的頻率了。
例如我們要知道Do(音名為C)的頻率,C比A還低音,跟C差了一共9個半音,因此C的頻率應該是:
440 * Math.pow(2, -9 / 12) = 261.6255653005986
其它的音就依此類推。

這樣就可以把所有的音程全部推算出來並放出聲音來了:


至於音色,就是由波形決定了,只要頻率不變,音色隨便怎麼變都可以。
上面的例子是以一個標準的正弦波所發出的,有興趣的自己可以套入不同的波形試試看。
我這邊寫了一個範例隨便亂搞波形弄了兩個音色出來。(都很難聽)
要記得,因為是8-bit的聲音,想要弄得像mp3一樣的音色是不太可能的,所以玩玩就好。

Demo在這邊,只弄了一個八度,按住對映的琴鍵播放,放開就停止:

1 則留言:

  1. good article ~~
    it good to make music related application~
    at least no need to make any mp3 into the library

    http://littleshell-multimedia.blogspot.com

    回覆刪除