Little Strange Software

スマホアプリの開発を行う LittleStrangeSoftware のブログです。

【JavaScript】WebAudioAPIで12音階を鳴らしてみます!

 どうも!LSSです!!

 

WebAudioAPIで色々試していますが、今回はそのうち「ドレミ」12音階を鳴らしてみるものを作ってみました!

なお、基準となる音「ラ」の音の周波数は440Hzだったり442Hzだったりするようですが、今回は「442Hz」で計算しています。

 

スライダーでオクターブや音階を選び、「音を鳴らす」ボタンを押すと、3秒間、指定した音が鳴る、というサンプルになります。

 

 

サンプル




 

 

コード

<p><input id="oto1" type="button" value="音を鳴らす" /></p>
<p><span id="octg"></span><br /><input id="oct" style="width: 100%;" max="6" min="2" type="range" value="4" /></p>
<p><span id="onkaig"></span><br /><input id="onkai" style="width: 100%;" max="11" min="0" type="range" value="9" /></p>
<p><span id="gaing"></span><br /><input id="rg1" style="width: 100%;" max="1" min="0" step="0.1" type="range" value="0.3" /></p>
<script>// <![CDATA[
otolist=['ド','ド#','レ','レ#','ミ','ファ','ファ#','ソ','ソ#','ラ','ラ#','シ'];
oto1.addEventListener('click',oc0p,false);
oct.addEventListener('input',gw,false);
onkai.addEventListener('input',gw,false);
rg1.addEventListener('input',gw,false);
AudioContext = window.AudioContext || window.webkitAudioContext;
ctxa=new AudioContext();
gw();
function shs(){
return 442*(Math.pow(2,parseInt(oct.value)-4+(parseInt(onkai.value)-9)/12));
}
function oc0p() {
oc0=ctxa.createOscillator();
oc0g=ctxa.createGain();
oc0t=ctxa.currentTime;
oc0.type='triangle';
oc0.frequency.value=shs();
oc0g.gain.value=parseFloat(rg1.value);
oc0.connect(oc0g);
oc0g.connect(ctxa.destination);
oc0.start();
oc0.stop(oc0t + 3);
}
function gw(){
octg.innerHTML='オクターブ : '+oct.value;
onkaig.innerHTML='音階 : '+otolist[parseInt(onkai.value)];
gaing.innerHTML='音量 : '+rg1.value;
}
// ]]></script>

 

 

あとがき

なんとなく、「オクターブがひとつ上がると、周波数は倍になる」事だけ知っていました。

1オクターブ=12音階(ピアノの黒鍵と白鍵が1オクターブあたり合わせて12個)で、1音階はどう表現するのかと思ったら、「2の1/12乗」という直感的に分かり辛い計算になるようですw

 

JavaScriptには「Math.pow」関数という、べき乗を算出してくれる関数があり、例えば「Math.pow(2,4)」なら「2の4乗=16」という計算をしてくれるんですね。

これが都合よく、1/12とかでもしれっと計算してくれるので、例えば
「ラの次の音(ラ#)」
の周波数を出そうと思ったら、

442*Math.pow(2,1/12)

で算出してくれます^^

「1オクターブ上のラ」なら、

442*Math.pow(2,1)

となり、

「1オクターブ上のラ#」なら、

442*Math.pow(2,1+1/12)

という感じですね。

 

 

 

ってなとこで、今回はこのへんで!

次回もまた、よろしくお願いします^^