return true;\r
}\r
}\r
- public bool bIsAutoPlayed; // 2011.6.10 yyagi\r
- \r
+ public bool bIsAutoPlayed; // 2011.6.10 yyagi\r
+ public bool b演奏終了後も再生が続くチップである; // #32248 2013.10.14 yyagi\r
+\r
public CChip()\r
{\r
this.nバーからの距離dot = new STDGBVALUE<int>() {\r
this.n発声時刻ms = 0;\r
this.nLag = -999;\r
this.bIsAutoPlayed = false;\r
+ this.b演奏終了後も再生が続くチップである = false;\r
this.dbチップサイズ倍率 = 1.0;\r
this.bHit = false;\r
this.b可視 = true;\r
}\r
}\r
}\r
+ /// <summary>\r
+ /// サウンドミキサーにサウンドを登録・削除する時刻を事前に算出する\r
+ /// </summary>\r
public void PlanToAddMixerChannel()\r
{\r
if ( CDTXMania.Sound管理.GetCurrentSoundDeviceType() == "DirectSound" ) // DShowでの再生の場合はミキシング負荷が高くないため、\r
n整数値 = pChip.n整数値,\r
n整数値・内部番号 = pChip.n整数値・内部番号,\r
n発声時刻ms = nAddMixer時刻ms,\r
- n発声位置 = nAddMixer位置\r
+ n発声位置 = nAddMixer位置,\r
+ b演奏終了後も再生が続くチップである = false\r
};\r
listAddMixerChannel.Add( c_AddMixer );\r
//Debug.WriteLine("listAddMixerChannel:" );\r
//Debug.WriteLine( "n新RemoveMixer時刻ms=" + n新RemoveMixer時刻ms + ",n新RemoveMixer位置=" + n新RemoveMixer位置 );\r
if ( n新RemoveMixer時刻ms < pChip.n発声時刻ms + duration ) // 曲の最後でサウンドが切れるような場合は\r
{\r
- continue; // 発声位置の計算ができないので、Mixer削除をあきらめる\r
+ CChip c_AddMixer_noremove = c_AddMixer;\r
+ c_AddMixer_noremove.b演奏終了後も再生が続くチップである = true;\r
+ listAddMixerChannel[ listAddMixerChannel.Count - 1 ] = c_AddMixer_noremove;\r
+ //continue; // 発声位置の計算ができないので、Mixer削除をあきらめる・・・のではなく\r
+ // #32248 2013.10.15 yyagi 演奏終了後も再生を続けるチップであるというフラグをpChip内に立てる\r
+ break;\r
}\r
#region [ 未使用コード ]\r
//if ( n新RemoveMixer時刻ms < pChip.n発声時刻ms + duration ) // 曲の最後でサウンドが切れるような場合\r
{\r
if ( wc.rSound[ i ] != null )\r
{\r
- CDTXMania.Sound管理.AddMixer( wc.rSound[ i ], db再生速度 );\r
+ CDTXMania.Sound管理.AddMixer( wc.rSound[ i ], db再生速度, pChip.b演奏終了後も再生が続くチップである );\r
//AddMixer( wc.rSound[ i ] ); // 最初はqueueを介さず直接ミキサー登録する\r
}\r
}\r
{\r
internal bool bIsAdd;\r
internal CSound csound;\r
+ internal bool b演奏終了後も再生が続くチップである;\r
};\r
\r
protected CAct演奏AVI actAVI;\r
protected Stopwatch sw2;\r
// protected GCLatencyMode gclatencymode;\r
\r
- public void AddMixer( CSound cs )\r
+ public void AddMixer( CSound cs, bool _b演奏終了後も再生が続くチップである )\r
{\r
stmixer stm = new stmixer()\r
{\r
bIsAdd = true,\r
- csound = cs\r
+ csound = cs,\r
+ b演奏終了後も再生が続くチップである = _b演奏終了後も再生が続くチップである\r
};\r
queueMixerSound.Enqueue( stm );\r
// Debug.WriteLine( "★Queue: add " + Path.GetFileName( stm.csound.strファイル名 ));\r
stmixer stm = new stmixer()\r
{\r
bIsAdd = false,\r
- csound = cs\r
+ csound = cs,\r
+ b演奏終了後も再生が続くチップである = false\r
};\r
queueMixerSound.Enqueue( stm );\r
// Debug.WriteLine( "★Queue: remove " + Path.GetFileName( stm.csound.strファイル名 ));\r
stmixer stm = queueMixerSound.Dequeue();\r
if ( stm.bIsAdd )\r
{\r
- CDTXMania.Sound管理.AddMixer( stm.csound, db再生速度 );\r
+ CDTXMania.Sound管理.AddMixer( stm.csound, db再生速度, stm.b演奏終了後も再生が続くチップである );\r
}\r
else\r
{\r
if ( wc.rSound[ i ] != null )\r
{\r
//CDTXMania.Sound管理.AddMixer( wc.rSound[ i ] );\r
- AddMixer( wc.rSound[ i ] );\r
+ AddMixer( wc.rSound[ i ], pChip.b演奏終了後も再生が続くチップである );\r
}\r
}\r
}\r
if ( wc.rSound[ i ] != null )\r
{\r
//CDTXMania.Sound管理.RemoveMixer( wc.rSound[ i ] );\r
- RemoveMixer( wc.rSound[ i ] );\r
+ if ( !wc.rSound[ i ].b演奏終了後も再生が続くチップである ) // #32248 2013.10.16 yyagi\r
+ { // DTX終了後も再生が続くチップの0xDB登録をなくすことはできず。\r
+ RemoveMixer( wc.rSound[ i ] ); // (ミキサー解除のタイミングが遅延する場合の対応が面倒なので。)\r
+ } // そこで、代わりにフラグをチェックしてミキサー削除ロジックへの遷移をカットする。\r
}\r
}\r
}\r
}\r
}\r
\r
+ public void AddMixer( CSound cs, double db再生速度, bool _b演奏終了後も再生が続くチップである )\r
+ {\r
+ cs.b演奏終了後も再生が続くチップである = _b演奏終了後も再生が続くチップである;\r
+ cs.db再生速度 = db再生速度;\r
+ cs.tBASSサウンドをミキサーに追加する();\r
+ }\r
public void AddMixer( CSound cs, double db再生速度 )\r
{\r
cs.db再生速度 = db再生速度;\r
{\r
cs.tBASSサウンドをミキサーから削除する();\r
}\r
-}\r
+ }\r
#endregion\r
\r
// CSound は、サウンドデバイスが変更されたときも、インスタンスを再作成することなく、新しいデバイスで作り直せる必要がある。\r
}\r
#endregion\r
\r
+ public bool b演奏終了後も再生が続くチップである = false; // これがtrueなら、本サウンドの再生終了のコールバック時に自動でミキサーから削除する\r
+\r
private STREAMPROC _cbStreamXA; // make it global, so that the GC can not remove it\r
-// private SYNCPROC _cbEndofStream; // ストリームの終端まで再生されたときに呼び出されるコールバック\r
+ private SYNCPROC _cbEndofStream; // ストリームの終端まで再生されたときに呼び出されるコールバック\r
// private WaitCallback _cbRemoveMixerChannel;\r
\r
/// <summary>\r
if ( this.bBASSサウンドである ) // stream数の削減用\r
{\r
tBASSサウンドをミキサーから削除する();\r
- //_cbEndofStream = null;\r
+ _cbEndofStream = null;\r
//_cbStreamXA = null;\r
CSound管理.nStreams--;\r
}\r
bool b = BassMix.BASS_Mixer_ChannelPlay( this.hBassStream );\r
if ( !b )\r
{\r
-Debug.WriteLine( "再生しようとしたが、Mixerに登録されていなかった: " + Path.GetFileName( this.strファイル名 ) + ", stream#=" + this.hBassStream + ", ErrCode=" + Bass.BASS_ErrorGetCode() );\r
+//Debug.WriteLine( "再生しようとしたが、Mixerに登録されていなかった: " + Path.GetFileName( this.strファイル名 ) + ", stream#=" + this.hBassStream + ", ErrCode=" + Bass.BASS_ErrorGetCode() );\r
\r
bool bb = tBASSサウンドをミキサーに追加する();\r
if ( !bb )\r
this.hBassStream = _hBassStream;\r
}\r
\r
+ // #32248 再生終了時に発火するcallbackを登録する (演奏終了後に再生終了するチップを非同期的にミキサーから削除するため。)\r
+ _cbEndofStream = new SYNCPROC( CallbackEndofStream );\r
+ Bass.BASS_ChannelSetSync( hBassStream, BASSSync.BASS_SYNC_END | BASSSync.BASS_SYNC_MIXTIME, 0, _cbEndofStream, IntPtr.Zero );\r
+\r
// インスタンスリストに登録。\r
\r
CSound.listインスタンス.Add( this );\r
}\r
return bytesread;\r
}\r
-\r
+ /// <summary>\r
+ /// ストリームの終端まで再生したときに呼び出されるコールバック\r
+ /// </summary>\r
+ /// <param name="handle"></param>\r
+ /// <param name="channel"></param>\r
+ /// <param name="data"></param>\r
+ /// <param name="user"></param>\r
+ private void CallbackEndofStream( int handle, int channel, int data, IntPtr user ) // #32248 2013.10.14 yyagi\r
+ {\r
+ // Debug.WriteLine( "Callback!(remove): " + Path.GetFileName( this.strファイル名 ) );\r
+ if ( b演奏終了後も再生が続くチップである ) // 演奏終了後に再生終了するチップ音のミキサー削除は、再生終了のコールバックに引っ掛けて、自前で行う。\r
+ { // そうでないものは、ミキサー削除予定時刻に削除する。\r
+ tBASSサウンドをミキサーから削除する( channel );\r
+ }\r
+ }\r
\r
// mixerからの削除\r
\r