拙作の S44PLAY.X というプログラムの技術的なことについて詳しく解説した文章です。ソフトバンクの Oh!X 1999 年夏号に掲載されました。掲載時のタイトルは『内蔵音源を駆使した高品位ステレオ PCM 再生』であり、「X680x0 の」という言葉はついていませんでした。Web での公開にあたり、Oh!X に掲載済みの原稿を著者が自由に使用できることを確認済みです。


目次

  1. はじめに
  2. 今回の試み
  3. FM 音源の処理速度の限界
  4. FM 音源で PCM データを再生する方法
    1. 矩形波に近い音を作る
    2. 変位の制御
    3. 複数の矩形波を重ねる
    4. STPLAY.X の場合
    5. 新しい方法
    6. 変位の符号に応じたチャンネルの切り換え
    7. 1/4 周期毎のチャンネル遷移
  5. ステレオ化
  6. サンプリング周波数の変換
    1. 間引き・伸張
    2. 直線補間
    3. 面積補間
  7. 実装
    1. フェードイン・フェードアウト
  8. FMP ファイル
  9. 困ったこと
    1. アセンブルできなくて…
    2. SCSI の強制ソフト転送
    3. 040turbo には酷?
  10. おわりに

1. はじめに

X680x0 の内蔵音源は、8 チャンネルの FM 音源(OPM…YM2151)と、15.625kHz までのサンプリング周波数で再生できる 1 チャンネルの PCM 音源(ADPCM…MSM6258V)で構成されています。PCM データをステレオ再生する(左と右で別々の PCM データを再生する)ためには最低でも 2 チャンネルの PCM 音源が必要ですから、ハードウェアを追加しない限り、普通の方法では PCM データをステレオで再生することはできません。しかし、限られた内蔵音源を駆使して PCM データをステレオ再生する試みは過去に幾つかありました。

X680x0 において広く公開された PCM のステレオ再生プログラムとしては、古くは Oh!X 1993 年 3 月号の“(で)のショートプロぱーてぃ”のコーナーに掲載された秋山嗣晴氏による PCMST.S に遡ります。PCMST.S によるステレオ再生の方法は、ステレオの PCM データを細切れにして ADPCM で左右交互に出力し、左右の切り換えを高速に行うことで ADPCM を疑似的にステレオ化するというものでした。私の知る限り、X68000 の内蔵音源のみで PCM データをステレオ再生する試みを広く発表されたプログラムとしては PCMST.S がおそらく初めてであり、私も当時その発想と実現力に感動を覚えつつ Oh!X に掲載されていたプログラムをせっせと入力した覚えがあります。

ただ、PCMST.S の方法では実際に左右同時に(意図した)音が出るわけではなく、また、PCM データを細切れにしているためにノイズが多いのが難点でした。なお、このプログラムはその後バージョンアップされて電脳倶楽部 VOL.99(1996 年 8 月号)に PCMST.X と WAVST.X として掲載されています。

電脳倶楽部に PCMST.X が掲載されたことがきっかけで、伊倉 "DigitalJunkie" 晴読氏が別のアプローチで PCM データをステレオ再生するプログラム STPLAY.X を作り、電脳倶楽部 VOL.100(1996 年 9 月号)に掲載されました。STPLAY.X は、右側の音を ADPCM で、左側の音を FM 音源で再生するという方法で、左右同時に 15.625kHz で PCM を再生することができました。

FM 音源を 4 チャンネル使うことで 1 チャンネルの PCM 音源をエミュレートできることは同氏の手によって電脳倶楽部 VOL.78(1994 年 11 月号)に掲載された“志村けんX”というプログラムで既に証明されており、STPLAY.X はそれを応用したものでした。

2. 今回の試み

さて、私が激光電脳倶楽部 VOL.6 に向けて音に関係する記事を書くことになったとき、私は自分も PCM のステレオ再生を試みようと思いました。それも激光電脳倶楽部なのですから、CD2PCMT.X などを使うことで音楽 CD から容易にデータを供給できる(勿論、個人的な使用の範囲でですが)サンプリング周波数が 44.1kHz のステレオの PCM データを直接再生できるプログラムを作りたくなりました。

前述の通り、X680x0 の内蔵 ADPCM 音源は最高で 15.625kHz までのサンプリング周波数にしか対応しておらず、ADPCM でこれよりも高い周波数で PCM データ再生することは不可能です。しかし、STPLAY.X で使われていた FM 音源の処理能力にはまだ少し余裕があります。そこで、私は 15.625kHz の ADPCM の使用はさっさと諦めて、左右両方のチャンネルを FM 音源で再生して再生周波数を ADPCM よりも上げられないかと考えました。

3. FM 音源の処理速度の限界

諦めついでにもう 1 つ。アセンブラで FM 音源レジスタを直接叩いたことがある人ならば知っていることですが、FM 音源レジスタの読み書きは FM 音源アドレスポート($00E90001)と FM 音源データポート($00E90003)という 2 つのポートをアクセスすることによって行います。ここで、それぞれのポートに書き込んだ後、FM 音源データポートの書き込みビジーフラグ($00E90003 の MSB)がクリアされるまで次の書き込みを行ってはいけないという決まりがあります。FM 音源データポートへの書き込みの後ビジーフラグがクリアされるまでにかかる時間は、FM 音源 LSI(YM2151)の入力クロックの 68 クロック分です。YM2151 には 4MHz のクロックが入っていますから、FM 音源データポートへの書き込みを繰り返す場合には少なくとも 17 μ 秒以上間隔をあけて行わなければならないことになります。実際にこれよりも短い間隔で FM 音源データポートに書き込もうとすると、書き込みに失敗して期待通りの音が出なくなります。

音楽 CD のサンプリング周波数は 44.1kHz です。単純に割り算をすると、1 周期あたり約 22.6757 μ 秒しかありません。しかもステレオですから、1 周期の間に 2 チャンネル分のデータを処理しなければなりません。

FM 音源データポートへの書き込みは 1 回あたり最低でも 17 μ 秒以上かかり、2 チャンネル更新するためには TL を 2 つ更新するため少なくとも 2 回データポートに書き込まなければなりませんから、17*2=34>22.6757 であり、実際に動かして確かめるまでもなく、FM 音源のみで PCM データをステレオで 44.1kHz という周波数で再生することが不可能であることがわかります。

仕方がないので、44.1kHz でのステレオ再生は諦めて、周波数を落としてステレオ再生することを考えましょう。

4. FM 音源で PCM データを再生する方法

ここで説明する方法は伊倉 "DigitalJunkie" 晴読氏が“志村けんX”や STPLAY.X で使用した方法を私が改良したものです。

4.1. 矩形波に近い音を作る

まず、FM 音源を 1 チャンネル使って、波長が非常に長くてなるべく矩形波に近い音を作ります(図 1)。この波形が、変位が最大になった状態をどれだけ安定して維持できるかが、再生できる PCM の音質に影響してきます。

図 1 矩形波に近い音の波形
図 1 矩形波に近い音の波形

矩形波に近い音のパラメータ(FM 音源レジスタに設定する値)は、次のような方法で独自に決定しました。

FM 音源のレジスタにどのようなパラメータを指定するとどのような音(波形)が作られるのかを数値計算で予測してグラフを描き、それがなるべく矩形波に近付くようにパラメータを調整して、目的に合ったパラメータを見つけるのです。

変調を強くかけたほうが矩形波に近付けやすいので、ここではコネクションを 0 にして 4 つのスロットを直列に接続します。フィードバックは使いません。すると、生成される波形は時刻 t に関する次のような関数で予測できます(波形を予測するための式は『Inside X68000』の記述を参考にしました)。

    変位(t)=α(C2)*sin(MUL(C2)*t
           +α(M2)*sin(MUL(M2)*t
           +α(C1)*sin(MUL(C1)*t
           +α(M1)*sin(MUL(M1)*t))))
    α(M1)=10^(-0.75/20*TL(M1)+e/2)
    α(C1)=10^(-0.75/20*TL(C1)+e/2)
    α(M2)=10^(-0.75/20*TL(M2)+e/2)
    α(C2)=10^(-0.75/20*TL(C2)+e/2)
    MUL(n)=スロットnのMUL(周波数の倍率)で掛ける値(0.5,1~15)
    TL(n)=スロットnのトータルレベル(0~127)
    t=時刻
    e=2.718281828459(自然対数の底)

グラフを描きながら MUL(n) と TL(n) を少しずつ変化させ、なるべく波長が長くて矩形波に近くて最大変位が安定している波形を生成するパラメータを探した結果、次のようなパラメータが得られました。

    MUL(M1)=1,MUL(C1)=1,MUL(M2)=1,MUL(C2)=0.5
    TL(M1)=45,TL(C1)=36,TL(M2)=34,TL(C2)=0
  または
    TL(M1)=47,TL(C1)=38,TL(M2)=35,TL(C2)=0

この矩形波に近い音の波長は、ほぼ 0.103563 秒であることが実験的にわかっています。

4.2. 変位の制御

コネクション 0 で生成される波の振幅は、キャリア 2(C2)のトータルレベル(TL)を変化させることで、キーオンしたままリアルタイムに変動させることができます。TL=0 のとき振幅は最大になり、TL=127 で最小(無音)になります。矩形波が最大変位を安定して維持している期間は、振幅が変位そのものを表しているので、C2 の TL を操作することでリアルタイムに変位を指定できることになります。TL を変化させることで生じる矩形波の変位の変動が、FM 音源で PCM データを再生する場合の音の素になります。

なお、TL で指定した数値に対して変位が指数関数的に変化するのに対して、一般的に PCM データは直線的な値なので、PCM データから TL に与える値を求めるためには対数関数による変換が必要です。具体的には、TL に応じて出力される変位は

    L=10^(-0.75/20*TL)

という式で計算される L に比例します(図 2 および図 3)。

図 2 TL と変位の関係
図 2 TL と変位の関係
図 3 矩形波に近い音の最大変位を TL で動かす
図 3 矩形波に近い音の最大変位を TL で動かす

PCM データは、大雑把な言い方をすれば音の波を一定の間隔で細切れにして得られる変位を並べたものですから、それを対数関数で変換して C2 の TL に流し込んでやれば、FM 音源で PCM データを再生できるということになります。なお、1 データ毎に対数関数を計算していたのでは遅くて仕方がないので、実際には PCM データの変位から TL への変換にテーブルを使います。16 ビットの PCM データを 7 ビットの TL に変換するために 64KB のテーブルを使います。

4.3. 複数の矩形波を重ねる

さて、TL で変位を自由に操れるといっても、矩形波(に近い音)が 1 つだけでは安定して使える期間が短すぎて、PCM データを長時間連続して再生することができません。そこで、この矩形波に近い音を Ch1~Ch4 の 4 つのチャンネルで Ch1→Ch2→Ch3→Ch4→Ch1→…の順序で、なるべく正確に 1/4 周期ずつずらして発生させます(図 4)。

図 4 矩形波に近い音を 1/4 周期ずつずらしてキーオンする
図 4 矩形波に近い音を 1/4 周期ずつずらしてキーオンする

この後、Ch1~Ch4 がそれぞれ安定して最大変位を維持している範囲を 1/4 周期ずつピックアップし、それぞれその範囲で TL を操作します。

4.4. STPLAY.X の場合

STPLAY.X では、PCM データを TL に変換して乗せるチャンネルの順序が常に Ch1→Ch2→Ch3→Ch4→Ch1→…となっていて、使用していないチャンネルはすべて最大変位(TL=0)の半分の変位(TL=8)に固定されていました。この方法では、Ch1 と Ch3、Ch2 と Ch4 がそれぞれ 1/2 周期ずつずれていますから、使用するチャンネルの変位を TL=8 の前後で高速に変動させてやれば、最終的には変位 0 を挟んで上下に高速に変動する波が作り出されます(図 5)。

図 5 矩形波に近い音の+側だけ使う
図 5 矩形波に近い音の+側だけ使う

この方法の欠点は、出力される音の最小の変位を TL=8 に割り当ててあり、図 2 からわかるように TL=8 の近辺では変位の分解能が低いために波形の再現性が悪く、音量に関係なく大量の高周波ノイズが発生してしまうことです。

4.5. 新しい方法

私が採った方法は、見掛けは STPLAY.X の方法よりもむしろ簡単です。Ch1 と Ch3、Ch2 と Ch4 はそれぞれ 1/2 周期ずつずれているので、Ch1 の変位が + 側にあるとき Ch3 の変位は - 側にあります。そこで、Ch1 の変位が + 側にある期間は、+ 側の PCM データを Ch1 に、- 側の PCM データを Ch3 に乗せるのです。使っていないチャンネルはすべて無音(TL=127)に固定します。他のチャンネルを使うときも同様です(図 6)。

図 6+側と-側で使うチャンネルを変える
図 6 +側と-側で使うチャンネルを変える

この新しい方法では、出力される音の最小の変位を TL=127 に割り当ててあり、図 2 からわかるように TL=127 の近辺では変位の分解能が非常に高いので、波形の再現性が STPLAY.X の方法よりも圧倒的に良くなります。

4.6. 変位の符号に応じたチャンネルの切り換え

ところで、当然のことですが、変位が + 側にあるときと - 側にあるときで使用するチャンネルを変えるということは、変位の符号が変わる度に使用するチャンネルを切り換えなければならないということです。チャンネルを切り換えるにはそれまで使っていたチャンネルを無音にした上で次に使うチャンネルにデータを乗せなければなりません。すると、チャンネルを切り換える瞬間に、最短でも FM 音源レジスタを 1 つ更新する(1 つのチャンネルを無音にする)のにかかる時間だけ、本来のデータと異なる変位を出力してしまうことになります。たとえ一瞬でも局所的に本来のデータと大きく異なる変位を出力するとプチノイズになってしまうので、いかにしてなるべく正しい変位を出力しつつチャンネルを切り換えるかが重要になってきます。

変位の符号が変わるということは、極端な高周波成分を含んでいない限り、その前後の変位は 0 に近いはずです。そこで、0 を挟んで変位の符号が変わっているところの前後(どちらか一方が + 側で他方が - 側)で、前後のうち変位が 0 に近い側の変位を強制的に 0 にすることにします。波形が少し乱れますが、前述のように極端な高周波成分が含まれていなければもともと 0 に近かったデータですから、音質の大きな劣化はないはずです(図 7)。

図 7 符号が変わるとき変位が 0 に近い側を 0 にする
図 7 符号が変わるとき変位が 0 に近い側を 0 にする

変位が 0 になっていれば、チャンネルの切り換えは簡単です。変位が 0 のデータを出力すればそのチャンネルは無音になりますから、そのまま次のデータから次のチャンネルに移ることができます。

4.7. 1/4 周期毎のチャンネル遷移

ところで、Ch1~Ch4 がそれぞれ安定して最大変位を維持している範囲を 1/4 周期ずつピックアップすると書きましたが、実はこれが非常にシビアな処理になります。再生が続いている間は 4 チャンネルともキーオンしたままですから、波の位相は MPU の動作とは無関係に正確に進行して行きます。これに追従して正確なタイミングで使用するチャンネル(TL を操作するチャンネル)を切り換えないと、あっという間に最大変位が安定している範囲を外れ、期待通りの音が出なくなってしまうのです。

STPLAY.X では上記の音の波長の値が不正確で、短時間で破綻してしまうため数分間隔でキーオンからやり直すことになっており、キーオンし直すときに異音が出てしまっていました。今回私は実験で上記の音のかなり正確な波長として 0.103563 秒という値を得、少なくとも 1 時間程度ならばキーオンし続けても破綻しないようにすることに成功しました。

実際に矩形波に近い音の波長を管理する方法は以下の通りです。

まず、非常に短い間隔で FM 音源レジスタを更新するために、TIMER-D による割り込みを使います。TIMER-D は CONFIG.SYS に PROCESS= の指定をしたときに Human がバックグラウンド処理のために使用しますが、PCM を再生している最中にバックグラウンドタスクを回すだけの MPU パワーが残っているとはとても思えませんから、ためらわずに TIMER-D 割り込みを Human から奪って使います。

TIMER-D 割り込みの割り込み間隔は 1 μ 秒単位で指定できますが、FM 音源レジスタを 1 つ更新するのに 18 μ 秒以上かかるので、割り込み間隔をあまり短くしても意味がありません。そこで、X68030 の場合はデフォルトで 22 μ 秒間隔で割り込むことにします。周波数に換算すると 45.455kHz になります。ステレオ再生時は 1 サンプリングあたり FM 音源レジスタを 2 回更新する必要があるので、22.727kHz になります。これは 44.1kHz の半分の 22.05kHz よりも少し高い周波数です。

FM 音源で PCM を再生する場合、最も厄介なのが、FM 音源で発生させた矩形波に近い音の波長の管理です。前述の通り、FM 音源で発生している音の波長は 0.103563 秒であり、割り込み間隔の 22 μ 秒で割ると 1 周期あたりの割り込み回数が約 4707.41 回ということになります。キーオンは 4707.41/4=1176.85 より割り込み回数にして 1176~1177 回の間隔で行えばよいとして、その後の 1/4 周期毎のチャンネル遷移を如何に正確に行うかが問題です。22 μ 秒という短い間隔の割り込み要求を MPU が 1 回も取りこぼさないという保証はなく、1 周期あたり 1 回ずつずれただけでも誤差が蓄積して数秒から数 10 秒で破綻してしまいます。特に後でディスクアクセスをしながら PCM をステレオ再生しようとしていることを考えると、割り込みを取りこぼすのは必至で、TIMER-D の割り込み回数だけに頼っていたのでは波長の管理はできないという結論に達します。

そこで、TIMER-C のカウンタを併用することにします。TIMER-C は普段は 1/100 秒カウンタとしてカーソルの点滅などに使用されているものです。TIMER-C を 16 μ 秒単位でダウンカウントするモードにして、256 回でオーバーフローするように初期値を与えます。すると 0.103563/(0.000016*256)=25.283935546875、0.283935546875*256=72.6875 となって、1 周期の間に TIMER-C は正確に 25 回オーバーフローしてから元の値よりも 72.6875 だけ減ることがわかります。これを利用して、TIMER-D のカウントのみで TIMER-C が 25 回オーバーフローする頃まで進んでから、残りの時間を TIMER-C が前回よりも 72.6875 小さい値になるまで TIMER-D 割り込みの中で TIMER-C のカウンタを監視しながら進めることで、1 周期の終わりを決定します。実際には TIMER-C のカウンタは整数なので、72.6875*256=18608 から「ワードサイズのワークから毎回 18608 ずつ引き、その上位バイトを採用する」という方法で TIMER-C の値を予測して比較します。

この方法によって 0.103563 秒という微妙な波長を(平均して)極めて正確に維持することが可能になり、1 時間くらいキーオンしたままでも大きな誤差が生じず、再生しつづけることができるのです。

ところで、1/4 周期進んだところで強制的に次のチャンネルに切り換えてしまうと、変位が大きな区間で切り換えることになった場合にプチノイズが発生してしまいます。今回採用した矩形波に近い音は、独自に作り出したパラメータで生成されていることもあって、最大変位が安定している範囲が 1/4 周期の 0.02589 秒よりも約 70% 長い 0.04423 秒あることがわかっています。つまり、あまり厳密に 1/4 周期毎にチャンネルを切り換えなくても、チャンネルを切り換えるタイミングが多少前後した程度ならば問題なく再生できるのです(勿論、長時間再生したとき 1 周期の長さの平均が 0.103563 秒になるように厳密に制御する必要があります)。

変位の符号が変わるときに変位を強制的に 0 にしているので、1/4 周期が経過しても少しの間はチャンネルを変えずに変位の符号が変わるのを待ち、変位の符号が変わった瞬間に符号と同時に 1/4 周期毎のチャンネルの遷移も行うことにしました。このようなチャンネル遷移の遅延はあまり長くはできませんが、たいていの PCM データは符号が頻繁に入れ替わるので、少し待つだけでプチノイズはほとんど除去されます。大きな低周波成分があるときは少し待っても変位の符号が変わらないことがあるので、そのような場合は途中で諦めて強制的にチャンネルを遷移します。

5. ステレオ化

前述のように、FM 音源で PCM を再生するためには 4 チャンネル必要です。FM 音源には全部で 8 つのチャンネルがありますから、すべてのチャンネルを使えば FM 音源のみで PCM をステレオ再生することができます。

注意しなければならないのは、FM 音源レジスタは 2 つ同時に更新できないということです。そのため、右側の変位を更新するタイミングと左側の変位を更新するタイミングが微妙にずれてしまいます。この問題を解決するには、PCM データの周波数を変換するときに、左右の出力データのサンプリング位置をサンプリング間隔の半分だけずらしておかなければなりません。

STPLAY.X では FM 音源が担当する音が片側だけだったので、例えば Ch1 を使っている間は FM 音源アドレスポートを Ch1 の TL($78)に固定して FM 音源データポートだけを更新し続けることができました。しかし、ステレオ化する場合、Ch1 の TL($78)と Ch5 の TL($7C)を交互に更新するために FM 音源アドレスポートも毎回更新しなければなりません。そのため、FM 音源による PCM のステレオ再生の負荷はモノラル再生の 2 倍以上になります。

6. サンプリング周波数の変換

入力データのサンプリング周波数と FM 音源で PCM を再生する際の出力時のサンプリング周波数は異なる場合が多いので、PCM データのサンプリング周波数の変換が必要です。サンプリング周波数の変換は、PCM データを OPM データに変換する前に行います。すなわち、PCM→PCM のサンプリング周波数変換を行います。

S44PLAY.X では、次の 3 通りのサンプリング変換方法を選べるようにしてみました。

6.1. 間引き・伸張

サンプリング間隔が短くなる場合は、データの伸張を行います。1 データ毎にサンプリングのタイミングの誤差を蓄積し、誤差が 1 データ分に達したら最後データを重複して出力します。

サンプリング間隔が長くなる場合は、余った入力データを捨てます。

この方法は非常に簡単なのでリアルタイムに変換できますが、音質は良くありません。

6.2. 直線補間

入力された PCM データを直線で補間した上で、出力側のサンプリング間隔でサンプリングしなおします(図 8)。

図 8 サンプリング周波数の変換(直線補間)
図 8 サンプリング周波数の変換(直線補間)

この方法では 1 データあたり 1 回の乗算が必要なので、68000 ではリアルタイムに変換できません。

6.3. 面積補間

面積補間という呼び方は筆者が勝手につけたものです。

入力された PCM データを直線で補間した上で、出力側のサンプリング間隔で刻み、切り取られた各区間の平均の高さ(面積に比例する)を出力データとします。

図 9 サンプリング周波数の変換(面積補間)
図 9 サンプリング周波数の変換(面積補間)

この方法では 1 データあたり 2 回以上の乗算が必要なので、リアルタイム変換ができるのは事実上 68060 のみです。しかし、今回採用した方法の中では最も音質が良いので、音質にこだわる場合はあらかじめこの方法で変換したデータのファイルを作っておくべきです。

7. 実装

060turbo で作り始めたので、.S44 ファイルをオンメモリで再生できるようにすることは比較的容易でした。060turbo に大容量の SIMM を装着していれば、数分間の曲をオンメモリで再生することができました。

プログラムの名前は、.S44 ファイルを直接再生できるということで、S44PLAY.X にしました。再生中はマシンのパワーをほとんど使ってしまうので他のことをする余裕がないことと、ディスクからデータを読み込みながら再生する機能があるため、他の音源ドライバのように常駐はしません。

次に、ファイルから読み込みながらの再生ができるようにしました。普通に、バッファを 2 つ使って、一方を再生している間に他方にファイルを読み込んでおくという方法です。68030 モードでも動くようになりました。ハードディスクや MO に置いてある .S44 ファイルを延々と再生することができます。当然のことですが、フロッピーディスクではデータの供給が間に合いません。

始めは音楽 CD から CD2PCMT.X を使って吸い出して作った .S44 ファイルを使ってテストしていたのですが、いちいち .S44 ファイルを作るのが面倒になり、数 10MB 単位のファイルを幾つも転がしておけないので、音楽 CD の音声トラックを直接読み込みながらの再生を試みてみました。CD2PCMT.X のソースを参考にしながら作ったのですが、初めはだいぶてこずりました。SCSI バスを何度もハングアップさせながら作っているうちに、ハングアップしても容易に復帰できるようにするための仕掛けのほうが強力になりました。X680x0 が CD プレイヤーになっている様はなかなか壮観です。

S44PLAY.X の公開済みの最新版は激光電脳倶楽部 Vol.7 に収録されていますが、バグが取れていないので、月刊電脳倶楽部のほうで更新する予定です。注 1

7.1. フェードイン・フェードアウト

再生中はキーオンしたままなので、FM 音源のエンベロープに関するレジスタを操作することで簡単にフェードイン・フェードアウトを行うことができます。フェードイン・フェードアウトの速度の指定が可能です。再生中にいつでも好きなところでフェードアウトを開始することができます。

8. FMP ファイル

ステレオ再生時の片側のサンプリング周波数は最大でも 25kHz 程度までなので、低いサンプリング周波数でいかに綺麗に再生するかが重要になってきます。しかし、サンプリング周波数の変換を複雑にするとマシンのパワーが不足するのでリアルタイムでの変換ができなくなってしまいます。そこで、高品質な変換を行う場合は、サンプリング周波数の変換(および PCM から TL への変換)を済ませたデータを一旦ファイルとして出力しておくことにしました。再生時には変換済みのデータをファイルから読み込みながらただひたすら FM 音源レジスタに垂れ流すだけにすることで、特に X68030 の場合は FM 音源 LSI(YM2151)の応答速度ぎりぎりの高いサンプリング周波数で再生できるようになりました。

リアルタイム変換で高品質なステレオ PCM 再生を行うには 68060 以上のパワーが必要です。しかし、データをあらかじめ変換しておけば 68000 でもディスクからデータを読み込みながらの再生が可能です。再生エンジンをゲームなどに実装するときは、あらかじめ FMP フォーマットに変換済みのファイルを用意しておくことで、主題歌などを高品質の PCM で再生することが可能です。

9. 困ったこと

9.1. アセンブルできなくて…

S44PLAY.X のソースリストはオールアセンブラで 17000 行以上あります。その中に 1 つで 4000 行近いマクロ定義があり、マクロ内のローカルシンボルが多すぎるために従来のアセンブラではアセンブルできません。仕方がないので HAS060.X のほうを改造してアセンブルしています。注 2

9.2. SCSI の強制ソフト転送

ディスクから PCM データを読み込みながら再生する場合、データの読み込みに DMA 転送が使用されていると、MPU が割り込みを取りこぼしてしまうので正常に再生できなくなります。そのため、データの読み込みはソフト転送で行う必要があります。

X68030 や Mach-2 の SCSI-BIOS の高レベル転送コール(_S_READ/_S_READEXT)は SRAM のソフト転送フラグに対応しているので問題ないのですが、SUPER から CompactXVI までの X68000 の内蔵の SCSI-BIOS の高レベル転送コールはソフト転送に対応していないので、これらのコールを自前で展開して低レベルのソフト転送コールを使うようにする必要がありました。

9.3. 040turbo には酷?

X68030 と 060turbo の 030 および 060 モードでは 25kHz で問題なくステレオ再生できます。ところがどういうわけか、040turbo の 040 モードに限ってステレオ 25kHz で正常に再生できないのです。68030 よりも 68040 のほうが速いはずなのに…。

これはどうやら 040turbo の 040 モード時のバスアクセスが極端に遅いことが原因のようです。060turbo の 060 モードでもバスアクセスは 030 モードよりも遅くなります。しかし、50MHz の 68060 はバスアクセスの遅さを補って余りあるパワーを持っているのに対して、25MHz の 68040 ではそれを補いきれないのです。こればかりは、割り込み間隔を伸ばす以外に対策がなさそうです。

10. おわりに

S44PLAY.X は、X680x0 用のプログラムの中で最も FM 音源を酷使するプログラムの 1 つと言えると思います。何しろ、FM 音源 LSI(YM2151)をこれ以上速く制御できないという速度で長時間アクセスし続けるのですから。

PCM 音源とは到底呼べないような音源を使って PCM データを再生するという発想は、パソコンがまだ 8 ビットだった時代からあったものです。古くからの Oh!X の読者ならば、あの「サンダーフォース!」の“声”が記憶に残っている人も少なくないのではないでしょうか。

パソコンを特定のソフトを動かすためのプラットフォームとしてだけでなく、パソコンそのものをオモチャとして使う、しかも他の人が思い付かない、あるいは思い付いても誰もやらないような突拍子もない使い方をする、そんな楽しみ方をこれからも続けてゆきたいものです。


脚注

1. S44PLAY.X の最新版はこちら… S44PLAY.X / FMPPLAY.X - ステレオ PCM 再生 - サウンド - ソフトウェアライブラリ - X68000 LIBRARY

2. S44PLAY.X v1.02 のソースは 25000 行以上あります。


更新履歴

2018 年 10 月 23 日

https://stdkmd.net/kohx3/ に引っ越しました。

── 続きを読む ──── 続きを隠す ──

2015 年 3 月 16 日

http://stdkmd.com/kohx3/ に引っ越しました。

2002 年 10 月 1 日

HTML 化。

1999 年 9 月 20 日

Oh!X 1999 年夏号に掲載。