Java で Sega Master System エミュレーターをプログラミングし (この質問は Java 固有のものではありません)、SN76489 サウンド チップ以外はすべて完了しました。このチップがどのように音を出すかは簡単です - 私が抱えている問題は、それを PC/ラップトップ/JVM が実行されているものなら何でも再生できる形式に変換することです。
手順は次のとおりです。
SN76489 はおよそ 221khz のサンプル レートで実行されるため、出力される波の周波数が最大 110khz になることを意味します (ただし、実際には、これほど高くなるものはないと思います)。したがって、ダウンサンプリングする前にローパス フィルターを実装する必要があります。
次に、それを 44.1khz にダウンサンプリングして、オーディオ ライン (私の場合は Java ソース データ ライン) 経由で出力できるようにします。
このためには、ローパス フィルターを 22.05khz に設定する必要がありますが、問題は、ローパス フィルターが実際にどのように機能するか (数学的に言えば) わからないことです。1つ書くことができるようにするためにこれが必要です。
現在、私のサウンド チップは 0.2 秒のバッファを作成し、上記のように 221khz でサンプルを保存します。これを理解しているので、ダウンサンプリングできますが、最初にローパス フィルターを適用せずにダウンサンプリングすると、結果のサウンド ストリームにエイリアシング グリッチが発生する可能性があることを理解しています。
これを行うための最も単純な数学的なアルゴリズムを推奨できる人はいますか?変数が関係しているため、ローパスは決して「正確」ではないことを理解していますが、私の脳にとって十分に馬鹿げた健全な説明が必要です(実際にはそうではありません)以前にウェーブ処理を扱った) を理解する必要があります。
SN76489 は 3 つの方形波と 1 つのノイズ チャネルを同時に出力します。これらは合計され、ミキサー/アンプに出力されます。チェーンのこの段階で、ローパス フィルターを実行してから、ダウンサンプリングして波を増幅します。人々が私に与えることができるどんな助けも大歓迎です。背景を読む必要があることは理解していますが、「何」を読む必要があるか知りたいです。どうもありがとう。
更新:私は最終的により単純なアプローチを思いつきましたが、まだ十分ではありません。SN76489 は、レジスタ値から各トーン チャネルを生成することによって機能します。1 の極性が出力され、値が減分されます。値が 0 になるまで、値がリセットされ、極性が -1 に切り替えられます。 . 次に、この値にボリュームを掛けて、そのサンプルの最終的な振幅を取得し、他のチャンネルと合計します。
ここでは、必要なナイキスト制限を超える方形波を生成するレジスタ値が生成されないようにするだけです。これにより、はるかに優れた信号が得られますが、まだブーンという音やポッピングが残っています。可能な最大周波数を 18,473Hz にする必要があるため、理由はわかりません。このポッピング/バズ音は、チップがチャンネルをある周波数から次の周波数に切り替えるときに、現在の波形が完全に終了しないためでしょうか? 例として、チップは 1111 を出力し、次に 00 を出力します - 完全な 4 つのゼロの代わりに新しい周波数に切り替えます - これはエイリアシングを引き起こす可能性がありますね?