OSDN Git Service

#37177 キーアサインでPOVを登録すると、同じ方向のHATが消える問題を修正。
[dtxmania/dtxmania.git] / DTXCreatorプロジェクト / コード / 07.MIDIインポート / CMIDI.cs
1 using System;\r
2 using System.Collections.Generic;\r
3 using System.Linq;\r
4 using System.Text;\r
5 using System.Threading.Tasks;\r
6 using System.Windows.Forms;\r
7 using System.IO;\r
8 using System.Drawing;\r
9 using System.Diagnostics;\r
10 using DTXCreator.WAV_BMP_AVI;\r
11 \r
12 namespace DTXCreator.MIDIインポート\r
13 {\r
14     internal class CMIDI\r
15     {\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
25         public int n分解能;\r
26         public Cメインフォーム formメインフォーム;\r
27                 public List<CMIDIイベント> lMIDIWAV;\r
28                 public int n重複チップ数;\r
29                 public DataGridView dgvチャンネル一覧;\r
30                 public bool[] bドラムチャンネルと思われる;\r
31 \r
32         public int dトラック数\r
33         {\r
34             get\r
35             {\r
36                 return lMIDIトラック.Count;\r
37             }\r
38         }\r
39 \r
40         public CMIDI( string _strファイル名 )\r
41         {\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
49                         this.f先頭BPM = 0.0f;\r
50                         this.n重複チップ数 = 0;\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
55                 }\r
56 \r
57         // 解析処理 全バイナリを見てMTrkだけ抜き取る\r
58         public void tMIDIを解析する()\r
59         {\r
60             // MThdが存在しなければ解析処理を行わない\r
61             if ( !bMIDIファイル ) return;\r
62                         this.lMIDIWAV = new List<CMIDIイベント>();\r
63 \r
64                         this.n分解能 = nBin2Int( this.byMIDIバイナリ, 12, 2 );\r
65 \r
66             for ( int i = 0; i<this.byMIDIバイナリ.Length; i++ )\r
67             {\r
68                 // MTrkがあればトラックを追加する\r
69                 if ( strBin2BinStr(this.byMIDIバイナリ, i, 4) == "4D 54 72 6B" )\r
70                 {\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
76                 }\r
77             }\r
78         }\r
79 \r
80                 // tMIDIチップをレーンに割り当てる()をCMIDIインポートダイアログに移動\r
81 \r
82 \r
83         // バイナリの指定のバイト数分を、"FF FF FF..."の形で出力する\r
84         static public string strBin2BinStr( byte[] byバイナリ, int d開始バイト, int dバイト数 )\r
85         {\r
86             string str文字列 = "";\r
87 \r
88             if ( dバイト数 <= 0 ) return "";\r
89 \r
90             for (int i = d開始バイト; i < d開始バイト + dバイト数; i++)\r
91             {\r
92                 if ( i >= byバイナリ.Length ) break;\r
93                 str文字列 += byバイナリ[i].ToString("X2") + " ";\r
94             }\r
95 \r
96             return str文字列.Substring( 0, str文字列.Length-1 );\r
97         }\r
98         \r
99         // バイナリの指定のバイト数分を、文字列に変換して出力する\r
100         static public string strBin2Str( byte[] byバイナリ, int d開始バイト, int dバイト数 )\r
101         {\r
102             string str文字列 = "";\r
103 \r
104             if ( dバイト数 <= 0 ) return "";\r
105 \r
106                         byte[] by出力 = new byte[ dバイト数 + 1 ];\r
107 \r
108             for (int i = d開始バイト; i < d開始バイト + dバイト数; i++)\r
109             {\r
110                 if ( i >= byバイナリ.Length ) break;\r
111                 by出力[i-d開始バイト] = byバイナリ[i];\r
112             }\r
113 \r
114                         if ( by出力[ 0 ] == 0 ) str文字列 = "";\r
115 \r
116                         System.Text.Encoding enc = GetCode( by出力 );                 //System.Text.Encoding.Default; //GetEncoding( "shift_jis" );\r
117                         if ( enc == null )\r
118                         {\r
119                                 enc = System.Text.Encoding.Unicode;\r
120                         }\r
121                         str文字列 = enc.GetString( by出力 );\r
122 \r
123             return str文字列.Trim('\0');\r
124         }\r
125         \r
126         // バイナリの指定のバイト数分を、数値に変換して出力する\r
127         static public int nBin2Int( byte[] byバイナリ, int d開始バイト, int dバイト数 )\r
128         {\r
129             int d数値 = 0;\r
130 \r
131             if ( dバイト数 <= 0 ) return 0;\r
132 \r
133             for (int i = d開始バイト; i < d開始バイト + dバイト数; i++)\r
134             {\r
135                 if ( i >= byバイナリ.Length ) break;\r
136                 d数値 += byバイナリ[i] * (int)Math.Pow( 256, dバイト数 - ( i - d開始バイト ) - 1 );\r
137             }\r
138 \r
139             return d数値;\r
140         }\r
141 \r
142                 /// <summary>\r
143                 /// 文字コードを判別する\r
144                 /// </summary>\r
145                 /// <remarks>\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
150                 /// </remarks>\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
155                 {\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
165 \r
166                         int len = bytes.Length;\r
167                         if (bytes[ len - 1 ] == 0x00 )\r
168                         {\r
169                                 --len;\r
170                         }\r
171                         byte b1, b2, b3, b4;\r
172 \r
173                         bool ascii = true;\r
174                         for ( int i = 0; i < len; i++ )\r
175                         {\r
176                                 b1 = bytes[ i ];\r
177                                 if ( !( b1 >= 0x20 && b1 <= 0x7E ) )\r
178                                 {\r
179                                         ascii = false;\r
180                                         break;\r
181                                 }\r
182                         }\r
183                         if ( ascii )\r
184                         {\r
185                                 return System.Text.Encoding.ASCII;\r
186                         }\r
187 \r
188                         //Encode::is_utf8 は無視\r
189 \r
190                         bool isBinary = false;\r
191                         for ( int i = 0; i < len; i++ )\r
192                         {\r
193                                 b1 = bytes[ i ];\r
194                                 if ( b1 <= 0x06 || b1 == 0x7F || b1 == 0xFF )\r
195                                 {\r
196                                         //'binary'\r
197                                         isBinary = true;\r
198                                         if ( b1 == 0x00 && i < len - 1 && bytes[ i + 1 ] <= 0x7F )\r
199                                         {\r
200                                                 //smells like raw unicode\r
201                                                 return System.Text.Encoding.Unicode;\r
202                                         }\r
203                                 }\r
204                         }\r
205                         if ( isBinary )\r
206                         {\r
207                                 return null;\r
208                         }\r
209 \r
210                         //not Japanese\r
211                         bool notJapanese = true;\r
212                         for ( int i = 0; i < len; i++ )\r
213                         {\r
214                                 b1 = bytes[ i ];\r
215                                 if ( b1 == bEscape || 0x80 <= b1 )\r
216                                 {\r
217                                         notJapanese = false;\r
218                                         break;\r
219                                 }\r
220                         }\r
221                         if ( notJapanese )\r
222                         {\r
223                                 return System.Text.Encoding.ASCII;\r
224                         }\r
225 \r
226                         for ( int i = 0; i < len - 2; i++ )\r
227                         {\r
228                                 b1 = bytes[ i ];\r
229                                 b2 = bytes[ i + 1 ];\r
230                                 b3 = bytes[ i + 2 ];\r
231 \r
232                                 if ( b1 == bEscape )\r
233                                 {\r
234                                         if ( b2 == bDollar && b3 == bAt )\r
235                                         {\r
236                                                 //JIS_0208 1978\r
237                                                 //JIS\r
238                                                 return System.Text.Encoding.GetEncoding( 50220 );\r
239                                         }\r
240                                         else if ( b2 == bDollar && b3 == bB )\r
241                                         {\r
242                                                 //JIS_0208 1983\r
243                                                 //JIS\r
244                                                 return System.Text.Encoding.GetEncoding( 50220 );\r
245                                         }\r
246                                         else if ( b2 == bOpen && ( b3 == bB || b3 == bJ ) )\r
247                                         {\r
248                                                 //JIS_ASC\r
249                                                 //JIS\r
250                                                 return System.Text.Encoding.GetEncoding( 50220 );\r
251                                         }\r
252                                         else if ( b2 == bOpen && b3 == bI )\r
253                                         {\r
254                                                 //JIS_KANA\r
255                                                 //JIS\r
256                                                 return System.Text.Encoding.GetEncoding( 50220 );\r
257                                         }\r
258                                         if ( i < len - 3 )\r
259                                         {\r
260                                                 b4 = bytes[ i + 3 ];\r
261                                                 if ( b2 == bDollar && b3 == bOpen && b4 == bD )\r
262                                                 {\r
263                                                         //JIS_0212\r
264                                                         //JIS\r
265                                                         return System.Text.Encoding.GetEncoding( 50220 );\r
266                                                 }\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
270                                                 {\r
271                                                         //JIS_0208 1990\r
272                                                         //JIS\r
273                                                         return System.Text.Encoding.GetEncoding( 50220 );\r
274                                                 }\r
275                                         }\r
276                                 }\r
277                         }\r
278 \r
279                         //should be euc|sjis|utf8\r
280                         //use of (?:) by Hiroki Ohzaki <ohzaki@iod.ricoh.co.jp>\r
281                         int sjis = 0;\r
282                         int euc = 0;\r
283                         int utf8 = 0;\r
284                         for ( int i = 0; i < len - 1; i++ )\r
285                         {\r
286                                 b1 = bytes[ 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
290                                 {\r
291                                         //SJIS_C\r
292                                         sjis += 2;\r
293                                         i++;\r
294                                 }\r
295                         }\r
296                         for ( int i = 0; i < len - 1; i++ )\r
297                         {\r
298                                 b1 = bytes[ 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
302                                 {\r
303                                         //EUC_C\r
304                                         //EUC_KANA\r
305                                         euc += 2;\r
306                                         i++;\r
307                                 }\r
308                                 else if ( i < len - 2 )\r
309                                 {\r
310                                         b3 = bytes[ i + 2 ];\r
311                                         if ( b1 == 0x8F && ( 0xA1 <= b2 && b2 <= 0xFE ) &&\r
312                                                 ( 0xA1 <= b3 && b3 <= 0xFE ) )\r
313                                         {\r
314                                                 //EUC_0212\r
315                                                 euc += 3;\r
316                                                 i += 2;\r
317                                         }\r
318                                 }\r
319                         }\r
320                         for ( int i = 0; i < len - 1; i++ )\r
321                         {\r
322                                 b1 = bytes[ i ];\r
323                                 b2 = bytes[ i + 1 ];\r
324                                 if ( ( 0xC0 <= b1 && b1 <= 0xDF ) && ( 0x80 <= b2 && b2 <= 0xBF ) )\r
325                                 {\r
326                                         //UTF8\r
327                                         utf8 += 2;\r
328                                         i++;\r
329                                 }\r
330                                 else if ( i < len - 2 )\r
331                                 {\r
332                                         b3 = bytes[ i + 2 ];\r
333                                         if ( ( 0xE0 <= b1 && b1 <= 0xEF ) && ( 0x80 <= b2 && b2 <= 0xBF ) &&\r
334                                                 ( 0x80 <= b3 && b3 <= 0xBF ) )\r
335                                         {\r
336                                                 //UTF8\r
337                                                 utf8 += 3;\r
338                                                 i += 2;\r
339                                         }\r
340                                 }\r
341                         }\r
342                         //M. Takahashi's suggestion\r
343                         //utf8 += utf8 / 2;\r
344 \r
345                         //Debug.WriteLine(\r
346                         //      string.Format( "sjis = {0}, euc = {1}, utf8 = {2}", sjis, euc, utf8 ) );\r
347                         if ( euc > sjis && euc > utf8 )\r
348                         {\r
349                                 //EUC\r
350                                 return System.Text.Encoding.GetEncoding( 51932 );\r
351                         }\r
352                         else if ( sjis > euc && sjis > utf8 )\r
353                         {\r
354                                 //SJIS\r
355                                 return System.Text.Encoding.GetEncoding( 932 );\r
356                         }\r
357                         else if ( utf8 > euc && utf8 > sjis )\r
358                         {\r
359                                 //UTF8\r
360                                 return System.Text.Encoding.UTF8;\r
361                         }\r
362 \r
363                         return null;\r
364                 }\r
365         }\r
366 \r
367 }\r