lipsync/trunk/Boare.Lib.Vsq/VsqTrack.cs

423 lines
14 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* VsqTrack.cs
* Copyright (c) 2008-2009 kbinani
*
* This file is part of Boare.Lib.Vsq.
*
* Boare.Lib.Vsq is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* Boare.Lib.Vsq is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
using System;
using System.Collections.Generic;
using System.IO;
namespace Boare.Lib.Vsq {
/// <summary>
/// Stores the data of a vsq track.
/// </summary>
[Serializable]
public partial class VsqTrack : ICloneable {
public string Tag;
/// <summary>
/// トラックの名前。
/// </summary>
public string Name;
public VsqMetaText MetaText;
private int m_edited_start = int.MaxValue;
private int m_edited_end = int.MinValue;
private class SingerEventIterator : Iterator {
VsqEventList m_list;
int m_pos;
public SingerEventIterator( VsqEventList list ) {
m_list = list;
m_pos = -1;
}
public bool hasNext() {
for ( int i = m_pos + 1; i < m_list.getCount(); i++ ) {
if ( m_list.getElement( i ).ID.type == VsqIDType.Singer ) {
return true;
}
}
return false;
}
public object next() {
for ( int i = m_pos + 1; i < m_list.getCount(); i++ ) {
VsqEvent item = m_list.getElement( i );
if ( item.ID.type == VsqIDType.Singer ) {
m_pos = i;
return item;
}
}
return null;
}
public void remove() {
if ( 0 <= m_pos && m_pos < m_list.getCount() ) {
m_list.removeAt( m_pos );
}
}
}
private class NoteEventIterator : Iterator {
VsqEventList m_list;
int m_pos;
public NoteEventIterator( VsqEventList list ) {
m_list = list;
m_pos = -1;
}
public bool hasNext() {
for ( int i = m_pos + 1; i < m_list.getCount(); i++ ) {
if ( m_list.getElement( i ).ID.type == VsqIDType.Anote ) {
return true;
}
}
return false;
}
public object next() {
for ( int i = m_pos + 1; i < m_list.getCount(); i++ ) {
VsqEvent item = m_list.getElement( i );
if ( item.ID.type == VsqIDType.Anote ) {
m_pos = i;
return item;
}
}
return null;
}
public void remove() {
if ( 0 <= m_pos && m_pos < m_list.getCount() ) {
m_list.removeAt( m_pos );
}
}
}
private class EventIterator : Iterator{
private VsqEventList m_list;
private int m_pos;
public EventIterator( VsqEventList list ) {
m_list = list;
m_pos = -1;
}
public Boolean hasNext() {
if ( 0 <= m_pos + 1 && m_pos + 1 < m_list.getCount() ) {
return true;
}
return false;
}
public Object next() {
m_pos++;
return m_list.getElement( m_pos );
}
public void remove() {
if ( 0 <= m_pos && m_pos < m_list.getCount() ) {
m_list.removeAt( m_pos );
}
}
}
public void sortEvent() {
MetaText.Events.sort();
}
/// <summary>
/// 歌手変更イベントを曲の先頭から順に返すIteratorを取得します
/// </summary>
/// <returns></returns>
public Iterator getSingerEventIterator() {
return new SingerEventIterator( MetaText.getEventList() );
}
/// <summary>
/// 音符イベントを曲の先頭から順に返すIteratorを取得します
/// </summary>
/// <returns></returns>
public Iterator getNoteEventIterator() {
if ( MetaText == null ) {
return new NoteEventIterator( new VsqEventList() );
} else {
return new NoteEventIterator( MetaText.getEventList() );
}
}
/// <summary>
/// メタテキストを,メモリー上のストリームに出力します
/// </summary>
/// <param name="sw"></param>
/// <param name="encode"></param>
/// <param name="eos"></param>
/// <param name="start"></param>
public void printMetaText( TextMemoryStream sw, int eos, int start ) {
MetaText.print( sw, false, eos, start );
}
/// <summary>
/// メタテキストを,指定されたファイルに出力します
/// </summary>
/// <param name="file"></param>
public void printMetaText( string file ) {
TextMemoryStream tms = new TextMemoryStream( FileAccess.ReadWrite );
int count = MetaText.getEventList().getCount();
int clLast = MetaText.getEventList().getElement( count - 1 ).Clock + 480;
MetaText.print( tms, true, clLast, 0 );
using ( StreamWriter sw = new StreamWriter( file ) ) {
tms.rewind();
while ( tms.peek() >= 0 ) {
string line = tms.readLine();
sw.WriteLine( line );
}
}
}
/// <summary>
/// Masterを取得します
/// </summary>
public VsqMaster getMaster() {
return MetaText.master;
}
internal void setMaster( VsqMaster value ) {
MetaText.master = value;
}
/// <summary>
/// Mixerを取得します
/// </summary>
public VsqMixer getMixer() {
return MetaText.mixer;
}
internal void setMixer( VsqMixer value ) {
MetaText.mixer = value;
}
/// <summary>
/// Commonを取得します
/// </summary>
/// <returns></returns>
public VsqCommon getCommon() {
return MetaText.Common;
}
/// <summary>
/// 指定したトラックのレンダラーを変更します
/// </summary>
/// <param name="track"></param>
/// <param name="new_renderer"></param>
/// <param name="singers"></param>
public void changeRenderer( string new_renderer, List<VsqID> singers ) {
VsqID default_id = null;
if ( singers.Count <= 0 ) {
default_id = new VsqID();
default_id.type = VsqIDType.Singer;
default_id.IconHandle = new IconHandle();
default_id.IconHandle.IconID = "$0701" + 0.ToString( "0000" );
default_id.IconHandle.IDS = "Unknown";
default_id.IconHandle.Index = 0;
default_id.IconHandle.Language = 0;
default_id.IconHandle.Length = 1;
default_id.IconHandle.Original = 0;
default_id.IconHandle.Program = 0;
default_id.IconHandle.Caption = "";
} else {
default_id = singers[0];
}
for ( Iterator itr = getSingerEventIterator(); itr.hasNext(); ) {
VsqEvent ve = (VsqEvent)itr.next();
int program = ve.ID.IconHandle.Program;
bool found = false;
for ( int i = 0; i < singers.Count; i++ ) {
if ( program == singers[i].IconHandle.Program ) {
ve.ID = (VsqID)singers[i].Clone();
found = true;
break;
}
}
if ( !found ) {
VsqID add = (VsqID)default_id.Clone();
add.IconHandle.Program = program;
ve.ID = add;
}
}
MetaText.Common.Version = new_renderer;
}
/// <summary>
/// このトラックが保持している指定されたカーブのBPListを取得します
/// </summary>
/// <param name="curve"></param>
/// <returns></returns>
public VsqBPList getCurve( string curve ) {
return MetaText.getElement( curve );
}
public void setCurve( string curve, VsqBPList value ) {
MetaText.setElement( curve, value );
}
public int getEventCount() {
return MetaText.getEventList().getCount();
}
public VsqEvent getEvent( int index ) {
return MetaText.getEventList().getElement( index );
}
public void setEvent( int index, VsqEvent item ) {
MetaText.getEventList().setElement( index, item );
}
public void addEvent( VsqEvent item ) {
MetaText.getEventList().add( item );
}
public Iterator getEventIterator() {
return new EventIterator( MetaText.getEventList() );
}
public void removeEvent( int index ) {
MetaText.getEventList().removeAt( index );
}
/// <summary>
/// このトラックの,最後に編集が加えられた範囲の,開始位置(クロック)を取得します.
/// </summary>
public int getEditedStart() {
return m_edited_start;
}
public void setEditedStart( int value ) {
if ( value < m_edited_start ) {
m_edited_start = value;
}
}
/// <summary>
/// このトラックの,最後に編集が加えられた範囲の,終了位置(クロック)を取得します.
/// </summary>
public int getEditedEnd() {
return m_edited_end;
}
public void setEditedEnd( int value ) {
if ( m_edited_end < value ) {
m_edited_end = value;
}
}
/// <summary>
/// このトラックの編集範囲EditedStart, EditedEndをリセットします
/// </summary>
public void resetEditedArea() {
m_edited_start = int.MaxValue;
m_edited_end = int.MinValue;
}
/// <summary>
/// このインスタンスのコピーを作成します
/// </summary>
/// <returns></returns>
public object Clone() {
VsqTrack res = new VsqTrack();
res.Name = Name;
if ( MetaText != null ) {
res.MetaText = (VsqMetaText)MetaText.Clone();
}
res.m_edited_start = m_edited_start;
res.m_edited_end = m_edited_end;
res.Tag = Tag;
return res;
}
/// <summary>
/// Master Trackを構築
/// </summary>
/// <param name="tempo"></param>
/// <param name="numerator"></param>
/// <param name="denominator"></param>
public VsqTrack( int tempo, int numerator, int denominator ) {
this.Name = "Master Track";
this.MetaText = null;
}
/// <summary>
/// Master Trackでないトラックを構築。
/// </summary>
/// <param name="name"></param>
/// <param name="singer"></param>
public VsqTrack( string name, string singer ) {
Name = name;
MetaText = new VsqMetaText( name, singer );
}
public VsqTrack()
: this( "Voice1", "Miku" ) {
}
/// <summary>
/// 歌詞の文字数を調べます
/// </summary>
/// <returns></returns>
public int getLyricLength() {
int counter = 0;
for ( int i = 0; i < MetaText.getEventList().getCount(); i++ ) {
if ( MetaText.getEventList().getElement( i ).ID.type == VsqIDType.Anote ) {
counter++;
}
}
return counter;
}
public VsqTrack( List<Boare.Lib.Vsq.MidiEvent> midi_event ) {
Name = "";
#if DEBUG
bocoree.debug.push_log( "VsqTrack..ctor" );
#endif
using ( TextMemoryStream sw = new TextMemoryStream() ) {
for ( int i = 0; i < midi_event.Count; i++ ) {
if ( midi_event[i].FirstByte == 0xff && midi_event[i].Data.Length > 0 ) {
// meta textを抽出
byte type = midi_event[i].Data[0];
if ( type == 0x01 || type == 0x03 ) {
char[] ch = new char[midi_event[i].Data.Length - 1];
for ( int j = 1; j < midi_event[i].Data.Length; j++ ) {
ch[j - 1] = (char)midi_event[i].Data[j];
}
string line = new string( ch );
if ( type == 0x01 ) {
int second_colon = line.IndexOf( ':', 3 );
line = line.Substring( second_colon + 1 );
line = line.Replace( "\\n", Environment.NewLine );
line = line.Replace( "\n", Environment.NewLine );
sw.write( line );
} else {
Name = line;
}
}
} else {
continue;
}
}
sw.rewind();
MetaText = new VsqMetaText( sw );
}
}
}
}