シンプルなUnixオーディオインターフェースを探しています。
楽しみながら、昔のゲームを移植してx86アセンブリ言語を学んでいます。最も要求の厳しい部分は、単純なサウンド(主に方形波)を再生する方法を見つけることです。現在、ゲームはスピーカーに直接書き込むことができると予想されます。現在、Unixシステムでオーディオを再生する最も簡単な方法は何ですか?
基準
より正確には、これが私が探しているものです(最も重要な基準)。
- 波形を再生できます。 (8ビット、8000Hzで十分です。)
- アセンブリ言語から呼び出すのに十分簡単です。
- 最新のDebian GNU / Linuxシステムに適しており、ルートなしで簡単なパッケージインストールが可能です。
- ユーザーはライブラリやその他の依存関係をインストールする必要はありません。
- できるだけ多くのUNIXシステムにわたって移植可能です。 (特に{Net、Free、Open}BSD。Solaris、MacOS、およびWSLには、これを行う独自の方法があると予想されます。)
優先事項
私が移植するコードは32ビットx86アセンブリ言語なので、今は64ビットに変換したくありません。また、コードはlibcにリンクする必要はなく、可能であればそれを維持するのが最善です。
研究
私が調査したいくつかの方法は次のとおりです。
/dev/audio
私が望むのはこれです:私はただ開いています
/dev/audio
ファイルとして保存し、バイトを書き込みます。残念ながら、Linuxカーネルはデフォルトでこのデバイスに付属していないように見えるので、カーネルモジュール(snd-pcm-oss)をrootとしてインストールする必要があります。 (また、これはマイナーな問題ですが、Linuxは以前のSunOSセマンティクスを使用しており、多重化を許可しません。)直接発言者アクセス(
/dev/tty0
、、/dev/input/by-path/platform-pcspkr-event-spkr
)このゲームはもともとこの目的で書かれていました。ただし、PC内蔵スピーカーに直接書き込むには、Linuxでルート構成とカーネルモジュール(pcspkr)が必要です。また、PCスピーカーが接続されていないノートパソコンや他のコンピュータでは機能しません。
アルザス
Linuxには、ALSA(Advanced Linux Sound Architecture)というカーネルモジュールなしで使用できるサウンドシステムが付属しています。他のUnixシステムでは真似する、たとえそれがどれほど良いかはわかりません。より多くの設定が必要で、ioctlを介して直接制御できるように見えますが、通常は外部ライブラリ(alsa-lib)が必要です。インターフェイスは純粋なアセンブリでは見えませんが、Cでは可能です。 Linuxでは、ALSAは本質的に動的にリンクされ、dlopenを使用して構成に応じて実行時に追加のライブラリ(パルス、パイプワイヤ)をロードします。私が作業しているアセンブリコードは32ビットですが、ほとんどの64ビットコンピュータには32ビットバージョンのlibalsa、pulse、およびパイプラインワイヤがインストールされていないため、これが問題になります。
パイプからフォーク/実行されたプログラムへ
システムコールを
pipe(2)
使用して、ゲームがsoxなどのプログラムに生データを送信できるように、ファイル記述子を作成できます。遊ぶフォークで実行されるコマンドです。これは移植性の問題を他のプログラムに適用する良い特性を持っていますが、外部プログラムへの実行時の依存関係を避けたいと思います。
答え1
アセンブリ言語から呼び出すのに十分簡単です。
UNIXシステムはすべて、C呼び出し規則を介して関数を呼び出すことができるという考えに基づいています。これは非常に基本的な原則です! CとUNIXの歴史が互いに絡み合っている理由があります。
できるだけ多くのUNIXシステムにわたって移植可能です。 (特に{Net、Free、Open}BSD。Solaris、MacOS、およびWSLには、これを行う独自の方法があると予想されます。)
リストから削除できます。アセンブリに滞在すると、特定のABIが作成されます。これに対して変更できるものはありません。 Cは、アセンブリを他のオペレーティングシステムに移植するために必要な膨大な努力のために開発されました。あなたは50年遅れています!
私が作業しているアセンブリコードは32ビットですが、ほとんどの64ビットコンピュータには32ビットバージョンのlibalsa、pulse、およびパイプラインワイヤがインストールされていないため、これが問題になります。
幸いなことに、まだ32ビット互換性層を提供する大規模なデスクトップディストリビューションではそうではありません。 (したがって32ビットライブラリ)
しかし、正直に言うと、20年間、ほとんどのコンピュータで本質的にレガシーモデルであったプラットフォームをサポートする際に飛び越えなければならない障害物です。少なくとも32ビット環境が必要です。
純粋なアセンブリインターフェイスは見えませんが、C言語で実行できます。
はい。 x86-Linux ABI C呼び出し規則に従ってレジスタを設定し、C関数を呼び出す必要があります。 (とにかく、グラフィック、キーボードIO、その他についてもこれを行う必要があると思います。)
ただし、他の依存関係が追加されてもlibalsaを直接呼び出すことはお勧めできませんが、portaudio
スリムライブラリを使用すると、実行する必要がある複雑な関数呼び出しの数を減らすことができます。
したがって、正直に言うと、この種のアセンブリを最新のコンピュータの最新のオペレーティングシステムに移植することは、通常Cまたは他の言語でやや書き直されます。 32ビットx86の限界を満たすことができれば、おそらく最も賢明なアプローチは、「これがメインループです」、「これはゲーム内の画像を更新するためのサブルーチンです」など、ゲームの機能的なコアユニットを識別することです。フレームバッファ"、"これは、キーボードの状態を取得するために呼び出されるサブルーチンです。" 外部構造をCに変換し、インラインアセンブリこのCスケルトンから。その後、プログラムはキーボードコントローラのメモリアドレスを照会するCから直接入力ライブラリを呼び出すことができます。サンプルをサウンドシステムに転送する必要がある場合は、アセンブリがサンプルバッファを埋め、アドレスを正しいportaudio関数に渡すなどの操作を実行します。
マネージドプラットフォームのアセンブリ学習は、本質的に互換性のないアセンブリからプラットフォームを呼び出すのではなく、プラットフォームのパラダイムと互換性のあるランタイムでプログラミング言語を埋める形式を取ることがわかります。