OSDN Git Service

#37271 TimeStretch=OFFの時に限り、ミキシング負荷を従来の半分にした。
[dtxmania/dtxmania.git] / FDK17プロジェクト / コード / 03.サウンド / CSound.cs
index 4a21da8..5ea1acc 100644 (file)
@@ -6,9 +6,9 @@ using System.Runtime.InteropServices;
 using System.IO;\r
 using System.Runtime.CompilerServices;\r
 using System.Threading;\r
-using SharpDX;\r
-using SharpDX.DirectSound;\r
-using SharpDX.Multimedia;\r
+using SlimDX;\r
+using SlimDX.DirectSound;\r
+using SlimDX.Multimedia;\r
 using Un4seen.Bass;\r
 using Un4seen.BassAsio;\r
 using Un4seen.BassWasapi;\r
@@ -48,50 +48,6 @@ namespace FDK
                        {\r
                                return _nMasterVolume;\r
                        }\r
-                       //get\r
-                       //{\r
-                       //    if ( SoundDeviceType == ESoundDeviceType.ExclusiveWASAPI || SoundDeviceType == ESoundDeviceType.ASIO )\r
-                       //    {\r
-                       //        return Bass.BASS_GetConfig(BASSConfig.BASS_CONFIG_GVOL_STREAM ) / 100;\r
-                       //    }\r
-                       //    else\r
-                       //    {\r
-                       //        return 100;\r
-                       //    }\r
-                       //}\r
-                       //set\r
-                       //{\r
-                       //    if ( SoundDeviceType == ESoundDeviceType.ExclusiveWASAPI )\r
-                       //    {\r
-                       //                      // LINEARでなくWINDOWS(2)を使う必要があるが、exclusive時は使用不可、またデバイス側が対応してないと使用不可\r
-                       //        bool b = BassWasapi.BASS_WASAPI_SetVolume( BASSWASAPIVolume.BASS_WASAPI_CURVE_LINEAR, value / 100.0f );\r
-                       //        if ( !b )\r
-                       //        {\r
-                       //            BASSError be = Bass.BASS_ErrorGetCode();\r
-                       //            Trace.TraceInformation( "WASAPI Master Volume Set Error: " + be.ToString() );\r
-                       //        }\r
-                       //    }\r
-                       //}\r
-                       //set\r
-                       //{\r
-                       //    if ( SoundDeviceType == ESoundDeviceType.ExclusiveWASAPI || SoundDeviceType == ESoundDeviceType.ASIO )\r
-                       //    {\r
-                       //        bool b = Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_GVOL_STREAM, value * 100 );\r
-                       //        if ( !b )\r
-                       //        {\r
-                       //            BASSError be = Bass.BASS_ErrorGetCode();\r
-                       //            Trace.TraceInformation( "Master Volume Set Error: " + be.ToString() );\r
-                       //        }\r
-                       //    }\r
-                       //}\r
-                       //set\r
-                       //{\r
-                       //    if ( SoundDeviceType == ESoundDeviceType.ExclusiveWASAPI || SoundDeviceType == ESoundDeviceType.ASIO )\r
-                       //    {\r
-                       //        var nodes = new BASS_MIXER_NODE[ 1 ] { new BASS_MIXER_NODE( 0, (float) value ) };\r
-                       //        BassMix.BASS_Mixer_ChannelSetEnvelope( SoundDevice.hMixer, BASSMIXEnvelope.BASS_MIXER_ENV_VOL, nodes );\r
-                       //    }\r
-                       //}\r
                        set\r
                        {\r
                                SoundDevice.nMasterVolume = value;\r
@@ -144,14 +100,6 @@ namespace FDK
                /// <para>SoundDelay よりも小さい値であること。(小さすぎる場合はBASSによって自動修正される。)</para>\r
                /// </summary>\r
                public static int SoundUpdatePeriodSharedWASAPI = 6;\r
-               /// <summary>\r
-               /// WASAPI利用時に、サウンドバッファの更新をevent drivenにするか、pollingにするかの設定。\r
-               /// デフォルト設定はpolling。event drivenにすることで、よりラグを小さくできるが、CPU負荷は若干上昇する。\r
-               /// (更新頻度が上がるため)\r
-               /// なおこれをtrueにすると、SoundUpdatePeriodExclusiveWASAPIの設定は無視される。\r
-               /// </summary>\r
-               public static bool bSoundUpdateByEventWASAPI = false;\r
-\r
                ///// <summary>\r
                ///// <para>ASIO 出力における再生遅延[ms](の希望値)。最終的にはこの数値を基にドライバが決定する)。</para>\r
                ///// </summary>\r
@@ -216,15 +164,12 @@ namespace FDK
                /// <param name="nSoundDelayExclusiveWASAPI"></param>\r
                /// <param name="nSoundDelayASIO"></param>\r
                /// <param name="nASIODevice"></param>\r
-               public CSound管理( IntPtr handle, ESoundDeviceType soundDeviceType,\r
-                       int nSoundDelayExclusiveWASAPI, bool _bSoundUpdateByEventWASAPI,\r
-                       int nSoundDelayASIO, int nASIODevice,\r
-                       bool _bUseOSTimer )\r
+               public CSound管理( IntPtr handle, ESoundDeviceType soundDeviceType, int nSoundDelayExclusiveWASAPI, int nSoundDelayASIO, int nASIODevice, bool _bUseOSTimer )\r
                {\r
                        WindowHandle = handle;\r
                        SoundDevice = null;\r
                        //bUseOSTimer = false;\r
-                       t初期化( soundDeviceType, nSoundDelayExclusiveWASAPI, _bSoundUpdateByEventWASAPI, nSoundDelayASIO, nASIODevice, _bUseOSTimer );\r
+                       t初期化( soundDeviceType, nSoundDelayExclusiveWASAPI, nSoundDelayASIO, nASIODevice, _bUseOSTimer );\r
                }\r
                public void Dispose()\r
                {\r
@@ -247,13 +192,10 @@ namespace FDK
                }\r
                public void t初期化( ESoundDeviceType soundDeviceType, int _nSoundDelayExclusiveWASAPI, int _nSoundDelayASIO, int _nASIODevice )\r
                {\r
-                       t初期化( soundDeviceType, _nSoundDelayExclusiveWASAPI, false, _nSoundDelayASIO, _nASIODevice, false );\r
+                       t初期化( soundDeviceType, _nSoundDelayExclusiveWASAPI, _nSoundDelayASIO, _nASIODevice, false );\r
                }\r
 \r
-               public void t初期化( ESoundDeviceType soundDeviceType,\r
-                       int _nSoundDelayExclusiveWASAPI, bool _bSoundUpdateByEventWASAPI,\r
-                       int _nSoundDelayASIO, int _nASIODevice,\r
-                       bool _bUseOSTimer )\r
+               public void t初期化( ESoundDeviceType soundDeviceType, int _nSoundDelayExclusiveWASAPI, int _nSoundDelayASIO, int _nASIODevice, bool _bUseOSTimer )\r
                {\r
                        //SoundDevice = null;                                           // 後で再初期化することがあるので、null初期化はコンストラクタに回す\r
                        rc演奏用タイマ = null;                                            // Global.Bass 依存(つまりユーザ依存)\r
@@ -263,7 +205,6 @@ namespace FDK
                        SoundDelayASIO = _nSoundDelayASIO;\r
                        ASIODevice = _nASIODevice;\r
                        bUseOSTimer = _bUseOSTimer;\r
-                       bSoundUpdateByEventWASAPI = _bSoundUpdateByEventWASAPI;\r
 \r
                        ESoundDeviceType[] ESoundDeviceTypes = new ESoundDeviceType[ 4 ]\r
                        {\r
@@ -742,10 +683,9 @@ namespace FDK
                                throw new NotImplementedException();\r
                        }\r
                        CSound clone = (CSound) MemberwiseClone();      // これだけだとCY連打が途切れる&タイトルに戻る際にNullRef例外発生\r
-                       clone.Buffer = this.DirectSound.DuplicateSoundBuffer( this.Buffer );\r
+                       this.DirectSound.DuplicateSoundBuffer( this.Buffer, out clone.Buffer );\r
 \r
-                       // CSound.listインスタンス.Add( this );                   // インスタンスリストに登録。\r
-                       // 本来これを加えるべきだが、Add後Removeできなくなっている。Clone()の仕方の問題であろう。\r
+                       CSound.listインスタンス.Add( clone );                     // インスタンスリストに登録。\r
 \r
                        return clone;\r
                }\r
@@ -773,6 +713,7 @@ namespace FDK
                {\r
                        this.e作成方法 = E作成方法.ファイルから;\r
                        this.strファイル名 = strファイル名;\r
+\r
                        if ( String.Compare( Path.GetExtension( strファイル名 ), ".xa", true ) == 0 ||\r
                                 String.Compare( Path.GetExtension( strファイル名 ), ".mp3", true ) == 0 ||\r
                                 String.Compare( Path.GetExtension( strファイル名 ), ".ogg", true ) == 0 ) // caselessで文字列比較\r
@@ -791,9 +732,9 @@ namespace FDK
                                //-----------------\r
                                try\r
                                {\r
-                                       using( var ws = new SoundStream( new FileStream( strファイル名, FileMode.Open ) ) )\r
+                                       using ( var ws = new WaveStream( strファイル名 ) )\r
                                        {\r
-                                               if( ws.Format.Encoding != WaveFormatEncoding.Pcm )\r
+                                               if ( ws.Format.FormatTag != WaveFormatTag.Pcm )\r
                                                        bファイルがWAVかつPCMフォーマットである = false;\r
                                        }\r
                                }\r
@@ -839,6 +780,7 @@ namespace FDK
                        this.strファイル名 = strファイル名;\r
 \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
 \r
@@ -846,10 +788,16 @@ namespace FDK
                        CWin32.WAVEFORMATEX cw32wfx;\r
                        tオンメモリ方式でデコードする( strファイル名, out this.byArrWAVファイルイメージ,\r
                        out nPCMデータの先頭インデックス, out nPCMサイズbyte, out cw32wfx, false );\r
-                       WaveFormat wfx = WaveFormat.CreateCustomFormat( WaveFormatEncoding.Pcm, (int) cw32wfx.nSamplesPerSec, (int) cw32wfx.nChannels, (int) cw32wfx.nAvgBytesPerSec, (int) cw32wfx.nBlockAlign, (int) cw32wfx.wBitsPerSample );\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) cw32wfx.nSamplesPerSec;\r
 \r
                        // セカンダリバッファを作成し、PCMデータを書き込む。\r
-                       tDirectSoundサウンドを作成する_セカンダリバッファの作成とWAVデータ書き込み\r
+                       tDirectSoundサウンドを作成するセカンダリバッファの作成とWAVデータ書き込み\r
                                ( ref this.byArrWAVファイルイメージ, DirectSound, CSoundDeviceDirectSound.DefaultFlags, wfx,\r
                                  nPCMサイズbyte, nPCMデータの先頭インデックス );\r
                }\r
@@ -894,34 +842,29 @@ namespace FDK
                                        {\r
                                                long chunkSize = (long) br.ReadUInt32();\r
 \r
-                                               var tag = (WaveFormatEncoding) br.ReadUInt16();\r
-                                               var channels = br.ReadInt16();\r
-                                               var samplesPerSecond = br.ReadInt32();\r
-                                               var averageBytesPerSecond = br.ReadInt32();\r
-                                               var blockAlignment = br.ReadInt16();\r
-                                               var bitsPerSample = br.ReadInt16();\r
+                                               var tag = (WaveFormatTag) br.ReadUInt16();\r
 \r
-                                               if( tag == WaveFormatEncoding.Pcm )\r
-                                               {\r
-                                                       wfx = WaveFormat.CreateCustomFormat( tag, samplesPerSecond, channels, averageBytesPerSecond, blockAlignment, bitsPerSample );\r
-                                               }\r
-                                               else if( tag == WaveFormatEncoding.Extensible )\r
-                                               {\r
-                                                       wfx = SharpDX.Multimedia.WaveFormatExtensible.CreateCustomFormat( // このクラスは WaveFormat を継承している。\r
-                                                               tag, samplesPerSecond, channels, averageBytesPerSecond, blockAlignment, bitsPerSample );\r
-                                               }\r
+                                               if( tag == WaveFormatTag.Pcm ) wfx = new WaveFormat();\r
+                                               else if( tag == WaveFormatTag.Extensible ) wfx = new SlimDX.Multimedia.WaveFormatExtensible();  // このクラスは WaveFormat を継承している。\r
                                                else\r
                                                        throw new InvalidDataException( string.Format( "未対応のWAVEフォーマットタグです。(Tag:{0})", tag.ToString() ) );\r
 \r
+                                               wfx.FormatTag = tag;\r
+                                               wfx.Channels = br.ReadInt16();\r
+                                               wfx.SamplesPerSecond = br.ReadInt32();\r
+                                               wfx.AverageBytesPerSecond = br.ReadInt32();\r
+                                               wfx.BlockAlignment = br.ReadInt16();\r
+                                               wfx.BitsPerSample = br.ReadInt16();\r
+\r
                                                long nフォーマットサイズbyte = 16;\r
 \r
-                                               if( wfx.Encoding == WaveFormatEncoding.Extensible )\r
+                                               if( wfx.FormatTag == WaveFormatTag.Extensible )\r
                                                {\r
-                                                       br.ReadUInt16();    // 拡張領域サイズbyte\r
-                                                       var wfxEx = (SharpDX.Multimedia.WaveFormatExtensible) wfx;\r
-                                                       /*wfxEx.ValidBitsPerSample = */br.ReadInt16(); // 対応するメンバがない?\r
+                                                       br.ReadUInt16();        // 拡張領域サイズbyte\r
+                                                       var wfxEx = (SlimDX.Multimedia.WaveFormatExtensible) wfx;\r
+                                                       wfxEx.ValidBitsPerSample = br.ReadInt16();\r
                                                        wfxEx.ChannelMask = (Speakers) br.ReadInt32();\r
-                                                       wfxEx.GuidSubFormat = new Guid( br.ReadBytes( 16 ) );   // GUID は 16byte (128bit)\r
+                                                       wfxEx.SubFormat = new Guid( br.ReadBytes( 16 ) );       // GUID は 16byte (128bit)\r
 \r
                                                        nフォーマットサイズbyte += 24;\r
                                                }\r
@@ -964,23 +907,21 @@ namespace FDK
 \r
 \r
                        // セカンダリバッファを作成し、PCMデータを書き込む。\r
-                       tDirectSoundサウンドを作成する_セカンダリバッファの作成とWAVデータ書き込み(\r
+                       tDirectSoundサウンドを作成するセカンダリバッファの作成とWAVデータ書き込み(\r
                                ref byArrWAVファイルイメージ, DirectSound, flags, wfx, nPCMサイズbyte, nPCMデータの先頭インデックス );\r
                }\r
 \r
-               private void tDirectSoundサウンドを作成する_セカンダリバッファの作成とWAVデータ書き込み\r
+               private void tDirectSoundサウンドを作成するセカンダリバッファの作成とWAVデータ書き込み\r
                        ( ref byte[] byArrWAVファイルイメージ, DirectSound DirectSound, BufferFlags flags, WaveFormat wfx,\r
                        int nPCMサイズbyte, int nPCMデータの先頭インデックス )\r
                {\r
                        // セカンダリバッファを作成し、PCMデータを書き込む。\r
 \r
-                       this._Format = wfx;\r
-\r
                        this.Buffer = new SecondarySoundBuffer( DirectSound, new SoundBufferDescription()\r
                        {\r
-                               Format = this._Format,\r
+                               Format = ( wfx.FormatTag == WaveFormatTag.Pcm ) ? wfx : (SlimDX.Multimedia.WaveFormatExtensible) wfx,\r
                                Flags = flags,\r
-                               BufferBytes = nPCMサイズbyte,\r
+                               SizeInBytes = nPCMサイズbyte,\r
                        } );\r
                        this.Buffer.Write( byArrWAVファイルイメージ, nPCMデータの先頭インデックス, nPCMサイズbyte, 0, LockFlags.None );\r
 \r
@@ -992,10 +933,12 @@ namespace FDK
                        this.DirectSound = DirectSound;\r
 \r
                        // DTXMania用に追加\r
-                       this.nオリジナルの周波数 = wfx.SampleRate;\r
-                       n総演奏時間ms = (int) ( ( (double) nPCMサイズbyte ) / ( this._Format.AverageBytesPerSecond * 0.001 ) );\r
+                       this.nオリジナルの周波数 = wfx.SamplesPerSecond;\r
+                       n総演奏時間ms = (int) ( ( (double) nPCMサイズbyte ) / ( this.Buffer.Format.AverageBytesPerSecond * 0.001 ) );\r
+\r
 \r
                        // インスタンスリストに登録。\r
+\r
                        CSound.listインスタンス.Add( this );\r
                }\r
 \r
@@ -1065,7 +1008,7 @@ namespace FDK
                        {\r
                                if ( this.eデバイス種別 == ESoundDeviceType.DirectSound )\r
                                {\r
-                                       return ( ( this.Buffer.Status & (int) BufferStatus.Playing ) != (int) BufferStatus.None );\r
+                                       return ( ( this.Buffer.Status & BufferStatus.Playing ) != BufferStatus.None );\r
                                }\r
                                else\r
                                {\r
@@ -1205,78 +1148,45 @@ Debug.WriteLine("更に再生に失敗: " + Path.GetFileName(this.strファイ
                        }\r
                        else if( this.bDirectSoundである )\r
                        {\r
-                               this.Buffer.CurrentPosition = 0;\r
+                               this.Buffer.CurrentPlayPosition = 0;\r
                        }\r
                }\r
                public void t再生位置を変更する( long n位置ms )\r
                {\r
-                       if( this.bBASSサウンドである )\r
+                       if ( this.bBASSサウンドである )\r
                        {\r
                                bool b = true;\r
                                try\r
                                {\r
                                        b = BassMix.BASS_Mixer_ChannelSetPosition( this.hBassStream, Bass.BASS_ChannelSeconds2Bytes( this.hBassStream, n位置ms * this.db周波数倍率 * this.db再生速度 / 1000.0 ), BASSMode.BASS_POS_BYTES );\r
                                }\r
-                               catch( Exception e )\r
+                               catch ( Exception e )\r
                                {\r
-                                       Trace.TraceInformation( Path.GetFileName( this.strファイル名 ) + ": Seek error: " + e.ToString() + ": " + n位置ms + "ms" );\r
+                                       Trace.TraceInformation( Path.GetFileName( this.strファイル名 ) + ": Seek error: " + e.ToString() );\r
                                }\r
                                finally\r
                                {\r
                                        if ( !b )\r
                                        {\r
                                                BASSError be = Bass.BASS_ErrorGetCode();\r
-                                               Trace.TraceInformation( Path.GetFileName( this.strファイル名 ) + ": Seek error: " + be.ToString() + ": " + n位置ms + "MS" );\r
+                                               Trace.TraceInformation( Path.GetFileName( this.strファイル名 ) + ": Seek error: " + be.ToString() );\r
                                        }\r
                                }\r
-                               //if ( this.n総演奏時間ms > 5000 )\r
-                               //{\r
-                               //    Trace.TraceInformation( Path.GetFileName( this.strファイル名 ) + ": Seeked to " + n位置ms + "ms = " + Bass.BASS_ChannelSeconds2Bytes( this.hBassStream, n位置ms * this.db周波数倍率 * this.db再生速度 / 1000.0 ) );\r
-                               //}\r
                        }\r
                        else if( this.bDirectSoundである )\r
                        {\r
-                               int n位置sample = (int) ( this._Format.SampleRate * n位置ms * 0.001 * _db周波数倍率 * _db再生速度 );  // #30839 2013.2.24 yyagi; add _db周波数倍率 and _db再生速度\r
+                               int n位置sample = (int) ( this.Buffer.Format.SamplesPerSecond * n位置ms * 0.001 * _db周波数倍率 * _db再生速度 );   // #30839 2013.2.24 yyagi; add _db周波数倍率 and _db再生速度\r
                                try\r
                                {\r
-                                       this.Buffer.CurrentPosition = n位置sample * this._Format.BlockAlign;\r
+                                       this.Buffer.CurrentPlayPosition = n位置sample * this.Buffer.Format.BlockAlignment;\r
                                }\r
-                               catch ( Exception e )\r
+                               catch ( DirectSoundException e )\r
                                {\r
                                        Trace.TraceError( "{0}: Seek error: {1}", Path.GetFileName( this.strファイル名 ), n位置ms, e.Message );\r
                                }\r
-                               //if ( this.n総演奏時間ms > 5000 )\r
-                               //{\r
-                               //    Trace.TraceInformation( Path.GetFileName( this.strファイル名 ) + ": Seeked to " + n位置ms + "ms = " + n位置sample );\r
-                               //}\r
-                       }\r
-               }\r
-               /// <summary>\r
-               /// デバッグ用\r
-               /// </summary>\r
-               /// <param name="n位置byte"></param>\r
-               /// <param name="db位置ms"></param>\r
-               public void t再生位置を取得する( out long n位置byte, out double db位置ms )\r
-               {\r
-                       if ( this.bBASSサウンドである )\r
-                       {\r
-                               n位置byte = BassMix.BASS_Mixer_ChannelGetPosition( this.hBassStream );\r
-                               db位置ms = Bass.BASS_ChannelBytes2Seconds( this.hBassStream, n位置byte );\r
-                       }\r
-                       else if ( this.bDirectSoundである )\r
-                       {\r
-                               this.Buffer.GetCurrentPosition( out int pos, out _ );\r
-                               n位置byte = (long) pos;\r
-                               db位置ms = n位置byte / this._Format.SampleRate / 0.001 / _db周波数倍率 / _db再生速度;\r
-                       }\r
-                       else\r
-                       {\r
-                               n位置byte = 0;\r
-                               db位置ms = 0.0;\r
                        }\r
                }\r
 \r
-\r
                public static void tすべてのサウンドを初期状態に戻す()\r
                {\r
                        foreach ( var sound in CSound.listインスタンス )\r
@@ -1493,7 +1403,6 @@ Debug.WriteLine("更に再生に失敗: " + Path.GetFileName(this.strファイ
                private double _db周波数倍率 = 1.0;\r
                private double _db再生速度 = 1.0;\r
                private bool bIs1倍速再生 = true;\r
-               private WaveFormat _Format;\r
 \r
                private void tBASSサウンドを作成する( string strファイル名, int hMixer, BASSFlag flags )\r
                {\r
@@ -1514,7 +1423,7 @@ Debug.WriteLine("更に再生に失敗: " + Path.GetFileName(this.strファイ
 \r
                                default:\r
                                        break;\r
-                       }\r
+                               }\r
                        #endregion\r
 \r
                        this.e作成方法 = E作成方法.ファイルから;\r
@@ -1529,7 +1438,7 @@ Debug.WriteLine("更に再生に失敗: " + Path.GetFileName(this.strファイ
                        \r
                        nBytes = Bass.BASS_ChannelGetLength( this._hBassStream );\r
                        \r
-                       tBASSサウンドを作成する_ストリーム生成後の共通処理( hMixer );\r
+                       tBASSサウンドを作成するストリーム生成後の共通処理( hMixer );\r
                }\r
                private void tBASSサウンドを作成する( byte[] byArrWAVファイルイメージ, int hMixer, BASSFlag flags )\r
                {\r
@@ -1546,9 +1455,8 @@ Debug.WriteLine("更に再生に失敗: " + Path.GetFileName(this.strファイ
 \r
                        nBytes = Bass.BASS_ChannelGetLength( this._hBassStream );\r
        \r
-                       tBASSサウンドを作成する_ストリーム生成後の共通処理( hMixer );\r
+                       tBASSサウンドを作成するストリーム生成後の共通処理( hMixer );\r
                }\r
-\r
                /// <summary>\r
                /// Decode "RIFF chunked Vorbis" to "raw wave"\r
                /// because BASE.DLL has two problems for RIFF chunked Vorbis;\r
@@ -1565,10 +1473,10 @@ Debug.WriteLine("更に再生に失敗: " + Path.GetFileName(this.strファイ
                        //-----------------\r
                        try\r
                        {\r
-                               using( var ws = new SoundStream( new FileStream( strファイル名, FileMode.Open ) ) )\r
+                               using ( var ws = new WaveStream( strファイル名 ) )\r
                                {\r
-                                       if( ws.Format.Encoding == WaveFormatEncoding.OggVorbisMode2Plus ||\r
-                                               ws.Format.Encoding == WaveFormatEncoding.OggVorbisMode3Plus )\r
+                                       if ( ws.Format.FormatTag == ( WaveFormatTag ) 0x6770 || // Ogg Vorbis Mode 2+\r
+                                                ws.Format.FormatTag == ( WaveFormatTag ) 0x6771 )      // Ogg Vorbis Mode 3+\r
                                        {\r
                                                Trace.TraceInformation( Path.GetFileName( strファイル名 ) + ": RIFF chunked Vorbis. Decode to raw Wave first, to avoid BASS.DLL troubles" );\r
                                                try\r
@@ -1588,7 +1496,7 @@ Debug.WriteLine("更に再生に失敗: " + Path.GetFileName(this.strファイ
                                // DirectShowのデコードに失敗したら、次はACMでのデコードを試すことになるため、ここではエラーログを出さない。\r
                                // Trace.TraceWarning( "Warning: " + Path.GetFileName( strファイル名 ) + " : デコードに失敗しました。" );\r
                        }\r
-                       catch ( Exception )\r
+                       catch ( Exception )\r
                        {\r
                                Trace.TraceWarning( "Warning: " + Path.GetFileName( strファイル名 ) + " : 読み込みに失敗しました。" );\r
                        }\r
@@ -1596,7 +1504,6 @@ Debug.WriteLine("更に再生に失敗: " + Path.GetFileName(this.strファイ
 \r
                        return bファイルにVorbisコンテナが含まれている;\r
                }\r
-\r
                private void tBASSサウンドを作成するXA( string strファイル名, int hMixer, BASSFlag flags )\r
                {\r
                        int nPCMデータの先頭インデックス;\r
@@ -1630,17 +1537,18 @@ Debug.WriteLine("更に再生に失敗: " + Path.GetFileName(this.strファイ
                        nBytes = Bass.BASS_ChannelGetLength( this._hBassStream );\r
 \r
 \r
-                       tBASSサウンドを作成する_ストリーム生成後の共通処理( hMixer );\r
+                       tBASSサウンドを作成するストリーム生成後の共通処理( hMixer );\r
                }\r
 \r
 \r
-               private void tBASSサウンドを作成する_ストリーム生成後の共通処理( int hMixer )\r
+               private void tBASSサウンドを作成するストリーム生成後の共通処理( int hMixer )\r
                {\r
                        CSound管理.nStreams++;\r
 \r
                        // 個々のストリームの出力をテンポ変更のストリームに入力する。テンポ変更ストリームの出力を、Mixerに出力する。\r
 \r
-//                     if ( CSound管理.bIsTimeStretch )      // TimeStretchのON/OFFに関わりなく、テンポ変更のストリームを生成する。後からON/OFF切り替え可能とするため。\r
+                       _hTempoStream = 0;\r
+                       if ( CSound管理.bIsTimeStretch )      // TimeStretchのON/OFFに関わりなく、テンポ変更のストリームを生成する。後からON/OFF切り替え可能とするため。\r
                        {\r
                                this._hTempoStream = BassFx.BASS_FX_TempoCreate( this._hBassStream, BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_FX_FREESOURCE );\r
                                if ( this._hTempoStream == 0 )\r