2 using System.Collections.Generic;
\r
5 using System.Threading.Tasks;
\r
6 using System.Windows.Forms;
\r
8 using System.Drawing;
\r
9 using System.Diagnostics;
\r
10 using DTXCreator.WAV_BMP_AVI;
\r
12 namespace DTXCreator.MIDIインポート
\r
14 internal class CMIDI
\r
16 public string strファイル名;
\r
17 public byte[] byMIDIバイナリ;
\r
18 public bool bMIDIファイル;
\r
19 public List<CMIDIトラック> lMIDIトラック;
\r
20 public List<CMIDIイベント> lMIDIイベント;
\r
21 public float f先頭BPM;
\r
22 public string strTimeSignature;
\r
23 public int[] nドラム各ノート数;
\r
25 public Cメインフォーム formメインフォーム;
\r
26 public List<CMIDIイベント> lMIDIWAV;
\r
28 public int [] lチャンネル毎のノート数1to16;
\r
29 public DataGridView dgvチャンネル一覧;
\r
30 public bool[] bドラムチャンネルと思われる;
\r
36 return lMIDIトラック.Count;
\r
40 public CMIDI( string _strファイル名 )
\r
42 this.strファイル名 = _strファイル名;
\r
43 this.byMIDIバイナリ = File.ReadAllBytes( this.strファイル名 );
\r
44 this.bMIDIファイル = ( strBin2BinStr(this.byMIDIバイナリ, 0, 4) == "4D 54 68 64" );
\r
45 this.lMIDIトラック = new List<CMIDIトラック>();
\r
46 this.lMIDIイベント = new List<CMIDIイベント>();
\r
47 this.nドラム各ノート数 = new int[256];
\r
48 this.lMIDIWAV = new List<CMIDIイベント>();
\r
51 this.lチャンネル毎のノート数1to16 = new int[17];
\r
52 this.dgvチャンネル一覧 = null;
\r
53 this.bドラムチャンネルと思われる = new bool[ 16 * 4 ];
\r
54 this.bドラムチャンネルと思われる[ 10 - 1 ] = true;
\r
57 // 解析処理 全バイナリを見てMTrkだけ抜き取る
\r
58 public void tMIDIを解析する()
\r
60 // MThdが存在しなければ解析処理を行わない
\r
61 if ( !bMIDIファイル ) return;
\r
62 this.lMIDIWAV = new List<CMIDIイベント>();
\r
64 this.n分解能 = nBin2Int( this.byMIDIバイナリ, 12, 2 );
\r
66 for ( int i = 0; i<this.byMIDIバイナリ.Length; i++ )
\r
68 // MTrkがあればトラックを追加する
\r
69 if ( strBin2BinStr(this.byMIDIバイナリ, i, 4) == "4D 54 72 6B" )
\r
71 int track_size = nBin2Int( this.byMIDIバイナリ, i + 4, 4 );
\r
72 byte[] data_track = new byte[track_size + 8 + 8]; // 大きめに取りました
\r
73 Array.Copy( this.byMIDIバイナリ, i, data_track, 0, nBin2Int( this.byMIDIバイナリ, i+4, 4 ) + 8 );
\r
74 this.lMIDIトラック.Add( new CMIDIトラック( this, this.dトラック数, data_track ) );
\r
75 this.lMIDIトラック[this.lMIDIトラック.Count-1].tトラックチャンクを走査する();
\r
81 /// dgv割り当て一覧で設定した値に応じて、各レーンへ振り分ける
\r
83 public void tMIDIチップをレーンに割り当てる( DataGridView dgv割り当て一覧 )
\r
85 // MIDIイベントがひとつでもあるなら処理する
\r
86 if ( this.lMIDIイベント.Count == 0 ) return;
\r
89 foreach ( CMIDIイベント vMIDIイベント in this.lMIDIイベント )
\r
91 foreach (DataGridViewRow dgvr in dgv割り当て一覧.Rows)
\r
93 if (vMIDIイベント.nキー == (int)dgvr.Cells["MIDI_Key"].Value )
\r
95 if ( (string)dgvr.Cells["DTX_Lane"].Value != "* Disuse *" )
\r
97 vMIDIイベント.nレーン番号 = this.formメインフォーム.mgr譜面管理者.nレーン名に対応するレーン番号を返す( (string)dgvr.Cells["DTX_Lane"].Value );
\r
98 vMIDIイベント.strコメント = (string)dgvr.Cells["Comment"].Value;
\r
99 vMIDIイベント.b裏チャンネル = (bool)dgvr.Cells["BackCH"].Value;
\r
100 vMIDIイベント.b入力 = true;
\r
104 vMIDIイベント.nレーン番号 = 0;
\r
105 vMIDIイベント.strコメント = "";
\r
106 vMIDIイベント.b裏チャンネル = false;
\r
107 vMIDIイベント.b入力 = false;
\r
109 if ( vMIDIイベント.eイベントタイプ == CMIDIイベント.Eイベントタイプ.BPM ||
\r
110 vMIDIイベント.eイベントタイプ == CMIDIイベント.Eイベントタイプ.BarLen )
\r
112 vMIDIイベント.b入力 = true;
\r
119 #region [ WAVリスト化する ]
\r
120 this.lMIDIWAV = new List<CMIDIイベント>();
\r
122 foreach ( CMIDIイベント vMIDIイベント in this.lMIDIイベント )
\r
124 // WAVリストで、同じ内容(キーとベロシティ)が無ければ挿入する
\r
125 bool bMIDIWAV_AddFlag = true;
\r
126 foreach ( CMIDIイベント vMIDIWAV in this.lMIDIWAV )
\r
128 if ( vMIDIWAV.strWAV重複チェック == vMIDIイベント.strWAV重複チェック )
\r
130 bMIDIWAV_AddFlag = false;
\r
134 if (bMIDIWAV_AddFlag)
\r
136 this.lMIDIWAV.Add( vMIDIイベント );
\r
141 #region [ キーが違うが同時刻で同じレーンに配置予定のチップを数える ]
\r
143 foreach ( CMIDIイベント v1 in this.lMIDIイベント )
\r
145 foreach ( CMIDIイベント v2 in this.lMIDIイベント )
\r
147 if ( v1.nキー != v2.nキー && v1.nレーン番号 == v2.nレーン番号 && v1.n時間 == v2.n時間 )
\r
158 // バイナリの指定のバイト数分を、"FF FF FF..."の形で出力する
\r
159 static public string strBin2BinStr( byte[] byバイナリ, int d開始バイト, int dバイト数 )
\r
161 string str文字列 = "";
\r
163 if ( dバイト数 <= 0 ) return "";
\r
165 for (int i = d開始バイト; i < d開始バイト + dバイト数; i++)
\r
167 if ( i >= byバイナリ.Length ) break;
\r
168 str文字列 += byバイナリ[i].ToString("X2") + " ";
\r
171 return str文字列.Substring( 0, str文字列.Length-1 );
\r
174 // バイナリの指定のバイト数分を、文字列に変換して出力する
\r
175 static public string strBin2Str( byte[] byバイナリ, int d開始バイト, int dバイト数 )
\r
177 string str文字列 = "";
\r
179 if ( dバイト数 <= 0 ) return "";
\r
181 byte[] by出力 = new byte[ dバイト数 + 1 ];
\r
183 for (int i = d開始バイト; i < d開始バイト + dバイト数; i++)
\r
185 if ( i >= byバイナリ.Length ) break;
\r
186 by出力[i-d開始バイト] = byバイナリ[i];
\r
189 if ( by出力[ 0 ] == 0 ) str文字列 = "";
\r
191 System.Text.Encoding enc = GetCode( by出力 ); //System.Text.Encoding.Default; //GetEncoding( "shift_jis" );
\r
194 enc = System.Text.Encoding.Unicode;
\r
196 str文字列 = enc.GetString( by出力 );
\r
198 return str文字列.Trim('\0');
\r
201 // バイナリの指定のバイト数分を、数値に変換して出力する
\r
202 static public int nBin2Int( byte[] byバイナリ, int d開始バイト, int dバイト数 )
\r
206 if ( dバイト数 <= 0 ) return 0;
\r
208 for (int i = d開始バイト; i < d開始バイト + dバイト数; i++)
\r
210 if ( i >= byバイナリ.Length ) break;
\r
211 d数値 += byバイナリ[i] * (int)Math.Pow( 256, dバイト数 - ( i - d開始バイト ) - 1 );
\r
221 /// http://dobon.net/vb/dotnet/string/detectcode.html を少し修正したもの。
\r
222 /// Jcode.pmのgetcodeメソッドを移植したものです。
\r
223 /// Jcode.pm(http://openlab.ring.gr.jp/Jcode/index-j.html)
\r
224 /// Jcode.pmのCopyright: Copyright 1999-2005 Dan Kogai
\r
226 /// <param name="bytes">文字コードを調べるデータ</param>
\r
227 /// <returns>適当と思われるEncodingオブジェクト。
\r
228 /// 判断できなかった時はnull。</returns>
\r
229 public static System.Text.Encoding GetCode( byte[] bytes )
\r
231 const byte bEscape = 0x1B;
\r
232 const byte bAt = 0x40;
\r
233 const byte bDollar = 0x24;
\r
234 const byte bAnd = 0x26;
\r
235 const byte bOpen = 0x28; //'('
\r
236 const byte bB = 0x42;
\r
237 const byte bD = 0x44;
\r
238 const byte bJ = 0x4A;
\r
239 const byte bI = 0x49;
\r
241 int len = bytes.Length;
\r
242 if (bytes[ len - 1 ] == 0x00 )
\r
246 byte b1, b2, b3, b4;
\r
249 for ( int i = 0; i < len; i++ )
\r
252 if ( !( b1 >= 0x20 && b1 <= 0x7E ) )
\r
260 return System.Text.Encoding.ASCII;
\r
263 //Encode::is_utf8 は無視
\r
265 bool isBinary = false;
\r
266 for ( int i = 0; i < len; i++ )
\r
269 if ( b1 <= 0x06 || b1 == 0x7F || b1 == 0xFF )
\r
273 if ( b1 == 0x00 && i < len - 1 && bytes[ i + 1 ] <= 0x7F )
\r
275 //smells like raw unicode
\r
276 return System.Text.Encoding.Unicode;
\r
286 bool notJapanese = true;
\r
287 for ( int i = 0; i < len; i++ )
\r
290 if ( b1 == bEscape || 0x80 <= b1 )
\r
292 notJapanese = false;
\r
298 return System.Text.Encoding.ASCII;
\r
301 for ( int i = 0; i < len - 2; i++ )
\r
304 b2 = bytes[ i + 1 ];
\r
305 b3 = bytes[ i + 2 ];
\r
307 if ( b1 == bEscape )
\r
309 if ( b2 == bDollar && b3 == bAt )
\r
313 return System.Text.Encoding.GetEncoding( 50220 );
\r
315 else if ( b2 == bDollar && b3 == bB )
\r
319 return System.Text.Encoding.GetEncoding( 50220 );
\r
321 else if ( b2 == bOpen && ( b3 == bB || b3 == bJ ) )
\r
325 return System.Text.Encoding.GetEncoding( 50220 );
\r
327 else if ( b2 == bOpen && b3 == bI )
\r
331 return System.Text.Encoding.GetEncoding( 50220 );
\r
335 b4 = bytes[ i + 3 ];
\r
336 if ( b2 == bDollar && b3 == bOpen && b4 == bD )
\r
340 return System.Text.Encoding.GetEncoding( 50220 );
\r
342 if ( i < len - 5 &&
\r
343 b2 == bAnd && b3 == bAt && b4 == bEscape &&
\r
344 bytes[ i + 4 ] == bDollar && bytes[ i + 5 ] == bB )
\r
348 return System.Text.Encoding.GetEncoding( 50220 );
\r
354 //should be euc|sjis|utf8
\r
355 //use of (?:) by Hiroki Ohzaki <ohzaki@iod.ricoh.co.jp>
\r
359 for ( int i = 0; i < len - 1; i++ )
\r
362 b2 = bytes[ i + 1 ];
\r
363 if ( ( ( 0x81 <= b1 && b1 <= 0x9F ) || ( 0xE0 <= b1 && b1 <= 0xFC ) ) &&
\r
364 ( ( 0x40 <= b2 && b2 <= 0x7E ) || ( 0x80 <= b2 && b2 <= 0xFC ) ) )
\r
371 for ( int i = 0; i < len - 1; i++ )
\r
374 b2 = bytes[ i + 1 ];
\r
375 if ( ( ( 0xA1 <= b1 && b1 <= 0xFE ) && ( 0xA1 <= b2 && b2 <= 0xFE ) ) ||
\r
376 ( b1 == 0x8E && ( 0xA1 <= b2 && b2 <= 0xDF ) ) )
\r
383 else if ( i < len - 2 )
\r
385 b3 = bytes[ i + 2 ];
\r
386 if ( b1 == 0x8F && ( 0xA1 <= b2 && b2 <= 0xFE ) &&
\r
387 ( 0xA1 <= b3 && b3 <= 0xFE ) )
\r
395 for ( int i = 0; i < len - 1; i++ )
\r
398 b2 = bytes[ i + 1 ];
\r
399 if ( ( 0xC0 <= b1 && b1 <= 0xDF ) && ( 0x80 <= b2 && b2 <= 0xBF ) )
\r
405 else if ( i < len - 2 )
\r
407 b3 = bytes[ i + 2 ];
\r
408 if ( ( 0xE0 <= b1 && b1 <= 0xEF ) && ( 0x80 <= b2 && b2 <= 0xBF ) &&
\r
409 ( 0x80 <= b3 && b3 <= 0xBF ) )
\r
417 //M. Takahashi's suggestion
\r
418 //utf8 += utf8 / 2;
\r
421 // string.Format( "sjis = {0}, euc = {1}, utf8 = {2}", sjis, euc, utf8 ) );
\r
422 if ( euc > sjis && euc > utf8 )
\r
425 return System.Text.Encoding.GetEncoding( 51932 );
\r
427 else if ( sjis > euc && sjis > utf8 )
\r
430 return System.Text.Encoding.GetEncoding( 932 );
\r
432 else if ( utf8 > euc && utf8 > sjis )
\r
435 return System.Text.Encoding.UTF8;
\r