cs11884への新機能実装案

Developer
Dec 2, 2011 at 12:08 AM
Edited Jan 16, 2012 at 8:28 PM

change set 11884へ新機能を実装したいと考えています。

(1)PSG(AY-3-8910)互換のノイズ音源。
(2)パルス波と(1)のミックス発生モード。
(3)パルス波にて、高い音程でノイズっぽくなるため、任意のデューティー比でそのノイズ対策。

上記の3点です。
波形生成のロジックは既に出来ており、(2)と(3)を既存@番号に組み込む方法では互換性などの問題があり、実装方法の見直しが必要になりました。
そこでの提案ですが、新しく@15系列の音色指定コマンドとサブコマンドで上記3点の機能を一手に引き受ける実装方法はいかがでしょうか。

たとえば@15をPulse Module TYPE-B とします。
@15-0 (または@15とだけ記述):ノイズ対策有効のパルス波。
@15-1:PSG互換ノイズ音
@15-2:パルス波とPSG互換ノイズ音のミックスモード。

@wb[n1]-[n2]
@15宛てだけに、デューティー比を n1/n2 (%) に設定する。

@nb[n]
@15宛てだけに、ノイズ周波数モードを[n]にする。@15-1と@15-2双方に有効。

LFOおよびパイプ処理については、既存のパルス波と区別する利点が薄いため
発動させない方向を考えています。

コミットについて:
branches/minorfix に追加更新して評価を受け、OKとなったら truncへマージ。

以上のような実装を考えています。
関係者の皆様、ご意見よろしくお願いいたします。

Developer
Jan 17, 2012 at 2:38 AM
Edited Jan 17, 2012 at 3:25 AM

簡易NRはMMLに「#NOISE REDUCTION ON」の記述が記載されている場合にだけ発動するようにすれば過去データに影響は与えない。
矩形波以外に簡易NRを掛けないのであれば将来的に実装したときのために「#PULSE NOISE REDUCTION ON」でもいいかもね。

波形セットとかは別に新しいコマンドを追加しなくても @w や @n を使えばOKかな。
コマンド追加は慎重にならなきゃならない。
今までどおりで書けるならそれに越したことは無いかな。
今でも@w は @3 と @5 でちゃんと分けてるし。

ノイズのクロックは「#PSG NOIZE CLOCK ○○」で指定してそれを使うようにすれば良いんじゃないかな?
1つのMMLの中で複数のクロックを使い分けること何かないだろうし。
○○の部分はそのまま周波数を入れると大変なので「PC98」「MSX」「X1」「FM7」などを指定すればわかりやすいかと。
もちろん記述が無ければデフォルトでPC98とか。

LFOとかに付いては今までどおりでいいんじゃない?
別に無理に外す必要もないし。
@15の方の矩形波はLFOのデューティ比切替には対応するんだよね?

ロジックの方ではノイズジェネレータのシフトレジスタって1初期化じゃなかったっけ?
なんか乱数で初期化されてるけど。
(↑と書いたけどソースによって違ったワナw)

とりあえず今思いつくことを簡単に。

Developer
Jan 17, 2012 at 8:22 PM
Edited Jan 17, 2012 at 8:23 PM

aloeさんからは、twitter経由で、ノイズ音源モジュールと、パルス音源モジュールは分けてくれた方が良いよ、とご意見いただきました。

メタデータで簡易NRを指示するのであれば、既存の@3と@5のpulseモジュールに簡易NRを組み込んでもいいよ、ということですね。

簡易NR機能は、今のところパルス波限定でしか先が見えていません。
@10にもいけるかな?と考えてみたものの、いいロジックが思いつかなくて。これだったらサンプリングレートを上げたほうがまし、という状況で挫折中です。

@3と@5に簡易NRをつける場合、ノイズミックス機能にPSGノイズを採用したいケースの場合分けも関係してくると思うと、既に@w-50 のように書いてなお、メタデータでノイズモジュール選択になるかな、と考えていくと、ちょっと複雑すぎるだろうか、という感じもしていて、@15の方針を提案していました。

ノイズモジュールと、パルスモジュールを分離することは最初に考えたものの、@15と@16の2つも使ったら怒られそうな気がして、少々無理のある@15にまとめる考えをしてしまっていましたが、2つ使ってもいいよ、となると非常に書くのが簡単になると思います。

@wは、@3と@5で場合分けされているのですが、#USING POLYでポリモードを発動しているとき、ポリモードが内部で複数トラック確保して順次発音要求を割り振っていく都合、音色番号指定がバッファされてノートオンの直前に音色定義実行されるため、最初のノートオンの時に@wが@5宛と認識するのに失敗し、最初のノートオンがどうしてもデフォルトのデューティー比50%になってしまう不具合があります。この不具合は@wも音色指定同様、バッファしてノートオン時に設定するようにプログラム変更すれば解決できますが、同様にPSGノイズの@nが次に控えてますので、定義中の音色番号によって場合分けしてパラメータ設定する方法を増やすとその度に、ポリモードのフォローがなかなか神経を使います。
@wは必ず音色番号を指定した後に書く、という暗黙の仕様があると思うのですが、現在の@nのように宛先音色が@4の1つだけだと、音色番号の前でも後でも良くなり、ポリモード問題もなくなるため、できることなら宛先音色は1つに限ったパラメータ設定するコマンド体系だと、保守しやすくて助かるかなと思っています。

PSGノイズのマスタークロックのモード設定は、劇的な変化がないので需要があればと思っていましたが、メタデータからの指定でやってみようと思います。
#PSG NOISE TYPE [機種名]くらいが読みやすそうでしょうか。

LFO周りは、外す方が簡単(m_osc2Connect=0するだけ)ですが、手抜きは良くないですね。
LFO用のパルス波モジュールも、音声生成用と同じ構成でインスタンスが用意されてますから、LFO用のいずれのパルス波であってもデューティー比を指定する受け皿はあるものの、LFO用のインスタンスに対してデューティー比パラメータを変更するコマンドがないので、結果としてモジュール起動時の初期値でのみ動いています。
なにかしらのコマンドを用意しないと、@15でも同様で、モジュール起動時の初期値デューティー比になってしまいます。初期値で動くなら@3と@15の動作が同じになるので、悪さをしないように外しておこうかな、という安易な発想でした。LFO用パルス波のデューティー比を変更するコマンド作ったほうが良いでしょうか?

PSGノイズジェネレータのシフトレジスタの初期値を、乱数で設定していた件。
エミュレーションとしては間違いだと思います。
そして、初期値の調べがついていません・・。
仮に調べがついたとして、初期値を入れてテストすると分かるのですが、再生開始時がブート時となるため、当然ですが再生開始時、いつも同じ鳴り方になってしまうんです。
しかし、日常の運用では、PSG電源投入直後に楽曲を再生開始するケースはまれで、ふつう楽曲が再生開始されるのは、PSG電源投入後、何秒経っているかは不確定要素のため、結果的に楽曲再生開始時のノイズ生成パターンは、常に一致しないと思うんです。
そのため、FlMMLの場合、あえてランダムとした方が、日常の運用にふさわしいのではないかと考えていました。

Developer
Jan 18, 2012 at 1:23 PM

MIXモードの件

別に新たに矩形波のジェネレータ作らなくても次の通りに作ればいいのでは?

MOscillator.as:
public function MOscillator() {
    (前略)
    setNoiseToPulse(0);
}

public function setNoiseToPulse(mode:int):void {
    var modPulse:MOscPulse = (MOscPulse)(getMod(PULSE));
    var modNoise:MOscMod;

    if (mode == 1) {
        modNoise = (MOscMod)(getMod(PSG_NOISE));
    } else {
        modNoise = (MOscMod)(getMod(NOISE));
    }
    modPulse.setNoise(modNoise);
}


MOscPulse.as:
protected var m_modNoise:MOscMod;

public function setNoise(noise:MOscMod):void {
    m_modNoise = noise;
}

@mx0 : 従来ノイズでMIXモード駆動
@mx1 : PSGノイズでMIXモード駆動
(コマンド名はとりあえず)

MML例
@3 @w-50 @n50 cdefg @mx0 cdefg @mx1 cdefg;
1回目と2回目の cdefg が従来ノイズでのMIXモード、3つ目の cdefg がPSGノイズでのMIXモード

上記のソース以外にも色々書かなきゃならんけど、とりあえずこれでわかるっしょ。

Developer
Jan 18, 2012 at 3:20 PM

↑を簡単に実装してみたらこんな感じ。

http://0503.jp/flmml

Developer
Jan 18, 2012 at 6:01 PM
Edited Jan 18, 2012 at 9:07 PM

MIXモードの件、返信ありがとうございます。サンプルソース、ダウンロードして動かしてみました。
なるほど、setNoiseToPulse()の書き方がそのようになれば、サンプル生成時に分岐が不要になっていいですね。

これを踏まえてちょっと提案したいのは、採用するミックスノイズの切り替えを、音色番号の枝番を使ってはどうでしょう?
(@mx(仮)のコマンドが増えると、MML書くのが難しい印象でした)

@3-1のように書くとsetWaveNo()が呼ばれてモード通知できるので、そこでsetNoiseToPulse()相当の切り替えを呼べば、コマンドを新設しなくてもホワイトノイズとPSGノイズの切り替えができるのかなと。

<案>
@3  ・・・通常パルス波(@3-0でも同様)。(@3指定+MIXモードOFF+呼び出すMIX用ノイズの選択はしない)
@3-1 ・・・ホワイトノイズまじりのパルス波(@3指定+MIXモードON+ホワイトノイズ選択)
@3-2 ・・・PSGノイズまじりのパルス波(@3指定+MIXモードON+PSGノイズ選択)
(従来通り@wのマイナス指定も動作させる。デューティー比設定+MIXモードON+ホワイトノイズの選択)

加えて、@n コマンドでの周波数指定を、ホワイトノイズとPSGノイズの両方に設定するという仕様を許してもらえれば(取り消されたコミットでこのように実装してます)、専用コマンドを新設せず、設定漏れはなくなるので、まず実使用上問題ないかなと。
(※まれな用途ですが、@4で@n50で使っていて、@15に切り替え@n31にし、さらに@4に戻すとき、@nを省略したときの動作として@n50を期待されると、そこは期待通りではなく@n31に上書きされているので、省略せず@n50と書いてもらう必要があります。)

MML例
@3 @w-50 @n50 cdefg @3-1 cdefg @3-2 cdefg;
1回目と2回目の cdefg が従来ノイズでのMIXモード、3つ目の cdefg がPSGノイズでのMIXモード。
@3-1を使えば@wにマイナスをつけなくてもよくなる

Developer
Jan 19, 2012 at 2:40 PM

コマンドは基本的に増やさない方向性(と言うかむやみに増やすと今後新機能を実装した時に使えるコマンドが無くなる)なので@3-1とかで言いと思いますよ。
ただ、基本0から始まるので@3 = @3-0と言うのも忘れずに実装しなきゃダメです。(もちろんリファレンスにも記述忘れずに)
サイン波も @0 = @0-0 だし、三角波も @2 = @2-0 ですから。
ま、これはよっぽど意識的に書かなきゃそんな動きになりますけど。
if (waveNo < 1) waveNo = 1; みたいに書いちゃだめってことですよ。

@n に関しては今までの慣例に沿ってそのように実装してます。
例えば @3 @w25 cde @5 @w4 cde @3 cde と演奏した場合、後者の @3 はデューティ比25%で演奏されますよね?
他の方の意見も聞いてみないことにはわからないけど、基本的に今までどおりの動きをさせる方が自然かと。
こっちのコマンドは記憶してる、こっちのコマンドは記憶していないとなると使う側からするとややこしいですし。

MIXモードの定義に戻って、個人的には @3-1 や @3-2 でいきなりMIXモード発動ではなく、あくまでもモード選択なだけ。
実際にMIXモードを発動するには @w-○○ を記述した時の方がいいかな?
@3-1 cdef @w-50 cdef と書くと前者の cdef は普通にトーンで、後者の cdef がMIXモードで発声。
@n でも書いてるけど基本今までどおりの動きを周到したいと言う事から。
そうなると @3 = @3-0 が今までどおりで、@3-1 がMIXモードにした場合にPSGノイズ使用となるかな。

Developer
Jan 19, 2012 at 9:58 PM
Edited Jan 19, 2012 at 10:23 PM

これまでいただいたご意見など受け、現時点での実装案のまとめを書きたいと思います。

change set 11884への新機能実装案3点:

(1)PSG(AY-3-8910)互換のノイズ音源。
(2)パルス波と(1)のミックス発生モード。
(3)パルス波にて、高い音程でノイズっぽくなるため、任意のデューティー比でそのノイズ対策。

具体的なコマンド実装案:

(1)の実装
@15-0 (または@15とだけ記述):PSG互換ノイズとして発音。
ノイズ周波数は、@nを使用する。
@n指定時、カレントが@15だったら@15宛てにノイズ周波数を指定する。
カレントが@3だったら、ミックス対象がどちらのノイズかを見て、@4または@15いずれかにノイズ周波数を指定する。
カレントが(@15または@3)以外だったら、@4宛てにノイズ周波数を指定する。
@15宛てのノイズ周波数は、0~255で受け付けて、0~31の範囲がPSG互換。
@nのコマンド受付が、音色宛先分岐するため、ポリモード対策のため音色同様ノートオン時にセットする。
(@wも音色同様ノートオン時セットにする)
@15をLFO波形に指定した場合のwidthの動き方が現在未定義なので鋭意作成中。

(2)の実装
パルス波は、既存の音色番号を使う方針とする。
@3-0 (または@3とだけ記述):パルス波として発音。
ただし、@w-**でミックスモード発動時にはホワイトノイズとミックスさせる、従来どおりのモード。
@3-1:パルス波として発音。
ただし、@w-**でミックスモード発動時にはPSG互換ノイズとミックスさせる、新規のモード。
上記2点、いずれも記述後@wマイナス表記を記述しないとノイズミックスにはならない。

(3)の実装
メタデータでモード指定する。
#PULSE NOISE REDUCTION
と記述したら、簡易NRモードで、パルス波(@3/@5)のレンダリングを行う。
ON/OFFまで書かないのは、OCTAVE REVERSEなどの記述にON/OFFが無いので、合わせてみた。

現状、上記の仕様で書いてます。

@3は音色番号をまったく記述しなかった場合に暗黙に選択される音色番号ですが、メタデータの取得が暗黙の@3を定義した後のタイミングなので、暗黙の@3を使うMMLの書き方で#PULSE NOISE REDUCTIONを指定したとき、現在手元のソースはモード取得に失敗するので、暫定的にサンプル生成時、常に#PULSE NOISE REDUCTIONの状態を見て、間違いない動作をさせるようにしています。思ったほどの負荷ではなさそうですが・・

■簡易NRが実装されると高音域のパルス波が普通に使えるようになるので、オクターブ受付範囲をo0~o9にしたいと思うのですが、いかがでしょうか?(モジュールFMは現状維持)
ところで現在オクターブのリミットが、-2~8となっていますが、なぜ-2からなのでしょう?

■以前、パルス波で、デューティー比6.25%に設定するため@10を使っているMMLを見ました。
@10には簡易NRがかけられず、現状の@wではぴったり指定も出来ないので、分数指定できる@wも欲しいなと思っています。現状デューティー比は引数が浮動小数点数ですので、MMLコマンドだけの予約で新たなイベントを作らずに@3宛てに分数指定のデューティー比指定コマンドが作れると思うのですが、いかがでしょうか?

Developer
Jan 20, 2012 at 2:24 AM

(1)
@15 はwaveNo指定は要らないでしょ。
まぁ、setWaveNo() をPSGノイズクラスに実装しなきゃ良いだけだけど。

(3)
負荷は出来るだけ軽減する方向で。
チリも積もればなんとやら。

Coordinator
Jan 28, 2012 at 3:02 PM

はや一週間…。

まあ特に急いで結論出す必要はないんですが、ある程度みんなで

「これなら」と思えるような状態になるまでは保留にしておいたほうが

よさげですねー。

 

Developer
Jan 29, 2012 at 11:32 AM

tekisukeさんより、twitterのコメントにて、パフォーマンス含め検討というお話をいただいていたと思います。
処理落ちして鳴らなくなる問題だけに焦点をあてるなら、再生バッファを8192からもっと増やす、というアプローチがまず最初に思いつくところでした。
処理速度そのものの改善という点では、重そうなところにあたりをつけて速度計測し、代替ルーチンで改善がみられるかの試行錯誤が必要か、と考えています。
これは改善できたらデモビルドが必要かもしれないですね。
使用メモリ量の問題も気にかけていました。

いずれにしても、簡易ノイズ対策のルーチンはどうしても処理の重さを発生させるので、別なところで稼げないかと考えています。
もしうまく処理速度を稼げたら、その余裕に見合う範囲の処理実装の提案をしてみたいと考えています。
つぎの提案まで、しばらく時間が掛かりそうです・・

Developer
Jul 5, 2012 at 11:57 PM
Edited May 8, 2013 at 3:04 PM
処理速度を重くしないで互換性を保ちつつ、機能実装していく方法を検討していましたが、ちょっと私の力では無理でした。。自分用に使用するカスタマイズ版を、独自に作成する方向で行きたいと思います。ありがとうございました。