2008年02月18日

サウンドフォントファイル(sf2)3

HDDクラッシュによって環境がクリーンになったためにコンパイル速度が速くなり作業がしやすくなった(ちなみに Delphi 6 Professional で製作中)。

キーとベロシティに対応したサンプルを見つけ出したりして音を鳴らすために必要な情報を収集する機能に関しては完成したと思う。
ただここまでで Modulator に関する全てのデータを無視している。英語のリファレンスを流し読みした感じではこの Modulator がノートオンのベロシティに応じて音量を変えたりなどの機能を実現させるための定義のような気がするので、多分無視して勝手にノートオンなどで発音してはいけないんじゃないかと思う。
それなりに動くものを作るのならこの辺の処理を書かないと使い物にならなそうだ。

しかし着実に前進しているあたり、自分にしてはちょっと珍しい。
posted by oov at 05:54| Comment(1) | TrackBack(0) | プログラム | このブログの読者になる | 更新情報をチェックする

2008年02月13日

サウンドフォントファイル(sf2)2

仕様書と実際のファイルを睨めっこしながらだいぶ流れがわかってきた。

・サウンドフォントファイル内に存在するバンク/プリセットの列挙
・格納されているサンプルデータの列挙

取り合えずここまでは多分動くものが作れる気がする。
Preset から Bag を頼りに関連付けられた Instrument を見つけ出し Instrument から対応するサンプルやそれぞれのパラメータを引っ張り出してくるところが完成すれば、発音もさせられるんじゃないかと思う。
波形の処理に関しては自分にとって未知の領域が多いので前途多難な感じはあるが、取り合えずサウンドフォントがどのようにして発音までの道のりを歩んでいくのかについては大雑把に把握できたような気がする。
posted by oov at 16:30| Comment(0) | TrackBack(0) | プログラム | このブログの読者になる | 更新情報をチェックする

2008年02月08日

サウンドフォントファイル(sf2)

http://connect.creativelabs.com/developer/SoundFont/sfspec21.pdf
サウンドフォントファイルのファイルフォーマットは普通に公開されている。

あと、SFEDT32.DLL というサウンドフォントを編集する場合に有用な機能が詰まった DLL も存在する。

なんで互換性問題がよく起こるのかわからないのでちょっと調べてみるべきだろうか。
posted by oov at 21:18| Comment(0) | TrackBack(0) | プログラム | このブログの読者になる | 更新情報をチェックする

2008年01月24日

dsound.dllに乗っかる2

WindowsXP からは DLL の検索順序が変わり、それまで簡単だった DLL のすり替えが少し難しくなった。
レジストリを書き換えることで以前の検索順序にする事はできるものの、これを行ってしまうと他のソフトの動作にも支障をきたす可能性があるため別なアプローチで行う方が望ましい。

CreateRemoteThread を使うと任意のプロセスに対してスレッドを注入できる。これを使うと比較的簡単に API フックが実現できるのだが、DirectX は COM が中心になっているためにAPIの差し替えを後々行ってもその効果が現れるタイミングが非常に少ない(インターフェイスを再取得するシーンがくるまでは以前のポインタを使いまわすため)。
なので CreateRemoteThread を使って注入する場合には恐らく CreateProcess でプロセスを立ち上げる時にメインスレッドを一旦サスペンド状態で立ち上げた後、スレッドを注入して API の置換をしなければいけないような気がする(試してないけど!)。
また、CreateRemoteThread はどうも Win9x 系ではサポートされていないらしい。手元には Win9x 系のマシンもないし対応は必須要件ではないけども、すり替え用の dsound.dll は Win9x 系でも動くように作ったつもりなので、せっかくだから CreateRemoteThread は使わずに動くようにしておきたい。

で、これらを踏まえた上で動くものを作るためにはそれなりに泥臭い処理が必要になる事がわかってきたのでそのメモのためにここに書いておく。

この処理でとても参考になったのは gdi++ での API フック手順。
gdi++ でも最初の手順はやはり CreateProcess でメインスレッドをサスペンド状態にして立ち上げる。そして CreateRemoteThread を使うのではなく、exe のエントリポイントのコードを直接書き換えて目的の DLL をロードする処理を注入する。そのプロセス上で DLL がアタッチされてしまえば、後は普通に API フックを行えばいい。
gdi++ の場合はフックした API の元の実装を呼んでいる間に呼ばれる別のフック中のAPIの呼び出しも監視する必要があるために関数本体を書き換えているが、今回の場合はそこまで深い監視は必要ないはずなのでもう少しシンプルなフックだけでいけそうだ。

と、思う。
posted by oov at 08:47| Comment(7) | TrackBack(0) | プログラム | このブログの読者になる | 更新情報をチェックする