OSDN Git Service

#24820 ASIOのエラー出力と、DirectShowへのフォールバックを強化。
authoryyagi <yyagi@16f42ceb-6dc6-49c8-ba94-f2d53467949d>
Mon, 24 Dec 2012 02:40:23 +0000 (02:40 +0000)
committeryyagi <yyagi@16f42ceb-6dc6-49c8-ba94-f2d53467949d>
Mon, 24 Dec 2012 02:40:23 +0000 (02:40 +0000)
#24820 DirectShowでの再生時に、oggをDirectShow任せにせず自力でデコードするよう修正(ogg読込の高速化)。これに伴い、xa読み込み部も設計を見直し。
#24820 関連ライブラリを最新のものに更新。

git-svn-id: http://svn.osdn.jp/svnroot/dtxmania/branches/120724(DTXMania%20with%20%2324820)@472 16f42ceb-6dc6-49c8-ba94-f2d53467949d

15 files changed:
DTXManiaプロジェクト/コード/全体/CConfigIni.cs
DTXManiaプロジェクト/コード/全体/CDTXMania.cs
FDK17プロジェクト/FDK19.csproj
FDK17プロジェクト/コード/03.サウンド/CSound.cs
FDK17プロジェクト/コード/03.サウンド/CSoundDeviceASIO.cs
FDK17プロジェクト/コード/03.サウンド/Cogg.cs [new file with mode: 0644]
FDK17プロジェクト/コード/03.サウンド/Cxa.cs
FDK17プロジェクト/コード/03.サウンド/SoundDecoder.cs [new file with mode: 0644]
実行時フォルダ/Bass.Net.dll
実行時フォルダ/DTXManiaGR.exe
実行時フォルダ/FDK.dll
実行時フォルダ/bass.dll
実行時フォルダ/bassasio.dll
実行時フォルダ/bassmix.dll
実行時フォルダ/basswasapi.dll

index a94a624..8f3e590 100644 (file)
@@ -1227,9 +1227,9 @@ namespace DTXMania
                        sw.WriteLine( "VSyncWait={0}", this.b垂直帰線待ちを行う ? 1 : 0 );\r
             sw.WriteLine();\r
 \r
-                       sw.WriteLine( "; サウンド出力方式(0=ACM, 1=ASIO, 2=WASAPI)" );\r
-                       sw.WriteLine( "; WASAPIはVista以降のOSで使用可能。" );\r
-                       sw.WriteLine( "; WASAPIã\81\8c使ç\94¨ä¸\8då\8f¯ã\81ªã\82\89ASIOã\81«、ASIOが使用不可ならACMを使用します。" );\r
+                       sw.WriteLine( "; サウンド出力方式(0=ACM(って今はまだDirectShowですが), 1=ASIO, 2=WASAPI)" );\r
+                       sw.WriteLine( "; WASAPIはVista以降のOSで使用可能。推奨方式はWASAPI。" );\r
+                       sw.WriteLine( "; WASAPIã\81\8c使ç\94¨ä¸\8då\8f¯ã\81ªã\82\89ASIOã\82\92、ASIOが使用不可ならACMを使用します。" );\r
                        sw.WriteLine( "; Sound device type(0=ACM, 1=ASIO, 2=WASAPI)" );\r
                        sw.WriteLine( "; WASAPI can use on Vista or later OSs." );\r
                        sw.WriteLine( "; If WASAPI is not available, DTXMania try to use ASIO. If ASIO can't be used, ACM is used." );\r
index defb5f7..cc5bb53 100644 (file)
@@ -1662,7 +1662,7 @@ for (int i = 0; i < 3; i++) {
                        #endregion\r
                        #region [ Sound管理 の初期化 ]\r
                        //---------------------\r
-                       Trace.TraceInformation( "DirectSound の初期化を行います。" );\r
+                       Trace.TraceInformation( "サウンドデバイスの初期化を行います。" );\r
                        Trace.Indent();\r
                        try\r
                        {                               \r
@@ -1683,7 +1683,7 @@ for (int i = 0; i < 3; i++) {
                                                break;\r
                                }\r
                                Sound管理 = new CSound管理( base.Window.Handle, soundDeviceType );\r
-                               Trace.TraceInformation( "DirectSound の初期化を完了しました。" );\r
+                               Trace.TraceInformation( "サウンドデバイスの初期化を完了しました。" );\r
                        }\r
                        catch (Exception e)\r
                        {\r
index b7fbe38..f3cf236 100644 (file)
@@ -43,7 +43,7 @@
     <Optimize>true</Optimize>\r
   </PropertyGroup>\r
   <ItemGroup>\r
-    <Reference Include="Bass.Net, Version=2.4.8.0, Culture=neutral, PublicKeyToken=b7566c273e6ef480, processorArchitecture=MSIL">\r
+    <Reference Include="Bass.Net, Version=2.4.9.1, Culture=neutral, PublicKeyToken=b7566c273e6ef480, processorArchitecture=MSIL">\r
       <SpecificVersion>False</SpecificVersion>\r
       <HintPath>..\実行時フォルダ\Bass.Net.dll</HintPath>\r
     </Reference>\r
@@ -98,6 +98,7 @@
     <Compile Include="コード\02.入力\E入力デバイス種別.cs" />\r
     <Compile Include="コード\02.入力\IInputDevice.cs" />\r
     <Compile Include="コード\02.入力\STInputEvent.cs" />\r
+    <Compile Include="コード\03.サウンド\Cogg.cs" />\r
     <Compile Include="コード\03.サウンド\CSound.cs" />\r
     <Compile Include="コード\03.サウンド\CSoundDeviceASIO.cs" />\r
     <Compile Include="コード\03.サウンド\CSoundDeviceDirectSound.cs" />\r
     <Compile Include="コード\03.サウンド\CSoundTimer.cs" />\r
     <Compile Include="コード\03.サウンド\Cxa.cs" />\r
     <Compile Include="コード\03.サウンド\ESoundDeviceType.cs" />\r
+    <Compile Include="コード\03.サウンド\SoundDecoder.cs" />\r
     <Compile Include="コード\03.サウンド\ISoundDevice.cs" />\r
     <Compile Include="コード\04.グラフィック\BitmapUtil.cs" />\r
     <Compile Include="コード\04.グラフィック\CAero.cs" />\r
index cbe93db..027f200 100644 (file)
@@ -102,11 +102,6 @@ namespace FDK
                        SoundDevice = null;                                                     // ユーザ依存\r
                        rc演奏用タイマ = null;                            // Global.Bass 依存(つまりユーザ依存)\r
 \r
-                       //SoundDeviceType = soundDeviceType;\r
-                       //SoundDeviceType = ESoundDeviceType.DirectSound;\r
-                       //SoundDeviceType = ESoundDeviceType.ExclusiveWASAPI;\r
-                       //SoundDeviceType = ESoundDeviceType.ASIO;\r
-\r
                        ESoundDeviceType[] ESoundDeviceTypes = new ESoundDeviceType[ 4 ]\r
                        {\r
                                ESoundDeviceType.ExclusiveWASAPI,\r
@@ -140,6 +135,7 @@ namespace FDK
                                }\r
                                catch ( Exception e )\r
                                {\r
+                                       Trace.TraceInformation( e.Message );\r
                                        if ( ESoundDeviceTypes[ n初期デバイス ] == ESoundDeviceType.Unknown )\r
                                        {\r
                                                throw new Exception( string.Format( "サウンドデバイスの初期化に失敗しました。" ) );\r
@@ -418,9 +414,10 @@ namespace FDK
                        this.e作成方法 = E作成方法.ファイルから;\r
                        this.strファイル名 = strファイル名;\r
 \r
-                       if ( String.Compare( Path.GetExtension( strファイル名 ), ".xa", true ) == 0 )      // caselessで文字列比較\r
+                       if ( String.Compare( Path.GetExtension( strファイル名 ), ".xa", true ) == 0 ||\r
+                                String.Compare( Path.GetExtension( strファイル名 ), ".ogg", true ) == 0 ) // caselessで文字列比較\r
                        {\r
-                               tDirectSoundサウンドを作成するXA( strファイル名, DirectSound );\r
+                               tDirectSoundサウンドを作成するXAOGG( strファイル名, DirectSound );\r
                                return;\r
                        }\r
 \r
@@ -476,24 +473,33 @@ namespace FDK
 \r
                        this.tDirectSoundサウンドを作成する( byArrWAVファイルイメージ, DirectSound );\r
                }\r
-               public void tDirectSoundサウンドを作成するXA( string strファイル名, DirectSound DirectSound )\r
+               public void tDirectSoundサウンドを作成するXAOGG( string strファイル名, DirectSound DirectSound )\r
                {\r
                        this.e作成方法 = E作成方法.ファイルから;\r
                        this.strファイル名 = strファイル名;\r
 \r
-                       Cxa xa = new Cxa();\r
-                       xa.Decode( strファイル名, out this.byArrWAVファイルイメージ );\r
+\r
+\r
+                       \r
+//                     Cxa xa = new Cxa();\r
+//                     xa.Decode( strファイル名, out this.byArrWAVファイルイメージ );\r
 \r
                        WaveFormat wfx = new WaveFormat();\r
                        int nPCMデータの先頭インデックス = 0;\r
-                       int nPCMサイズbyte = (int) ( xa.xaheader.nSamples * xa.xaheader.nChannels * 2 );     // nBytes = Bass.BASS_ChannelGetLength( this.hBassStream );\r
+//                     int nPCMサイズbyte = (int) ( xa.xaheader.nSamples * xa.xaheader.nChannels * 2 );     // nBytes = Bass.BASS_ChannelGetLength( this.hBassStream );\r
 \r
-                       wfx.AverageBytesPerSecond = (int) xa.waveformatex.nAvgBytesPerSec;\r
-                       wfx.BitsPerSample = (short) xa.waveformatex.wBitsPerSample;\r
-                       wfx.BlockAlignment = (short) xa.waveformatex.nBlockAlign;\r
-                       wfx.Channels = (short) xa.waveformatex.nChannels;\r
+                       int nPCMサイズbyte;\r
+                       CWin32.WAVEFORMATEX cw32wfx;\r
+                       tオンメモリ方式でデコードする( strファイル名, out this.byArrWAVファイルイメージ,\r
+                       out nPCMデータの先頭インデックス, out nPCMサイズbyte, out cw32wfx );\r
+\r
+                       wfx.AverageBytesPerSecond = (int) cw32wfx.nAvgBytesPerSec;\r
+                       wfx.BitsPerSample = (short) cw32wfx.wBitsPerSample;\r
+                       wfx.BlockAlignment = (short) cw32wfx.nBlockAlign;\r
+                       wfx.Channels = (short) cw32wfx.nChannels;\r
                        wfx.FormatTag = WaveFormatTag.Pcm;      // xa.waveformatex.wFormatTag;\r
-                       wfx.SamplesPerSecond = (int) xa.waveformatex.nSamplesPerSec;\r
+                       wfx.SamplesPerSecond = (int) cw32wfx.nSamplesPerSec;\r
+\r
 \r
 \r
                        // セカンダリバッファを作成し、PCMデータを書き込む。\r
@@ -508,6 +514,7 @@ namespace FDK
 \r
                        // DTXMania用に追加\r
                        n総演奏時間ms = (int) ( ( (double) nPCMサイズbyte ) / ( this.Buffer.Format.AverageBytesPerSecond * 0.001 ) );\r
+                       nBytes = nPCMサイズbyte;\r
 \r
                        // 作成完了。\r
 \r
@@ -744,7 +751,36 @@ namespace FDK
                        if( this.bBASSサウンドである )\r
                        {\r
 //Debug.WriteLine( "再生中?: " +  System.IO.Path.GetFileName(this.strファイル名) + " status=" + BassMix.BASS_Mixer_ChannelIsActive( this.hBassStream ) + " current=" + BassMix.BASS_Mixer_ChannelGetPosition( this.hBassStream ) + " nBytes=" + nBytes );\r
-                               BassMix.BASS_Mixer_ChannelPlay( this.hBassStream );\r
+                               bool b = BassMix.BASS_Mixer_ChannelPlay( this.hBassStream );\r
+                               if ( !b )\r
+                               {\r
+Debug.WriteLine( "再生しようとしたが、Mixerに登録されていなかった: " + Path.GetFileName( this.strファイル名 ) );\r
+//Debug.WriteLine( "ErrCode= " +Bass.BASS_ErrorGetCode() );\r
+\r
+                                       bool bb = tBASSサウンドをミキサーに追加する(false);\r
+                                       if ( !bb )\r
+                                       {\r
+Debug.WriteLine( "Mixerへの登録に失敗: " + Path.GetFileName( this.strファイル名 ) + ": " + Bass.BASS_ErrorGetCode() );\r
+                                       }\r
+                                       else\r
+                                       {\r
+Debug.WriteLine( "Mixerへの登録に成功: " + Path.GetFileName( this.strファイル名 ) + ": " + Bass.BASS_ErrorGetCode() );\r
+                                       }\r
+//                    bool bbb = BassMix.BASS_Mixer_ChannelPlay( this.hBassStream );\r
+//                    if ( !bbb )\r
+//                    {\r
+//Debug.WriteLine( "更に再生に失敗                                 : " + Path.GetFileName( this.strファイル名 ) );\r
+//Debug.WriteLine( "ErrCode= " +Bass.BASS_ErrorGetCode() );\r
+//                    }\r
+//                    else\r
+//                    {\r
+//Debug.WriteLine( "再生成功(ミキサー追加後)                       : " + Path.GetFileName( this.strファイル名 ) );\r
+//                    }\r
+                               }\r
+                               else\r
+                               {\r
+Debug.WriteLine( "再生成功                                       : " + Path.GetFileName( this.strファイル名 ) );\r
+                               }\r
                        }\r
                        else if( this.bDirectSoundである )\r
                        {\r
@@ -760,8 +796,10 @@ namespace FDK
                {\r
                        if( this.bBASSサウンドである )\r
                        {\r
-//Debug.WriteLine( "停止: " + System.IO.Path.GetFileName( this.strファイル名 ) + " status=" + BassMix.BASS_Mixer_ChannelIsActive( this.hBassStream ) + " current=" + BassMix.BASS_Mixer_ChannelGetPosition( this.hBassStream ) + " nBytes=" + nBytes );\r
+Debug.WriteLine( "停止: " + System.IO.Path.GetFileName( this.strファイル名 ) + " status=" + BassMix.BASS_Mixer_ChannelIsActive( this.hBassStream ) + " current=" + BassMix.BASS_Mixer_ChannelGetPosition( this.hBassStream ) + " nBytes=" + nBytes );\r
                                BassMix.BASS_Mixer_ChannelPause( this.hBassStream );\r
+\r
+//tBASSサウンドをミキサーから削除する();\r
                        }\r
                        else if( this.bDirectSoundである )\r
                        {\r
@@ -912,6 +950,7 @@ namespace FDK
                protected GCHandle hGC;\r
                protected int hBassStream = -1;                                 // ASIO, WASAPI 用\r
                protected SecondarySoundBuffer Buffer = null;   // DirectSound 用\r
+               protected int hMixer = -1;      // 設計壊してゴメン Mixerに後で登録するときに使う\r
                //-----------------\r
                #endregion\r
 \r
@@ -970,6 +1009,8 @@ namespace FDK
                        nBytes = Bass.BASS_ChannelGetLength( this.hBassStream );\r
                        double seconds = Bass.BASS_ChannelBytes2Seconds( this.hBassStream, nBytes );\r
                        this.n総演奏時間ms = (int) ( seconds * 1000 );\r
+                       this.pos = 0;\r
+                       this.hMixer = hMixer;\r
                }\r
                private void tBASSサウンドを作成する( byte[] byArrWAVファイルイメージ, int hMixer, BASSFlag flags )\r
                {\r
@@ -998,13 +1039,22 @@ namespace FDK
                        nBytes = Bass.BASS_ChannelGetLength( this.hBassStream );\r
                        double seconds = Bass.BASS_ChannelBytes2Seconds( this.hBassStream, nBytes );\r
                        this.n総演奏時間ms = (int) ( seconds * 1000 );\r
+                       this.pos = 0;\r
+                       this.hMixer = hMixer;\r
                }\r
                private void tBASSサウンドを作成するXA( string strファイル名, int hMixer, BASSFlag flags )\r
                {\r
-                       Cxa xa = new Cxa();\r
-                       xa.Decode( strファイル名, out this.byArrWAVファイルイメージ );\r
+                       int nPCMデータの先頭インデックス;\r
+                       CWin32.WAVEFORMATEX wfx;\r
+                       int totalPCMSize;\r
+\r
+                       tオンメモリ方式でデコードする( strファイル名, out this.byArrWAVファイルイメージ,\r
+                           out nPCMデータの先頭インデックス, out totalPCMSize, out wfx );\r
+\r
+                       nBytes = totalPCMSize;\r
 \r
                        this.e作成方法 = E作成方法.WAVファイルイメージから;\r
+                       this.strファイル名 = strファイル名; \r
                        this.hGC = GCHandle.Alloc( this.byArrWAVファイルイメージ, GCHandleType.Pinned );                // byte[] をピン留め\r
 \r
 \r
@@ -1012,27 +1062,43 @@ namespace FDK
 \r
                        // BASSファイルストリームを作成。\r
 \r
-                       this.hBassStream = Bass.BASS_StreamCreate( xa.xaheader.nSamplesPerSec, xa.xaheader.nChannels, BASSFlag.BASS_STREAM_DECODE, _myStreamCreate, IntPtr.Zero );\r
+                       //this.hBassStream = Bass.BASS_StreamCreate( xa.xaheader.nSamplesPerSec, xa.xaheader.nChannels, BASSFlag.BASS_STREAM_DECODE, _myStreamCreate, IntPtr.Zero );\r
+                       this.hBassStream = Bass.BASS_StreamCreate( (int)wfx.nSamplesPerSec, (int)wfx.nChannels, BASSFlag.BASS_STREAM_DECODE, _myStreamCreate, IntPtr.Zero );\r
                        if ( this.hBassStream == 0 )\r
                        {\r
                                hGC.Free();\r
                                BASSError err = Bass.BASS_ErrorGetCode();\r
-Debug.WriteLine( "BASS_SampleCreate: " + err );\r
                                throw new Exception( "サウンドストリームの生成に失敗しました。(BASS_SampleCreate: " + err + ")" );\r
                        }\r
 \r
                        // ミキサーにBASSファイルストリームを追加。\r
 \r
-                       BassMix.BASS_Mixer_StreamAddChannel( hMixer, this.hBassStream, BASSFlag.BASS_SPEAKER_FRONT | BASSFlag.BASS_MIXER_PAUSE | BASSFlag.BASS_MIXER_NORAMPIN );\r
-\r
+                       bool b = BassMix.BASS_Mixer_StreamAddChannel( hMixer, this.hBassStream, BASSFlag.BASS_SPEAKER_FRONT | BASSFlag.BASS_MIXER_PAUSE | BASSFlag.BASS_MIXER_NORAMPIN );\r
+                       if ( !b )\r
+                       {\r
+                               hGC.Free();\r
+                               BASSError err = Bass.BASS_ErrorGetCode();\r
+                               throw new Exception( "サウンドストリームの生成に失敗しました。(BASS_Mixer_StreamAddChannel: " + err + ")" );\r
+                       }\r
                        // インスタンスリストに登録。\r
 \r
                        CSound.listインスタンス.Add( this );\r
 \r
                        // nBytesとn総演奏時間の取得; DTXMania用に追加。\r
-                       nBytes = (int) ( xa.xaheader.nSamples * xa.xaheader.nChannels * 2 );    // nBytes = Bass.BASS_ChannelGetLength( this.hBassStream );\r
+                       //nBytes = (int) ( xa.xaheader.nSamples * xa.xaheader.nChannels * 2 );  // nBytes = Bass.BASS_ChannelGetLength( this.hBassStream );\r
+                       //nBytes = Bass.BASS_ChannelGetLength( this.hBassStream );\r
+                       //if ( nBytes < 0 )\r
+                       //{\r
+                       //    hGC.Free();\r
+                       //    BASSError err = Bass.BASS_ErrorGetCode();\r
+                       //    throw new Exception( "サウンドストリームの生成に失敗しました。(BASS_ChannelGetLength: " + err + ")" );\r
+                       //}\r
+                       //nBytes = (int) this.byArrWAVファイルイメージ.Length;\r
+\r
                        double seconds = Bass.BASS_ChannelBytes2Seconds( this.hBassStream, nBytes );\r
                        this.n総演奏時間ms = (int) ( seconds * 1000 );\r
+                       this.pos = 0;\r
+                       this.hMixer = hMixer;\r
                }\r
                //-----------------\r
 \r
@@ -1051,6 +1117,91 @@ Debug.WriteLine( "BASS_SampleCreate: " + err );
                        }\r
                        return bytesread;\r
                }\r
+\r
+\r
+               public bool tBASSサウンドをミキサーに追加する()\r
+               {\r
+                       return tBASSサウンドをミキサーに追加する( true );\r
+               }\r
+       \r
+               /// <summary>\r
+               /// \r
+               /// </summary>\r
+               /// <param name="pause">falseなら、追加と同時に再生する</param>\r
+               /// <returns></returns>\r
+               public bool tBASSサウンドをミキサーに追加する( bool pause )\r
+               {\r
+                       BASSFlag bf = BASSFlag.BASS_SPEAKER_FRONT | BASSFlag.BASS_MIXER_NORAMPIN;\r
+                       if ( pause )\r
+                       {\r
+                               bf |= BASSFlag.BASS_MIXER_PAUSE;\r
+                       }\r
+                       return BassMix.BASS_Mixer_StreamAddChannel( this.hMixer, this.hBassStream, bf );\r
+               }\r
+               public bool tBASSサウンドをミキサーから削除する()\r
+               {\r
+                       return BassMix.BASS_Mixer_ChannelRemove( this.hBassStream );\r
+               }\r
+\r
+\r
+               public void tオンメモリ方式でデコードする( string strファイル名, out byte[] buffer,\r
+                       out int nPCMデータの先頭インデックス, out int totalPCMSize, out CWin32.WAVEFORMATEX wfx )\r
+               {\r
+                       nPCMデータの先頭インデックス = 0;\r
+                       //int nPCMサイズbyte = (int) ( xa.xaheader.nSamples * xa.xaheader.nChannels * 2 );   // nBytes = Bass.BASS_ChannelGetLength( this.hBassStream );\r
+\r
+                       SoundDecoder sounddecoder;\r
+\r
+                       if ( String.Compare( Path.GetExtension( strファイル名 ), ".xa", true ) == 0 )\r
+                       {\r
+                               sounddecoder = new Cxa();\r
+                       }\r
+                       else if ( String.Compare( Path.GetExtension( strファイル名 ), ".ogg", true ) == 0 )\r
+                       {\r
+                               sounddecoder = new Cogg();\r
+                       }\r
+                       else\r
+                       {\r
+                               throw new NotImplementedException();\r
+                       }\r
+\r
+                       int nHandle = sounddecoder.Open( strファイル名 );\r
+                       if ( nHandle < 0 )\r
+                       {\r
+                               throw new Exception( string.Format( "Open() に失敗しました。({0})({1})", nHandle, strファイル名 ) );\r
+                       }\r
+                       wfx = new CWin32.WAVEFORMATEX();\r
+                       if ( sounddecoder.GetFormat( nHandle, ref wfx ) < 0 )\r
+                       {\r
+                               sounddecoder.Close( nHandle );\r
+                               throw new Exception( string.Format( "GetFormat() に失敗しました。({0})", strファイル名 ) );\r
+                       }\r
+                       //totalPCMSize = (int) sounddecoder.nTotalPCMSize;              //  tデコード後のサイズを調べる()で既に取得済みの値を流用する。ms単位の高速化だが、チップ音がたくさんあると塵積で結構効果がある\r
+                       totalPCMSize = (int) sounddecoder.GetTotalPCMSize( nHandle );\r
+                       if ( totalPCMSize == 0 )\r
+                       {\r
+                               sounddecoder.Close( nHandle );\r
+                               throw new Exception( string.Format( "GetTotalPCMSize() に失敗しました。({0})", strファイル名 ) );\r
+                       }\r
+                       totalPCMSize += ( ( totalPCMSize % 2 ) != 0 ) ? 1 : 0;\r
+                       buffer = new byte[ totalPCMSize ];\r
+                       GCHandle handle = GCHandle.Alloc( buffer, GCHandleType.Pinned );\r
+                       try\r
+                       {\r
+                               if ( sounddecoder.Decode( nHandle, handle.AddrOfPinnedObject(), (uint) totalPCMSize, 0 ) < 0 )\r
+                               {\r
+                                       buffer = null;\r
+                                       throw new Exception( string.Format( "デコードに失敗しました。({0})", strファイル名 ) );\r
+                               }\r
+                       }\r
+                       finally\r
+                       {\r
+                               handle.Free();\r
+                               sounddecoder.Close( nHandle );\r
+                       }\r
+                       sounddecoder = null;\r
+               }\r
+\r
                #endregion\r
        }\r
 }\r
index dae0b2e..a941b20 100644 (file)
@@ -137,11 +137,35 @@ namespace FDK
                        // ASIO 出力チャンネルの初期化。\r
 \r
                        this.tAsioProc = new ASIOPROC( this.tAsio処理 );              // アンマネージに渡す delegate は、フィールドとして保持しておかないとGCでアドレスが変わってしまう。\r
-                       BassAsio.BASS_ASIO_ChannelEnable( false, 0, this.tAsioProc, IntPtr.Zero );                              // 出力チャンネル0 の有効化。\r
+                       if ( !BassAsio.BASS_ASIO_ChannelEnable( false, 0, this.tAsioProc, IntPtr.Zero ) )               // 出力チャンネル0 の有効化。\r
+                       {\r
+                               #region [ ASIO 出力チャンネルの初期化に失敗。]\r
+                               //-----------------\r
+                               Bass.BASS_Free();\r
+                               throw new Exception( string.Format( "Failed BASS_ASIO_ChannelEnable() [{0}]", BassAsio.BASS_ASIO_ErrorGetCode().ToString() ) );\r
+                               //-----------------\r
+                               #endregion\r
+                       }\r
                        //for( int i = 1; i < this.n出力チャンネル数; i++ )\r
                        //      BassAsio.BASS_ASIO_ChannelJoin( false, i, 0 );\r
-                       BassAsio.BASS_ASIO_ChannelJoin( false, 1, 0 );                                                                                  // 出力チャンネル1をチャンネル0 とグループ化。(ステレオ限定)\r
-                       BassAsio.BASS_ASIO_ChannelSetFormat( false, 0, this.fmtASIOチャンネルフォーマット ); // 出力チャンネル0のフォーマット\r
+                       if (!BassAsio.BASS_ASIO_ChannelJoin( false, 1, 0 ))                                                                             // 出力チャンネル1をチャンネル0 とグループ化。(ステレオ限定)\r
+                       {\r
+                               #region [ 初期化に失敗。]\r
+                               //-----------------\r
+                               Bass.BASS_Free();\r
+                               throw new Exception( string.Format( "Failed BASS_ASIO_ChannelJoin() [{0}]", BassAsio.BASS_ASIO_ErrorGetCode().ToString() ) );\r
+                               //-----------------\r
+                               #endregion\r
+                       }\r
+                       if ( !BassAsio.BASS_ASIO_ChannelSetFormat( false, 0, this.fmtASIOチャンネルフォーマット ) )  // 出力チャンネル0のフォーマット\r
+                       {\r
+                               #region [ ASIO 出力チャンネルの初期化に失敗。]\r
+                               //-----------------\r
+                               Bass.BASS_Free();\r
+                               throw new Exception( string.Format( "Failed BASS_ASIO_ChannelSetFormat() [{0}]", BassAsio.BASS_ASIO_ErrorGetCode().ToString() ) );\r
+                               //-----------------\r
+                               #endregion\r
+                       }\r
 \r
 \r
                        // ASIO 出力と同じフォーマットを持つ BASS ミキサーを作成。\r
@@ -172,11 +196,17 @@ namespace FDK
                        // 出力を開始。\r
 \r
                        this.nバッファサイズsample = (int) ( nバッファサイズms * this.db周波数 / 1000.0 );\r
-                       BassAsio.BASS_ASIO_Start( this.nバッファサイズsample );          // 範囲外の値を指定した場合は自動的にデフォルト値に設定される。\r
-\r
-                       int n遅延sample = BassAsio.BASS_ASIO_GetLatency( false );     // この関数は BASS_ASIO_Start() 後にしか呼び出せない。\r
-                       this.n実出力遅延ms = (long) ( n遅延sample * 1000.0f / this.db周波数 );\r
-                       Trace.TraceInformation( "ASIO デバイス出力開始:バッファ{0}sample [{1}ms(希望{2}ms)]", n遅延sample, this.n実出力遅延ms, nバッファサイズms );\r
+                       if ( !BassAsio.BASS_ASIO_Start( this.nバッファサイズsample ) )           // 範囲外の値を指定した場合は自動的にデフォルト値に設定される。\r
+                       {\r
+                               Bass.BASS_Free();\r
+                               throw new Exception( "ASIO デバイス出力開始に失敗しました。" + BassAsio.BASS_ASIO_ErrorGetCode().ToString() );\r
+                       }\r
+                       else\r
+                       {\r
+                               int n遅延sample = BassAsio.BASS_ASIO_GetLatency( false );     // この関数は BASS_ASIO_Start() 後にしか呼び出せない。\r
+                               this.n実出力遅延ms = (long) ( n遅延sample * 1000.0f / this.db周波数 );\r
+                               Trace.TraceInformation( "ASIO デバイス出力開始:バッファ{0}sample [{1}ms(希望{2}ms)]", n遅延sample, this.n実出力遅延ms, nバッファサイズms );\r
+                       }\r
                }\r
 \r
                public CSound tサウンドを作成する( string strファイル名 )\r
diff --git a/FDK17プロジェクト/コード/03.サウンド/Cogg.cs b/FDK17プロジェクト/コード/03.サウンド/Cogg.cs
new file mode 100644 (file)
index 0000000..e50124c
--- /dev/null
@@ -0,0 +1,62 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Runtime.InteropServices;\r
+using System.IO;\r
+using System.Diagnostics;\r
+using System.Threading;\r
+\r
+\r
+namespace FDK\r
+{\r
+       public unsafe class Cogg : SoundDecoder\r
+       {\r
+               static byte[] FOURCC = Encoding.ASCII.GetBytes( "SggO" );       // OggS の little endian\r
+\r
+\r
+               #region [ SoundDecoder.dll インポート(ogg 関連)]\r
+               //-----------------\r
+               [DllImport( "SoundDecoder.dll" )]\r
+               private static extern void oggClose( int nHandle );\r
+               [DllImport( "SoundDecoder.dll" )]\r
+               private static extern int oggDecode( int nHandle, IntPtr pDest, uint szDestSize, int bLoop );\r
+               [DllImport( "SoundDecoder.dll" )]\r
+               private static extern int oggGetFormat( int nHandle, ref CWin32.WAVEFORMATEX wfx );\r
+               [DllImport( "SoundDecoder.dll" )]\r
+               private static extern uint oggGetTotalPCMSize( int nHandle );\r
+               [DllImport( "SoundDecoder.dll" )]\r
+               private static extern int oggOpen( string fileName );\r
+               [DllImport( "SoundDecoder.dll" )]\r
+               private static extern int oggSeek( int nHandle, uint dwPosition );\r
+               //-----------------\r
+               #endregion\r
+\r
+\r
+               public override int Open( string filename )\r
+               {\r
+                       return oggOpen( filename );\r
+               }\r
+               public override int GetFormat( int nHandle, ref CWin32.WAVEFORMATEX wfx )\r
+               {\r
+                       return oggGetFormat( nHandle, ref wfx );\r
+               }\r
+               public override uint GetTotalPCMSize( int nHandle )\r
+               {\r
+                       return oggGetTotalPCMSize( nHandle );\r
+               }\r
+               public override int Seek( int nHandle, uint dwPosition )\r
+               {\r
+                       return oggSeek( nHandle, dwPosition );\r
+               }\r
+               public override int Decode( int nHandle, IntPtr pDest, uint szDestSize, int bLoop )\r
+               {\r
+                       return oggDecode( nHandle, pDest, szDestSize, bLoop );\r
+               }\r
+\r
+               public override void Close( int nHandle )\r
+               {\r
+                       oggClose( nHandle );\r
+               }\r
+\r
+       }\r
+}\r
index 1335903..ac2ef7d 100644 (file)
@@ -9,9 +9,9 @@ using System.Threading;
 \r
 namespace FDK\r
 {\r
-       public unsafe class Cxa\r
+       public unsafe class Cxa : SoundDecoder  //, IDisposable\r
        {\r
-               static byte[] _XAID = Encoding.ASCII.GetBytes( "1DWK" );        // KWD1 の little endian\r
+               static byte[] FOURCC = Encoding.ASCII.GetBytes( "1DWK" );       // KWD1 の little endian\r
 \r
                #region [ XA用構造体の宣言 ]\r
                [StructLayout(LayoutKind.Sequential)]\r
@@ -58,6 +58,195 @@ namespace FDK
                public XASTREAMHEADER xastreamheader;\r
                public CWin32.WAVEFORMATEX waveformatex;\r
 \r
+               private string filename;\r
+               private byte[] srcBuf = null, dstBuf = null;\r
+               private int nHandle = -1;\r
+\r
+               public override int Open( string filename )\r
+               {\r
+                       this.filename = filename;\r
+\r
+                       #region [ XAヘッダと、XAデータの読み出し  ]\r
+                       xaheader = new XAHEADER();\r
+                       using ( FileStream fs = new FileStream( filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite ) )       // FileShare を付けとかないと、Close() 後もロックがかかる??\r
+                       {\r
+                               using ( BinaryReader br = new BinaryReader( fs ) )\r
+                               {\r
+                                       xaheader.id = br.ReadUInt32();\r
+                                       xaheader.nDataLen = br.ReadUInt32();\r
+                                       xaheader.nSamples = br.ReadUInt32();\r
+                                       xaheader.nSamplesPerSec = br.ReadUInt16();\r
+                                       xaheader.nBits = br.ReadByte();\r
+                                       xaheader.nChannels = br.ReadByte();\r
+                                       xaheader.nLoopPtr = br.ReadUInt32();\r
+\r
+                                       xaheader.befL = new short[ 2 ];\r
+                                       xaheader.befR = new short[ 2 ];\r
+                                       xaheader.pad = new byte[ 4 ];\r
+\r
+                                       xaheader.befL[ 0 ] = br.ReadInt16();\r
+                                       xaheader.befL[ 1 ] = br.ReadInt16();\r
+                                       xaheader.befR[ 0 ] = br.ReadInt16();\r
+                                       xaheader.befR[ 1 ] = br.ReadInt16();\r
+                                       xaheader.pad = br.ReadBytes( 4 );\r
+\r
+                                       srcBuf = new byte[ xaheader.nDataLen ];\r
+                                       srcBuf = br.ReadBytes( (int) xaheader.nDataLen );\r
+                               }\r
+                       }\r
+                       //string xaid = Encoding.ASCII.GetString( xah.id );\r
+                       #region [ デバッグ表示 ]\r
+                       //Debug.WriteLine( "**XAHEADER**" );\r
+                       //Debug.WriteLine( "id=             " + xaheader.id.ToString( "X8" ) );\r
+                       //Debug.WriteLine( "nDataLen=       " + xaheader.nDataLen.ToString( "X8" ) );\r
+                       //Debug.WriteLine( "nSamples=       " + xaheader.nSamples.ToString( "X8" ) );\r
+                       //Debug.WriteLine( "nSamplesPerSec= " + xaheader.nSamplesPerSec.ToString( "X4" ) );\r
+                       //Debug.WriteLine( "nBits=          " + xaheader.nBits.ToString( "X2" ) );\r
+                       //Debug.WriteLine( "nChannels=      " + xaheader.nChannels.ToString( "X2" ) );\r
+                       //Debug.WriteLine( "nLoopPtr=       " + xaheader.nLoopPtr.ToString( "X8" ) );\r
+                       //Debug.WriteLine( "befL[0]=        " + xaheader.befL[ 0 ].ToString( "X4" ) );\r
+                       //Debug.WriteLine( "befL[1]=        " + xaheader.befL[ 1 ].ToString( "X4" ) );\r
+                       //Debug.WriteLine( "befR[0]=        " + xaheader.befR[ 0 ].ToString( "X4" ) );\r
+                       //Debug.WriteLine( "befR[1]=        " + xaheader.befR[ 1 ].ToString( "X4" ) );\r
+                       #endregion\r
+                       #endregion\r
+\r
+                       IntPtr hxas;\r
+\r
+                       #region [ WAVEFORMEX情報の取得  ]\r
+                       waveformatex = new CWin32.WAVEFORMATEX();\r
+                       hxas = xaDecodeOpen( ref xaheader, out waveformatex );\r
+                       if ( hxas == null )\r
+                       {\r
+                               Trace.TraceError( "Error: xa: Open(): xaDecodeOpen(): " + Path.GetFileName( filename ) );\r
+                               dstBuf = null;\r
+                               return -1;\r
+                       }\r
+\r
+                       #region [ デバッグ表示 ]\r
+                       //Debug.WriteLine( "**WAVEFORMATEX**" );\r
+                       //Debug.WriteLine( "wFormatTag=      " + waveformatex.wFormatTag.ToString( "X4" ) );\r
+                       //Debug.WriteLine( "nChannels =      " + waveformatex.nChannels.ToString( "X4" ) );\r
+                       //Debug.WriteLine( "nSamplesPerSec=  " + waveformatex.nSamplesPerSec.ToString( "X8" ) );\r
+                       //Debug.WriteLine( "nAvgBytesPerSec= " + waveformatex.nAvgBytesPerSec.ToString( "X8" ) );\r
+                       //Debug.WriteLine( "nBlockAlign=     " + waveformatex.nBlockAlign.ToString( "X4" ) );\r
+                       //Debug.WriteLine( "wBitsPerSample=  " + waveformatex.wBitsPerSample.ToString( "X4" ) );\r
+                       //Debug.WriteLine( "cbSize=          " + waveformatex.cbSize.ToString( "X4" ) );\r
+                       #endregion\r
+                       #endregion\r
+\r
+                       this.nHandle = (int) hxas;\r
+                       return (int) hxas;\r
+               }\r
+               public override int GetFormat( int nHandle, ref CWin32.WAVEFORMATEX wfx )\r
+               {\r
+                       #region [ WAVEFORMATEX構造体の手動コピー ]\r
+                       wfx.nAvgBytesPerSec = waveformatex.nAvgBytesPerSec;\r
+                       wfx.wBitsPerSample  =  waveformatex.wBitsPerSample;\r
+                       wfx.nBlockAlign     =  waveformatex.nBlockAlign;\r
+                       wfx.nChannels       =  waveformatex.nChannels;\r
+                       wfx.wFormatTag      = waveformatex.wFormatTag;\r
+                       wfx.nSamplesPerSec  = waveformatex.nSamplesPerSec;\r
+\r
+                       return 0;\r
+                       #endregion\r
+               }\r
+               public override uint GetTotalPCMSize( int nHandle )\r
+               {\r
+                       #region [ データ長の取得 ]\r
+                       uint dlen;\r
+                       xaDecodeSize( (IntPtr) nHandle, xaheader.nDataLen, out dlen );\r
+                       #region [ デバッグ表示 ]\r
+                       //Debug.WriteLine( "**INTERNAL VALUE**" );\r
+                       //Debug.WriteLine( "dlen=          " + dlen );\r
+                       #endregion\r
+                       #endregion\r
+\r
+                       return dlen;\r
+               }\r
+               public override int Seek( int nHandle, uint dwPosition )\r
+               {\r
+                       return 0;\r
+               }\r
+               public override int Decode( int nHandle, IntPtr pDest, uint szDestSize, int bLoop )\r
+               {\r
+                       #region [ xaデータのデコード ]\r
+                       xastreamheader = new XASTREAMHEADER();\r
+                       bool b;\r
+                       unsafe\r
+                       {\r
+                               fixed ( byte* pXaBuf = srcBuf )\r
+                               {\r
+                                       byte* pWavBuf = (byte*) pDest;\r
+\r
+                                       xastreamheader.pSrc = pXaBuf;\r
+                                       xastreamheader.nSrcLen = xaheader.nDataLen;\r
+                                       xastreamheader.nSrcUsed = 0;\r
+                                       xastreamheader.pDst = pWavBuf;\r
+                                       xastreamheader.nDstLen = szDestSize;\r
+                                       xastreamheader.nDstUsed = 0;\r
+                                       b = xaDecodeConvert( (IntPtr) nHandle, ref xastreamheader );\r
+                                       if ( !b )\r
+                                       {\r
+                                               Trace.TraceError( "Error: xaDecodeConvert(): " + Path.GetFileName( filename ) );\r
+                                               dstBuf = null;\r
+                                               return -1;\r
+                                       }\r
+                               }\r
+                       }\r
+                       #region [ デバッグ表示 ]\r
+                       //Debug.WriteLine( "**XASTREAMHEADER**" );\r
+                       //Debug.WriteLine( "nSrcLen=  " + xastreamheader.nSrcLen );\r
+                       //Debug.WriteLine( "nSrcUsed= " + xastreamheader.nSrcUsed );\r
+                       //Debug.WriteLine( "nDstLen=  " + xastreamheader.nDstLen );\r
+                       //Debug.WriteLine( "nDstUsed= " + xastreamheader.nDstUsed );\r
+                       #endregion\r
+                       #endregion\r
+\r
+                       return b? 0 : -1;\r
+               }\r
+\r
+               public override void Close( int nHandle )\r
+               {\r
+                       #region [ xaファイルのクローズ ]\r
+                       bool bb = xaDecodeClose( (IntPtr) nHandle );\r
+                       if ( !bb )\r
+                       {\r
+                               Trace.TraceError( "Error: xaDecodeClose(): " + Path.GetFileName( filename ) );\r
+                       }\r
+                       #endregion\r
+               }\r
+\r
+\r
+\r
+               //#region [ IDisposable 実装 ]\r
+               ////-----------------\r
+               //private bool bDispose完了済み = false;\r
+               //public void Dispose()\r
+               //{\r
+               //    if ( !this.bDispose完了済み )\r
+               //    {\r
+               //        if ( srcBuf != null )\r
+               //        {\r
+               //            srcBuf = null;\r
+               //        }\r
+               //        if ( dstBuf != null )\r
+               //        {\r
+               //            dstBuf = null;\r
+               //        }\r
+\r
+               //        if ( this.nHandle >= 0 )\r
+               //        {\r
+               //            this.Close( this.nHandle );\r
+               //            this.nHandle = -1;\r
+               //        }\r
+               //        this.bDispose完了済み = true;\r
+               //    }\r
+               //}\r
+               ////-----------------\r
+               //#endregion\r
+\r
+#if false\r
                /// <summary>\r
                /// xaファイルを読み込んで、wavにdecodeする\r
                /// </summary>\r
@@ -191,5 +380,6 @@ namespace FDK
 \r
                        return true;\r
                }\r
+#endif\r
        }\r
 }\r
diff --git a/FDK17プロジェクト/コード/03.サウンド/SoundDecoder.cs b/FDK17プロジェクト/コード/03.サウンド/SoundDecoder.cs
new file mode 100644 (file)
index 0000000..8eb04e9
--- /dev/null
@@ -0,0 +1,20 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Diagnostics;\r
+\r
+namespace FDK\r
+{\r
+       /// <summary>\r
+       /// xa,oggデコード用の基底クラス\r
+       /// </summary>\r
+       public abstract class SoundDecoder //: IDisposable\r
+       {\r
+               public abstract int Open( string filename );\r
+               public abstract int GetFormat( int nHandle, ref CWin32.WAVEFORMATEX wfx );\r
+               public abstract uint GetTotalPCMSize( int nHandle );\r
+               public abstract int Seek( int nHandle, uint dwPosition );\r
+               public abstract int Decode( int nHandle, IntPtr pDest, uint szDestSize, int bLoop );\r
+               public abstract void Close( int nHandle );\r
+       }\r
+}\r
index e728ab7..f3a612b 100644 (file)
Binary files a/実行時フォルダ/Bass.Net.dll and b/実行時フォルダ/Bass.Net.dll differ
index 2a06f2a..425a60d 100644 (file)
Binary files a/実行時フォルダ/DTXManiaGR.exe and b/実行時フォルダ/DTXManiaGR.exe differ
index 5a3c134..aa76027 100644 (file)
Binary files a/実行時フォルダ/FDK.dll and b/実行時フォルダ/FDK.dll differ
index 963bea5..5d5e81c 100644 (file)
Binary files a/実行時フォルダ/bass.dll and b/実行時フォルダ/bass.dll differ
index fc00a29..001cb4e 100644 (file)
Binary files a/実行時フォルダ/bassasio.dll and b/実行時フォルダ/bassasio.dll differ
index ad54bd0..064974b 100644 (file)
Binary files a/実行時フォルダ/bassmix.dll and b/実行時フォルダ/bassmix.dll differ
index 0b183a6..078e5a5 100644 (file)
Binary files a/実行時フォルダ/basswasapi.dll and b/実行時フォルダ/basswasapi.dll differ