ドライバ処理の流れ/SCCの処理
SCCの処理
- レジスタ値の作成
- キーイネーブルデータの作成
- レジスタ値の書き込み
- 波形の書き込み
レジスタ値の作成
SCC音源には9880H-988FHに分周比や音量などを設定するレジスタがあります。
そのレジスタ群と同じ並びのデータをE2A2H-E2B1Hに作成します。
何故バッファにデータを作るのかといえば、まとめておけば転送しやすいというのもあるでしょうがもう一つ、同じ値を書き込まない為でもあります。
ここで作成するデータは、分周比と音量データです。
分周比はワークエリアの(+0AH)(+0BH)[分周比データ] からコピーするだけ、音量データは(+0CH)[音量データ]からコピーするだけですが、その時コピー先のバッファと値を比較します。
バッファには前回SCCに書き込んだデータがそのまま残っているので、値が異なるとレジスタの値が変更されたということが分かります。
レジスタの値が変更された時のみ書き込むように、そのためのフラグE2A0H-E2A1Hの該当ビットを1にして、バッファに値をワークエリアからコピーします。
PSGでは前回書き込んだ値をお構いなしに毎回書き込んでいましたが、SCCはわざわざチェックして同じ値の場合は書き込みません。
分周比の書き込み
現象としてはっきりしていることは、同じ分周比を1/60秒間隔で書き込み続けるとビブラートを高速化したような感じで音が濁るということです。
原因は恐らく分周比カウンタが書き込みによって初期化され、再生中の1サンプルだけが間延びしてしまうためなのかなと考えていますが詳細は検証していません。
こんな感じになります。
※エンコードすると差が分かり難くなった気がするので念の為、 wav ファイルも置いておきます。(音量注意)
分周比の値やタイミングによって目立ったり目立たなかったりしますが、これでは演奏に耐えないので同じ値の場合はスキップするようになっています。
他のレジスタでは特に大きな弊害はなかったような気がしますが、無駄な書き込みは避ける方針のようです。
キーイネーブルデータの作成
各チャンネルの(+0DH)[波形/キーオンフラグ]を調べてデータを作成するのですが、b1[キーオン] をチェックするのではなく、(+0DH)が0か否かで判定しています。
となると、SCCではb0,b2,b3は使用されず0のまま、モーフィングが使用されているときはキーオフされないという条件なのだと思われます。
キーイネーブルデータの作り方は、Cレジスタに1を初期設定し、チャンネルを変更する度にSLA Cとして1をシフトしていき、キーオンするチャンネルのときにORで合成してく方法でした。
このデータも分周比や音量と同じく、バッファの値と比較し、変更があった時のみ書き込みされます。
レジスタ値の書き込み
こちらの処理は簡単です。E2A0H-E2A1Hのフラグを見ながら、1の項目だけを書き込みしていくだけです。
SCCレジスタの書き込み部分はサブルーチン化されていて、そこでは- SCCを出す
- データを書き込む
- 8000-9FFFHのバンクを0BHに戻す
波形の書き込み
メガROMのSCCは波形を4チャンネル分しか設定できないので、4チャンネル分の処理となっています。
まず(+0FH)b7[波形転送フラグ]をチェックします。0なら次のチャンネルへ処理を進めます。
1なら(+28H)(+27H)[波形データ開始アドレス]を取得し、(+0DH)b6[モーフィングフラグ]をチェックします。
- モーフィングでない場合(通常波形転送)
SCCを出す。
全チャンネルキーオフをSCCに書き込み。
波形を32バイト転送。
バッファからキーイネーブルデータを取得しSCCに書き戻す。
8000-9FFFHのバンクを0BHに戻す。
(+0FH)b7[波形転送フラグ]を0にする。
- モーフィングの場合
SCCを出す。
波形データ1バイトを転送後、波形アドレスに(+31H)[波形アドレス増分]を加算して更新。
32バイト繰り返す。
8000-9FFFHのバンクを0BHに戻す。
処理の疑問点
通常の波形転送では一旦全てキーオフしてから波形データを転送しています。
所謂波形メモリアクセスの競合でのノイズ対策かと思いますが、キーオンした時に結局間違ったサンプルを出力したら同じことではないのかと少し疑問です。
またキーオフするにしても、何故全チャンネルキーオフなのか。
ちょっとこれは実験してみないと分かりません。
なんとキーオフするのはわざわざノイズを増やす行為になってしまっていました。


この2枚の画像は、上がキーオフして転送時のノイズ、下が何もせず波形転送時のノイズです。分周比はどちらも338。
波形を32バイト転送するために掛かる時間は800クロック程。
そうなるとサンプル2個分の長さ以上キーオフされている計算です。波形から正確には読み取れませんが大体そうなっているようです。
一方何もせず波形転送した場合、波形データ読み取りミスで値がおかしいのはこの分周比だと1サンプル程度。しかもタイミングの問題ですから、うまく読み取れた場合何の影響もありません。
キーオフの方は毎回実行しているため必ずサンプル2個分以上(分周比338の場合)は出力offということになるので、ノイズが多くなるのは納得の結果です。
何故わざわざこの処理を行っているのか。良いことは無いと思うのですが…分かりません。
モーフィング処理
モーフィング処理のときは、キーオフせずそのまま転送しています。
この処理は任意の波形を切り替えているのかと思っていたのですが、どうやら違うようです。
基本となる波形の転送を、連続、1バイト毎、2バイト毎、と転送していきその結果波形が変わる仕組みです。
波形データは特定のエリアに固まって存在するので、波形データの配置がモーフィングした時の音色変化に関係します。
例えばボス曲のモーフィングで使用する波形以降のデータの並びはこんな感じです。

モーフィング開始は1個目の波形です。

8クロック後に、アドレス増分が+1されます。結果、転送される波形は1個目と2個目が圧縮された形になります。

また8クロック後、波形3個分。

更に8クロック後、波形4個分。このあたりから波形の元の形がわからなくなってきます。

以降は8クロック毎にこのように変化します。




もう意味のある変化というよりは、ランダムに近い感じです。




ラスト。



gifアニメにするとこうなります。

この波形変化の音です。
こういう仕様だと、狙った音にするには難しそうです。
配置している音は単体でも使用すると思われるので、モーフィング専用に作成するわけにもいかないのではないかと。
バグでプログラムのデータが鳴っていたという話がありましたが、確かにこれでは音色データが鳴っているのかプログラムが鳴っているのか判別つかないですね。
音色作成でできることは波形データの並び替えぐらいなので、結構苦労してモーフィングデータを作っていたのかもしれません。
因みにこちらの処理は、[波形転送フラグ]を0にしないので、波形変化しなくても割り込みの度に波形データを書き込みするようです。