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
16 internal class CDTX : CActivity
\r
20 public enum E種別 { DTX, GDA, G2D, BMS, BME, SMF }
\r
21 public enum Eレーンビットパターン
\r
36 public class CAVI : IDisposable
\r
39 private bool bDispose済み;
\r
41 public string strコメント文 = "";
\r
42 public string strファイル名 = "";
\r
44 public void OnDeviceCreated()
\r
46 #region [ strAVIファイル名の作成。]
\r
49 if( !string.IsNullOrEmpty( CDTXMania.DTX.PATH_WAV ) )
\r
50 strAVIファイル名 = CDTXMania.DTX.PATH_WAV + this.strファイル名;
\r
52 strAVIファイル名 = CDTXMania.DTX.strフォルダ名 + this.strファイル名;
\r
56 if( !File.Exists( strAVIファイル名 ) )
\r
58 Trace.TraceWarning( "ファイルが存在しません。({0})({1})", this.strコメント文, strAVIファイル名 );
\r
67 this.avi = new CAvi( strAVIファイル名 );
\r
68 Trace.TraceInformation( "動画を生成しました。({0})({1})({2}frames)", this.strコメント文, strAVIファイル名, this.avi.GetMaxFrameCount() );
\r
70 catch( Exception e )
\r
72 Trace.TraceError( e.Message );
\r
73 Trace.TraceError( "動画の生成に失敗しました。({0})({1})", this.strコメント文, strAVIファイル名 );
\r
77 public override string ToString()
\r
79 return string.Format( "CAVI{0}: File:{1}, Comment:{2}", CDTX.tZZ( this.n番号 ), this.strファイル名, this.strコメント文 );
\r
82 #region [ IDisposable 実装 ]
\r
84 public void Dispose()
\r
86 if( this.bDispose済み )
\r
89 if( this.avi != null )
\r
91 #region [ strAVIファイル名 の作成。 ]
\r
94 if( !string.IsNullOrEmpty( CDTXMania.DTX.PATH_WAV ) )
\r
95 strAVIファイル名 = CDTXMania.DTX.PATH_WAV + this.strファイル名;
\r
97 strAVIファイル名 = CDTXMania.DTX.strフォルダ名 + this.strファイル名;
\r
101 this.avi.Dispose();
\r
104 Trace.TraceInformation( "動画を解放しました。({0})({1})", this.strコメント文, strAVIファイル名 );
\r
107 this.bDispose済み = true;
\r
109 //-----------------
\r
112 public class CAVIPAN
\r
115 public int n移動時間ct;
\r
117 public Point pt動画側開始位置 = new Point( 0, 0 );
\r
118 public Point pt動画側終了位置 = new Point( 0, 0 );
\r
119 public Point pt表示側開始位置 = new Point( 0, 0 );
\r
120 public Point pt表示側終了位置 = new Point( 0, 0 );
\r
121 public Size sz開始サイズ = new Size( 0, 0 );
\r
122 public Size sz終了サイズ = new Size( 0, 0 );
\r
124 public override string ToString()
\r
126 return string.Format( "CAVIPAN{0}: AVI:{14}, 開始サイズ:{1}x{2}, 終了サイズ:{3}x{4}, 動画側開始位置:{5}x{6}, 動画側終了位置:{7}x{8}, 表示側開始位置:{9}x{10}, 表示側終了位置:{11}x{12}, 移動時間:{13}ct",
\r
127 CDTX.tZZ( this.n番号 ),
\r
128 this.sz開始サイズ.Width, this.sz開始サイズ.Height,
\r
129 this.sz終了サイズ.Width, this.sz終了サイズ.Height,
\r
130 this.pt動画側開始位置.X, this.pt動画側開始位置.Y,
\r
131 this.pt動画側終了位置.X, this.pt動画側終了位置.Y,
\r
132 this.pt表示側開始位置.X, this.pt表示側開始位置.Y,
\r
133 this.pt表示側終了位置.X, this.pt表示側終了位置.Y,
\r
135 CDTX.tZZ( this.nAVI番号 ) );
\r
142 public Point pt画像側右下座標 = new Point( 0, 0 );
\r
143 public Point pt画像側左上座標 = new Point( 0, 0 );
\r
144 public Point pt表示座標 = new Point( 0, 0 );
\r
146 public override string ToString()
\r
148 return string.Format( "CBGA{0}, BMP:{1}, 画像側左上座標:{2}x{3}, 画像側右下座標:{4}x{5}, 表示座標:{6}x{7}",
\r
149 CDTX.tZZ( this.n番号 ),
\r
150 CDTX.tZZ( this.nBMP番号 ),
\r
151 this.pt画像側左上座標.X, this.pt画像側左上座標.Y,
\r
152 this.pt画像側右下座標.X, this.pt画像側右下座標.Y,
\r
153 this.pt表示座標.X, this.pt表示座標.Y );
\r
156 public class CBGAPAN
\r
159 public int n移動時間ct;
\r
161 public Point pt画像側開始位置 = new Point( 0, 0 );
\r
162 public Point pt画像側終了位置 = new Point( 0, 0 );
\r
163 public Point pt表示側開始位置 = new Point( 0, 0 );
\r
164 public Point pt表示側終了位置 = new Point( 0, 0 );
\r
165 public Size sz開始サイズ = new Size( 0, 0 );
\r
166 public Size sz終了サイズ = new Size( 0, 0 );
\r
168 public override string ToString()
\r
170 return string.Format( "CBGAPAN{0}: BMP:{14}, 開始サイズ:{1}x{2}, 終了サイズ:{3}x{4}, 画像側開始位置:{5}x{6}, 画像側終了位置:{7}x{8}, 表示側開始位置:{9}x{10}, 表示側終了位置:{11}x{12}, 移動時間:{13}ct",
\r
171 CDTX.tZZ( this.nBMP番号 ),
\r
172 this.sz開始サイズ.Width, this.sz開始サイズ.Height,
\r
173 this.sz終了サイズ.Width, this.sz終了サイズ.Height,
\r
174 this.pt画像側開始位置.X, this.pt画像側開始位置.Y,
\r
175 this.pt画像側終了位置.X, this.pt画像側終了位置.Y,
\r
176 this.pt表示側開始位置.X, this.pt表示側開始位置.Y,
\r
177 this.pt表示側終了位置.X, this.pt表示側終了位置.Y,
\r
179 CDTX.tZZ( this.nBMP番号 ) );
\r
182 public class CBMP : CBMPbase, IDisposable
\r
186 b黒を透過する = true; // BMPでは、黒を透過色とする
\r
188 public override void PutLog( string strテクスチャファイル名 )
\r
190 Trace.TraceInformation( "テクスチャを生成しました。({0})({1})({2}x{3})", this.strコメント文, strテクスチャファイル名, this.n幅, this.n高さ );
\r
192 public override string ToString()
\r
194 return string.Format( "CBMP{0}: File:{1}, Comment:{2}", CDTX.tZZ( this.n番号 ), this.strファイル名, this.strコメント文 );
\r
198 public class CBMPTEX : CBMPbase, IDisposable
\r
202 b黒を透過する = false; // BMPTEXでは、透過色はαで表現する
\r
204 public override void PutLog( string strテクスチャファイル名 )
\r
206 Trace.TraceInformation( "テクスチャを生成しました。({0})({1})(Gr:{2}x{3})(Tx:{4}x{5})", this.strコメント文, strテクスチャファイル名, this.tx画像.sz画像サイズ.Width, this.tx画像.sz画像サイズ.Height, this.tx画像.szテクスチャサイズ.Width, this.tx画像.szテクスチャサイズ.Height );
\r
208 public override string ToString()
\r
210 return string.Format( "CBMPTEX{0}: File:{1}, Comment:{2}", CDTX.tZZ( this.n番号 ), this.strファイル名, this.strコメント文 );
\r
213 public class CBMPbase : IDisposable
\r
217 public string strコメント文 = "";
\r
218 public string strファイル名 = "";
\r
219 public CTexture tx画像;
\r
224 return this.tx画像.sz画像サイズ.Height;
\r
231 return this.tx画像.sz画像サイズ.Width;
\r
234 public bool b黒を透過する;
\r
235 public Bitmap bitmap;
\r
237 public string GetFullPathname
\r
241 if ( !string.IsNullOrEmpty( CDTXMania.DTX.PATH_WAV ) )
\r
242 return CDTXMania.DTX.PATH_WAV + this.strファイル名;
\r
244 return CDTXMania.DTX.strフォルダ名 + this.strファイル名;
\r
248 public void OnDeviceCreated()
\r
250 #region [ strテクスチャファイル名 を作成。]
\r
251 string strテクスチャファイル名 = this.GetFullPathname;
\r
254 if ( !File.Exists( strテクスチャファイル名 ) )
\r
256 Trace.TraceWarning( "ファイルが存在しません。({0})({1})", this.strコメント文, strテクスチャファイル名 );
\r
262 byte[] txData = File.ReadAllBytes( strテクスチャファイル名 );
\r
263 this.tx画像 = CDTXMania.tテクスチャの生成( txData, b黒を透過する );
\r
265 if ( this.tx画像 != null )
\r
268 if ( CDTXMania.ConfigIni.bLog作成解放ログ出力 )
\r
269 PutLog( strテクスチャファイル名 );
\r
276 Trace.TraceError( "テクスチャの生成に失敗しました。({0})({1})", this.strコメント文, strテクスチャファイル名 );
\r
281 /// BGA画像のデコードをTexture()に渡す前に行う、OnDeviceCreate()
\r
283 /// <param name="bitmap">テクスチャ画像</param>
\r
284 /// <param name="strテクスチャファイル名">ファイル名</param>
\r
285 public void OnDeviceCreated( Bitmap bitmap, string strテクスチャファイル名 )
\r
287 if ( bitmap != null && b黒を透過する )
\r
289 bitmap.MakeTransparent( Color.Black ); // 黒を透過色にする
\r
291 this.tx画像 = CDTXMania.tテクスチャの生成( bitmap, b黒を透過する );
\r
293 if ( this.tx画像 != null )
\r
296 if ( CDTXMania.ConfigIni.bLog作成解放ログ出力 )
\r
297 PutLog( strテクスチャファイル名 );
\r
303 Trace.TraceError( "テクスチャの生成に失敗しました。({0})({1})", this.strコメント文, strテクスチャファイル名 );
\r
306 if ( bitmap != null )
\r
312 public virtual void PutLog( string strテクスチャファイル名 )
\r
316 #region [ IDisposable 実装 ]
\r
317 //-----------------
\r
318 public void Dispose()
\r
320 if ( this.bDisposed済み )
\r
323 if ( this.tx画像 != null )
\r
325 #region [ strテクスチャファイル名 を作成。]
\r
326 //-----------------
\r
327 string strテクスチャファイル名 = this.GetFullPathname;
\r
328 //if( !string.IsNullOrEmpty( CDTXMania.DTX.PATH_WAV ) )
\r
329 // strテクスチャファイル名 = CDTXMania.DTX.PATH_WAV + this.strファイル名;
\r
331 // strテクスチャファイル名 = CDTXMania.DTX.strフォルダ名 + this.strファイル名;
\r
332 //-----------------
\r
335 CDTXMania.tテクスチャの解放( ref this.tx画像 );
\r
337 if ( CDTXMania.ConfigIni.bLog作成解放ログ出力 )
\r
338 Trace.TraceInformation( "テクスチャを解放しました。({0})({1})", this.strコメント文, strテクスチャファイル名 );
\r
342 this.bDisposed済み = true;
\r
345 #region [ private ]
\r
346 //-----------------
\r
347 private bool bDisposed済み;
\r
348 //-----------------
\r
353 public double dbBPM値;
\r
355 public int n表記上の番号;
\r
357 public override string ToString()
\r
359 StringBuilder builder = new StringBuilder( 0x80 );
\r
360 if( this.n内部番号 != this.n表記上の番号 )
\r
362 builder.Append( string.Format( "CBPM{0}(内部{1})", CDTX.tZZ( this.n表記上の番号 ), this.n内部番号 ) );
\r
366 builder.Append( string.Format( "CBPM{0}", CDTX.tZZ( this.n表記上の番号 ) ) );
\r
368 builder.Append( string.Format( ", BPM:{0}", this.dbBPM値 ) );
\r
369 return builder.ToString();
\r
372 public class CChip : IComparable<CDTX.CChip>, ICloneable
\r
375 public bool b可視 = true;
\r
376 public double dbチップサイズ倍率 = 1.0;
\r
377 public double db実数値;
\r
378 public EAVI種別 eAVI種別;
\r
379 public EBGA種別 eBGA種別;
\r
380 public E楽器パート e楽器パート = E楽器パート.UNKNOWN;
\r
381 public int nチャンネル番号;
\r
382 public STDGBVALUE<int> nバーからの距離dot;
\r
384 public int n整数値・内部番号;
\r
386 public int n透明度 = 0xff;
\r
388 public int n発声時刻ms;
\r
389 public int nLag; // 2011.2.1 yyagi
\r
390 public CDTX.CAVI rAVI;
\r
391 public CDTX.CAVIPAN rAVIPan;
\r
392 public CDTX.CBGA rBGA;
\r
393 public CDTX.CBGAPAN rBGAPan;
\r
394 public CDTX.CBMP rBMP;
\r
395 public CDTX.CBMPTEX rBMPTEX;
\r
396 public bool bBPMチップである
\r
400 if (this.nチャンネル番号 == 3 || this.nチャンネル番号 == 8) {
\r
407 public bool bWAVを使うチャンネルである
\r
411 switch( this.nチャンネル番号 )
\r
502 public bool b自動再生音チャンネルである
\r
506 int num = this.nチャンネル番号;
\r
507 if( ( ( ( num != 1 ) && ( ( 0x61 > num ) || ( num > 0x69 ) ) ) && ( ( 0x70 > num ) || ( num > 0x79 ) ) ) && ( ( 0x80 > num ) || ( num > 0x89 ) ) )
\r
509 return ( ( 0x90 <= num ) && ( num <= 0x92 ) );
\r
514 public bool bIsAutoPlayed; // 2011.6.10 yyagi
\r
515 public bool b演奏終了後も再生が続くチップである; // #32248 2013.10.14 yyagi
\r
519 this.nバーからの距離dot = new STDGBVALUE<int>() {
\r
529 this.n整数値・内部番号 = 0;
\r
534 this.bIsAutoPlayed = false;
\r
535 this.b演奏終了後も再生が続くチップである = false;
\r
536 this.dbチップサイズ倍率 = 1.0;
\r
539 this.e楽器パート = E楽器パート.UNKNOWN;
\r
541 this.nバーからの距離dot.Drums = 0;
\r
542 this.nバーからの距離dot.Guitar = 0;
\r
543 this.nバーからの距離dot.Bass = 0;
\r
546 public override string ToString()
\r
548 string[] chToStr =
\r
550 "??", "バックコーラス", "小節長変更", "BPM変更", "BMPレイヤ1", "??", "??", "BMPレイヤ2",
\r
551 "BPM変更(拡張)", "??", "??", "??", "??", "??", "??", "??",
\r
552 "??", "HHClose", "Snare", "Kick", "HiTom", "LowTom", "Cymbal", "FloorTom",
\r
553 "HHOpen", "RideCymbal", "LeftCymbal", "", "", "", "", "ドラム歓声切替",
\r
554 "ギターOPEN", "ギター - - B", "ギター - G -", "ギター - G B", "ギター R - -", "ギター R - B", "ギター R G -", "ギター R G B",
\r
555 "ギターWailing", "??", "??", "??", "??", "??", "??", "ギターWailing音切替",
\r
556 "??", "HHClose(不可視)", "Snare(不可視)", "Kick(不可視)", "HiTom(不可視)", "LowTom(不可視)", "Cymbal(不可視)", "FloorTom(不可視)",
\r
557 "HHOpen(不可視)", "RideCymbal(不可視)", "LeftCymbal(不可視)", "??", "??", "??", "??", "??",
\r
558 "??", "??", "??", "??", "??", "??", "??", "??",
\r
559 "??", "??", "??", "??", "??", "??", "??", "??",
\r
560 "小節線", "拍線", "MIDIコーラス", "フィルイン", "AVI", "BMPレイヤ3", "BMPレイヤ4", "BMPレイヤ5",
\r
561 "BMPレイヤ6", "BMPレイヤ7", "??", "??", "??", "??", "??", "??",
\r
562 "BMPレイヤ8", "SE01", "SE02", "SE03", "SE04", "SE05", "SE06", "SE07",
\r
563 "SE08", "SE09", "??", "??", "??", "??", "??", "??",
\r
564 "SE10", "SE11", "SE12", "SE13", "SE14", "SE15", "SE16", "SE17",
\r
565 "SE18", "SE19", "??", "??", "??", "??", "??", "??",
\r
566 "SE20", "SE21", "SE22", "SE23", "SE24", "SE25", "SE26", "SE27",
\r
567 "SE28", "SE29", "??", "??", "??", "??", "??", "??",
\r
568 "SE30", "SE31", "SE32", "??", "??", "??", "??", "??",
\r
569 "??", "??", "??", "??", "??", "??", "??", "??",
\r
570 "ベースOPEN", "ベース - - B", "ベース - G -", "ベース - G B", "ベース R - -", "ベース R - B", "ベース R G -", "ベース R G B",
\r
571 "ベースWailing", "??", "??", "??", "??", "??", "??", "ベースWailing音切替",
\r
572 "??", "HHClose(空うち)", "Snare(空うち)", "Kick(空うち)", "HiTom(空うち)", "LowTom(空うち)", "Cymbal(空うち)", "FloorTom(空うち)",
\r
573 "HHOpen(空うち)", "RideCymbal(空うち)", "ギター(空打ち)", "ベース(空打ち)", "LeftCymbal(空うち)", "??", "??", "??",
\r
574 "??", "??", "??", "??", "BGAスコープ画像切替1", "??", "??", "BGAスコープ画像切替2",
\r
575 "??", "??", "??", "??", "??", "??", "??", "??",
\r
576 "??", "??", "??", "??", "??", "BGAスコープ画像切替3", "BGAスコープ画像切替4", "BGAスコープ画像切替5",
\r
577 "BGAスコープ画像切替6", "BGAスコープ画像切替7", "??", "??", "??", "??", "??", "??",
\r
580 return string.Format( "CChip: 位置:{0:D4}.{1:D3}, 時刻{2:D6}, Ch:{3:X2}({4}), Pn:{5}({11})(内部{6}), Pd:{7}, Sz:{8}, UseWav:{9}, Auto:{10}",
\r
581 this.n発声位置 / 384, this.n発声位置 % 384,
\r
583 this.nチャンネル番号, chToStr[ this.nチャンネル番号 ],
\r
584 this.n整数値, this.n整数値・内部番号,
\r
587 this.bWAVを使うチャンネルである,
\r
588 this.b自動再生音チャンネルである,
\r
589 CDTX.tZZ( this.n整数値 ) );
\r
591 public int GetDuration()
\r
595 if ( this.bWAVを使うチャンネルである ) // WAV
\r
597 CDTX.CWAV wc = CDTXMania.DTX.listWAV[ this.n整数値・内部番号 ];
\r
598 nDuration = ( wc.rSound[ 0 ] == null ) ? 0 : wc.rSound[ 0 ].n総演奏時間ms;
\r
600 else if ( this.nチャンネル番号 == 0x54 ) // AVI
\r
602 if ( this.rAVI != null && this.rAVI.avi != null )
\r
604 int dwRate = (int) this.rAVI.avi.dwレート;
\r
605 int dwScale = (int) this.rAVI.avi.dwスケール;
\r
606 nDuration = (int) ( 1000.0f * dwScale / dwRate * this.rAVI.avi.GetMaxFrameCount() );
\r
607 //Trace.TraceInformation( "CAVI: nDuration=" + nDuration + ", dwScale=" + dwScale + ", dwRate=" + dwRate + ", frames=" + this.rAVI.avi.GetMaxFrameCount() );
\r
611 return (int) ( nDuration / CDTXMania.DTX.db再生速度 );
\r
614 #region [ IComparable 実装 ]
\r
615 //-----------------
\r
616 public int CompareTo( CDTX.CChip other )
\r
618 byte[] n優先度 = new byte[] {
\r
619 5, 5, 3, 3, 5, 5, 5, 5, 3, 5, 5, 5, 5, 5, 5, 5,
\r
620 5, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 5, 5, 5, 5, 5,
\r
621 7, 7, 7, 7, 7, 7, 7, 7, 5, 5, 5, 5, 5, 5, 5, 5,
\r
622 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
\r
623 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
\r
624 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
\r
625 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
\r
626 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
\r
627 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
\r
628 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
\r
629 7, 7, 7, 7, 7, 7, 7, 7, 5, 5, 5, 5, 5, 5, 5, 5,
\r
630 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
\r
631 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
\r
632 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
\r
633 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
\r
634 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
\r
640 if( this.n発声位置 < other.n発声位置 )
\r
643 if( this.n発声位置 > other.n発声位置 )
\r
649 if( n優先度[ this.nチャンネル番号 ] < n優先度[ other.nチャンネル番号 ] )
\r
652 if( n優先度[ this.nチャンネル番号 ] > n優先度[ other.nチャンネル番号 ] )
\r
656 // 位置も優先度も同じなら同じと返す。
\r
660 //-----------------
\r
663 /// shallow copyです。
\r
665 /// <returns></returns>
\r
666 public object Clone()
\r
668 return MemberwiseClone();
\r
671 public class CWAV : IDisposable
\r
673 public bool bBGMとして使う;
\r
674 public List<int> listこのWAVを使用するチャンネル番号の集合 = new List<int>( 16 );
\r
675 public int nチップサイズ = 100;
\r
677 public long[] n一時停止時刻 = new long[ CDTXMania.ConfigIni.nPoliphonicSounds ]; // 4
\r
678 public int n音量 = 100;
\r
679 public int n現在再生中のサウンド番号;
\r
680 public long[] n再生開始時刻 = new long[ CDTXMania.ConfigIni.nPoliphonicSounds ]; // 4
\r
682 public int n表記上の番号;
\r
683 public CSound[] rSound = new CSound[ CDTXMania.ConfigIni.nPoliphonicSounds ]; // 4
\r
684 public string strコメント文 = "";
\r
685 public string strファイル名 = "";
\r
686 public bool bBGMとして使わない
\r
690 return !this.bBGMとして使う;
\r
694 this.bBGMとして使う = !value;
\r
697 public bool bIsBassSound = false;
\r
698 public bool bIsGuitarSound = false;
\r
699 public bool bIsDrumsSound = false;
\r
700 public bool bIsSESound = false;
\r
701 public bool bIsBGMSound = false;
\r
703 public override string ToString()
\r
705 var sb = new StringBuilder( 128 );
\r
707 if( this.n表記上の番号 == this.n内部番号 )
\r
709 sb.Append( string.Format( "CWAV{0}: ", CDTX.tZZ( this.n表記上の番号 ) ) );
\r
713 sb.Append( string.Format( "CWAV{0}(内部{1}): ", CDTX.tZZ( this.n表記上の番号 ), this.n内部番号 ) );
\r
715 sb.Append( string.Format( "音量:{0}, 位置:{1}, サイズ:{2}, BGM:{3}, File:{4}, Comment:{5}", this.n音量, this.n位置, this.nチップサイズ, this.bBGMとして使う ? 'Y' : 'N', this.strファイル名, this.strコメント文 ) );
\r
717 return sb.ToString();
\r
720 #region [ Dispose-Finalize パターン実装 ]
\r
721 //-----------------
\r
722 public void Dispose()
\r
724 this.Dispose( true );
\r
725 GC.SuppressFinalize( this );
\r
727 public void Dispose( bool bManagedリソースの解放も行う )
\r
729 if( this.bDisposed済み )
\r
732 if( bManagedリソースの解放も行う )
\r
734 for ( int i = 0; i < CDTXMania.ConfigIni.nPoliphonicSounds; i++ ) // 4
\r
736 if( this.rSound[ i ] != null )
\r
737 CDTXMania.Sound管理.tサウンドを破棄する( this.rSound[ i ] );
\r
738 this.rSound[ i ] = null;
\r
740 if( ( i == 0 ) && CDTXMania.ConfigIni.bLog作成解放ログ出力 )
\r
741 Trace.TraceInformation( "サウンドを解放しました。({0})({1})", this.strコメント文, this.strファイル名 );
\r
745 this.bDisposed済み = true;
\r
749 this.Dispose( false );
\r
751 //-----------------
\r
754 #region [ private ]
\r
755 //-----------------
\r
756 private bool bDisposed済み;
\r
757 //-----------------
\r
764 public struct STLANEINT
\r
781 return this.HH + this.SD + this.BD + this.HT + this.LT + this.CY + this.FT + this.HHO + this.RD + this.LC;
\r
787 public int this[ int index ]
\r
824 return this.Guitar;
\r
829 throw new IndexOutOfRangeException();
\r
835 throw new ArgumentOutOfRangeException();
\r
880 this.Guitar = value;
\r
887 throw new IndexOutOfRangeException();
\r
891 public struct STRESULT
\r
901 public string this[ int index ]
\r
928 throw new IndexOutOfRangeException();
\r
962 throw new IndexOutOfRangeException();
\r
966 public struct STチップがある
\r
969 public bool Guitar;
\r
972 public bool HHOpen;
\r
974 public bool LeftCymbal;
\r
975 public bool OpenGuitar;
\r
976 public bool OpenBass;
\r
978 public bool this[ int index ]
\r
988 return this.Guitar;
\r
994 return this.HHOpen;
\r
1000 return this.LeftCymbal;
\r
1003 return this.OpenGuitar;
\r
1006 return this.OpenBass;
\r
1008 throw new IndexOutOfRangeException();
\r
1015 this.Drums = value;
\r
1019 this.Guitar = value;
\r
1023 this.Bass = value;
\r
1027 this.HHOpen = value;
\r
1031 this.Ride = value;
\r
1035 this.LeftCymbal = value;
\r
1039 this.OpenGuitar = value;
\r
1043 this.OpenBass = value;
\r
1046 throw new IndexOutOfRangeException();
\r
1054 public int nBGMAdjust
\r
1059 public string ARTIST;
\r
1060 public string BACKGROUND;
\r
1061 public string BACKGROUND_GR;
\r
1062 public double BASEBPM;
\r
1063 public bool BLACKCOLORKEY;
\r
1064 public double BPM;
\r
1065 public STチップがある bチップがある;
\r
1066 public string COMMENT;
\r
1067 public double db再生速度;
\r
1069 public string GENRE;
\r
1070 public bool HIDDENLEVEL;
\r
1071 public STDGBVALUE<int> LEVEL;
\r
1072 public Dictionary<int, CAVI> listAVI;
\r
1073 public Dictionary<int, CAVIPAN> listAVIPAN;
\r
1074 public Dictionary<int, CBGA> listBGA;
\r
1075 public Dictionary<int, CBGAPAN> listBGAPAN;
\r
1076 public Dictionary<int, CBMP> listBMP;
\r
1077 public Dictionary<int, CBMPTEX> listBMPTEX;
\r
1078 public Dictionary<int, CBPM> listBPM;
\r
1079 public List<CChip> listChip;
\r
1080 public Dictionary<int, CWAV> listWAV;
\r
1081 public string MIDIFILE;
\r
1082 public bool MIDINOTE;
\r
1083 public int MIDIレベル;
\r
1084 public STLANEINT n可視チップ数;
\r
1085 public const int n最大音数 = 4;
\r
1086 public const int n小節の解像度 = 384;
\r
1087 public string PANEL;
\r
1088 public string PATH_WAV;
\r
1089 public string PREIMAGE;
\r
1090 public string PREMOVIE;
\r
1091 public string PREVIEW;
\r
1092 public STRESULT RESULTIMAGE;
\r
1093 public STRESULT RESULTMOVIE;
\r
1094 public STRESULT RESULTSOUND;
\r
1095 public string SOUND_AUDIENCE;
\r
1096 public string SOUND_FULLCOMBO;
\r
1097 public string SOUND_NOWLOADING;
\r
1098 public string SOUND_STAGEFAILED;
\r
1099 public string STAGEFILE;
\r
1100 public string strハッシュofDTXファイル;
\r
1101 public string strファイル名;
\r
1102 public string strファイル名の絶対パス;
\r
1103 public string strフォルダ名;
\r
1104 public string TITLE;
\r
1105 public double dbDTXVPlaySpeed;
\r
1107 #if TEST_NOTEOFFMODE
\r
1108 public STLANEVALUE<bool> b演奏で直前の音を消音する;
\r
1109 // public bool bHH演奏で直前のHHを消音する;
\r
1110 // public bool bGUITAR演奏で直前のGUITARを消音する;
\r
1111 // public bool bBASS演奏で直前のBASSを消音する;
\r
1119 this.COMMENT = "";
\r
1122 this.PREVIEW = "";
\r
1123 this.PREIMAGE = "";
\r
1124 this.PREMOVIE = "";
\r
1125 this.STAGEFILE = "";
\r
1126 this.BACKGROUND = "";
\r
1127 this.BACKGROUND_GR = "";
\r
1128 this.PATH_WAV = "";
\r
1129 this.MIDIFILE = "";
\r
1130 this.SOUND_STAGEFAILED = "";
\r
1131 this.SOUND_FULLCOMBO = "";
\r
1132 this.SOUND_NOWLOADING = "";
\r
1133 this.SOUND_AUDIENCE = "";
\r
1135 this.BLACKCOLORKEY = true;
\r
1136 STDGBVALUE<int> stdgbvalue = new STDGBVALUE<int>();
\r
1137 stdgbvalue.Drums = 0;
\r
1138 stdgbvalue.Guitar = 0;
\r
1139 stdgbvalue.Bass = 0;
\r
1140 this.LEVEL = stdgbvalue;
\r
1141 for (int i = 0; i < 7; i++) {
\r
1142 this.RESULTIMAGE[i] = "";
\r
1143 this.RESULTMOVIE[i] = "";
\r
1144 this.RESULTSOUND[i] = "";
\r
1146 this.db再生速度 = 1.0;
\r
1147 this.strハッシュofDTXファイル = "";
\r
1148 this.bチップがある = new STチップがある();
\r
1149 this.bチップがある.Drums = false;
\r
1150 this.bチップがある.Guitar = false;
\r
1151 this.bチップがある.Bass = false;
\r
1152 this.bチップがある.HHOpen = false;
\r
1153 this.bチップがある.Ride = false;
\r
1154 this.bチップがある.LeftCymbal = false;
\r
1155 this.bチップがある.OpenGuitar = false;
\r
1156 this.bチップがある.OpenBass = false;
\r
1157 this.strファイル名 = "";
\r
1158 this.strフォルダ名 = "";
\r
1159 this.strファイル名の絶対パス = "";
\r
1160 this.n無限管理WAV = new int[ 36 * 36 ];
\r
1161 this.n無限管理BPM = new int[ 36 * 36 ];
\r
1162 this.n無限管理VOL = new int[ 36 * 36 ];
\r
1163 this.n無限管理PAN = new int[ 36 * 36 ];
\r
1164 this.n無限管理SIZE = new int[ 36 * 36 ];
\r
1165 this.nRESULTIMAGE用優先順位 = new int[ 7 ];
\r
1166 this.nRESULTMOVIE用優先順位 = new int[ 7 ];
\r
1167 this.nRESULTSOUND用優先順位 = new int[ 7 ];
\r
1169 #region [ 2011.1.1 yyagi GDA->DTX変換テーブル リファクタ後 ]
\r
1170 STGDAPARAM[] stgdaparamArray = new STGDAPARAM[] { // GDA->DTX conversion table
\r
1171 new STGDAPARAM("TC", 0x03), new STGDAPARAM("BL", 0x02), new STGDAPARAM("GS", 0x29),
\r
1172 new STGDAPARAM("DS", 0x30), new STGDAPARAM("FI", 0x53), new STGDAPARAM("HH", 0x11),
\r
1173 new STGDAPARAM("SD", 0x12), new STGDAPARAM("BD", 0x13), new STGDAPARAM("HT", 0x14),
\r
1174 new STGDAPARAM("LT", 0x15), new STGDAPARAM("CY", 0x16), new STGDAPARAM("G1", 0x21),
\r
1175 new STGDAPARAM("G2", 0x22), new STGDAPARAM("G3", 0x23), new STGDAPARAM("G4", 0x24),
\r
1176 new STGDAPARAM("G5", 0x25), new STGDAPARAM("G6", 0x26), new STGDAPARAM("G7", 0x27),
\r
1177 new STGDAPARAM("GW", 0x28), new STGDAPARAM("01", 0x61), new STGDAPARAM("02", 0x62),
\r
1178 new STGDAPARAM("03", 0x63), new STGDAPARAM("04", 0x64), new STGDAPARAM("05", 0x65),
\r
1179 new STGDAPARAM("06", 0x66), new STGDAPARAM("07", 0x67), new STGDAPARAM("08", 0x68),
\r
1180 new STGDAPARAM("09", 0x69), new STGDAPARAM("0A", 0x70), new STGDAPARAM("0B", 0x71),
\r
1181 new STGDAPARAM("0C", 0x72), new STGDAPARAM("0D", 0x73), new STGDAPARAM("0E", 0x74),
\r
1182 new STGDAPARAM("0F", 0x75), new STGDAPARAM("10", 0x76), new STGDAPARAM("11", 0x77),
\r
1183 new STGDAPARAM("12", 0x78), new STGDAPARAM("13", 0x79), new STGDAPARAM("14", 0x80),
\r
1184 new STGDAPARAM("15", 0x81), new STGDAPARAM("16", 0x82), new STGDAPARAM("17", 0x83),
\r
1185 new STGDAPARAM("18", 0x84), new STGDAPARAM("19", 0x85), new STGDAPARAM("1A", 0x86),
\r
1186 new STGDAPARAM("1B", 0x87), new STGDAPARAM("1C", 0x88), new STGDAPARAM("1D", 0x89),
\r
1187 new STGDAPARAM("1E", 0x90), new STGDAPARAM("1F", 0x91), new STGDAPARAM("20", 0x92),
\r
1188 new STGDAPARAM("B1", 0xA1), new STGDAPARAM("B2", 0xA2), new STGDAPARAM("B3", 0xA3),
\r
1189 new STGDAPARAM("B4", 0xA4), new STGDAPARAM("B5", 0xA5), new STGDAPARAM("B6", 0xA6),
\r
1190 new STGDAPARAM("B7", 0xA7), new STGDAPARAM("BW", 0xA8), new STGDAPARAM("G0", 0x20),
\r
1191 new STGDAPARAM("B0", 0xA0)
\r
1193 this.stGDAParam = stgdaparamArray;
\r
1195 this.nBGMAdjust = 0;
\r
1196 this.nPolyphonicSounds = CDTXMania.ConfigIni.nPoliphonicSounds;
\r
1197 this.dbDTXVPlaySpeed = 1.0f;
\r
1199 #if TEST_NOTEOFFMODE
\r
1200 this.bHH演奏で直前のHHを消音する = true;
\r
1201 this.bGUITAR演奏で直前のGUITARを消音する = true;
\r
1202 this.bBASS演奏で直前のBASSを消音する = true;
\r
1206 public CDTX( string str全入力文字列 )
\r
1210 this.t入力・全入力文字列から( str全入力文字列 );
\r
1212 public CDTX( string strファイル名, bool bヘッダのみ )
\r
1216 this.t入力( strファイル名, bヘッダのみ );
\r
1218 public CDTX( string str全入力文字列, double db再生速度, int nBGMAdjust )
\r
1222 this.t入力・全入力文字列から( str全入力文字列, db再生速度, nBGMAdjust );
\r
1224 public CDTX( string strファイル名, bool bヘッダのみ, double db再生速度, int nBGMAdjust )
\r
1228 this.t入力( strファイル名, bヘッダのみ, db再生速度, nBGMAdjust );
\r
1234 public int nモニタを考慮した音量( E楽器パート part )
\r
1236 CConfigIni configIni = CDTXMania.ConfigIni;
\r
1239 case E楽器パート.DRUMS:
\r
1240 if( configIni.b演奏音を強調する.Drums )
\r
1242 return configIni.n自動再生音量;
\r
1244 return configIni.n手動再生音量;
\r
1246 case E楽器パート.GUITAR:
\r
1247 if( configIni.b演奏音を強調する.Guitar )
\r
1249 return configIni.n自動再生音量;
\r
1251 return configIni.n手動再生音量;
\r
1254 if( configIni.b演奏音を強調する.Bass )
\r
1256 return configIni.n自動再生音量;
\r
1258 return configIni.n手動再生音量;
\r
1260 if( ( !configIni.b演奏音を強調する.Drums && !configIni.b演奏音を強調する.Guitar ) && !configIni.b演奏音を強調する.Bass )
\r
1262 return configIni.n手動再生音量;
\r
1264 return configIni.n自動再生音量;
\r
1266 public void tAVIの読み込み()
\r
1268 if( this.listAVI != null )
\r
1270 foreach( CAVI cavi in this.listAVI.Values )
\r
1272 cavi.OnDeviceCreated();
\r
1275 if( !this.bヘッダのみ )
\r
1277 foreach( CChip chip in this.listChip )
\r
1279 if( chip.nチャンネル番号 == 0x54 )
\r
1281 chip.eAVI種別 = EAVI種別.Unknown;
\r
1283 chip.rAVIPan = null;
\r
1284 if( this.listAVIPAN.ContainsKey( chip.n整数値 ) )
\r
1286 CAVIPAN cavipan = this.listAVIPAN[ chip.n整数値 ];
\r
1287 if( this.listAVI.ContainsKey( cavipan.nAVI番号 ) && ( this.listAVI[ cavipan.nAVI番号 ].avi != null ) )
\r
1289 chip.eAVI種別 = EAVI種別.AVIPAN;
\r
1290 chip.rAVI = this.listAVI[ cavipan.nAVI番号 ];
\r
1291 chip.rAVIPan = cavipan;
\r
1295 if( this.listAVI.ContainsKey( chip.n整数値 ) && ( this.listAVI[ chip.n整数値 ].avi != null ) )
\r
1297 chip.eAVI種別 = EAVI種別.AVI;
\r
1298 chip.rAVI = this.listAVI[ chip.n整数値 ];
\r
1304 #region [ BMP/BMPTEXの並列読み込み・デコード用メソッド ]
\r
1305 delegate void BackgroundBMPLoadAll( Dictionary<int, CBMP> listB );
\r
1306 static BackgroundBMPLoadAll backgroundBMPLoadAll = new BackgroundBMPLoadAll( BMPLoadAll );
\r
1307 delegate void BackgroundBMPTEXLoadAll( Dictionary<int, CBMPTEX> listB );
\r
1308 static BackgroundBMPTEXLoadAll backgroundBMPTEXLoadAll = new BackgroundBMPTEXLoadAll( BMPTEXLoadAll );
\r
1309 private static void LoadTexture( CBMPbase cbmp ) // バックグラウンドスレッドで動作する、ファイル読み込み部
\r
1311 string filename = cbmp.GetFullPathname;
\r
1312 if ( !File.Exists( filename ) )
\r
1314 Trace.TraceWarning( "ファイルが存在しません。({0})", filename );
\r
1315 cbmp.bitmap = null;
\r
1318 cbmp.bitmap = new Bitmap( filename );
\r
1320 private static void BMPLoadAll( Dictionary<int, CBMP> listB ) // バックグラウンドスレッドで、テクスチャファイルをひたすら読み込んではキューに追加する
\r
1322 //Trace.TraceInformation( "Back: ThreadID(BMPLoad)=" + Thread.CurrentThread.ManagedThreadId + ", listCount=" + listB.Count );
\r
1323 foreach ( CBMPbase cbmp in listB.Values )
\r
1325 LoadTexture( cbmp );
\r
1326 lock ( lockQueue )
\r
1328 queueCBMPbaseDone.Enqueue( cbmp );
\r
1329 // Trace.TraceInformation( "Back: Enqueued(" + queueCBMPbaseDone.Count + "): " + cbmp.strファイル名 );
\r
1331 if ( queueCBMPbaseDone.Count > 8 )
\r
1333 Thread.Sleep( 10 );
\r
1337 private static void BMPTEXLoadAll( Dictionary<int, CBMPTEX> listB ) // ダサい実装だが、Dictionary<>の中には手を出せず、妥協した
\r
1339 //Trace.TraceInformation( "Back: ThreadID(BMPLoad)=" + Thread.CurrentThread.ManagedThreadId + ", listCount=" + listB.Count );
\r
1340 foreach ( CBMPbase cbmp in listB.Values )
\r
1342 LoadTexture( cbmp );
\r
1343 lock ( lockQueue )
\r
1345 queueCBMPbaseDone.Enqueue( cbmp );
\r
1346 // Trace.TraceInformation( "Back: Enqueued(" + queueCBMPbaseDone.Count + "): " + cbmp.strファイル名 );
\r
1348 if ( queueCBMPbaseDone.Count > 8 )
\r
1350 Thread.Sleep( 10 );
\r
1355 private static Queue<CBMPbase> queueCBMPbaseDone = new Queue<CBMPbase>();
\r
1356 private static object lockQueue = new object();
\r
1357 private static int nLoadDone;
\r
1360 public void tBMP_BMPTEXの読み込み()
\r
1362 #region [ CPUコア数の取得 ]
\r
1363 CWin32.SYSTEM_INFO sysInfo = new CWin32.SYSTEM_INFO();
\r
1364 CWin32.GetSystemInfo( ref sysInfo );
\r
1365 int nCPUCores = (int) sysInfo.dwNumberOfProcessors;
\r
1367 #region [ BMP読み込み ]
\r
1368 if ( this.listBMP != null )
\r
1370 if ( nCPUCores <= 1 )
\r
1372 #region [ シングルスレッドで逐次読み出し・デコード・テクスチャ定義 ]
\r
1373 foreach ( CBMP cbmp in this.listBMP.Values )
\r
1375 cbmp.OnDeviceCreated();
\r
1381 #region [ メインスレッド(テクスチャ定義)とバックグラウンドスレッド(読み出し・デコード)を並列動作させ高速化 ]
\r
1382 //Trace.TraceInformation( "Main: ThreadID(Main)=" + Thread.CurrentThread.ManagedThreadId + ", listCount=" + this.listBMP.Count );
\r
1384 backgroundBMPLoadAll.BeginInvoke( listBMP, null, null );
\r
1386 // t.Priority = ThreadPriority.Lowest;
\r
1387 // t.Start( listBMP );
\r
1388 int c = listBMP.Count;
\r
1389 while ( nLoadDone < c )
\r
1391 if ( queueCBMPbaseDone.Count > 0 )
\r
1394 //Trace.TraceInformation( "Main: Lock Begin for dequeue1." );
\r
1395 lock ( lockQueue )
\r
1397 cbmp = (CBMP) queueCBMPbaseDone.Dequeue();
\r
1398 // Trace.TraceInformation( "Main: Dequeued(" + queueCBMPbaseDone.Count + "): " + cbmp.strファイル名 );
\r
1400 cbmp.OnDeviceCreated( cbmp.bitmap, cbmp.GetFullPathname );
\r
1402 //Trace.TraceInformation( "Main: OnDeviceCreated: " + cbmp.strファイル名 );
\r
1406 //Trace.TraceInformation( "Main: Sleeped.");
\r
1407 Thread.Sleep( 5 ); // WaitOneのイベント待ちにすると、メインスレッド処理中に2個以上イベント完了したときにそれを正しく検出できなくなるので、
\r
1408 } // ポーリングに逃げてしまいました。
\r
1414 #region [ BMPTEX読み込み ]
\r
1415 if ( this.listBMPTEX != null )
\r
1417 if ( nCPUCores <= 1 )
\r
1419 #region [ シングルスレッドで逐次読み出し・デコード・テクスチャ定義 ]
\r
1420 foreach ( CBMPTEX cbmptex in this.listBMPTEX.Values )
\r
1422 cbmptex.OnDeviceCreated();
\r
1428 #region [ メインスレッド(テクスチャ定義)とバックグラウンドスレッド(読み出し・デコード)を並列動作させ高速化 ]
\r
1429 //Trace.TraceInformation( "Main: ThreadID(Main)=" + Thread.CurrentThread.ManagedThreadId + ", listCount=" + this.listBMP.Count );
\r
1431 backgroundBMPTEXLoadAll.BeginInvoke( listBMPTEX, null, null );
\r
1432 int c = listBMPTEX.Count;
\r
1433 while ( nLoadDone < c )
\r
1435 if ( queueCBMPbaseDone.Count > 0 )
\r
1438 //Trace.TraceInformation( "Main: Lock Begin for dequeue1." );
\r
1439 lock ( lockQueue )
\r
1441 cbmptex = (CBMPTEX) queueCBMPbaseDone.Dequeue();
\r
1442 // Trace.TraceInformation( "Main: Dequeued(" + queueCBMPbaseDone.Count + "): " + cbmp.strファイル名 );
\r
1444 cbmptex.OnDeviceCreated( cbmptex.bitmap, cbmptex.GetFullPathname );
\r
1446 //Trace.TraceInformation( "Main: OnDeviceCreated: " + cbmp.strファイル名 );
\r
1450 //Trace.TraceInformation( "Main: Sleeped.");
\r
1451 Thread.Sleep( 5 ); // WaitOneのイベント待ちにすると、メインスレッド処理中に2個以上イベント完了したときにそれを正しく検出できなくなるので、
\r
1452 } // ポーリングに逃げてしまいました。
\r
1458 if ( !this.bヘッダのみ )
\r
1460 foreach ( CChip chip in this.listChip )
\r
1462 #region [ BGAPAN/BGA/BMPTEX/BMP ]
\r
1463 if ( ( ( ( chip.nチャンネル番号 == 4 ) || ( chip.nチャンネル番号 == 7 ) ) || ( ( chip.nチャンネル番号 >= 0x55 ) && ( chip.nチャンネル番号 <= 0x59 ) ) ) || ( chip.nチャンネル番号 == 0x60 ) )
\r
1465 chip.eBGA種別 = EBGA種別.Unknown;
\r
1467 chip.rBMPTEX = null;
\r
1469 chip.rBGAPan = null;
\r
1470 #region [ BGAPAN ]
\r
1471 if ( this.listBGAPAN.ContainsKey( chip.n整数値 ) )
\r
1473 CBGAPAN cbgapan = this.listBGAPAN[ chip.n整数値 ];
\r
1474 if ( this.listBMPTEX.ContainsKey( cbgapan.nBMP番号 ) && this.listBMPTEX[ cbgapan.nBMP番号 ].bUse )
\r
1476 chip.eBGA種別 = EBGA種別.BGAPAN;
\r
1477 chip.rBMPTEX = this.listBMPTEX[ cbgapan.nBMP番号 ];
\r
1478 chip.rBGAPan = cbgapan;
\r
1481 if ( this.listBMP.ContainsKey( cbgapan.nBMP番号 ) && this.listBMP[ cbgapan.nBMP番号 ].bUse )
\r
1483 chip.eBGA種別 = EBGA種別.BGAPAN;
\r
1484 chip.rBMP = this.listBMP[ cbgapan.nBMP番号 ];
\r
1485 chip.rBGAPan = cbgapan;
\r
1491 if ( this.listBGA.ContainsKey( chip.n整数値 ) )
\r
1493 CBGA cbga = this.listBGA[ chip.n整数値 ];
\r
1494 if ( this.listBMPTEX.ContainsKey( cbga.nBMP番号 ) && this.listBMPTEX[ cbga.nBMP番号 ].bUse )
\r
1496 chip.eBGA種別 = EBGA種別.BGA;
\r
1497 chip.rBMPTEX = this.listBMPTEX[ cbga.nBMP番号 ];
\r
1501 if ( this.listBMP.ContainsKey( cbga.nBMP番号 ) && this.listBMP[ cbga.nBMP番号 ].bUse )
\r
1503 chip.eBGA種別 = EBGA種別.BGA;
\r
1504 chip.rBMP = this.listBMP[ cbga.nBMP番号 ];
\r
1510 #region [ BMPTEX ]
\r
1511 if ( this.listBMPTEX.ContainsKey( chip.n整数値 ) && this.listBMPTEX[ chip.n整数値 ].bUse )
\r
1513 chip.eBGA種別 = EBGA種別.BMPTEX;
\r
1514 chip.rBMPTEX = this.listBMPTEX[ chip.n整数値 ];
\r
1519 if ( this.listBMP.ContainsKey( chip.n整数値 ) && this.listBMP[ chip.n整数値 ].bUse )
\r
1521 chip.eBGA種別 = EBGA種別.BMP;
\r
1522 chip.rBMP = this.listBMP[ chip.n整数値 ];
\r
1528 #region [ BGA入れ替え ]
\r
1529 if ( ( ( ( chip.nチャンネル番号 == 0xc4 ) || ( chip.nチャンネル番号 == 0xc7 ) ) || ( ( chip.nチャンネル番号 >= 0xd5 ) && ( chip.nチャンネル番号 <= 0xd9 ) ) ) || ( chip.nチャンネル番号 == 0xe0 ) )
\r
1531 chip.eBGA種別 = EBGA種別.Unknown;
\r
1533 chip.rBMPTEX = null;
\r
1535 chip.rBGAPan = null;
\r
1536 if ( this.listBMPTEX.ContainsKey( chip.n整数値 ) && this.listBMPTEX[ chip.n整数値 ].bUse )
\r
1538 chip.eBGA種別 = EBGA種別.BMPTEX;
\r
1539 chip.rBMPTEX = this.listBMPTEX[ chip.n整数値 ];
\r
1541 else if ( this.listBMP.ContainsKey( chip.n整数値 ) && this.listBMP[ chip.n整数値 ].bUse )
\r
1543 chip.eBGA種別 = EBGA種別.BMP;
\r
1544 chip.rBMP = this.listBMP[ chip.n整数値 ];
\r
1551 public void tWave再生位置自動補正()
\r
1553 foreach( CWAV cwav in this.listWAV.Values )
\r
1555 this.tWave再生位置自動補正( cwav );
\r
1558 public void tWave再生位置自動補正( CWAV wc )
\r
1560 if ( wc.rSound[ 0 ] != null && wc.rSound[ 0 ].n総演奏時間ms >= 5000 )
\r
1562 for ( int i = 0; i < nPolyphonicSounds; i++ )
\r
1564 if ( ( wc.rSound[ i ] != null ) && ( wc.rSound[ i ].b再生中 ) )
\r
1566 long nCurrentTime = CSound管理.rc演奏用タイマ.nシステム時刻ms;
\r
1567 if ( nCurrentTime > wc.n再生開始時刻[ i ] )
\r
1569 long nAbsTimeFromStartPlaying = nCurrentTime - wc.n再生開始時刻[ i ];
\r
1570 //Trace.TraceInformation( "再生位置自動補正: {0}, seek先={1}ms, 全音長={2}ms",
\r
1571 // Path.GetFileName( wc.rSound[ 0 ].strファイル名 ),
\r
1572 // nAbsTimeFromStartPlaying,
\r
1573 // wc.rSound[ 0 ].n総演奏時間ms
\r
1575 // wc.rSound[ i ].t再生位置を変更する( wc.rSound[ i ].t時刻から位置を返す( nAbsTimeFromStartPlaying ) );
\r
1576 wc.rSound[ i ].t再生位置を変更する( nAbsTimeFromStartPlaying ); // WASAPI/ASIO用
\r
1582 public void tWavの再生停止( int nWaveの内部番号 )
\r
1584 if( this.listWAV.ContainsKey( nWaveの内部番号 ) )
\r
1586 CWAV cwav = this.listWAV[ nWaveの内部番号 ];
\r
1587 for ( int i = 0; i < nPolyphonicSounds; i++ )
\r
1589 if( cwav.rSound[ i ] != null && cwav.rSound[ i ].b再生中 )
\r
1591 cwav.rSound[ i ].t再生を停止する();
\r
1596 public void tWAVの読み込み( CWAV cwav )
\r
1598 // Trace.TraceInformation("WAV files={0}", this.listWAV.Count);
\r
1600 // foreach (CWAV cwav in this.listWAV.Values)
\r
1602 // string strCount = count.ToString() + " / " + this.listWAV.Count.ToString();
\r
1603 // Debug.WriteLine(strCount);
\r
1604 // CDTXMania.act文字コンソール.tPrint(0, 0, C文字コンソール.Eフォント種別.白, strCount);
\r
1607 string str = string.IsNullOrEmpty(this.PATH_WAV) ? this.strフォルダ名 : this.PATH_WAV;
\r
1608 str = str + cwav.strファイル名;
\r
1609 bool bIsDirectSound = ( CDTXMania.Sound管理.GetCurrentSoundDeviceType() == "DirectSound" );
\r
1614 // cwav.rSound[ 0 ] = CDTXMania.Sound管理.tサウンドを生成する( str );
\r
1615 // cwav.rSound[ 0 ].n音量 = 100;
\r
1616 // if ( CDTXMania.ConfigIni.bLog作成解放ログ出力 )
\r
1618 // Trace.TraceInformation( "サウンドを作成しました。({3})({0})({1})({2}bytes)", cwav.strコメント文, str, cwav.rSound[ 0 ].nサウンドバッファサイズ, cwav.rSound[ 0 ].bストリーム再生する ? "Stream" : "OnMemory" );
\r
1623 // cwav.rSound[ 0 ] = null;
\r
1624 // Trace.TraceError( "サウンドの作成に失敗しました。({0})({1})", cwav.strコメント文, str );
\r
1626 //if ( cwav.rSound[ 0 ] == null ) // #xxxxx 2012.5.3 yyagi rSound[1-3]もClone()するようにし、これらのストリーム再生がおかしくなる問題を修正
\r
1628 // for ( int j = 1; j < nPolyphonicSounds; j++ )
\r
1630 // cwav.rSound[ j ] = null;
\r
1635 // for ( int j = 1; j < nPolyphonicSounds; j++ )
\r
1637 // cwav.rSound[ j ] = (CSound) cwav.rSound[ 0 ].Clone(); // #24007 2011.9.5 yyagi add: to accelerate loading chip sounds
\r
1638 // CDTXMania.Sound管理.tサウンドを登録する( cwav.rSound[ j ] );
\r
1645 cwav.rSound[ 0 ] = CDTXMania.Sound管理.tサウンドを生成する( str );
\r
1646 cwav.rSound[ 0 ].n音量 = 100;
\r
1647 if ( CDTXMania.ConfigIni.bLog作成解放ログ出力 )
\r
1649 Trace.TraceInformation( "サウンドを作成しました。({3})({0})({1})({2}bytes)", cwav.strコメント文, str, cwav.rSound[ 0 ].nサウンドバッファサイズ, cwav.rSound[ 0 ].bストリーム再生する ? "Stream" : "OnMemory" );
\r
1652 catch ( Exception e )
\r
1654 cwav.rSound[ 0 ] = null;
\r
1655 Trace.TraceError( "サウンドの作成に失敗しました。({0})({1})", cwav.strコメント文, str );
\r
1656 Trace.TraceError( "例外: " + e.Message );
\r
1659 #region [ 同時発音数を、チャンネルによって変える ]
\r
1660 int nPoly = nPolyphonicSounds;
\r
1661 if ( CDTXMania.Sound管理.GetCurrentSoundDeviceType() != "DirectSound" ) // DShowでの再生の場合はミキシング負荷が高くないため、
\r
1662 { // チップのライフタイム管理を行わない
\r
1663 if ( cwav.bIsBassSound ) nPoly = (nPolyphonicSounds >= 2)? 2 : 1;
\r
1664 else if ( cwav.bIsGuitarSound ) nPoly = (nPolyphonicSounds >= 2)? 2 : 1;
\r
1665 else if ( cwav.bIsSESound ) nPoly = 1;
\r
1666 else if ( cwav.bIsBGMSound) nPoly = 1;
\r
1668 if ( cwav.bIsBGMSound ) nPoly = 1;
\r
1672 //if ( bIsDirectSound ) // DShowでの再生の場合はCloneする
\r
1674 // for ( int i = 1; i < nPoly; i++ )
\r
1676 // cwav.rSound[ i ] = (CSound) cwav.rSound[ 0 ].Clone(); // #24007 2011.9.5 yyagi add: to accelerate loading chip sounds
\r
1677 // // CDTXMania.Sound管理.tサウンドを登録する( cwav.rSound[ j ] );
\r
1679 // for ( int i = nPoly; i < nPolyphonicSounds; i++ )
\r
1681 // cwav.rSound[ i ] = null;
\r
1684 //else // WASAPI/ASIO時は通常通り登録
\r
1686 for ( int i = 1; i < nPoly; i++ )
\r
1690 cwav.rSound[ i ] = CDTXMania.Sound管理.tサウンドを生成する( str );
\r
1691 cwav.rSound[ i ].n音量 = 100;
\r
1692 if ( CDTXMania.ConfigIni.bLog作成解放ログ出力 )
\r
1694 Trace.TraceInformation( "サウンドを作成しました。({3})({0})({1})({2}bytes)", cwav.strコメント文, str, cwav.rSound[ 0 ].nサウンドバッファサイズ, cwav.rSound[ 0 ].bストリーム再生する ? "Stream" : "OnMemory" );
\r
1697 catch ( Exception e )
\r
1699 cwav.rSound[ i ] = null;
\r
1700 Trace.TraceError( "サウンドの作成に失敗しました。({0})({1})", cwav.strコメント文, str );
\r
1701 Trace.TraceError( "例外: " + e.Message );
\r
1706 catch( Exception exception )
\r
1708 Trace.TraceError( "サウンドの生成に失敗しました。({0})({1})({2})", exception.Message, cwav.strコメント文, str );
\r
1709 for ( int j = 0; j < nPolyphonicSounds; j++ )
\r
1711 cwav.rSound[ j ] = null;
\r
1717 public static string tZZ( int n )
\r
1719 if( n < 0 || n >= 36 * 36 )
\r
1720 return "!!"; // オーバー/アンダーフロー。
\r
1722 // n を36進数2桁の文字列にして返す。
\r
1724 string str = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
\r
1725 return new string( new char[] { str[ n / 36 ], str[ n % 36 ] } );
\r
1727 public void tギターとベースのランダム化(E楽器パート part, Eランダムモード eRandom)
\r
1729 if( ( ( part == E楽器パート.GUITAR ) || ( part == E楽器パート.BASS ) ) && ( eRandom != Eランダムモード.OFF ) )
\r
1731 int[,] nランダムレーン候補 = new int[ , ] { { 0, 1, 2, 3, 4, 5, 6, 7 }, { 0, 2, 1, 3, 4, 6, 5, 7 }, { 0, 1, 4, 5, 2, 3, 6, 7 }, { 0, 2, 4, 6, 1, 3, 5, 7 }, { 0, 4, 1, 5, 2, 6, 3, 7 }, { 0, 4, 2, 6, 1, 5, 3, 7 } };
\r
1732 int n小節番号 = -10000;
\r
1733 int n小節内乱数6通り = 0;
\r
1734 // int GOTO_END = 0; // gotoの飛び先のダミーコードで使うダミー変数
\r
1735 foreach( CChip chip in this.listChip )
\r
1737 int nRGBレーンビットパターン;
\r
1738 int n新RGBレーンビットパターン = 0; // 「未割り当てのローカル変数」ビルドエラー回避のために0を初期値に設定
\r
1740 if( ( chip.n発声位置 / 384 ) != n小節番号 ) // 小節が変化したら
\r
1742 n小節番号 = chip.n発声位置 / 384;
\r
1743 n小節内乱数6通り = CDTXMania.Random.Next( 6 );
\r
1745 int nランダム化前チャンネル番号 = chip.nチャンネル番号;
\r
1746 if( ( ( ( part != E楽器パート.GUITAR ) || ( 0x20 > nランダム化前チャンネル番号 ) ) || ( nランダム化前チャンネル番号 > 0x27 ) )
\r
1747 && ( ( ( part != E楽器パート.BASS ) || ( 0xA0 > nランダム化前チャンネル番号 ) ) || ( nランダム化前チャンネル番号 > 0xa7 ) )
\r
1754 case Eランダムモード.RANDOM: // 1小節単位でレーンのR/G/Bがランダムに入れ替わる
\r
1755 chip.nチャンネル番号 = ( nランダム化前チャンネル番号 & 0xF0 ) | nランダムレーン候補[ n小節内乱数6通り, nランダム化前チャンネル番号 & 0x07 ];
\r
1756 continue; // goto Label_02C4;
\r
1758 case Eランダムモード.SUPERRANDOM: // チップごとにR/G/Bがランダムで入れ替わる(レーンの本数までは変わらない)。
\r
1759 chip.nチャンネル番号 = ( nランダム化前チャンネル番号 & 0xF0 ) | nランダムレーン候補[ CDTXMania.Random.Next( 6 ), nランダム化前チャンネル番号 & 0x07 ];
\r
1760 continue; // goto Label_02C4;
\r
1762 case Eランダムモード.HYPERRANDOM: // レーンの本数も変わる
\r
1763 nRGBレーンビットパターン = nランダム化前チャンネル番号 & 7;
\r
1764 // n新RGBレーンビットパターン = (int)Eレーンビットパターン.OPEN; // この値は結局未使用なので削除
\r
1765 flag = ((part == E楽器パート.GUITAR) && this.bチップがある.OpenGuitar) || ((part == E楽器パート.BASS) && this.bチップがある.OpenBass); // #23546 2010.10.28 yyagi fixed (bチップがある.Bass→bチップがある.OpenBass)
\r
1766 if (((nRGBレーンビットパターン != (int)Eレーンビットパターン.xxB) && (nRGBレーンビットパターン != (int)Eレーンビットパターン.xGx)) && (nRGBレーンビットパターン != (int)Eレーンビットパターン.Rxx)) // xxB, xGx, Rxx レーン1本相当
\r
1768 break; // レーン1本相当でなければ、とりあえず先に進む
\r
1770 n新RGBレーンビットパターン = CDTXMania.Random.Next( 6 ) + 1; // レーン1本相当なら、レーン1本か2本(1~6)に変化して終了
\r
1774 continue; // goto Label_02C4;
\r
1776 switch( nRGBレーンビットパターン )
\r
1778 case (int)Eレーンビットパターン.xGB: // xGB レーン2本相当
\r
1779 case (int)Eレーンビットパターン.RxB: // RxB
\r
1780 case (int)Eレーンビットパターン.RGx: // RGx
\r
1781 n新RGBレーンビットパターン = flag ? CDTXMania.Random.Next( 8 ) : ( CDTXMania.Random.Next( 7 ) + 1 ); // OPENあり譜面ならOPENを含むランダム, OPENなし譜面ならOPENを含まないランダム
\r
1782 break; // goto Label_02B2;
\r
1785 if( nRGBレーンビットパターン == (int)Eレーンビットパターン.RGB ) // RGB レーン3本相当
\r
1787 if( flag ) // OPENあり譜面の場合
\r
1789 int n乱数パーセント = CDTXMania.Random.Next( 100 );
\r
1790 if( n乱数パーセント < 30 )
\r
1792 n新RGBレーンビットパターン = (int)Eレーンビットパターン.OPEN;
\r
1794 else if( n乱数パーセント < 60 )
\r
1796 n新RGBレーンビットパターン = (int)Eレーンビットパターン.RGB;
\r
1798 else if( n乱数パーセント < 85 )
\r
1800 switch( CDTXMania.Random.Next( 3 ) )
\r
1803 n新RGBレーンビットパターン = (int)Eレーンビットパターン.xGB;
\r
1804 break; // goto Label_02B2;
\r
1807 n新RGBレーンビットパターン = (int)Eレーンビットパターン.RxB;
\r
1808 break; // goto Label_02B2;
\r
1810 n新RGBレーンビットパターン = (int)Eレーンビットパターン.RGx;
\r
1814 switch( CDTXMania.Random.Next( 3 ) )
\r
1817 n新RGBレーンビットパターン = (int)Eレーンビットパターン.xxB;
\r
1818 break; // goto Label_02B2;
\r
1821 n新RGBレーンビットパターン = (int)Eレーンビットパターン.xGx;
\r
1822 break; // goto Label_02B2;
\r
1824 n新RGBレーンビットパターン = (int)Eレーンビットパターン.Rxx;
\r
1827 else // OPENなし譜面の場合
\r
1829 int n乱数パーセント = CDTXMania.Random.Next( 100 );
\r
1830 if( n乱数パーセント < 60 )
\r
1832 n新RGBレーンビットパターン = (int)Eレーンビットパターン.RGB;
\r
1834 else if( n乱数パーセント < 85 )
\r
1836 switch( CDTXMania.Random.Next( 3 ) )
\r
1839 n新RGBレーンビットパターン = (int)Eレーンビットパターン.xGB;
\r
1840 break; // goto Label_02B2;
\r
1843 n新RGBレーンビットパターン = (int)Eレーンビットパターン.RxB;
\r
1844 break; // goto Label_02B2;
\r
1846 n新RGBレーンビットパターン = (int)Eレーンビットパターン.RGx;
\r
1850 switch( CDTXMania.Random.Next( 3 ) )
\r
1853 n新RGBレーンビットパターン = (int)Eレーンビットパターン.xxB;
\r
1854 break; // goto Label_02B2;
\r
1857 n新RGBレーンビットパターン = (int)Eレーンビットパターン.xGx;
\r
1858 break; // goto Label_02B2;
\r
1860 n新RGBレーンビットパターン = (int)Eレーンビットパターン.Rxx;
\r
1864 break; // goto Label_02B2;
\r
1867 chip.nチャンネル番号 = ( nランダム化前チャンネル番号 & 0xF0 ) | n新RGBレーンビットパターン;
\r
1869 // GOTO_END++; // goto用のダミーコード
\r
1874 #region [ チップの再生と停止 ]
\r
1875 public void tチップの再生( CChip rChip, long n再生開始システム時刻ms, int nLane )
\r
1877 this.tチップの再生( rChip, n再生開始システム時刻ms, nLane, CDTXMania.ConfigIni.n自動再生音量, false, false );
\r
1879 public void tチップの再生( CChip rChip, long n再生開始システム時刻ms, int nLane, int nVol )
\r
1881 this.tチップの再生( rChip, n再生開始システム時刻ms, nLane, nVol, false, false );
\r
1883 public void tチップの再生( CChip rChip, long n再生開始システム時刻ms, int nLane, int nVol, bool bMIDIMonitor )
\r
1885 this.tチップの再生( rChip, n再生開始システム時刻ms, nLane, nVol, bMIDIMonitor, false );
\r
1887 public void tチップの再生( CChip pChip, long n再生開始システム時刻ms, int nLane, int nVol, bool bMIDIMonitor, bool bBad )
\r
1889 if( pChip.n整数値・内部番号 >= 0 )
\r
1891 if( ( nLane < (int) Eレーン.LC ) || ( (int) Eレーン.BGM < nLane ) )
\r
1893 throw new ArgumentOutOfRangeException();
\r
1895 if( this.listWAV.ContainsKey( pChip.n整数値・内部番号 ) )
\r
1897 CWAV wc = this.listWAV[ pChip.n整数値・内部番号 ];
\r
1898 int index = wc.n現在再生中のサウンド番号 = ( wc.n現在再生中のサウンド番号 + 1 ) % nPolyphonicSounds;
\r
1899 if( ( wc.rSound[ 0 ] != null ) &&
\r
1900 ( wc.rSound[ 0 ].bストリーム再生する || wc.rSound[index] == null ) )
\r
1902 index = wc.n現在再生中のサウンド番号 = 0;
\r
1904 CSound sound = wc.rSound[ index ];
\r
1905 if( sound != null )
\r
1909 sound.db周波数倍率 = ( (float) ( 100 + ( ( ( CDTXMania.Random.Next( 3 ) + 1 ) * 7 ) * ( 1 - ( CDTXMania.Random.Next( 2 ) * 2 ) ) ) ) ) / 100f;
\r
1913 sound.db周波数倍率 = 1.0;
\r
1915 sound.db再生速度 = ( (double) CDTXMania.ConfigIni.n演奏速度 ) / 20.0;
\r
1916 // 再生速度によって、WASAPI/ASIOで使う使用mixerが決まるため、付随情報の設定(音量/PAN)は、再生速度の設定後に行う
\r
1917 sound.n音量 = (int) ( ( (double) ( nVol * wc.n音量 ) ) / 100.0 );
\r
1918 sound.n位置 = wc.n位置;
\r
1921 wc.n再生開始時刻[ wc.n現在再生中のサウンド番号 ] = n再生開始システム時刻ms;
\r
1922 this.tWave再生位置自動補正( wc );
\r
1926 public void t各自動再生音チップの再生時刻を変更する( int nBGMAdjustの増減値 )
\r
1928 this.nBGMAdjust += nBGMAdjustの増減値;
\r
1929 for( int i = 0; i < this.listChip.Count; i++ )
\r
1931 int nChannelNumber = this.listChip[ i ].nチャンネル番号;
\r
1933 ( nChannelNumber == 1 ) ||
\r
1934 ( ( 0x61 <= nChannelNumber ) && ( nChannelNumber <= 0x69 ) )
\r
1936 ( ( 0x70 <= nChannelNumber ) && ( nChannelNumber <= 0x79 ) )
\r
1938 ( ( ( 0x80 <= nChannelNumber ) && ( nChannelNumber <= 0x89 ) ) || ( ( 0x90 <= nChannelNumber ) && ( nChannelNumber <= 0x92 ) ) )
\r
1941 this.listChip[ i ].n発声時刻ms += nBGMAdjustの増減値;
\r
1944 foreach( CWAV cwav in this.listWAV.Values )
\r
1946 for ( int j = 0; j < nPolyphonicSounds; j++ )
\r
1948 if( ( cwav.rSound[ j ] != null ) && cwav.rSound[ j ].b再生中 )
\r
1950 cwav.n再生開始時刻[ j ] += nBGMAdjustの増減値;
\r
1955 public void t全チップの再生一時停止()
\r
1957 foreach( CWAV cwav in this.listWAV.Values )
\r
1959 for ( int i = 0; i < nPolyphonicSounds; i++ )
\r
1961 if( ( cwav.rSound[ i ] != null ) && cwav.rSound[ i ].b再生中 )
\r
1963 cwav.rSound[ i ].t再生を一時停止する();
\r
1964 cwav.n一時停止時刻[ i ] = CSound管理.rc演奏用タイマ.nシステム時刻ms;
\r
1969 public void t全チップの再生再開()
\r
1971 foreach( CWAV cwav in this.listWAV.Values )
\r
1973 for ( int i = 0; i < nPolyphonicSounds; i++ )
\r
1975 if( ( cwav.rSound[ i ] != null ) && cwav.rSound[ i ].b一時停止中 )
\r
1977 //long num1 = cwav.n一時停止時刻[ i ];
\r
1978 //long num2 = cwav.n再生開始時刻[ i ];
\r
1979 cwav.rSound[ i ].t再生を再開する( cwav.n一時停止時刻[ i ] - cwav.n再生開始時刻[ i ] );
\r
1980 cwav.n再生開始時刻[ i ] += CSound管理.rc演奏用タイマ.nシステム時刻ms - cwav.n一時停止時刻[ i ];
\r
1985 public void t全チップの再生停止()
\r
1987 foreach( CWAV cwav in this.listWAV.Values )
\r
1989 this.tWavの再生停止( cwav.n内部番号 );
\r
1994 public void t入力( string strファイル名, bool bヘッダのみ )
\r
1996 this.t入力( strファイル名, bヘッダのみ, 1.0, 0 );
\r
1998 public void t入力( string strファイル名, bool bヘッダのみ, double db再生速度, int nBGMAdjust )
\r
2000 this.bヘッダのみ = bヘッダのみ;
\r
2001 this.strファイル名の絶対パス = Path.GetFullPath( strファイル名 );
\r
2002 this.strファイル名 = Path.GetFileName( this.strファイル名の絶対パス );
\r
2003 this.strフォルダ名 = Path.GetDirectoryName( this.strファイル名の絶対パス ) + @"\";
\r
2004 string ext = Path.GetExtension( this.strファイル名 ).ToLower();
\r
2005 if ( ext != null )
\r
2007 if ( !( ext == ".dtx" ) )
\r
2009 if ( ext == ".gda" )
\r
2011 this.e種別 = E種別.GDA;
\r
2013 else if ( ext == ".g2d" )
\r
2015 this.e種別 = E種別.G2D;
\r
2017 else if ( ext == ".bms" )
\r
2019 this.e種別 = E種別.BMS;
\r
2021 else if ( ext == ".bme" )
\r
2023 this.e種別 = E種別.BME;
\r
2025 else if ( ext == ".mid" )
\r
2027 this.e種別 = E種別.SMF;
\r
2032 this.e種別 = E種別.DTX;
\r
2035 if ( this.e種別 != E種別.SMF )
\r
2039 //DateTime timeBeginLoad = DateTime.Now;
\r
2042 StreamReader reader = new StreamReader( strファイル名, Encoding.GetEncoding( "Shift_JIS" ) );
\r
2043 string str2 = reader.ReadToEnd();
\r
2045 //span = (TimeSpan) ( DateTime.Now - timeBeginLoad );
\r
2046 //Trace.TraceInformation( "DTXfileload時間: {0}", span.ToString() );
\r
2048 this.t入力・全入力文字列から( str2, db再生速度, nBGMAdjust );
\r
2056 Trace.TraceWarning( "SMF の演奏は未対応です。(検討中)" );
\r
2059 public void t入力・全入力文字列から( string str全入力文字列 )
\r
2061 this.t入力・全入力文字列から( str全入力文字列, 1.0, 0 );
\r
2063 public unsafe void t入力・全入力文字列から( string str全入力文字列, double db再生速度, int nBGMAdjust )
\r
2065 //DateTime timeBeginLoad = DateTime.Now;
\r
2068 if ( !string.IsNullOrEmpty( str全入力文字列 ) )
\r
2071 this.db再生速度 = db再生速度;
\r
2072 str全入力文字列 = str全入力文字列.Replace( Environment.NewLine, "\n" );
\r
2073 str全入力文字列 = str全入力文字列.Replace( '\t', ' ' );
\r
2074 str全入力文字列 = str全入力文字列 + "\n";
\r
2076 //span = (TimeSpan) ( DateTime.Now - timeBeginLoad );
\r
2077 //Trace.TraceInformation( "改行カット時間: {0}", span.ToString() );
\r
2078 //timeBeginLoad = DateTime.Now;
\r
2080 for ( int j = 0; j < 36 * 36; j++ )
\r
2082 this.n無限管理WAV[ j ] = -j;
\r
2083 this.n無限管理BPM[ j ] = -j;
\r
2084 this.n無限管理VOL[ j ] = -j;
\r
2085 this.n無限管理PAN[ j ] = -10000 - j;
\r
2086 this.n無限管理SIZE[ j ] = -j;
\r
2088 this.n内部番号WAV1to = 1;
\r
2089 this.n内部番号BPM1to = 1;
\r
2090 this.bstackIFからENDIFをスキップする = new Stack<bool>();
\r
2091 this.bstackIFからENDIFをスキップする.Push( false );
\r
2093 for ( int k = 0; k < 7; k++ )
\r
2095 this.nRESULTIMAGE用優先順位[ k ] = 0;
\r
2096 this.nRESULTMOVIE用優先順位[ k ] = 0;
\r
2097 this.nRESULTSOUND用優先順位[ k ] = 0;
\r
2100 #region [ 入力/行解析 ]
\r
2101 CharEnumerator ce = str全入力文字列.GetEnumerator();
\r
2102 if ( ce.MoveNext() )
\r
2107 if ( !this.t入力・空白と改行をスキップする( ref ce ) )
\r
2111 if ( ce.Current == '#' )
\r
2113 if ( ce.MoveNext() )
\r
2115 StringBuilder builder = new StringBuilder( 0x20 );
\r
2116 if ( this.t入力・コマンド文字列を抜き出す( ref ce, ref builder ) )
\r
2118 StringBuilder builder2 = new StringBuilder( 0x400 );
\r
2119 if ( this.t入力・パラメータ文字列を抜き出す( ref ce, ref builder2 ) )
\r
2121 StringBuilder builder3 = new StringBuilder( 0x400 );
\r
2122 if ( this.t入力・コメント文字列を抜き出す( ref ce, ref builder3 ) )
\r
2124 this.t入力・行解析( ref builder, ref builder2, ref builder3 );
\r
2134 while ( this.t入力・コメントをスキップする( ref ce ) );
\r
2136 //span = (TimeSpan) ( DateTime.Now - timeBeginLoad );
\r
2137 //Trace.TraceInformation( "抜き出し時間: {0}", span.ToString() );
\r
2138 //timeBeginLoad = DateTime.Now;
\r
2139 this.n無限管理WAV = null;
\r
2140 this.n無限管理BPM = null;
\r
2141 this.n無限管理VOL = null;
\r
2142 this.n無限管理PAN = null;
\r
2143 this.n無限管理SIZE = null;
\r
2144 if ( !this.bヘッダのみ )
\r
2146 #region [ BPM/BMP初期化 ]
\r
2149 foreach ( CBPM cbpm2 in this.listBPM.Values )
\r
2151 if ( cbpm2.n表記上の番号 == 0 )
\r
2157 if ( cbpm == null )
\r
2159 cbpm = new CBPM();
\r
2160 cbpm.n内部番号 = this.n内部番号BPM1to++;
\r
2162 cbpm.dbBPM値 = 120.0;
\r
2163 this.listBPM.Add( cbpm.n内部番号, cbpm );
\r
2164 CChip chip = new CChip();
\r
2166 chip.nチャンネル番号 = 8; // 拡張BPM
\r
2168 chip.n整数値・内部番号 = cbpm.n内部番号;
\r
2169 this.listChip.Insert( 0, chip );
\r
2173 CChip chip = new CChip();
\r
2175 chip.nチャンネル番号 = 8; // 拡張BPM
\r
2177 chip.n整数値・内部番号 = cbpm.n内部番号;
\r
2178 this.listChip.Insert( 0, chip );
\r
2180 if ( this.listBMP.ContainsKey( 0 ) )
\r
2182 CChip chip = new CChip();
\r
2184 chip.nチャンネル番号 = 4; // BGA (レイヤBGA1)
\r
2186 chip.n整数値・内部番号 = 0;
\r
2187 this.listChip.Insert( 0, chip );
\r
2190 //span = (TimeSpan) ( DateTime.Now - timeBeginLoad );
\r
2191 //Trace.TraceInformation( "前準備完了時間: {0}", span.ToString() );
\r
2192 //timeBeginLoad = DateTime.Now;
\r
2193 #region [ CWAV初期化 ]
\r
2194 foreach ( CWAV cwav in this.listWAV.Values )
\r
2196 if ( cwav.nチップサイズ < 0 )
\r
2198 cwav.nチップサイズ = 100;
\r
2200 if ( cwav.n位置 <= -10000 )
\r
2204 if ( cwav.n音量 < 0 )
\r
2210 //span = (TimeSpan) ( DateTime.Now - timeBeginLoad );
\r
2211 //Trace.TraceInformation( "CWAV前準備時間: {0}", span.ToString() );
\r
2212 //timeBeginLoad = DateTime.Now;
\r
2213 #region [ チップ倍率設定 ] // #28145 2012.4.22 yyagi 二重ループを1重ループに変更して高速化)
\r
2214 //foreach ( CWAV cwav in this.listWAV.Values )
\r
2216 // foreach( CChip chip in this.listChip )
\r
2218 // if( chip.n整数値・内部番号 == cwav.n内部番号 )
\r
2220 // chip.dbチップサイズ倍率 = ( (double) cwav.nチップサイズ ) / 100.0;
\r
2221 // if (chip.nチャンネル番号 == 0x01 ) // BGMだったら
\r
2223 // cwav.bIsOnBGMLane = true;
\r
2228 foreach ( CChip chip in this.listChip )
\r
2230 if ( this.listWAV.ContainsKey( chip.n整数値・内部番号 ) )
\r
2231 //foreach ( CWAV cwav in this.listWAV.Values )
\r
2233 CWAV cwav = this.listWAV[ chip.n整数値・内部番号 ];
\r
2234 // if ( chip.n整数値・内部番号 == cwav.n内部番号 )
\r
2236 chip.dbチップサイズ倍率 = ( (double) cwav.nチップサイズ ) / 100.0;
\r
2237 //if ( chip.nチャンネル番号 == 0x01 ) // BGMだったら
\r
2239 // cwav.bIsOnBGMLane = true;
\r
2245 //span = (TimeSpan) ( DateTime.Now - timeBeginLoad );
\r
2246 //Trace.TraceInformation( "CWAV全準備時間: {0}", span.ToString() );
\r
2247 //timeBeginLoad = DateTime.Now;
\r
2248 #region [ 必要に応じて空打ち音を0小節に定義する ]
\r
2249 //for ( int m = 0xb1; m <= 0xbc; m++ ) // #28146 2012.4.21 yyagi; bb -> bc
\r
2251 // foreach ( CChip chip in this.listChip )
\r
2253 // if ( chip.nチャンネル番号 == m )
\r
2255 // CChip c = new CChip();
\r
2257 // c.nチャンネル番号 = chip.nチャンネル番号;
\r
2258 // c.n整数値 = chip.n整数値;
\r
2259 // c.n整数値・内部番号 = chip.n整数値・内部番号;
\r
2260 // this.listChip.Insert( 0, c );
\r
2266 //span = (TimeSpan) ( DateTime.Now - timeBeginLoad );
\r
2267 //Trace.TraceInformation( "空打確認時間: {0}", span.ToString() );
\r
2268 //timeBeginLoad = DateTime.Now;
\r
2269 #region [ 拍子・拍線の挿入 ]
\r
2270 if ( this.listChip.Count > 0 )
\r
2272 this.listChip.Sort(); // 高速化のためにはこれを削りたいが、listChipの最後がn発声位置の終端である必要があるので、
\r
2273 // 保守性確保を優先してここでのソートは残しておく
\r
2274 // なお、093時点では、このソートを削除しても動作するようにはしてある。
\r
2275 // (ここまでの一部チップ登録を、listChip.Add(c)から同Insert(0,c)に変更してある)
\r
2276 // これにより、数ms程度ながらここでのソートも高速化されている。
\r
2277 double barlength = 1.0;
\r
2278 int nEndOfSong = ( this.listChip[ this.listChip.Count - 1 ].n発声位置 + 384 ) - ( this.listChip[ this.listChip.Count - 1 ].n発声位置 % 384 );
\r
2279 for ( int tick384 = 0; tick384 <= nEndOfSong; tick384 += 384 ) // 小節線の挿入 (後に出てくる拍子線とループをまとめようとするなら、forループの終了条件の微妙な違いに注意が必要)
\r
2281 CChip chip = new CChip();
\r
2282 chip.n発声位置 = tick384;
\r
2283 chip.nチャンネル番号 = 0x50; // 小節線
\r
2284 chip.n整数値 = 36 * 36 - 1;
\r
2285 this.listChip.Add( chip );
\r
2287 //this.listChip.Sort(); // ここでのソートは不要。ただし最後にソートすること
\r
2288 int nChipNo_BarLength = 0;
\r
2289 int nChipNo_C1 = 0;
\r
2290 for ( int tick384 = 0; tick384 < nEndOfSong; tick384 += 384 )
\r
2292 int n発声位置_C1_同一小節内 = 0;
\r
2293 while ( ( nChipNo_C1 < this.listChip.Count ) && ( this.listChip[ nChipNo_C1 ].n発声位置 < ( tick384 + 384 ) ) )
\r
2295 if ( this.listChip[ nChipNo_C1 ].nチャンネル番号 == 0xc1 ) // 拍線シフトの検出
\r
2297 n発声位置_C1_同一小節内 = this.listChip[ nChipNo_C1 ].n発声位置 - tick384;
\r
2301 if ( ( this.e種別 == E種別.BMS ) || ( this.e種別 == E種別.BME ) )
\r
2305 while ( ( nChipNo_BarLength < this.listChip.Count ) && ( this.listChip[ nChipNo_BarLength ].n発声位置 <= tick384 ) )
\r
2307 if ( this.listChip[ nChipNo_BarLength ].nチャンネル番号 == 0x02 ) // bar lengthの検出
\r
2309 barlength = this.listChip[ nChipNo_BarLength ].db実数値;
\r
2311 nChipNo_BarLength++;
\r
2313 for ( int i = 0; i < 100; i++ ) // 拍線の挿入
\r
2315 int tickBeat = (int) ( ( (double) ( 384 * i ) ) / ( 4.0 * barlength ) );
\r
2316 if ( ( tickBeat + n発声位置_C1_同一小節内 ) >= 384 )
\r
2320 if ( ( ( tickBeat + n発声位置_C1_同一小節内 ) % 384 ) != 0 )
\r
2322 CChip chip = new CChip();
\r
2323 chip.n発声位置 = tick384 + ( tickBeat + n発声位置_C1_同一小節内 );
\r
2324 chip.nチャンネル番号 = 0x51; // beat line 拍線
\r
2325 chip.n整数値 = 36 * 36 - 1;
\r
2326 this.listChip.Add( chip );
\r
2330 this.listChip.Sort();
\r
2333 //span = (TimeSpan) ( DateTime.Now - timeBeginLoad );
\r
2334 //Trace.TraceInformation( "拍子・拍線挿入時間: {0}", span.ToString() );
\r
2335 //timeBeginLoad = DateTime.Now;
\r
2336 #region [ C2 [拍線・小節線表示指定] の処理 ] // #28145 2012.4.21 yyagi; 2重ループをほぼ1重にして高速化
\r
2337 bool bShowBeatBarLine = true;
\r
2338 for ( int i = 0; i < this.listChip.Count; i++ )
\r
2340 bool bChangedBeatBarStatus = false;
\r
2341 if ( ( this.listChip[ i ].nチャンネル番号 == 0xc2 ) )
\r
2343 if ( this.listChip[ i ].n整数値 == 1 ) // BAR/BEAT LINE = ON
\r
2345 bShowBeatBarLine = true;
\r
2346 bChangedBeatBarStatus = true;
\r
2348 else if ( this.listChip[ i ].n整数値 == 2 ) // BAR/BEAT LINE = OFF
\r
2350 bShowBeatBarLine = false;
\r
2351 bChangedBeatBarStatus = true;
\r
2354 int startIndex = i;
\r
2355 if ( bChangedBeatBarStatus ) // C2チップの前に50/51チップが来ている可能性に配慮
\r
2357 while ( startIndex > 0 && this.listChip[ startIndex ].n発声位置 == this.listChip[ i ].n発声位置 )
\r
2361 startIndex++; // 1つ小さく過ぎているので、戻す
\r
2363 for ( int j = startIndex; j <= i; j++ )
\r
2365 if ( ( ( this.listChip[ j ].nチャンネル番号 == 0x50 ) || ( this.listChip[ j ].nチャンネル番号 == 0x51 ) ) &&
\r
2366 ( this.listChip[ j ].n整数値 == ( 36 * 36 - 1 ) ) )
\r
2368 this.listChip[ j ].b可視 = bShowBeatBarLine;
\r
2373 //span = (TimeSpan) ( DateTime.Now - timeBeginLoad );
\r
2374 //Trace.TraceInformation( "C2 [拍線・小節線表示指定]: {0}", span.ToString() );
\r
2375 //timeBeginLoad = DateTime.Now;
\r
2376 #region [ 発声時刻の計算 ]
\r
2377 double bpm = 120.0;
\r
2378 double dbBarLength = 1.0;
\r
2382 foreach ( CChip chip in this.listChip )
\r
2384 chip.n発声時刻ms = ms + ( (int) ( ( ( 0x271 * ( chip.n発声位置 - n発声位置 ) ) * dbBarLength ) / bpm ) );
\r
2385 if ( ( ( this.e種別 == E種別.BMS ) || ( this.e種別 == E種別.BME ) ) && ( ( dbBarLength != 1.0 ) && ( ( chip.n発声位置 / 384 ) != nBar ) ) )
\r
2387 n発声位置 = chip.n発声位置;
\r
2388 ms = chip.n発声時刻ms;
\r
2389 dbBarLength = 1.0;
\r
2391 nBar = chip.n発声位置 / 384;
\r
2392 ch = chip.nチャンネル番号;
\r
2395 case 0x02: // BarLength
\r
2397 n発声位置 = chip.n発声位置;
\r
2398 ms = chip.n発声時刻ms;
\r
2399 dbBarLength = chip.db実数値;
\r
2404 n発声位置 = chip.n発声位置;
\r
2405 ms = chip.n発声時刻ms;
\r
2406 bpm = this.BASEBPM + chip.n整数値;
\r
2409 case 0x04: // BGA (レイヤBGA1)
\r
2410 case 0x07: // レイヤBGA2
\r
2411 case 0x55: // レイヤBGA3
\r
2412 case 0x56: // レイヤBGA4
\r
2413 case 0x57: // レイヤBGA5
\r
2414 case 0x58: // レイヤBGA6
\r
2415 case 0x59: // レイヤBGA7
\r
2416 case 0x60: // レイヤBGA8
\r
2419 case 0x05: // Extended Object (非対応)
\r
2420 case 0x06: // Missアニメ (非対応)
\r
2430 case 0x08: // 拡張BPM
\r
2432 n発声位置 = chip.n発声位置;
\r
2433 ms = chip.n発声時刻ms;
\r
2434 if ( this.listBPM.ContainsKey( chip.n整数値・内部番号 ) )
\r
2436 bpm = ( ( this.listBPM[ chip.n整数値・内部番号 ].n表記上の番号 == 0 ) ? 0.0 : this.BASEBPM ) + this.listBPM[ chip.n整数値・内部番号 ].dbBPM値;
\r
2440 case 0x54: // 動画再生
\r
2442 if ( this.listAVIPAN.ContainsKey( chip.n整数値 ) )
\r
2444 int num21 = ms + ( (int) ( ( ( 0x271 * ( chip.n発声位置 - n発声位置 ) ) * dbBarLength ) / bpm ) );
\r
2445 int num22 = ms + ( (int) ( ( ( 0x271 * ( ( chip.n発声位置 + this.listAVIPAN[ chip.n整数値 ].n移動時間ct ) - n発声位置 ) ) * dbBarLength ) / bpm ) );
\r
2446 chip.n総移動時間 = num22 - num21;
\r
2455 if ( this.listBGAPAN.ContainsKey( chip.n整数値 ) )
\r
2457 int num19 = ms + ( (int) ( ( ( 0x271 * ( chip.n発声位置 - n発声位置 ) ) * dbBarLength ) / bpm ) );
\r
2458 int num20 = ms + ( (int) ( ( ( 0x271 * ( ( chip.n発声位置 + this.listBGAPAN[ chip.n整数値 ].n移動時間ct ) - n発声位置 ) ) * dbBarLength ) / bpm ) );
\r
2459 chip.n総移動時間 = num20 - num19;
\r
2462 if ( this.db再生速度 > 0.0 )
\r
2464 double _db再生速度 = ( CDTXMania.DTXVmode.Enabled ) ? this.dbDTXVPlaySpeed : this.db再生速度;
\r
2465 foreach ( CChip chip in this.listChip )
\r
2467 chip.n発声時刻ms = (int) ( ( (double) chip.n発声時刻ms ) / _db再生速度 );
\r
2471 //span = (TimeSpan) ( DateTime.Now - timeBeginLoad );
\r
2472 //Trace.TraceInformation( "発声時刻計算: {0}", span.ToString() );
\r
2473 //timeBeginLoad = DateTime.Now;
\r
2474 this.nBGMAdjust = 0;
\r
2475 this.t各自動再生音チップの再生時刻を変更する( nBGMAdjust );
\r
2476 //span = (TimeSpan) ( DateTime.Now - timeBeginLoad );
\r
2477 //Trace.TraceInformation( "再生時刻変更: {0}", span.ToString() );
\r
2478 //timeBeginLoad = DateTime.Now;
\r
2479 #region [ 可視チップ数カウント ]
\r
2480 for ( int n = 0; n < 12; n++ )
\r
2482 this.n可視チップ数[ n ] = 0;
\r
2484 foreach ( CChip chip in this.listChip )
\r
2486 int c = chip.nチャンネル番号;
\r
2487 if ( ( 0x11 <= c ) && ( c <= 0x1a ) )
\r
2489 this.n可視チップ数[ c - 0x11 ]++;
\r
2491 if ( ( 0x20 <= c ) && ( c <= 0x27 ) )
\r
2493 this.n可視チップ数.Guitar++;
\r
2495 if ( ( 0xA0 <= c ) && ( c <= 0xa7 ) )
\r
2497 this.n可視チップ数.Bass++;
\r
2501 //span = (TimeSpan) ( DateTime.Now - timeBeginLoad );
\r
2502 //Trace.TraceInformation( "可視チップ数カウント {0}", span.ToString() );
\r
2503 //timeBeginLoad = DateTime.Now;
\r
2504 #region [ チップの種類を分類し、対応するフラグを立てる ]
\r
2505 foreach ( CChip chip in this.listChip )
\r
2507 if ( ( chip.bWAVを使うチャンネルである && this.listWAV.ContainsKey( chip.n整数値・内部番号 ) ) && !this.listWAV[ chip.n整数値・内部番号 ].listこのWAVを使用するチャンネル番号の集合.Contains( chip.nチャンネル番号 ) )
\r
2509 this.listWAV[ chip.n整数値・内部番号 ].listこのWAVを使用するチャンネル番号の集合.Add( chip.nチャンネル番号 );
\r
2511 int c = chip.nチャンネル番号 >> 4;
\r
2515 this.listWAV[ chip.n整数値・内部番号 ].bIsDrumsSound = true; break;
\r
2517 this.listWAV[ chip.n整数値・内部番号 ].bIsGuitarSound = true; break;
\r
2519 this.listWAV[ chip.n整数値・内部番号 ].bIsBassSound = true; break;
\r
2524 this.listWAV[ chip.n整数値・内部番号 ].bIsSESound = true; break;
\r
2526 if ( chip.nチャンネル番号 == 0x01 )
\r
2528 this.listWAV[ chip.n整数値・内部番号 ].bIsBGMSound = true; break;
\r
2535 //span = (TimeSpan) ( DateTime.Now - timeBeginLoad );
\r
2536 //Trace.TraceInformation( "ch番号集合確認: {0}", span.ToString() );
\r
2537 //timeBeginLoad = DateTime.Now;
\r
2538 #region [ hash値計算 ]
\r
2539 byte[] buffer = null;
\r
2542 FileStream stream = new FileStream( this.strファイル名の絶対パス, FileMode.Open, FileAccess.Read );
\r
2543 buffer = new byte[ stream.Length ];
\r
2544 stream.Read( buffer, 0, (int) stream.Length );
\r
2547 catch ( Exception exception )
\r
2549 Trace.TraceError( exception.Message );
\r
2550 Trace.TraceError( "DTXのハッシュの計算に失敗しました。({0})", this.strファイル名の絶対パス );
\r
2552 if ( buffer != null )
\r
2554 byte[] buffer2 = new MD5CryptoServiceProvider().ComputeHash( buffer );
\r
2555 StringBuilder sb = new StringBuilder();
\r
2556 foreach ( byte b in buffer2 )
\r
2558 sb.Append( b.ToString( "x2" ) );
\r
2560 this.strハッシュofDTXファイル = sb.ToString();
\r
2564 this.strハッシュofDTXファイル = "00000000000000000000000000000000";
\r
2567 //span = (TimeSpan) ( DateTime.Now - timeBeginLoad );
\r
2568 //Trace.TraceInformation( "hash計算: {0}", span.ToString() );
\r
2569 //timeBeginLoad = DateTime.Now;
\r
2570 #region [ bLogDTX詳細ログ出力 ]
\r
2571 if ( CDTXMania.ConfigIni.bLogDTX詳細ログ出力 )
\r
2573 foreach ( CWAV cwav in this.listWAV.Values )
\r
2575 Trace.TraceInformation( cwav.ToString() );
\r
2577 foreach ( CAVI cavi in this.listAVI.Values )
\r
2579 Trace.TraceInformation( cavi.ToString() );
\r
2581 foreach ( CAVIPAN cavipan in this.listAVIPAN.Values )
\r
2583 Trace.TraceInformation( cavipan.ToString() );
\r
2585 foreach ( CBGA cbga in this.listBGA.Values )
\r
2587 Trace.TraceInformation( cbga.ToString() );
\r
2589 foreach ( CBGAPAN cbgapan in this.listBGAPAN.Values )
\r
2591 Trace.TraceInformation( cbgapan.ToString() );
\r
2593 foreach ( CBMP cbmp in this.listBMP.Values )
\r
2595 Trace.TraceInformation( cbmp.ToString() );
\r
2597 foreach ( CBMPTEX cbmptex in this.listBMPTEX.Values )
\r
2599 Trace.TraceInformation( cbmptex.ToString() );
\r
2601 foreach ( CBPM cbpm3 in this.listBPM.Values )
\r
2603 Trace.TraceInformation( cbpm3.ToString() );
\r
2605 foreach ( CChip chip in this.listChip )
\r
2607 Trace.TraceInformation( chip.ToString() );
\r
2616 /// サウンドミキサーにサウンドを登録・削除する時刻を事前に算出する
\r
2618 public void PlanToAddMixerChannel()
\r
2620 if ( CDTXMania.Sound管理.GetCurrentSoundDeviceType() == "DirectSound" ) // DShowでの再生の場合はミキシング負荷が高くないため、
\r
2621 { // チップのライフタイム管理を行わない
\r
2625 List<CChip> listAddMixerChannel = new List<CChip>( 128 ); ;
\r
2626 List<CChip> listRemoveMixerChannel = new List<CChip>( 128 );
\r
2627 List<CChip> listRemoveTiming = new List<CChip>( 128 );
\r
2629 foreach ( CChip pChip in listChip )
\r
2631 switch ( pChip.nチャンネル番号 )
\r
2633 // BGM, 演奏チャネル, 不可視サウンド, フィルインサウンド, 空打ち音はミキサー管理の対象
\r
2637 case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: case 0x18: case 0x19: case 0x1A:
\r
2639 case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: case 0x28:
\r
2641 case 0xA0: case 0xA1: case 0xA2: case 0xA3: case 0xA4: case 0xA5: case 0xA6: case 0xA7: case 0xA8:
\r
2643 case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
\r
2644 case 0x38: case 0x39: case 0x3A:
\r
2646 case 0xB1: case 0xB2: case 0xB3: case 0xB4: case 0xB5: case 0xB6: case 0xB7: case 0xB8:
\r
2647 case 0xB9: case 0xBA: case 0xBB: case 0xBC:
\r
2649 case 0x1F: case 0x2F: case 0xAF:
\r
2651 case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67: case 0x68: case 0x69:
\r
2652 case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77: case 0x78: case 0x79:
\r
2653 case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87: case 0x88: case 0x89:
\r
2654 case 0x90: case 0x91: case 0x92:
\r
2656 #region [ 発音1秒前のタイミングを記録 ]
\r
2657 int n発音前余裕ms = 1000, n発音後余裕ms = 800;
\r
2659 int ch = pChip.nチャンネル番号 >> 4;
\r
2660 if ( ch == 0x02 || ch == 0x0A )
\r
2665 if ( ch == 0x06 || ch == 0x07 || ch == 0x08 || ch == 0x09 )
\r
2671 if ( pChip.nチャンネル番号 == 0x01 ) // BGMチップは即ミキサーに追加
\r
2673 if ( listWAV.ContainsKey( pChip.n整数値・内部番号 ) )
\r
2675 CDTX.CWAV wc = CDTXMania.DTX.listWAV[ pChip.n整数値・内部番号 ];
\r
2676 if ( wc.rSound[ 0 ] != null )
\r
2678 CDTXMania.Sound管理.AddMixer( wc.rSound[ 0 ] ); // BGMは多重再生しない仕様としているので、1個目だけミキサーに登録すればよい
\r
2684 int nAddMixer時刻ms, nAddMixer位置 = 0;
\r
2685 //Debug.WriteLine("==================================================================");
\r
2686 //Debug.WriteLine( "Start: ch=" + pChip.nチャンネル番号.ToString("x2") + ", nWAV番号=" + pChip.n整数値 + ", time=" + pChip.n発声時刻ms + ", lasttime=" + listChip[ listChip.Count - 1 ].n発声時刻ms );
\r
2687 t発声時刻msと発声位置を取得する( pChip.n発声時刻ms - n発音前余裕ms, out nAddMixer時刻ms, out nAddMixer位置 );
\r
2688 //Debug.WriteLine( "nAddMixer時刻ms=" + nAddMixer時刻ms + ",nAddMixer位置=" + nAddMixer位置 );
\r
2690 CChip c_AddMixer = new CChip()
\r
2693 n整数値 = pChip.n整数値,
\r
2694 n整数値・内部番号 = pChip.n整数値・内部番号,
\r
2695 n発声時刻ms = nAddMixer時刻ms,
\r
2696 n発声位置 = nAddMixer位置,
\r
2697 b演奏終了後も再生が続くチップである = false
\r
2699 listAddMixerChannel.Add( c_AddMixer );
\r
2700 //Debug.WriteLine("listAddMixerChannel:" );
\r
2701 //DebugOut_CChipList( listAddMixerChannel );
\r
2705 if ( listWAV.ContainsKey( pChip.n整数値・内部番号 ) )
\r
2707 CDTX.CWAV wc = CDTXMania.DTX.listWAV[ pChip.n整数値・内部番号 ];
\r
2708 duration = ( wc.rSound[ 0 ] == null ) ? 0 : (int) ( wc.rSound[ 0 ].n総演奏時間ms / this.db再生速度 ); // #23664 durationに再生速度が加味されておらず、低速再生でBGMが途切れる問題を修正 (発声時刻msは、DTX読み込み時に再生速度加味済)
\r
2710 //Debug.WriteLine("duration=" + duration );
\r
2711 int n新RemoveMixer時刻ms, n新RemoveMixer位置;
\r
2712 t発声時刻msと発声位置を取得する( pChip.n発声時刻ms + duration + n発音後余裕ms, out n新RemoveMixer時刻ms, out n新RemoveMixer位置 );
\r
2713 //Debug.WriteLine( "n新RemoveMixer時刻ms=" + n新RemoveMixer時刻ms + ",n新RemoveMixer位置=" + n新RemoveMixer位置 );
\r
2714 if ( n新RemoveMixer時刻ms < pChip.n発声時刻ms + duration ) // 曲の最後でサウンドが切れるような場合は
\r
2716 CChip c_AddMixer_noremove = c_AddMixer;
\r
2717 c_AddMixer_noremove.b演奏終了後も再生が続くチップである = true;
\r
2718 listAddMixerChannel[ listAddMixerChannel.Count - 1 ] = c_AddMixer_noremove;
\r
2719 //continue; // 発声位置の計算ができないので、Mixer削除をあきらめる・・・のではなく
\r
2720 // #32248 2013.10.15 yyagi 演奏終了後も再生を続けるチップであるというフラグをpChip内に立てる
\r
2723 #region [ 未使用コード ]
\r
2724 //if ( n新RemoveMixer時刻ms < pChip.n発声時刻ms + duration ) // 曲の最後でサウンドが切れるような場合
\r
2726 // n新RemoveMixer時刻ms = pChip.n発声時刻ms + duration;
\r
2727 // // 「位置」は比例計算で求めてお茶を濁す...このやり方だと誤動作したため対応中止
\r
2728 // n新RemoveMixer位置 = listChip[ listChip.Count - 1 ].n発声位置 * n新RemoveMixer時刻ms / listChip[ listChip.Count - 1 ].n発声時刻ms;
\r
2732 #region [ 発音終了2秒後にmixerから削除するが、その前に再発音することになるのかを確認(再発音ならmixer削除タイミングを延期) ]
\r
2733 int n整数値 = pChip.n整数値;
\r
2734 int index = listRemoveTiming.FindIndex(
\r
2735 delegate( CChip cchip ) { return cchip.n整数値 == n整数値; }
\r
2737 //Debug.WriteLine( "index=" + index );
\r
2738 if ( index >= 0 ) // 過去に同じチップで発音中のものが見つかった場合
\r
2739 { // 過去の発音のmixer削除を確定させるか、延期するかの2択。
\r
2740 int n旧RemoveMixer時刻ms = listRemoveTiming[ index ].n発声時刻ms;
\r
2741 int n旧RemoveMixer位置 = listRemoveTiming[ index ].n発声位置;
\r
2743 //Debug.WriteLine( "n旧RemoveMixer時刻ms=" + n旧RemoveMixer時刻ms + ",n旧RemoveMixer位置=" + n旧RemoveMixer位置 );
\r
2744 if ( pChip.n発声時刻ms - n発音前余裕ms <= n旧RemoveMixer時刻ms ) // mixer削除前に、同じ音の再発音がある場合は、
\r
2745 { // mixer削除時刻を遅延させる(if-else後に行う)
\r
2746 //Debug.WriteLine( "remove TAIL of listAddMixerChannel. TAIL INDEX=" + listAddMixerChannel.Count );
\r
2747 //DebugOut_CChipList( listAddMixerChannel );
\r
2748 listAddMixerChannel.RemoveAt( listAddMixerChannel.Count - 1 ); // また、同じチップ音の「mixerへの再追加」は削除する
\r
2749 //Debug.WriteLine( "removed result:" );
\r
2750 //DebugOut_CChipList( listAddMixerChannel );
\r
2752 else // 逆に、時間軸上、mixer削除後に再発音するような流れの場合は
\r
2754 //Debug.WriteLine( "Publish the value(listRemoveTiming[index] to listRemoveMixerChannel." );
\r
2755 listRemoveMixerChannel.Add( listRemoveTiming[ index ] ); // mixer削除を確定させる
\r
2756 //Debug.WriteLine( "listRemoveMixerChannel:" );
\r
2757 //DebugOut_CChipList( listRemoveMixerChannel );
\r
2758 //listRemoveTiming.RemoveAt( index );
\r
2760 CChip c = new CChip() // mixer削除時刻を更新(遅延)する
\r
2763 n整数値 = listRemoveTiming[ index ].n整数値,
\r
2764 n整数値・内部番号 = listRemoveTiming[ index ].n整数値・内部番号,
\r
2765 n発声時刻ms = n新RemoveMixer時刻ms,
\r
2766 n発声位置 = n新RemoveMixer位置
\r
2768 listRemoveTiming[ index ] = c;
\r
2769 //listRemoveTiming[ index ].n発声時刻ms = n新RemoveMixer時刻ms; // mixer削除時刻を更新(遅延)する
\r
2770 //listRemoveTiming[ index ].n発声位置 = n新RemoveMixer位置;
\r
2771 //Debug.WriteLine( "listRemoveTiming: modified" );
\r
2772 //DebugOut_CChipList( listRemoveTiming );
\r
2774 else // 過去に同じチップを発音していないor
\r
2775 { // 発音していたが既にmixer削除確定していたなら
\r
2776 CChip c = new CChip() // 新しくmixer削除候補として追加する
\r
2779 n整数値 = pChip.n整数値,
\r
2780 n整数値・内部番号 = pChip.n整数値・内部番号,
\r
2781 n発声時刻ms = n新RemoveMixer時刻ms,
\r
2782 n発声位置 = n新RemoveMixer位置
\r
2784 //Debug.WriteLine( "Add new chip to listRemoveMixerTiming: " );
\r
2785 //Debug.WriteLine( "ch=" + c.nチャンネル番号.ToString( "x2" ) + ", nWAV番号=" + c.n整数値 + ", time=" + c.n発声時刻ms + ", lasttime=" + listChip[ listChip.Count - 1 ].n発声時刻ms );
\r
2786 listRemoveTiming.Add( c );
\r
2787 //Debug.WriteLine( "listRemoveTiming:" );
\r
2788 //DebugOut_CChipList( listRemoveTiming );
\r
2794 //Debug.WriteLine("==================================================================");
\r
2795 //Debug.WriteLine( "Result:" );
\r
2796 //Debug.WriteLine( "listAddMixerChannel:" );
\r
2797 //DebugOut_CChipList( listAddMixerChannel );
\r
2798 //Debug.WriteLine( "listRemoveMixerChannel:" );
\r
2799 //DebugOut_CChipList( listRemoveMixerChannel );
\r
2800 //Debug.WriteLine( "listRemoveTiming:" );
\r
2801 //DebugOut_CChipList( listRemoveTiming );
\r
2802 //Debug.WriteLine( "==================================================================" );
\r
2804 listChip.AddRange( listAddMixerChannel );
\r
2805 listChip.AddRange( listRemoveMixerChannel );
\r
2806 listChip.AddRange( listRemoveTiming );
\r
2809 private void DebugOut_CChipList( List<CChip> c )
\r
2811 //Debug.WriteLine( "Count=" + c.Count );
\r
2812 for ( int i = 0; i < c.Count; i++ )
\r
2814 Debug.WriteLine( i + ": ch=" + c[ i ].nチャンネル番号.ToString("x2") + ", WAV番号=" + c[ i ].n整数値 + ", time=" + c[ i ].n発声時刻ms );
\r
2817 private bool t発声時刻msと発声位置を取得する( int n希望発声時刻ms, out int n新発声時刻ms, out int n新発声位置 )
\r
2819 // 発声時刻msから発声位置を逆算することはできないため、近似計算する。
\r
2820 // 具体的には、希望発声位置前後の2つのチップの発声位置の中間を取る。
\r
2822 if ( n希望発声時刻ms < 0 )
\r
2826 //else if ( n希望発声時刻ms > listChip[ listChip.Count - 1 ].n発声時刻ms ) // BGMの最後の余韻を殺してしまうので、この条件は外す
\r
2828 // n希望発声時刻ms = listChip[ listChip.Count - 1 ].n発声時刻ms;
\r
2831 int index_min = -1, index_max = -1;
\r
2832 for ( int i = 0; i < listChip.Count; i++ ) // 希望発声位置前後の「前」の方のチップを検索
\r
2834 if ( listChip[ i ].n発声時刻ms >= n希望発声時刻ms )
\r
2840 if ( index_min < 0 ) // 希望発声時刻に至らずに曲が終了してしまう場合
\r
2842 // listの最終項目の時刻をそのまま使用する
\r
2843 //・・・のではダメ。BGMが尻切れになる。
\r
2844 // そこで、listの最終項目の発声時刻msと発生位置から、希望発声時刻に相当する希望発声位置を比例計算して求める。
\r
2845 //n新発声時刻ms = n希望発声時刻ms;
\r
2846 //n新発声位置 = listChip[ listChip.Count - 1 ].n発声位置 * n希望発声時刻ms / listChip[ listChip.Count - 1 ].n発声時刻ms;
\r
2847 n新発声時刻ms = listChip[ listChip.Count - 1 ].n発声時刻ms;
\r
2848 n新発声位置 = listChip[ listChip.Count - 1 ].n発声位置;
\r
2851 index_max = index_min + 1;
\r
2852 if ( index_max >= listChip.Count )
\r
2854 index_max = index_min;
\r
2856 n新発声時刻ms = ( listChip[ index_max ].n発声時刻ms + listChip[ index_min ].n発声時刻ms ) / 2;
\r
2857 n新発声位置 = ( listChip[ index_max ].n発声位置 + listChip[ index_min ].n発声位置 ) / 2;
\r
2864 /// Swap infos between Guitar and Bass (notes, level, n可視チップ数, bチップがある)
\r
2866 public void SwapGuitarBassInfos() // #24063 2011.1.24 yyagi ギターとベースの譜面情報入替
\r
2868 for (int i = this.listChip.Count - 1; i >= 0; i--) {
\r
2869 if (listChip[i].e楽器パート == E楽器パート.BASS) {
\r
2870 listChip[i].e楽器パート = E楽器パート.GUITAR;
\r
2871 listChip[i].nチャンネル番号 -= ( 0xA0 - 0x20 );
\r
2873 else if ( listChip[i].e楽器パート == E楽器パート.GUITAR )
\r
2875 listChip[i].e楽器パート = E楽器パート.BASS;
\r
2876 listChip[i].nチャンネル番号 += ( 0xA0 - 0x20 );
\r
2878 else if ( listChip[ i ].nチャンネル番号 == 0x28 ) // #25215 2011.5.21 yyagi wailingはE楽器パート.UNKNOWNが割り当てられているので個別に対応
\r
2880 listChip[ i ].nチャンネル番号 += ( 0xA0 - 0x20 );
\r
2882 else if ( listChip[ i ].nチャンネル番号 == 0xA8 ) // #25215 2011.5.21 yyagi wailingはE楽器パート.UNKNOWNが割り当てられているので個別に対応
\r
2884 listChip[ i ].nチャンネル番号 -= ( 0xA0 - 0x20 );
\r
2887 int t = this.LEVEL.Bass;
\r
2888 this.LEVEL.Bass = this.LEVEL.Guitar;
\r
2889 this.LEVEL.Guitar = t;
\r
2891 t = this.n可視チップ数.Bass;
\r
2892 this.n可視チップ数.Bass = this.n可視チップ数.Guitar;
\r
2893 this.n可視チップ数.Guitar = t;
\r
2895 bool ts = this.bチップがある.Bass;
\r
2896 this.bチップがある.Bass = this.bチップがある.Guitar;
\r
2897 this.bチップがある.Guitar = ts;
\r
2899 // SwapGuitarBassInfos_AutoFlags();
\r
2902 // SwapGuitarBassInfos_AutoFlags()は、CDTXからCConfigIniに移動。
\r
2906 public override void On活性化()
\r
2908 this.listWAV = new Dictionary<int, CWAV>();
\r
2909 this.listBMP = new Dictionary<int, CBMP>();
\r
2910 this.listBMPTEX = new Dictionary<int, CBMPTEX>();
\r
2911 this.listBPM = new Dictionary<int, CBPM>();
\r
2912 this.listBGAPAN = new Dictionary<int, CBGAPAN>();
\r
2913 this.listBGA = new Dictionary<int, CBGA>();
\r
2914 this.listAVIPAN = new Dictionary<int, CAVIPAN>();
\r
2915 this.listAVI = new Dictionary<int, CAVI>();
\r
2916 this.listChip = new List<CChip>();
\r
2919 public override void On非活性化()
\r
2921 if( this.listWAV != null )
\r
2923 foreach( CWAV cwav in this.listWAV.Values )
\r
2927 this.listWAV = null;
\r
2929 if( this.listBMP != null )
\r
2931 foreach( CBMP cbmp in this.listBMP.Values )
\r
2935 this.listBMP = null;
\r
2937 if( this.listBMPTEX != null )
\r
2939 foreach( CBMPTEX cbmptex in this.listBMPTEX.Values )
\r
2941 cbmptex.Dispose();
\r
2943 this.listBMPTEX = null;
\r
2945 if( this.listAVI != null )
\r
2947 foreach( CAVI cavi in this.listAVI.Values )
\r
2951 this.listAVI = null;
\r
2953 if( this.listBPM != null )
\r
2955 this.listBPM.Clear();
\r
2956 this.listBPM = null;
\r
2958 if( this.listBGAPAN != null )
\r
2960 this.listBGAPAN.Clear();
\r
2961 this.listBGAPAN = null;
\r
2963 if( this.listBGA != null )
\r
2965 this.listBGA.Clear();
\r
2966 this.listBGA = null;
\r
2968 if( this.listAVIPAN != null )
\r
2970 this.listAVIPAN.Clear();
\r
2971 this.listAVIPAN = null;
\r
2973 if( this.listChip != null )
\r
2975 this.listChip.Clear();
\r
2979 public override void OnManagedリソースの作成()
\r
2981 if( !base.b活性化してない )
\r
2983 this.tBMP_BMPTEXの読み込み();
\r
2985 base.OnManagedリソースの作成();
\r
2988 public override void OnManagedリソースの解放()
\r
2990 if( !base.b活性化してない )
\r
2992 if( this.listBMP != null )
\r
2994 foreach( CBMP cbmp in this.listBMP.Values )
\r
2999 if( this.listBMPTEX != null )
\r
3001 foreach( CBMPTEX cbmptex in this.listBMPTEX.Values )
\r
3003 cbmptex.Dispose();
\r
3006 if( this.listAVI != null )
\r
3008 foreach( CAVI cavi in this.listAVI.Values )
\r
3013 base.OnManagedリソースの解放();
\r
3020 #region [ private ]
\r
3021 //-----------------
\r
3023 /// <para>GDAチャンネル番号に対応するDTXチャンネル番号。</para>
\r
3025 [StructLayout( LayoutKind.Sequential )]
\r
3026 private struct STGDAPARAM
\r
3028 public string strGDAのチャンネル文字列;
\r
3029 public int nDTXのチャンネル番号;
\r
3031 public STGDAPARAM( string strGDAのチャンネル文字列, int nDTXのチャンネル番号 ) // 2011.1.1 yyagi 構造体のコンストラクタ追加(初期化簡易化のため)
\r
3033 this.strGDAのチャンネル文字列 = strGDAのチャンネル文字列;
\r
3034 this.nDTXのチャンネル番号 = nDTXのチャンネル番号;
\r
3038 private readonly STGDAPARAM[] stGDAParam;
\r
3039 private bool bヘッダのみ;
\r
3040 private Stack<bool> bstackIFからENDIFをスキップする;
\r
3042 private int n現在の行数;
\r
3043 private int n現在の乱数;
\r
3045 private int nPolyphonicSounds = 4; // #28228 2012.5.1 yyagi
\r
3047 private int n内部番号BPM1to;
\r
3048 private int n内部番号WAV1to;
\r
3049 private int[] n無限管理BPM;
\r
3050 private int[] n無限管理PAN;
\r
3051 private int[] n無限管理SIZE;
\r
3052 private int[] n無限管理VOL;
\r
3053 private int[] n無限管理WAV;
\r
3054 private int[] nRESULTIMAGE用優先順位;
\r
3055 private int[] nRESULTMOVIE用優先順位;
\r
3056 private int[] nRESULTSOUND用優先順位;
\r
3058 private bool t入力・コマンド文字列を抜き出す( ref CharEnumerator ce, ref StringBuilder sb文字列 )
\r
3060 if( !this.t入力・空白をスキップする( ref ce ) )
\r
3061 return false; // 文字が尽きた
\r
3063 #region [ コマンド終端文字(':')、半角空白、コメント開始文字(';')、改行のいずれかが出現するまでをコマンド文字列と見なし、sb文字列 にコピーする。]
\r
3064 //-----------------
\r
3065 while( ce.Current != ':' && ce.Current != ' ' && ce.Current != ';' && ce.Current != '\n' )
\r
3067 sb文字列.Append( ce.Current );
\r
3069 if( !ce.MoveNext() )
\r
3070 return false; // 文字が尽きた
\r
3072 //-----------------
\r
3075 #region [ コマンド終端文字(':')で終端したなら、その次から空白をスキップしておく。]
\r
3076 //-----------------
\r
3077 if( ce.Current == ':' )
\r
3079 if( !ce.MoveNext() )
\r
3080 return false; // 文字が尽きた
\r
3082 if( !this.t入力・空白をスキップする( ref ce ) )
\r
3083 return false; // 文字が尽きた
\r
3085 //-----------------
\r
3090 private bool t入力・コメントをスキップする( ref CharEnumerator ce )
\r
3092 // 改行が現れるまでをコメントと見なしてスキップする。
\r
3094 while( ce.Current != '\n' )
\r
3096 if( !ce.MoveNext() )
\r
3097 return false; // 文字が尽きた
\r
3100 // 改行の次の文字へ移動した結果を返す。
\r
3102 return ce.MoveNext();
\r
3104 private bool t入力・コメント文字列を抜き出す( ref CharEnumerator ce, ref StringBuilder sb文字列 )
\r
3106 if( ce.Current != ';' ) // コメント開始文字(';')じゃなければ正常帰還。
\r
3109 if( !ce.MoveNext() ) // ';' の次で文字列が終わってたら終了帰還。
\r
3112 #region [ ';' の次の文字から '\n' の1つ前までをコメント文字列と見なし、sb文字列にコピーする。]
\r
3113 //-----------------
\r
3114 while( ce.Current != '\n' )
\r
3116 sb文字列.Append( ce.Current );
\r
3118 if( !ce.MoveNext() )
\r
3121 //-----------------
\r
3126 private void t入力・パラメータ食い込みチェック( string strコマンド名, ref string strコマンド, ref string strパラメータ )
\r
3128 if( ( strコマンド.Length > strコマンド名.Length ) && strコマンド.StartsWith( strコマンド名, StringComparison.OrdinalIgnoreCase ) )
\r
3130 strパラメータ = strコマンド.Substring( strコマンド名.Length ).Trim();
\r
3131 strコマンド = strコマンド.Substring( 0, strコマンド名.Length );
\r
3134 private bool t入力・パラメータ文字列を抜き出す( ref CharEnumerator ce, ref StringBuilder sb文字列 )
\r
3136 if( !this.t入力・空白をスキップする( ref ce ) )
\r
3137 return false; // 文字が尽きた
\r
3139 #region [ 改行またはコメント開始文字(';')が出現するまでをパラメータ文字列と見なし、sb文字列 にコピーする。]
\r
3140 //-----------------
\r
3141 while( ce.Current != '\n' && ce.Current != ';' )
\r
3143 sb文字列.Append( ce.Current );
\r
3145 if( !ce.MoveNext() )
\r
3148 //-----------------
\r
3153 private bool t入力・空白と改行をスキップする( ref CharEnumerator ce )
\r
3155 // 空白と改行が続く間はこれらをスキップする。
\r
3157 while( ce.Current == ' ' || ce.Current == '\n' )
\r
3159 if( ce.Current == '\n' )
\r
3160 this.n現在の行数++; // 改行文字では行番号が増える。
\r
3162 if( !ce.MoveNext() )
\r
3163 return false; // 文字が尽きた
\r
3168 private bool t入力・空白をスキップする( ref CharEnumerator ce )
\r
3170 // 空白が続く間はこれをスキップする。
\r
3172 while( ce.Current == ' ' )
\r
3174 if( !ce.MoveNext() )
\r
3175 return false; // 文字が尽きた
\r
3180 private void t入力・行解析( ref StringBuilder sbコマンド, ref StringBuilder sbパラメータ, ref StringBuilder sbコメント )
\r
3182 string strコマンド = sbコマンド.ToString();
\r
3183 string strパラメータ = sbパラメータ.ToString().Trim();
\r
3184 string strコメント = sbコメント.ToString();
\r
3189 //-----------------
\r
3190 if( strコマンド.StartsWith( "IF", StringComparison.OrdinalIgnoreCase ) )
\r
3192 this.t入力・パラメータ食い込みチェック( "IF", ref strコマンド, ref strパラメータ );
\r
3194 if( this.bstackIFからENDIFをスキップする.Count == 255 )
\r
3196 Trace.TraceWarning( "#IF の入れ子の数が 255 を超えました。この #IF を無視します。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数 );
\r
3198 else if( this.bstackIFからENDIFをスキップする.Peek() )
\r
3200 this.bstackIFからENDIFをスキップする.Push( true ); // 親が true ならその入れ子も問答無用で true 。
\r
3202 else // 親が false なら入れ子はパラメータと乱数を比較して結果を判断する。
\r
3206 if( !int.TryParse( strパラメータ, out n数値 ) )
\r
3209 this.bstackIFからENDIFをスキップする.Push( n数値 != this.n現在の乱数 ); // 乱数と数値が一致したら true 。
\r
3212 //-----------------
\r
3215 //-----------------
\r
3216 else if( strコマンド.StartsWith( "ENDIF", StringComparison.OrdinalIgnoreCase ) )
\r
3218 this.t入力・パラメータ食い込みチェック( "ENDIF", ref strコマンド, ref strパラメータ );
\r
3220 if( this.bstackIFからENDIFをスキップする.Count > 1 )
\r
3222 this.bstackIFからENDIFをスキップする.Pop(); // 入れ子を1つ脱出。
\r
3226 Trace.TraceWarning( "#ENDIF に対応する #IF がありません。この #ENDIF を無視します。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数 );
\r
3229 //-----------------
\r
3232 else if( !this.bstackIFからENDIFをスキップする.Peek() ) // IF~ENDIF をスキップするなら以下はすべて無視。
\r
3234 #region [ PATH_WAV ]
\r
3235 //-----------------
\r
3236 if( strコマンド.StartsWith( "PATH_WAV", StringComparison.OrdinalIgnoreCase ) )
\r
3238 this.t入力・パラメータ食い込みチェック( "PATH_WAV", ref strコマンド, ref strパラメータ );
\r
3239 this.PATH_WAV = strパラメータ;
\r
3241 //-----------------
\r
3244 //-----------------
\r
3245 else if( strコマンド.StartsWith( "TITLE", StringComparison.OrdinalIgnoreCase ) )
\r
3247 this.t入力・パラメータ食い込みチェック( "TITLE", ref strコマンド, ref strパラメータ );
\r
3248 this.TITLE = strパラメータ;
\r
3250 //-----------------
\r
3252 #region [ ARTIST ]
\r
3253 //-----------------
\r
3254 else if( strコマンド.StartsWith( "ARTIST", StringComparison.OrdinalIgnoreCase ) )
\r
3256 this.t入力・パラメータ食い込みチェック( "ARTIST", ref strコマンド, ref strパラメータ );
\r
3257 this.ARTIST = strパラメータ;
\r
3259 //-----------------
\r
3261 #region [ COMMENT ]
\r
3262 //-----------------
\r
3263 else if( strコマンド.StartsWith( "COMMENT", StringComparison.OrdinalIgnoreCase ) )
\r
3265 this.t入力・パラメータ食い込みチェック( "COMMENT", ref strコマンド, ref strパラメータ );
\r
3266 this.COMMENT = strパラメータ;
\r
3268 //-----------------
\r
3270 #region [ DLEVEL, PLAYLEVEL ]
\r
3271 //-----------------
\r
3273 strコマンド.StartsWith( "DLEVEL", StringComparison.OrdinalIgnoreCase ) ||
\r
3274 strコマンド.StartsWith( "PLAYLEVEL", StringComparison.OrdinalIgnoreCase ) )
\r
3276 this.t入力・パラメータ食い込みチェック( "DLEVEL", ref strコマンド, ref strパラメータ );
\r
3277 this.t入力・パラメータ食い込みチェック( "PLAYLEVEL", ref strコマンド, ref strパラメータ );
\r
3280 if( int.TryParse( strパラメータ, out dlevel ) )
\r
3282 this.LEVEL.Drums = Math.Min( Math.Max( dlevel, 0 ), 100 ); // 0~100 に丸める
\r
3285 //-----------------
\r
3287 #region [ GLEVEL ]
\r
3288 //-----------------
\r
3289 else if( strコマンド.StartsWith( "GLEVEL", StringComparison.OrdinalIgnoreCase ) )
\r
3291 this.t入力・パラメータ食い込みチェック( "GLEVEL", ref strコマンド, ref strパラメータ );
\r
3294 if( int.TryParse( strパラメータ, out glevel ) )
\r
3296 this.LEVEL.Guitar = Math.Min( Math.Max( glevel, 0 ), 100 ); // 0~100 に丸める
\r
3299 //-----------------
\r
3301 #region [ BLEVEL ]
\r
3302 //-----------------
\r
3303 else if( strコマンド.StartsWith( "BLEVEL", StringComparison.OrdinalIgnoreCase ) )
\r
3305 this.t入力・パラメータ食い込みチェック( "BLEVEL", ref strコマンド, ref strパラメータ );
\r
3308 if( int.TryParse( strパラメータ, out blevel ) )
\r
3310 this.LEVEL.Bass = Math.Min( Math.Max( blevel, 0 ), 100 ); // 0~100 に丸める
\r
3313 //-----------------
\r
3315 #if TEST_NOTEOFFMODE
\r
3316 else if (str.StartsWith("SUPRESSNOTEOFF_HIHAT", StringComparison.OrdinalIgnoreCase)) {
\r
3317 this.t入力・パラメータ食い込みチェック("SUPRESSNOTEOFF_HIHAT", ref str, ref str2);
\r
3318 this.bHH演奏で直前のHHを消音する = !str2.ToLower().Equals("on");
\r
3320 else if (str.StartsWith("SUPRESSNOTEOFF_GUITAR", StringComparison.OrdinalIgnoreCase)) {
\r
3321 this.t入力・パラメータ食い込みチェック("SUPRESSNOTEOFF_GUITAR", ref str, ref str2);
\r
3322 this.bGUITAR演奏で直前のGUITARを消音する = !str2.ToLower().Equals("on");
\r
3324 else if (str.StartsWith("SUPRESSNOTEOFF_BASS", StringComparison.OrdinalIgnoreCase)) {
\r
3325 this.t入力・パラメータ食い込みチェック("SUPRESSNOTEOFF_BASS", ref str, ref str2);
\r
3326 this.bBASS演奏で直前のBASSを消音する = !str2.ToLower().Equals("on");
\r
3330 //-----------------
\r
3331 else if( strコマンド.StartsWith( "GENRE", StringComparison.OrdinalIgnoreCase ) )
\r
3333 this.t入力・パラメータ食い込みチェック( "GENRE", ref strコマンド, ref strパラメータ );
\r
3334 this.GENRE = strパラメータ;
\r
3336 //-----------------
\r
3338 #region [ HIDDENLEVEL ]
\r
3339 //-----------------
\r
3340 else if( strコマンド.StartsWith( "HIDDENLEVEL", StringComparison.OrdinalIgnoreCase ) )
\r
3342 this.t入力・パラメータ食い込みチェック( "HIDDENLEVEL", ref strコマンド, ref strパラメータ );
\r
3343 this.HIDDENLEVEL = strパラメータ.ToLower().Equals( "on" );
\r
3345 //-----------------
\r
3347 #region [ STAGEFILE ]
\r
3348 //-----------------
\r
3349 else if( strコマンド.StartsWith( "STAGEFILE", StringComparison.OrdinalIgnoreCase ) )
\r
3351 this.t入力・パラメータ食い込みチェック( "STAGEFILE", ref strコマンド, ref strパラメータ );
\r
3352 this.STAGEFILE = strパラメータ;
\r
3354 //-----------------
\r
3356 #region [ PREVIEW ]
\r
3357 //-----------------
\r
3358 else if( strコマンド.StartsWith( "PREVIEW", StringComparison.OrdinalIgnoreCase ) )
\r
3360 this.t入力・パラメータ食い込みチェック( "PREVIEW", ref strコマンド, ref strパラメータ );
\r
3361 this.PREVIEW = strパラメータ;
\r
3363 //-----------------
\r
3365 #region [ PREIMAGE ]
\r
3366 //-----------------
\r
3367 else if( strコマンド.StartsWith( "PREIMAGE", StringComparison.OrdinalIgnoreCase ) )
\r
3369 this.t入力・パラメータ食い込みチェック( "PREIMAGE", ref strコマンド, ref strパラメータ );
\r
3370 this.PREIMAGE = strパラメータ;
\r
3372 //-----------------
\r
3374 #region [ PREMOVIE ]
\r
3375 //-----------------
\r
3376 else if( strコマンド.StartsWith( "PREMOVIE", StringComparison.OrdinalIgnoreCase ) )
\r
3378 this.t入力・パラメータ食い込みチェック( "PREMOVIE", ref strコマンド, ref strパラメータ );
\r
3379 this.PREMOVIE = strパラメータ;
\r
3381 //-----------------
\r
3383 #region [ BACKGROUND_GR ]
\r
3384 //-----------------
\r
3385 else if( strコマンド.StartsWith( "BACKGROUND_GR", StringComparison.OrdinalIgnoreCase ) )
\r
3387 this.t入力・パラメータ食い込みチェック( "BACKGROUND_GR", ref strコマンド, ref strパラメータ );
\r
3388 this.BACKGROUND_GR = strパラメータ;
\r
3390 //-----------------
\r
3392 #region [ BACKGROU}ND, WALL ]
\r
3393 //-----------------
\r
3395 strコマンド.StartsWith( "BACKGROUND", StringComparison.OrdinalIgnoreCase ) ||
\r
3396 strコマンド.StartsWith( "WALL", StringComparison.OrdinalIgnoreCase ) )
\r
3398 this.t入力・パラメータ食い込みチェック( "BACKGROUND", ref strコマンド, ref strパラメータ );
\r
3399 this.t入力・パラメータ食い込みチェック( "WALL", ref strコマンド, ref strパラメータ );
\r
3400 this.BACKGROUND = strパラメータ;
\r
3402 //-----------------
\r
3404 #region [ RANDOM ]
\r
3405 //-----------------
\r
3406 else if( strコマンド.StartsWith( "RANDOM", StringComparison.OrdinalIgnoreCase ) )
\r
3408 this.t入力・パラメータ食い込みチェック( "RANDOM", ref strコマンド, ref strパラメータ );
\r
3411 if( !int.TryParse( strパラメータ, out n数値 ) )
\r
3414 this.n現在の乱数 = CDTXMania.Random.Next( n数値 ) + 1; // 1~数値 までの乱数を生成。
\r
3416 //-----------------
\r
3418 #region [ SOUND_NOWLOADING ]
\r
3419 //-----------------
\r
3420 else if( strコマンド.StartsWith( "SOUND_NOWLOADING", StringComparison.OrdinalIgnoreCase ) )
\r
3422 this.t入力・パラメータ食い込みチェック( "SOUND_NOWLOADING", ref strコマンド, ref strパラメータ );
\r
3423 this.SOUND_NOWLOADING = strパラメータ;
\r
3425 //-----------------
\r
3428 //-----------------
\r
3429 else if( strコマンド.StartsWith( "BPM", StringComparison.OrdinalIgnoreCase ) )
\r
3431 this.t入力・行解析・BPM_BPMzz( strコマンド, strパラメータ, strコメント );
\r
3433 //-----------------
\r
3435 else if( !this.bヘッダのみ ) // ヘッダのみの解析の場合、以下は無視。
\r
3438 //-----------------
\r
3439 if( strコマンド.StartsWith( "PANEL", StringComparison.OrdinalIgnoreCase ) )
\r
3441 this.t入力・パラメータ食い込みチェック( "PANEL", ref strコマンド, ref strパラメータ );
\r
3443 int dummyResult; // #23885 2010.12.12 yyagi: not to confuse "#PANEL strings (panel)" and "#PANEL int (panpot of EL)"
\r
3444 if( !int.TryParse( strパラメータ, out dummyResult ) )
\r
3445 { // 数値じゃないならPANELとみなす
\r
3446 this.PANEL = strパラメータ; //
\r
3448 } // 数値ならPAN ELとみなす
\r
3451 //-----------------
\r
3453 #region [ MIDIFILE ]
\r
3454 //-----------------
\r
3455 else if( strコマンド.StartsWith( "MIDIFILE", StringComparison.OrdinalIgnoreCase ) )
\r
3457 this.t入力・パラメータ食い込みチェック( "MIDIFILE", ref strコマンド, ref strパラメータ );
\r
3458 this.MIDIFILE = strパラメータ;
\r
3460 //-----------------
\r
3462 #region [ MIDINOTE ]
\r
3463 //-----------------
\r
3464 else if( strコマンド.StartsWith( "MIDINOTE", StringComparison.OrdinalIgnoreCase ) )
\r
3466 this.t入力・パラメータ食い込みチェック( "MIDINOTE", ref strコマンド, ref strパラメータ );
\r
3467 this.MIDINOTE = strパラメータ.ToLower().Equals( "on" );
\r
3469 //-----------------
\r
3471 #region [ BLACKCOLORKEY ]
\r
3472 //-----------------
\r
3473 else if( strコマンド.StartsWith( "BLACKCOLORKEY", StringComparison.OrdinalIgnoreCase ) )
\r
3475 this.t入力・パラメータ食い込みチェック( "BLACKCOLORKEY", ref strコマンド, ref strパラメータ );
\r
3476 this.BLACKCOLORKEY = strパラメータ.ToLower().Equals( "on" );
\r
3478 //-----------------
\r
3480 #region [ BASEBPM ]
\r
3481 //-----------------
\r
3482 else if( strコマンド.StartsWith( "BASEBPM", StringComparison.OrdinalIgnoreCase ) )
\r
3484 this.t入力・パラメータ食い込みチェック( "BASEBPM", ref strコマンド, ref strパラメータ );
\r
3486 double basebpm = 0.0;
\r
3487 //if( double.TryParse( str2, out num6 ) && ( num6 > 0.0 ) )
\r
3488 if( TryParse( strパラメータ, out basebpm ) && basebpm > 0.0 ) // #23880 2010.12.30 yyagi: alternative TryParse to permit both '.' and ',' for decimal point
\r
3489 { // #24204 2011.01.21 yyagi: Fix the condition correctly
\r
3490 this.BASEBPM = basebpm;
\r
3493 //-----------------
\r
3495 #region [ SOUND_STAGEFAILED ]
\r
3496 //-----------------
\r
3497 else if( strコマンド.StartsWith( "SOUND_STAGEFAILED", StringComparison.OrdinalIgnoreCase ) )
\r
3499 this.t入力・パラメータ食い込みチェック( "SOUND_STAGEFAILED", ref strコマンド, ref strパラメータ );
\r
3500 this.SOUND_STAGEFAILED = strパラメータ;
\r
3502 //-----------------
\r
3504 #region [ SOUND_FULLCOMBO ]
\r
3505 //-----------------
\r
3506 else if( strコマンド.StartsWith( "SOUND_FULLCOMBO", StringComparison.OrdinalIgnoreCase ) )
\r
3508 this.t入力・パラメータ食い込みチェック( "SOUND_FULLCOMBO", ref strコマンド, ref strパラメータ );
\r
3509 this.SOUND_FULLCOMBO = strパラメータ;
\r
3511 //-----------------
\r
3513 #region [ SOUND_AUDIENCE ]
\r
3514 //-----------------
\r
3515 else if( strコマンド.StartsWith( "SOUND_AUDIENCE", StringComparison.OrdinalIgnoreCase ) )
\r
3517 this.t入力・パラメータ食い込みチェック( "SOUND_AUDIENCE", ref strコマンド, ref strパラメータ );
\r
3518 this.SOUND_AUDIENCE = strパラメータ;
\r
3520 //-----------------
\r
3522 #region [ DTXVPLAYSPEED ]
\r
3523 //-----------------
\r
3524 else if ( strコマンド.StartsWith( "DTXVPLAYSPEED", StringComparison.OrdinalIgnoreCase ) )
\r
3526 this.t入力・パラメータ食い込みチェック( "DTXVPLAYSPEED", ref strコマンド, ref strパラメータ );
\r
3528 double dtxvplayspeed = 0.0;
\r
3529 if ( TryParse( strパラメータ, out dtxvplayspeed ) && dtxvplayspeed > 0.0 )
\r
3531 this.dbDTXVPlaySpeed = dtxvplayspeed;
\r
3534 //-----------------
\r
3536 // オブジェクト記述コマンドの処理。
\r
3538 else if( !this.t入力・行解析・WAVVOL_VOLUME( strコマンド, strパラメータ, strコメント ) &&
\r
3539 !this.t入力・行解析・WAVPAN_PAN( strコマンド, strパラメータ, strコメント ) &&
\r
3540 !this.t入力・行解析・WAV( strコマンド, strパラメータ, strコメント ) &&
\r
3541 !this.t入力・行解析・BMPTEX( strコマンド, strパラメータ, strコメント ) &&
\r
3542 !this.t入力・行解析・BMP( strコマンド, strパラメータ, strコメント ) &&
\r
3543 !this.t入力・行解析・BGAPAN( strコマンド, strパラメータ, strコメント ) &&
\r
3544 !this.t入力・行解析・BGA( strコマンド, strパラメータ, strコメント ) &&
\r
3545 !this.t入力・行解析・AVIPAN( strコマンド, strパラメータ, strコメント ) &&
\r
3546 !this.t入力・行解析・AVI_VIDEO( strコマンド, strパラメータ, strコメント ) &&
\r
3547 // !this.t入力・行解析・BPM_BPMzz( strコマンド, strパラメータ, strコメント ) && // bヘッダのみ==trueの場合でもチェックするよう変更
\r
3548 !this.t入力・行解析・RESULTIMAGE( strコマンド, strパラメータ, strコメント ) &&
\r
3549 !this.t入力・行解析・RESULTMOVIE( strコマンド, strパラメータ, strコメント ) &&
\r
3550 !this.t入力・行解析・RESULTSOUND( strコマンド, strパラメータ, strコメント ) &&
\r
3551 !this.t入力・行解析・SIZE( strコマンド, strパラメータ, strコメント ) )
\r
3553 this.t入力・行解析・チップ配置( strコマンド, strパラメータ, strコメント );
\r
3556 Debug.Assert( true ); // #23885 2010.12.12 yyagi: dummy line to exit parsing the line
\r
3557 // 2011.8.17 from: "int xx=0;" から変更。毎回警告が出るので。
\r
3560 //{ // Duration測定のため、bヘッダのみ==trueでも、チップ配置は行う
\r
3561 // this.t入力・行解析・チップ配置( strコマンド, strパラメータ, strコメント );
\r
3565 private bool t入力・行解析・AVI_VIDEO( string strコマンド, string strパラメータ, string strコメント )
\r
3569 #region [ "AVI" or "VIDEO" で始まらないコマンドは無効。]
\r
3570 //-----------------
\r
3571 if( strコマンド.StartsWith( "AVI", StringComparison.OrdinalIgnoreCase ) )
\r
3572 strコマンド = strコマンド.Substring( 3 ); // strコマンド から先頭の"AVI"文字を除去。
\r
3574 else if( strコマンド.StartsWith( "VIDEO", StringComparison.OrdinalIgnoreCase ) )
\r
3575 strコマンド = strコマンド.Substring( 5 ); // strコマンド から先頭の"VIDEO"文字を除去。
\r
3579 //-----------------
\r
3584 if( strコマンド.Length < 2 )
\r
3585 return false; // AVI番号 zz がないなら無効。
\r
3587 #region [ AVI番号 zz を取得する。]
\r
3588 //-----------------
\r
3589 int zz = C変換.n36進数2桁の文字列を数値に変換して返す( strコマンド.Substring( 0, 2 ) );
\r
3590 if( zz < 0 || zz >= 36 * 36 )
\r
3592 Trace.TraceError( "AVI(VIDEO)番号に 00~ZZ 以外の値または不正な文字列が指定されました。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数 );
\r
3595 //-----------------
\r
3598 #region [ AVIリストに {zz, avi} の組を登録する。 ]
\r
3599 //-----------------
\r
3600 var avi = new CAVI() {
\r
3602 strファイル名 = strパラメータ,
\r
3603 strコメント文 = strコメント,
\r
3606 if( this.listAVI.ContainsKey( zz ) ) // 既にリスト中に存在しているなら削除。後のものが有効。
\r
3607 this.listAVI.Remove( zz );
\r
3609 this.listAVI.Add( zz, avi );
\r
3610 //-----------------
\r
3615 private bool t入力・行解析・AVIPAN( string strコマンド, string strパラメータ, string strコメント )
\r
3619 #region [ "AVIPAN" で始まらないコマンドは無効。]
\r
3620 //-----------------
\r
3621 if( !strコマンド.StartsWith( "AVIPAN", StringComparison.OrdinalIgnoreCase ) )
\r
3624 strコマンド = strコマンド.Substring( 6 ); // strコマンド から先頭の"AVIPAN"文字を除去。
\r
3625 //-----------------
\r
3630 if( strコマンド.Length < 2 )
\r
3631 return false; // AVIPAN番号 zz がないなら無効。
\r
3633 #region [ AVIPAN番号 zz を取得する。]
\r
3634 //-----------------
\r
3635 int zz = C変換.n36進数2桁の文字列を数値に変換して返す( strコマンド.Substring( 0, 2 ) );
\r
3636 if( zz < 0 || zz >= 36 * 36 )
\r
3638 Trace.TraceError( "AVIPAN番号に 00~ZZ 以外の値または不正な文字列が指定されました。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数 );
\r
3641 //-----------------
\r
3644 var avipan = new CAVIPAN() {
\r
3648 // パラメータ引数(14個)を取得し、avipan に登録していく。
\r
3650 string[] strParams = strパラメータ.Split( new char[] { ' ', ',', '(', ')', '[', ']', 'x', '|' }, StringSplitOptions.RemoveEmptyEntries );
\r
3652 #region [ パラメータ引数は全14個ないと無効。]
\r
3653 //-----------------
\r
3654 if( strParams.Length < 14 )
\r
3656 Trace.TraceError( "AVIPAN: 引数が足りません。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数 );
\r
3659 //-----------------
\r
3665 #region [ 1. AVI番号 ]
\r
3666 //-----------------
\r
3667 if( string.IsNullOrEmpty( strParams[ i ] ) || strParams[ i ].Length > 2 )
\r
3669 Trace.TraceError( "AVIPAN: {2}番目の数(AVI番号)が異常です。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数, i + 1 );
\r
3672 avipan.nAVI番号 = C変換.n36進数2桁の文字列を数値に変換して返す( strParams[ i ] );
\r
3673 if( avipan.nAVI番号 < 1 || avipan.nAVI番号 >= 36 * 36 )
\r
3675 Trace.TraceError( "AVIPAN: {2}番目の数(AVI番号)が異常です。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数, i + 1 );
\r
3679 //-----------------
\r
3681 #region [ 2. 開始転送サイズ・幅 ]
\r
3682 //-----------------
\r
3684 if( !int.TryParse( strParams[ i ], out n値 ) )
\r
3686 Trace.TraceError( "AVIPAN: {2}番目の引数(開始転送サイズ・幅)が異常です。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数, i + 1 );
\r
3689 avipan.sz開始サイズ.Width = n値;
\r
3691 //-----------------
\r
3693 #region [ 3. 転送サイズ・高さ ]
\r
3694 //-----------------
\r
3696 if( !int.TryParse( strParams[ i ], out n値 ) )
\r
3698 Trace.TraceError( "AVIPAN: {2}番目の引数(開始転送サイズ・高さ)が異常です。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数, i + 1 );
\r
3701 avipan.sz開始サイズ.Height = n値;
\r
3703 //-----------------
\r
3705 #region [ 4. 終了転送サイズ・幅 ]
\r
3706 //-----------------
\r
3708 if( !int.TryParse( strParams[ i ], out n値 ) )
\r
3710 Trace.TraceError( "AVIPAN: {2}番目の引数(終了転送サイズ・幅)が異常です。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数, i + 1 );
\r
3713 avipan.sz終了サイズ.Width = n値;
\r
3715 //-----------------
\r
3717 #region [ 5. 終了転送サイズ・高さ ]
\r
3718 //-----------------
\r
3720 if( !int.TryParse( strParams[ i ], out n値 ) )
\r
3722 Trace.TraceError( "AVIPAN: {2}番目の引数(終了転送サイズ・高さ)が異常です。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数, i + 1 );
\r
3725 avipan.sz終了サイズ.Height = n値;
\r
3727 //-----------------
\r
3729 #region [ 6. 動画側開始位置・X ]
\r
3730 //-----------------
\r
3732 if( !int.TryParse( strParams[ i ], out n値 ) )
\r
3734 Trace.TraceError( "AVIPAN: {2}番目の引数(動画側開始位置・X)が異常です。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数, i + 1 );
\r
3737 avipan.pt動画側開始位置.X = n値;
\r
3739 //-----------------
\r
3741 #region [ 7. 動画側開始位置・Y ]
\r
3742 //-----------------
\r
3744 if( !int.TryParse( strParams[ i ], out n値 ) )
\r
3746 Trace.TraceError( "AVIPAN: {2}番目の引数(動画側開始位置・Y)が異常です。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数, i + 1 );
\r
3749 avipan.pt動画側開始位置.Y = n値;
\r
3751 //-----------------
\r
3753 #region [ 8. 動画側終了位置・X ]
\r
3754 //-----------------
\r
3756 if( !int.TryParse( strParams[ i ], out n値 ) )
\r
3758 Trace.TraceError( "AVIPAN: {2}番目の引数(動画側終了位置・X)が異常です。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数, i + 1 );
\r
3761 avipan.pt動画側終了位置.X = n値;
\r
3763 //-----------------
\r
3765 #region [ 9. 動画側終了位置・Y ]
\r
3766 //-----------------
\r
3768 if( !int.TryParse( strParams[ i ], out n値 ) )
\r
3770 Trace.TraceError( "AVIPAN: {2}番目の引数(動画側終了位置・Y)が異常です。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数, i + 1 );
\r
3773 avipan.pt動画側終了位置.Y = n値;
\r
3775 //-----------------
\r
3777 #region [ 10.表示側開始位置・X ]
\r
3778 //-----------------
\r
3780 if( !int.TryParse( strParams[ i ], out n値 ) )
\r
3782 Trace.TraceError( "AVIPAN: {2}番目の引数(表示側開始位置・X)が異常です。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数, i + 1 );
\r
3785 avipan.pt表示側開始位置.X = n値;
\r
3787 //-----------------
\r
3789 #region [ 11.表示側開始位置・Y ]
\r
3790 //-----------------
\r
3792 if( !int.TryParse( strParams[ i ], out n値 ) )
\r
3794 Trace.TraceError( "AVIPAN: {2}番目の引数(表示側開始位置・Y)が異常です。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数, i + 1 );
\r
3797 avipan.pt表示側開始位置.Y = n値;
\r
3799 //-----------------
\r
3801 #region [ 12.表示側終了位置・X ]
\r
3802 //-----------------
\r
3804 if( !int.TryParse( strParams[ i ], out n値 ) )
\r
3806 Trace.TraceError( "AVIPAN: {2}番目の引数(表示側終了位置・X)が異常です。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数, i + 1 );
\r
3809 avipan.pt表示側終了位置.X = n値;
\r
3811 //-----------------
\r
3813 #region [ 13.表示側終了位置・Y ]
\r
3814 //-----------------
\r
3816 if( !int.TryParse( strParams[ i ], out n値 ) )
\r
3818 Trace.TraceError( "AVIPAN: {2}番目の引数(表示側終了位置・Y)が異常です。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数, i + 1 );
\r
3821 avipan.pt表示側終了位置.Y = n値;
\r
3823 //-----------------
\r
3825 #region [ 14.移動時間 ]
\r
3826 //-----------------
\r
3828 if( !int.TryParse( strParams[ i ], out n値 ) )
\r
3830 Trace.TraceError( "AVIPAN: {2}番目の引数(移動時間)が異常です。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数, i + 1 );
\r
3837 avipan.n移動時間ct = n値;
\r
3839 //-----------------
\r
3842 #region [ AVIPANリストに {zz, avipan} の組を登録する。]
\r
3843 //-----------------
\r
3844 if( this.listAVIPAN.ContainsKey( zz ) ) // 既にリスト中に存在しているなら削除。後のものが有効。
\r
3845 this.listAVIPAN.Remove( zz );
\r
3847 this.listAVIPAN.Add( zz, avipan );
\r
3848 //-----------------
\r
3853 private bool t入力・行解析・BGA( string strコマンド, string strパラメータ, string strコメント )
\r
3857 #region [ "BGA" で始まらないコマンドは無効。]
\r
3858 //-----------------
\r
3859 if( !strコマンド.StartsWith( "BGA", StringComparison.OrdinalIgnoreCase ) )
\r
3862 strコマンド = strコマンド.Substring( 3 ); // strコマンド から先頭の"BGA"文字を除去。
\r
3863 //-----------------
\r
3868 if( strコマンド.Length < 2 )
\r
3869 return false; // BGA番号 zz がないなら無効。
\r
3871 #region [ BGA番号 zz を取得する。]
\r
3872 //-----------------
\r
3873 int zz = C変換.n36進数2桁の文字列を数値に変換して返す( strコマンド.Substring( 0, 2 ) );
\r
3874 if( zz < 0 || zz >= 36 * 36 )
\r
3876 Trace.TraceError( "BGA番号に 00~ZZ 以外の値または不正な文字列が指定されました。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数 );
\r
3879 //-----------------
\r
3882 var bga = new CBGA() {
\r
3886 // パラメータ引数(7個)を取得し、bga に登録していく。
\r
3888 string[] strParams = strパラメータ.Split( new char[] { ' ', ',', '(', ')', '[', ']', 'x', '|' }, StringSplitOptions.RemoveEmptyEntries );
\r
3890 #region [ パラメータ引数は全7個ないと無効。]
\r
3891 //-----------------
\r
3892 if( strParams.Length < 7 )
\r
3894 Trace.TraceError( "BGA: 引数が足りません。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数 );
\r
3897 //-----------------
\r
3903 #region [ 1.BMP番号 ]
\r
3904 //-----------------
\r
3905 if( string.IsNullOrEmpty( strParams[ i ] ) || strParams[ i ].Length > 2 )
\r
3907 Trace.TraceError( "BGA: {2}番目の数(BMP番号)が異常です。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数, i + 1 );
\r
3910 bga.nBMP番号 = C変換.n36進数2桁の文字列を数値に変換して返す( strParams[ i ] );
\r
3911 if( bga.nBMP番号 < 1 || bga.nBMP番号 >= 36 * 36 )
\r
3913 Trace.TraceError( "BGA: {2}番目の数(BMP番号)が異常です。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数, i + 1 );
\r
3917 //-----------------
\r
3919 #region [ 2.画像側位置1・X ]
\r
3920 //-----------------
\r
3922 if( !int.TryParse( strParams[ i ], out n値 ) )
\r
3924 Trace.TraceError( "BGA: {2}番目の引数(画像側位置1・X)が異常です。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数, i + 1 );
\r
3927 bga.pt画像側左上座標.X = n値;
\r
3929 //-----------------
\r
3931 #region [ 3.画像側位置1・Y ]
\r
3932 //-----------------
\r
3934 if( !int.TryParse( strParams[ i ], out n値 ) )
\r
3936 Trace.TraceError( "BGA: {2}番目の引数(画像側位置1・Y)が異常です。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数, i + 1 );
\r
3939 bga.pt画像側左上座標.Y = n値;
\r
3941 //-----------------
\r
3943 #region [ 4.画像側位置2・X ]
\r
3944 //-----------------
\r
3946 if( !int.TryParse( strParams[ i ], out n値 ) )
\r
3948 Trace.TraceError( "BGA: {2}番目の引数(画像側位置2・X)が異常です。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数, i + 1 );
\r
3951 bga.pt画像側右下座標.X = n値;
\r
3953 //-----------------
\r
3955 #region [ 5.画像側位置2・Y ]
\r
3956 //-----------------
\r
3958 if( !int.TryParse( strParams[ i ], out n値 ) )
\r
3960 Trace.TraceError( "BGA: {2}番目の引数(画像側座標2・Y)が異常です。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数, i + 1 );
\r
3963 bga.pt画像側右下座標.Y = n値;
\r
3965 //-----------------
\r
3967 #region [ 6.表示位置・X ]
\r
3968 //-----------------
\r
3970 if( !int.TryParse( strParams[ i ], out n値 ) )
\r
3972 Trace.TraceError( "BGA: {2}番目の引数(表示位置・X)が異常です。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数, i + 1 );
\r
3975 bga.pt表示座標.X = n値;
\r
3977 //-----------------
\r
3979 #region [ 7.表示位置・Y ]
\r
3980 //-----------------
\r
3982 if( !int.TryParse( strParams[ i ], out n値 ) )
\r
3984 Trace.TraceError( "BGA: {2}番目の引数(表示位置・Y)が異常です。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数, i + 1 );
\r
3987 bga.pt表示座標.Y = n値;
\r
3989 //-----------------
\r
3992 #region [ 画像側座標の正規化とクリッピング。]
\r
3993 //-----------------
\r
3994 if( bga.pt画像側左上座標.X > bga.pt画像側右下座標.X )
\r
3996 n値 = bga.pt画像側左上座標.X;
\r
3997 bga.pt画像側左上座標.X = bga.pt画像側右下座標.X;
\r
3998 bga.pt画像側右下座標.X = n値;
\r
4000 if( bga.pt画像側左上座標.Y > bga.pt画像側右下座標.Y )
\r
4002 n値 = bga.pt画像側左上座標.Y;
\r
4003 bga.pt画像側左上座標.Y = bga.pt画像側右下座標.Y;
\r
4004 bga.pt画像側右下座標.Y = n値;
\r
4006 //-----------------
\r
4008 #region [ BGAリストに {zz, bga} の組を登録する。]
\r
4009 //-----------------
\r
4010 if( this.listBGA.ContainsKey( zz ) ) // 既にリスト中に存在しているなら削除。後のものが有効。
\r
4011 this.listBGA.Remove( zz );
\r
4013 this.listBGA.Add( zz, bga );
\r
4014 //-----------------
\r
4019 private bool t入力・行解析・BGAPAN( string strコマンド, string strパラメータ, string strコメント )
\r
4023 #region [ "BGAPAN" で始まらないコマンドは無効。]
\r
4024 //-----------------
\r
4025 if( !strコマンド.StartsWith( "BGAPAN", StringComparison.OrdinalIgnoreCase ) )
\r
4028 strコマンド = strコマンド.Substring( 6 ); // strコマンド から先頭の"BGAPAN"文字を除去。
\r
4029 //-----------------
\r
4034 if( strコマンド.Length < 2 )
\r
4035 return false; // BGAPAN番号 zz がないなら無効。
\r
4037 #region [ BGAPAN番号 zz を取得する。]
\r
4038 //-----------------
\r
4039 int zz = C変換.n36進数2桁の文字列を数値に変換して返す( strコマンド.Substring( 0, 2 ) );
\r
4040 if( zz < 0 || zz >= 36 * 36 )
\r
4042 Trace.TraceError( "BGAPAN番号に 00~ZZ 以外の値または不正な文字列が指定されました。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数 );
\r
4045 //-----------------
\r
4048 var bgapan = new CBGAPAN() {
\r
4052 // パラメータ引数(14個)を取得し、bgapan に登録していく。
\r
4054 string[] strParams = strパラメータ.Split( new char[] { ' ', ',', '(', ')', '[', ']', 'x', '|' }, StringSplitOptions.RemoveEmptyEntries );
\r
4056 #region [ パラメータ引数は全14個ないと無効。]
\r
4057 //-----------------
\r
4058 if( strParams.Length < 14 )
\r
4060 Trace.TraceError( "BGAPAN: 引数が足りません。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数 );
\r
4063 //-----------------
\r
4069 #region [ 1. BMP番号 ]
\r
4070 //-----------------
\r
4071 if( string.IsNullOrEmpty( strParams[ i ] ) || strParams[ i ].Length > 2 )
\r
4073 Trace.TraceError( "BGAPAN: {2}番目の数(BMP番号)が異常です。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数, i + 1 );
\r
4076 bgapan.nBMP番号 = C変換.n36進数2桁の文字列を数値に変換して返す( strParams[ i ] );
\r
4077 if( bgapan.nBMP番号 < 1 || bgapan.nBMP番号 >= 36 * 36 )
\r
4079 Trace.TraceError( "BGAPAN: {2}番目の数(BMP番号)が異常です。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数, i + 1 );
\r
4083 //-----------------
\r
4085 #region [ 2. 開始転送サイズ・幅 ]
\r
4086 //-----------------
\r
4088 if( !int.TryParse( strParams[ i ], out n値 ) )
\r
4090 Trace.TraceError( "BGAPAN: {2}番目の引数(開始転送サイズ・幅)が異常です。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数, i + 1 );
\r
4093 bgapan.sz開始サイズ.Width = n値;
\r
4095 //-----------------
\r
4097 #region [ 3. 開始転送サイズ・高さ ]
\r
4098 //-----------------
\r
4100 if( !int.TryParse( strParams[ i ], out n値 ) )
\r
4102 Trace.TraceError( "BGAPAN: {2}番目の引数(開始転送サイズ・高さ)が異常です。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数, i + 1 );
\r
4105 bgapan.sz開始サイズ.Height = n値;
\r
4107 //-----------------
\r
4109 #region [ 4. 終了転送サイズ・幅 ]
\r
4110 //-----------------
\r
4112 if( !int.TryParse( strParams[ i ], out n値 ) )
\r
4114 Trace.TraceError( "BGAPAN: {2}番目の引数(終了転送サイズ・幅)が異常です。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数, i + 1 );
\r
4117 bgapan.sz終了サイズ.Width = n値;
\r
4119 //-----------------
\r
4121 #region [ 5. 終了転送サイズ・高さ ]
\r
4122 //-----------------
\r
4124 if( !int.TryParse( strParams[ i ], out n値 ) )
\r
4126 Trace.TraceError( "BGAPAN: {2}番目の引数(終了転送サイズ・高さ)が異常です。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数, i + 1 );
\r
4129 bgapan.sz終了サイズ.Height = n値;
\r
4131 //-----------------
\r
4133 #region [ 6. 画像側開始位置・X ]
\r
4134 //-----------------
\r
4136 if( !int.TryParse( strParams[ i ], out n値 ) )
\r
4138 Trace.TraceError( "BGAPAN: {2}番目の引数(画像側開始位置・X)が異常です。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数, i + 1 );
\r
4141 bgapan.pt画像側開始位置.X = n値;
\r
4143 //-----------------
\r
4145 #region [ 7. 画像側開始位置・Y ]
\r
4146 //-----------------
\r
4148 if( !int.TryParse( strParams[ i ], out n値 ) )
\r
4150 Trace.TraceError( "BGAPAN: {2}番目の引数(画像側開始位置・Y)が異常です。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数, i + 1 );
\r
4153 bgapan.pt画像側開始位置.Y = n値;
\r
4155 //-----------------
\r
4157 #region [ 8. 画像側終了位置・X ]
\r
4158 //-----------------
\r
4160 if( !int.TryParse( strParams[ i ], out n値 ) )
\r
4162 Trace.TraceError( "BGAPAN: {2}番目の引数(画像側終了位置・X)が異常です。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数, i + 1 );
\r
4165 bgapan.pt画像側終了位置.X = n値;
\r
4167 //-----------------
\r
4169 #region [ 9. 画像側終了位置・Y ]
\r
4170 //-----------------
\r
4172 if( !int.TryParse( strParams[ i ], out n値 ) )
\r
4174 Trace.TraceError( "BGAPAN: {2}番目の引数(画像側終了位置・Y)が異常です。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数, i + 1 );
\r
4177 bgapan.pt画像側終了位置.Y = n値;
\r
4179 //-----------------
\r
4181 #region [ 10.表示側開始位置・X ]
\r
4182 //-----------------
\r
4184 if( !int.TryParse( strParams[ i ], out n値 ) )
\r
4186 Trace.TraceError( "BGAPAN: {2}番目の引数(表示側開始位置・X)が異常です。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数, i + 1 );
\r
4189 bgapan.pt表示側開始位置.X = n値;
\r
4191 //-----------------
\r
4193 #region [ 11.表示側開始位置・Y ]
\r
4194 //-----------------
\r
4196 if( !int.TryParse( strParams[ i ], out n値 ) )
\r
4198 Trace.TraceError( "BGAPAN: {2}番目の引数(表示側開始位置・Y)が異常です。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数, i + 1 );
\r
4201 bgapan.pt表示側開始位置.Y = n値;
\r
4203 //-----------------
\r
4205 #region [ 12.表示側終了位置・X ]
\r
4206 //-----------------
\r
4208 if( !int.TryParse( strParams[ i ], out n値 ) )
\r
4210 Trace.TraceError( "BGAPAN: {2}番目の引数(表示側終了位置・X)が異常です。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数, i + 1 );
\r
4213 bgapan.pt表示側終了位置.X = n値;
\r
4215 //-----------------
\r
4217 #region [ 13.表示側終了位置・Y ]
\r
4218 //-----------------
\r
4220 if( !int.TryParse( strParams[ i ], out n値 ) )
\r
4222 Trace.TraceError( "BGAPAN: {2}番目の引数(表示側終了位置・Y)が異常です。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数, i + 1 );
\r
4225 bgapan.pt表示側終了位置.Y = n値;
\r
4227 //-----------------
\r
4229 #region [ 14.移動時間 ]
\r
4230 //-----------------
\r
4232 if( !int.TryParse( strParams[ i ], out n値 ) )
\r
4234 Trace.TraceError( "BGAPAN: {2}番目の引数(移動時間)が異常です。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数, i + 1 );
\r
4241 bgapan.n移動時間ct = n値;
\r
4243 //-----------------
\r
4246 #region [ BGAPANリストに {zz, bgapan} の組を登録する。]
\r
4247 //-----------------
\r
4248 if( this.listBGAPAN.ContainsKey( zz ) ) // 既にリスト中に存在しているなら削除。後のものが有効。
\r
4249 this.listBGAPAN.Remove( zz );
\r
4251 this.listBGAPAN.Add( zz, bgapan );
\r
4252 //-----------------
\r
4257 private bool t入力・行解析・BMP( string strコマンド, string strパラメータ, string strコメント )
\r
4261 #region [ "BMP" で始まらないコマンドは無効。]
\r
4262 //-----------------
\r
4263 if( !strコマンド.StartsWith( "BMP", StringComparison.OrdinalIgnoreCase ) )
\r
4266 strコマンド = strコマンド.Substring( 3 ); // strコマンド から先頭の"BMP"文字を除去。
\r
4267 //-----------------
\r
4274 #region [ BMP番号 zz を取得する。]
\r
4275 //-----------------
\r
4276 if( strコマンド.Length < 2 )
\r
4278 #region [ (A) "#BMP:" の場合 → zz = 00 ]
\r
4279 //-----------------
\r
4281 //-----------------
\r
4286 #region [ (B) "#BMPzz:" の場合 → zz = 00 ~ ZZ ]
\r
4287 //-----------------
\r
4288 zz = C変換.n36進数2桁の文字列を数値に変換して返す( strコマンド.Substring( 0, 2 ) );
\r
4289 if( zz < 0 || zz >= 36 * 36 )
\r
4291 Trace.TraceError( "BMP番号に 00~ZZ 以外の値または不正な文字列が指定されました。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数 );
\r
4294 //-----------------
\r
4297 //-----------------
\r
4301 var bmp = new CBMP() {
\r
4303 strファイル名 = strパラメータ,
\r
4304 strコメント文 = strコメント,
\r
4307 #region [ BMPリストに {zz, bmp} の組を登録。]
\r
4308 //-----------------
\r
4309 if( this.listBMP.ContainsKey( zz ) ) // 既にリスト中に存在しているなら削除。後のものが有効。
\r
4310 this.listBMP.Remove( zz );
\r
4312 this.listBMP.Add( zz, bmp );
\r
4313 //-----------------
\r
4318 private bool t入力・行解析・BMPTEX( string strコマンド, string strパラメータ, string strコメント )
\r
4322 #region [ "BMPTEX" で始まらないコマンドは無効。]
\r
4323 //-----------------
\r
4324 if( !strコマンド.StartsWith( "BMPTEX", StringComparison.OrdinalIgnoreCase ) )
\r
4327 strコマンド = strコマンド.Substring( 6 ); // strコマンド から先頭の"BMPTEX"文字を除去。
\r
4328 //-----------------
\r
4333 if( strコマンド.Length < 2 )
\r
4334 return false; // BMPTEX番号 zz がないなら無効。
\r
4336 #region [ BMPTEX番号 zz を取得する。]
\r
4337 //-----------------
\r
4338 int zz = C変換.n36進数2桁の文字列を数値に変換して返す( strコマンド.Substring( 0, 2 ) );
\r
4339 if( zz < 0 || zz >= 36 * 36 )
\r
4341 Trace.TraceError( "BMPTEX番号に 00~ZZ 以外の値または不正な文字列が指定されました。[{0}: {1}]", this.strファイル名の絶対パス, this.n現在の行数 );
\r
4344 //-----------------
\r
4347 var bmptex = new CBMPTEX() {
\r
4349 strファイル名 = strパラメータ,
\r
4350 strコメント文 = strコメント,
\r
4353 #region [ BMPTEXリストに {zz, bmptex} の組を登録する。]
\r
4354 //-----------------
\r
4355 if( this.listBMPTEX.ContainsKey( zz ) ) // 既にリスト中に存在しているなら削除。後のものが有効。
\r
4356 this.listBMPTEX.Remove( zz );
\r
4358 this.listBMPTEX.Add( zz, bmptex );
\r
4359 //-----------------
\r
4364 private bool t入力・行解析・BPM_BPMzz( string strコマンド, string strパラメータ, string strコメント )
\r
4368 #region [ "BPM" で始まらないコマンドは無効。]
\r
4369 //-----------------
\r
4370 if( !strコマンド.StartsWith( "BPM", StringComparison.OrdinalIgnoreCase ) )
\r
4373 strコマンド = strコマンド.Substring( 3 ); // strコマンド から先頭の"BPM"文字を除去。
\r
4374 //-----------------
\r
4381 #region [ BPM番号 zz を取得する。]
\r
4382 //-----------------
\r
4383 if( strコマンド.Length < 2 )
\r
4385 #region [ (A) "#BPM:" の場合 → zz = 00 ]
\r
4386 //-----------------
\r
4388 //-----------------
\r
4393 #region [ (B) "#BPMzz:" の場合 → zz = 00 ~ ZZ ]
\r
4394 //-----------------
\r
4395 zz = C変換.n36進数2桁の文字列を数値に変換して返す( strコマンド.Substring( 0, 2 ) );
\r
4396 if( zz < 0 || zz >= 36 * 36 )
\r
4398 Trace.TraceError( "BPM番号に 00~ZZ 以外の値または不正な文字列が指定されました。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数 );
\r
4401 //-----------------
\r
4404 //-----------------
\r
4407 double dbBPM = 0.0;
\r
4409 #region [ BPM値を取得する。]
\r
4410 //-----------------
\r
4411 //if( !double.TryParse( strパラメータ, out result ) )
\r
4412 if( !TryParse( strパラメータ, out dbBPM ) ) // #23880 2010.12.30 yyagi: alternative TryParse to permit both '.' and ',' for decimal point
\r
4415 if( dbBPM <= 0.0 )
\r
4417 //-----------------
\r
4420 if( zz == 0 ) // "#BPM00:" と "#BPM:" は等価。
\r
4421 this.BPM = dbBPM; // この曲の代表 BPM に格納する。
\r
4423 #region [ BPMリストに {内部番号, zz, dbBPM} の組を登録。]
\r
4424 //-----------------
\r
4428 n内部番号 = this.n内部番号BPM1to,
\r
4432 //-----------------
\r
4435 #region [ BPM番号が zz であるBPM未設定のBPMチップがあれば、そのサイズを変更する。無限管理に対応。]
\r
4436 //-----------------
\r
4437 if( this.n無限管理BPM[ zz ] == -zz ) // 初期状態では n無限管理BPM[zz] = -zz である。この場合、#BPMzz がまだ出現していないことを意味する。
\r
4439 for( int i = 0; i < this.listChip.Count; i++ ) // これまでに出てきたチップのうち、該当する(BPM値が未設定の)BPMチップの値を変更する(仕組み上、必ず後方参照となる)。
\r
4441 var chip = this.listChip[ i ];
\r
4443 if( chip.bBPMチップである && chip.n整数値・内部番号 == -zz ) // #BPMzz 行より前の行に出現した #BPMzz では、整数値・内部番号は -zz に初期化されている。
\r
4444 chip.n整数値・内部番号 = this.n内部番号BPM1to;
\r
4447 this.n無限管理BPM[ zz ] = this.n内部番号BPM1to; // 次にこの BPM番号 zz を使うBPMチップが現れたら、このBPM値が格納されることになる。
\r
4448 this.n内部番号BPM1to++; // 内部番号は単純増加連番。
\r
4449 //-----------------
\r
4454 private bool t入力・行解析・RESULTIMAGE( string strコマンド, string strパラメータ, string strコメント )
\r
4458 #region [ "RESULTIMAGE" で始まらないコマンドは無効。]
\r
4459 //-----------------
\r
4460 if( !strコマンド.StartsWith( "RESULTIMAGE", StringComparison.OrdinalIgnoreCase ) )
\r
4463 strコマンド = strコマンド.Substring( 11 ); // strコマンド から先頭の"RESULTIMAGE"文字を除去。
\r
4464 //-----------------
\r
4468 // コマンドには "#RESULTIMAGE:" と "#RESULTIMAGE_SS~E" の2種類があり、パラメータの処理はそれぞれ異なる。
\r
4470 if( strコマンド.Length < 2 )
\r
4472 #region [ (A) ランク指定がない場合("#RESULTIMAGE:") → 優先順位が設定されていないすべてのランクで同じパラメータを使用する。]
\r
4473 //-----------------
\r
4474 for( int i = 0; i < 7; i++ )
\r
4476 if( this.nRESULTIMAGE用優先順位[ i ] == 0 )
\r
4477 this.RESULTIMAGE[ i ] = strパラメータ.Trim();
\r
4479 //-----------------
\r
4484 #region [ (B) ランク指定がある場合("#RESULTIMAGE_SS~E:") → 優先順位に従ってパラメータを記録する。]
\r
4485 //-----------------
\r
4486 switch( strコマンド.ToUpper() )
\r
4489 this.t入力・行解析・RESULTIMAGE・ファイルを設定する( 0, strパラメータ );
\r
4493 this.t入力・行解析・RESULTIMAGE・ファイルを設定する( 1, strパラメータ );
\r
4497 this.t入力・行解析・RESULTIMAGE・ファイルを設定する( 2, strパラメータ );
\r
4501 this.t入力・行解析・RESULTIMAGE・ファイルを設定する( 3, strパラメータ );
\r
4505 this.t入力・行解析・RESULTIMAGE・ファイルを設定する( 4, strパラメータ );
\r
4509 this.t入力・行解析・RESULTIMAGE・ファイルを設定する( 5, strパラメータ );
\r
4513 this.t入力・行解析・RESULTIMAGE・ファイルを設定する( 6, strパラメータ );
\r
4516 //-----------------
\r
4522 private void t入力・行解析・RESULTIMAGE・ファイルを設定する( int nランク0to6, string strファイル名 )
\r
4524 if( nランク0to6 < 0 || nランク0to6 > 6 ) // 値域チェック。
\r
4527 // 指定されたランクから上位のすべてのランクについて、ファイル名を更新する。
\r
4529 for( int i = nランク0to6; i >= 0; i-- )
\r
4531 int n優先順位 = 7 - nランク0to6;
\r
4533 // 現状より優先順位の低い RESULTIMAGE[] に限り、ファイル名を更新できる。
\r
4534 //(例:#RESULTMOVIE_D が #RESULTIMAGE_A より後に出現しても、#RESULTIMAGE_A で指定されたファイル名を上書きすることはできない。しかしその逆は可能。)
\r
4536 if( this.nRESULTIMAGE用優先順位[ i ] < n優先順位 )
\r
4538 this.nRESULTIMAGE用優先順位[ i ] = n優先順位;
\r
4539 this.RESULTIMAGE[ i ] = strファイル名;
\r
4543 private bool t入力・行解析・RESULTMOVIE( string strコマンド, string strパラメータ, string strコメント )
\r
4547 #region [ "RESULTMOVIE" で始まらないコマンドは無効。]
\r
4548 //-----------------
\r
4549 if( !strコマンド.StartsWith( "RESULTMOVIE", StringComparison.OrdinalIgnoreCase ) )
\r
4552 strコマンド = strコマンド.Substring( 11 ); // strコマンド から先頭の"RESULTMOVIE"文字を除去。
\r
4553 //-----------------
\r
4557 // コマンドには "#RESULTMOVIE:" と "#RESULTMOVIE_SS~E" の2種類があり、パラメータの処理はそれぞれ異なる。
\r
4559 if( strコマンド.Length < 2 )
\r
4561 #region [ (A) ランク指定がない場合("#RESULTMOVIE:") → 優先順位が設定されていないすべてのランクで同じパラメータを使用する。]
\r
4562 //-----------------
\r
4563 for( int i = 0; i < 7; i++ )
\r
4565 if( this.nRESULTMOVIE用優先順位[ i ] == 0 )
\r
4566 this.RESULTMOVIE[ i ] = strパラメータ.Trim();
\r
4568 //-----------------
\r
4573 #region [ (B) ランク指定がある場合("#RESULTMOVIE_SS~E:") → 優先順位に従ってパラメータを記録する。]
\r
4574 //-----------------
\r
4575 switch( strコマンド.ToUpper() )
\r
4578 this.t入力・行解析・RESULTMOVIE・ファイルを設定する( 0, strパラメータ );
\r
4582 this.t入力・行解析・RESULTMOVIE・ファイルを設定する( 1, strパラメータ );
\r
4586 this.t入力・行解析・RESULTMOVIE・ファイルを設定する( 2, strパラメータ );
\r
4590 this.t入力・行解析・RESULTMOVIE・ファイルを設定する( 3, strパラメータ );
\r
4594 this.t入力・行解析・RESULTMOVIE・ファイルを設定する( 4, strパラメータ );
\r
4598 this.t入力・行解析・RESULTMOVIE・ファイルを設定する( 5, strパラメータ );
\r
4602 this.t入力・行解析・RESULTMOVIE・ファイルを設定する( 6, strパラメータ );
\r
4605 //-----------------
\r
4611 private void t入力・行解析・RESULTMOVIE・ファイルを設定する( int nランク0to6, string strファイル名 )
\r
4613 if( nランク0to6 < 0 || nランク0to6 > 6 ) // 値域チェック。
\r
4616 // 指定されたランクから上位のすべてのランクについて、ファイル名を更新する。
\r
4618 for( int i = nランク0to6; i >= 0; i-- )
\r
4620 int n優先順位 = 7 - nランク0to6;
\r
4622 // 現状より優先順位の低い RESULTMOVIE[] に限り、ファイル名を更新できる。
\r
4623 //(例:#RESULTMOVIE_D が #RESULTMOVIE_A より後に出現しても、#RESULTMOVIE_A で指定されたファイル名を上書きすることはできない。しかしその逆は可能。)
\r
4625 if( this.nRESULTMOVIE用優先順位[ i ] < n優先順位 )
\r
4627 this.nRESULTMOVIE用優先順位[ i ] = n優先順位;
\r
4628 this.RESULTMOVIE[ i ] = strファイル名;
\r
4632 private bool t入力・行解析・RESULTSOUND( string strコマンド, string strパラメータ, string strコメント )
\r
4636 #region [ "RESULTSOUND" で始まらないコマンドは無効。]
\r
4637 //-----------------
\r
4638 if( !strコマンド.StartsWith( "RESULTSOUND", StringComparison.OrdinalIgnoreCase ) )
\r
4641 strコマンド = strコマンド.Substring( 11 ); // strコマンド から先頭の"RESULTSOUND"文字を除去。
\r
4642 //-----------------
\r
4646 // コマンドには "#RESULTSOUND:" と "#RESULTSOUND_SS~E" の2種類があり、パラメータの処理はそれぞれ異なる。
\r
4648 if( strコマンド.Length < 2 )
\r
4650 #region [ (A) ランク指定がない場合("#RESULTSOUND:") → 優先順位が設定されていないすべてのランクで同じパラメータを使用する。]
\r
4651 //-----------------
\r
4652 for( int i = 0; i < 7; i++ )
\r
4654 if( this.nRESULTSOUND用優先順位[ i ] == 0 )
\r
4655 this.RESULTSOUND[ i ] = strパラメータ.Trim();
\r
4657 //-----------------
\r
4662 #region [ (B) ランク指定がある場合("#RESULTSOUND_SS~E:") → 優先順位に従ってパラメータを記録する。]
\r
4663 //-----------------
\r
4664 switch( strコマンド.ToUpper() )
\r
4667 this.t入力・行解析・RESULTSOUND・ファイルを設定する( 0, strパラメータ );
\r
4671 this.t入力・行解析・RESULTSOUND・ファイルを設定する( 1, strパラメータ );
\r
4675 this.t入力・行解析・RESULTSOUND・ファイルを設定する( 2, strパラメータ );
\r
4679 this.t入力・行解析・RESULTSOUND・ファイルを設定する( 3, strパラメータ );
\r
4683 this.t入力・行解析・RESULTSOUND・ファイルを設定する( 4, strパラメータ );
\r
4687 this.t入力・行解析・RESULTSOUND・ファイルを設定する( 5, strパラメータ );
\r
4691 this.t入力・行解析・RESULTSOUND・ファイルを設定する( 6, strパラメータ );
\r
4694 //-----------------
\r
4700 private void t入力・行解析・RESULTSOUND・ファイルを設定する( int nランク0to6, string strファイル名 )
\r
4702 if( nランク0to6 < 0 || nランク0to6 > 6 ) // 値域チェック。
\r
4705 // 指定されたランクから上位のすべてのランクについて、ファイル名を更新する。
\r
4707 for( int i = nランク0to6; i >= 0; i-- )
\r
4709 int n優先順位 = 7 - nランク0to6;
\r
4711 // 現状より優先順位の低い RESULTSOUND[] に限り、ファイル名を更新できる。
\r
4712 //(例:#RESULTSOUND_D が #RESULTSOUND_A より後に出現しても、#RESULTSOUND_A で指定されたファイル名を上書きすることはできない。しかしその逆は可能。)
\r
4714 if( this.nRESULTSOUND用優先順位[ i ] < n優先順位 )
\r
4716 this.nRESULTSOUND用優先順位[ i ] = n優先順位;
\r
4717 this.RESULTSOUND[ i ] = strファイル名;
\r
4721 private bool t入力・行解析・SIZE( string strコマンド, string strパラメータ, string strコメント )
\r
4725 #region [ "SIZE" で始まらないコマンドや、その後ろに2文字(番号)が付随してないコマンドは無効。]
\r
4726 //-----------------
\r
4727 if( !strコマンド.StartsWith( "SIZE", StringComparison.OrdinalIgnoreCase ) )
\r
4730 strコマンド = strコマンド.Substring( 4 ); // strコマンド から先頭の"SIZE"文字を除去。
\r
4732 if( strコマンド.Length < 2 ) // サイズ番号の指定がない場合は無効。
\r
4734 //-----------------
\r
4737 #region [ nWAV番号(36進数2桁)を取得。]
\r
4738 //-----------------
\r
4739 int nWAV番号 = C変換.n36進数2桁の文字列を数値に変換して返す( strコマンド.Substring( 0, 2 ) );
\r
4741 if( nWAV番号 < 0 || nWAV番号 >= 36 * 36 )
\r
4743 Trace.TraceError( "SIZEのWAV番号に 00~ZZ 以外の値または不正な文字列が指定されました。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数 );
\r
4746 //-----------------
\r
4752 #region [ nサイズ値 を取得する。値は 0~100 に収める。]
\r
4753 //-----------------
\r
4756 if( !int.TryParse( strパラメータ, out nサイズ値 ) )
\r
4757 return true; // int変換に失敗しても、この行自体の処理は終えたのでtrueを返す。
\r
4759 nサイズ値 = Math.Min( Math.Max( nサイズ値, 0 ), 100 ); // 0未満は0、100超えは100に強制変換。
\r
4760 //-----------------
\r
4763 #region [ nWAV番号で示されるサイズ未設定のWAVチップがあれば、そのサイズを変更する。無限管理に対応。]
\r
4764 //-----------------
\r
4765 if( this.n無限管理SIZE[ nWAV番号 ] == -nWAV番号 ) // 初期状態では n無限管理SIZE[xx] = -xx である。この場合、#SIZExx がまだ出現していないことを意味する。
\r
4767 foreach( CWAV wav in this.listWAV.Values ) // これまでに出てきたWAVチップのうち、該当する(サイズが未設定の)チップのサイズを変更する(仕組み上、必ず後方参照となる)。
\r
4769 if( wav.nチップサイズ == -nWAV番号 ) // #SIZExx 行より前の行に出現した #WAVxx では、チップサイズは -xx に初期化されている。
\r
4770 wav.nチップサイズ = nサイズ値;
\r
4773 this.n無限管理SIZE[ nWAV番号 ] = nサイズ値; // 次にこの nWAV番号を使うWAVチップが現れたら、負数の代わりに、このサイズ値が格納されることになる。
\r
4774 //-----------------
\r
4779 private bool t入力・行解析・WAV( string strコマンド, string strパラメータ, string strコメント )
\r
4783 #region [ "WAV" で始まらないコマンドは無効。]
\r
4784 //-----------------
\r
4785 if( !strコマンド.StartsWith( "WAV", StringComparison.OrdinalIgnoreCase ) )
\r
4788 strコマンド = strコマンド.Substring( 3 ); // strコマンド から先頭の"WAV"文字を除去。
\r
4789 //-----------------
\r
4794 if( strコマンド.Length < 2 )
\r
4795 return false; // WAV番号 zz がないなら無効。
\r
4797 #region [ WAV番号 zz を取得する。]
\r
4798 //-----------------
\r
4799 int zz = C変換.n36進数2桁の文字列を数値に変換して返す( strコマンド.Substring( 0, 2 ) );
\r
4800 if( zz < 0 || zz >= 36 * 36 )
\r
4802 Trace.TraceError( "WAV番号に 00~ZZ 以外の値または不正な文字列が指定されました。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数 );
\r
4805 //-----------------
\r
4808 var wav = new CWAV() {
\r
4809 n内部番号 = this.n内部番号WAV1to,
\r
4811 nチップサイズ = this.n無限管理SIZE[ zz ],
\r
4812 n位置 = this.n無限管理PAN[ zz ],
\r
4813 n音量 = this.n無限管理VOL[ zz ],
\r
4814 strファイル名 = strパラメータ,
\r
4815 strコメント文 = strコメント,
\r
4818 #region [ WAVリストに {内部番号, wav} の組を登録。]
\r
4819 //-----------------
\r
4820 this.listWAV.Add( this.n内部番号WAV1to, wav );
\r
4821 //-----------------
\r
4824 #region [ WAV番号が zz である内部番号未設定のWAVチップがあれば、その内部番号を変更する。無限管理対応。]
\r
4825 //-----------------
\r
4826 if( this.n無限管理WAV[ zz ] == -zz ) // 初期状態では n無限管理WAV[zz] = -zz である。この場合、#WAVzz がまだ出現していないことを意味する。
\r
4828 for( int i = 0; i < this.listChip.Count; i++ ) // これまでに出てきたチップのうち、該当する(内部番号が未設定の)WAVチップの値を変更する(仕組み上、必ず後方参照となる)。
\r
4830 var chip = this.listChip[ i ];
\r
4832 if( chip.bWAVを使うチャンネルである && ( chip.n整数値・内部番号 == -zz ) ) // この #WAVzz 行より前の行に出現した #WAVzz では、整数値・内部番号は -zz に初期化されている。
\r
4833 chip.n整数値・内部番号 = this.n内部番号WAV1to;
\r
4836 this.n無限管理WAV[ zz ] = this.n内部番号WAV1to; // 次にこの WAV番号 zz を使うWAVチップが現れたら、この内部番号が格納されることになる。
\r
4837 this.n内部番号WAV1to++; // 内部番号は単純増加連番。
\r
4838 //-----------------
\r
4843 private bool t入力・行解析・WAVPAN_PAN( string strコマンド, string strパラメータ, string strコメント )
\r
4847 #region [ "WAVPAN" or "PAN" で始まらないコマンドは無効。]
\r
4848 //-----------------
\r
4849 if( strコマンド.StartsWith( "WAVPAN", StringComparison.OrdinalIgnoreCase ) )
\r
4850 strコマンド = strコマンド.Substring( 6 ); // strコマンド から先頭の"WAVPAN"文字を除去。
\r
4852 else if( strコマンド.StartsWith( "PAN", StringComparison.OrdinalIgnoreCase ) )
\r
4853 strコマンド = strコマンド.Substring( 3 ); // strコマンド から先頭の"PAN"文字を除去。
\r
4857 //-----------------
\r
4862 if( strコマンド.Length < 2 )
\r
4863 return false; // WAV番号 zz がないなら無効。
\r
4865 #region [ WAV番号 zz を取得する。]
\r
4866 //-----------------
\r
4867 int zz = C変換.n36進数2桁の文字列を数値に変換して返す( strコマンド.Substring( 0, 2 ) );
\r
4868 if( zz < 0 || zz >= 36 * 36 )
\r
4870 Trace.TraceError( "WAVPAN(PAN)のWAV番号に 00~ZZ 以外の値または不正な文字列が指定されました。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数 );
\r
4873 //-----------------
\r
4876 #region [ WAV番号 zz を持つWAVチップの位置を変更する。無限定義対応。]
\r
4877 //-----------------
\r
4879 if( int.TryParse( strパラメータ, out n位置 ) )
\r
4881 n位置 = Math.Min( Math.Max( n位置, -100 ), 100 ); // -100~+100 に丸める
\r
4883 if( this.n無限管理PAN[ zz ] == ( -10000 - zz ) ) // 初期状態では n無限管理PAN[zz] = -10000 - zz である。この場合、#WAVPANzz, #PANzz がまだ出現していないことを意味する。
\r
4885 foreach( CWAV wav in this.listWAV.Values ) // これまでに出てきたチップのうち、該当する(位置が未設定の)WAVチップの値を変更する(仕組み上、必ず後方参照となる)。
\r
4887 if( wav.n位置 == ( -10000 - zz ) ) // #WAVPANzz, #PANzz 行より前の行に出現した #WAVzz では、位置は -10000-zz に初期化されている。
\r
4891 this.n無限管理PAN[ zz ] = n位置; // 次にこの WAV番号 zz を使うWAVチップが現れたら、この位置が格納されることになる。
\r
4893 //-----------------
\r
4898 private bool t入力・行解析・WAVVOL_VOLUME( string strコマンド, string strパラメータ, string strコメント )
\r
4902 #region [ "WAVCOL" or "VOLUME" で始まらないコマンドは無効。]
\r
4903 //-----------------
\r
4904 if( strコマンド.StartsWith( "WAVVOL", StringComparison.OrdinalIgnoreCase ) )
\r
4905 strコマンド = strコマンド.Substring( 6 ); // strコマンド から先頭の"WAVVOL"文字を除去。
\r
4907 else if( strコマンド.StartsWith( "VOLUME", StringComparison.OrdinalIgnoreCase ) )
\r
4908 strコマンド = strコマンド.Substring( 6 ); // strコマンド から先頭の"VOLUME"文字を除去。
\r
4912 //-----------------
\r
4917 if( strコマンド.Length < 2 )
\r
4918 return false; // WAV番号 zz がないなら無効。
\r
4920 #region [ WAV番号 zz を取得する。]
\r
4921 //-----------------
\r
4922 int zz = C変換.n36進数2桁の文字列を数値に変換して返す( strコマンド.Substring( 0, 2 ) );
\r
4923 if( zz < 0 || zz >= 36 * 36 )
\r
4925 Trace.TraceError( "WAV番号に 00~ZZ 以外の値または不正な文字列が指定されました。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数 );
\r
4928 //-----------------
\r
4931 #region [ WAV番号 zz を持つWAVチップの音量を変更する。無限定義対応。]
\r
4932 //-----------------
\r
4934 if( int.TryParse( strパラメータ, out n音量 ) )
\r
4936 n音量 = Math.Min( Math.Max( n音量, 0 ), 100 ); // 0~100に丸める。
\r
4938 if( this.n無限管理VOL[ zz ] == -zz ) // 初期状態では n無限管理VOL[zz] = - zz である。この場合、#WAVVOLzz, #VOLUMEzz がまだ出現していないことを意味する。
\r
4940 foreach( CWAV wav in this.listWAV.Values ) // これまでに出てきたチップのうち、該当する(音量が未設定の)WAVチップの値を変更する(仕組み上、必ず後方参照となる)。
\r
4942 if( wav.n音量 == -zz ) // #WAVVOLzz, #VOLUMEzz 行より前の行に出現した #WAVzz では、音量は -zz に初期化されている。
\r
4946 this.n無限管理VOL[ zz ] = n音量; // 次にこの WAV番号 zz を使うWAVチップが現れたら、この音量が格納されることになる。
\r
4948 //-----------------
\r
4953 private bool t入力・行解析・チップ配置( string strコマンド, string strパラメータ, string strコメント )
\r
4957 if( strコマンド.Length != 5 ) // コマンドは必ず5文字であること。
\r
4960 #region [ n小節番号 を取得する。]
\r
4961 //-----------------
\r
4962 int n小節番号 = C変換.n小節番号の文字列3桁を数値に変換して返す( strコマンド.Substring( 0, 3 ) );
\r
4966 n小節番号++; // 先頭に空の1小節を設ける。
\r
4967 //-----------------
\r
4970 #region [ nチャンネル番号 を取得する。]
\r
4971 //-----------------
\r
4972 int nチャンネル番号 = -1;
\r
4974 // ファイルフォーマットによって処理が異なる。
\r
4976 if( this.e種別 == E種別.GDA || this.e種別 == E種別.G2D )
\r
4978 #region [ (A) GDA, G2D の場合:チャンネル文字列をDTXのチャンネル番号へ置き換える。]
\r
4979 //-----------------
\r
4980 string strチャンネル文字列 = strコマンド.Substring( 3, 2 );
\r
4982 foreach( STGDAPARAM param in this.stGDAParam )
\r
4984 if( strチャンネル文字列.Equals( param.strGDAのチャンネル文字列, StringComparison.OrdinalIgnoreCase ) )
\r
4986 nチャンネル番号 = param.nDTXのチャンネル番号;
\r
4990 if( nチャンネル番号 < 0 )
\r
4991 return false; // 置き換え失敗
\r
4992 //-----------------
\r
4997 #region [ (B) その他の場合:チャンネル番号は16進数2桁。]
\r
4998 //-----------------
\r
4999 nチャンネル番号 = C変換.n16進数2桁の文字列を数値に変換して返す( strコマンド.Substring( 3, 2 ) );
\r
5001 if( nチャンネル番号 < 0 )
\r
5003 //-----------------
\r
5006 //-----------------
\r
5008 #region [ 取得したチャンネル番号で、this.bチップがある に該当があれば設定する。]
\r
5009 //-----------------
\r
5010 if( ( nチャンネル番号 >= 0x11 ) && ( nチャンネル番号 <= 0x1a ) )
\r
5012 this.bチップがある.Drums = true;
\r
5014 else if( ( nチャンネル番号 >= 0x20 ) && ( nチャンネル番号 <= 0x27 ) )
\r
5016 this.bチップがある.Guitar = true;
\r
5018 else if( ( nチャンネル番号 >= 0xA0 ) && ( nチャンネル番号 <= 0xa7 ) )
\r
5020 this.bチップがある.Bass = true;
\r
5022 switch( nチャンネル番号 )
\r
5025 this.bチップがある.HHOpen = true;
\r
5029 this.bチップがある.Ride = true;
\r
5033 this.bチップがある.LeftCymbal = true;
\r
5037 this.bチップがある.OpenGuitar = true;
\r
5041 this.bチップがある.OpenBass = true;
\r
5044 //-----------------
\r
5050 #region [ 小節長変更(Ch.02)は他のチャンネルとはパラメータが特殊なので、先にとっとと終わらせる。 ]
\r
5051 //-----------------
\r
5052 if( nチャンネル番号 == 0x02 )
\r
5056 double db小節長倍率 = 1.0;
\r
5057 //if( !double.TryParse( strパラメータ, out result ) )
\r
5058 if( !this.TryParse( strパラメータ, out db小節長倍率 ) ) // #23880 2010.12.30 yyagi: alternative TryParse to permit both '.' and ',' for decimal point
\r
5060 Trace.TraceError( "小節長倍率に不正な値を指定しました。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数 );
\r
5066 this.listChip.Insert(
\r
5069 nチャンネル番号 = nチャンネル番号,
\r
5071 n発声位置 = n小節番号 * 384,
\r
5074 return true; // 配置終了。
\r
5076 //-----------------
\r
5082 if( string.IsNullOrEmpty( strパラメータ ) ) // パラメータはnullまたは空文字列ではないこと。
\r
5085 #region [ strパラメータ にオブジェクト記述を格納し、その n文字数 をカウントする。]
\r
5086 //-----------------
\r
5089 var sb = new StringBuilder( strパラメータ.Length );
\r
5091 // strパラメータを先頭から1文字ずつ見ながら正規化(無効文字('_')を飛ばしたり不正な文字でエラーを出したり)し、sb へ格納する。
\r
5093 CharEnumerator ce = strパラメータ.GetEnumerator();
\r
5094 while( ce.MoveNext() )
\r
5096 if( ce.Current == '_' ) // '_' は無視。
\r
5099 if( C変換.str36進数文字.IndexOf( ce.Current ) < 0 ) // オブジェクト記述は36進数文字であること。
\r
5101 Trace.TraceError( "不正なオブジェクト指定があります。[{0}: {1}行]", this.strファイル名の絶対パス, this.n現在の行数 );
\r
5105 sb.Append( ce.Current );
\r
5109 strパラメータ = sb.ToString(); // 正規化された文字列になりました。
\r
5111 if( ( n文字数 % 2 ) != 0 ) // パラメータの文字数が奇数の場合、最後の1文字を無視する。
\r
5113 //-----------------
\r
5117 // (4) パラメータをオブジェクト数値に分解して配置する。
\r
5119 for( int i = 0; i < ( n文字数 / 2 ); i++ ) // 2文字で1オブジェクト数値
\r
5121 #region [ nオブジェクト数値 を1つ取得する。'00' なら無視。]
\r
5122 //-----------------
\r
5123 int nオブジェクト数値 = 0;
\r
5125 if( nチャンネル番号 == 0x03 )
\r
5127 // Ch.03 のみ 16進数2桁。
\r
5128 nオブジェクト数値 = C変換.n16進数2桁の文字列を数値に変換して返す( strパラメータ.Substring( i * 2, 2 ) );
\r
5132 // その他のチャンネルは36進数2桁。
\r
5133 nオブジェクト数値 = C変換.n36進数2桁の文字列を数値に変換して返す( strパラメータ.Substring( i * 2, 2 ) );
\r
5136 if( nオブジェクト数値 == 0x00 )
\r
5138 //-----------------
\r
5141 // オブジェクト数値に対応するチップを生成。
\r
5143 var chip = new CChip();
\r
5145 chip.nチャンネル番号 = nチャンネル番号;
\r
5146 chip.n発声位置 = ( n小節番号 * 384 ) + ( ( 384 * i ) / ( n文字数 / 2 ) );
\r
5147 chip.n整数値 = nオブジェクト数値;
\r
5148 chip.n整数値・内部番号 = nオブジェクト数値;
\r
5150 #region [ chip.e楽器パート = ... ]
\r
5151 //-----------------
\r
5152 if( ( nチャンネル番号 >= 0x11 ) && ( nチャンネル番号 <= 0x1A ) )
\r
5154 chip.e楽器パート = E楽器パート.DRUMS;
\r
5156 if( ( nチャンネル番号 >= 0x20 ) && ( nチャンネル番号 <= 0x27 ) )
\r
5158 chip.e楽器パート = E楽器パート.GUITAR;
\r
5160 if( ( nチャンネル番号 >= 160 ) && ( nチャンネル番号 <= 0xA7 ) )
\r
5162 chip.e楽器パート = E楽器パート.BASS;
\r
5164 //-----------------
\r
5167 #region [ 無限定義への対応 → 内部番号の取得。]
\r
5168 //-----------------
\r
5169 if( chip.bWAVを使うチャンネルである )
\r
5171 chip.n整数値・内部番号 = this.n無限管理WAV[ nオブジェクト数値 ]; // これが本当に一意なWAV番号となる。(無限定義の場合、chip.n整数値 は一意である保証がない。)
\r
5173 else if( chip.bBPMチップである )
\r
5175 chip.n整数値・内部番号 = this.n無限管理BPM[ nオブジェクト数値 ]; // これが本当に一意なBPM番号となる。(同上。)
\r
5177 //-----------------
\r
5180 #region [ フィルインON/OFFチャンネル(Ch.53)の場合、発声位置を少し前後にずらす。]
\r
5181 //-----------------
\r
5182 if( nチャンネル番号 == 0x53 )
\r
5184 // ずらすのは、フィルインONチップと同じ位置にいるチップでも確実にフィルインが発動し、
\r
5185 // 同様に、フィルインOFFチップと同じ位置にいるチップでも確実にフィルインが終了するようにするため。
\r
5187 if( ( nオブジェクト数値 > 0 ) && ( nオブジェクト数値 != 2 ) )
\r
5189 chip.n発声位置 -= 32; // 384÷32=12 ということで、フィルインONチップは12分音符ほど前へ移動。
\r
5191 else if( nオブジェクト数値 == 2 )
\r
5193 chip.n発声位置 += 32; // 同じく、フィルインOFFチップは12分音符ほど後ろへ移動。
\r
5196 //-----------------
\r
5201 this.listChip.Add( chip );
\r
5205 #region [#23880 2010.12.30 yyagi: コンマとスペースの両方を小数点として扱うTryParse]
\r
5207 /// 小数点としてコンマとピリオドの両方を受け付けるTryParse()
\r
5209 /// <param name="s">strings convert to double</param>
\r
5210 /// <param name="result">parsed double value</param>
\r
5211 /// <returns>s が正常に変換された場合は true。それ以外の場合は false。</returns>
\r
5212 /// <exception cref="ArgumentException">style が NumberStyles 値でないか、style に NumberStyles.AllowHexSpecifier 値が含まれている</exception>
\r
5213 private bool TryParse(string s, out double result) { // #23880 2010.12.30 yyagi: alternative TryParse to permit both '.' and ',' for decimal point
\r
5214 // EU諸国での #BPM 123,45 のような記述に対応するため、
\r
5215 // 小数点の最終位置を検出して、それをlocaleにあった
\r
5216 // 文字に置き換えてからTryParse()する
\r
5219 const string DecimalSeparators = ".,"; // 小数点文字
\r
5220 const string GroupSeparators = ".,' "; // 桁区切り文字
\r
5221 const string NumberSymbols = "0123456789"; // 数値文字
\r
5223 int len = s.Length; // 文字列長
\r
5224 int decimalPosition = len; // 真の小数点の位置 最初は文字列終端位置に仮置きする
\r
5226 for (int i = 0; i < len; i++) { // まず、真の小数点(一番最後に現れる小数点)の位置を求める
\r
5228 if (NumberSymbols.IndexOf(c) >= 0) { // 数値だったらスキップ
\r
5230 } else if (DecimalSeparators.IndexOf(c) >= 0) { // 小数点文字だったら、その都度位置を上書き記憶
\r
5231 decimalPosition = i;
\r
5232 } else if (GroupSeparators.IndexOf(c) >= 0) { // 桁区切り文字の場合もスキップ
\r
5234 } else { // 数値・小数点・区切り文字以外がきたらループ終了
\r
5239 StringBuilder decimalStr = new StringBuilder(16);
\r
5240 for (int i = 0; i < len; i++) { // 次に、localeにあった数値文字列を生成する
\r
5242 if (NumberSymbols.IndexOf(c) >= 0) { // 数値だったら
\r
5243 decimalStr.Append(c); // そのままコピー
\r
5244 } else if (DecimalSeparators.IndexOf(c) >= 0) { // 小数点文字だったら
\r
5245 if (i == decimalPosition) { // 最後に出現した小数点文字なら、localeに合った小数点を出力する
\r
5246 decimalStr.Append(CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator);
\r
5248 } else if (GroupSeparators.IndexOf(c) >= 0) { // 桁区切り文字だったら
\r
5249 continue; // 何もしない(スキップ)
\r
5254 return double.TryParse(decimalStr.ToString(), out result); // 最後に、自分のlocale向けの文字列に対してTryParse実行
\r
5257 //-----------------
\r