トレモロエンベロープ
このドライバの中で、一番解析がややこしかった部分です。
音量が増幅したり減衰したりを繰り返すエンベロープとなります。
コマンド
データ | オフセット | 内容 |
---|---|---|
DDH | +0 | トレモロエンベロープ設定 |
+1 |
b0 - b3: 共通除数兼増減維持カウント(+22H)[維持カウント値]に保存。1-15。 (0禁止。永久ループになる) b4 - b6: (+21H)[タイプB維持カウント]の値 b7: 開始エンベロープタイプ 0=タイプB 1=タイプA-0 |
|
+2 |
b0 - b3: 減算算出用被除数(整数部分) b4 - b7: 加算算出用被除数(整数部分) |
ボリュームエンベロープのコマンドと異なる点は、コマンドにあるデータが直接ワークエリアに保存されるわけではないという点になります。
サンプルとして、DDH 25H 32Hのデータの場合を考えて見ます。
まず、減算算出用被除数 - 加算算出用被除数の値が(+38H)[閾値算出用減算値]に保存されます。3 - 2で01Hが入ります。
次に減算算出用被除数 / 共通除数兼増減維持カウントを整数4bit+小数4bitの固定小数点として計算します。3.0H / 5.0H = 0.9Hとなって、(+23H)[音量減算値]に09Hが入ります。
そして加算算出用被除数 / 共通除数兼増減維持カウント、2.0H / 5.0H = 0.6Hを行い(+24H)[音量加算値]に06Hが入ります。
恐らく考え方としてはこれでいいと思うのですが、このドライバの割り算ルーチンは想定している処理と異なっていました。
割り算は減算ループで実装されているのですが、減算ループで余りが出た時、余りを16倍して減算ループを行うことで小数を求めるのが基本的な方法だと思われます。
ところがここでの方法は、余りが出た時に共通除数から余りを引いて、それを16倍して減算ループしていました。
その答えをcplで反転して4bitのみ取り出す、というような処理です。
この方法でもほぼ同じような結果になるのですが、小数部分で割り切れた場合に答えが違ってしまいます。
それが意図したものなのか、解析に読み違いがあるのか、バグなのかは判別が付きませんが、運用上は計算をしてから数値を決めるのではなく、音を聞いてパラメータを調整すると思うので計算結果が特定の値で違うからと言ってあまり問題にはならないはずです。
データ形式がややこしくなっているのは、データサイズを短くするためだと思われます。
残りは、共通除数兼増減維持カウントとタイプB維持カウントがそのまま(+22H)、(+21H)にセットされます。
データ | 意味 |
---|---|
FEH 01H | (+09H)を01Hにセットする。音名音長のデータ形式指定 |
E9H 1EH | 基本音長30 |
EAH 09H | v9 |
D0H | o6 |
F8H 05H | 波形転送5番(sin波) |
DDH 25H 32H | トレモロエンベロープ設定 開始タイプB (+21H)タイプB維持カウント2 (+22H)維持カウント5 (+23H)音量減算値0.9H (+24H)音量加算値0.6H (+38H)閾値算出用減算値1 |
04H | 音長150クロックでo6c |
FFH | 曲データ終了 |

ボリュームエンベロープと同様にタイプAかBで開始し、タイプCの部分からトレモロが開始されタイプC,Dは存在しない形です。
タイプBのクロックが2指定なのに、実際には4クロックあります。
じつはボリュームエンベロープのクロック指定でも同じなのですが、内部処理として期間のカウントが少し曖昧です。
エンベロープ処理を適用していても、最初の1クロックは発音開始のクロックなのでエンベロープ処理を実行しません。
次のクロックから処理が開始されるので、データで指定したクロックより1クロック期間が長くなります。
しかし、タイプAから開始して、Bになったときは1クロック余計に掛かることはありません。
他にも、タイプによって、減算タイミングがカウント到達時か、毎回か、カウント到達時にはどちらのタイプの処理を行うのか等が異なります。
エンベロープの期間が長くなったり、短くなったりで、見た目上は指定通りの長さに見えるのですが、内部的にはタイプの状態が1クロックずれるようなことが発生します。
(エンベロープの画像の黄色線では、感覚的に分かりやすい位置で区切っているので、内部処理と合致している場合としていない場合があります)
加えてエンベロープコマンドで指定したタイプB維持カウントやタイプC減算維持カウントはデータの範囲は0-7ですが、内部で+1されて1-8の値がワークエリアに入ります。
これによりタイプBで開始しているのと、タイプBがトレモロ処理と帳尻が合わない組み合わせなので+2クロック長くなってしまっています。
この辺り、厳密に追うと面倒なだけだと思うので、値が+1ずれる、+2ずれる等のように考えておくだけで十分かと思います。
トレモロ処理
さて、タイプCに相当する部分からトレモロ処理が開始されます。
減衰処理
トレモロ処理は増幅部と減衰部に分かれます。初めの処理は減衰部から始まります。
減衰処理に切り替わった最初の処理は、現在の音量データ(+0CH)から(+38H)[閾値算出用減算値]を引き、マイナスと下限チェックの後(+20H)[音量データ閾値]に保存します(ここでのチェックは値の下限補正)。
その後、現在の音量データを整数4bit+小数4bitの固定小数点に変換し、(+23H)[音量減算値]で引いて結果を(+37H)[固定小数点音量値計算テンポラリ]に保存します。ここでもマイナスと下限チェックは行われます。
2回目以降は、この固定小数点音量値計算テンポラリから音量減算値を引くことになります。
初回、2回目以降の共通処理は、固定小数点音量値計算テンポラリの値を7捨8入して整数化し、音量データの更新値とします(下限チェックはここでも実行されます)。
下限チェックに掛かると値が下限に補正される他、(+30H)b4[トレモロエンベロープ下限到達フラグ]が1となります。
この作業を(+22H)[維持カウント]分繰り返すことが減衰部の処理となります。[維持カウント]分繰り返すと、初回フラグがリセットされ、増幅処理へ移行します。
増幅処理
増幅処理も初回と2回目以降で少し異なります。
初回の時は現在の音量データを固定小数点化して、2回目以降は(+37H)[固定小数点音量値計算テンポラリ]に(+24H)[音量加算値]を足して、(+37H)に保存します。
この時(+30H)b4[下限到達フラグ]が立っていると、(+20H)[音量データ閾値]と(+0CH)[音量データ]を比較し、音量データが閾値以上の場合(+30H)b3[トレモロエンベロープ終了フラグ]が1になります。以降、次の音までトレモロ処理は行われません。
初回、2回目以降の共通処理です。
固定小数点音量値計算テンポラリを7捨8入して整数化し、音量データの更新値とします。
ここでも下限到達フラグが立っていると、音量データ閾値と更新された音量データを比較します。
音量データが閾値以上の場合、減衰処理へ移行します。
音量データが小さい場合や、下限到達していない場合は減衰処理と同じように、(+22H)[維持カウント]分繰り返します。
維持カウントを繰り返した後は、減衰処理へ移行します。
閾値について
閾値は、減衰部になった時の音量から閾値算出用の値を引いたものになります。
通常は下限より大きい値になりますが、振幅が小さくなるにつれて下限に迫ってきます。
最終的に閾値=下限となって底を突きます。その状態のあと、増幅に移行したらその音のトレモロエンベロープは終了です。

一方音量は下限に到達しても、閾値はまだ上にあるという状態があります。

維持カウントが減衰/増幅の繰り返し回数ですが、増幅時の音量がその閾値以上になると維持カウントに関係なく、即座に減衰に移行します。
これにより、減衰に入った時の音量を増幅で超えてしまうことはなくなります(減衰時は維持カウント分のクロックに必ずなりますが、増幅時はそれより早く切り替わる可能性があります)。
つまり閾値は、トレモロエンベロープの終了判定でもあり、増幅が減衰開始時の音量を超えないようにする境界線としても働くことになります。
このことからデータは、減衰していく振幅を想定していて、音量減算値 > 音量加算値となるように設定する必要があると思われます。
音量変化について
音源に書き込むレジスタ値は整数値ですが、エンベロープ計算の内部では固定小数点を使って計算していて、音量が0に見えても内部では0.3等の数値を持っているので完全に0になるまでの変化がかなり自然です(正確な計算というわけではありませんが…)。ビブラートは2種類の周波数変化で割り切っていたりするのに、このエンベロープの処理との落差にはビックリです。
下限設定
ボリュームエンベロープと同じく、下限設定が有効です。
サンプルです。
データ | 意味 |
---|---|
FEH 01H | (+09H)を01Hにセットする。音名音長のデータ形式指定 |
E9H 1EH | 基本音長30 |
EAH 0FH | v15 |
D0H | o6 |
F8H 05H | 波形転送5番(sin波) |
DDH A6H 42H | トレモロエンベロープ設定 開始タイプA-0 (+21H)タイプB維持カウント2 (+22H)維持カウント6 (+23H)音量減算値0.AH (+24H)音量加算値0.5H (+38H)閾値算出用減算値2 |
DBH 03H | 下限設定3 |
04H | 音長150クロックでo6c |
FFH | 曲データ終了 |
