ソフトウェア音源 『μ』(turboR用)

仕様説明(仮設)

μの基本性能
 
 
μの内部構造
 
 
メモリマネージャー
 
 
初期設定
 
 
操作プログラム
 
 
実行例
 
 

《《 μの基本性能 》》

サンプリングレートは15.7KHz
チャンネル数は2〜8、設定後は可変・固定周波の組み合わせを自由に選択できます。
音量は64段階。1/60秒単位の指定が可能です。
1周波256バイトを音色として割り当て、31.4KHzのレートで計算します。
サンプリングモードでは再生速度を変更して音階を付ける事が可能です。
※中央値0は80h
データの制限はなく、メモリが許す限り再生できます。
音声データは2bit4bit形式(混在可)の非可逆圧縮した物を使用します。
ADPCMに近い形式です。
可変周波は1チャンネル当り10%、固定周波だと15%必要で、
更にユーザー側がPCMへデータ転送する際に10%程度消費されます。
例えば、可変・固定周波をそれぞれ2チャンネルずつ指定した場合、
計算に10×2+15×2で50%、
PCM転送に(100%−50%)×10%で5%消費すると考えられ、
合計55%の負担という事になります。
ユーザー側は、転送用にIXレジスタを確保し、
プログラム中280ステート以内に
『 DB.A4.B7.28.07.DD.7E.00.D3.A4.DD.23 』
もしくは
『 C7(RST 00H) 』
のコードを書いて下さい。これでPCMへのアクセスは完了します。
▽詳細については後述の実行例を参照して下さい
A1STでは、曲の内容によって音割れノイズ等が発生する事があり、
又、GTに比べ高音が出にくい等の症状が確認されています。

《《 μの内部構造 》》

μでは、1/60秒毎に発生する割り込みを使って
PCMに出力するデータの計算を行っています。
ここで簡単に処理を説明すると、
 
チャンネル毎に      各チャンネルの
可変・固定周波の    計算結果を合成し    I/O出力
計算を行う        バッファに転送
という流れになっており、発音はμの仮想レジスタによって制御されます。
バッファについては計算時間を考慮して1/30秒分確保していますが、
これにより発音が同時間、更に固定周波はノイズ除去のため約1/2000秒余分に遅れます。
サンプリング指定 (0) 固定波形再生(SCCエミュレーター等)
00h - 0Fh : 可変周波の音色  : ポインタ下位上位(2バイト) × 8チャンネル
10h - 1Fh : 可変周波の周波数 : 下位上位(2バイト)(*1) × 8チャンネル
20h - 27h : 可変周波の音量  : 00〜3Fh(1バイト) × 8チャンネル
サンプリング指定 (1) 連続波形再生(サンプリング再生)
00h - 0Fh : 可変周波の音色  : ポインタの格納アドレス下位上位(2バイト) × 8チャンネル
10h - 1Fh : 可変周波の周波数 : 下位上位(2バイト)(*2) × 8チャンネル
20h - 27h : 可変周波の音量  : 00〜3Fh(1バイト) × 8チャンネル
   7Dh    : サンプリング指定 : ビットが1の時有効(可変周波のみ)
   7Eh    : 可変・固定の選択 : 各ビットがチャンネルに対応(0:可変周波 1:固定周波)
   7Fh    : 波形のリセット  : ビットが1の時にリセットされます(*3)
80h - FFh : 固定周波の設定  : 16バイト(*4) × 8チャンネル
 
(*1) f=0.47912n 例えば「ラ」の音(440Hz)なら 0396h となります。
(*2) 再生速度×128。
   音階を付けずに15.7KHzのサンプリングデータをそのまま鳴らしたい場合は 0080h となります。
   設定する値は00F6h(約1.92倍)までにして下さい。
(*3) 固定周波が選択されている場合は出力計算の初期化、
   可変周波なら強制的に波形データの最初から参照されます。
   μは1周波が終わるまで次の波形に更新しない仕様のため、
   発音時の波形を揃えたい場合又は、サンプリング再生の最初に指定して下さい。
   尚、設定後に0クリアする必要はありません。
(*4) +1からの2バイトがポインタ、+5が音量、+6が再生形式で、
   以上4バイトがユーザー側が設定してもよい場所です。
   ▽詳細については後述の実行例を参照して下さい
0000h - 000Bh : PCM出力(RST 00H)
000Ch - 000Dh : 内部エラーアドレス
    000Eh     : PCM出力数(1/120秒分で、129〜133の値を取る)
    000Fh     : フレームカウンタ(割り込み発生後にインクリメントされる)
0010h - 0012h : 内部で使用
0013h - 0014h : reserved
    0015h     : MSX−DOS2が使用するバンク
0016h - 0017h : FM音源のI/Oウェイト
0018h - 001Ah : 内部で使用
001Bh - 001Fh : 割り込みフック1(基本処理後に呼ばれる(*1))
0020h - 0022h : 内部で使用
0023h - 0027h : 割り込みフック2(μの基本処理後に呼ばれる(*2))
0028h - 0037h : ユーザー側で使用可能
0038h - 00FFh : 割り込み処理
0100h - 03FFh : ユーザー側で使用可能
0400h - 0BFFh : PCM出力変換表
0C00h - 0CFFh : メモリマッパー
0D00h - 0DFFh : μレジスタ
0E00h - 0EFFh : PSG・FM音源レジスタ
0F00h - 1347h : PCMバッファ
1348h - 1EE3h : ワークエリア
1EE4h - 2187h : 基本プログラム(一部)
2188h - 244Bh : 操作プログラム
244Ch - 3FFFh : ユーザー側で使用可能
(*1) 割り込み発生時、CレジスタにVDPの読取情報を入れてコールされます。
   拡張する場合は、直後に119ステート消費されている事と
   終了時にPCMへのアクセスを行って下さい。
   この時、CYフラグがクリアされているとμの演奏処理は行われません。
   ※BC・DE・HL・AFレジスタは破壊しても構いません
(*2) ここを拡張してμの演奏を行います。
   必要な処理を任意で追加して下さい。制約は特にありません。
μの実行に際して致命的な障害が生じた場合は
Aレジスタにエラー番号をセットした後、
アドレスの000C・000Dhの内容が示すアドレスにジャンプします。
 
00h : メモリ不足
01h : フレームオーバー
 
エラー発生時は全て処理を中止して復旧処理
もしくはプログラムの見直しを行って下さい。

《《 メモリマネージャー 》》

PCMの計算をするには大量のメモリが必要となる訳ですが、
μではメモリマネージャーが管理するメモリを使って処理を行っています。
管理できる容量は256K512Kバイト。
256バイト1単位とし、アクセスはポインタを媒介としてやり取りされます。
又、ここで言うポインタとは2バイトの数値で
上位がメモリのバンク・下位がアドレスを示しており
例えば、値が0312hならバンク3の+1200hという事になります。
領域の割り当て(準備)
 1FC5h  入力: DE=ポインタ B=割り当てる単位数
        出力:
        破壊:
        使用: ページ1
 
メモリマネージャーにメモリを管理させる領域を指定します。
例:バンク7の+800h〜+3FFFhまでを割り当てたいなら、
   DE=0708h B=38hとなります。
※一度割り当てたメモリは元に戻す事はできません
 
メモリの要求
 1FEAh  入力: DE=要求する単位数
        出力: DE=ポインタ
        破壊: AF・AF’
        使用: ページ1
 
メモリを要求します。この時、要求量がである場合、
返されるポインタは直接そのメモリを示します。
※メモリが足りない場合は内部エラーとなります
 
メモリの開放
 2079h  入力: DE=ポインタ
        出力:
        破壊: DE・AF
        使用: ページ1
 
メモリを開放します。
 
読み込み
 20D2h  入力: DE=ポインタ    H=上位アドレス   A=単位数
        出力: DE=ポインタ(次) H=上位アドレス(次)
            Z’フラグ(ONで終了)
        破壊: AF・AF’
        使用: ページ1・2
 
確保されたメモリ領域からレジスタHが示すアドレスにブロック転送を行います。
領域が大きい等の理由で転送範囲を小さくした場合は
途中のポインタが返されますので、続行させる時はその値を指定して下さい。
 
書き込み
 20D7h  入力: DE=ポインタ    H=上位アドレス   A=単位数
        出力: DE=ポインタ(次) H=上位アドレス(次)
            Z’フラグ(ONで終了)
        破壊: AF・AF’
        使用: ページ1・2
 
確保されたメモリ領域にレジスタHが示すアドレスからブロック転送を行います。
領域が大きい等の理由で転送範囲を小さくした場合は
途中のポインタが返されますので、続行させる時はその値を指定して下さい。
 
メモリ容量の取得
 216Fh  入力:
        出力: DE=単位数
        破壊: F
        使用:
 
メモリ容量の残りを取得します。
尚、このルーチンはPCMへのアクセスを行っていません。
実行時に34ステート消費される事に注意して下さい。
 
<初期値>
A1ST   68ブロック  17,408バイト
A1GT 1076ブロック 275,456バイト
 

《《 初期設定 》》

BASICからμBIOSを起動させると、R800 ROMモードに設定された後、
メモリはMSX-DOS領域と一部のバンクを除いて
全てメモリマネージャーの管理下に置かれます。
μBIOSが使用するメモリバンクは
02h.03h.04h.05hで、ページ0メモリマップ参照)は02hとなっており、
ユーザー側は
00h.01h.06h.07h.08h.09h.0Ch.0Dh.0Eh.0Fhのバンクが使用可能です。
これは機種によるメモリ容量の違いに関係なく使う事を目的としています。
初期化
 C000h  入力:
        出力:
        破壊: 全て
 
ここからμが組み込まれます。BASICからコールして下さい。
 
チャンネル数及びマスターボリュームの設定
 1EE4h  入力: A=チャンネル数(4〜8) DE=音量
            B=補整率(00h-80h)
        出力:
        破壊: 全て
        使用: ページ3
 
チャンネル数の設定、及び各チャンネルの合計値から
PCMに出力する値を算出するための変換表を作成します。
音量は、800hの時に合計値と出力値が同じに、
又、合計値が出力の限界に近付くと
補整率が0に近い程大きく補整される様になっています。
※演奏中にコールした場合、動作の保証はできません
 
PCMバッファのクリア
 1F06h  入力:
        出力: IXレジスタの設定
        破壊: F・裏レジスタ全て
        使用:
 
PCMバッファの内容を無音状態にクリアします。
初期設定時又はディスクアクセス等で演奏を停止した場合に必要です。
※演奏中(実行中)には使用しないで下さい
 
演奏開始
 1F19h  入力:
        出力: IXレジスタの設定
        破壊: 表レジスタ全て
        使用:
 
演奏準備をした後、割り込みのタイミングが取れ次第、演奏を開始します。
 
PCM計算
 1F62h  入力:
        出力:
        破壊: 全て
        使用: ページ1・2・3
 
μレジスタを参照し、PCMの出力計算を行います。
割り込みフック2からコールして下さい。
※処理が終了する前に再び呼び出された場合は内部エラーとなります
μは一部のプログラムを除きSPの操作を行っていません。
このため、実行時に使用ページ上にSPがあった場合は問題が発生します。
無用の混乱を避ける為にもSPはページ0に置くのが望ましいでしょう。
尚、割り込みフック2では150バイト程スタックを確保しています。
これ以上必要な場合はユーザー側で工面して下さい。

《《 操作プログラム 》》

これらのプログラムは無くても動作に支障はありません。
必要無いならデータを破壊しても構いません。
ブロック転送
 2188h  入力: HL=転送元 DE=転送先 BC=転送長
        出力:
        破壊: 表レジスタ全て
        使用:
 
アセンブラで言う所のLDIRと同じ働きをします。
 
波形の補間計算(設定)
 21EFh  入力: HL=基準データアドレス DE=ポインタ
            A=データ長(0〜6) C=補間係数
        出力:
        破壊: 表レジスタ全て・AF’・IY
        使用: ページ1・2
 
HLが示す基準データから256バイト長の波形データを作成します。
次項の計算ルーチンと併用して下さい。
データ長は2^(n+1)バイトで、
補間係数は小さくなるほど高周波成分を多く含む様になり、
大きくすると三角波の様ななだらかな音色になります。
 
波形の補間計算(計算)
 242Ch  入力:
        出力: Zフラグ(クリアで終了)
        破壊: 表レジスタ全て・AF’・IY
        使用: ページ1
 
前項のルーチンで設定後、分割して計算を行います。
これは、1つのデータを作成するのに
50%も消費(1/60秒換算)される事に対しての対応処置で、
設定ルーチンも同様に1回当たり2%程度消費されます。
 

《《 実行例 》》

ここでは
実際どの様にしてルーチンを呼び出すのか、使い方とその手順を説明します。
尚、アドレスや引数等は現バージョンでの話です。
今後変更される可能性は十分にあります。
BASICからμBIOSを読み込み、初期化を実行。全てはここから始まります。
μを動かすには全てのページメインメモリに変えて、
メモリマネージャーに管理させてもよいメモリ領域を割り当てて下さい。
起動時に多少は割り当てていますが、
A1STのメモリ容量では足りなくなると思われます。
 
又、スロット切替・拡張メモリについてはμは全く感知していません。
ユーザー側が必要とする場合は任意でプログラムを組み込んで下さい。
初期化が終わったら割り込み禁止・解除を行って下さい。
μでは割り込み処理時以外 割り込み制御を行っておらず、
拡張する際は重複してイベントを発生させない様注意が必要です。
例えば、メモリの要求開放時に割り込みが発生して
割り込み処理中に再び同様の処理が行われれば誤作動を起こします。
特に走査線割り込み等を使う場合は、
禁止・解除及びプログラムの組み立て等 十分考慮して下さい。
 
割り込みが発生するとフック1
そして何も拡張されていなければフック2が呼ばれます。
又、演奏開始は主にタイミングを取るのが目的で
コールしなければフック2が呼ばれないという訳ではありません。
PCMバッファμレジスタクリアは演奏前に必ず行って下さい。
チャンネル0・2で音を鳴らす例を示します。
 
初期化を行った後はチャンネル数及び音量の設定が必要です。
仮に4チャンネル構成、補整を掛け
合計値が最大で約2チャンネル分だと想定すると
A=4、DE=400h、B=00h、となります。
 
次は発音の準備。
まず割り込みを禁止して、フック2
ユーザー側で用意した発音ルーチンへジャンプするプログラムを書きます。
発音ルーチンではμレジスタに必要な書き込みを行った後、
PCM計算を呼び出して下さい。
 
接続準備が出来たら演奏開始を実行し、割り込みを解除すれば
割り込みのタイミングを取って演奏が開始されます。
(制御が十分であるなら割り込みの禁止・解除は必要ありません)
 
それでは、「ラ」の音(440Hz)と「シ」の音(494Hz)を出してみましょう。
最初は音色指定(後述の音色作成参照)、
μレジスタの00h・01h、04h・05hにそれぞれ下位上位と設定します。
 
次に周波数、
f=0.47912nなので、μレジスタの
10h・11h、14h・15hにそれぞれ下位上位(96h・03h、07h・04h)、
音量はμレジスタの20h、22hにそれぞれ3Fh(最大)とします。
 
最後にサンプリング指定組み合わせ波形リセットの設定。
μレジスタの7Dh・7Ehに00h、7Fhに05hと書き込めば完了です。
256バイト長の音色データを作るまでの手順を説明します。
 
まずはメモリの確保、
メモリマネージャーを使用しない場合はユーザー側が任意に用意し、
そうでない場合は、DE=0001hとしてメモリの要求を行って下さい。
又、この時返されるポインタはメモリを開放する際にも必要ですので
必ず保存して置いて下さい。
 
メモリが確保できたら、次は補間計算です。
仮に1周波32バイトのデータを用意していたとすると、
HL=データのアドレス、DE=返されたポインタ、A=4、
補間係数Cは04hとでもしておき、補間計算(設定)をコールします。
その後、補間計算(計算)をZフラグがONの間ループでコールして下さい。
これで音色が1つ作成できました。
サンプリングを再生させるまでの手順を説明します。
 
ここでも基本はメモリの確保からです。
まず、メモリマネージャーから必要量のメモリを要求して下さい。
 
MIO形式のデータは、
始めの1バイトが再生形式でその後256バイト単位で中身のデータが続きます。
再生形式は再生時に使用しますので記録しておいて下さい。
 
メモリ上に読み込んだらアドレスの下位を0に揃えて、
返されたポインタに中身のデータ転送して下さい。
 
それではチャンネル1で鳴らしてみましょう。
可変周波の時と同様に準備をした後、
μレジスタの91h・92hに返されたポインタの下位上位、
95hに音量、96hに再生形式を設定して下さい。
 
サンプリング指定組み合わせ波形リセットの設定は
μレジスタの7Dhに00h、7Ehに02h、7Fhに02hと書き込めば完了です。
※再生が終了したらポインタに0300hの値が書き込まれます
※7Fhに書き込むのは、最初と組み合わせ(可変周波・固定周波)を変更する時だけで構いません
チャンネル3で再生速度を変更してサンプリング再生する例を示します。
メモリマネージャーから必要量のメモリを要求して下さい。
但し、DE=0001hを指定してデータ全ての連続したアドレスを保存する必要があります。
データの終端にはポインタとして0301hの値を書き込んで下さい。
 
μレジスタの06h・07hにポインタが格納されたアドレス下位上位を設定。
μレジスタの16h・17hに再生速度の下位上位を設定。(速度×128)
μレジスタの23hに音量を設定。
ポインタが格納されたデータはページ0に置いて下さい。
 
サンプリング指定組み合わせ波形リセットの設定。
μレジスタの7Dhに08h、7Ehに00h、7Fhに08hと書き込めば完了です。
※なるべくサンプリングレートの高いデータを使用しないと音痴になります
MSX turboRのPCMとは一体何なのか!?
悪く言えば、ただのD/Aコンバータ。
良く言えば、バッファ容量1バイトのPCM音源。
PCMを生かすも殺すもユーザーの努力次第と言った所でしょうか。
ユーザー側がPCMへ定期的にアクセスする事でこの音源は成り立ちます。
プログラムの特性を考えて なるべく最適な配置を考えて下さい。
 
PCMの周期は456クロック
(ここで言うクロックとは、CPUの動作が7.16MHzとして換算したもので
DRAMリフレッシュを含まないステートとは別の表現をしています)
実質的には この期間内にアクセスすれば問題ないのですが、
割り込みの発生等を考慮すると
なるべく280ステート以内に配置するのが良いと思われます。
 
又、VRAMアクセスの際62クロック未満はウェイトが掛かる事から
ダミー命令等でタイミングを取る必要はないと思われているかも知れません。
しかし、ウェイトが掛かるとPCMにノイズが入る事が確認されています。
 
IXレジスタについて。
μ内部でも当然ほとんどのルーチンでPCMアクセスが行われ
その都度IXレジスタが変化しています。
演奏中でない時に例えば大量のメモリを読み書き転送したりすると、
場合によってはPCMバッファメモリマップ参照)から出る可能性があります。
処理に時間が掛かる場合は
必要に応じてIXレジスタをPCMバッファの最初の位置に戻して下さい。
但し、一時的であってもIXレジスタを使って演算を行ったり
直接PCMのI/Oを操作してはいけません。
システムは
単にIXレジスタを管理しているだけではなく その命令自体を監視しています。
割り込みを許可しているのであれば割り込みフック2
『 DD.21.00.0F.C9 』
の5バイトを書き込むのが最も簡単です。
 
ちなみに、サブルーチンの最後にアクセスを行うのなら
『 DB.A4.B7.C8.DD.7E.00.D3.A4.DD.23.C9 』
と書いても構いません。



戻る

ツリー表示
トップページへ