OSDN Git Service

#30333 [DTXC] インポートを更に高速化(正確には、低速になっていたのを元に戻した)
[dtxmania/dtxmania.git] / DTXCreatorプロジェクト / コード / 07.MIDIインポート / CMIDIインポートダイアログ.cs
1 using System;\r
2 using System.Collections;\r
3 using System.Collections.Generic;\r
4 using System.Text;\r
5 using System.Windows.Forms;\r
6 using System.ComponentModel;\r
7 using System.IO;\r
8 using System.Drawing;\r
9 using System.Diagnostics;\r
10 using DTXCreator.譜面;\r
11 using DTXCreator.WAV_BMP_AVI;\r
12 using DTXCreator.Properties;\r
13 \r
14 namespace DTXCreator.MIDIインポート\r
15 {\r
16     public partial class CMIDIインポートダイアログ : Form\r
17     {\r
18 \r
19         private CMIDI cMIDI;\r
20         public Cメインフォーム formメインフォーム;\r
21         private bool b一覧準備完了;\r
22                 private System.Resources.ResourceManager resource;\r
23                 \r
24         public CMIDIインポートダイアログ()\r
25         {\r
26             InitializeComponent();\r
27                         this.b一覧準備完了 = false;\r
28                         dgvチャンネル一覧変更イベント抑止();\r
29                         resource = new System.Resources.ResourceManager( this.GetType() );\r
30         }\r
31 \r
32                 public void dgvチャンネル一覧変更イベント抑止()\r
33                 {\r
34                         try\r
35                         {\r
36                                 dgvチャンネル一覧.CellValueChanged -= dgvチャンネル一覧_CellValueChanged;\r
37                         }\r
38                         catch ( Exception e )\r
39                         {\r
40                                 Debug.WriteLine( "dgvチャンネル一覧.CellValueChangedのイベントエントリ削除に失敗しましたが、続行します。{0}", e.Message );\r
41                         }\r
42                 }\r
43                 public void dgvチャンネル一覧変更イベント復旧()\r
44                 {\r
45                         dgvチャンネル一覧.CellValueChanged += dgvチャンネル一覧_CellValueChanged;\r
46                 }\r
47 \r
48                 private void CMIDIインポートダイアログ_KeyDown(object sender, KeyEventArgs e)\r
49         {\r
50             if ( e.KeyCode == Keys.Return )\r
51             {\r
52                 this.buttonOK.PerformClick();\r
53             }\r
54             else if ( e.KeyCode == Keys.Escape )\r
55             {\r
56                 this.buttonCancel.PerformClick();\r
57             }\r
58         }\r
59 \r
60                 private void dgvチャンネル一覧_CurrentCellDirtyStateChanged(object sender, EventArgs e)\r
61                 {\r
62                         if ( dgvチャンネル一覧.IsCurrentCellDirty )\r
63                         {\r
64                                 dgvチャンネル一覧.CommitEdit( DataGridViewDataErrorContexts.Commit );\r
65                         }\r
66                 }\r
67                 private void dgvチャンネル一覧_CellValueChanged( object sender, DataGridViewCellEventArgs e )\r
68                 {\r
69                         if ( cMIDI != null && this.b一覧準備完了 ) this.tMIDIファイルを開く( cMIDI.strファイル名 );\r
70                 }\r
71 \r
72         private void buttonOpen_Click(object sender, EventArgs e)\r
73         {\r
74             this.tMIDIファイルを選択する();\r
75         }\r
76 \r
77         public void tMIDI割り当て一覧を作成する()\r
78         {\r
79             // レーン一覧を作成\r
80             this.DTX_Lane.Items.AddRange( "* Disuse *" );\r
81             foreach ( Cレーン cレーン in this.formメインフォーム.mgr譜面管理者.listレーン )\r
82             {\r
83                                 if ( cレーン.eレーン種別 == Cレーン.E種別.WAV ) this.DTX_Lane.Items.AddRange( cレーン.strレーン名 );\r
84             }\r
85             \r
86             // MIDIキー一覧を作成\r
87             for ( int i = 127; i >= 0; i-- )\r
88             {\r
89                 string str楽器名 = "";\r
90                 string[] strキー名 = new string[] { "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B", };\r
91                 string strレーン名 = "* Disuse *";\r
92                                 bool b裏チャンネル = false;\r
93                 switch ( i )\r
94                 {\r
95                     case 35 : str楽器名 = "Bass Drum 2"; strレーン名 = "BD"; break;\r
96                     case 36 : str楽器名 = "Bass Drum 1"; strレーン名 = "BD"; break;\r
97                     case 37 : str楽器名 = "Side Stick"; strレーン名 = "SE1"; break;\r
98                     case 38 : str楽器名 = "Snare Drum 1"; strレーン名 = "SD"; break;\r
99                     case 39 : str楽器名 = "Hand Clap"; strレーン名 = "SE1"; break;\r
100                     case 40 : str楽器名 = "Snare Drum 2"; strレーン名 = "SD"; break;\r
101                     case 41 : str楽器名 = "Low Tom 2"; strレーン名 = "FT"; break;\r
102                     case 42 : str楽器名 = "Closed Hi-hat"; strレーン名 = "HH"; break;\r
103                     case 43 : str楽器名 = "Low Tom 1"; strレーン名 = "FT"; break;\r
104                     case 44 : str楽器名 = "Pedal Hi-hat"; strレーン名 = "LP"; break;\r
105                     case 45 : str楽器名 = "Mid Tom 2"; strレーン名 = "LT"; break;\r
106                     case 46 : str楽器名 = "Open Hi-hat"; strレーン名 = "HH"; b裏チャンネル = true; break;\r
107                     case 47 : str楽器名 = "Mid Tom 1"; strレーン名 = "LT"; break;\r
108                     case 48 : str楽器名 = "High Tom 2"; strレーン名 = "HT"; break;\r
109                     case 49 : str楽器名 = "Crash Cymbal 1"; strレーン名 = "CY"; break;\r
110                     case 50 : str楽器名 = "High Tom 1"; strレーン名 = "HT"; break;\r
111                     case 51 : str楽器名 = "Ride Cymbal 1"; strレーン名 = "CY"; b裏チャンネル = true; break;\r
112                     case 52 : str楽器名 = "Chinese Cymbal"; strレーン名 = "CY"; break;\r
113                     case 53 : str楽器名 = "Ride Bell"; strレーン名 = "CY"; b裏チャンネル = true; break;\r
114                     case 54 : str楽器名 = "Tambourine"; strレーン名 = "SE1"; break;\r
115                     case 55 : str楽器名 = "Splash Cymbal"; strレーン名 = "LC"; break;\r
116                     case 56 : str楽器名 = "Cowbell"; strレーン名 = "SE1"; break;\r
117                     case 57 : str楽器名 = "Crash Cymbal 2"; strレーン名 = "LC"; break;\r
118                     case 58 : str楽器名 = "Vibra Slap"; strレーン名 = "SE1"; break;\r
119                     case 59 : str楽器名 = "Ride Cymbal 2"; strレーン名 = "CY"; b裏チャンネル = true; break;\r
120                     case 60 : str楽器名 = "High Bongo"; break;\r
121                     case 61 : str楽器名 = "Low Bongo"; break;\r
122                     case 62 : str楽器名 = "Mute High Conga"; break;\r
123                     case 63 : str楽器名 = "Open High Conga"; break;\r
124                     case 64 : str楽器名 = "Low Conga"; break;\r
125                     case 65 : str楽器名 = "High Timbale"; break;\r
126                     case 66 : str楽器名 = "Low Timbale"; break;\r
127                     case 67 : str楽器名 = "High Agogo"; break;\r
128                     case 68 : str楽器名 = "Low Agogo"; break;\r
129                     case 69 : str楽器名 = "Cabasa"; break;\r
130                     case 70 : str楽器名 = "Maracas"; break;\r
131                     case 71 : str楽器名 = "Short Whistle"; break;\r
132                     case 72 : str楽器名 = "Long Whistle"; break;\r
133                     case 73 : str楽器名 = "Short Guiro"; break;\r
134                     case 74 : str楽器名 = "Long Guiro"; break;\r
135                     case 75 : str楽器名 = "Claves"; break;\r
136                     case 76 : str楽器名 = "High Wood Block"; break;\r
137                     case 77 : str楽器名 = "Low Wood Block"; break;\r
138                     case 78 : str楽器名 = "Mute Cuica"; break;\r
139                     case 79 : str楽器名 = "Open Cuica"; break;\r
140                     case 80 : str楽器名 = "Mute Triangle"; break;\r
141                     case 81 : str楽器名 = "Open Triangle"; break;\r
142                 }\r
143                 this.dgv割り当て一覧.Rows.Add( i, strキー名[i%12], strレーン名, b裏チャンネル, 0, str楽器名 );\r
144                 if ( i%12 == 1 || i%12 == 3 || i%12 == 6 || i%12 == 8 || i%12 == 10 ) this.dgv割り当て一覧.Rows[127-i].DefaultCellStyle.BackColor = Color.FromArgb( 240, 248, 255 );\r
145                 if ( i%12 == 0 ) this.dgv割り当て一覧.Rows[127-i].DefaultCellStyle.BackColor = Color.FromArgb( 255, 224, 224 );\r
146                 tMIDI割り当て一覧のレーン名の背景色を変更する( this.dgv割り当て一覧.RowCount-1 );\r
147 \r
148             }\r
149             this.dgv割り当て一覧.Columns["MIDI_Key"].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;\r
150             this.dgv割り当て一覧.Columns["DTX_Lane"].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;\r
151             this.dgv割り当て一覧.Columns["DTX_Lane"].DefaultCellStyle.Font = new Font( "meiryo", 8f, FontStyle.Bold );\r
152             this.dgv割り当て一覧.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;\r
153 \r
154             this.dgv割り当て一覧.FirstDisplayedScrollingRowIndex = 81;//key35=LBDが表示される位置\r
155 \r
156         }\r
157 \r
158         public void tMIDIチャンネル一覧を作成する()\r
159         {\r
160                         for (int i = 1; i <= 16; i++)\r
161                         {\r
162                                 this.dgvチャンネル一覧.Rows.Add( i, 0, (i==10) );\r
163                                 this.dgvチャンネル一覧.Rows[i-1].DefaultCellStyle.BackColor = (i==10) ? Color.FromArgb( 255, 224, 224 ) : Color.FromArgb( 255, 255, 255 );\r
164                         }\r
165                         this.b一覧準備完了 = true;\r
166                         //      dgvチャンネル一覧変更イベント復旧();     //ここでイベントを復旧してはいけない\r
167                                                                                                                 //(直後にファイルを開く動作+解析動作が発生するのでそこで)\r
168                                                                                                                 //ChangValueイベントが発生しファイルを開き直す動作が何度も発生してしまう\r
169                 }\r
170 \r
171         public void tMIDIファイルを選択する()\r
172         {\r
173             #region [ ファイル選択 ]\r
174             //-----------------\r
175 \r
176             OpenFileDialog dialog = new OpenFileDialog();\r
177             dialog.Title = "MIDIファイルを選択";\r
178             dialog.Filter = "MIDIファイル (*.mid,*.midi)|*.mid;*.midi|すべてのファイル (*.*)|*.*";\r
179             dialog.FilterIndex = 1;\r
180             dialog.InitialDirectory = this.formメインフォーム.strMIDIインポートフォルダ;\r
181             DialogResult result = dialog.ShowDialog();\r
182 \r
183             if (result != DialogResult.OK) return;\r
184 \r
185             //-----------------\r
186             #endregion\r
187 \r
188             this.tMIDIファイルを開く( dialog.FileName );\r
189         }\r
190 \r
191         public void tMIDIファイルを開く( string strファイル名 )\r
192         {\r
193             #region [ ファイル確認 ]\r
194             //-----------------\r
195             if ( !File.Exists( strファイル名 ) )\r
196             {\r
197                 MessageBox.Show(\r
198                     "ファイルが見つかりません。",\r
199                     "MIDIインポート",\r
200                     MessageBoxButtons.OK, MessageBoxIcon.Hand, MessageBoxDefaultButton.Button1);\r
201                 return;\r
202             }\r
203             //-----------------\r
204             #endregion\r
205 \r
206             #region [ 拡張子 ]\r
207             //-----------------\r
208             string str拡張子 = Path.GetExtension(strファイル名);\r
209 \r
210             if ( !str拡張子.Equals(".mid", StringComparison.OrdinalIgnoreCase ) && !str拡張子.Equals( ".midi", StringComparison.OrdinalIgnoreCase) )\r
211             {\r
212                 MessageBox.Show(\r
213                     "MIDIファイルではありません。",\r
214                     "MIDIインポート",\r
215                     MessageBoxButtons.OK, MessageBoxIcon.Hand, MessageBoxDefaultButton.Button1);\r
216                 return;\r
217             }\r
218             //-----------------\r
219             #endregion\r
220 \r
221                         #region [ 各設定 ]\r
222             //-----------------\r
223                         this.formメインフォーム.str作業フォルダ名 = Path.GetDirectoryName( strファイル名 ) + @"\";\r
224                         this.formメインフォーム.strMIDIインポートフォルダ = Path.GetDirectoryName( strファイル名 ) + @"\";\r
225             //-----------------\r
226             #endregion\r
227 \r
228             #region [ MIDIファイル解析 ]\r
229             //-----------------\r
230             cMIDI = new CMIDI( strファイル名 );\r
231             cMIDI.formメインフォーム = this.formメインフォーム;\r
232                         cMIDI.dgvチャンネル一覧 = this.dgvチャンネル一覧;\r
233             cMIDI.tMIDIを解析する();\r
234                         cMIDI.tMIDIチップをレーンに割り当てる( this.dgv割り当て一覧 );\r
235 \r
236                         this.label重複チップ数.Text = resource.GetString("label重複チップ数.Text") + " : " + cMIDI.n重複チップ数;\r
237                         \r
238             // ヘッダがMIDI以外なら中断\r
239             if ( !cMIDI.bMIDIファイル )\r
240             {\r
241                 MessageBox.Show(\r
242                     "MIDIファイルではありません。",\r
243                     "MIDIインポート",\r
244                     MessageBoxButtons.OK, MessageBoxIcon.Hand, MessageBoxDefaultButton.Button1);\r
245                                 cMIDI = null;\r
246                 return;\r
247             }\r
248             //-----------------\r
249             #endregion\r
250             \r
251             #region [ 解析結果を出力・処理 ]\r
252             //-----------------\r
253             // 各キーのノート数を表に出力する\r
254             for ( int i = 0 ; i < 128 ; i++ )\r
255                 this.dgv割り当て一覧.Rows[127-i].Cells["Notes"].Value = cMIDI.nドラム各ノート数[i];\r
256                         \r
257             // MIDI解析内容をテキストボックスに出力する\r
258             string str文字列 = "";\r
259             str文字列 += "File:" + strファイル名 + "\r\n";\r
260             str文字列 += "BPM:" + cMIDI.f先頭BPM + "\r\n";\r
261             str文字列 += "TimeBase:" + cMIDI.n分解能 + "\r\n";\r
262             str文字列 += "\r\n";\r
263             \r
264             foreach ( CMIDIトラック value in cMIDI.lMIDIトラック )\r
265             {\r
266                 str文字列 += "Track " + value.nトラック数;\r
267                 str文字列 += " : " + value.strトラック名 + "\r\n";\r
268                 str文字列 += value.str解析内容 + "\r\n";\r
269             }\r
270             \r
271             this.textBox1.Text = str文字列;\r
272 \r
273                         for ( int i = 1; i <= 16; i++ )\r
274                         {\r
275                                 this.dgvチャンネル一覧.Rows[i-1].Cells["ChNotes"].Value = this.cMIDI.lチャンネル毎のノート数1to16[i];\r
276                                 this.dgvチャンネル一覧.Rows[i-1].Cells["ChLoad"].Value  = this.cMIDI.bドラムチャンネルと思われる[i-1];\r
277                         }\r
278             //-----------------\r
279             #endregion\r
280 \r
281         }\r
282         \r
283         // レーン名をワンクリックで開く用\r
284         private void dgv割り当て一覧_CellEnter( object sender, DataGridViewCellEventArgs e )\r
285         {\r
286             DataGridView dgv割り当て一覧 = (DataGridView) sender;\r
287 \r
288             if ( dgv割り当て一覧.Columns[e.ColumnIndex].Name == "DTX_Lane" && dgv割り当て一覧.Columns[e.ColumnIndex] is DataGridViewComboBoxColumn )\r
289                 SendKeys.Send("{F4}");\r
290         }\r
291 \r
292                 // レーン名を変更したら\r
293         private void dgv割り当て一覧_CellEndEdit( object sender, DataGridViewCellEventArgs e )\r
294         {\r
295             DataGridView dgv割り当て一覧 = (DataGridView) sender;\r
296 \r
297             if ( dgv割り当て一覧.Columns[e.ColumnIndex].Name == "DTX_Lane" )\r
298                 tMIDI割り当て一覧のレーン名の背景色を変更する( e.RowIndex );\r
299                         \r
300             if ( cMIDI != null && this.b一覧準備完了 )\r
301                         {\r
302                                 cMIDI.tMIDIチップをレーンに割り当てる( dgv割り当て一覧 );\r
303                                 this.label重複チップ数.Text = resource.GetString("label重複チップ数.Text") + " : " + cMIDI.n重複チップ数;\r
304                                 \r
305                         }\r
306 \r
307         }\r
308                 \r
309                 /// <summary>\r
310                 /// レーン名変更時に呼び出される\r
311                 /// </summary>\r
312         private void tMIDI割り当て一覧のレーン名の背景色を変更する( int RowIndex )\r
313         {\r
314                         string strレーン名 = (string)this.dgv割り当て一覧.Rows[RowIndex].Cells["DTX_Lane"].Value;\r
315             int nレーン番号 = this.formメインフォーム.mgr譜面管理者.nレーン名に対応するレーン番号を返す( strレーン名 );\r
316 \r
317             if ( nレーン番号 >= this.formメインフォーム.mgr譜面管理者.nレーン名に対応するレーン番号を返す( "LC" ) )\r
318             {\r
319                 Color color = this.formメインフォーム.mgr譜面管理者.listレーン[nレーン番号].col背景色;\r
320                 color = Color.FromArgb( color.R/2+128, color.G/2+128, color.B/2+128 );\r
321                 this.dgv割り当て一覧.Rows[RowIndex].Cells["DTX_Lane"].Style.BackColor = color;\r
322             }\r
323                         else if ( strレーン名 == "* Disuse *" )\r
324                         {\r
325                 Color color = Color.FromArgb( 128, 128, 128 );\r
326                 this.dgv割り当て一覧.Rows[RowIndex].Cells["DTX_Lane"].Style.BackColor = color;\r
327                         }\r
328         }\r
329 \r
330         public void tMIDIインポート結果を反映する()\r
331         {\r
332             if ( cMIDI != null && cMIDI.lMIDIイベント.Count > 0 )\r
333             {\r
334                                 \r
335                                 #region [ チップリストで、ベロシティをDTX向けに調整する ]\r
336                                 foreach ( CMIDIイベント vMIDIイベント in cMIDI.lMIDIイベント )\r
337                                 {\r
338                                         int velo = vMIDIイベント.nベロシティ;\r
339                                         if ( this.checkBoxベロシティ最大値127.Checked ) velo = (int)(velo / 1.27);//127を最大値\r
340                                         if ( this.checkBoxベロシティカーブ調整.Checked ) velo = (int)( Math.Pow( velo, 1.5 ) / Math.Pow( 100, 0.5 ) );//ベロシティカーブ\r
341                                         velo = ( velo / (int)this.numericUpDownVOLUME間隔.Value ) * (int)this.numericUpDownVOLUME間隔.Value;\r
342                                         velo = ( velo > 100 ) ? 100 : ( ( velo == 0 ) ? 1 : velo );\r
343                                         vMIDIイベント.nベロシティ_DTX変換後 = velo;\r
344                                 }\r
345                                 #endregion\r
346 \r
347                                 #region [ 配置予定チップを割り当て一覧に沿ってレーンを割り当てる ]\r
348                                 cMIDI.tMIDIチップをレーンに割り当てる( this.dgv割り当て一覧 );\r
349                                 #endregion\r
350                                 \r
351                                 #region [ WAVリスト出力 ]\r
352 \r
353                                 #region [ #WAV02 BGM仮置き用 ]\r
354                                 CWAV cwav = this.formメインフォーム.mgrWAVリスト管理者.tWAVをキャッシュから検索して返す_なければ新規生成する( 2 );\r
355                                 cwav.strラベル名 = "BGM";\r
356                                 cwav.bBGMとして使用 = true;\r
357                                 cwav.col背景色 = Color.FromArgb( 224, 255, 224 );\r
358                                 #endregion\r
359                                 \r
360                                 #region [ #WAV04 以降をWAVリスト割り当てに使う ]\r
361                                 // WAVリストをソートして見やすくする\r
362                                 cMIDI.lMIDIWAV.Sort( nMIDIWAVSort );\r
363 \r
364                                 int nWAVCount = 4;\r
365                                 int nレーン番号before = 0;\r
366                                 \r
367                                 foreach ( CMIDIイベント vMIDIWAV in cMIDI.lMIDIWAV )\r
368                                 {\r
369                                         // ノートチップ以外をWAVリストに表示させない\r
370                                         if ( vMIDIWAV.eイベントタイプ != CMIDIイベント.Eイベントタイプ.NoteOnOff ) continue;\r
371 \r
372                                         // レーン毎に1行空ける\r
373                                         if ( nWAVCount > 4 && nレーン番号before != vMIDIWAV.nレーン番号 ) nWAVCount++;\r
374                                         nレーン番号before = vMIDIWAV.nレーン番号;\r
375 \r
376                                         // WAVリストに配置\r
377                                         cwav = this.formメインフォーム.mgrWAVリスト管理者.tWAVをキャッシュから検索して返す_なければ新規生成する( nWAVCount );\r
378                                         cwav.strファイル名 = vMIDIWAV.nキー.ToString() + ".ogg";\r
379                                         cwav.n音量0to100 = vMIDIWAV.nベロシティ_DTX変換後;\r
380                                         cwav.strラベル名 = this.formメインフォーム.mgr譜面管理者.listレーン[vMIDIWAV.nレーン番号].strレーン名\r
381                                                 + ( vMIDIWAV.b裏チャンネル ? "*" : "" )\r
382                                                 + " " + vMIDIWAV.strコメント;\r
383 \r
384                                         // WAVリストの背景色を、レーンの色に合わせる\r
385                                         Color color = this.formメインフォーム.mgr譜面管理者.listレーン[vMIDIWAV.nレーン番号].col背景色;\r
386                                         cwav.col背景色 = Color.FromArgb( color.R/2 + 128, color.G/2 + 128, color.B/2 + 128 );\r
387 \r
388                                         // 配置予定全チップにWAV番号を指定する\r
389                                         foreach ( CMIDIイベント vMIDIイベント in cMIDI.lMIDIイベント )\r
390                                         {\r
391                                                 if ( vMIDIWAV.strWAV重複チェック == vMIDIイベント.strWAV重複チェック )\r
392                                                         vMIDIイベント.nWAV = nWAVCount;\r
393                                         }\r
394                                         nWAVCount ++;\r
395                                 }\r
396                                 #endregion\r
397 \r
398                                 #region [ WAVリスト強制更新 ]\r
399                                 this.formメインフォーム.listViewWAVリスト.Refresh();\r
400                                 #endregion\r
401 \r
402                                 #endregion\r
403                                 \r
404                                 #region [ 小節付加+変拍子設定 ]\r
405                                 tMIDIイベントリストから小節リストを構成する( cMIDI.lMIDIイベント, cMIDI.n分解能 );\r
406                                 #endregion\r
407                                 \r
408                                 #region [ チップ配置 ]\r
409                                 // 複数トラックへの対応のため\r
410                                 cMIDI.lMIDIイベント.Sort( ( ( a, b ) => (int) a.n時間 - (int) b.n時間 ) );\r
411 \r
412                                 // 配置予定チップを実際に配置する\r
413                 foreach ( CMIDIイベント vMIDIイベント in cMIDI.lMIDIイベント )\r
414                 {\r
415                                         if ( vMIDIイベント.b入力 )\r
416                                         {\r
417                                                 vMIDIイベント.挿入( this.formメインフォーム, cMIDI.n分解能 );\r
418                                         }\r
419                 }\r
420 \r
421                                 // BGMチップを仮置き\r
422                                 this.formメインフォーム.mgr譜面管理者.tチップを配置または置換する( this.formメインフォーム.mgr譜面管理者.nレーン名に対応するレーン番号を返す( "BGM" ), 0, 2, 0f, false );\r
423                                 #endregion\r
424 \r
425                                 #region [ 情報を入力 ]\r
426                 if ( cMIDI.f先頭BPM > 0.0 ) this.formメインフォーム.numericUpDownBPM.Value = (decimal)cMIDI.f先頭BPM;\r
427                                 string str曲タイトル = cMIDI.lMIDIトラック[0].strトラック名;\r
428                                 if ( str曲タイトル == "" )\r
429                                 {\r
430                                         str曲タイトル = Path.GetFileName( cMIDI.strファイル名 );\r
431                                 }\r
432                 this.formメインフォーム.textBox曲名.Text = str曲タイトル;\r
433 \r
434                                 if ( cMIDI.n重複チップ数 > 0 ) this.formメインフォーム.textBoxコメント.Text = resource.GetString("label重複チップ数.Text") + " : "+cMIDI.n重複チップ数;\r
435                                 #endregion\r
436 \r
437                                 #region [ LP発生なら、LPレーンを表示する。 ]\r
438                                 for ( int i = 0; i < this.dgv割り当て一覧.Rows.Count; i++ )\r
439                                 {\r
440                                         if ( (string)this.dgv割り当て一覧.Rows[ i ].Cells[ "DTX_Lane" ].Value == "LP" &&\r
441                                                 (int)this.dgv割り当て一覧.Rows[ i ].Cells[ "Notes" ].Value > 0 )\r
442                                         {\r
443                                                 this.formメインフォーム.mgr譜面管理者.tExpandLanes( Cレーン.ELaneType.LP );\r
444                                         }\r
445                                 }\r
446                                 #endregion\r
447                         }\r
448                 }\r
449                 \r
450                 /// <summary>\r
451                 /// WAVリストを順番にソートする\r
452                 /// ・レーン番号:昇順\r
453                 /// ・裏チャンネル:昇順(表が0、裏が1)\r
454                 /// ・(MIDIの)キー:昇順\r
455                 /// ・音量:降順\r
456                 /// </summary>\r
457                 static int nMIDIWAVSort( CMIDIイベント a, CMIDIイベント b )\r
458                 {\r
459                         // 昇順\r
460                         if ( a.nレーン番号 > b.nレーン番号 ) return 1;\r
461                         else if ( a.nレーン番号 < b.nレーン番号 ) return -1;\r
462                         else\r
463                         {\r
464                                 // 昇順\r
465                                 if ( (a.b裏チャンネル?1:0) > (b.b裏チャンネル?1:0) ) return 1;\r
466                                 else if ( (a.b裏チャンネル?1:0) < (b.b裏チャンネル?1:0) ) return -1;\r
467                                 else\r
468                                 {\r
469                                         // 昇順\r
470                                         if ( a.nキー > b.nキー ) return 1;\r
471                                         else if ( a.nキー < b.nキー ) return -1;\r
472                                         else\r
473                                         {\r
474                                                 // 降順\r
475                                                 if ( a.nベロシティ > b.nベロシティ ) return -1;\r
476                                                 else if ( a.nベロシティ < b.nベロシティ ) return 1;\r
477                                                 else return 0;\r
478                                         }\r
479                                 }\r
480                         }\r
481                 }\r
482 \r
483                 private struct barlen\r
484                 {\r
485                         public int n時間;\r
486                         public int n分子;\r
487                         public int n分母;\r
488 \r
489                         public barlen( int _n時間, int _n分子, int _n分母 )\r
490                         {\r
491                                 n時間 = _n時間;\r
492                                 n分子 = _n分子;\r
493                                 n分母 = _n分母;\r
494                         }\r
495                 }\r
496         \r
497                 private void tMIDIイベントリストから小節リストを構成する( List<CMIDIイベント> cml, int n四分音符の分解能 )\r
498                 {\r
499                         if ( cml.Count <= 0 ) return;\r
500 \r
501                         // 最終拍子イベント以降、曲最後までの小節について、この先のロジックで小節長を変更するために、ダミーで最後に拍子変更のイベントを入れる。\r
502 \r
503                         int n最終分子 = 1;\r
504                         int n最終分母 = 1;\r
505                         int n最終時間 = (int)cml[ cml.Count - 1 ].n時間;\r
506 \r
507                         cml.Reverse();\r
508                         foreach ( CMIDIイベント cm in cml )\r
509                         {\r
510                                 if ( cm.eイベントタイプ == CMIDIイベント.Eイベントタイプ.BarLen )\r
511                                 {\r
512                                         n最終分子 = cm.n拍子分子;\r
513                                         n最終分母 = cm.n拍子分母;\r
514                                         break;\r
515                                 }\r
516                         }\r
517                         cml.Reverse();\r
518 \r
519                         if ( n最終時間 >= 0 )\r
520                         {\r
521                                 cml.Add( new CMIDIBARLen( (UInt32)n最終時間, n最終分子, n最終分母 ) );\r
522                         }\r
523 \r
524                         \r
525                         this.formメインフォーム.mgr譜面管理者.dic小節.Clear();\r
526                         foreach ( CMIDIイベント cm in cml )\r
527                         {\r
528                                 if ( cm.eイベントタイプ == CMIDIイベント.Eイベントタイプ.BarLen )\r
529                                 {\r
530                                         // もし拍子変更イベントの絶対時間が、小節外にあれば、必要なだけ小節を追加する\r
531                                         while ( true )\r
532                                         {\r
533                                                 bool bExistBar = true;\r
534                                                 // 現在保持している小節リストの、nGridの最大値を取得する\r
535                                                 int nCurrentMaxBar = this.formメインフォーム.mgr譜面管理者.n現在の最大の小節番号を返す();\r
536                                                 int nCurremtMaxBar_FirstGrid = this.formメインフォーム.mgr譜面管理者.n譜面先頭からみた小節先頭の位置gridを返す( nCurrentMaxBar );\r
537                                                 if ( nCurremtMaxBar_FirstGrid < 0 ) nCurremtMaxBar_FirstGrid = 0;\r
538 \r
539                                                 C小節 c最終小節 = this.formメインフォーム.mgr譜面管理者.p譜面先頭からの位置gridを含む小節を返す( nCurremtMaxBar_FirstGrid );\r
540                                                 float fCurrent小節倍率 = (c最終小節 == null) ? 1.0f : c最終小節.f小節長倍率;\r
541                                                 int nCurrentMaxGrid = nCurremtMaxBar_FirstGrid + (int) ( 192 * fCurrent小節倍率 ) - 1;\r
542                                                 if ( nCurrentMaxBar < 0 ) nCurrentMaxGrid = -1;\r
543 \r
544                                                 // 拍子変更イベントの絶対時間が、小節外にあれば、新規に小節を一つ追加する。\r
545                                                 // 小節長は前の小節長を継承するか、MIDIイベント指定による新しい値にするか。\r
546                                                 // 小節を1つ追加しただけでは足りないのであれば、whileループで繰り返し追加し続ける。\r
547                                                 int nEvent時間 = (int)cm.n時間 * ( 192 / 4 ) / n四分音符の分解能;\r
548                                                 if ( nCurrentMaxGrid < (int) nEvent時間 )\r
549                                                 {\r
550                                                         ++nCurrentMaxBar;\r
551 \r
552                                                         C小節 c小節 = new C小節( nCurrentMaxBar );\r
553                                                         if ( c小節 != null )\r
554                                                         {\r
555                                                                 c小節.f小節長倍率 = fCurrent小節倍率;\r
556                                                                 this.formメインフォーム.mgr譜面管理者.dic小節.Add( nCurrentMaxBar, c小節 );\r
557                                                         }\r
558                                                         else\r
559                                                         {\r
560                                                                 throw new Exception("C小節の作成に失敗しました。");\r
561                                                         }\r
562                                                 }\r
563                                                 else\r
564                                                 {\r
565                                                         // 小節追加whileループの最後か、または小節が既に存在する場合でも、拍子の変更があれば反映する。\r
566                                                         if (cm.eイベントタイプ == CMIDIイベント.Eイベントタイプ.BarLen)\r
567                                                         {\r
568                                                                 C小節 c小節 = this.formメインフォーム.mgr譜面管理者.p譜面先頭からの位置gridを含む小節を返す( nEvent時間 );\r
569                                                                 this.formメインフォーム.t小節長を変更する_小節単位( c小節.n小節番号0to3599, (float)cm.n拍子分子 / cm.n拍子分母 );\r
570                                                         }\r
571                                                         break;\r
572                                                 }\r
573                                         }\r
574                                 }\r
575                         }\r
576                 }\r
577         }\r
578 }\r