所以說...
啊,不是雙聲道問題
1760Hz確實是440Hz的4倍
不過若把
var multiplier = 2.0 * Math.PI / sampleFrequency;
改成
var multiplier = 8.0 * Math.PI / sampleFrequency;
聽起來的結果也不像440Hz
也許是這邊也要改吧
dv.setInt8(i,dv.getInt8(i)+volume * Math.sin(i * multiplier * 440.0));
嗯...
這樣改就行了
我是沒想清楚為何要這樣改
因為理論上2PI弳才是一圈啊
雖然是在取樣率11025的時候才2PI弳
var sampleFrequency = 44100;
var multiplier = 0.5 * Math.PI / sampleFrequency;
var volume = 12;
for(var i=76;i<data.target.result.byteLength;i++)
{
dv.setInt8(i,128);
}
for(var i=76;i<data.target.result.byteLength;i++)
{
dv.setInt8(i,dv.getInt8(i)+volume * Math.sin(i * multiplier * 440.0));
}
聽起來就像La第四個八度 (440Hz理論上是La的第四個八度)多了
雖然還是跟振盪器產生的聲音不同
不過這樣還算可以接受啦!!
(嗯,聲音為何會不同呢?我想到原因是我的正弦波沒振盪器的標準這樣!!)
明天再處理任意音符的和弦
其實和弦照著StackOverflow上那篇疊加上去即可
只是我目前還不太清楚要怎麼處理La以外的音
(理論上若不知道Hz,要開12次方根來乘
效果不確定好不好)
(嗯,波形太純粹的聲音感覺真的不太好聽!!)
-------------10/23-------------------
想了一陣子
還是不知道為何聲音跟振盪器的不同
算了,反正我也不是要用振盪器的聲音
但是知道為何分母是四倍,不能把分子乘四倍解決的原因了
頻率是 次數/時間
取樣率代表是一秒鐘取樣幾次
var sampleFrequency = 44100;
var multiplier = 2.0 * Math.PI / sampleFrequency;
var volume = 12;
for(var i=76;i<data.target.result.byteLength;i++)
{
dv.setInt8(i,128);
}
for(var i=76;i<data.target.result.byteLength;i++)
{
dv.setInt8(i,dv.getInt8(i)+volume * Math.sin(i * multiplier * 440.0));
}
這麼寫的問題出在哪邊呢?
2 pi弳是轉一圈
每秒取樣44100次
也就是說在44100次時完成轉一圈的動作
可是這麼寫能成立的前提是在44100時真的是轉一圈
而實際上我用的.wav檔
是雙聲道,然後每次取樣的是採16bits(2個bytes)
因此分母應該是 44100*2(雙聲道)*2(取樣用2個bytes)
這個值其實就是.wav檔的 每秒平均區塊大小
也就是 1C(28,第29)個位元組開始取四個bytes的資料,儲存採Little Endian
因為後面的迴圈程式其實就是把每個取樣的值都跑計算過一次
因此可以推斷出 multiplier應該是 2PI弳 / 每秒的取樣位元組數量
這邊我把程式碼修正後再貼上來
那現在開始處理和弦
勉強算成功
勉強是因為
覺得後面的尾部本該是音量降低的部份被放大了,導致有些雜音跟爆音的感覺
也就是說目前若拿來實際運用的話是有隱憂的
和弦主要的難點是在於,如何在不用檔案上傳的情況下
取得音樂檔
(不然三和弦要傳三個音樂檔,五和弦五個,七和弦七個,一首有可能有許多不同的和弦)
jQuery提供能拿到現成的大多是文字檔
因此還是得用AJAX的XHR來做
大概就這樣
----------------10/24------------------------
估計是比對do.wav,do1.wav,do2.wav,do-3.wav還有產生出來的和弦的wav檔
看要怎麼消除雜訊跟爆音
這方面叫做混音(mix)
但試了幾個混音演算法
我覺得效果都不好(也許是我試錯)
感覺會有不可避免的雜訊
因此就用應急的手法抑制下
(超過時間點就調成靜音,會溢位的用最大值或最小值取代)