/* * VsqMetaText/VsqMetaText.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.Text; using System.IO; using System.Drawing; using System.Windows.Forms; namespace Boare.Lib.Vsq { /// /// vsqのメタテキストの中身を処理するためのクラス /// [Serializable] public class VsqMetaText : ICloneable { public VsqCommon Common; internal VsqMaster master; internal VsqMixer mixer; private VsqEventList m_events; /// /// PIT。ピッチベンド(pitchBendBPList)。default=0 /// public VsqBPList PIT; /// /// PBS。ピッチベンドセンシティビティ(pitchBendSensBPList)。dfault=2 /// public VsqBPList PBS; /// /// DYN。ダイナミクス(dynamicsBPList)。default=64 /// public VsqBPList DYN; /// /// BRE。ブレシネス(epRResidualBPList)。default=0 /// public VsqBPList BRE; /// /// BRI。ブライトネス(epRESlopeBPList)。default=64 /// public VsqBPList BRI; /// /// CLE。クリアネス(epRESlopeDepthBPList)。default=0 /// public VsqBPList CLE; private VsqBPList reso1FreqBPList; private VsqBPList reso2FreqBPList; private VsqBPList reso3FreqBPList; private VsqBPList reso4FreqBPList; private VsqBPList reso1BWBPList; private VsqBPList reso2BWBPList; private VsqBPList reso3BWBPList; private VsqBPList reso4BWBPList; private VsqBPList reso1AmpBPList; private VsqBPList reso2AmpBPList; private VsqBPList reso3AmpBPList; private VsqBPList reso4AmpBPList; /// /// GEN。ジェンダーファクター(genderFactorBPList)。default=64 /// public VsqBPList GEN; /// /// POR。ポルタメントタイミング(portamentoTimingBPList)。default=64 /// public VsqBPList POR; /// /// OPE。オープニング(openingBPList)。default=127 /// public VsqBPList OPE; public object Clone() { VsqMetaText res = new VsqMetaText(); if ( Common != null ) { res.Common = (VsqCommon)Common.Clone(); } if ( master != null ) { res.master = (VsqMaster)master.Clone(); } if ( mixer != null ) { res.mixer = (VsqMixer)mixer.Clone(); } if ( m_events != null ) { res.m_events = new VsqEventList(); for ( Iterator itr = m_events.iterator(); itr.hasNext(); ) { res.m_events.add( (VsqEvent)((VsqEvent)itr.next()).Clone() ); } } if ( PIT != null ) { res.PIT = (VsqBPList)PIT.Clone(); } if ( PBS != null ) { res.PBS = (VsqBPList)PBS.Clone(); } if ( DYN != null ) { res.DYN = (VsqBPList)DYN.Clone(); } if ( BRE != null ) { res.BRE = (VsqBPList)BRE.Clone(); } if ( BRI != null ) { res.BRI = (VsqBPList)BRI.Clone(); } if ( CLE != null ) { res.CLE = (VsqBPList)CLE.Clone(); } if ( reso1FreqBPList != null ) { res.reso1FreqBPList = (VsqBPList)reso1FreqBPList.Clone(); } if ( reso2FreqBPList != null ) { res.reso2FreqBPList = (VsqBPList)reso2FreqBPList.Clone(); } if ( reso3FreqBPList != null ) { res.reso3FreqBPList = (VsqBPList)reso3FreqBPList.Clone(); } if ( reso4FreqBPList != null ) { res.reso4FreqBPList = (VsqBPList)reso4FreqBPList.Clone(); } if ( reso1BWBPList != null ) { res.reso1BWBPList = (VsqBPList)reso1BWBPList.Clone(); } if ( reso2BWBPList != null ) { res.reso2BWBPList = (VsqBPList)reso2BWBPList.Clone(); } if ( reso3BWBPList != null ) { res.reso3BWBPList = (VsqBPList)reso3BWBPList.Clone(); } if ( reso4BWBPList != null ) { res.reso4BWBPList = (VsqBPList)reso4BWBPList.Clone(); } if ( reso1AmpBPList != null ) { res.reso1AmpBPList = (VsqBPList)reso1AmpBPList.Clone(); } if ( reso2AmpBPList != null ) { res.reso2AmpBPList = (VsqBPList)reso2AmpBPList.Clone(); } if ( reso3AmpBPList != null ) { res.reso3AmpBPList = (VsqBPList)reso3AmpBPList.Clone(); } if ( reso4AmpBPList != null ) { res.reso4AmpBPList = (VsqBPList)reso4AmpBPList.Clone(); } if ( GEN != null ) { res.GEN = (VsqBPList)GEN.Clone(); } if ( POR != null ) { res.POR = (VsqBPList)POR.Clone(); } if ( OPE != null ) { res.OPE = (VsqBPList)OPE.Clone(); } return res; } public VsqEventList getEventList() { return m_events; } internal VsqBPList getElement( string curve ) { switch ( curve.Trim().ToLower() ) { case "bre": return this.BRE; case "bri": return this.BRI; case "cle": return this.CLE; case "dyn": return this.DYN; case "gen": return this.GEN; case "ope": return this.OPE; case "pbs": return this.PBS; case "pit": return this.PIT; case "por": return this.POR; default: return null; } } internal void setElement( string curve, VsqBPList value ) { switch ( curve.Trim().ToLower() ) { case "bre": this.BRE = value; break; case "bri": this.BRI = value; break; case "cle": this.CLE = value; break; case "dyn": this.DYN = value; break; case "gen": this.GEN = value; break; case "ope": this.OPE = value; break; case "pbs": this.PBS = value; break; case "pit": this.PIT = value; break; case "por": this.POR = value; break; } } /// /// Editor画面上で上からindex番目のカーブを表すBPListを求めます /// /// /// public VsqBPList getCurve( int index ) { switch ( index ) { case 1: return DYN; case 2: return BRE; case 3: return BRI; case 4: return CLE; case 5: return OPE; case 6: return GEN; case 7: return POR; case 8: return PIT; case 9: return PBS; default: return null; } } /// /// Editor画面上で上からindex番目のカーブの名前を調べます /// /// /// public static string getCurveName( int index ) { switch ( index ) { case 0: return "VEL"; case 1: return "DYN"; case 2: return "BRE"; case 3: return "BRI"; case 4: return "CLE"; case 5: return "OPE"; case 6: return "GEN"; case 7: return "POR"; case 8: return "PIT"; case 9: return "PBS"; default: return ""; } } /// /// Singerプロパティに指定されている /// public string getSinger() { for ( Iterator itr = m_events.iterator(); itr.hasNext(); ) { VsqEvent item = (VsqEvent)itr.next(); if ( item.ID.type == VsqIDType.Singer ) { return item.ID.IconHandle.IDS; } } return ""; } public void setSinger( string value ) { for ( Iterator itr = m_events.iterator(); itr.hasNext(); ) { VsqEvent item = (VsqEvent)itr.next(); if ( item.ID.type == VsqIDType.Singer ) { item.ID.IconHandle.IDS = value; break; } } } /// /// EOSイベントが記録されているクロックを取得します。 /// /// public int getIndexOfEOS() { int result; if ( m_events.getCount() > 0 ) { int ilast = m_events.getCount() - 1; result = m_events.getElement( ilast ).Clock; } else { result = -1; } return result; } /// /// このインスタンスから、IDとHandleのリストを構築します /// /// /// void BuildIDHandleList( out List id, out List handle ) { id = new List(); handle = new List(); int current_id = -1; int current_handle = -1; List events = new List(); for ( Iterator itr = m_events.iterator(); itr.hasNext(); ) { events.Add( (VsqEvent)itr.next() ); } events.Sort(); for( int i = 0; i < events.Count; i++ ){ VsqEvent item = events[i]; VsqID id_item = (VsqID)item.ID.Clone(); current_id++; item.ID.value = current_id; id_item.value = current_id; // IconHandle if ( item.ID.IconHandle != null ) { current_handle++; VsqHandle handle_item = item.ID.IconHandle.castToVsqHandle(); handle_item.Index = current_handle; handle.Add( handle_item ); id_item.IconHandle_index = current_handle; } // LyricHandle if ( item.ID.LyricHandle != null ) { current_handle++; VsqHandle handle_item = item.ID.LyricHandle.castToVsqHandle(); handle_item.Index = current_handle; handle.Add( handle_item ); id_item.LyricHandle_index = current_handle; } // VibratoHandle if ( item.ID.VibratoHandle != null ) { current_handle++; VsqHandle handle_item = item.ID.VibratoHandle.castToVsqHandle(); handle_item.Index = current_handle; handle.Add( handle_item ); id_item.VibratoHandle_index = current_handle; } id.Add( id_item ); } } /// /// このインスタンスの内容を指定されたファイルに出力します。 /// /// /// public void print( TextMemoryStream sw, bool encode, int eos, int start ) { if ( Common != null ) { Common.write( sw ); } if ( master != null ) { master.write( sw ); } if ( mixer != null ) { mixer.write( sw ); } List id; List handle; BuildIDHandleList( out id, out handle ); writeEventList( sw, eos ); int i; for ( i = 0; i < id.Count; i++ ) { id[i].write( sw ); } for ( i = 0; i < handle.Count; i++ ) { handle[i].write( sw, encode ); } if ( PIT.getCount() > 0 ) { PIT.print( sw, start, "[PitchBendBPList]" ); } if ( PBS.getCount() > 0 ) { PBS.print( sw, start, "[PitchBendSensBPList]" ); } if ( DYN.getCount() > 0 ) { DYN.print( sw, start, "[DynamicsBPList]" ); } if ( BRE.getCount() > 0 ) { BRE.print( sw, start, "[EpRResidualBPList]" ); } if ( BRI.getCount() > 0 ) { BRI.print( sw, start, "[EpRESlopeBPList]" ); } if ( CLE.getCount() > 0 ) { CLE.print( sw, start, "[EpRESlopeDepthBPList]" ); } if ( reso1FreqBPList.getCount() > 0 ) { reso1FreqBPList.print( sw, start, "[Reso1FreqBPList]" ); } if ( reso2FreqBPList.getCount() > 0 ) { reso2FreqBPList.print( sw, start, "[Reso2FreqBPList]" ); } if ( reso3FreqBPList.getCount() > 0 ) { reso3FreqBPList.print( sw, start, "[Reso3FreqBPList]" ); } if ( reso4FreqBPList.getCount() > 0 ) { reso4FreqBPList.print( sw, start, "[Reso4FreqBPList]" ); } if ( reso1BWBPList.getCount() > 0 ) { reso1BWBPList.print( sw, start, "[Reso1BWBPList]" ); } if ( reso2BWBPList.getCount() > 0 ) { reso2BWBPList.print( sw, start, "[Reso2BWBPList]" ); } if ( reso3BWBPList.getCount() > 0 ) { reso3BWBPList.print( sw, start, "[Reso3BWBPList]" ); } if ( reso4BWBPList.getCount() > 0 ) { reso4BWBPList.print( sw, start, "[Reso4BWBPList]" ); } if ( reso1AmpBPList.getCount() > 0 ) { reso1AmpBPList.print( sw, start, "[Reso1AmpBPList]" ); } if ( reso2AmpBPList.getCount() > 0 ) { reso2AmpBPList.print( sw, start, "[Reso2AmpBPList]" ); } if ( reso3AmpBPList.getCount() > 0 ) { reso3AmpBPList.print( sw, start, "[Reso3AmpBPList]" ); } if ( reso4AmpBPList.getCount() > 0 ) { reso4AmpBPList.print( sw, start, "[Reso4AmpBPList]" ); } if ( GEN.getCount() > 0 ) { GEN.print( sw, start, "[GenderFactorBPList]" ); } if ( POR.getCount() > 0 ) { POR.print( sw, start, "[PortamentoTimingBPList]" ); } if ( OPE.getCount() > 0 ) { OPE.print( sw, start, "[OpeningBPList]" ); } } private void writeEventList( TextMemoryStream sw, int eos ) { sw.writeLine( "[EventList]" ); List temp = new List(); for ( Iterator itr = m_events.iterator(); itr.hasNext(); ) { temp.Add( (VsqEvent)itr.next() ); } temp.Sort(); int i = 0; while ( i < temp.Count ) { VsqEvent item = temp[i]; if ( !item.ID.Equals( VsqID.EOS ) ) { string ids = "ID#" + i.ToString( "0000" ); int clock = temp[i].Clock; while ( i + 1 < temp.Count && clock == temp[i + 1].Clock ) { i++; ids += ",ID#" + i.ToString( "0000" ); } sw.writeLine( clock + "=" + ids ); } i++; } sw.writeLine( eos + "=EOS" ); } /// /// 何も無いVsqMetaTextを構築する。これは、Master Track用のMetaTextとしてのみ使用されるべき /// public VsqMetaText() { } /// /// 最初のトラック以外の一般のメタテキストを構築。(Masterが作られない) /// public VsqMetaText( string name, string singer ) : this( name, 0, singer, false ) { } /// /// 最初のトラックのメタテキストを構築。(Masterが作られる) /// /// public VsqMetaText( string name, string singer, int pre_measure ) : this( name, pre_measure, singer, true ) { } private VsqMetaText( string name, int pre_measure, string singer, bool is_first_track ) { Common = new VsqCommon( name, Color.FromArgb( 179, 181, 123 ), 1, 1 ); PIT = new VsqBPList( 0, -8192, 8192 ); PIT.add( 0, PIT.getDefault() ); PBS = new VsqBPList( 2, 0, 24 ); PBS.add( 0, PBS.getDefault() ); DYN = new VsqBPList( 64, 0, 127 ); DYN.add( 0, DYN.getDefault() ); BRE = new VsqBPList( 0, 0, 127 ); BRE.add( 0, BRE.getDefault() ); BRI = new VsqBPList( 64, 0, 127 ); BRI.add( 0, BRI.getDefault() ); CLE = new VsqBPList( 0, 0, 127 ); CLE.add( 0, CLE.getDefault() ); reso1FreqBPList = new VsqBPList( 255, 0, 255 ); reso1FreqBPList.add( 0, reso1FreqBPList.getDefault() ); reso2FreqBPList = new VsqBPList( 255, 0, 255 ); reso2FreqBPList.add( 0, reso2FreqBPList.getDefault() ); reso3FreqBPList = new VsqBPList( 255, 0, 255 ); reso3FreqBPList.add( 0, reso3FreqBPList.getDefault() ); reso4FreqBPList = new VsqBPList( 255, 0, 255 ); reso4FreqBPList.add( 0, reso4FreqBPList.getDefault() ); reso1BWBPList = new VsqBPList( 255, 0, 255 ); reso1BWBPList.add( 0, reso1BWBPList.getDefault() ); reso2BWBPList = new VsqBPList( 255, 0, 255 ); reso2BWBPList.add( 0, reso2BWBPList.getDefault() ); reso3BWBPList = new VsqBPList( 255, 0, 255 ); reso3BWBPList.add( 0, reso3BWBPList.getDefault() ); reso4BWBPList = new VsqBPList( 255, 0, 255 ); reso4BWBPList.add( 0, reso4BWBPList.getDefault() ); reso1AmpBPList = new VsqBPList( 255, 0, 255 ); reso1AmpBPList.add( 0, reso1AmpBPList.getDefault() ); reso2AmpBPList = new VsqBPList( 255, 0, 255 ); reso2AmpBPList.add( 0, reso2AmpBPList.getDefault() ); reso3AmpBPList = new VsqBPList( 255, 0, 255 ); reso3AmpBPList.add( 0, reso3AmpBPList.getDefault() ); reso4AmpBPList = new VsqBPList( 255, 0, 255 ); reso4AmpBPList.add( 0, reso4AmpBPList.getDefault() ); GEN = new VsqBPList( 64, 0, 127 ); GEN.add( 0, GEN.getDefault() ); POR = new VsqBPList( 64, 0, 127 ); POR.add( 0, POR.getDefault() ); OPE = new VsqBPList( 127, 0, 127 ); OPE.add( 0, OPE.getDefault() ); if ( is_first_track ) { master = new VsqMaster( pre_measure ); } else { master = null; } m_events = new VsqEventList(); VsqID id = new VsqID( 0 ); id.type = VsqIDType.Singer; id.IconHandle = new IconHandle(); id.IconHandle.IconID = "$07010000"; id.IconHandle.IDS = singer; id.IconHandle.Original = 0; id.IconHandle.Caption = ""; id.IconHandle.Length = 1; id.IconHandle.Language = 0; id.IconHandle.Program = 0; m_events.add( new VsqEvent( 0, id ) ); } public VsqMetaText( TextMemoryStream sr ) { List> t_event_list = new List>(); Dictionary __id = new Dictionary(); Dictionary __handle = new Dictionary(); PIT = new VsqBPList( 0, -8192, 8192 ); PBS = new VsqBPList( 2, 0, 24 ); DYN = new VsqBPList( 64, 0, 127 ); BRE = new VsqBPList( 0 , 0, 127); BRI = new VsqBPList( 64, 0, 127 ); CLE = new VsqBPList( 0, 0, 127 ); reso1FreqBPList = new VsqBPList( 255, 0, 255 ); reso2FreqBPList = new VsqBPList( 255, 0, 255 ); reso3FreqBPList = new VsqBPList( 255, 0, 255 ); reso4FreqBPList = new VsqBPList( 255, 0, 255 ); reso1BWBPList = new VsqBPList( 255, 0, 255 ); reso2BWBPList = new VsqBPList( 255, 0, 255 ); reso3BWBPList = new VsqBPList( 255, 0, 255 ); reso4BWBPList = new VsqBPList( 255, 0, 255 ); reso1AmpBPList = new VsqBPList( 255, 0, 255 ); reso2AmpBPList = new VsqBPList( 255, 0, 255 ); reso3AmpBPList = new VsqBPList( 255, 0, 255 ); reso4AmpBPList = new VsqBPList( 255, 0, 255 ); GEN = new VsqBPList( 64, 0, 127 ); POR = new VsqBPList( 64, 0, 127 ); OPE = new VsqBPList( 127, 0, 127 ); string last_line = sr.readLine(); while ( true ) { #region "TextMemoryStreamから順次読込み" if ( last_line.Length == 0 ) { break; } switch ( last_line ) { case "[Common]": Common = new VsqCommon( sr, ref last_line ); break; case "[Master]": master = new VsqMaster( sr, ref last_line ); break; case "[Mixer]": mixer = new VsqMixer( sr, ref last_line ); break; case "[EventList]": last_line = sr.readLine(); while ( !last_line.StartsWith( "[" ) ) { string[] spl2 = last_line.Split( new char[] { '=' } ); int clock = int.Parse( spl2[0] ); int id_number = -1; if ( spl2[1] != "EOS" ) { string[] ids = spl2[1].Split( ",".ToCharArray() ); for ( int i = 0; i < ids.Length; i++ ) { string[] spl3 = ids[i].Split( new char[] { '#' } ); id_number = int.Parse( spl3[1] ); t_event_list.Add( new KeyValuePair( clock, id_number ) ); } } else { t_event_list.Add( new KeyValuePair( clock, -1) ); } if ( sr.peek() < 0 ) { break; } else { last_line = sr.readLine(); } } break; case "[PitchBendBPList]": last_line = PIT.appendFromText( sr ); break; case "[PitchBendSensBPList]": last_line = PBS.appendFromText( sr ); break; case "[DynamicsBPList]": last_line = DYN.appendFromText( sr ); break; case "[EpRResidualBPList]": last_line = BRE.appendFromText( sr ); break; case "[EpRESlopeBPList]": last_line = BRI.appendFromText( sr ); break; case "[EpRESlopeDepthBPList]": last_line = CLE.appendFromText( sr ); break; case "[Reso1FreqBPList]": last_line = reso1FreqBPList.appendFromText( sr ); break; case "[Reso2FreqBPList]": last_line = reso2FreqBPList.appendFromText( sr ); break; case "[Reso3FreqBPList]": last_line = reso3FreqBPList.appendFromText( sr ); break; case "[Reso4FreqBPList]": last_line = reso4FreqBPList.appendFromText( sr ); break; case "[Reso1BWBPList]": last_line = reso1BWBPList.appendFromText( sr ); break; case "[Reso2BWBPList]": last_line = reso2BWBPList.appendFromText( sr ); break; case "[Reso3BWBPList]": last_line = reso3BWBPList.appendFromText( sr ); break; case "[Reso4BWBPList]": last_line = reso4BWBPList.appendFromText( sr ); break; case "[Reso1AmpBPList]": last_line = reso1AmpBPList.appendFromText( sr ); break; case "[Reso2AmpBPList]": last_line = reso2AmpBPList.appendFromText( sr ); break; case "[Reso3AmpBPList]": last_line = reso3AmpBPList.appendFromText( sr ); break; case "[Reso4AmpBPList]": last_line = reso4AmpBPList.appendFromText( sr ); break; case "[GenderFactorBPList]": last_line = GEN.appendFromText( sr ); break; case "[PortamentoTimingBPList]": last_line = POR.appendFromText( sr ); break; case "[OpeningBPList]": last_line = OPE.appendFromText( sr ); break; default: string buffer = last_line; buffer = buffer.Replace( "[", "" ); buffer = buffer.Replace( "]", "" ); string[] spl = buffer.Split( new char[] { '#' } ); int index = int.Parse( spl[1] ); if ( last_line.StartsWith( "[ID#" ) ) { __id.Add( index, new VsqID( sr, index, ref last_line ) ); } else if ( last_line.StartsWith( "[h#" ) ) { __handle.Add( index, new VsqHandle( sr, index, ref last_line ) ); } break; #endregion } if ( sr.peek() < 0 ) { break; } } // まずhandleをidに埋め込み for ( int i = 0; i < __id.Count; i++ ) { if ( __handle.ContainsKey( __id[i].IconHandle_index ) ) { __id[i].IconHandle = __handle[__id[i].IconHandle_index].castToIconHandle(); } if ( __handle.ContainsKey( __id[i].LyricHandle_index ) ) { __id[i].LyricHandle = __handle[__id[i].LyricHandle_index].castToLyricHandle(); } if ( __handle.ContainsKey( __id[i].VibratoHandle_index ) ) { __id[i].VibratoHandle = __handle[__id[i].VibratoHandle_index].castToVibratoHandle(); } } // idをeventListに埋め込み m_events = new VsqEventList(); for ( int i = 0; i < t_event_list.Count; i++ ) { int clock = t_event_list[i].Key; int id_number = t_event_list[i].Value; if ( __id.ContainsKey( id_number ) ) { m_events.add( new VsqEvent( clock, (VsqID)__id[id_number].Clone() ) ); } } } public static bool test( string fpath ) { VsqMetaText metaText; using ( TextMemoryStream sr = new TextMemoryStream( fpath, Encoding.Unicode ) ) { metaText = new VsqMetaText( sr ); } string result = "test.txt"; StreamReader honmono = new StreamReader( fpath ); TextMemoryStream copy = new TextMemoryStream( FileAccess.ReadWrite ); metaText.print( copy, true, 1000, 100 ); copy.rewind(); while ( honmono.Peek() >= 0 && copy.peek() >= 0 ) { string hon = honmono.ReadLine(); string cop = copy.readLine(); if ( hon != cop ) { Console.WriteLine( "honmono,copy=" + hon + "," + cop ); honmono.Close(); copy.close(); return false; } } honmono.Close(); copy.close(); return true; } } public enum VsqIDType { Singer, Anote, Unknown } public enum VsqHandleType { Lyric, Vibrato, Singer } }