今更NESでPCM再生
※中途半端な知識で書いているため壮絶に間違っている可能性があります。おかしなところは指摘してもらえると有難いです。
$4011 にWAVEデータを流し込んで再生する、というやつです。
とりあえず8KHzで2秒程度再生するものを作ってみました(ca65 使用。素材はニコニ・コモンズから拝借)。クロック計算は目分量ですが一応聞くには耐えるようです。マッパーを導入してバンク切り替えを行うようにすれば長時間再生もできそうですね(色々めんどくさそうなのであまりやる気ありませんが^^;)。
音声を差し替えたい場合は、8KHz 8-bit unsigned モノラル raw形式の音声ファイル(2秒以内)を用意し、同梱の 8to7.py で7bitに変換して make し直せばOKです。例えば、sox を使うなら以下の通り:
$ sox in.wav -u --channels 1 --bits 8 --rate 8000 out.raw trim 0 2.0 $ python 8to7.py out.raw dat.pcm
NESのFPSは約60.099で、1FあたりのPPUクロック数は 341*262 (BGオフの場合)で、CPUクロックはPPUクロックの1/3なので、1秒間に使えるCPUクロックは
60.099 * (341*262) / 3 = 1789812.79
となります。よって、8KHzで再生するなら
1789812.79 / 8000 = 223.73
より、1サンプルあたり約224CPUクロックで再生するように調整すればいいことになります(前述の通り、そこまで厳密にやらなくても一応それなりには聞こえるようです)。
8to7.py では単純に入力値を2で割って7bit値を生成していますが、これが最善なのかどうかはよくわかりません。
これを書いた後にKZ-S氏のPCM再生デモの存在に気付きました。こちらはバンク切り替えに対応しており、クロック計算もまじめに行っているようです。