ということで、今回はコードを鳴らすために複数のオシレーターを使い、それらの音源をミックスして鳴らそうと思う。
OscillatorNodeやGainNodeの詳しい説明は、以下の記事を参照してほしい。
音をミックスする
音のミックスは非常に簡単で、複数のOscillatorNodeをAudioContext.destinationに繋ぐだけで良い。
ただ、そのまま繋ぐと音が割れてしまうことがあるので、OscillatorNodeとdestinationの間にGainNodeを挟み、音量の調整したほうが良いだろう。
const ctx = new AudioContext();
// Oscillator -> Gain
const vca1 = ctx.createGain();
const vco1 = ctx.createOscillator();
vco1.connect(vca1);
// Oscillator -> Gain
const vca2 = ctx.createGain();
const vco2 = ctx.createOscillator();
vco2.connect(vca2);
// Gain -> Speaker
vca1.connect(ctx.destination);
vca2.connect(ctx.destination);
// そのままミックスすると音が割れるため
vca1.gain.value = 0.5;
vca2.gain.value = 0.5;
// 440Hzと倍音の880Hzを鳴らす
vco1.frequency.value = 440;
vco2.frequency.value = 880;
vco1.start();
vco2.start();
上記の例では、440Hzと880Hzのサイン波を同じ音量でミックスしている。
これと同じ要領で複数の音源を接続すれば、もっと複雑なコード(和音)も鳴らせる。
複数のOscillatorをつかってコードを鳴らす
<div id="app">
<div
v-for="(o, i) in osc"
:key="o"
class="synth-group">
<h3>OSC {{ i+1 }}</h3>
<div class="field-group">
<label>Wave form</label>
<template v-for="form in waveForms">
<label>
<input type="radio" :value="form" v-model.number="osc[i].form">
{{ form }}
</label>
</template>
</div>
<div class="field-group">
<label>Frequency</label>
<input type="number" v-model.number="osc[i].freq">
</div>
<div class="field-group">
<label>Volume</label>
<input type="range" min="0" max="1" step="any" v-model.number="osc[i].volume">
</div>
</div>
<button type="button" @click="start">Start</button>
<button type="button" @click="stop">Stop</button>
</div>
new Vue({
el: '#app',
data() {
return {
waveForms: ['sine', 'square', 'sawtooth', 'triangle'],
ctx: new AudioContext(),
osc: [
// osc1
{
node: null,
gain: null,
form: 'sine',
freq: 523.25, // C5
volume: 0.3
},
// osc2
{
node: null,
gain: null,
form: 'sine',
freq: 659.25, // E5
volume: 0.3
},
// osc3
{
node: null,
gain: null,
form: 'sine',
freq: 783.99, // G5
volume: 0.3
}
]
}
},
methods: {
start() {
this.osc.forEach((o, i) => {
const gain = this.osc[i].gain = this.ctx.createGain();
gain.connect(this.ctx.destination);
gain.gain.value = o.volume;
const osc = this.osc[i].node = this.ctx.createOscillator();
osc.connect(gain);
osc.frequency.value = o.freq;
osc.type = o.form;
osc.start();
});
},
stop() {
this.osc.forEach(o => o.node.stop());
}
}
});
3つのオシレーターからそれぞれC5、E5、G5(ドミソ)を発音し、それをミックスすることでCメジャーコードを鳴らすことができる。
もちろんFrequencyを変えれば、他のコードも鳴らすことができる。
割りと簡単にできるが、音源をミックスすればするほど音量調整が面倒になるので、このあたりは何か良い方法がないか試してみようと思う。
以上
written by @bc_rikko
0 件のコメント :
コメントを投稿