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
24 public int [] nチャンネル0to15毎のノート数;
\r
26 public Cメインフォーム formメインフォーム;
\r
27 public List<CMIDIイベント> lMIDIWAV;
\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.nチャンネル0to15毎のノート数 = 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
80 // tMIDIチップをレーンに割り当てる()をCMIDIインポートダイアログに移動
\r
83 // バイナリの指定のバイト数分を、"FF FF FF..."の形で出力する
\r
84 static public string strBin2BinStr( byte[] byバイナリ, int d開始バイト, int dバイト数 )
\r
88 if ( dバイト数 <= 0 ) return "";
\r
90 for (int i = d開始バイト; i < d開始バイト + dバイト数; i++)
\r
92 if ( i >= byバイナリ.Length ) break;
\r
93 str文字列 += byバイナリ[i].ToString("X2") + " ";
\r
96 return str文字列.Substring( 0, str文字列.Length-1 );
\r
99 // バイナリの指定のバイト数分を、文字列に変換して出力する
\r
100 static public string strBin2Str( byte[] byバイナリ, int d開始バイト, int dバイト数 )
\r
102 string str文字列 = "";
\r
104 if ( dバイト数 <= 0 ) return "";
\r
106 byte[] by出力 = new byte[ dバイト数 + 1 ];
\r
108 for (int i = d開始バイト; i < d開始バイト + dバイト数; i++)
\r
110 if ( i >= byバイナリ.Length ) break;
\r
111 by出力[i-d開始バイト] = byバイナリ[i];
\r
114 if ( by出力[ 0 ] == 0 ) str文字列 = "";
\r
116 System.Text.Encoding enc = GetCode( by出力 ); //System.Text.Encoding.Default; //GetEncoding( "shift_jis" );
\r
119 enc = System.Text.Encoding.Unicode;
\r
121 str文字列 = enc.GetString( by出力 );
\r
123 return str文字列.Trim('\0');
\r
126 // バイナリの指定のバイト数分を、数値に変換して出力する
\r
127 static public int nBin2Int( byte[] byバイナリ, int d開始バイト, int dバイト数 )
\r
131 if ( dバイト数 <= 0 ) return 0;
\r
133 for (int i = d開始バイト; i < d開始バイト + dバイト数; i++)
\r
135 if ( i >= byバイナリ.Length ) break;
\r
136 d数値 += byバイナリ[i] * (int)Math.Pow( 256, dバイト数 - ( i - d開始バイト ) - 1 );
\r
146 /// http://dobon.net/vb/dotnet/string/detectcode.html を少し修正したもの。
\r
147 /// Jcode.pmのgetcodeメソッドを移植したものです。
\r
148 /// Jcode.pm(http://openlab.ring.gr.jp/Jcode/index-j.html)
\r
149 /// Jcode.pmのCopyright: Copyright 1999-2005 Dan Kogai
\r
151 /// <param name="bytes">文字コードを調べるデータ</param>
\r
152 /// <returns>適当と思われるEncodingオブジェクト。
\r
153 /// 判断できなかった時はnull。</returns>
\r
154 public static System.Text.Encoding GetCode( byte[] bytes )
\r
156 const byte bEscape = 0x1B;
\r
157 const byte bAt = 0x40;
\r
158 const byte bDollar = 0x24;
\r
159 const byte bAnd = 0x26;
\r
160 const byte bOpen = 0x28; //'('
\r
161 const byte bB = 0x42;
\r
162 const byte bD = 0x44;
\r
163 const byte bJ = 0x4A;
\r
164 const byte bI = 0x49;
\r
166 int len = bytes.Length;
\r
167 if (bytes[ len - 1 ] == 0x00 )
\r
171 byte b1, b2, b3, b4;
\r
174 for ( int i = 0; i < len; i++ )
\r
177 if ( !( b1 >= 0x20 && b1 <= 0x7E ) )
\r
185 return System.Text.Encoding.ASCII;
\r
188 //Encode::is_utf8 は無視
\r
190 bool isBinary = false;
\r
191 for ( int i = 0; i < len; i++ )
\r
194 if ( b1 <= 0x06 || b1 == 0x7F || b1 == 0xFF )
\r
198 if ( b1 == 0x00 && i < len - 1 && bytes[ i + 1 ] <= 0x7F )
\r
200 //smells like raw unicode
\r
201 return System.Text.Encoding.Unicode;
\r
211 bool notJapanese = true;
\r
212 for ( int i = 0; i < len; i++ )
\r
215 if ( b1 == bEscape || 0x80 <= b1 )
\r
217 notJapanese = false;
\r
223 return System.Text.Encoding.ASCII;
\r
226 for ( int i = 0; i < len - 2; i++ )
\r
229 b2 = bytes[ i + 1 ];
\r
230 b3 = bytes[ i + 2 ];
\r
232 if ( b1 == bEscape )
\r
234 if ( b2 == bDollar && b3 == bAt )
\r
238 return System.Text.Encoding.GetEncoding( 50220 );
\r
240 else if ( b2 == bDollar && b3 == bB )
\r
244 return System.Text.Encoding.GetEncoding( 50220 );
\r
246 else if ( b2 == bOpen && ( b3 == bB || b3 == bJ ) )
\r
250 return System.Text.Encoding.GetEncoding( 50220 );
\r
252 else if ( b2 == bOpen && b3 == bI )
\r
256 return System.Text.Encoding.GetEncoding( 50220 );
\r
260 b4 = bytes[ i + 3 ];
\r
261 if ( b2 == bDollar && b3 == bOpen && b4 == bD )
\r
265 return System.Text.Encoding.GetEncoding( 50220 );
\r
267 if ( i < len - 5 &&
\r
268 b2 == bAnd && b3 == bAt && b4 == bEscape &&
\r
269 bytes[ i + 4 ] == bDollar && bytes[ i + 5 ] == bB )
\r
273 return System.Text.Encoding.GetEncoding( 50220 );
\r
279 //should be euc|sjis|utf8
\r
280 //use of (?:) by Hiroki Ohzaki <ohzaki@iod.ricoh.co.jp>
\r
284 for ( int i = 0; i < len - 1; i++ )
\r
287 b2 = bytes[ i + 1 ];
\r
288 if ( ( ( 0x81 <= b1 && b1 <= 0x9F ) || ( 0xE0 <= b1 && b1 <= 0xFC ) ) &&
\r
289 ( ( 0x40 <= b2 && b2 <= 0x7E ) || ( 0x80 <= b2 && b2 <= 0xFC ) ) )
\r
296 for ( int i = 0; i < len - 1; i++ )
\r
299 b2 = bytes[ i + 1 ];
\r
300 if ( ( ( 0xA1 <= b1 && b1 <= 0xFE ) && ( 0xA1 <= b2 && b2 <= 0xFE ) ) ||
\r
301 ( b1 == 0x8E && ( 0xA1 <= b2 && b2 <= 0xDF ) ) )
\r
308 else if ( i < len - 2 )
\r
310 b3 = bytes[ i + 2 ];
\r
311 if ( b1 == 0x8F && ( 0xA1 <= b2 && b2 <= 0xFE ) &&
\r
312 ( 0xA1 <= b3 && b3 <= 0xFE ) )
\r
320 for ( int i = 0; i < len - 1; i++ )
\r
323 b2 = bytes[ i + 1 ];
\r
324 if ( ( 0xC0 <= b1 && b1 <= 0xDF ) && ( 0x80 <= b2 && b2 <= 0xBF ) )
\r
330 else if ( i < len - 2 )
\r
332 b3 = bytes[ i + 2 ];
\r
333 if ( ( 0xE0 <= b1 && b1 <= 0xEF ) && ( 0x80 <= b2 && b2 <= 0xBF ) &&
\r
334 ( 0x80 <= b3 && b3 <= 0xBF ) )
\r
342 //M. Takahashi's suggestion
\r
343 //utf8 += utf8 / 2;
\r
346 // string.Format( "sjis = {0}, euc = {1}, utf8 = {2}", sjis, euc, utf8 ) );
\r
347 if ( euc > sjis && euc > utf8 )
\r
350 return System.Text.Encoding.GetEncoding( 51932 );
\r
352 else if ( sjis > euc && sjis > utf8 )
\r
355 return System.Text.Encoding.GetEncoding( 932 );
\r
357 else if ( utf8 > euc && utf8 > sjis )
\r
360 return System.Text.Encoding.UTF8;
\r