OSDN Git Service

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