2 using System.Collections.Generic;
\r
4 using System.Runtime.InteropServices;
\r
5 using System.Drawing;
\r
6 using System.Diagnostics;
\r
8 using System.Security.Cryptography;
\r
9 using System.Reflection;
\r
10 using System.Globalization;
\r
11 using System.Threading;
\r
17 /// CDTX 内で用いる入れ子型を partial にし、ここで定義します。
\r
19 public partial class CDTX : CActivity
\r
22 public int nBGMAdjust
\r
27 public string ARTIST;
\r
28 public string BACKGROUND;
\r
29 public string BACKGROUND_GR;
\r
30 public double BASEBPM;
\r
31 public bool BLACKCOLORKEY;
\r
33 public STチップがある bチップがある;
\r
34 public string COMMENT;
\r
35 public double db再生速度;
\r
37 public string GENRE;
\r
38 public bool HIDDENLEVEL;
\r
39 public STDGBVALUE<int> LEVEL;
\r
40 public Dictionary<int, CAVI> listAVI;
\r
41 public Dictionary<int, CAVIPAN> listAVIPAN;
\r
42 public Dictionary<int, CBGA> listBGA;
\r
43 public Dictionary<int, CBGAPAN> listBGAPAN;
\r
44 public Dictionary<int, CBMP> listBMP;
\r
45 public Dictionary<int, CBMPTEX> listBMPTEX;
\r
46 public Dictionary<int, CBPM> listBPM;
\r
47 public List<CChip> listChip;
\r
48 public Dictionary<int, CWAV> listWAV;
\r
49 public string MIDIFILE;
\r
50 public bool MIDINOTE;
\r
52 public STLANEINT n可視チップ数;
\r
53 public const int n最大音数 = 4;
\r
54 public const int n小節の解像度 = 384;
\r
55 public string PANEL;
\r
56 public string PATH_WAV;
\r
57 public string PREIMAGE;
\r
58 public string PREMOVIE;
\r
59 public string PREVIEW;
\r
60 public STRESULT RESULTIMAGE;
\r
61 public STRESULT RESULTMOVIE;
\r
62 public STRESULT RESULTSOUND;
\r
63 public string SOUND_AUDIENCE;
\r
64 public string SOUND_FULLCOMBO;
\r
65 public string SOUND_NOWLOADING;
\r
66 public string SOUND_STAGEFAILED;
\r
67 public string STAGEFILE;
\r
68 public string strハッシュofDTXファイル;
\r
69 public string strファイル名;
\r
70 public string strファイル名の絶対パス;
\r
71 public string strフォルダ名;
\r
72 public string TITLE;
\r
73 public double dbDTXVPlaySpeed;
\r
74 public bool bMovieをFullscreen再生する;
\r
75 public bool bUse556x710BGAAVI;
\r
76 public STDGBVALUE<List<int>> listAutoGhostLag;
\r
77 public STDGBVALUE<List<int>> listTargetGhsotLag;
\r
79 #if TEST_NOTEOFFMODE
\r
80 public STLANEVALUE<bool> b演奏で直前の音を消音する;
\r
81 // public bool bHH演奏で直前のHHを消音する;
\r
82 // public bool bGUITAR演奏で直前のGUITARを消音する;
\r
83 // public bool bBASS演奏で直前のBASSを消音する;
\r
97 this.STAGEFILE = "";
\r
98 this.BACKGROUND = "";
\r
99 this.BACKGROUND_GR = "";
\r
100 this.PATH_WAV = "";
\r
101 this.MIDIFILE = "";
\r
102 this.SOUND_STAGEFAILED = "";
\r
103 this.SOUND_FULLCOMBO = "";
\r
104 this.SOUND_NOWLOADING = "";
\r
105 this.SOUND_AUDIENCE = "";
\r
107 this.BLACKCOLORKEY = true;
\r
108 STDGBVALUE<int> stdgbvalue = new STDGBVALUE<int>();
\r
109 stdgbvalue.Drums = 0;
\r
110 stdgbvalue.Guitar = 0;
\r
111 stdgbvalue.Bass = 0;
\r
112 this.LEVEL = stdgbvalue;
\r
113 for (int i = 0; i < 7; i++)
\r
115 this.RESULTIMAGE[i] = "";
\r
116 this.RESULTMOVIE[i] = "";
\r
117 this.RESULTSOUND[i] = "";
\r
120 this.strハッシュofDTXファイル = "";
\r
121 this.bチップがある = new STチップがある();
\r
122 this.bチップがある.Drums = false;
\r
123 this.bチップがある.Guitar = false;
\r
124 this.bチップがある.Bass = false;
\r
125 this.bチップがある.HHOpen = false;
\r
126 this.bチップがある.Ride = false;
\r
127 this.bチップがある.LeftCymbal = false;
\r
128 this.bチップがある.OpenGuitar = false;
\r
129 this.bチップがある.OpenBass = false;
\r
130 this.bチップがある.BGA = false;
\r
131 this.bチップがある.Movie = false;
\r
132 this.bチップがある.LeftPedal = false;
\r
133 this.bチップがある.LeftBassDrum = false;
\r
134 this.bMovieをFullscreen再生する = false;
\r
135 this.strファイル名 = "";
\r
136 this.strフォルダ名 = "";
\r
137 this.strファイル名の絶対パス = "";
\r
138 this.n無限管理WAV = new int[36 * 36];
\r
139 this.n無限管理BPM = new int[36 * 36];
\r
140 this.n無限管理VOL = new int[36 * 36];
\r
141 this.n無限管理PAN = new int[36 * 36];
\r
142 this.n無限管理SIZE = new int[36 * 36];
\r
143 this.nRESULTIMAGE用優先順位 = new int[7];
\r
144 this.nRESULTMOVIE用優先順位 = new int[7];
\r
145 this.nRESULTSOUND用優先順位 = new int[7];
\r
146 this.listAutoGhostLag = new STDGBVALUE<List<int>>();
\r
147 this.listTargetGhsotLag = new STDGBVALUE<List<int>>();
\r
149 #region [ 2011.1.1 yyagi GDA->DTX変換テーブル リファクタ後 ]
\r
150 STGDAPARAM[] stgdaparamArray = new STGDAPARAM[] { // GDA->DTX conversion table
\r
151 new STGDAPARAM("TC", Ech定義.BPM),
\r
152 new STGDAPARAM("BL", Ech定義.BarLength),
\r
153 new STGDAPARAM("GS", Ech定義.flowspeed_gt_nouse),
\r
154 new STGDAPARAM("DS", Ech定義.flowspeed_dr_nouse),
\r
155 new STGDAPARAM("FI", Ech定義.FillIn),
\r
156 new STGDAPARAM("HH", Ech定義.HiHatClose),
\r
157 new STGDAPARAM("SD", Ech定義.Snare),
\r
158 new STGDAPARAM("BD", Ech定義.BassDrum),
\r
159 new STGDAPARAM("HT", Ech定義.HighTom),
\r
160 new STGDAPARAM("LT", Ech定義.LowTom),
\r
161 new STGDAPARAM("CY", Ech定義.Cymbal),
\r
162 new STGDAPARAM("G1", Ech定義.Guitar_xxB),
\r
163 new STGDAPARAM("G2", Ech定義.Guitar_xGx),
\r
164 new STGDAPARAM("G3", Ech定義.Guitar_xGB),
\r
165 new STGDAPARAM("G4", Ech定義.Guitar_Rxx),
\r
166 new STGDAPARAM("G5", Ech定義.Guitar_RxB),
\r
167 new STGDAPARAM("G6", Ech定義.Guitar_RGx),
\r
168 new STGDAPARAM("G7", Ech定義.Guitar_RGB),
\r
169 new STGDAPARAM("GW", Ech定義.Guitar_Wailing),
\r
170 new STGDAPARAM("01", Ech定義.SE01),
\r
171 new STGDAPARAM("02", Ech定義.SE02),
\r
172 new STGDAPARAM("03", Ech定義.SE03),
\r
173 new STGDAPARAM("04", Ech定義.SE04),
\r
174 new STGDAPARAM("05", Ech定義.SE05),
\r
175 new STGDAPARAM("06", Ech定義.SE06),
\r
176 new STGDAPARAM("07", Ech定義.SE07),
\r
177 new STGDAPARAM("08", Ech定義.SE08),
\r
178 new STGDAPARAM("09", Ech定義.SE09),
\r
179 new STGDAPARAM("0A", Ech定義.SE10),
\r
180 new STGDAPARAM("0B", Ech定義.SE11),
\r
181 new STGDAPARAM("0C", Ech定義.SE12),
\r
182 new STGDAPARAM("0D", Ech定義.SE13),
\r
183 new STGDAPARAM("0E", Ech定義.SE14),
\r
184 new STGDAPARAM("0F", Ech定義.SE15),
\r
185 new STGDAPARAM("10", Ech定義.SE16),
\r
186 new STGDAPARAM("11", Ech定義.SE17),
\r
187 new STGDAPARAM("12", Ech定義.SE18),
\r
188 new STGDAPARAM("13", Ech定義.SE19),
\r
189 new STGDAPARAM("14", Ech定義.SE20),
\r
190 new STGDAPARAM("15", Ech定義.SE21),
\r
191 new STGDAPARAM("16", Ech定義.SE22),
\r
192 new STGDAPARAM("17", Ech定義.SE23),
\r
193 new STGDAPARAM("18", Ech定義.SE24),
\r
194 new STGDAPARAM("19", Ech定義.SE25),
\r
195 new STGDAPARAM("1A", Ech定義.SE26),
\r
196 new STGDAPARAM("1B", Ech定義.SE27),
\r
197 new STGDAPARAM("1C", Ech定義.SE28),
\r
198 new STGDAPARAM("1D", Ech定義.SE29),
\r
199 new STGDAPARAM("1E", Ech定義.SE30),
\r
200 new STGDAPARAM("1F", Ech定義.SE31),
\r
201 new STGDAPARAM("20", Ech定義.SE32),
\r
202 new STGDAPARAM("B1", Ech定義.Bass_xxB),
\r
203 new STGDAPARAM("B2", Ech定義.Bass_xGx),
\r
204 new STGDAPARAM("B3", Ech定義.Bass_xGB),
\r
205 new STGDAPARAM("B4", Ech定義.Bass_Rxx),
\r
206 new STGDAPARAM("B5", Ech定義.Bass_RxB),
\r
207 new STGDAPARAM("B6", Ech定義.Bass_RGx),
\r
208 new STGDAPARAM("B7", Ech定義.Bass_RGB),
\r
209 new STGDAPARAM("BW", Ech定義.Bass_Wailing),
\r
210 new STGDAPARAM("G0", Ech定義.Guitar_Open),
\r
211 new STGDAPARAM("B0", Ech定義.Bass_Open)
\r
213 this.stGDAParam = stgdaparamArray;
\r
215 this.nBGMAdjust = 0;
\r
216 this.nPolyphonicSounds = CDTXMania.Instance.ConfigIni.nPoliphonicSounds;
\r
217 this.dbDTXVPlaySpeed = 1.0f;
\r
218 this.bUse556x710BGAAVI = false;
\r
220 #if TEST_NOTEOFFMODE
\r
221 this.bHH演奏で直前のHHを消音する = true;
\r
222 this.bGUITAR演奏で直前のGUITARを消音する = true;
\r
223 this.bBASS演奏で直前のBASSを消音する = true;
\r
227 private CDTX(string str全入力文字列)
\r
231 this.t入力_全入力文字列から(str全入力文字列);
\r
233 public CDTX(string strファイル名, bool bヘッダのみ)
\r
237 this.t入力(strファイル名, bヘッダのみ);
\r
239 private CDTX(string str全入力文字列, double db再生速度, int nBGMAdjust)
\r
243 this.t入力_全入力文字列から(str全入力文字列, db再生速度, nBGMAdjust);
\r
245 public CDTX(string strファイル名, bool bヘッダのみ, double db再生速度, int nBGMAdjust)
\r
249 this.t入力(strファイル名, bヘッダのみ, db再生速度, nBGMAdjust);
\r
256 public int nモニタを考慮した音量(E楽器パート part)
\r
258 CConfigIni configIni = CDTXMania.Instance.ConfigIni;
\r
262 if (configIni.b演奏音を強調する.Drums)
\r
264 return configIni.n自動再生音量;
\r
266 return configIni.n手動再生音量;
\r
268 case E楽器パート.GUITAR:
\r
269 if (configIni.b演奏音を強調する.Guitar)
\r
271 return configIni.n自動再生音量;
\r
273 return configIni.n手動再生音量;
\r
276 if (configIni.b演奏音を強調する.Bass)
\r
278 return configIni.n自動再生音量;
\r
280 return configIni.n手動再生音量;
\r
282 if ((!configIni.b演奏音を強調する.Drums && !configIni.b演奏音を強調する.Guitar) && !configIni.b演奏音を強調する.Bass)
\r
284 return configIni.n手動再生音量;
\r
286 return configIni.n自動再生音量;
\r
288 public void tAVIの読み込み()
\r
290 if (this.listAVI != null)
\r
292 foreach (CAVI cavi in this.listAVI.Values)
\r
294 cavi.OnDeviceCreated();
\r
299 foreach (CChip chip in this.listChip)
\r
301 chip.ApplyAVI(listAVI, listAVIPAN);
\r
305 #region [ BMP/BMPTEXの並列読み込み・デコード用メソッド ]
\r
306 delegate void BackgroundBMPLoadAll(Dictionary<int, CBMP> listB);
\r
307 static BackgroundBMPLoadAll backgroundBMPLoadAll = new BackgroundBMPLoadAll(BMPLoadAll);
\r
308 delegate void BackgroundBMPTEXLoadAll(Dictionary<int, CBMPTEX> listB);
\r
309 static BackgroundBMPTEXLoadAll backgroundBMPTEXLoadAll = new BackgroundBMPTEXLoadAll(BMPTEXLoadAll);
\r
310 private static void LoadTexture(CBMPbase cbmp) // バックグラウンドスレッドで動作する、ファイル読み込み部
\r
312 string filename = cbmp.GetFullPathname;
\r
313 if (!File.Exists(filename))
\r
315 Trace.TraceWarning("ファイルが存在しません。({0})", filename);
\r
316 cbmp.bitmap = null;
\r
321 cbmp.bitmap = new Bitmap(filename);
\r
323 catch (ArgumentException)
\r
325 Trace.TraceWarning("引数が不正です。ファイルが破損している可能性があります。({0})", filename);
\r
326 cbmp.bitmap = null;
\r
330 private static void BMPLoadAll(Dictionary<int, CBMP> listB) // バックグラウンドスレッドで、テクスチャファイルをひたすら読み込んではキューに追加する
\r
332 //Trace.TraceInformation( "Back: ThreadID(BMPLoad)=" + Thread.CurrentThread.ManagedThreadId + ", listCount=" + listB.Count );
\r
333 foreach (CBMPbase cbmp in listB.Values)
\r
338 queueCBMPbaseDone.Enqueue(cbmp);
\r
339 // Trace.TraceInformation( "Back: Enqueued(" + queueCBMPbaseDone.Count + "): " + cbmp.strファイル名 );
\r
341 if (queueCBMPbaseDone.Count > 8)
\r
347 private static void BMPTEXLoadAll(Dictionary<int, CBMPTEX> listB) // ダサい実装だが、Dictionary<>の中には手を出せず、妥協した
\r
349 //Trace.TraceInformation( "Back: ThreadID(BMPLoad)=" + Thread.CurrentThread.ManagedThreadId + ", listCount=" + listB.Count );
\r
350 foreach (CBMPbase cbmp in listB.Values)
\r
355 queueCBMPbaseDone.Enqueue(cbmp);
\r
356 // Trace.TraceInformation( "Back: Enqueued(" + queueCBMPbaseDone.Count + "): " + cbmp.strファイル名 );
\r
358 if (queueCBMPbaseDone.Count > 8)
\r
365 private static Queue<CBMPbase> queueCBMPbaseDone = new Queue<CBMPbase>();
\r
366 private static object lockQueue = new object();
\r
367 private static int nLoadDone;
\r
370 public void tBMP_BMPTEXの読み込み()
\r
372 #region [ CPUコア数の取得 ]
\r
373 CWin32.SYSTEM_INFO sysInfo = new CWin32.SYSTEM_INFO();
\r
374 CWin32.GetSystemInfo(ref sysInfo);
\r
375 int nCPUCores = (int)sysInfo.dwNumberOfProcessors;
\r
377 #region [ BMP読み込み ]
\r
378 if (this.listBMP != null)
\r
380 if (nCPUCores <= 1)
\r
382 #region [ シングルスレッドで逐次読み出し・デコード・テクスチャ定義 ]
\r
383 foreach (CBMP cbmp in this.listBMP.Values)
\r
385 cbmp.OnDeviceCreated();
\r
391 #region [ メインスレッド(テクスチャ定義)とバックグラウンドスレッド(読み出し・デコード)を並列動作させ高速化 ]
\r
392 //Trace.TraceInformation( "Main: ThreadID(Main)=" + Thread.CurrentThread.ManagedThreadId + ", listCount=" + this.listBMP.Count );
\r
394 backgroundBMPLoadAll.BeginInvoke(listBMP, null, null);
\r
396 // t.Priority = ThreadPriority.Lowest;
\r
397 // t.Start( listBMP );
\r
398 int c = listBMP.Count;
\r
399 while (nLoadDone < c)
\r
401 if (queueCBMPbaseDone.Count > 0)
\r
404 //Trace.TraceInformation( "Main: Lock Begin for dequeue1." );
\r
409 cbmp = (CBMP)queueCBMPbaseDone.Dequeue();
\r
410 // Trace.TraceInformation( "Main: Dequeued(" + queueCBMPbaseDone.Count + "): " + cbmp.strファイル名 );
\r
412 cbmp.OnDeviceCreated(cbmp.bitmap, cbmp.GetFullPathname);
\r
414 catch (InvalidCastException) // bmp読み込み失敗時は、キャストに失敗する
\r
421 //Trace.TraceInformation( "Main: OnDeviceCreated: " + cbmp.strファイル名 );
\r
425 //Trace.TraceInformation( "Main: Sleeped.");
\r
426 Thread.Sleep(5); // WaitOneのイベント待ちにすると、メインスレッド処理中に2個以上イベント完了したときにそれを正しく検出できなくなるので、
\r
427 } // ポーリングに逃げてしまいました。
\r
433 #region [ BMPTEX読み込み ]
\r
434 if (this.listBMPTEX != null)
\r
436 if (nCPUCores <= 1)
\r
438 #region [ シングルスレッドで逐次読み出し・デコード・テクスチャ定義 ]
\r
439 foreach (CBMPTEX cbmptex in this.listBMPTEX.Values)
\r
441 cbmptex.OnDeviceCreated();
\r
447 #region [ メインスレッド(テクスチャ定義)とバックグラウンドスレッド(読み出し・デコード)を並列動作させ高速化 ]
\r
448 //Trace.TraceInformation( "Main: ThreadID(Main)=" + Thread.CurrentThread.ManagedThreadId + ", listCount=" + this.listBMP.Count );
\r
450 backgroundBMPTEXLoadAll.BeginInvoke(listBMPTEX, null, null);
\r
451 int c = listBMPTEX.Count;
\r
452 while (nLoadDone < c)
\r
454 if (queueCBMPbaseDone.Count > 0)
\r
457 //Trace.TraceInformation( "Main: Lock Begin for dequeue1." );
\r
462 cbmptex = (CBMPTEX)queueCBMPbaseDone.Dequeue();
\r
463 // Trace.TraceInformation( "Main: Dequeued(" + queueCBMPbaseDone.Count + "): " + cbmp.strファイル名 );
\r
465 cbmptex.OnDeviceCreated(cbmptex.bitmap, cbmptex.GetFullPathname);
\r
467 catch (InvalidCastException)
\r
474 //Trace.TraceInformation( "Main: OnDeviceCreated: " + cbmp.strファイル名 );
\r
478 //Trace.TraceInformation( "Main: Sleeped.");
\r
479 Thread.Sleep(5); // WaitOneのイベント待ちにすると、メインスレッド処理中に2個以上イベント完了したときにそれを正しく検出できなくなるので、
\r
480 } // ポーリングに逃げてしまいました。
\r
488 foreach (CChip chip in this.listChip)
\r
490 chip.ApplyBMP_BMPTEX(listBGA, listBGAPAN, listBMP, listBMPTEX);
\r
494 public void tWave再生位置自動補正()
\r
496 foreach (CWAV cwav in this.listWAV.Values)
\r
498 this.tWave再生位置自動補正(cwav);
\r
501 public void tWave再生位置自動補正(CWAV wc)
\r
503 if (wc.rSound[0] != null && wc.rSound[0].n総演奏時間ms >= 5000)
\r
505 for (int i = 0; i < nPolyphonicSounds; i++)
\r
507 if ((wc.rSound[i] != null) && (wc.rSound[i].b再生中))
\r
509 long nCurrentTime = CSound管理.rc演奏用タイマ.nシステム時刻ms;
\r
510 if (nCurrentTime > wc.n再生開始時刻[i])
\r
512 long nAbsTimeFromStartPlaying = nCurrentTime - wc.n再生開始時刻[i];
\r
513 //Trace.TraceInformation( "再生位置自動補正: {0}, seek先={1}ms, 全音長={2}ms",
\r
514 // Path.GetFileName( wc.rSound[ 0 ].strファイル名 ),
\r
515 // nAbsTimeFromStartPlaying,
\r
516 // wc.rSound[ 0 ].n総演奏時間ms
\r
518 // wc.rSound[ i ].t再生位置を変更する( wc.rSound[ i ].t時刻から位置を返す( nAbsTimeFromStartPlaying ) );
\r
519 wc.rSound[i].t再生位置を変更する(nAbsTimeFromStartPlaying); // WASAPI/ASIO用
\r
520 //Debug.WriteLine( "再生位置を変更: " + Path.GetFileName( wc.strファイル名 ) + nAbsTimeFromStartPlaying + "ms");
\r
530 public void tWaveBGM再生位置表示()
\r
532 foreach (CWAV wc in this.listWAV.Values)
\r
534 if (wc.rSound[0] != null && wc.rSound[0].n総演奏時間ms >= 5000)
\r
536 for (int i = 0; i < nPolyphonicSounds; i++)
\r
538 if ((wc.rSound[i] != null) && (wc.rSound[i].b再生中))
\r
542 wc.rSound[i].t再生位置を取得する(out n位置byte, out db位置ms);
\r
543 Trace.TraceInformation("再生位置: {0}, seek先={1}ms / {2}byte, 全音長={3}ms",
\r
544 Path.GetFileName(wc.rSound[0].strファイル名),
\r
546 wc.rSound[0].n総演奏時間ms
\r
554 public void tWavの再生停止(int nWaveの内部番号)
\r
556 tWavの再生停止(nWaveの内部番号, false);
\r
558 public void tWavの再生停止(int nWaveの内部番号, bool bミキサーからも削除する)
\r
560 if (this.listWAV.ContainsKey(nWaveの内部番号))
\r
562 CWAV cwav = this.listWAV[nWaveの内部番号];
\r
563 for (int i = 0; i < nPolyphonicSounds; i++)
\r
565 if (cwav.rSound[i] != null && cwav.rSound[i].b再生中)
\r
569 cwav.rSound[i].tサウンドを停止してMixerからも削除する();
\r
573 cwav.rSound[i].t再生を停止する();
\r
579 public void tWAVの読み込み(CWAV cwav)
\r
581 // Trace.TraceInformation("WAV files={0}", this.listWAV.Count);
\r
583 // foreach (CWAV cwav in this.listWAV.Values)
\r
585 // string strCount = count.ToString() + " / " + this.listWAV.Count.ToString();
\r
586 // Debug.WriteLine(strCount);
\r
587 // CDTXMania.Instance.app.act文字コンソール.tPrint(0, 0, C文字コンソール.Eフォント種別.白, strCount);
\r
590 string str = string.IsNullOrEmpty(this.PATH_WAV) ? this.strフォルダ名 : this.PATH_WAV;
\r
591 str = str + cwav.strファイル名;
\r
592 bool bIsDirectSound = (CDTXMania.Instance.Sound管理.GetCurrentSoundDeviceType() == "DirectSound");
\r
597 // cwav.rSound[ 0 ] = CDTXMania.Instance.app.Sound管理.tサウンドを生成する( str );
\r
598 // cwav.rSound[ 0 ].n音量 = 100;
\r
599 // if ( CDTXMania.Instance.app.ConfigIni.bLog作成解放ログ出力 )
\r
601 // Trace.TraceInformation( "サウンドを作成しました。({3})({0})({1})({2}bytes)", cwav.strコメント文, str, cwav.rSound[ 0 ].nサウンドバッファサイズ, cwav.rSound[ 0 ].bストリーム再生する ? "Stream" : "OnMemory" );
\r
606 // cwav.rSound[ 0 ] = null;
\r
607 // Trace.TraceError( "サウンドの作成に失敗しました。({0})({1})", cwav.strコメント文, str );
\r
609 //if ( cwav.rSound[ 0 ] == null ) // #xxxxx 2012.5.3 yyagi rSound[1-3]もClone()するようにし、これらのストリーム再生がおかしくなる問題を修正
\r
611 // for ( int j = 1; j < nPolyphonicSounds; j++ )
\r
613 // cwav.rSound[ j ] = null;
\r
618 // for ( int j = 1; j < nPolyphonicSounds; j++ )
\r
620 // cwav.rSound[ j ] = (CSound) cwav.rSound[ 0 ].Clone(); // #24007 2011.9.5 yyagi add: to accelerate loading chip sounds
\r
621 // CDTXMania.Instance.app.Sound管理.tサウンドを登録する( cwav.rSound[ j ] );
\r
628 cwav.rSound[0] = CDTXMania.Instance.Sound管理.tサウンドを生成する(str);
\r
629 cwav.rSound[0].n音量 = 100;
\r
630 if (!CDTXMania.Instance.ConfigIni.bDynamicBassMixerManagement)
\r
632 cwav.rSound[0].tBASSサウンドをミキサーに追加する();
\r
634 if (CDTXMania.Instance.ConfigIni.bLog作成解放ログ出力)
\r
636 Trace.TraceInformation("サウンドを作成しました。({3})({0})({1})({2}bytes)", cwav.strコメント文, str, cwav.rSound[0].nサウンドバッファサイズ, cwav.rSound[0].bストリーム再生する ? "Stream" : "OnMemory");
\r
639 catch (Exception e)
\r
641 cwav.rSound[0] = null;
\r
642 Trace.TraceError("サウンドの作成に失敗しました。({0})({1})", cwav.strコメント文, str);
\r
643 Trace.TraceError("例外: " + e.Message);
\r
646 #region [ 同時発音数を、チャンネルによって変える ]
\r
647 int nPoly = nPolyphonicSounds;
\r
648 if (CDTXMania.Instance.Sound管理.GetCurrentSoundDeviceType() != "DirectSound") // DShowでの再生の場合はミキシング負荷が高くないため、
\r
649 { // チップのライフタイム管理を行わない
\r
650 if (cwav.bIsBassSound) nPoly = (nPolyphonicSounds >= 2) ? 2 : 1;
\r
651 else if (cwav.bIsGuitarSound) nPoly = (nPolyphonicSounds >= 2) ? 2 : 1;
\r
652 else if (cwav.bIsSESound) nPoly = 1;
\r
653 else if (cwav.bIsBGMSound) nPoly = 1;
\r
655 if (cwav.bIsBGMSound) nPoly = 1;
\r
659 //if ( bIsDirectSound ) // DShowでの再生の場合はCloneする
\r
661 // for ( int i = 1; i < nPoly; i++ )
\r
663 // cwav.rSound[ i ] = (CSound) cwav.rSound[ 0 ].Clone(); // #24007 2011.9.5 yyagi add: to accelerate loading chip sounds
\r
664 // // CDTXMania.Instance.app.Sound管理.tサウンドを登録する( cwav.rSound[ j ] );
\r
666 // for ( int i = nPoly; i < nPolyphonicSounds; i++ )
\r
668 // cwav.rSound[ i ] = null;
\r
671 //else // WASAPI/ASIO時は通常通り登録
\r
673 for (int i = 1; i < nPoly; i++)
\r
677 cwav.rSound[i] = CDTXMania.Instance.Sound管理.tサウンドを生成する(str);
\r
678 cwav.rSound[i].n音量 = 100;
\r
679 if (!CDTXMania.Instance.ConfigIni.bDynamicBassMixerManagement)
\r
681 cwav.rSound[i].tBASSサウンドをミキサーに追加する();
\r
683 if (CDTXMania.Instance.ConfigIni.bLog作成解放ログ出力)
\r
685 Trace.TraceInformation("サウンドを作成しました。({3})({0})({1})({2}bytes)", cwav.strコメント文, str, cwav.rSound[0].nサウンドバッファサイズ, cwav.rSound[0].bストリーム再生する ? "Stream" : "OnMemory");
\r
688 catch (Exception e)
\r
690 cwav.rSound[i] = null;
\r
691 Trace.TraceError("サウンドの作成に失敗しました。({0})({1})", cwav.strコメント文, str);
\r
692 Trace.TraceError("例外: " + e.Message);
\r
697 catch (Exception exception)
\r
699 Trace.TraceError("サウンドの生成に失敗しました。({0})({1})({2})", exception.Message, cwav.strコメント文, str);
\r
700 for (int j = 0; j < nPolyphonicSounds; j++)
\r
702 cwav.rSound[j] = null;
\r
708 public static string tZZ(int n)
\r
710 if (n < 0 || n >= 36 * 36)
\r
711 return "!!"; // オーバー/アンダーフロー。
\r
713 // n を36進数2桁の文字列にして返す。
\r
715 string str = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
\r
716 return new string(new char[] { str[n / 36], str[n % 36] });
\r
718 public void tギターとベースのランダム化(E楽器パート part, Eランダムモード eRandom)
\r
720 if (((part == E楽器パート.GUITAR) || (part == E楽器パート.BASS)) && (eRandom != Eランダムモード.OFF))
\r
722 int n小節番号 = -10000;
\r
724 // int GOTO_END = 0; // gotoの飛び先のダミーコードで使うダミー変数
\r
725 foreach (CChip chip in this.listChip)
\r
727 bool bOpenChip = (chip.bGuitar可視チップ && this.bチップがある.OpenGuitar) || ((chip.bBass可視チップ) && this.bチップがある.OpenBass);
\r
728 if ((chip.n発声位置 / 384) != n小節番号) // 小節が変化したら
\r
730 n小節番号 = chip.n発声位置 / 384;
\r
731 seed = CDTXMania.Instance.Random.Next(6);
\r
734 chip.RandomizeRGB(eRandom, seed, bOpenChip);
\r
735 // #23546 2010.10.28 yyagi fixed (bチップがある.Bass→bチップがある.OpenBass)
\r
737 // GOTO_END++; // goto用のダミーコード
\r
742 #region [ チップの再生と停止 ]
\r
743 public void tチップの再生(CChip rChip, long n再生開始システム時刻ms, int nLane)
\r
745 this.tチップの再生(rChip, n再生開始システム時刻ms, nLane, CDTXMania.Instance.ConfigIni.n自動再生音量, false, false);
\r
747 public void tチップの再生(CChip rChip, long n再生開始システム時刻ms, int nLane, int nVol)
\r
749 this.tチップの再生(rChip, n再生開始システム時刻ms, nLane, nVol, false, false);
\r
751 public void tチップの再生(CChip rChip, long n再生開始システム時刻ms, int nLane, int nVol, bool bMIDIMonitor)
\r
753 this.tチップの再生(rChip, n再生開始システム時刻ms, nLane, nVol, bMIDIMonitor, false);
\r
755 public void tチップの再生(CChip pChip, long n再生開始システム時刻ms, int nLane, int nVol, bool bMIDIMonitor, bool bBad)
\r
757 if (pChip.n整数値_内部番号 >= 0)
\r
759 if ((nLane < (int)Eレーン.LC) || ((int)Eレーン.BGM < nLane))
\r
761 throw new ArgumentOutOfRangeException();
\r
763 if (this.listWAV.ContainsKey(pChip.n整数値_内部番号))
\r
765 CWAV wc = this.listWAV[pChip.n整数値_内部番号];
\r
766 int index = wc.n現在再生中のサウンド番号 = (wc.n現在再生中のサウンド番号 + 1) % nPolyphonicSounds;
\r
767 if ((wc.rSound[0] != null) &&
\r
768 (wc.rSound[0].bストリーム再生する || wc.rSound[index] == null))
\r
770 index = wc.n現在再生中のサウンド番号 = 0;
\r
772 CSound sound = wc.rSound[index];
\r
777 sound.db周波数倍率 = ((float)(100 + (((CDTXMania.Instance.Random.Next(3) + 1) * 7) * (1 - (CDTXMania.Instance.Random.Next(2) * 2))))) / 100f;
\r
781 sound.db周波数倍率 = 1.0;
\r
783 sound.db再生速度 = ((double)CDTXMania.Instance.ConfigIni.n演奏速度) / 20.0;
\r
784 // 再生速度によって、WASAPI/ASIOで使う使用mixerが決まるため、付随情報の設定(音量/PAN)は、再生速度の設定後に行う
\r
785 sound.n音量 = (int)(((double)(nVol * wc.n音量)) / 100.0);
\r
786 sound.n位置 = wc.n位置;
\r
789 wc.n再生開始時刻[wc.n現在再生中のサウンド番号] = n再生開始システム時刻ms;
\r
790 this.tWave再生位置自動補正(wc);
\r
794 public void t各自動再生音チップの再生時刻を変更する(int nBGMAdjustの増減値)
\r
796 this.nBGMAdjust += nBGMAdjustの増減値;
\r
797 foreach (CChip chip in listChip)
\r
799 chip.AddPlayPositionMsForSE(nBGMAdjustの増減値);
\r
801 foreach (CWAV cwav in this.listWAV.Values)
\r
803 for (int j = 0; j < nPolyphonicSounds; j++)
\r
805 if ((cwav.rSound[j] != null) && cwav.rSound[j].b再生中)
\r
807 cwav.n再生開始時刻[j] += nBGMAdjustの増減値;
\r
812 public void t全チップの再生一時停止()
\r
814 foreach (CWAV cwav in this.listWAV.Values)
\r
816 for (int i = 0; i < nPolyphonicSounds; i++)
\r
818 if ((cwav.rSound[i] != null) && cwav.rSound[i].b再生中)
\r
820 cwav.n一時停止時刻[i] = CSound管理.rc演奏用タイマ.nシステム時刻ms;
\r
821 cwav.rSound[i].t再生を一時停止する();
\r
827 /// 全チップの再生を再開する。しかし一時停止と再開を繰り返すと、再生位置が徐々にずれる問題あり。
\r
828 /// 泥臭い回避方法は、CStage演奏画面共通.cs の tキー入力()を参照のこと。
\r
830 public void t全チップの再生再開()
\r
832 foreach (CWAV cwav in this.listWAV.Values)
\r
834 for (int i = 0; i < nPolyphonicSounds; i++)
\r
836 if ((cwav.rSound[i] != null) && cwav.rSound[i].b一時停止中)
\r
838 //long num1 = cwav.n一時停止時刻[ i ];
\r
839 //long num2 = cwav.n再生開始時刻[ i ];
\r
840 cwav.n再生開始時刻[i] += CSound管理.rc演奏用タイマ.nシステム時刻ms - cwav.n一時停止時刻[i];
\r
845 public void t全チップの再生停止()
\r
847 foreach (CWAV cwav in this.listWAV.Values)
\r
849 this.tWavの再生停止(cwav.n内部番号);
\r
852 public void t全チップの再生停止とミキサーからの削除()
\r
854 foreach (CWAV cwav in this.listWAV.Values)
\r
856 this.tWavの再生停止(cwav.n内部番号, true);
\r
862 /// サウンドミキサーにサウンドを登録・削除する時刻を事前に算出する
\r
864 public void PlanToAddMixerChannel()
\r
866 if (CDTXMania.Instance.Sound管理.GetCurrentSoundDeviceType() == "DirectSound") // DShowでの再生の場合はミキシング負荷が高くないため、
\r
867 { // チップのライフタイム管理を行わない
\r
871 List<CChip> listAddMixerChannel = new List<CChip>(128); ;
\r
872 List<CChip> listRemoveMixerChannel = new List<CChip>(128);
\r
873 List<CChip> listRemoveTiming = new List<CChip>(128);
\r
875 //foreach ( CChip pChip in listChip )
\r
876 for (int i = 0; i < listChip.Count; i++)
\r
878 CChip pChip = listChip[i];
\r
879 if (pChip.bWAVを使うチャンネルである)
\r
881 #region [ 発音1秒前のタイミングを記録 ]
\r
882 int n発音前余裕ms = 1000, n発音後余裕ms = 800; // Drums
\r
884 int ch = (int)(pChip.eチャンネル番号) >> 4;
\r
886 if (ch == 2 || ch == 0x0a)
\r
892 if (ch == 0x06 || ch == 0x07 || ch == 0x08 || ch == 0x09)
\r
899 #region [ BGMチップならば即ミキサーに追加・・・はしない (全て注釈化) ]
\r
900 //if ( pChip.nチャンネル番号 == 0x01 ) // BGMチップは即ミキサーに追加
\r
902 // if ( listWAV.ContainsKey( pChip.n整数値・内部番号 ) )
\r
904 // CDTX.CWAV wc = CDTXMania.Instance.app.DTX.listWAV[ pChip.n整数値・内部番号 ];
\r
905 // if ( wc.rSound[ 0 ] != null )
\r
907 // CDTXMania.Instance.app.Sound管理.AddMixer( wc.rSound[ 0 ] ); // BGMは多重再生しない仕様としているので、1個目だけミキサーに登録すればよい
\r
912 #region [ 発音1秒前のタイミングを算出 ]
\r
913 int nAddMixer時刻ms, nAddMixer位置 = 0;
\r
914 //Debug.WriteLine("==================================================================");
\r
915 //Debug.WriteLine( "Start: ch=" + pChip.nチャンネル番号.ToString("x2") + ", nWAV番号=" + pChip.n整数値 + ", time=" + pChip.n発声時刻ms + ", lasttime=" + listChip[ listChip.Count - 1 ].n発声時刻ms );
\r
916 t発声時刻msと発声位置を取得する(pChip.n発声時刻ms - n発音前余裕ms, out nAddMixer時刻ms, out nAddMixer位置);
\r
917 //Debug.WriteLine( "nAddMixer時刻ms=" + nAddMixer時刻ms + ",nAddMixer位置=" + nAddMixer位置 );
\r
919 CChip c_AddMixer = new CChip(nAddMixer位置, pChip.n整数値, pChip.n整数値_内部番号, Ech定義.MixerAdd, nAddMixer時刻ms, false);
\r
920 listAddMixerChannel.Add(c_AddMixer);
\r
921 //Debug.WriteLine("listAddMixerChannel:" );
\r
922 //DebugOut_CChipList( listAddMixerChannel );
\r
925 #region [ そのチップ音のfullduration(チップ音wavの最大再生時間)を取得 ]
\r
926 int fullduration = 0;
\r
927 if (listWAV.ContainsKey(pChip.n整数値_内部番号))
\r
929 CDTX.CWAV wc = CDTXMania.Instance.DTX.listWAV[pChip.n整数値_内部番号];
\r
930 double _db再生速度 = (CDTXMania.Instance.DTXVmode.Enabled) ? this.dbDTXVPlaySpeed : this.db再生速度;
\r
931 fullduration = (wc.rSound[0] == null) ? 0 : (int)(wc.rSound[0].n総演奏時間ms / _db再生速度); // #23664 durationに再生速度が加味されておらず、低速再生でBGMが途切れる問題を修正 (発声時刻msは、DTX読み込み時に再生速度加味済)
\r
933 //Debug.WriteLine("fullduration=" + fullduration );
\r
936 #region [ そのチップのduration (GtBsが次の音にかき消されることを加味した再生時間) を取得・・・のコードは未使用。mixing抑制の効果が薄いため。]
\r
939 // int ch = ( pChip.nチャンネル番号 >> 4 );
\r
940 // bool bGtBs = ( ch == 0x02 || ch == 0x0A );
\r
941 // if ( bGtBs ) // Guitar/Bassの場合
\r
947 // if ( ++p >= listChip.Count )
\r
951 // chNext = ( listChip[ p ].nチャンネル番号 >> 4 );
\r
952 // duration = listChip[ p ].n発声時刻ms - pChip.n発声時刻ms;
\r
953 // if ( ch == chNext )
\r
958 // while ( duration < fullduration );
\r
962 // duration = fullduration;
\r
966 //Debug.WriteLine( i + ": duration diff= " + (fullduration - duration ) );
\r
967 duration = fullduration;
\r
968 int n新RemoveMixer時刻ms, n新RemoveMixer位置;
\r
969 t発声時刻msと発声位置を取得する(pChip.n発声時刻ms + duration + n発音後余裕ms, out n新RemoveMixer時刻ms, out n新RemoveMixer位置);
\r
970 //Debug.WriteLine( "n新RemoveMixer時刻ms=" + n新RemoveMixer時刻ms + ",n新RemoveMixer位置=" + n新RemoveMixer位置 );
\r
971 if (n新RemoveMixer時刻ms < pChip.n発声時刻ms + duration) // 曲の最後でサウンドが切れるような場合は
\r
973 CChip c_AddMixer_noremove = c_AddMixer;
\r
974 c_AddMixer_noremove.SetSoundAfterPlayEnd(true);
\r
975 listAddMixerChannel[listAddMixerChannel.Count - 1] = c_AddMixer_noremove;
\r
976 //continue; // 発声位置の計算ができないので、Mixer削除をあきらめる・・・のではなく
\r
977 // #32248 2013.10.15 yyagi 演奏終了後も再生を続けるチップであるというフラグをpChip内に立てる
\r
981 //if ( n新RemoveMixer時刻ms < pChip.n発声時刻ms + duration ) // 曲の最後でサウンドが切れるような場合
\r
983 // n新RemoveMixer時刻ms = pChip.n発声時刻ms + duration;
\r
984 // // 「位置」は比例計算で求めてお茶を濁す...このやり方だと誤動作したため対応中止
\r
985 // n新RemoveMixer位置 = listChip[ listChip.Count - 1 ].n発声位置 * n新RemoveMixer時刻ms / listChip[ listChip.Count - 1 ].n発声時刻ms;
\r
989 #region [ 発音終了2秒後にmixerから削除するが、その前に再発音することになるのかを確認(再発音ならmixer削除タイミングを延期) ]
\r
990 int n整数値 = pChip.n整数値;
\r
991 int index = listRemoveTiming.FindIndex(
\r
992 delegate(CChip cchip) { return cchip.n整数値 == n整数値; }
\r
994 //Debug.WriteLine( "index=" + index );
\r
995 if (index >= 0) // 過去に同じチップで発音中のものが見つかった場合
\r
996 { // 過去の発音のmixer削除を確定させるか、延期するかの2択。
\r
997 int n旧RemoveMixer時刻ms = listRemoveTiming[index].n発声時刻ms;
\r
998 int n旧RemoveMixer位置 = listRemoveTiming[index].n発声位置;
\r
1000 //Debug.WriteLine( "n旧RemoveMixer時刻ms=" + n旧RemoveMixer時刻ms + ",n旧RemoveMixer位置=" + n旧RemoveMixer位置 );
\r
1001 if (pChip.n発声時刻ms - n発音前余裕ms <= n旧RemoveMixer時刻ms) // mixer削除前に、同じ音の再発音がある場合は、
\r
1002 { // mixer削除時刻を遅延させる(if-else後に行う)
\r
1003 //Debug.WriteLine( "remove TAIL of listAddMixerChannel. TAIL INDEX=" + listAddMixerChannel.Count );
\r
1004 //DebugOut_CChipList( listAddMixerChannel );
\r
1005 listAddMixerChannel.RemoveAt(listAddMixerChannel.Count - 1); // また、同じチップ音の「mixerへの再追加」は削除する
\r
1006 //Debug.WriteLine( "removed result:" );
\r
1007 //DebugOut_CChipList( listAddMixerChannel );
\r
1009 else // 逆に、時間軸上、mixer削除後に再発音するような流れの場合は
\r
1011 //Debug.WriteLine( "Publish the value(listRemoveTiming[index] to listRemoveMixerChannel." );
\r
1012 listRemoveMixerChannel.Add(listRemoveTiming[index]); // mixer削除を確定させる
\r
1013 //Debug.WriteLine( "listRemoveMixerChannel:" );
\r
1014 //DebugOut_CChipList( listRemoveMixerChannel );
\r
1015 //listRemoveTiming.RemoveAt( index );
\r
1017 CChip c = new CChip(n新RemoveMixer位置, listRemoveTiming[index].n整数値, listRemoveTiming[index].n整数値_内部番号, Ech定義.MixerRemove, n新RemoveMixer時刻ms, false);// mixer削除時刻を更新(遅延)する
\r
1018 listRemoveTiming[index] = c;
\r
1019 //listRemoveTiming[ index ].n発声時刻ms = n新RemoveMixer時刻ms; // mixer削除時刻を更新(遅延)する
\r
1020 //listRemoveTiming[ index ].n発声位置 = n新RemoveMixer位置;
\r
1021 //Debug.WriteLine( "listRemoveTiming: modified" );
\r
1022 //DebugOut_CChipList( listRemoveTiming );
\r
1024 else // 過去に同じチップを発音していないor
\r
1025 { // 発音していたが既にmixer削除確定していたなら
\r
1026 CChip c = new CChip(n新RemoveMixer位置, pChip.n整数値, pChip.n整数値_内部番号, Ech定義.MixerRemove, n新RemoveMixer時刻ms, false);// 新しくmixer削除候補として追加する
\r
1027 //Debug.WriteLine( "Add new chip to listRemoveMixerTiming: " );
\r
1028 //Debug.WriteLine( "ch=" + c.nチャンネル番号.ToString( "x2" ) + ", nWAV番号=" + c.n整数値 + ", time=" + c.n発声時刻ms + ", lasttime=" + listChip[ listChip.Count - 1 ].n発声時刻ms );
\r
1029 listRemoveTiming.Add(c);
\r
1030 //Debug.WriteLine( "listRemoveTiming:" );
\r
1031 //DebugOut_CChipList( listRemoveTiming );
\r
1037 //Debug.WriteLine("==================================================================");
\r
1038 //Debug.WriteLine( "Result:" );
\r
1039 //Debug.WriteLine( "listAddMixerChannel:" );
\r
1040 //DebugOut_CChipList( listAddMixerChannel );
\r
1041 //Debug.WriteLine( "listRemoveMixerChannel:" );
\r
1042 //DebugOut_CChipList( listRemoveMixerChannel );
\r
1043 //Debug.WriteLine( "listRemoveTiming:" );
\r
1044 //DebugOut_CChipList( listRemoveTiming );
\r
1045 //Debug.WriteLine( "==================================================================" );
\r
1047 listChip.AddRange(listAddMixerChannel);
\r
1048 listChip.AddRange(listRemoveMixerChannel);
\r
1049 listChip.AddRange(listRemoveTiming);
\r
1052 private void DebugOut_CChipList(List<CChip> c)
\r
1054 //Debug.WriteLine( "Count=" + c.Count );
\r
1055 for (int i = 0; i < c.Count; i++)
\r
1057 Debug.WriteLine(i + ": ch=" + c[i].eチャンネル番号.ToString("x2") + ", WAV番号=" + c[i].n整数値 + ", time=" + c[i].n発声時刻ms);
\r
1062 /// 発声時刻msから発声位置を逆算することはできないため、近似計算する。
\r
1063 /// 具体的には、希望発声位置前後の2つのチップの発声位置の中間を取る。
\r
1065 /// <param name="n希望発声時刻ms"></param>
\r
1066 /// <param name="n新発声時刻ms"></param>
\r
1067 /// <param name="n新発声位置"></param>
\r
1068 /// <returns></returns>
\r
1069 private bool t発声時刻msと発声位置を取得する(int n希望発声時刻ms, out int n新発声時刻ms, out int n新発声位置)
\r
1071 // 発声時刻msから発声位置を逆算することはできないため、近似計算する。
\r
1072 // 具体的には、希望発声位置前後の2つのチップの発声位置の中間を取る。
\r
1074 if (n希望発声時刻ms < 0)
\r
1078 //else if ( n希望発声時刻ms > listChip[ listChip.Count - 1 ].n発声時刻ms ) // BGMの最後の余韻を殺してしまうので、この条件は外す
\r
1080 // n希望発声時刻ms = listChip[ listChip.Count - 1 ].n発声時刻ms;
\r
1083 int index_min = -1, index_max = -1;
\r
1084 for (int i = 0; i < listChip.Count; i++) // 希望発声位置前後の「前」の方のチップを検索
\r
1086 if (listChip[i].n発声時刻ms >= n希望発声時刻ms)
\r
1092 if (index_min < 0) // 希望発声時刻に至らずに曲が終了してしまう場合
\r
1094 // listの最終項目の時刻をそのまま使用する
\r
1095 //・・・のではダメ。BGMが尻切れになる。
\r
1096 // そこで、listの最終項目の発声時刻msと発生位置から、希望発声時刻に相当する希望発声位置を比例計算して求める。
\r
1097 //n新発声時刻ms = n希望発声時刻ms;
\r
1098 //n新発声位置 = listChip[ listChip.Count - 1 ].n発声位置 * n希望発声時刻ms / listChip[ listChip.Count - 1 ].n発声時刻ms;
\r
1099 n新発声時刻ms = listChip[listChip.Count - 1].n発声時刻ms;
\r
1100 n新発声位置 = listChip[listChip.Count - 1].n発声位置;
\r
1103 index_max = index_min + 1;
\r
1104 if (index_max >= listChip.Count)
\r
1106 index_max = index_min;
\r
1108 n新発声時刻ms = (listChip[index_max].n発声時刻ms + listChip[index_min].n発声時刻ms) / 2;
\r
1109 n新発声位置 = (listChip[index_max].n発声位置 + listChip[index_min].n発声位置) / 2;
\r
1116 /// Swap infos between Guitar and Bass (notes, level, n可視チップ数, bチップがある)
\r
1118 public void SwapGuitarBassInfos() // #24063 2011.1.24 yyagi ギターとベースの譜面情報入替
\r
1120 foreach (CChip chip in listChip)
\r
1124 int t = this.LEVEL.Bass;
\r
1125 this.LEVEL.Bass = this.LEVEL.Guitar;
\r
1126 this.LEVEL.Guitar = t;
\r
1128 t = this.n可視チップ数.Bass;
\r
1129 this.n可視チップ数.Bass = this.n可視チップ数.Guitar;
\r
1130 this.n可視チップ数.Guitar = t;
\r
1132 bool ts = this.bチップがある.Bass;
\r
1133 this.bチップがある.Bass = this.bチップがある.Guitar;
\r
1134 this.bチップがある.Guitar = ts;
\r
1136 // SwapGuitarBassInfos_AutoFlags();
\r
1139 // SwapGuitarBassInfos_AutoFlags()は、CDTXからCConfigIniに移動。
\r
1143 public override void On活性化()
\r
1145 this.listWAV = new Dictionary<int, CWAV>();
\r
1146 this.listBMP = new Dictionary<int, CBMP>();
\r
1147 this.listBMPTEX = new Dictionary<int, CBMPTEX>();
\r
1148 this.listBPM = new Dictionary<int, CBPM>();
\r
1149 this.listBGAPAN = new Dictionary<int, CBGAPAN>();
\r
1150 this.listBGA = new Dictionary<int, CBGA>();
\r
1151 this.listAVIPAN = new Dictionary<int, CAVIPAN>();
\r
1152 this.listAVI = new Dictionary<int, CAVI>();
\r
1153 this.listChip = new List<CChip>();
\r
1156 public override void On非活性化()
\r
1158 if (this.listWAV != null)
\r
1160 foreach (CWAV cwav in this.listWAV.Values)
\r
1164 this.listWAV = null;
\r
1166 if (this.listBMP != null)
\r
1168 foreach (CBMP cbmp in this.listBMP.Values)
\r
1172 this.listBMP = null;
\r
1174 if (this.listBMPTEX != null)
\r
1176 foreach (CBMPTEX cbmptex in this.listBMPTEX.Values)
\r
1178 cbmptex.Dispose();
\r
1180 this.listBMPTEX = null;
\r
1182 if (this.listAVI != null)
\r
1184 foreach (CAVI cavi in this.listAVI.Values)
\r
1188 this.listAVI = null;
\r
1190 if (this.listBPM != null)
\r
1192 this.listBPM.Clear();
\r
1193 this.listBPM = null;
\r
1195 if (this.listBGAPAN != null)
\r
1197 this.listBGAPAN.Clear();
\r
1198 this.listBGAPAN = null;
\r
1200 if (this.listBGA != null)
\r
1202 this.listBGA.Clear();
\r
1203 this.listBGA = null;
\r
1205 if (this.listAVIPAN != null)
\r
1207 this.listAVIPAN.Clear();
\r
1208 this.listAVIPAN = null;
\r
1210 if (this.listChip != null)
\r
1212 this.listChip.Clear();
\r
1216 public override void OnManagedリソースの作成()
\r
1218 if (!base.b活性化してない)
\r
1220 this.tBMP_BMPTEXの読み込み();
\r
1222 base.OnManagedリソースの作成();
\r
1225 public override void OnManagedリソースの解放()
\r
1227 if (!base.b活性化してない)
\r
1229 if (this.listBMP != null)
\r
1231 foreach (CBMP cbmp in this.listBMP.Values)
\r
1236 if (this.listBMPTEX != null)
\r
1238 foreach (CBMPTEX cbmptex in this.listBMPTEX.Values)
\r
1240 cbmptex.Dispose();
\r
1243 if (this.listAVI != null)
\r
1245 foreach (CAVI cavi in this.listAVI.Values)
\r
1250 base.OnManagedリソースの解放();
\r
1257 #region [ private ]
\r
1258 //-----------------
\r
1260 /// <para>GDAチャンネル番号に対応するDTXチャンネル番号。</para>
\r
1262 [StructLayout(LayoutKind.Sequential)]
\r
1263 private struct STGDAPARAM
\r
1265 public string strGDAのチャンネル文字列;
\r
1266 public Ech定義 eDTXのチャンネル番号;
\r
1268 public STGDAPARAM(string strGDAのチャンネル文字列, Ech定義 eDTXのチャンネル番号) // 2011.1.1 yyagi 構造体のコンストラクタ追加(初期化簡易化のため)
\r
1270 this.strGDAのチャンネル文字列 = strGDAのチャンネル文字列;
\r
1271 this.eDTXのチャンネル番号 = eDTXのチャンネル番号;
\r
1275 private readonly STGDAPARAM[] stGDAParam;
\r
1276 private bool bヘッダのみ;
\r
1277 private Stack<bool> bstackIFからENDIFをスキップする;
\r
1279 private int n現在の行数;
\r
1280 private int n現在の乱数;
\r
1282 private int nPolyphonicSounds = 4; // #28228 2012.5.1 yyagi
\r
1284 private int n内部番号BPM1to;
\r
1285 private int n内部番号WAV1to;
\r
1286 private int[] n無限管理BPM;
\r
1287 private int[] n無限管理PAN;
\r
1288 private int[] n無限管理SIZE;
\r
1289 private int[] n無限管理VOL;
\r
1290 private int[] n無限管理WAV;
\r
1291 private int[] nRESULTIMAGE用優先順位;
\r
1292 private int[] nRESULTMOVIE用優先順位;
\r
1293 private int[] nRESULTSOUND用優先順位;
\r
1295 #region [#23880 2010.12.30 yyagi: コンマとスペースの両方を小数点として扱うTryParse]
\r
1297 /// 小数点としてコンマとピリオドの両方を受け付けるTryParse()
\r
1299 /// <param name="s">strings convert to double</param>
\r
1300 /// <param name="result">parsed double value</param>
\r
1301 /// <returns>s が正常に変換された場合は true。それ以外の場合は false。</returns>
\r
1302 /// <exception cref="ArgumentException">style が NumberStyles 値でないか、style に NumberStyles.AllowHexSpecifier 値が含まれている</exception>
\r
1303 private bool TryParse(string s, out double result)
\r
1304 { // #23880 2010.12.30 yyagi: alternative TryParse to permit both '.' and ',' for decimal point
\r
1305 // EU諸国での #BPM 123,45 のような記述に対応するため、
\r
1306 // 小数点の最終位置を検出して、それをlocaleにあった
\r
1307 // 文字に置き換えてからTryParse()する
\r
1310 const string DecimalSeparators = ".,"; // 小数点文字
\r
1311 const string GroupSeparators = ".,' "; // 桁区切り文字
\r
1312 const string NumberSymbols = "0123456789"; // 数値文字
\r
1314 int len = s.Length; // 文字列長
\r
1315 int decimalPosition = len; // 真の小数点の位置 最初は文字列終端位置に仮置きする
\r
1317 for (int i = 0; i < len; i++)
\r
1318 { // まず、真の小数点(一番最後に現れる小数点)の位置を求める
\r
1320 if (NumberSymbols.IndexOf(c) >= 0)
\r
1324 else if (DecimalSeparators.IndexOf(c) >= 0)
\r
1325 { // 小数点文字だったら、その都度位置を上書き記憶
\r
1326 decimalPosition = i;
\r
1328 else if (GroupSeparators.IndexOf(c) >= 0)
\r
1329 { // 桁区切り文字の場合もスキップ
\r
1333 { // 数値・小数点・区切り文字以外がきたらループ終了
\r
1338 StringBuilder decimalStr = new StringBuilder(16);
\r
1339 for (int i = 0; i < len; i++)
\r
1340 { // 次に、localeにあった数値文字列を生成する
\r
1342 if (NumberSymbols.IndexOf(c) >= 0)
\r
1344 decimalStr.Append(c); // そのままコピー
\r
1346 else if (DecimalSeparators.IndexOf(c) >= 0)
\r
1348 if (i == decimalPosition)
\r
1349 { // 最後に出現した小数点文字なら、localeに合った小数点を出力する
\r
1350 decimalStr.Append(CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator);
\r
1353 else if (GroupSeparators.IndexOf(c) >= 0)
\r
1355 continue; // 何もしない(スキップ)
\r
1362 return double.TryParse(decimalStr.ToString(), out result); // 最後に、自分のlocale向けの文字列に対してTryParse実行
\r
1365 //-----------------
\r
1368 internal void t全AVIの一時停止()
\r
1371 foreach (var avi in listAVI)
\r
1373 if (avi.Value.avi != null && avi.Value.avi.b再生中)
\r
1375 avi.Value.avi.Pause();
\r
1380 foreach (var avi in listAVIPAN)
\r
1382 //if ( avi.Value.avi != null && avi.Value.avi.b再生中 )
\r
1384 // avi.Value.avi.ToggleRun();
\r
1388 internal void t全AVIの再生再開()
\r
1391 foreach (var avi in listAVI)
\r
1393 if (avi.Value.avi != null && avi.Value.avi.b一時停止中)
\r
1395 avi.Value.avi.ToggleRun();
\r
1399 foreach (var avi in listAVIPAN)
\r
1401 //if ( avi.Value.avi != null && avi.Value.avi.b一時停止中 )
\r
1403 // avi.Value.avi.ToggleRun();
\r