C#でOgg Vorbis - OggVorbisFileに関する追補

| コメント(0) | トラックバック(0)

概要: OggVorbis_Fileって、ヒープ中で完全に位置が固定されている事を仮定しているんでしょうか? 今作っている曲のループ境界探索ツール(?)でAccessViolation問題が再発したので、試し...

OggVorbis_Fileって、ヒープ中で完全に位置が固定されている事を仮定しているんでしょうか? 今作っている曲のループ境界探索ツール(?)でAccessViolation問題が再発したので、試しに次のようにしてみたら、ぴたりと止みました(また気のせいかも知れませんが)。

public class OggVorbisFile : IDisposable {
  #region コンストラクタ/ファイナライザ
  public OggVorbisFile() {
    this.data = new byte[ 720 ];
    this.gchandle = GCHandle.Alloc( this.data,
      GCHandleType.Pinned );
    this.address = Marshal.UnsafeAddrOfPinnedArrayElement
      ( this.data, 0 );
    return;
  }
  ~OggVorbisFile() {
    this.Dispose();
 
    return;
  }
  private bool disposed = false;
  public void Dispose() {
    if ( this.disposed )
      return;
 
    this.gchandle.Free();
 
    this.disposed = true;
    GC.SuppressFinalize( this );
 
    return;
  }
  #endregion
  #region 実体
  byte[] data;
  GCHandle gchandle;
  IntPtr address;
  #endregion
  #region 型変換
  public static implicit operator IntPtr
    ( OggVorbisFile oggVorbisFile ) {
    return oggVorbisFile.address;
  }
  #endregion
}

OggVorbis_Fileは720バイトだという事を既知として(無論、libvorbisのバージョンアップによって変わる可能性はあります)、720バイトのbyte配列を作り、GCHandleでpinする、つまりヒープ中でのアドレスを固定するというものです。以前のOggVorbisFileと違う所は、ヒープ中で固定されているかいないかだけ(のはず)なのですが、何故なんででしょうねぇ(libvorbisのソースを見ていないので、これで解決できているのかどうかは断言できませんが、OggVorbis_Fileのメンバにアクセスしないのであればこれが一番簡単なCヒープの模倣手段でしょう)。

ついでに、セカンダリバッファを更新するスレッド「だけ」で、ファイルのov_open_callbacksからov_readまでの処理をするようにしていましたが、ov_open_callbacksをメインスレッドで、ov_readを別スレッドで呼び出すようにしても、AccessViolationが出なくなりました。これでdeferOpeningとかいう、あまり外部に見せたくない引数を消す事ができました。

2007-03-09追記: この方法を使う時は、アンマネージド関数のプロトタイプ宣言で[In, Out] OggVorbisFile oggVorbisFileとしていた所は、IntPtr oggVorbisFileに変えておいてください。暗黙の型変換が行われるので、労力は小さくて済むでしょう。

トラックバック(0)

トラックバックURL: http://w4ard.s26.xrea.com/program/mt/mt-tb.cgi/25

コメントする

このブログ記事について

このページは、E+Xが2007年3月 6日 16:31に書いたブログ記事です。

ひとつ前のブログ記事は「Having Headed Wwwward: XHTML 1.1 Reference Is Complete」です。

次のブログ記事は「DirectSound強化週間」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。