矩形波とは
だいたいこんなよーな形の波形です。
音はいわゆるピコピコ音というやつで、ゲームウォッチやファミコン、ゲームボーイなど、PCエンジン手前くらいまでのほとんどのゲーム機での音は矩形波です。
なぜ矩形波が多く使われているかというと、スイッチのON/OFFだけで音を出すことができるから。
上の画像ではチューニングの基本とされる「ラ」の音(440Hz)を出していますが、
↓こういう回路を作って、スイッチをものすごい勢いで連打すれば、マイコンやPCなどなくてもこの音は出せます。
ただし、1秒間に440連打しないと無理です。高橋名人(16Hz)にもファミコンロッキー(50Hz)にも無理でしょう。
矩形波は波が最大の時(HIGH)と最小(LOW)の時の比率(Duty比といいます)が1:1です。
Arduinoのtone()関数で出力できるのは矩形波です。つまり、HIGHとLOWは同じ間隔で鳴っています。
さて、次に、矩形波の音色を多少いじったものをパルス波と言います。
こんな感じで、HIGH/LOWの長さが違います。↑の画像だとHIGHが長くLOWが短くなっていますが、もちろん逆も可能。
ファミコン・ゲームボーイでメインとなる音は、この矩形波とパルス波の中間の性能を持っています。
HIGH/LOWの比率が「12.5:87.5」「25:75」「50:50」(←矩形波)「75:25」の4種類。
聴き比べてみると、意外と音色は変わるものです。
ということで、とりあえずProcessingを使って矩形波とパルス波を鳴らしてみました。ついでにサイン波と三角波も出せるようにしてあります。
マウスクリックで波形が替えられます。
マウスカーソルのX軸がパルス波の幅、Y軸がボリュームです。
import ddf.minim.*; import ddf.minim.signals.*; Minim minim; AudioOutput out; SineWave sine; SquareWave square; PulseWave pulse; TriangleWave tri; int wavetype = 0; void setup() { // Screen Init. size(600, 200); frameRate(60); smooth(); strokeWeight(1); // minim Init. minim = new Minim(this); out = minim.getLineOut(Minim.MONO); sine = new SineWave(440, 0.5, out.sampleRate()); pulse = new PulseWave(440, 0.5, out.sampleRate()); square = new SquareWave(440, 0.5, out.sampleRate()); tri = new TriangleWave(440, 0.5, out.sampleRate()); // sine wave output out.addSignal(sine); } void draw() { // BG-Black FG-Green background(0); stroke(0, 255, 0); translate(0, height/2); // Oscilloscope like View float oldx, oldy, x, y; oldx = oldy = 0; for (int i = 0; i < out.bufferSize() - 1; i++) { x = map(i, 0, out.bufferSize(), 0, width); y = map(out.mix.get(i), 0, 1.0, 0, height/2); line(oldx, oldy, x, y); oldx = x; oldy = y; } } void mouseMoved() { // X-pos as Pulse width float pulse_width = map(mouseX, 0, width, 1, 30); pulse.setPulseWidth(pulse_width); // Y-pos as Volume float amp = map(mouseY, 0, height, 1.0, 0.0); sine.setAmp(amp); pulse.setAmp(amp); square.setAmp(amp); tri.setAmp(amp); } void mousePressed() { // Wave type Switch out.clearSignals(); if (mouseButton == LEFT){ ++wavetype; if (wavetype > 3) wavetype = 0; }else if (mouseButton == RIGHT){ --wavetype; if (wavetype < 0) wavetype = 3; } switch (wavetype){ case 0: out.addSignal(sine); break; case 1: out.addSignal(pulse); break; case 2: out.addSignal(square); break; case 3: out.addSignal(tri); break; } } void stop() { out.close(); minim.stop(); super.stop(); }
以下のページを参考にしました。ありがとうございます。
computer graphics 3.2 サイン波の視覚化
ddf.minim.signals Class Oscillator