矩形波とは
だいたいこんなよーな形の波形です。
音はいわゆるピコピコ音というやつで、ゲームウォッチやファミコン、ゲームボーイなど、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