この記事は Qiita p5js アドベントカレンダー24日目の記事です。
これはなに
前日に書いた【p5.js】p5.soundで音を利用した表現を描画するの続編です。
上記の記事ではpreload()で用意した音を使用しましたが、今回はp5.soundで音を生成してみる内容です。
試してみる
オシレーターを用意する
まずは音の出力に必須となるオシレーターを用意します。
オシレーターとは
シンセサイザーが音を出すためにはその元となる波形が必要になります。
オシレーターはその波形をつくってあげるもののことで、p5.soundではp5.OSCillator
というクラスが用意されています。
インスタンスを用意する
p5.Oscillatorをnewしてインスタンスをsetup()内に用意します。
引数のsine
は波形の種類のことで、
sine(正弦波)、triangle(三角形)、sawtooth(のこぎり波)、square(矩形波)の4種類があります。
この辺はシンセサイザーを触ったことがある人はおなじみなのではないでしょうか。
function setup() {
createCanvas(600, 600);
const osc = new p5.Oscillator('sine')
}
音を出す
osc.start()
をsetupに追加して実行します。
function setup() {
createCanvas(600, 600);
const osc = new p5.Oscillator('sine')
// 追加
osc.start()
}
実行すると「ポーーーーーーーーーーー」という音がなりました!
音の出力だけならcreateCanvas()
も不要なので、setup()内のたった2行で音が出せるということがわかりました。
恐るべしp5.sound。
freqメソッドで周波数を変える
周波数をfreqメソッドで変更することで音色を変えることができます。
下記のようなコードを書いてみました。
let isPlaying = false
let osc = null
function setup() {
// createCanvas(600, 600);
osc = new p5.Oscillator('sine')
osc.start()
isPlaying = true
// 周波数1000からスタート
osc.freq(1000)
}
function draw() {
// 開始から1秒後にrandom(400)な周波数が渡される
if(isPlaying) osc.freq(random(400), 1)
}
実行から1秒間は1000から数値が下がっていくように発音されます。
その後、フレームレートごと(1秒間に60回)の頻度でrandom()が返す値がfreqに渡るため、
「ボコボコボコボコッ!」と激しく音色が変わることが確認できると思います。
音の情報を描画する
音の周波数や音量をリアルタイムで描画してみましょう。
p5にはFFT
というクラスがあり、これが持つメソッドを用いて周波数などを描画することができます。
リファレンスを参考に下記のようなコードを書いてみました。
keyPressedとkeyReleasedで、キーボードを入力しているときだけ音が鳴るようにしています。
またfft.analyze(周波数域)とfft.waveform(振幅)がもつ情報を用いて、
発生しているがどの帯域でどれくらいの音量が出ているかを表しています。
let osc = null
let env = null
function setup() {
createCanvas(600,600);
osc = new p5.Oscillator('sine')
osc.freq(500)
fft = new p5.FFT();
}
function draw() {
background(220);
let spectrum = fft.analyze();
for (let i = 0; i< spectrum.length; i++){
let x = map(i, 0, spectrum.length, 0, width);
let h = -height + map(spectrum[i], 0, 255, height, 0);
rect(x, height, width / spectrum.length, h )
}
let waveform = fft.waveform();
noFill();
beginShape();
stroke(20);
for (let i = 0; i < waveform.length; i++){
let x = map(i, 0, waveform.length, 0, width);
let y = map( waveform[i], -1, 1, 0, height);
vertex(x,y);
}
endShape();
}
function keyPressed() {
osc.start()
}
function keyReleased() {
osc.stop()
}
あとがき
まだまだp5.soundには音を操るための関数やクラスがたくさん用意されています。
組み合わせていけばオリジナルのシンセサイザーなんかも作れたり、
もしかしたらライブコーディングで演奏なんかもできるのかもしれません。