====================================== Nintendo Disksystem Soundの資料 ver1.1 ====================================== goroh氏,NORI氏,T.Aoyama氏の解析を元に作成したディスクシステム音源の資料です。 ディスク部分に付いてはgoroh氏とNORI氏の資料を参照して下さい。 ============== レジスタの解説 ============== レジスタ(R/W) 解説 -------------------------------------------------------------------------------- $4040- $407F(R/W) Main wavetable port bit --FFFFFF(W) $4089のbit7が1の時のみ設定可能。 bit -1FFFFFF(R) $4089のbit7が1の時は指定アドレスのデータが返って来る。 $4089のbit7が0の時は指定アドレスに関係無く音源が参照中のデータが 返って来る。 波形データに付いては後述(#1 波形データに付いてを参照) #ver1.0では(R)時のビットが逆でした -------------------------------------------------------------------------------- $4080(W) Volume Envelope port bit eeVVVVVV e Envelopeモード 00 減衰モード+スピード設定 01 増加モード+スピード設定 1x 直接モード+ヴォリューム値設定 V Envelopeデータ モードによって意味が変わり,減衰/増加モードでは速度を設定 し,直接モードではヴォリューム値を設定する。 詳しい説明は後述(#2 Envelopeに付いてを参照) -------------------------------------------------------------------------------- $4081(R?/W?) Unknown -------------------------------------------------------------------------------- $4082(W) Main Frequency port(Low) bit FFFFFFFF $4083(W) Main Frequency port(High) bit ec--FFFF e サウンド出力イネーブル(0:出力する 1:出力しない) 出力イネーブルを1にすると,Main wavetable参照アドレスが初期化さ れる。 c エンベロープイネーブル(0:作動 1:停止) Volume EnvelopeとSweep Envelope共にこのビットに影響される。 F 出力周波数レジスタ (1789772.5/(65536x64))x(F)Hzが出力される。0は出力停止。 64はwavetable size分で64段階で1周期である為。 Fを1単位変えると,0.426715....Hz変わる。 440Hz(O4-A)を出力したい場合,$407(1031)を入力する。 計算式は以下の通り 出力周波数(Hz) F入力値 = ---------------------- 1789772.5/(65536x64) #ver1.0ではFを1単位…の計算が間違っていました -------------------------------------------------------------------------------- $4084(W) Sweep Envelope port bit eeVVVVVV e Envelopeモード 00 減衰モード+スピード設定 01 増加モード+スピード設定 1x 直接モード+ヴォリューム値設定 V Envelopeデータ モードによって意味が変わり,減衰/増加モードでは速度を設定 し,直接モードではヴォリューム値を設定する。 詳しい説明は後述(#2 Envelopeに付いてを参照) -------------------------------------------------------------------------------- $4085(W) Sweep Bias port bit -BBBBBBB B Biasデータ 符号付7bit(2の補数表現)です。 ※エミュレータへの対応に付いて $4088の参照アドレスは実際には初期化することは出来ないが,エミュ レータへ実装する際は、$4085への書き込みによりEffector(LFO) wavetable 参照アドレスを初期化した方が対応しやすい。 詳しい説明は後述(#3 Sweepに付いてを参照) -------------------------------------------------------------------------------- $4086(W) Effector(LFO) Frequency port(Low) bit FFFFFFFF $4087(W) Effector(LFO) Frequency port(High) bit e---FFFF e Effector(LFO) wavetable設定(0:通常モード 1:設定モード) 設定モードでも音は出力されたままである。 F 出力周波数レジスタ (1789772.5/(65536x64))x(F)Hzが出力される。0は停止。 64はwavetable size分で64段階で1周期である為。 計算式は$4082,$4083と同じです。 詳しい説明は後述(#3 Sweepに付いてを参照) -------------------------------------------------------------------------------- $4088(W) Effector(LFO) wavetable port bit -----ddd d テーブルデータ data : 0 1 2 3 4 5 6 7 table: 0 +1 +2 +4 *0 -4 -2 -1 *が付いている時にSweep Biasが0にリセットされる。 ・$4087のbit7が1の時に設定可能。必ず32バイト分設定する。 ・32バイト分のバッファがあり,周波数変調をコントロールする。 詳しい説明は後述(#3 Sweepに付いてを参照) -------------------------------------------------------------------------------- $4089(W) Sound control port bit e-----vv e Main wavetable設定(0:通常モード 1:設定モード) Main wavetable設定を1にすると、サウンド出力は停止する。 v Main volume control 00: 100.0%(Max) 01: 66.6% 02: 50.0% 03: 40.0% -------------------------------------------------------------------------------- $408A(W) Sound control port 2 bit eeeeeeee e エンベロープ出力速度(0で停止する) $01:最高速 $FF:最低速 ディスクシステムBIOSで初期値$E8(232)がセットされる。 詳細は後述(#2 Envelopeに付いてを参照) -------------------------------------------------------------------------------- $4090(R) Main volume envelope value port bit -1vvvvvv v Volume Envelope値 現在のVolume Envelope値を得る事が出来ます。 -------------------------------------------------------------------------------- $4091(R) Unknown -------------------------------------------------------------------------------- $4092(R) Sweep envelope value port bit -1vvvvvv v Sweep Envelope値 現在のSweep Envelope値を得る事が出来ます。 -------------------------------------------------------------------------------- $4093- $40FF(R?/W?) Unknown -------------------------------------------------------------------------------- $4020- $403F(R/W) Disk control ports $4023(W) 2C33 I/O control port bit ------SD S Sound出力 0:Disable 1:Enable D Disk I/O 0:Disable 1:Enable ※BIOSで使用される為ほぼ無視して構わない。 -------------------------------------------------------------------------------- ========== 詳しい説明 ========== #1 波形データに付いて 波形データは最終的にPWMで出力される為に実際は多少ひずんで,設定した数値通りのリ ニアな波形が出力されません。更に,LPFが掛かるので矩形波を入力したとしても角が取 れたような波形が出力されます。 例えば,ノコギリ波データを入力した場合は以下の様になります(概念図です)。 | | 振| ** 振| ** 幅| *** * 幅| *** * | *** * → | * *** * | *** * | ** * * | *** * | *** * | *** * | ** * --+-------------------- --+-------------------- 波形 波形 -------------------------------------------------------------------------------- #2 Envelopeに付いて ●直接モード設定の有効範囲 Volume Envelope/Sweep Envelope共に構成はほぼ同じで,出力の有効範囲が変わります。 Volume Envelope $00〜$3F(64段階) $21以上は$20の音量で出力される。 Sweep Envelope $00〜$3F(64段階) Volume Envelopeは直接モードでもエンベロープモードの場合でも,即座に数値が反映さ れる訳では無く,波形データ参照アドレスが$4040にリセットされた時に初めて反映され ます。つまり,波形(一周期)の途中では音量は変わらないと言う事です。 ●減衰モード 減衰モードは,現在のVolume Envelope/Sweep Envelope値から0まで減衰します。(停止し てもモードは変更されません) ●増加モード 増加モードは,Volume Envelope/Sweep Envelope値が$20未満である場合のみ増加し,$20 になると停止します。(停止してもモードは変更されず,$20以上を直接モードで設定して もエンベロープは止まったままです) ●Envelope速度 Envelope速度は$408Aの設定に速度が影響され,$408Aが0の場合はEnvelopeが停止します。 $4083のbit6が1でもEnvelopeは停止します。 1段階変化するまでのクロック数は以下の式で計算されます。 1段階クロック数の演算 (速度+1) x 1789772.5 $408A設定値 x (速度+1) x 1789772.5 CLK = --------------------------- = ------------------------------------ (232 / $408A設定値) x 960 232 x 960 ※1789772.5を44100にすると44.1KHzに対する1段階のサンプル数を得る事が出来ます。 -------------------------------------------------------------------------------- #3 Sweepに付いて ●波形データ参照アドレスに付いて Sub wavetableは32バイトしかありませんが,参照アドレス更新スピードはMain wavetable と同じです。つまり,同じデータを2回演算すると言う事です。 ●$4085に付いて $4085はSweep Biasの初期値を設定するポートです。実際はEffector(LFO) wabetable参照 アドレスを初期化出来ませんが,エミュレータ上では初期化すると上手く動作します。 (バイオミラクル ぼくってウパの2面BGM) Sweep BiasはEffector(LFO) Frequency単位でEffector(LFO) wabetableからのデータによ り増減やリセットを行い,最終的な出力に影響を及ぼします。 なお,Effector(LFO) wavetableのデータ4(*が付いているデータ)の時はSweep Biasが0に 初期化されます。 Sweep Biasは+63を超えると-64に,-64を下回ると+63にラップアラウンドします。 なお,Effector(LFO) wavetable設定モードの場合やEffector(LFO) Frequencyが0の場合は, Effector(LFO) wavetableによる計算処理自体が行われません。 -------------------------------------------------------------------------------- #4 最終的な周波数の演算に付いて Sweep Biasと,Sweep Envelopeの出力値によって様々な効果を出す事が出来ますが,計算 方法がかなり特殊です。 (1) Sweep EnvelopeとSweep Biasを乗算する。 (2) (1)の値を16で割る(結果は少数以下切り捨て)。 (3) (2)で余りが出た場合,Sweep Biasが正ならば(2)の値に2を足し,負ならば(2)の値か ら1を引く。 (4) (3)の最大値は193で,これを超えると-64へラップします(超えた場合は258を引く)。 (5) Main周波数と(4)を乗算し64で除算する。 (6) 最終出力周波数はMain周波数と(5)を加算する。 (7) 最終周波数が負の周波数になった場合,この数値にMain周波数を4倍した周波数を加 算する。 (5),(6),(7),は以下の方法でも同じです。 (5') (4)の後,計算値が-64を下回る場合は計算値に256を足す。 (6') Main周波数と(5')を乗算し64で除算する。 (7') 最終出力周波数はMain周波数と(6')を加算する。 ソフトウェアでは以下の様になります。 value_1 = Sweep envelope出力値 * Sweep Bias; // (1) value_2 = value_1 / 16; // (2) if( (value_1 % 16) != 0 ) { // (3) if( Sweep Bias >= 0 ) { value_2 = value_2 + 2; } else { value_2 = value_2 - 1; } } if( value_2 > 193 ) // (4) value_2 = value_2 - 258; Freq = Main Freq * value_2 / 64; // (5) Freq = Main Freq + Freq; // (6) if( Freq < 0 ) Freq = (Main Freq * 4) + Freq; // (7) これはゼルダの剣ビームやOPのLFO等で非常に重要です。 -------------------------------------------------------------------------------- 更新履歴 ver1.0 初版 ver1.1 2個所程の記述ミスを修正 --------------------------------------------------------------------------------