Develop and Download Open Source Software

Browse Subversion Repository

Contents of /trunk/Boare.Lib.Vsq/VsqTrack.cs

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6 - (show annotations) (download)
Thu Jun 25 14:16:22 2009 UTC (3 years, 10 months ago) by kbinani
File size: 14777 byte(s)
1 /*
2 * VsqTrack.cs
3 * Copyright (c) 2008-2009 kbinani
4 *
5 * This file is part of Boare.Lib.Vsq.
6 *
7 * Boare.Lib.Vsq is free software; you can redistribute it and/or
8 * modify it under the terms of the BSD License.
9 *
10 * Boare.Lib.Vsq is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 */
14 using System;
15 using System.Collections.Generic;
16 using System.IO;
17
18 namespace Boare.Lib.Vsq {
19
20 /// <summary>
21 /// Stores the data of a vsq track.
22 /// </summary>
23 [Serializable]
24 public partial class VsqTrack : ICloneable {
25 public object Tag;
26 /// <summary>
27 /// トラックの名前。
28 /// </summary>
29 public string Name;
30 private VsqMetaText m_meta_text;
31 private List<Boare.Lib.Vsq.MidiEvent> m_midi_event;
32 private int m_edited_start = int.MaxValue;
33 private int m_edited_end = int.MinValue;
34 public string Renderer = "VOCALOID2";
35
36 private class SingerEventIterator : Iterator {
37 VsqEventList m_list;
38 int m_pos;
39
40 public SingerEventIterator( VsqEventList list ) {
41 m_list = list;
42 m_pos = -1;
43 }
44
45 public bool hasNext() {
46 for ( int i = m_pos + 1; i < m_list.getCount(); i++ ) {
47 if ( m_list.getElement( i ).ID.type == VsqIDType.Singer ) {
48 return true;
49 }
50 }
51 return false;
52 }
53
54 public object next() {
55 for ( int i = m_pos + 1; i < m_list.getCount(); i++ ) {
56 VsqEvent item = m_list.getElement( i );
57 if ( item.ID.type == VsqIDType.Singer ) {
58 m_pos = i;
59 return item;
60 }
61 }
62 return null;
63 }
64
65 public void remove() {
66 if ( 0 <= m_pos && m_pos < m_list.getCount() ) {
67 m_list.removeAt( m_pos );
68 }
69 }
70 }
71
72 private class NoteEventIterator : Iterator {
73 VsqEventList m_list;
74 int m_pos;
75
76 public NoteEventIterator( VsqEventList list ) {
77 m_list = list;
78 m_pos = -1;
79 }
80
81 public bool hasNext() {
82 for ( int i = m_pos + 1; i < m_list.getCount(); i++ ) {
83 if ( m_list.getElement( i ).ID.type == VsqIDType.Anote ) {
84 return true;
85 }
86 }
87 return false;
88 }
89
90 public object next() {
91 for ( int i = m_pos + 1; i < m_list.getCount(); i++ ) {
92 VsqEvent item = m_list.getElement( i );
93 if ( item.ID.type == VsqIDType.Anote ) {
94 m_pos = i;
95 return item;
96 }
97 }
98 return null;
99 }
100
101 public void remove() {
102 if ( 0 <= m_pos && m_pos < m_list.getCount() ) {
103 m_list.removeAt( m_pos );
104 }
105 }
106 }
107
108 private class EventIterator : Iterator{
109 private VsqEventList m_list;
110 private int m_pos;
111
112 public EventIterator( VsqEventList list ) {
113 m_list = list;
114 m_pos = -1;
115 }
116
117 public Boolean hasNext() {
118 if ( 0 <= m_pos + 1 && m_pos + 1 < m_list.getCount() ) {
119 return true;
120 }
121 return false;
122 }
123
124 public Object next() {
125 m_pos++;
126 return m_list.getElement( m_pos );
127 }
128
129 public void remove() {
130 if ( 0 <= m_pos && m_pos < m_list.getCount() ) {
131 m_list.removeAt( m_pos );
132 }
133 }
134 }
135
136
137 /// <summary>
138 /// 歌手変更イベントを,曲の先頭から順に返すIteratorを取得します
139 /// </summary>
140 /// <returns></returns>
141 public Iterator getSingerEventIterator() {
142 return new SingerEventIterator( m_meta_text.getEventList() );
143 }
144
145 /// <summary>
146 /// 音符イベントを,曲の先頭から順に返すIteratorを取得します
147 /// </summary>
148 /// <returns></returns>
149 public Iterator getNoteEventIterator() {
150 return new NoteEventIterator( m_meta_text.getEventList() );
151 }
152
153 /// <summary>
154 /// メタテキストを,メモリー上のストリームに出力します
155 /// </summary>
156 /// <param name="sw"></param>
157 /// <param name="encode"></param>
158 /// <param name="eos"></param>
159 /// <param name="start"></param>
160 public void printMetaText( TextMemoryStream sw, int eos, int start ) {
161 m_meta_text.print( sw, false, eos, start );
162 }
163
164 /// <summary>
165 /// メタテキストを,指定されたファイルに出力します
166 /// </summary>
167 /// <param name="file"></param>
168 public void printMetaText( string file ) {
169 TextMemoryStream tms = new TextMemoryStream( FileAccess.ReadWrite );
170 int count = m_meta_text.getEventList().getCount();
171 int clLast = m_meta_text.getEventList().getElement( count - 1 ).Clock + 480;
172 m_meta_text.print( tms, true, clLast, 0 );
173 using ( StreamWriter sw = new StreamWriter( file ) ) {
174 tms.rewind();
175 while ( tms.peek() >= 0 ) {
176 string line = tms.readLine();
177 sw.WriteLine( line );
178 }
179 }
180 }
181
182 /// <summary>
183 /// Masterを取得します
184 /// </summary>
185 public VsqMaster getMaster() {
186 return m_meta_text.master;
187 }
188
189 internal void setMaster( VsqMaster value ) {
190 m_meta_text.master = value;
191 }
192
193 /// <summary>
194 /// Mixerを取得します
195 /// </summary>
196 public VsqMixer getMixer() {
197 return m_meta_text.mixer;
198 }
199
200 internal void setMixer( VsqMixer value ) {
201 m_meta_text.mixer = value;
202 }
203
204 /// <summary>
205 /// このトラックが保持している,指定されたカーブのBPListを取得します
206 /// </summary>
207 /// <param name="curve"></param>
208 /// <returns></returns>
209 public VsqBPList getCurve( string curve ) {
210 return m_meta_text.getElement( curve );
211 }
212
213 public void setCurve( string curve, VsqBPList value ) {
214 m_meta_text.setElement( curve, value );
215 }
216
217 public int getEventCount() {
218 return m_meta_text.getEventList().getCount();
219 }
220
221 public VsqEvent getEvent( int index ) {
222 return m_meta_text.getEventList().getElement( index );
223 }
224
225 public void setEvent( int index, VsqEvent item ) {
226 m_meta_text.getEventList().setElement( index, item );
227 }
228
229 public void addEvent( VsqEvent item ) {
230 m_meta_text.getEventList().add( item );
231 }
232
233 public Iterator getEventIterator() {
234 return new EventIterator( m_meta_text.getEventList() );
235 }
236
237 public void removeEvent( int index ) {
238 m_meta_text.getEventList().removeAt( index );
239 }
240
241 /// <summary>
242 /// このトラックの,最後に編集が加えられた範囲の,開始位置(クロック)を取得します.
243 /// このインスタンスを保持しているVsqFileインスタンスのExecuteメソッドによって自動的に更新されます
244 /// </summary>
245 public int getEditedStart() {
246 return m_edited_start;
247 }
248
249 internal void setEditedStart( int value ) {
250 if ( value < m_edited_start ) {
251 m_edited_start = value;
252 }
253 }
254
255 /// <summary>
256 /// このトラックの,最後に編集が加えられた範囲の,終了位置(クロック)を取得します.
257 /// このインスタンスを保持しているVsqFileインスタンスのExecuteメソッドによって自動的に更新されます
258 /// </summary>
259 public int getEditedEnd() {
260 return m_edited_end;
261 }
262
263 internal void setEditedEnd( int value ) {
264 if ( m_edited_end < value ) {
265 m_edited_end = value;
266 }
267 }
268
269 /// <summary>
270 /// このトラックの,編集範囲(EditedStart, EditedEnd)をリセットします.
271 /// </summary>
272 public void resetEditedArea() {
273 m_edited_start = int.MaxValue;
274 m_edited_end = int.MinValue;
275 }
276
277 /// <summary>
278 /// このインスタンスのコピーを作成します
279 /// </summary>
280 /// <returns></returns>
281 public object Clone() {
282 VsqTrack res = new VsqTrack();
283 res.Name = Name;
284 if ( m_meta_text != null ) {
285 res.m_meta_text = (VsqMetaText)m_meta_text.Clone();
286 }
287 if ( m_midi_event != null ) {
288 res.m_midi_event = new List<MidiEvent>( m_midi_event );
289 }
290 res.m_edited_start = m_edited_start;
291 res.m_edited_end = m_edited_end;
292 res.Renderer = Renderer;
293 return res;
294 }
295
296 private VsqTrack() {
297 }
298
299 /// <summary>
300 /// Master Trackを構築
301 /// </summary>
302 /// <param name="tempo"></param>
303 /// <param name="numerator"></param>
304 /// <param name="denominator"></param>
305 public VsqTrack( int tempo, int numerator, int denominator ) {
306 this.Name = "Master Track";
307 this.m_meta_text = null;
308 m_midi_event = new List<MidiEvent>();
309
310 // テンポを設定
311 MidiEvent mi_tempo = new MidiEvent();
312 mi_tempo.Clock = 0;
313 mi_tempo.FirstByte = 0xff;
314 byte b1 = (byte)(tempo & 0xff);
315 tempo = tempo >> 8;
316 byte b2 = (byte)(tempo & 0xff);
317 tempo = tempo >> 8;
318 byte b3 = (byte)(tempo & 0xff);
319 mi_tempo.Data = new byte[5] { 0x51, 0x03, b3, b2, b1 };
320 m_midi_event.Add( mi_tempo );
321
322 // 拍子を設定
323 MidiEvent mi_timesig = MidiEvent.generateTimeSigEvent( 0, numerator, denominator );
324 m_midi_event.Add( mi_timesig );
325 }
326
327 /// <summary>
328 /// Master Trackでないトラックを構築。
329 /// </summary>
330 /// <param name="name"></param>
331 /// <param name="singer"></param>
332 public VsqTrack( string name, string singer ) {
333 Name = name;
334 m_meta_text = new VsqMetaText( name, singer );
335 m_midi_event = new List<MidiEvent>();
336 }
337
338 /// <summary>
339 /// 歌詞の文字数を調べます
340 /// </summary>
341 /// <returns></returns>
342 public int getLyricLength() {
343 int counter = 0;
344 for ( int i = 0; i < m_meta_text.getEventList().getCount(); i++ ) {
345 if ( m_meta_text.getEventList().getElement( i ).ID.type == VsqIDType.Anote ) {
346 counter++;
347 }
348 }
349 return counter;
350 }
351
352 public VsqTrack( List<Boare.Lib.Vsq.MidiEvent> midi_events ) {
353 m_midi_event = new List<MidiEvent>( midi_events );
354 Name = "";
355 #if DEBUG
356 bocoree.debug.push_log( "VsqTrack..ctor" );
357 #endif
358 using ( TextMemoryStream sw = new TextMemoryStream() ) {
359 for ( int i = 0; i < m_midi_event.Count; i++ ) {
360 if ( m_midi_event[i].FirstByte == 0xff && m_midi_event[i].Data.Length > 0 ) {
361 // meta textを抽出
362 byte type = m_midi_event[i].Data[0];
363 if ( type == 0x01 || type == 0x03 ) {
364 char[] ch = new char[m_midi_event[i].Data.Length - 1];
365 for ( int j = 1; j < midi_events[i].Data.Length; j++ ) {
366 ch[j - 1] = (char)midi_events[i].Data[j];
367 }
368 string line = new string( ch );
369 if ( type == 0x01 ) {
370 int second_colon = line.IndexOf( ':', 3 );
371 line = line.Substring( second_colon + 1 );
372 line = line.Replace( "\\n", Environment.NewLine );
373 line = line.Replace( "\n", Environment.NewLine );
374 sw.write( line );
375 } else {
376 Name = line;
377 }
378 }
379 } else {
380 continue;
381 }
382 }
383 sw.rewind();
384 m_meta_text = new VsqMetaText( sw );
385 }
386 }
387
388 public List<MidiEvent> getTempoList() {
389 List<MidiEvent> list = new List<MidiEvent>();
390 for ( int i = 0; i < m_midi_event.Count; i++ ) {
391 if ( m_midi_event[i].FirstByte == 0xff && m_midi_event[i].Data.Length >= 4 && m_midi_event[i].Data[0] == 0x51 ) {
392 list.Add( m_midi_event[i] );
393 }
394 }
395 return list;
396 }
397
398 /// <summary>
399 /// MidiEventの中から拍子情報を抽出します
400 /// </summary>
401 /// <returns></returns>
402 public List<MidiEvent> getTimeSigList() {
403 List<MidiEvent> list = new List<MidiEvent>();
404 for ( int i = 0; i < m_midi_event.Count; i++ ) {
405 if ( m_midi_event[i].FirstByte == 0xff && m_midi_event[i].Data.Length >= 5 && m_midi_event[i].Data[0] == 0x58 ) {
406 list.Add( m_midi_event[i] );
407 }
408 }
409 return list;
410 }
411 }
412
413 }

SourceForge.JP is a Japanese version of SourceForge.net. For developments that are not related to Japan, we recommend you to use SourceForge.net.