トップ 差分 一覧 ソース ヘルプ ログイン

ファミコンDPCMで音程を鳴らす

最終更新時間:2010年04月09日 01時35分12秒
このエントリーをはてなブックマークに追加

[Chiptune]

ファミコンにはDPCMが1音分用意されている。
バスドラムに使われることが多いが、これでベース音を鳴らしているソフトも存在する。
というわけでベース音を鳴らしてみる。
(高周波音では音が小さすぎて実用にならない。詳細は後述)

まずはDPCMの音程の仕様。

再生周波数(再生速度)を16段階に変更できる。
これは単純な比ではなく音階となるよう設定されており、下位から
CDEFGABCDFGACEGC
となる。(C毎にオクターブが上がる)
(以上、Wikipediaより)

この「CDEFGABC」の部分を使うことにする。

次に、一番下の「C」の音程を決める。
ここではC2(中央のド = C4)とする。

DPCM用の波形を作成する。
FamitrackerでDPCMに変換するので、普通のwavファイルを作成する。
WaveGeneで510Hzの音を作成する。これくらいがきれいな音程が出るようだ。
(dmcconvなど、他のソフトで変換する場合は不明)
ただし、後述するとおり、容量を節約しようと思うなら、別な周波数を探すことを勧める。

波形は、矩形波でも三角波でも鋸波でも適当に混ぜればよい。
出力フォーマットはなんでもおk
(ここでは 96000Hz, 16Bit, Mono とする)

そしてFamitrackerでDPCMに変換する。
変換時の設定は

  • Quality = 15
  • Volume = 1~3くらい

Volumeは無理にあげようとすると、波形がなまってしまう上に音量が上がらない。この程度で十分だ。
もし小さすぎるなら上げてみるとよいが、意外と小音量のうちに限界が来てしまう。

DPCMの仕様上、最大音量は再生周波数に比例し、鳴らしたい音の周波数に反比例する。
そして、その最大音量が意外と小さいのだ。残念である。
いろいろな周波数の三角波をDPCMに変換して、それをバイナリエディタで覗くと仕組みがよくわかるだろう。

これでDPCM波形はできあがり。
ここではbass.dmcというファイル名で保存した。

あとはmckでDPCMファイルを読み込んで鳴らせばいい。
DPCMの定義はこんな感じになる。

@DPCM0={"bass.dmc",0}/*C*/
@DPCM1={"bass.dmc",1}/*D*/
@DPCM2={"bass.dmc",2}/*E*/
@DPCM3={"bass.dmc",3}/*F*/
@DPCM4={"bass.dmc",4}/*G*/
@DPCM5={"bass.dmc",5}/*A*/
@DPCM6={"bass.dmc",6}/*B*/
@DPCM7={"bass.dmc",7}/*C*/

あとは

E n0 n1 n2 n3 n4 n5 n6 n7

これで「ドレミファソラシド」と鳴ってくれるはずだ。


これだけでは重大な欠点がある。
C# や D# などが鳴らせないじゃないか。

というわけで、C#のDPCM波形を作成する。
WaveGeneでの周波数を

510 * 2 ^ (1 / 12) ≒ 540(Hz)

にする。あとは同様にやればおk
今度はファイル名をbass2.dmcとした。

DPCMの定義を追加して

@DPCM0={"bass.dmc",0}/*C*/
@DPCM1={"bass2.dmc",0}/*C#*/
@DPCM2={"bass.dmc",1}/*D*/
@DPCM3={"bass2.dmc",1}/*D#*/
@DPCM4={"bass.dmc",2}/*E*/
@DPCM5={"bass.dmc",3}/*F*/
@DPCM6={"bass2.dmc",3}/*F#*/
@DPCM7={"bass.dmc",4}/*G*/
@DPCM8={"bass2.dmc",4}/*G#*/
@DPCM9={"bass.dmc",5}/*A*/
@DPCM10={"bass2.dmc",5}/*A#*/
@DPCM11={"bass.dmc",6}/*B*/
@DPCM12={"bass.dmc",7}/*C*/
@DPCM13={"bass.dmc",7}/*C#*/

またも鳴らしてみる。

E n0 n1 n2 n3 n4 n5 n6 n7 n8 n9 n10 n11 n12 n13

たぶんこれでおk

さらにほかの音程を鳴らしたいなら、WaveGeneの周波数を

510 * 2 ^ (x / 12)
(xには上げたい音数を半音単位で入れる 下げたいときは負の値を入れる)

として、同様にやればいい。


DPCM波形はループ再生も可能だ。
これを利用して容量を節約しよう。
MCKの仕様上、DPCMにはどう足掻いても16KBまでしか使えないし
なにより、DPCMに大容量を使ってしまうのはファミコンらしくない。

というわけで、今のところ確認済みのちょうどいいWaveGene周波数を載せておく。
(96000Hz, 16Bit, Mono 出力の波形をFamiTrackerでQuality=15で変換した場合)

周波数 → バイト数(周波数指定に0,7,12,15を入れたときの音階)
480Hz → 17バイト(B)
720Hz → 17バイト(F#)
754Hz → 65バイト(G)

テキトーに調べているので、間違っているかもしれない。
この整数倍/整数分の1の周波数もおkの場合がある。耳とバイナリエディタで確認してから使うとよし。

ちなみに、510Hz(C)は8バイトでかなり正確にループする。
しかし、ファミコンDPCMのループ単位は1+16nバイトなのだ。非常にいじわるである。


また、波形によってもループがつながるかどうかは変化する。
WaveGeneなら「ゲート」を使用した波形がループをつなげやすい。
バイナリエディタでdmcファイルを見ると「AA」が連続している場所が多数あるので、それを見てループを決めればよい。
この方法なら、周波数が結構いい加減でもループがつながってくれる(音の自由度や音量は犠牲になる)。