From 8ab2a598b3e341f6b84dc1528f3001a4498cfad9 Mon Sep 17 00:00:00 2001 From: kbinani Date: Wed, 29 Jul 2009 17:03:20 +0000 Subject: [PATCH] git-svn-id: http://svn.sourceforge.jp/svnroot/lipsync@8 b1f601f4-4f45-0410-8980-aecacb008692 --- trunk/Boare.Lib.AppUtil/BSplitContainer.cs | 6 +- .../Boare.Lib.AppUtil.csproj | 15 +- trunk/Boare.Lib.AppUtil/MessageBody.cs | 100 +- trunk/Boare.Lib.AppUtil/Messaging.cs | 12 + trunk/Boare.Lib.AppUtil/Misc.cs | 164 +- trunk/Boare.Lib.AppUtil/VersionInfo.cs | 1 + .../XmlSerializeWithDescription.cs | 41 +- trunk/Boare.Lib.AppUtil/makefile | 6 - trunk/Boare.Lib.Media/Boare.Lib.Media.csproj | 4 + trunk/Boare.Lib.Media/MidiInDevice.cs | 29 +- trunk/Boare.Lib.Media/Wave.cs | 38 + trunk/Boare.Lib.Media/WavePlay.cs | 22 +- trunk/Boare.Lib.Media/WaveReader.cs | 90 +- trunk/Boare.Lib.Media/WaveWriter.cs | 2 +- trunk/Boare.Lib.Vsq/Boare.Lib.Vsq.csproj | 13 +- trunk/Boare.Lib.Vsq/NRPN.cs | 611 ++++++- trunk/Boare.Lib.Vsq/SMF/MidiFile.cs | 72 +- trunk/Boare.Lib.Vsq/SingerConfig.cs | 85 +- trunk/Boare.Lib.Vsq/SymbolTable.cs | 2 +- trunk/Boare.Lib.Vsq/TempoTableEntry.cs | 130 ++ trunk/Boare.Lib.Vsq/TimeSigTableEntry.cs | 3 + trunk/Boare.Lib.Vsq/UstEvent.cs | 48 +- trunk/Boare.Lib.Vsq/UstFile.cs | 29 +- trunk/Boare.Lib.Vsq/VibratoBPList.cs | 43 + trunk/Boare.Lib.Vsq/VibratoBPPair.cs | 4 + trunk/Boare.Lib.Vsq/VsqBPList.cs | 118 +- trunk/Boare.Lib.Vsq/VsqCommand.cs | 43 +- trunk/Boare.Lib.Vsq/VsqCommandType.cs | 6 +- trunk/Boare.Lib.Vsq/VsqEvent.cs | 15 +- trunk/Boare.Lib.Vsq/VsqEventList.cs | 46 +- trunk/Boare.Lib.Vsq/VsqFile.cs | 1549 ++++++++++------- trunk/Boare.Lib.Vsq/VsqMetaText/Common.cs | 4 + trunk/Boare.Lib.Vsq/VsqMetaText/Handle.cs | 89 +- trunk/Boare.Lib.Vsq/VsqMetaText/ID.cs | 26 +- trunk/Boare.Lib.Vsq/VsqMetaText/Lyric.cs | 14 +- trunk/Boare.Lib.Vsq/VsqMetaText/Master.cs | 7 +- trunk/Boare.Lib.Vsq/VsqMetaText/Mixer.cs | 10 +- .../Boare.Lib.Vsq/VsqMetaText/VsqMetaText.cs | 317 ++-- trunk/Boare.Lib.Vsq/VsqNrpn.cs | 61 +- trunk/Boare.Lib.Vsq/VsqTrack.cs | 189 +- trunk/Boare.Lib.Vsq/makefile | 13 +- trunk/LipSync/LipSync/Editor/Form1.cs | 21 +- trunk/LipSync/LipSync/Editor/Form1Util.cs | 10 +- trunk/bocoree/bocoree.csproj | 5 +- trunk/bocoree/makefile | 2 +- trunk/bocoree/misc.cs | 39 +- trunk/bocoree/windows.cs | 35 +- trunk/bocoree/wingdi.cs | 48 + trunk/bocoree/winmm.cs | 700 ++++++-- 49 files changed, 3567 insertions(+), 1370 deletions(-) diff --git a/trunk/Boare.Lib.AppUtil/BSplitContainer.cs b/trunk/Boare.Lib.AppUtil/BSplitContainer.cs index d943296..aac39df 100644 --- a/trunk/Boare.Lib.AppUtil/BSplitContainer.cs +++ b/trunk/Boare.Lib.AppUtil/BSplitContainer.cs @@ -429,11 +429,11 @@ namespace Boare.Lib.AppUtil { protected override void OnSizeChanged( EventArgs e ) { #if DEBUG - Console.WriteLine( "BSplitContainer+OnSizeChanged" ); + //Console.WriteLine( "BSplitContainer+OnSizeChanged" ); //Console.WriteLine( " FixedPanel=" + FixedPanel ); //Console.WriteLine( " m_splitter_distance=" + m_splitter_distance ); - Console.WriteLine( " Width=" + Width ); - Console.WriteLine( " Height=" + Height ); + //Console.WriteLine( " Width=" + Width ); + //Console.WriteLine( " Height=" + Height ); //Console.WriteLine( " m_panel2_distance=" + m_panel2_distance ); #endif base.OnSizeChanged( e ); diff --git a/trunk/Boare.Lib.AppUtil/Boare.Lib.AppUtil.csproj b/trunk/Boare.Lib.AppUtil/Boare.Lib.AppUtil.csproj index ee00d4c..0b38cdb 100644 --- a/trunk/Boare.Lib.AppUtil/Boare.Lib.AppUtil.csproj +++ b/trunk/Boare.Lib.AppUtil/Boare.Lib.AppUtil.csproj @@ -3,15 +3,18 @@ Debug AnyCPU - 9.0.21022 + 9.0.30729 2.0 {0C58B068-272F-4390-A14F-3D72AFCF3DFB} Library Properties Boare.Lib.AppUtil Boare.Lib.AppUtil - v3.5 + v2.0 512 + false + + true @@ -49,9 +52,6 @@ - - 3.5 - @@ -74,6 +74,10 @@ + + + Component + Form @@ -81,6 +85,7 @@ InputBox.cs + diff --git a/trunk/Boare.Lib.AppUtil/MessageBody.cs b/trunk/Boare.Lib.AppUtil/MessageBody.cs index c8bc0f5..2ca09ac 100644 --- a/trunk/Boare.Lib.AppUtil/MessageBody.cs +++ b/trunk/Boare.Lib.AppUtil/MessageBody.cs @@ -21,7 +21,7 @@ namespace Boare.Lib.AppUtil { public class MessageBody { public string lang; public string po_header = ""; - public Dictionary list = new Dictionary(); + public Dictionary list = new Dictionary(); public MessageBody( string lang_ ) { lang = lang_; @@ -29,55 +29,81 @@ namespace Boare.Lib.AppUtil { public MessageBody( string lang, string[] ids, string[] messages ) { this.lang = lang; - list = new Dictionary(); + list = new Dictionary(); for( int i = 0; i < ids.Length; i++ ) { - list.Add( ids[i], messages[i] ); + list.Add( ids[i], new MessageBodyEntry( messages[i], new string[] { } ) ); } } public MessageBody( string lang_, string file ) { lang = lang_; - //Dictionary list = new Dictionary(); po_header = ""; using ( StreamReader sr = new StreamReader( file ) ) { while ( sr.Peek() >= 0 ) { string msgid; string first_line = sr.ReadLine(); - string last_line = ReadTillMessageEnd( sr, first_line, "msgid", out msgid ); + string[] location; + string last_line = ReadTillMessageEnd( sr, first_line, "msgid", out msgid, out location ); string msgstr; - last_line = ReadTillMessageEnd( sr, last_line, "msgstr", out msgstr ); - //if ( msgid.Length > 0 && msgstr.Length > 0 ) { + string[] location_dumy; + last_line = ReadTillMessageEnd( sr, last_line, "msgstr", out msgstr, out location_dumy ); if ( msgid.Length > 0 ) { if ( list.ContainsKey( msgid ) ) { - list[msgid] = msgstr; + list[msgid] = new MessageBodyEntry( msgstr, location ); } else { - list.Add( msgid, msgstr ); + list.Add( msgid, new MessageBodyEntry( msgstr, location ) ); } } else { po_header = msgstr; + string[] spl = po_header.Split( new char[] { (char)0x0d, (char)0x0a }, StringSplitOptions.RemoveEmptyEntries ); + po_header = ""; + int count = 0; + foreach ( string line in spl ) { + string[] spl2 = line.Split( new char[] { ':' }, 2 ); + if ( spl2.Length == 2 ) { + string name = spl2[0].Trim(); + if ( name.ToLower() == "Content-Type".ToLower() ) { + po_header += (count == 0 ? "" : "\n") + "Content-Type: text/plain; charset=UTF-8"; + } else if ( name.ToLower() == "Content-Transfer-Encoding".ToLower() ) { + po_header += (count == 0 ? "" : "\n") + "Content-Transfer-Encoding: 8bit"; + } else { + po_header += (count == 0 ? "" : "\n") + line; + } + } else { + po_header += (count == 0 ? "" : "\n") + line; + } + count++; + } } } } - string[] ids = new string[list.Keys.Count]; - string[] msgs = new string[ids.Length]; - int i = -1; - foreach ( string id in list.Keys ) { - i++; - ids[i] = id; - msgs[i] = list[ids[i]]; - } +#if DEBUG + Console.WriteLine( "MessageBody..ctor; po_header=" + po_header ); +#endif } public string GetMessage( string id ) { if ( list.ContainsKey( id ) ) { - string ret = list[id]; + string ret = list[id].Message; if ( ret == "" ) { return id; + } else { + return list[id].Message; + } + } + return id; + } + + public MessageBodyEntry GetMessageDetail( string id ) { + if ( list.ContainsKey( id ) ) { + string ret = list[id].Message; + if ( ret == "" ) { + return new MessageBodyEntry( id, new string[] { } ); } else { return list[id]; } } - return id; + return new MessageBodyEntry( id, new string[] { } ); } public void Write( string file ) { @@ -85,19 +111,26 @@ namespace Boare.Lib.AppUtil { if ( po_header != "" ) { sw.WriteLine( "msgid \"\"" ); sw.WriteLine( "msgstr \"\"" ); - sw.WriteLine( po_header ); + string[] spl = po_header.Split( new char[] { (char)0x0d, (char)0x0a }, StringSplitOptions.RemoveEmptyEntries ); + foreach ( string line in spl ) { + sw.WriteLine( "\"" + line + "\\" + "n\"" ); + } sw.WriteLine(); } else { sw.WriteLine( "msgid \"\"" ); sw.WriteLine( "msgstr \"\"" ); - sw.WriteLine( "\"Content-Type: text/plain; charset=UTF-8\\n\"" ); - sw.WriteLine( "\"Content-Transfer-Encoding: 8bit\\n\"" ); + sw.WriteLine( "\"Content-Type: text/plain; charset=UTF-8\\" + "n\"" ); + sw.WriteLine( "\"Content-Transfer-Encoding: 8bit\\" + "n\"" ); sw.WriteLine(); } foreach ( string key in list.Keys ) { string skey = key.Replace( "\n", "\\n\"\n\"" ); + string s = list[key].Message; + List location = list[key].Location; + for ( int i = 0; i < location.Count; i++ ) { + sw.WriteLine( "#: " + location[i] ); + } sw.WriteLine( "msgid \"" + skey + "\"" ); - string s = list[key]; s = s.Replace( "\n", "\\n\"\n\"" ); sw.WriteLine( "msgstr \"" + s + "\"" ); sw.WriteLine(); @@ -120,28 +153,35 @@ namespace Boare.Lib.AppUtil { message = message.Substring( 0, message.Length - 1 ); } - private static string ReadTillMessageEnd( StreamReader sr, string first_line, string entry, out string msg ) { + private static string ReadTillMessageEnd( StreamReader sr, string first_line, string entry, out string msg, out string[] locations ) { msg = ""; string line = first_line; + List location = new List(); bool entry_found = false; if ( line.StartsWith( entry ) ) { + // 1行目がすでに"entry"の行だった場合 string dum, dum2; SeparateEntryAndMessage( line, out dum, out dum2 ); msg += dum2; } else { - while ( sr.Peek() >= 0 ) { - line = sr.ReadLine(); - if ( line.StartsWith( "#" ) ) { - continue; - } - if ( line.StartsWith( entry ) ) { + while ( true ) { + if ( line.StartsWith( "#:" ) ) { + line = line.Substring( 2 ).Trim(); + location.Add( line ); + } else if ( line.StartsWith( entry ) ) { string dum, dum2; SeparateEntryAndMessage( line, out dum, out dum2 ); msg += dum2; break; } + if ( sr.Peek() >= 0 ) { + line = sr.ReadLine(); + } else { + break; + } } } + locations = location.ToArray(); string ret = ""; while ( sr.Peek() >= 0 ) { line = sr.ReadLine(); diff --git a/trunk/Boare.Lib.AppUtil/Messaging.cs b/trunk/Boare.Lib.AppUtil/Messaging.cs index 30eb1f7..4af6471 100644 --- a/trunk/Boare.Lib.AppUtil/Messaging.cs +++ b/trunk/Boare.Lib.AppUtil/Messaging.cs @@ -91,6 +91,18 @@ namespace Boare.Lib.AppUtil { s_messages.Add( new MessageBody( Path.GetFileNameWithoutExtension( file ), file ) ); } + public static MessageBodyEntry GetMessageDetail( string id ) { + if ( s_lang.Length <= 0 ) { + s_lang = "en"; + } + foreach ( MessageBody mb in s_messages ) { + if ( mb.lang == s_lang ) { + return mb.GetMessageDetail( id ); + } + } + return new MessageBodyEntry( id, new string[] { } ); + } + public static string GetMessage( string id ) { if ( s_lang.Length <= 0 ) { s_lang = "en"; diff --git a/trunk/Boare.Lib.AppUtil/Misc.cs b/trunk/Boare.Lib.AppUtil/Misc.cs index 56ea996..28d1e40 100644 --- a/trunk/Boare.Lib.AppUtil/Misc.cs +++ b/trunk/Boare.Lib.AppUtil/Misc.cs @@ -13,16 +13,120 @@ */ using System; using System.Collections.Generic; -using System.Text; using System.Drawing; -using System.Windows.Forms; using System.Drawing.Imaging; -using System.Reflection; using System.IO; +using System.Reflection; +using System.Windows.Forms; namespace Boare.Lib.AppUtil { public static partial class Misc { + public static void ApplyContextMenuFontRecurse( ContextMenuStrip item, Font font ) { + item.Font = font; + foreach ( ToolStripItem tsi in item.Items ) { + ApplyToolStripFontRecurse( tsi, font ); + } + } + + public static void ApplyToolStripFontRecurse( ToolStripItem item, Font font ) { + item.Font = font; + if ( item is ToolStripMenuItem ) { + ToolStripMenuItem tsmi = (ToolStripMenuItem)item; + foreach ( ToolStripItem tsi in tsmi.DropDownItems ) { + ApplyToolStripFontRecurse( tsi, font ); + } + } else if ( item is ToolStripDropDownItem ) { + ToolStripDropDownItem tsdd = (ToolStripDropDownItem)item; + foreach ( ToolStripItem tsi in tsdd.DropDownItems ) { + ApplyToolStripFontRecurse( tsi, font ); + } + } + } + + /// + /// 指定したフォントを描画するとき、描画指定したy座標と、描かれる文字の中心線のズレを調べます + /// + /// + /// + public static int GetStringDrawOffset( Font font ) { + int ret = 0; + string pangram = "cozy lummox gives smart squid who asks for job pen. 01234567890 THE QUICK BROWN FOX JUMPED OVER THE LAZY DOGS."; + SizeF size = new SizeF(); + using ( Bitmap b = new Bitmap( 1, 1 ) ) { + using ( Graphics g = Graphics.FromImage( b ) ) { + size = g.MeasureString( pangram, font ); + } + } + if ( size.Height <= 0 ) { + return 0; + } + using ( Bitmap b = new Bitmap( (int)size.Width * 3, (int)size.Height * 3 ) ) { + using ( Graphics g = Graphics.FromImage( b ) ) { + g.Clear( Color.White ); + g.DrawString( pangram, font, Brushes.Black, new PointF( (int)size.Width, (int)size.Height ) ); + } + using ( BitmapEx b2 = new BitmapEx( b ) ) { + // 上端に最初に現れる色つきピクセルを探す + int firsty = 0; + bool found = false; + for ( int y = 0; y < b2.Height; y++ ) { + for ( int x = 0; x < b2.Width; x++ ) { + Color c = b2.GetPixel( x, y ); + if ( c.R != 255 || c.G != 255 || c.B != 255 ) { + found = true; + firsty = y; + break; + } + } + if ( found ) { + break; + } + } + + // 下端 + int endy = b2.Height - 1; + found = false; + for ( int y = b2.Height - 1; y >= 0; y-- ) { + for ( int x = 0; x < b2.Width; x++ ) { + Color c = b2.GetPixel( x, y ); + if ( c.R != 255 || c.G != 255 || c.B != 255 ) { + found = true; + endy = y; + break; + } + } + if ( found ) { + break; + } + } + + int center = (firsty + endy) / 2; + ret = center - (int)size.Height; + } + } + return ret; + } + + /// + /// 指定した言語コードの表す言語が、右から左へ記述する言語かどうかを調べます + /// + /// + /// + public static bool IsRightToLeftLanguage( string language_code ) { + language_code = language_code.ToLower(); + switch ( language_code ) { + case "ar": + case "he": + case "iw": + case "fa": + case "ur": + return true; + default: + return false; + } + } + /// /// 指定したディレクトリに作成可能な、一時ファイル名を取得します /// @@ -92,19 +196,19 @@ namespace Boare.Lib.AppUtil { public static string GetExtensionFromImageFormat( ImageFormat format ) { switch ( format.ToString().ToLower() ) { case "bmp": - return "bmp"; + return ".bmp"; case "emf": - return "emf"; + return ".emf"; case "gif": - return "gif"; + return ".gif"; case "jpeg": - return "jpg"; + return ".jpg"; case "png": - return "png"; + return ".png"; case "tiff": - return "tiff"; + return ".tiff"; case "wmf": - return "wmf"; + return ".wmf"; default: return ""; @@ -169,44 +273,6 @@ namespace Boare.Lib.AppUtil { v = imax; } - /*public static void RgbToHsv( double r, double g, double b, out double h, out double s, out double v ) { - double tmph, imax, imin; - const double sqrt3 = 1.7320508075688772935274463415059; - const double deg2rad = 180.0 / Math.PI; - imax = Math.Max( r, Math.Max( g, b ) ); - imin = Math.Min( r, Math.Min( g, b ) ); - if ( imax == 0.0 ) { - h = 0; - s = 0; - v = 0; - return; - } else if ( imax == imin ) { - tmph = 0; - } else { - double x = 2.0 * r - g - b; - double y = sqrt3 * (g - b); - if ( x == 0.0 ) { - if ( y > 0.0 ) { - tmph = 90.0; - } else { - tmph = 270.0; - } - } else { - tmph = Math.Atan2( y, x ); - tmph = tmph * deg2rad; - } - } - while ( tmph < 0.0 ) { - tmph = tmph + 360.0; - } - while ( tmph >= 360.0 ) { - tmph = tmph - 360.0; - } - h = tmph / 360.0; - s = (imax - imin) / imax; - v = imax; - }*/ - public static Color HsvToColor( double h, double s, double v ) { double dr, dg, db; HsvToRgb( h, s, v, out dr, out dg, out db ); @@ -286,7 +352,7 @@ namespace Boare.Lib.AppUtil { } /// - /// 指定したコントロールと、その子コントロールのフォントを変更します + /// 指定したコントロールと、その子コントロールのフォントを再帰的に変更します /// /// /// diff --git a/trunk/Boare.Lib.AppUtil/VersionInfo.cs b/trunk/Boare.Lib.AppUtil/VersionInfo.cs index aef1bc4..e1af10a 100644 --- a/trunk/Boare.Lib.AppUtil/VersionInfo.cs +++ b/trunk/Boare.Lib.AppUtil/VersionInfo.cs @@ -179,6 +179,7 @@ namespace Boare.Lib.AppUtil { m_last_speed = 0f; m_last_t = 0f; m_shift = 0f; + timer.Enabled = true; } else { timer.Enabled = false; diff --git a/trunk/Boare.Lib.AppUtil/XmlSerializeWithDescription.cs b/trunk/Boare.Lib.AppUtil/XmlSerializeWithDescription.cs index c2d9966..1a815b4 100644 --- a/trunk/Boare.Lib.AppUtil/XmlSerializeWithDescription.cs +++ b/trunk/Boare.Lib.AppUtil/XmlSerializeWithDescription.cs @@ -1,4 +1,17 @@ -using System; +/* + * XmlSerializeWithDescription.cs + * Copyright (c) 2009 kbinani + * + * This file is part of Boare.Lib.AppUtil. + * + * Boare.Lib.AppUtil is free software; you can redistribute it and/or + * modify it under the terms of the BSD License. + * + * Boare.Lib.AppUtil 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.Xml; @@ -41,9 +54,6 @@ namespace Boare.Lib.AppUtil { /// フィールドおよびプロパティを、XmlItemDescription属性の文字列を付加しながらXmlシリアライズする /// public class XmlSerializeWithDescription { - [XmlItemDescription( "mio" )] - private string foo; - private XmlTextWriter m_writer; private Type m_type; @@ -69,28 +79,11 @@ namespace Boare.Lib.AppUtil { if ( t.IsGenericType ) { List f = new List(); Type list_type = f.GetType().GetGenericTypeDefinition(); -#if DEBUG - Console.WriteLine( "t.GetGenericTypeDefinition().Equals( list_type )=" + t.GetGenericTypeDefinition().Equals( list_type ) ); -#endif if ( t.GetGenericTypeDefinition().Equals( list_type ) ) { Type[] gen = t.GetGenericArguments(); -#if DEBUG - Console.WriteLine( "gen.Length=" + gen.Length ); -#endif if ( gen.Length == 1 ) { PropertyInfo count_property = t.GetProperty( "Count", typeof( int ) ); int count = (int)count_property.GetValue( obj, new object[] { } ); -#if DEBUG - Console.WriteLine( "count=" + count ); - Console.WriteLine( "Properties" ); - foreach ( PropertyInfo pi in t.GetProperties() ) { - Console.WriteLine( " " + pi ); - } - Console.WriteLine( "Methods" ); - foreach ( MethodInfo mi in t.GetMethods() ) { - Console.WriteLine( " " + mi ); - } -#endif Type returntype = gen[0]; MethodInfo indexer = t.GetMethod( "get_Item", new Type[] { typeof( int ) } ); string name = ""; @@ -134,9 +127,6 @@ namespace Boare.Lib.AppUtil { xid = (XmlItemDescription)attr[0]; } WriteContents( fi.Name, fi.GetValue( obj ), xid ); -#if DEBUG - m_writer.Flush(); -#endif } foreach ( PropertyInfo pi in t.GetProperties() ) { if ( !pi.CanRead | !pi.CanWrite ) { @@ -154,9 +144,6 @@ namespace Boare.Lib.AppUtil { xid = (XmlItemDescription)attr[0]; } WriteContents( pi.Name, pi.GetValue( obj, new object[] { } ), xid ); -#if DEBUG - m_writer.Flush(); -#endif } } } diff --git a/trunk/Boare.Lib.AppUtil/makefile b/trunk/Boare.Lib.AppUtil/makefile index 0087be8..8106f0f 100644 --- a/trunk/Boare.Lib.AppUtil/makefile +++ b/trunk/Boare.Lib.AppUtil/makefile @@ -6,12 +6,6 @@ Boare.Lib.AppUtil.dll: *.cs bocoree.dll gmcs $(OPT) -recurse:*.cs -unsafe+ -target:library -out:Boare.Lib.AppUtil.dll \ -r:bocoree.dll,System.Drawing,System.Windows.Forms -bocoree.dll: ../bocoree/bocoree.dll - cp ../bocoree/bocoree.dll bocoree.dll - -../bocoree/bocoree.dll: - cd ../bocoree/ && $(MAKE) OPT=$(OPT) - clean: $(RM) Boare.Lib.AppUtil.dll $(RM) bocoree.dll diff --git a/trunk/Boare.Lib.Media/Boare.Lib.Media.csproj b/trunk/Boare.Lib.Media/Boare.Lib.Media.csproj index e9938f6..9e0ac18 100644 --- a/trunk/Boare.Lib.Media/Boare.Lib.Media.csproj +++ b/trunk/Boare.Lib.Media/Boare.Lib.Media.csproj @@ -15,6 +15,9 @@ v2.0 + false + + true @@ -63,6 +66,7 @@ + diff --git a/trunk/Boare.Lib.Media/MidiInDevice.cs b/trunk/Boare.Lib.Media/MidiInDevice.cs index 3c8b2ec..aca1e56 100644 --- a/trunk/Boare.Lib.Media/MidiInDevice.cs +++ b/trunk/Boare.Lib.Media/MidiInDevice.cs @@ -24,23 +24,10 @@ namespace Boare.Lib.Media { public class MidiInDevice : IDisposable { delegate void MidiInProcDelegate( uint hMidiIn, uint wMsg, int dwInstance, int dwParam1, int dwParam2 ); - private const int CALLBACK_EVENT = 0x50000; - private const int CALLBACK_FUNCTION = 0x30000; - private const int CALLBACK_NULL = 0; - private const int CALLBACK_TASK = 0x20000; - private const int CALLBACK_THREAD = 0x20000; - private const int CALLBACK_TYPEMASK = 0x70000; - private const int CALLBACK_WINDOW = 0x10000; private volatile MidiInProcDelegate m_delegate; private IntPtr m_delegate_pointer; private uint m_hmidiin = 0; private int m_port_number; - private const int MM_MIM_CLOSE = 0x3c2; - private const int MM_MIM_DATA = 0x3c3; - private const int MM_MIM_ERROR = 0x3c5; - private const int MM_MIM_LONGDATA = 0x3c4; - private const int MM_MIM_LONGERROR = 0x3c6; - private const int MM_MIM_OPEN = 0x3c1; public event MidiReceivedEventHandler MidiReceived; @@ -48,7 +35,7 @@ namespace Boare.Lib.Media { m_port_number = port_number; m_delegate = new MidiInProcDelegate( MidiInProc ); m_delegate_pointer = Marshal.GetFunctionPointerForDelegate( m_delegate ); - windows.midiInOpen( ref m_hmidiin, port_number, m_delegate_pointer, 0, CALLBACK_FUNCTION ); + windows.midiInOpen( ref m_hmidiin, port_number, m_delegate_pointer, 0, windows.CALLBACK_FUNCTION ); } public void Start() { @@ -116,14 +103,14 @@ namespace Boare.Lib.Media { return ret.ToArray(); } - private void MidiInProc( uint hMidiIn, uint wMsg, int dwInstance, int dwParam1, int dwParam2 ) { + public void MidiInProc( uint hMidiIn, uint wMsg, int dwInstance, int dwParam1, int dwParam2 ) { try { switch ( wMsg ) { - case MM_MIM_OPEN: + case windows.MM_MIM_OPEN: return; - case MM_MIM_CLOSE: + case windows.MM_MIM_CLOSE: return; - case MM_MIM_DATA: + case windows.MM_MIM_DATA: int receive = dwParam1; DateTime now = DateTime.Now; switch ( receive & 0xF0 ) { @@ -147,11 +134,11 @@ namespace Boare.Lib.Media { break; } return; - case MM_MIM_LONGDATA: + case windows.MM_MIM_LONGDATA: return; - case MM_MIM_ERROR: + case windows.MM_MIM_ERROR: return; - case MM_MIM_LONGERROR: + case windows.MM_MIM_LONGERROR: return; } } catch ( Exception ex ) { diff --git a/trunk/Boare.Lib.Media/Wave.cs b/trunk/Boare.Lib.Media/Wave.cs index 2615824..5de0197 100644 --- a/trunk/Boare.Lib.Media/Wave.cs +++ b/trunk/Boare.Lib.Media/Wave.cs @@ -85,6 +85,44 @@ namespace Boare.Lib.Media { } } #endif + public unsafe double TEST_GetF0( uint time, double[] window_function ) { + int window_size = window_function.Length; + double[] formanto = GetFormanto( time, window_function ); +#if DEBUG + if ( s_test ) { + using ( StreamWriter sw = new StreamWriter( @"C:\TEST_GetF0_formanto.txt" ) ) { + for ( int i = 0; i < formanto.Length; i++ ) { + sw.WriteLine( Math.Abs( formanto[i] ) ); + } + } + } +#endif + int size = formanto.Length; + double[] wv = new double[size + 1]; + for ( int i = 0; i < size; i++ ) { + wv[i] = formanto[i]; + } + int nmaxsqrt = (int)Math.Sqrt( size ); + int[] ip_ = new int[nmaxsqrt + 2]; + double[] w_ = new double[size * 5 / 4]; + ip_[0] = 0; + + fixed ( int* ip = &ip_[0] ) + fixed ( double* w = &w_[0] ) + fixed ( double* a = &wv[0] ) { + fft.rdft( size, 1, a, ip, w ); + } +#if DEBUG + if ( s_test ) { + using ( StreamWriter sw = new StreamWriter( @"C:\TEST_GetF0_fft_formanto.txt" ) ) { + for ( int i = 0; i < wv.Length; i++ ) { + sw.WriteLine( Math.Abs( wv[i] ) ); + } + } + } +#endif + return 0; + } public double GetF0( uint time, double[] window_function ) { return GetF0( time, window_function, new FormantoDetectionArguments() ); diff --git a/trunk/Boare.Lib.Media/WavePlay.cs b/trunk/Boare.Lib.Media/WavePlay.cs index 3730602..64306bb 100644 --- a/trunk/Boare.Lib.Media/WavePlay.cs +++ b/trunk/Boare.Lib.Media/WavePlay.cs @@ -71,21 +71,15 @@ namespace Boare.Lib.Media { } else { index_done = dwuser; } -#if DEBUG - bocoree.debug.push_log( "dwuser=" + dwuser ); - bocoree.debug.push_log( "index_done=" + index_done ); -#endif - s_done[index_done] = true; - if ( s_last_buffer == index_done ) { - s_playing = false; + if ( 0 <= index_done && index_done < _NUM_BUF ) { + s_done[index_done] = true; + if ( s_last_buffer == index_done ) { + s_playing = false; + } + if ( dwuser >= _NUM_BUF ) { + s_wave_header[index_done].dwUser = new IntPtr( index_done ); + } } - if ( dwuser >= _NUM_BUF ) { - s_wave_header[index_done].dwUser = new IntPtr( index_done ); - } -#if DEBUG - bocoree.debug.push_log( "whdr.dwUser=" + whdr.dwUser.ToInt32() ); - bocoree.debug.push_log( "dwParam1=0x" + Convert.ToString( dwParam1, 16 ) + "; dwParam2=0x" + Convert.ToString( dwParam2, 16 ) ); -#endif } } diff --git a/trunk/Boare.Lib.Media/WaveReader.cs b/trunk/Boare.Lib.Media/WaveReader.cs index 1cc9033..7f0bfcc 100644 --- a/trunk/Boare.Lib.Media/WaveReader.cs +++ b/trunk/Boare.Lib.Media/WaveReader.cs @@ -40,7 +40,7 @@ namespace Boare.Lib.Media { if ( m_opened ) { m_stream.Close(); } - m_stream = new FileStream( file, FileMode.Open ); + m_stream = new FileStream( file, FileMode.Open, FileAccess.Read ); // RIFF byte[] buf = new byte[4]; @@ -116,13 +116,13 @@ namespace Boare.Lib.Media { } } - public void Read( int start, int length, out float[] left, out float[] right ) { - left = new float[length]; - right = new float[length]; + public void Read( long start, int length, out double[] left, out double[] right ) { + left = new double[length]; + right = new double[length]; if ( !m_opened ) { return; } - int loc = 0x2e + m_byte_per_sample * m_channel * start; + long loc = 0x2e + m_byte_per_sample * m_channel * start; m_stream.Seek( loc, SeekOrigin.Begin ); if ( m_byte_per_sample == 2 ) { @@ -191,7 +191,82 @@ namespace Boare.Lib.Media { } } - public unsafe void Read( int start, int length, out IntPtr ptr_left, out IntPtr ptr_right ) { + public void Read( long start, int length, out float[] left, out float[] right ) { + left = new float[length]; + right = new float[length]; + if ( !m_opened ) { + return; + } + long loc = 0x2e + m_byte_per_sample * m_channel * start; + m_stream.Seek( loc, SeekOrigin.Begin ); + + if ( m_byte_per_sample == 2 ) { + if ( m_channel == 2 ) { + byte[] buf = new byte[4]; + for ( int i = 0; i < length; i++ ) { + int ret = m_stream.Read( buf, 0, 4 ); + if ( ret < 4 ) { + for ( int j = i; j < length; j++ ) { + left[j] = 0.0f; + right[j] = 0.0f; + } + break; + } + short l = (short)(buf[0] | buf[1] << 8); + short r = (short)(buf[2] | buf[3] << 8); + left[i] = l / 32768.0f; + right[i] = r / 32768.0f; + } + } else { + byte[] buf = new byte[2]; + for ( int i = 0; i < length; i++ ) { + int ret = m_stream.Read( buf, 0, 2 ); + if ( ret < 2 ) { + for ( int j = i; j < length; j++ ) { + left[j] = 0.0f; + right[j] = 0.0f; + } + break; + } + short l = (short)(buf[0] | buf[1] << 8); + left[i] = l / 32768.0f; + right[i] = left[i]; + } + } + } else { + if ( m_channel == 2 ) { + byte[] buf = new byte[2]; + for ( int i = 0; i < length; i++ ) { + int ret = m_stream.Read( buf, 0, 2 ); + if ( ret < 2 ) { + for ( int j = i; j < length; j++ ) { + left[j] = 0.0f; + right[j] = 0.0f; + } + break; + } + left[i] = (buf[0] - 64.0f) / 64.0f; + right[i] = (buf[1] - 64.0f) / 64.0f; + } + } else { + byte[] buf = new byte[1]; + for ( int i = 0; i < length; i++ ) { + int ret = m_stream.Read( buf, 0, 1 ); + if ( ret < 1 ) { + for ( int j = i; j < length; j++ ) { + left[j] = 0.0f; + right[j] = 0.0f; + } + break; + } + left[i] = (buf[0] - 64.0f) / 64.0f; + right[i] = left[i]; + } + } + } + } + + public unsafe void Read( long start, int length, out IntPtr ptr_left, out IntPtr ptr_right ) { ptr_left = Marshal.AllocHGlobal( sizeof( float ) * length ); ptr_right = Marshal.AllocHGlobal( sizeof( float ) * length ); float* left = (float*)ptr_left.ToPointer(); @@ -199,7 +274,7 @@ namespace Boare.Lib.Media { if ( !m_opened ) { return; } - int loc = 0x2e + m_byte_per_sample * m_channel * start; + long loc = 0x2e + m_byte_per_sample * m_channel * start; m_stream.Seek( loc, SeekOrigin.Begin ); if ( m_byte_per_sample == 2 ) { @@ -272,6 +347,7 @@ namespace Boare.Lib.Media { m_opened = false; if ( m_stream != null ) { m_stream.Close(); + m_stream = null; } } diff --git a/trunk/Boare.Lib.Media/WaveWriter.cs b/trunk/Boare.Lib.Media/WaveWriter.cs index e4591e7..e94795d 100644 --- a/trunk/Boare.Lib.Media/WaveWriter.cs +++ b/trunk/Boare.Lib.Media/WaveWriter.cs @@ -30,7 +30,7 @@ namespace Boare.Lib.Media { public WaveWriter( string path, WaveChannel channel, ushort bit_per_sample, uint sample_rate ) { m_path = path; - m_stream = new FileStream( m_path, FileMode.Create ); + m_stream = new FileStream( m_path, FileMode.Create, FileAccess.Write ); m_channel = channel; m_bit_per_sample = bit_per_sample; m_sample_rate = sample_rate; diff --git a/trunk/Boare.Lib.Vsq/Boare.Lib.Vsq.csproj b/trunk/Boare.Lib.Vsq/Boare.Lib.Vsq.csproj index 55616ef..af7814a 100644 --- a/trunk/Boare.Lib.Vsq/Boare.Lib.Vsq.csproj +++ b/trunk/Boare.Lib.Vsq/Boare.Lib.Vsq.csproj @@ -2,7 +2,7 @@ Debug AnyCPU - 9.0.21022 + 9.0.30729 2.0 {673347F3-6FC2-4F82-9273-BF158E0F8CB1} Library @@ -15,6 +15,9 @@ v2.0 + false + + true @@ -60,14 +63,20 @@ + + + + + + @@ -91,7 +100,7 @@ - + diff --git a/trunk/Boare.Lib.Vsq/NRPN.cs b/trunk/Boare.Lib.Vsq/NRPN.cs index 294bcf4..b57dc32 100644 --- a/trunk/Boare.Lib.Vsq/NRPN.cs +++ b/trunk/Boare.Lib.Vsq/NRPN.cs @@ -11,239 +11,736 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ +using System; +using System.Reflection; +using System.Collections.Generic; + namespace Boare.Lib.Vsq { - public enum NRPN : ushort { + public static class NRPN { /// /// (0x5000) Version number(MSB) &, Device number(LSB) /// - CVM_NM_VERSION_AND_DEVICE = 0x5000, + public const ushort CVM_NM_VERSION_AND_DEVICE = 0x5000; /// /// (0x5001) Delay in millisec(MSB, LSB) /// - CVM_NM_DELAY = 0x5001, + public const ushort CVM_NM_DELAY = 0x5001; /// /// (0x5002) Note number(MSB) /// - CVM_NM_NOTE_NUMBER = 0x5002, + public const ushort CVM_NM_NOTE_NUMBER = 0x5002; /// /// (0x5003) Velocity(MSB) /// - CVM_NM_VELOCITY = 0x5003, + public const ushort CVM_NM_VELOCITY = 0x5003; /// /// (0x5004) Note Duration in millisec(MSB, LSB) /// - CVM_NM_NOTE_DURATION = 0x5004, + public const ushort CVM_NM_NOTE_DURATION = 0x5004; /// /// (0x5005) Note Location(MSB) /// - CVM_NM_NOTE_LOCATION = 0x5005, + public const ushort CVM_NM_NOTE_LOCATION = 0x5005; + /// + /// (0x5006) Attack Type(MSB, LSB) + /// + public const ushort CVM_NM_ATTACK_TYPE = 0x5006; + /// + /// (0x5007) Attack Duration in millisec(MSB, LSB) + /// + public const ushort CVM_NM_ATTACK_DURATION = 0x5007; + /// + /// (0x5008) Attack Depth(MSB) + /// + public const ushort CVM_NM_ATTACK_DEPTH = 0x5008; /// /// (0x500c) Index of Vibrato DB(MSB: ID_H00, LSB:ID_L00) /// - CVM_NM_INDEX_OF_VIBRATO_DB = 0x500c, + public const ushort CVM_NM_INDEX_OF_VIBRATO_DB = 0x500c; /// /// (0x500d) Vibrato configuration(MSB: Index of Vibrato Type, LSB: Duration &, Configuration parameter of vibrato) /// - CVM_NM_VIBRATO_CONFIG = 0x500d, + public const ushort CVM_NM_VIBRATO_CONFIG = 0x500d; /// /// (0x500e) Vibrato Delay(MSB) /// - CVM_NM_VIBRATO_DELAY = 0x500e, + public const ushort CVM_NM_VIBRATO_DELAY = 0x500e; + /*/// + /// (0x5011) Unknonw(MSB), only used in VOCALOID1 + /// + public const ushort CVM_NM_UNKNOWN1 = 0x5011;*/ /// /// (0x5012) Number of phonetic symbols in bytes(MSB) /// - CVM_NM_PHONETIC_SYMBOL_BYTES = 0x5012, + public const ushort CVM_NM_PHONETIC_SYMBOL_BYTES = 0x5012; /// /// (0x5013) Phonetic symbol 1(MSB:Phonetic symbol 1, LSB: Consonant adjustment 1) /// - CVM_NM_PHONETIC_SYMBOL1 = 0x5013, + public const ushort CVM_NM_PHONETIC_SYMBOL1 = 0x5013; + /// + /// (0x5014) Phonetic symbol 2(MSB:Phonetic symbol 2, LSB: Consonant adjustment 2) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL2 = 0x5014; + /// + /// (0x5015) Phonetic symbol 3(MSB:Phonetic symbol 3, LSB: Consonant adjustment 3) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL3 = 0x5015; + /// + /// (0x5016) Phonetic symbol 4(MSB:Phonetic symbol 4, LSB: Consonant adjustment 4) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL4 = 0x5016; + /// + /// (0x5017) Phonetic symbol 5(MSB:Phonetic symbol 5, LSB: Consonant adjustment 5) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL5 = 0x5017; + /// + /// (0x5018) Phonetic symbol 6(MSB:Phonetic symbol 6, LSB: Consonant adjustment 6) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL6 = 0x5018; + /// + /// (0x5019) Phonetic symbol 7(MSB:Phonetic symbol 7, LSB: Consonant adjustment 7) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL7 = 0x5019; + /// + /// (0x501a) Phonetic symbol 8(MSB:Phonetic symbol 8, LSB: Consonant adjustment 8) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL8 = 0x501a; + /// + /// (0x501b) Phonetic symbol 9(MSB:Phonetic symbol 9, LSB: Consonant adjustment 9) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL9 = 0x501b; + /// + /// (0x501c) Phonetic symbol 10(MSB:Phonetic symbol 10, LSB: Consonant adjustment 10) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL10 = 0x501c; + /// + /// (0x501d) Phonetic symbol 11(MSB:Phonetic symbol 11, LSB: Consonant adjustment 11) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL11 = 0x501d; + /// + /// (0x501e) Phonetic symbol 12(MSB:Phonetic symbol 12, LSB: Consonant adjustment 12) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL12 = 0x501e; + /// + /// (0x501f) Phonetic symbol 13(MSB:Phonetic symbol 13, LSB: Consonant adjustment 13) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL13 = 0x501f; + /// + /// (0x5020) Phonetic symbol 14(MSB:Phonetic symbol 14, LSB: Consonant adjustment 14) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL14 = 0x5020; + /// + /// (0x5021) Phonetic symbol 15(MSB:Phonetic symbol 15, LSB: Consonant adjustment 15) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL15 = 0x5021; + /// + /// (0x5022) Phonetic symbol 16(MSB:Phonetic symbol 16, LSB: Consonant adjustment 16) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL16 = 0x5022; + /// + /// (0x5023) Phonetic symbol 17(MSB:Phonetic symbol 17, LSB: Consonant adjustment 17) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL17 = 0x5023; + /// + /// (0x5024) Phonetic symbol 18(MSB:Phonetic symbol 18, LSB: Consonant adjustment 18) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL18 = 0x5024; + /// + /// (0x5025) Phonetic symbol 19(MSB:Phonetic symbol 19, LSB: Consonant adjustment 19) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL19 = 0x5025; + /// + /// (0x5026) Phonetic symbol 20(MSB:Phonetic symbol 20, LSB: Consonant adjustment 20) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL20 = 0x5026; + /// + /// (0x5027) Phonetic symbol 21(MSB:Phonetic symbol 21, LSB: Consonant adjustment 21) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL21 = 0x5027; + /// + /// (0x5028) Phonetic symbol 22(MSB:Phonetic symbol 22, LSB: Consonant adjustment 22) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL22 = 0x5028; + /// + /// (0x5029) Phonetic symbol 23(MSB:Phonetic symbol 23, LSB: Consonant adjustment 23) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL23 = 0x5029; + /// + /// (0x502a) Phonetic symbol 24(MSB:Phonetic symbol 24, LSB: Consonant adjustment 24) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL24 = 0x502a; + /// + /// (0x502b) Phonetic symbol 25(MSB:Phonetic symbol 25, LSB: Consonant adjustment 25) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL25 = 0x502b; + /// + /// (0x502c) Phonetic symbol 26(MSB:Phonetic symbol 26, LSB: Consonant adjustment 26) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL26 = 0x502c; + /// + /// (0x502d) Phonetic symbol 27(MSB:Phonetic symbol 27, LSB: Consonant adjustment 27) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL27 = 0x502d; + /// + /// (0x502e) Phonetic symbol 28(MSB:Phonetic symbol 28, LSB: Consonant adjustment 28) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL28 = 0x502e; + /// + /// (0x502f) Phonetic symbol 29(MSB:Phonetic symbol 29, LSB: Consonant adjustment 29) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL29 = 0x502f; + /// + /// (0x5030) Phonetic symbol 30(MSB:Phonetic symbol 30, LSB: Consonant adjustment 30) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL30 = 0x5030; + /// + /// (0x5031) Phonetic symbol 31(MSB:Phonetic symbol 31, LSB: Consonant adjustment 31) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL31 = 0x5031; + /// + /// (0x5032) Phonetic symbol 32(MSB:Phonetic symbol 32, LSB: Consonant adjustment 32) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL32 = 0x5032; + /// + /// (0x5033) Phonetic symbol 33(MSB:Phonetic symbol 33, LSB: Consonant adjustment 33) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL33 = 0x5033; + /// + /// (0x5034) Phonetic symbol 34(MSB:Phonetic symbol 34, LSB: Consonant adjustment 34) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL34 = 0x5034; + /// + /// (0x5035) Phonetic symbol 35(MSB:Phonetic symbol 35, LSB: Consonant adjustment 35) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL35 = 0x5035; + /// + /// (0x5036) Phonetic symbol 36(MSB:Phonetic symbol 36, LSB: Consonant adjustment 36) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL36 = 0x5036; + /// + /// (0x5037) Phonetic symbol 37(MSB:Phonetic symbol 37, LSB: Consonant adjustment 37) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL37 = 0x5037; + /// + /// (0x5038) Phonetic symbol 38(MSB:Phonetic symbol 38, LSB: Consonant adjustment 38) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL38 = 0x5038; + /// + /// (0x5039) Phonetic symbol 39(MSB:Phonetic symbol 39, LSB: Consonant adjustment 39) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL39 = 0x5039; + /// + /// (0x503a) Phonetic symbol 40(MSB:Phonetic symbol 40, LSB: Consonant adjustment 40) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL40 = 0x503a; + /// + /// (0x503b) Phonetic symbol 41(MSB:Phonetic symbol 41, LSB: Consonant adjustment 41) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL41 = 0x503b; + /// + /// (0x503c) Phonetic symbol 42(MSB:Phonetic symbol 42, LSB: Consonant adjustment 42) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL42 = 0x503c; + /// + /// (0x503d) Phonetic symbol 43(MSB:Phonetic symbol 43, LSB: Consonant adjustment 43) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL43 = 0x503d; + /// + /// (0x503e) Phonetic symbol 44(MSB:Phonetic symbol 44, LSB: Consonant adjustment 44) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL44 = 0x503e; + /// + /// (0x503f) Phonetic symbol 45(MSB:Phonetic symbol 45, LSB: Consonant adjustment 45) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL45 = 0x503f; + /// + /// (0x5040) Phonetic symbol 46(MSB:Phonetic symbol 46, LSB: Consonant adjustment 46) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL46 = 0x5040; + /// + /// (0x5041) Phonetic symbol 47(MSB:Phonetic symbol 47, LSB: Consonant adjustment 47) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL47 = 0x5041; + /// + /// (0x5042) Phonetic symbol 48(MSB:Phonetic symbol 48, LSB: Consonant adjustment 48) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL48 = 0x5042; + /// + /// (0x5043) Phonetic symbol 49(MSB:Phonetic symbol 49, LSB: Consonant adjustment 49) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL49 = 0x5043; + /// + /// (0x5044) Phonetic symbol 50(MSB:Phonetic symbol 50, LSB: Consonant adjustment 50) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL50 = 0x5044; + /// + /// (0x5045) Phonetic symbol 51(MSB:Phonetic symbol 51, LSB: Consonant adjustment 51) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL51 = 0x5045; + /// + /// (0x5046) Phonetic symbol 52(MSB:Phonetic symbol 52, LSB: Consonant adjustment 52) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL52 = 0x5046; + /// + /// (0x5047) Phonetic symbol 53(MSB:Phonetic symbol 53, LSB: Consonant adjustment 53) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL53 = 0x5047; + /// + /// (0x5048) Phonetic symbol 54(MSB:Phonetic symbol 54, LSB: Consonant adjustment 54) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL54 = 0x5048; + /// + /// (0x5049) Phonetic symbol 55(MSB:Phonetic symbol 55, LSB: Consonant adjustment 55) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL55 = 0x5049; + /// + /// (0x504a) Phonetic symbol 56(MSB:Phonetic symbol 56, LSB: Consonant adjustment 56) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL56 = 0x504a; + /// + /// (0x504b) Phonetic symbol 57(MSB:Phonetic symbol 57, LSB: Consonant adjustment 57) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL57 = 0x504b; + /// + /// (0x504c) Phonetic symbol 58(MSB:Phonetic symbol 58, LSB: Consonant adjustment 58) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL58 = 0x504c; + /// + /// (0x504d) Phonetic symbol 59(MSB:Phonetic symbol 59, LSB: Consonant adjustment 59) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL59 = 0x504d; + /// + /// (0x504e) Phonetic symbol 60(MSB:Phonetic symbol 60, LSB: Consonant adjustment 60) + /// + public const ushort CVM_NM_PHONETIC_SYMBOL60 = 0x504e; /// /// (0x504f) Phonetic symbol continuation(MSB, 0x7f=end, 0x00=continue) /// - CVM_NM_PHONETIC_SYMBOL_CONTINUATION = 0x504f, + public const ushort CVM_NM_PHONETIC_SYMBOL_CONTINUATION = 0x504f; /// /// (0x5050) v1mean in Cent/5(MSB) /// - CVM_NM_V1MEAN = 0x5050, + public const ushort CVM_NM_V1MEAN = 0x5050; /// /// (0x5051) d1mean in millisec/5(MSB) /// - CVM_NM_D1MEAN = 0x5051, + public const ushort CVM_NM_D1MEAN = 0x5051; /// /// (0x5052) d1meanFirstNote in millisec/5(MSB) /// - CVM_NM_D1MEAN_FIRST_NOTE = 0x5052, + public const ushort CVM_NM_D1MEAN_FIRST_NOTE = 0x5052; /// /// (0x5053) d2mean in millisec/5(MSB) /// - CVM_NM_D2MEAN = 0x5053, + public const ushort CVM_NM_D2MEAN = 0x5053; /// /// (0x5054) d4mean in millisec/5(MSB) /// - CVM_NM_D4MEAN = 0x5054, + public const ushort CVM_NM_D4MEAN = 0x5054; /// /// (0x5055) pMeanOnsetFirstNote in Cent/5(MSB) /// - CVM_NM_PMEAN_ONSET_FIRST_NOTE = 0x5055, + public const ushort CVM_NM_PMEAN_ONSET_FIRST_NOTE = 0x5055; /// /// (0x5056) vMeanNoteTransition in Cent/5(MSB) /// - CVM_NM_VMEAN_NOTE_TRNSITION = 0x5056, + public const ushort CVM_NM_VMEAN_NOTE_TRNSITION = 0x5056; /// /// (0x5057) pMeanEndingNote in Cent/5(MSB) /// - CVM_NM_PMEAN_ENDING_NOTE = 0x5057, + public const ushort CVM_NM_PMEAN_ENDING_NOTE = 0x5057; /// /// (0x5058) AddScooptoUpIntervals &, AddPortamentoToDownIntervals(MSB) /// - CVM_NM_ADD_PORTAMENTO = 0x5058, + public const ushort CVM_NM_ADD_PORTAMENTO = 0x5058; /// /// (0x5059) changAfterPeak(MSB) /// - CVM_NM_CHANGE_AFTER_PEAK = 0x5059, + public const ushort CVM_NM_CHANGE_AFTER_PEAK = 0x5059; /// /// (0x505a) Accent(MSB) /// - CVM_NM_ACCENT = 0x505a, + public const ushort CVM_NM_ACCENT = 0x505a; /// - /// (0x597f) Note message continuation(MSB) + /// (0x507f) Note message continuation(MSB) /// - CVM_NM_NOTE_MESSAGE_CONTINUATION = 0x507f, + public const ushort CVM_NM_NOTE_MESSAGE_CONTINUATION = 0x507f; + + /// + /// (0x5075) Extended Note message; Voice Overlap(MSB, LSB)(VoiceOverlap = ((MSB & 0x7f) << 7) | (LSB & 0x7f) - 8192) + /// + public const ushort CVM_EXNM_VOICE_OVERLAP = 0x5075; + /// + /// (0x5076) Extended Note message; Flags length in bytes(MSB, LSB) + /// + public const ushort CVM_EXNM_FLAGS_BYTES = 0x5076; + /// + /// (0x5077) Extended Note message; Flag(MSB) + /// + public const ushort CVM_EXNM_FLAGS = 0x5077; + /// + /// (0x5078) Extended Note message; Flag continuation(MSB)(MSB, 0x7f=end, 0x00=continue) + /// + public const ushort CVM_EXNM_FLAGS_CONINUATION = 0x5078; + /// + /// (0x5079) Extended Note message; Moduration(MSB, LSB)(Moduration = ((MSB & 0x7f) << 7) | (LSB & 0x7f) - 100) + /// + public const ushort CVM_EXNM_MODURATION = 0x5079; + /// + /// (0x507a) Extended Note message; PreUtterance(MSB, LSB)(PreUtterance = ((MSB & 0x7f) << 7) | (LSB & 0x7f) - 8192) + /// + public const ushort CVM_EXNM_PRE_UTTERANCE = 0x507a; + /// + /// (0x507e) Extended Note message; Envelope: value1(MSB, LSB) actual value = (value3.msb & 0xf) << 28 | (value2.msb & 0x7f) << 21 | (value2.lsb & 0x7f) << 14 | (value1.msb & 0x7f) << 7 | (value1.lsb & 0x7f) + /// + public const ushort CVM_EXNM_ENV_DATA1 = 0x507e; + /// + /// (0x507d) Extended Note message; Envelope: value2(MSB, LSB) + /// + public const ushort CVM_EXNM_ENV_DATA2 = 0x507d; + /// + /// (0x507c) Extended Note message; Envelope: value3(MSB) + /// + public const ushort CVM_EXNM_ENV_DATA3 = 0x507c; + /// + /// (0x507b) Extended Note message; Envelope: data point continuation(MSB)(MSB, 0x7f=end, 0x00=continue) + /// + public const ushort CVM_EXNM_ENV_DATA_CONTINUATION = 0x507b; /// /// (0x6000) Version number &, Device number(MSB, LSB) /// - CC_BS_VERSION_AND_DEVICE = 0x6000, + public const ushort CC_BS_VERSION_AND_DEVICE = 0x6000; /// /// (0x6001) Delay in millisec(MSB, LSB) /// - CC_BS_DELAY = 0x6001, + public const ushort CC_BS_DELAY = 0x6001; /// /// (0x6002) Laugnage type(MSB, optional LSB) /// - CC_BS_LANGUAGE_TYPE = 0x6002, + public const ushort CC_BS_LANGUAGE_TYPE = 0x6002; /// /// (0x6100) Version number &, device number(MSB, LSB) /// - CC_CV_VERSION_AND_DEVICE = 0x6100, + public const ushort CC_CV_VERSION_AND_DEVICE = 0x6100; /// /// (0x6101) Delay in millisec(MSB, LSB) /// - CC_CV_DELAY = 0x6101, + public const ushort CC_CV_DELAY = 0x6101; /// /// (0x6102) Volume value(MSB) /// - CC_CV_VOLUME = 0x6102, + public const ushort CC_CV_VOLUME = 0x6102; /// /// (0x6200) Version number &, device number(MSB, LSB) /// - CC_P_VERSION_AND_DEVICE = 0x6200, + public const ushort CC_P_VERSION_AND_DEVICE = 0x6200; /// /// (0x6201) Delay in millisec(MSB, LSB) /// - CC_P_DELAY = 0x6201, + public const ushort CC_P_DELAY = 0x6201; /// /// (0x6202) Pan value(MSB) /// - CC_PAN = 0x6202, + public const ushort CC_PAN = 0x6202; /// /// (0x6300) Version number &, device number(MSB, LSB) /// - CC_E_VESION_AND_DEVICE = 0x6300, + public const ushort CC_E_VESION_AND_DEVICE = 0x6300; /// /// (0x6301) Delay in millisec(MSB, LSB) /// - CC_E_DELAY = 0x6301, + public const ushort CC_E_DELAY = 0x6301; /// /// (0x6302) Expression vlaue(MSB) /// - CC_E_EXPRESSION = 0x6302, + public const ushort CC_E_EXPRESSION = 0x6302; /// /// (0x6400) Version number &, device number(MSB, LSB) /// - CC_VR_VERSION_AND_DEVICE = 0x6400, + public const ushort CC_VR_VERSION_AND_DEVICE = 0x6400; /// /// (0x6401) Delay in millisec(MSB, LSB) /// - CC_VR_DELAY = 0x6401, + public const ushort CC_VR_DELAY = 0x6401; /// /// (0x6402) Vibrato Rate value(MSB) /// - CC_VR_VIBRATO_RATE = 0x6402, + public const ushort CC_VR_VIBRATO_RATE = 0x6402; /// /// (0x6500) Version number &, device number(MSB, LSB) /// - CC_VD_VERSION_AND_DEVICE = 0x6500, + public const ushort CC_VD_VERSION_AND_DEVICE = 0x6500; /// /// (0x6501) Delay in millisec(MSB, LSB) /// - CC_VD_DELAY = 0x6501, + public const ushort CC_VD_DELAY = 0x6501; /// /// (0x6502) Vibrato Depth value(MSB) /// - CC_VD_VIBRATO_DEPTH = 0x6502, + public const ushort CC_VD_VIBRATO_DEPTH = 0x6502; + + /// + /// (0x6600) Version number &, device number(MSB, LSB) + /// + public const ushort CC_FX2_VERSION_AND_DEVICE = 0x6600; + /// + /// (0x6601) Delay in millisec(MSB, LSB) + /// + public const ushort CC_FX2_DELAY = 0x6601; + /// + /// (0x6602) Effect2 Depth(MSB) + /// + public const ushort CC_FX2_EFFECT2_DEPTH = 0x6602; /// /// (0x6700) Version number &, device number(MSB, LSB) /// - CC_PBS_VERSION_AND_DEVICE = 0x6700, + public const ushort CC_PBS_VERSION_AND_DEVICE = 0x6700; /// /// (0x6701) Delay in millisec(MSB, LSB) /// - CC_PBS_DELAY = 0x6701, + public const ushort CC_PBS_DELAY = 0x6701; /// /// (0x6702) Pitch Bend Sensitivity(MSB, LSB) /// - CC_PBS_PITCH_BEND_SENSITIVITY = 0x6702, + public const ushort CC_PBS_PITCH_BEND_SENSITIVITY = 0x6702; /// /// (0x5300) Version number &, device number(MSB, LSB) /// - PC_VERSION_AND_DEVICE = 0x5300, + public const ushort PC_VERSION_AND_DEVICE = 0x5300; /// /// (0x5301) Delay in millisec(MSB, LSB) /// - PC_DELAY = 0x5301, + public const ushort PC_DELAY = 0x5301; /// /// (0x5302) Voice Type(MSB) /// - PC_VOICE_TYPE = 0x5302, + public const ushort PC_VOICE_TYPE = 0x5302; /// /// (0x5400) Version number &, device number(MSB, LSB) /// - PB_VERSION_AND_DEVICE = 0x5400, + public const ushort PB_VERSION_AND_DEVICE = 0x5400; /// /// (0x5401) Delay in millisec(MSB, LSB) /// - PB_DELAY = 0x5401, + public const ushort PB_DELAY = 0x5401; /// /// (0x5402) Pitch Bend value(MSB, LSB) /// - PB_PITCH_BEND = 0x5402, + public const ushort PB_PITCH_BEND = 0x5402; /// /// (0x5500) Version number &, device number(MSB, LSB) /// - VCP_VERSION_AND_DEVICE = 0x5500, + public const ushort VCP_VERSION_AND_DEVICE = 0x5500; /// /// (0x5501) Delay in millisec(MSB, LSB) /// - VCP_DELAY = 0x5501, + public const ushort VCP_DELAY = 0x5501; /// /// (0x5502) Voice Change Parameter ID(MSB) /// - VCP_VOICE_CHANGE_PARAMETER_ID = 0x5502, + public const ushort VCP_VOICE_CHANGE_PARAMETER_ID = 0x5502; /// /// (0x5503) Voice Change Parameter value(MSB) /// - VCP_VOICE_CHANGE_PARAMETER = 0x5503, + public const ushort VCP_VOICE_CHANGE_PARAMETER = 0x5503; + + private class NrpnIterator : Iterator { + private List nrpns = new List(); + private int m_pos = -1; + + public NrpnIterator() { + Type t = typeof( NRPN ); + foreach ( FieldInfo fi in t.GetFields() ) { + if ( fi.FieldType.Equals( typeof( ushort ) ) ) { + nrpns.Add( (ushort)fi.GetValue( t ) ); + } + } + } + + public bool hasNext() { + if ( 0 <= m_pos + 1 && m_pos + 1 < nrpns.Count ) { + return true; + } else { + return false; + } + } + + public Object next() { + m_pos++; + return nrpns[m_pos]; + } + + public void remove() { + } + } + + public static Iterator iterator() { + return new NrpnIterator(); + } + + public static string getName( ushort nrpn ) { + foreach ( FieldInfo fi in typeof( NRPN ).GetFields() ) { + if ( fi.FieldType.Equals( typeof( ushort ) ) ) { + ushort v = (ushort)fi.GetValue( typeof( NRPN ) ); + if ( v == nrpn ) { + return fi.Name; + } + } + } + return ""; + } + + /// + /// 指定したコントロールに対応するVoice Change Parameter IDの値を調べます + /// + /// + /// + public static byte getVoiceChangeParameterID( string curve_name ) { + byte lsb = 0x31; + switch ( curve_name.ToLower() ) { + case "harmonics": + lsb = 0x30; + break; + case "bre": + lsb = 0x31; + break; + case "bri": + lsb = 0x32; + break; + case "cle": + lsb = 0x33; + break; + case "por": + lsb = 0x34; + break; + case "ope": + lsb = 0x35; + break; + case "reso1freq": + lsb = 0x40; + break; + case "reso2freq": + lsb = 0x41; + break; + case "reso3freq": + lsb = 0x42; + break; + case "reso4freq": + lsb = 0x43; + break; + case "reso1bw": + lsb = 0x50; + break; + case "reso2bw": + lsb = 0x51; + break; + case "reso3bw": + lsb = 0x52; + break; + case "reso4bw": + lsb = 0x53; + break; + case "reso1amp": + lsb = 0x60; + break; + case "reso2amp": + lsb = 0x61; + break; + case "reso3amp": + lsb = 0x62; + break; + case "reso4amp": + lsb = 0x63; + break; + case "gen": + lsb = 0x70; + break; + } + return lsb; + } + + public static bool is_require_data_lsb( ushort nrpn ) { + switch ( nrpn ) { + case CVM_NM_VERSION_AND_DEVICE: + case CVM_NM_DELAY: + case CVM_NM_NOTE_DURATION: + case CVM_NM_INDEX_OF_VIBRATO_DB: + case CVM_NM_VIBRATO_CONFIG: + case CVM_NM_PHONETIC_SYMBOL1: + case CC_BS_VERSION_AND_DEVICE: + case CC_BS_DELAY: + case CC_BS_LANGUAGE_TYPE: + case CC_CV_VERSION_AND_DEVICE: + case CC_CV_DELAY: + case CC_P_VERSION_AND_DEVICE: + case CC_P_DELAY: + case CC_E_VESION_AND_DEVICE: + case CC_E_DELAY: + case CC_VR_VERSION_AND_DEVICE: + case CC_VR_DELAY: + case CC_VD_VERSION_AND_DEVICE: + case CC_VD_DELAY: + case CC_FX2_VERSION_AND_DEVICE: + case CC_FX2_DELAY: + case CC_PBS_VERSION_AND_DEVICE: + case CC_PBS_DELAY: + case CC_PBS_PITCH_BEND_SENSITIVITY: + case PC_VERSION_AND_DEVICE: + case PC_DELAY: + case PB_VERSION_AND_DEVICE: + case PB_DELAY: + case PB_PITCH_BEND: + case VCP_VERSION_AND_DEVICE: + case VCP_DELAY: + case CVM_EXNM_ENV_DATA1: + case CVM_EXNM_ENV_DATA2: + return true; + case CVM_NM_NOTE_NUMBER: + case CVM_NM_VELOCITY: + case CVM_NM_NOTE_LOCATION: + case CVM_NM_VIBRATO_DELAY: + //case CVM_NM_UNKNOWN1: + case CVM_NM_PHONETIC_SYMBOL_BYTES: + case CVM_NM_PHONETIC_SYMBOL_CONTINUATION: + case CVM_NM_V1MEAN: + case CVM_NM_D1MEAN: + case CVM_NM_D1MEAN_FIRST_NOTE: + case CVM_NM_D2MEAN: + case CVM_NM_D4MEAN: + case CVM_NM_PMEAN_ONSET_FIRST_NOTE: + case CVM_NM_VMEAN_NOTE_TRNSITION: + case CVM_NM_PMEAN_ENDING_NOTE: + case CVM_NM_ADD_PORTAMENTO: + case CVM_NM_CHANGE_AFTER_PEAK: + case CVM_NM_ACCENT: + case CVM_NM_NOTE_MESSAGE_CONTINUATION: + case CC_CV_VOLUME: + case CC_PAN: + case CC_E_EXPRESSION: + case CC_VR_VIBRATO_RATE: + case CC_VD_VIBRATO_DEPTH: + case CC_FX2_EFFECT2_DEPTH: + case PC_VOICE_TYPE: + case VCP_VOICE_CHANGE_PARAMETER_ID: + case VCP_VOICE_CHANGE_PARAMETER: + case CVM_EXNM_ENV_DATA3: + case CVM_EXNM_ENV_DATA_CONTINUATION: + return false; + } + return false; + } + } } diff --git a/trunk/Boare.Lib.Vsq/SMF/MidiFile.cs b/trunk/Boare.Lib.Vsq/SMF/MidiFile.cs index 987e6c2..aa7e39a 100644 --- a/trunk/Boare.Lib.Vsq/SMF/MidiFile.cs +++ b/trunk/Boare.Lib.Vsq/SMF/MidiFile.cs @@ -61,7 +61,11 @@ namespace Boare.Lib.Vsq { private static long readDeltaClock( Stream stream ) { long ret = 0; while ( true ) { - byte d = (byte)stream.ReadByte(); + int i = stream.ReadByte(); + if ( i < 0 ) { + break; + } + byte d = (byte)i; ret = (ret << 7) | ((long)d & 0x7f); if ( (d & 0x80) == 0x00 ) { break; @@ -203,11 +207,8 @@ namespace Boare.Lib.Vsq { private ushort m_format; private ushort m_time_format; - public MidiFile( string path ) - : this( new FileStream( path, FileMode.Open ) ) { - } - - public MidiFile( Stream stream ) { + public MidiFile( string path ){ + Stream stream = new FileStream( path, FileMode.Open, FileAccess.Read ); // ヘッダ byte[] byte4 = new byte[4]; stream.Read( byte4, 0, 4 ); @@ -251,9 +252,66 @@ namespace Boare.Lib.Vsq { long clock = 0; byte last_status_byte = 0x00; while ( stream.Position < startpos + size ) { - m_events[track].Add( MidiEvent.read( stream, ref clock, ref last_status_byte ) ); + MidiEvent mi = MidiEvent.read( stream, ref clock, ref last_status_byte ); + m_events[track].Add( mi ); + } + if ( m_time_format != 480 ) { + int count = m_events[track].Count; + for ( int i = 0; i < count; i++ ) { + MidiEvent mi = m_events[track][i]; + mi.Clock = mi.Clock * 480 / m_time_format; + m_events[track][i] = mi; + } } } + m_time_format = 480; +#if DEBUG + string dbg = Path.Combine( Path.GetDirectoryName( path ), Path.GetFileNameWithoutExtension( path ) + ".txt" ); + using ( StreamWriter sw = new StreamWriter( dbg ) ) { + const string format = " {0,8} 0x{1:X4} {2,-35} 0x{3:X2} 0x{4:X2}"; + const string format0 = " {0,8} 0x{1:X4} {2,-35} 0x{3:X2}"; + for ( int track = 1; track < m_events.Count; track++ ) { + sw.WriteLine( "MidiFile..ctor; track=" + track ); + byte msb, lsb, data_msb, data_lsb; + msb = lsb = data_msb = data_lsb = 0x0; + for ( int i = 0; i < m_events[track].Count; i++ ) { + if ( m_events[track][i].FirstByte == 0xb0 ) { + switch ( m_events[track][i].Data[0] ) { + case 0x63: + msb = m_events[track][i].Data[1]; + lsb = 0x0; + break; + case 0x62: + lsb = m_events[track][i].Data[1]; + break; + case 0x06: + data_msb = m_events[track][i].Data[1]; + ushort nrpn = (ushort)(msb << 8 | lsb); + string name = NRPN.getName( nrpn ); + if ( name == "" ) { + name = "* * UNKNOWN * *"; + sw.WriteLine( string.Format( format0, m_events[track][i].Clock, nrpn, name, data_msb ) ); + } else { + //if ( !NRPN.is_require_data_lsb( nrpn ) ) { + sw.WriteLine( string.Format( format0, m_events[track][i].Clock, nrpn, name, data_msb ) ); + //} + } + break; + case 0x26: + data_lsb = m_events[track][i].Data[1]; + ushort nrpn2 = (ushort)(msb << 8 | lsb); + string name2 = NRPN.getName( nrpn2 ); + if ( name2 == "" ) { + name2 = "* * UNKNOWN * *"; + } + sw.WriteLine( string.Format( format, m_events[track][i].Clock, nrpn2, name2, data_msb, data_lsb ) ); + break; + } + } + } + } + } +#endif stream.Close(); } diff --git a/trunk/Boare.Lib.Vsq/SingerConfig.cs b/trunk/Boare.Lib.Vsq/SingerConfig.cs index 06f9d65..4c5700b 100644 --- a/trunk/Boare.Lib.Vsq/SingerConfig.cs +++ b/trunk/Boare.Lib.Vsq/SingerConfig.cs @@ -17,17 +17,37 @@ using System.Collections.Generic; namespace Boare.Lib.Vsq { - public class SingerConfig { - public string ID; - public string FORMAT; - public string VOICEIDSTR; - public string VOICENAME; + public class SingerConfig : ICloneable { + public string ID = ""; + public string FORMAT = ""; + public string VOICEIDSTR = ""; + public string VOICENAME = "Unknown"; public int Breathiness; public int Brightness; public int Clearness; public int Opening; public int GenderFactor; public int Original; + public int Program; + + public SingerConfig() { + } + + public object Clone() { + SingerConfig ret = new SingerConfig(); + ret.ID = ID; + ret.FORMAT = FORMAT; + ret.VOICEIDSTR = VOICEIDSTR; + ret.VOICENAME = VOICENAME; + ret.Breathiness = Breathiness; + ret.Brightness = Brightness; + ret.Clearness = Clearness; + ret.Opening = Opening; + ret.GenderFactor = GenderFactor; + ret.Original = Original; + ret.Program = Program; + return ret; + } public static void decode_vvd_bytes( ref byte[] dat ) { for ( int i = 0; i < dat.Length; i++ ) { @@ -115,18 +135,19 @@ namespace Boare.Lib.Vsq { return 0x0; } - public SingerConfig( string file, int original ) { - original = original; - ID = "VOCALOID:VIRTUAL:VOICE"; - FORMAT = "2.0.0.0"; - VOICEIDSTR = ""; - VOICENAME = "Miku"; - Breathiness = 0; - Brightness = 0; - Clearness = 0; - Opening = 0; - GenderFactor = 0; - original = 0; + public static SingerConfig readSingerConfig( string file, int original ) { + SingerConfig sc = new SingerConfig(); + //original = original; + sc.ID = "VOCALOID:VIRTUAL:VOICE"; + sc.FORMAT = "2.0.0.0"; + sc.VOICEIDSTR = ""; + sc.VOICENAME = "Miku"; + sc.Breathiness = 0; + sc.Brightness = 0; + sc.Clearness = 0; + sc.Opening = 0; + sc.GenderFactor = 0; + sc.Original = original; //original = 0; FileStream fs = null; try { fs = new FileStream( file, FileMode.Open, FileAccess.Read ); @@ -156,36 +177,36 @@ namespace Boare.Lib.Vsq { value = value.Substring( 1, value.Length - 2 ); value = value.Replace( "\\\"", "\"" ); if ( id == "ID" ) { - ID = value; + sc.ID = value; } else if ( id == "FORMAT" ) { - FORMAT = value; + sc.FORMAT = value; } else if ( id == "VOICEIDSTR" ) { - VOICEIDSTR = value; + sc.VOICEIDSTR = value; } else if ( id == "VOICENAME" ) { - VOICENAME = value; + sc.VOICENAME = value; } else if ( id == "Breathiness" ) { try { - Breathiness = int.Parse( value ); + sc.Breathiness = int.Parse( value ); } catch { } } else if ( id == "Brightness" ) { try { - Brightness = int.Parse( value ); + sc.Brightness = int.Parse( value ); } catch { } } else if ( id == "Clearness" ) { try { - Clearness = int.Parse( value ); + sc.Clearness = int.Parse( value ); } catch { } } else if ( id == "Opening" ) { try { - Opening = int.Parse( value ); + sc.Opening = int.Parse( value ); } catch { } } else if ( id == "Gender:Factor" ) { try { - GenderFactor = int.Parse( value ); + sc.GenderFactor = int.Parse( value ); } catch { } } @@ -197,6 +218,7 @@ namespace Boare.Lib.Vsq { fs.Close(); } } + return sc; } /// @@ -226,7 +248,7 @@ namespace Boare.Lib.Vsq { return end; } - public new string[] ToString() { + public string[] ToStringArray() { List ret = new List(); ret.Add( "\"ID\":=:\"" + ID + "\"" ); ret.Add( "\"FORMAT\":=:\"" + FORMAT + "\"" ); @@ -239,6 +261,15 @@ namespace Boare.Lib.Vsq { ret.Add( "\"Gender:Factor\":=:\"" + GenderFactor + "\"" ); return ret.ToArray(); } + + public override string ToString() { + string[] r = ToStringArray(); + string ret = ""; + foreach ( string s in r ) { + ret += s + "\n"; + } + return ret; + } } } diff --git a/trunk/Boare.Lib.Vsq/SymbolTable.cs b/trunk/Boare.Lib.Vsq/SymbolTable.cs index 2f31c87..ce3f07a 100644 --- a/trunk/Boare.Lib.Vsq/SymbolTable.cs +++ b/trunk/Boare.Lib.Vsq/SymbolTable.cs @@ -480,7 +480,7 @@ namespace Boare.Lib.Vsq { int count = 0; // 辞書フォルダからの読込み - string editor_path = VsqUtil.getEditorPath(); + string editor_path = VocaloSysUtil.getEditorPath2(); if ( editor_path.Length > 0 ) { string path = Path.Combine( Path.GetDirectoryName( editor_path ), "UDIC" ); if ( !Directory.Exists( path ) ) { diff --git a/trunk/Boare.Lib.Vsq/TempoTableEntry.cs b/trunk/Boare.Lib.Vsq/TempoTableEntry.cs index 005c52d..cbc8b57 100644 --- a/trunk/Boare.Lib.Vsq/TempoTableEntry.cs +++ b/trunk/Boare.Lib.Vsq/TempoTableEntry.cs @@ -16,6 +16,133 @@ using System.Collections.Generic; namespace Boare.Lib.Vsq { + public class TempoTable : ICloneable { + private struct TempoTableEntry : IComparable { + public int Clock; + public int Tempo; + public double Time; + + public TempoTableEntry( int clock, int tempo, double time ) { + Clock = clock; + Tempo = tempo; + Time = time; + } + + public int CompareTo( TempoTableEntry item ) { + return Clock - item.Clock; + } + } + + private List m_tempo_table; + private int m_base_tempo; + private int m_tpq; + + private TempoTable() { + } + + public TempoTable( int base_tempo, int clock_per_quoter ) { + m_base_tempo = base_tempo; + m_tpq = clock_per_quoter; + m_tempo_table = new List(); + m_tempo_table.Add( new TempoTableEntry( 0, base_tempo, 0.0 ) ); + } + + public object Clone() { + TempoTable ret = new TempoTable(); + ret.m_base_tempo = m_base_tempo; + ret.m_tpq = m_tpq; + ret.m_tempo_table = new List(); + for ( int i = 0; i < m_tempo_table.Count; i++ ) { + ret.m_tempo_table.Add( m_tempo_table[i] ); + } + ret.update(); + return ret; + } + + public void add( int clock, int tempo ) { + bool found = false; + for ( int i = 0; i < m_tempo_table.Count; i++ ) { + if ( m_tempo_table[i].Clock == clock ) { + found = true; + m_tempo_table[i] = new TempoTableEntry( clock, tempo, 0.0 ); + break; + } + } + if ( !found ) { + m_tempo_table.Add( new TempoTableEntry( clock, tempo, 0.0 ) ); + } + m_tempo_table.Sort(); + update(); + } + + public void clear( int base_tempo ) { + m_tempo_table.Clear(); + m_tempo_table.Add( new TempoTableEntry( 0, base_tempo, 0.0 ) ); + } + + private void update() { + for ( int i = 0; i < m_tempo_table.Count; i++ ) { + long sum = 0; + for ( int k = 0; k < i; k++ ) { + sum += (m_tempo_table[k].Tempo * (m_tempo_table[k + 1].Clock - m_tempo_table[k].Clock)); + } + double time = sum / (m_tpq * 1e6); + m_tempo_table[i] = new TempoTableEntry( m_tempo_table[i].Clock, m_tempo_table[i].Tempo, time ); + } + } + + /// + /// 指定した時刻における、クロックを取得します + /// + /// + /// + public double getClockFromSec( double time ) { + // timeにおけるテンポを取得 + int tempo = m_base_tempo; + double base_clock = 0; + double base_time = 0f; + if ( m_tempo_table.Count == 0 ) { + tempo = m_base_tempo; + base_clock = 0; + base_time = 0f; + } else if ( m_tempo_table.Count == 1 ) { + tempo = m_tempo_table[0].Tempo; + base_clock = m_tempo_table[0].Clock; + base_time = m_tempo_table[0].Time; + } else { + for ( int i = m_tempo_table.Count - 1; i >= 0; i-- ) { + if ( m_tempo_table[i].Time < time ) { + return m_tempo_table[i].Clock + (time - m_tempo_table[i].Time) * m_tpq * 1000000.0 / m_tempo_table[i].Tempo; + } + } + } + double dt = time - base_time; + return base_clock + dt * m_tpq * 1000000.0 / (double)tempo; + } + + /// + /// 指定したクロックにおける、clock=0からの演奏経過時間(sec)を取得します + /// + /// + /// + public double getSecFromClock( int clock ) { + for ( int i = m_tempo_table.Count - 1; i >= 0; i-- ) { + if ( m_tempo_table[i].Clock < clock ) { + double init = m_tempo_table[i].Time; + int dclock = clock - m_tempo_table[i].Clock; + double sec_per_clock1 = m_tempo_table[i].Tempo * 1e-6 / 480.0; + return init + dclock * sec_per_clock1; + } + } + double sec_per_clock = m_base_tempo * 1e-6 / 480.0; + return clock * sec_per_clock; + } + + public int getBaseTempo() { + return m_base_tempo; + } + } + [Serializable] public class TempoTableEntry : IComparable, ICloneable { public int Clock; @@ -32,6 +159,9 @@ namespace Boare.Lib.Vsq { this.Time = _time; } + public TempoTableEntry() { + } + public int CompareTo( TempoTableEntry entry ) { return this.Clock - entry.Clock; } diff --git a/trunk/Boare.Lib.Vsq/TimeSigTableEntry.cs b/trunk/Boare.Lib.Vsq/TimeSigTableEntry.cs index 7b4c8e1..5140ab3 100644 --- a/trunk/Boare.Lib.Vsq/TimeSigTableEntry.cs +++ b/trunk/Boare.Lib.Vsq/TimeSigTableEntry.cs @@ -45,6 +45,9 @@ namespace Boare.Lib.Vsq{ BarCount = bar_count; } + public TimeSigTableEntry() { + } + public override string ToString() { return "{Clock=" + Clock + ", Numerator=" + Numerator + ", Denominator=" + Denominator + ", BarCount=" + BarCount + "}"; } diff --git a/trunk/Boare.Lib.Vsq/UstEvent.cs b/trunk/Boare.Lib.Vsq/UstEvent.cs index 7fe1804..612322c 100644 --- a/trunk/Boare.Lib.Vsq/UstEvent.cs +++ b/trunk/Boare.Lib.Vsq/UstEvent.cs @@ -18,8 +18,9 @@ using System.Text; namespace Boare.Lib.Vsq { + [Serializable] public class UstEvent : ICloneable { - public object Tag; + public string Tag; public int Length = 0; public string Lyric = ""; public int Note = -1; @@ -27,6 +28,16 @@ namespace Boare.Lib.Vsq { public int PBType = -1; public float[] Pitches = null; public float Tempo = -1; + public UstVibrato Vibrato = null; + public UstPortamento Portamento = null; + public int PreUtterance = 0; + public int VoiceOverlap = 0; + public UstEnvelope Envelope = null; + public string Flags = ""; + public int Moduration = 100; + + public UstEvent(){ + } public object Clone() { UstEvent ret = new UstEvent(); @@ -42,6 +53,20 @@ namespace Boare.Lib.Vsq { } } ret.Tempo = Tempo; + if ( Vibrato != null ) { + ret.Vibrato = (UstVibrato)Vibrato.Clone(); + } + if ( Portamento != null ) { + ret.Portamento = (UstPortamento)Portamento.Clone(); + } + if ( Envelope != null ) { + ret.Envelope = (UstEnvelope)Envelope.Clone(); + } + ret.PreUtterance = PreUtterance; + ret.VoiceOverlap = VoiceOverlap; + ret.Flags = Flags; + ret.Moduration = Moduration; + ret.Tag = Tag; return ret; } @@ -68,6 +93,27 @@ namespace Boare.Lib.Vsq { if ( Tempo > 0 ) { sw.WriteLine( "Tempo=" + Tempo ); } + if ( Vibrato != null ) { + sw.WriteLine( Vibrato.ToString() ); + } + if ( Portamento != null ) { + Portamento.print( sw ); + } + if ( Envelope != null ) { + if ( PreUtterance >= 0 ) { + sw.WriteLine( "PreUtterance=" + PreUtterance ); + } + if ( VoiceOverlap != 0 ) { + sw.WriteLine( "VoiceOverlap=" + VoiceOverlap ); + } + sw.WriteLine( Envelope.ToString() ); + } + if ( Flags != "" ) { + sw.WriteLine( "Flags=" + Flags ); + } + if ( Moduration >= 0 ) { + sw.WriteLine( "Moduration=" + Moduration ); + } } } diff --git a/trunk/Boare.Lib.Vsq/UstFile.cs b/trunk/Boare.Lib.Vsq/UstFile.cs index 2f43177..db75cd6 100644 --- a/trunk/Boare.Lib.Vsq/UstFile.cs +++ b/trunk/Boare.Lib.Vsq/UstFile.cs @@ -22,7 +22,7 @@ namespace Boare.Lib.Vsq{ public class UstFile : ICloneable { public object Tag; - private float m_tempo = 125.00f; + private float m_tempo = 120.00f; private string m_project_name = ""; private string m_voice_dir = ""; private string m_out_file = ""; @@ -115,6 +115,33 @@ namespace Boare.Lib.Vsq{ if ( float.TryParse( spl[1], out v ) ){ ue.Tempo = v; } + } else if ( spl[0] == "VBR" ) { + ue.Vibrato = new UstVibrato( line ); + /* + PBW=50,50,46,48,56,50,50,50,50 + PBS=-87 + PBY=-15.9,-20,-31.5,-26.6 + PBM=,s,r,j,s,s,s,s,s + */ + } else if ( spl[0] == "PBW" || spl[0] == "PBS" || spl[0] == "PBY" || spl[0] == "PBM" ) { + if ( ue.Portamento == null ) { + ue.Portamento = new UstPortamento(); + } + ue.Portamento.ParseLine( line ); + } else if ( spl[0] == "Envelope" ) { + ue.Envelope = new UstEnvelope( line ); + //PreUtterance=1 + //VoiceOverlap=6 + } else if ( spl[0] == "VoiceOverlap" ) { + if ( spl[1] != "" ) { + ue.VoiceOverlap = int.Parse( spl[1] ); + } + } else if ( spl[0] == "PreUtterance" ) { + if ( spl[1] != "" ) { + ue.PreUtterance = int.Parse( spl[1] ); + } + } else if ( spl[0] == "Flags" ) { + ue.Flags = line.Substring( 6 ); } } line = sr.ReadLine(); diff --git a/trunk/Boare.Lib.Vsq/VibratoBPList.cs b/trunk/Boare.Lib.Vsq/VibratoBPList.cs index 754214b..2264746 100644 --- a/trunk/Boare.Lib.Vsq/VibratoBPList.cs +++ b/trunk/Boare.Lib.Vsq/VibratoBPList.cs @@ -16,6 +16,7 @@ using System.Collections.Generic; namespace Boare.Lib.Vsq { + [Serializable] public class VibratoBPList : ICloneable { private List m_list; @@ -38,6 +39,24 @@ namespace Boare.Lib.Vsq { m_list.Sort(); } + public int getValue( float x, int default_value ) { + if ( m_list.Count <= 0 ) { + return default_value; + } + int index = -1; + for ( int i = 0; i < m_list.Count; i++ ) { + if ( x < m_list[i].X ) { + break; + } + index = i; + } + if ( index == -1 ) { + return default_value; + } else { + return m_list[index].Y; + } + } + public object Clone() { VibratoBPList ret = new VibratoBPList(); for ( int i = 0; i < m_list.Count; i++ ) { @@ -57,6 +76,30 @@ namespace Boare.Lib.Vsq { public void setElement( int index, VibratoBPPair value ) { m_list[index] = value; } + + /// + /// XMLシリアライズ用 + /// + public string Data { + get { + string ret = ""; + for ( int i = 0; i < m_list.Count; i++ ) { + ret += (i == 0 ? "" : ",") + m_list[i].X + "=" + m_list[i].Y; + } + return ret; + } + set { + m_list.Clear(); + string[] spl = value.Split( ',' ); + for ( int i = 0; i < spl.Length; i++ ) { + string[] spl2 = spl[i].Split( '=' ); + if ( spl2.Length < 2 ) { + continue; + } + m_list.Add( new VibratoBPPair( float.Parse( spl2[0] ), int.Parse( spl2[1] ) ) ); + } + } + } } } \ No newline at end of file diff --git a/trunk/Boare.Lib.Vsq/VibratoBPPair.cs b/trunk/Boare.Lib.Vsq/VibratoBPPair.cs index daa75b1..8262ee4 100644 --- a/trunk/Boare.Lib.Vsq/VibratoBPPair.cs +++ b/trunk/Boare.Lib.Vsq/VibratoBPPair.cs @@ -15,10 +15,14 @@ using System; namespace Boare.Lib.Vsq { + [Serializable] public class VibratoBPPair : IComparable { public float X; public int Y; + public VibratoBPPair() { + } + public VibratoBPPair( float x, int y ) { X = x; Y = y; diff --git a/trunk/Boare.Lib.Vsq/VsqBPList.cs b/trunk/Boare.Lib.Vsq/VsqBPList.cs index ee1127b..8c45c59 100644 --- a/trunk/Boare.Lib.Vsq/VsqBPList.cs +++ b/trunk/Boare.Lib.Vsq/VsqBPList.cs @@ -24,9 +24,9 @@ namespace Boare.Lib.Vsq { [Serializable] public class VsqBPList : ICloneable { private SortedList m_list = new SortedList(); - private int m_default = 0; - private int m_maximum = 127; - private int m_minimum = 0; + public int Default = 0; + public int Maximum = 127; + public int Minimum = 0; private class KeyClockIterator : Iterator { private SortedList m_list; @@ -58,12 +58,49 @@ namespace Boare.Lib.Vsq { } } + public VsqBPList() + : this( 0, 0, 64 ) { + } + + /// + /// XMLシリアライズ用 + /// + public string Data { + get { + string ret = ""; + int count = -1; + foreach ( int key in m_list.Keys ) { + count++; + ret += (count == 0 ? "" : "," ) + key + "=" + m_list[key]; + } + return ret; + } + set { + m_list.Clear(); + string[] spl = value.Split( ',' ); + for ( int i = 0; i < spl.Length; i++ ) { + string[] spl2 = spl[i].Split( '=' ); + if ( spl2.Length < 2 ) { + continue; + } + try { + m_list.Add( int.Parse( spl2[0] ), int.Parse( spl2[1] ) ); + } catch ( Exception ex ) { +#if DEBUG + Console.WriteLine( " ex=" + ex ); + Console.WriteLine( " i=" + i + "; spl2[0]=" + spl2[0] + "; spl2[1]=" + spl2[1] ); +#endif + } + } + } + } + /// /// このVsqBPListの同一コピーを作成します /// /// public object Clone() { - VsqBPList res = new VsqBPList( m_default, m_minimum, m_maximum ); + VsqBPList res = new VsqBPList( Default, Minimum, Maximum ); foreach ( int key in m_list.Keys ) { res.m_list.Add( key, m_list[key] ); } @@ -75,23 +112,23 @@ namespace Boare.Lib.Vsq { /// /// public VsqBPList( int default_value, int minimum, int maximum ) { - m_default = default_value; - m_maximum = maximum; - m_minimum = minimum; + Default = default_value; + Maximum = maximum; + Minimum = minimum; } /// /// このリストに設定された最大値を取得します。 /// public int getMaximum() { - return m_maximum; + return Maximum; } /// /// このリストに設定された最小値を取得します /// public int getMinimum() { - return m_minimum; + return Minimum; } public Iterator keyClockIterator() { @@ -113,7 +150,10 @@ namespace Boare.Lib.Vsq { } public int[] getKeys() { - List t = new List( m_list.Keys ); + List t = new List(); + foreach( int key in m_list.Keys ){ + t.Add( key ); + } return t.ToArray(); } @@ -136,9 +176,59 @@ namespace Boare.Lib.Vsq { } } - public int getElement( int clock ) { + public int getElement( int index ) { + return m_list[m_list.Keys[index]]; + } + + public int getKeyClock( int index ) { + return m_list.Keys[index]; + } + + public int getValue( int clock, ref int index ) { if ( m_list.Count == 0 ) { - return getDefault(); + return Default; + } else { + if ( index < 0 ) { + index = 0; + } + for ( int i = index ; i < m_list.Keys.Count; i++ ) { + int keyclock = m_list.Keys[i]; + if ( clock < keyclock ) { + if ( i > 0 ) { + index = i; + return m_list[m_list.Keys[i - 1]]; + } else { + index = i; + return Default; + } + } + } + index = m_list.Keys.Count - 1; + return m_list[m_list.Keys[m_list.Keys.Count - 1]]; + } + } + + public int getValue( int clock ) { + if ( m_list.Count == 0 ) { + return Default; + } else { + for ( int i = 0; i < m_list.Keys.Count; i++ ) { + int keyclock = m_list.Keys[i]; + if ( clock < keyclock ) { + if ( i > 0 ) { + return m_list[m_list.Keys[i - 1]]; + } else { + return Default; + } + } + } + return m_list[m_list.Keys[m_list.Keys.Count - 1]]; + } + } + + public int OLD_getElement( int clock ) { + if ( m_list.Count == 0 ) { + return Default; } else { if ( m_list.ContainsKey( clock ) ) { return m_list[clock]; @@ -155,7 +245,7 @@ namespace Boare.Lib.Vsq { if ( m_list.ContainsKey( index ) ) { return m_list[index]; } else { - return m_default; + return Default; } } } @@ -165,7 +255,7 @@ namespace Boare.Lib.Vsq { /// このBPListのデフォルト値を取得します /// public int getDefault() { - return m_default; + return Default; } /// diff --git a/trunk/Boare.Lib.Vsq/VsqCommand.cs b/trunk/Boare.Lib.Vsq/VsqCommand.cs index 12b406a..1938fc6 100644 --- a/trunk/Boare.Lib.Vsq/VsqCommand.cs +++ b/trunk/Boare.Lib.Vsq/VsqCommand.cs @@ -37,18 +37,8 @@ namespace Boare.Lib.Vsq { /// /// VsqCommandはgenerateCommand*からコンストラクトしなければならない。 - /// なので、無引数のコンストラクタを隠蔽するためのもの。 /// - internal VsqCommand() { - } - - public static VsqCommand generateCommandTrackChangeRenderer( int track, string renderer ) { - VsqCommand command = new VsqCommand(); - command.Type = VsqCommandType.TrackChangeRenderer; - command.Args = new object[2]; - command.Args[0] = track; - command.Args[1] = renderer; - return command; + public VsqCommand() { } public static VsqCommand generateCommandRoot() { @@ -163,6 +153,15 @@ namespace Boare.Lib.Vsq { return command; } + public static VsqCommand generateCommandTrackChangePlayMode( int track, int play_mode ) { + VsqCommand command = new VsqCommand(); + command.Type = VsqCommandType.TrackChangePlayMode; + command.Args = new object[2]; + command.Args[0] = track; + command.Args[1] = play_mode; + return command; + } + /// /// VsqIDとClockを同時に変更するコマンドを発行します /// @@ -296,6 +295,28 @@ namespace Boare.Lib.Vsq { return command; } + public static VsqCommand generateCommandEventReplace( int track, VsqEvent item ) { + VsqCommand command = new VsqCommand(); + command.Type = VsqCommandType.EventReplace; + command.Args = new object[2]; + command.Args[0] = track; + command.Args[1] = item.Clone(); + return command; + } + + public static VsqCommand generateCommandEventReplaceRange( int track, VsqEvent[] items ) { + VsqCommand command = new VsqCommand(); + command.Type = VsqCommandType.EventReplaceRange; + command.Args = new object[2]; + command.Args[0] = track; + VsqEvent[] objs = new VsqEvent[items.Length]; + for( int i = 0; i < items.Length; i++ ){ + objs[i] = (VsqEvent)items[i].Clone(); + } + command.Args[1] = objs; + return command; + } + /// /// 指定したトラックの、音符のアクセント(Accent)を変更するコマンドを発行します。 /// リストaccent_listには、音符を指定するInternalIDと、変更したいアクセント値のペアを登録します diff --git a/trunk/Boare.Lib.Vsq/VsqCommandType.cs b/trunk/Boare.Lib.Vsq/VsqCommandType.cs index 97b3789..2ba70e0 100644 --- a/trunk/Boare.Lib.Vsq/VsqCommandType.cs +++ b/trunk/Boare.Lib.Vsq/VsqCommandType.cs @@ -44,7 +44,9 @@ namespace Boare.Lib.Vsq { EventChangeIDContaintsRange, TrackReplace, Replace, - TrackChangeRenderer, + TrackChangePlayMode, + EventReplace, + EventReplaceRange, } -} \ No newline at end of file +} diff --git a/trunk/Boare.Lib.Vsq/VsqEvent.cs b/trunk/Boare.Lib.Vsq/VsqEvent.cs index fa53f10..a2416dc 100644 --- a/trunk/Boare.Lib.Vsq/VsqEvent.cs +++ b/trunk/Boare.Lib.Vsq/VsqEvent.cs @@ -20,21 +20,26 @@ namespace Boare.Lib.Vsq { /// [Serializable] public class VsqEvent : IComparable, ICloneable { - public object Tag; + public string Tag; /// /// 内部で使用するインスタンス固有のID /// public int InternalID; public int Clock; public VsqID ID; + public UstEvent UstEvent = new UstEvent(); /// /// このオブジェクトのコピーを作成します /// /// public object Clone() { - VsqEvent ret = new VsqEvent( Clock, ID ); + VsqEvent ret = new VsqEvent( Clock, (VsqID)ID.Clone() ); ret.InternalID = InternalID; + if ( UstEvent != null ) { + ret.UstEvent = (UstEvent)UstEvent.Clone(); + } + ret.Tag = Tag; return ret; } @@ -59,9 +64,13 @@ namespace Boare.Lib.Vsq { } } + public VsqEvent() + : this( 0, new VsqID() ) { + } + public VsqEvent( int clock, VsqID id /*, int internal_id*/ ) { Clock = clock; - ID = (VsqID)id.Clone(); + ID = id; //InternalID = internal_id; InternalID = 0; } diff --git a/trunk/Boare.Lib.Vsq/VsqEventList.cs b/trunk/Boare.Lib.Vsq/VsqEventList.cs index 5cfe739..69d4eb9 100644 --- a/trunk/Boare.Lib.Vsq/VsqEventList.cs +++ b/trunk/Boare.Lib.Vsq/VsqEventList.cs @@ -21,43 +21,56 @@ namespace Boare.Lib.Vsq { /// [Serializable] public class VsqEventList { - private List m_list; + public List Events; private List m_ids; /// /// コンストラクタ /// public VsqEventList() { - m_list = new List(); + Events = new List(); m_ids = new List(); } + public void sort() { + lock ( this ) { + Events.Sort(); + for ( int i = 0; i < Events.Count; i++ ) { + m_ids[i] = Events[i].InternalID; + } + } + } + public void clear() { - m_list.Clear(); + Events.Clear(); m_ids.Clear(); } public Iterator iterator() { - return new ListIterator( m_list ); + updateIDList(); + return new ListIterator( Events ); } public void add( VsqEvent item ) { + updateIDList(); int new_id = getNextId( 0 ); item.InternalID = new_id; - m_list.Add( item ); + Events.Add( item ); m_ids.Add( new_id ); - m_list.Sort(); - for ( int i = 0; i < m_list.Count; i++ ) { - m_ids[i] = m_list[i].InternalID; + Events.Sort(); + for ( int i = 0; i < Events.Count; i++ ) { + m_ids[i] = Events[i].InternalID; } } public void removeAt( int index ) { - m_list.RemoveAt( index ); + updateIDList(); + Events.RemoveAt( index ); m_ids.RemoveAt( index ); } private int getNextId( int next ) { + updateIDList(); int index = -1; List current = new List( m_ids ); int nfound = 0; @@ -75,15 +88,24 @@ namespace Boare.Lib.Vsq { } public int getCount() { - return m_list.Count; + return Events.Count; } public VsqEvent getElement( int index ) { - return m_list[index]; + return Events[index]; } public void setElement( int index, VsqEvent value ) { - m_list[index] = value; + Events[index] = value; + } + + public void updateIDList() { + if ( m_ids.Count != Events.Count ) { + m_ids.Clear(); + for ( int i = 0; i < Events.Count; i++ ) { + m_ids.Add( Events[i].InternalID ); + } + } } } diff --git a/trunk/Boare.Lib.Vsq/VsqFile.cs b/trunk/Boare.Lib.Vsq/VsqFile.cs index fa12ec6..c98daf8 100644 --- a/trunk/Boare.Lib.Vsq/VsqFile.cs +++ b/trunk/Boare.Lib.Vsq/VsqFile.cs @@ -25,12 +25,16 @@ namespace Boare.Lib.Vsq { /// /// トラックのリスト.最初のトラックはMasterTrackであり,通常の音符が格納されるトラックはインデックス1以降となる /// - protected List m_tracks; + public List Track; /// /// テンポ情報を保持したテーブル /// - protected List m_tempo_table; - protected List m_timesig_table; +#if USE_TEMPO_LIST + protected TempoTable m_tempo_table; +#else + public List TempoTable; +#endif + public List TimesigTable; protected int m_tpq; /// /// 曲の長さを取得します。(クロック(4分音符は480クロック)) @@ -39,7 +43,7 @@ namespace Boare.Lib.Vsq { protected int m_base_tempo; public VsqMaster Master; // VsqMaster, VsqMixerは通常,最初の非Master Trackに記述されるが,可搬性のため, public VsqMixer Mixer; // ここではVsqFileに直属するものとして取り扱う. - protected int m_premeasure_clocks; + //protected int m_premeasure_clocks; public object Tag; static readonly byte[] _MTRK = new byte[] { 0x4d, 0x54, 0x72, 0x6b }; @@ -47,6 +51,19 @@ namespace Boare.Lib.Vsq { static readonly byte[] _MASTER_TRACK = new byte[] { 0x4D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x54, 0x72, 0x61, 0x63, 0x6B, }; static readonly string[] _CURVES = new string[] { "VEL", "DYN", "BRE", "BRI", "CLE", "OPE", "GEN", "POR", "PIT", "PBS" }; + /// + /// テンポ値を一律order倍します。 + /// + /// + public void speedingUp( double order ) { + lock ( TempoTable ) { + for ( int i = 0; i < TempoTable.Count; i++ ) { + TempoTable[i].Tempo = (int)(TempoTable[i].Tempo / order); + } + } + updateTempoInfo(); + } + /// /// このインスタンスに編集を行うコマンドを実行します /// @@ -75,8 +92,8 @@ namespace Boare.Lib.Vsq { VsqMixerEntry mixer = (VsqMixerEntry)command.Args[1]; int position = (int)command.Args[2]; VsqCommand ret = VsqCommand.generateCommandDeleteTrack( position ); - if ( m_tracks.Count <= 17 ) { - m_tracks.Insert( position, (VsqTrack)track.Clone() ); + if ( Track.Count <= 17 ) { + Track.Insert( position, (VsqTrack)track.Clone() ); Mixer.Slave.Add( (VsqMixerEntry)mixer.Clone() ); return ret; } else { @@ -86,8 +103,8 @@ namespace Boare.Lib.Vsq { } else if ( type == VsqCommandType.DeleteTrack ) { #region DeleteTrack int track = (int)command.Args[0]; - VsqCommand ret = VsqCommand.generateCommandAddTrack( m_tracks[track], Mixer.Slave[track - 1], track ); - m_tracks.RemoveAt( track ); + VsqCommand ret = VsqCommand.generateCommandAddTrack( Track[track], Mixer.Slave[track - 1], track ); + Track.RemoveAt( track ); Mixer.Slave.RemoveAt( track - 1 ); updateTotalClocks(); return ret; @@ -99,8 +116,8 @@ namespace Boare.Lib.Vsq { int new_clock = (int)command.Args[2]; int index = -1; - for ( int i = 0; i < getTempoList().Count; i++ ) { - if ( getTempoList()[i].Clock == clock ) { + for ( int i = 0; i < TempoTable.Count; i++ ) { + if ( TempoTable[i].Clock == clock ) { index = i; break; } @@ -108,27 +125,27 @@ namespace Boare.Lib.Vsq { VsqCommand ret = null; if ( index >= 0 ) { if ( tempo <= 0 ) { - ret = VsqCommand.generateCommandUpdateTempo( clock, clock, getTempoList()[index].Tempo ); - getTempoList().RemoveAt( index ); + ret = VsqCommand.generateCommandUpdateTempo( clock, clock, TempoTable[index].Tempo ); + TempoTable.RemoveAt( index ); } else { - ret = VsqCommand.generateCommandUpdateTempo( new_clock, clock, getTempoList()[index].Tempo ); - getTempoList()[index].Tempo= tempo ; - getTempoList()[index].Clock= new_clock ; + ret = VsqCommand.generateCommandUpdateTempo( new_clock, clock, TempoTable[index].Tempo ); + TempoTable[index].Tempo= tempo ; + TempoTable[index].Clock= new_clock ; } } else { ret = VsqCommand.generateCommandUpdateTempo( clock, clock, -1 ); - getTempoList().Add( new TempoTableEntry( new_clock, tempo, 0.0 ) ); + TempoTable.Add( new TempoTableEntry( new_clock, tempo, 0.0 ) ); } updateTempoInfo(); updateTotalClocks(); // 編集領域を更新 int affected_clock = Math.Min( clock, new_clock ); - for ( int i = 1; i < m_tracks.Count; i++ ) { - if ( affected_clock < m_tracks[i].getEditedStart() ) { - m_tracks[i].setEditedStart( affected_clock ); + for ( int i = 1; i < Track.Count; i++ ) { + if ( affected_clock < Track[i].getEditedStart() ) { + Track[i].setEditedStart( affected_clock ); } - m_tracks[i].setEditedEnd( (int)TotalClocks ); + Track[i].setEditedEnd( (int)TotalClocks ); } return ret; #endregion @@ -143,32 +160,32 @@ namespace Boare.Lib.Vsq { int index = -1; affected_clock = Math.Min( affected_clock, clocks[i] ); affected_clock = Math.Min( affected_clock, new_clocks[i] ); - for ( int j = 0; j < getTempoList().Count; j++ ) { - if ( getTempoList()[j].Clock == clocks[i] ) { + for ( int j = 0; j < TempoTable.Count; j++ ) { + if ( TempoTable[j].Clock == clocks[i] ) { index = j; break; } } if ( index >= 0 ) { - new_tempos[i] = getTempoList()[index].Tempo; + new_tempos[i] = TempoTable[index].Tempo; if ( tempos[i] <= 0 ) { - getTempoList().RemoveAt( index ); + TempoTable.RemoveAt( index ); } else { - getTempoList()[index].Tempo = tempos[i]; - getTempoList()[index].Clock = new_clocks[i]; + TempoTable[index].Tempo = tempos[i]; + TempoTable[index].Clock = new_clocks[i]; } } else { new_tempos[i] = -1; - getTempoList().Add( new TempoTableEntry( new_clocks[i], tempos[i], 0.0 ) ); + TempoTable.Add( new TempoTableEntry( new_clocks[i], tempos[i], 0.0 ) ); } } updateTempoInfo(); updateTotalClocks(); - for ( int i = 1; i < m_tracks.Count; i++ ) { - if ( affected_clock < m_tracks[i].getEditedStart() ) { - m_tracks[i].setEditedStart( affected_clock ); + for ( int i = 1; i < Track.Count; i++ ) { + if ( affected_clock < Track[i].getEditedStart() ) { + Track[i].setEditedStart( affected_clock ); } - m_tracks[i].setEditedEnd( (int)TotalClocks ); + Track[i].setEditedEnd( (int)TotalClocks ); } return VsqCommand.generateCommandUpdateTempoRange( new_clocks, clocks, new_tempos ); #endregion @@ -179,8 +196,8 @@ namespace Boare.Lib.Vsq { int denominator = (int)command.Args[2]; int new_barcount = (int)command.Args[3]; int index = -1; - for ( int i = 0; i < getTimeSigList().Count; i++ ) { - if ( barcount == getTimeSigList()[i].BarCount ) { + for ( int i = 0; i < TimesigTable.Count; i++ ) { + if ( barcount == TimesigTable[i].BarCount ) { index = i; break; } @@ -188,17 +205,17 @@ namespace Boare.Lib.Vsq { VsqCommand ret = null; if ( index >= 0 ) { if ( numerator <= 0 ) { - ret = VsqCommand.generateCommandUpdateTimesig( barcount, barcount, getTimeSigList()[index].Numerator, getTimeSigList()[index].Denominator ); - getTimeSigList().RemoveAt( index ); + ret = VsqCommand.generateCommandUpdateTimesig( barcount, barcount, TimesigTable[index].Numerator, TimesigTable[index].Denominator ); + TimesigTable.RemoveAt( index ); } else { - ret = VsqCommand.generateCommandUpdateTimesig( new_barcount, barcount, getTimeSigList()[index].Numerator, getTimeSigList()[index].Denominator ); - getTimeSigList()[index].BarCount = new_barcount; - getTimeSigList()[index].Numerator = numerator; - getTimeSigList()[index].Denominator = denominator; + ret = VsqCommand.generateCommandUpdateTimesig( new_barcount, barcount, TimesigTable[index].Numerator, TimesigTable[index].Denominator ); + TimesigTable[index].BarCount = new_barcount; + TimesigTable[index].Numerator = numerator; + TimesigTable[index].Denominator = denominator; } } else { ret = VsqCommand.generateCommandUpdateTimesig( new_barcount, new_barcount, -1, -1 ); - getTimeSigList().Add( new TimeSigTableEntry( 0, numerator, denominator, new_barcount ) ); + TimesigTable.Add( new TimeSigTableEntry( 0, numerator, denominator, new_barcount ) ); } updateTimesigInfo(); updateTotalClocks(); @@ -214,26 +231,29 @@ namespace Boare.Lib.Vsq { int[] new_denominators = new int[denominators.Length]; for ( int i = 0; i < barcounts.Length; i++ ) { int index = -1; - for ( int j = 0; j < getTimeSigList().Count; j++ ) { - if ( getTimeSigList()[j].BarCount == barcounts[i] ) { + // すでに拍子が登録されているかどうかを検査 + for ( int j = 0; j < TimesigTable.Count; j++ ) { + if ( TimesigTable[j].BarCount == barcounts[i] ) { index = j; break; } } if ( index >= 0 ) { - new_numerators[i] = getTimeSigList()[index].Numerator; - new_denominators[i] = getTimeSigList()[index].Denominator; + // 登録されている場合 + new_numerators[i] = TimesigTable[index].Numerator; + new_denominators[i] = TimesigTable[index].Denominator; if ( numerators[i] <= 0 ) { - getTimeSigList().RemoveAt( index ); + TimesigTable.RemoveAt( index ); } else { - getTimeSigList()[index].BarCount = new_barcounts[i]; - getTimeSigList()[index].Numerator = numerators[i]; - getTimeSigList()[index].Denominator = denominators[i]; + TimesigTable[index].BarCount = new_barcounts[i]; + TimesigTable[index].Numerator = numerators[i]; + TimesigTable[index].Denominator = denominators[i]; } } else { + // 登録されていない場合 new_numerators[i] = -1; new_denominators[i] = -1; - getTimeSigList().Add( new TimeSigTableEntry( 0, numerators[i], denominators[i], new_barcounts[i] ) ); + TimesigTable.Add( new TimeSigTableEntry( 0, numerators[i], denominators[i], new_barcounts[i] ) ); } } updateTimesigInfo(); @@ -244,42 +264,46 @@ namespace Boare.Lib.Vsq { #region Replace VsqFile vsq = (VsqFile)command.Args[0]; VsqFile inv = (VsqFile)this.Clone(); - m_tracks.Clear(); - for ( int i = 0; i < vsq.m_tracks.Count; i++ ) { - m_tracks.Add( (VsqTrack)vsq.m_tracks[i].Clone() ); + Track.Clear(); + for ( int i = 0; i < vsq.Track.Count; i++ ) { + Track.Add( (VsqTrack)vsq.Track[i].Clone() ); } - m_tempo_table.Clear(); - for ( int i = 0; i < vsq.m_tempo_table.Count; i++ ) { - m_tempo_table.Add( (TempoTableEntry)vsq.m_tempo_table[i].Clone() ); +#if USE_TEMPO_LIST + m_tempo_table = (TempoTable)vsq.m_tempo_table.Clone(); +#else + TempoTable.Clear(); + for ( int i = 0; i < vsq.TempoTable.Count; i++ ) { + TempoTable.Add( (TempoTableEntry)vsq.TempoTable[i].Clone() ); } - m_timesig_table.Clear(); - for ( int i = 0; i < vsq.m_timesig_table.Count; i++ ) { - m_timesig_table.Add( (TimeSigTableEntry)vsq.m_timesig_table[i].Clone() ); +#endif + TimesigTable.Clear(); + for ( int i = 0; i < vsq.TimesigTable.Count; i++ ) { + TimesigTable.Add( (TimeSigTableEntry)vsq.TimesigTable[i].Clone() ); } m_tpq = vsq.m_tpq; TotalClocks = vsq.TotalClocks; m_base_tempo = vsq.m_base_tempo; Master = (VsqMaster)vsq.Master.Clone(); Mixer = (VsqMixer)vsq.Mixer.Clone(); - m_premeasure_clocks = vsq.m_premeasure_clocks; + //m_premeasure_clocks = vsq.m_premeasure_clocks; updateTotalClocks(); return VsqCommand.generateCommandReplace( inv ); #endregion } else if ( type == VsqCommandType.EventAdd ) { - #region TrackAddNote + #region EventAdd int track = (int)command.Args[0]; VsqEvent item = (VsqEvent)command.Args[1]; //int key = this.Tracks[track].GetNextId( 0 ); //item.InternalID = key; - m_tracks[track].addEvent( item ); + Track[track].addEvent( item ); VsqCommand ret = VsqCommand.generateCommandEventDelete( track, item.InternalID ); //this.Tracks[track].Events.Sort(); updateTotalClocks(); - if ( item.Clock < m_tracks[track].getEditedStart() ) { - m_tracks[track].setEditedStart( item.Clock ); + if ( item.Clock < Track[track].getEditedStart() ) { + Track[track].setEditedStart( item.Clock ); } - if ( m_tracks[track].getEditedEnd() < item.Clock + item.ID.Length ) { - m_tracks[track].setEditedEnd( item.Clock + item.ID.Length ); + if ( Track[track].getEditedEnd() < item.Clock + item.ID.Length ) { + Track[track].setEditedEnd( item.Clock + item.ID.Length ); } return ret; #endregion @@ -302,7 +326,7 @@ namespace Boare.Lib.Vsq { #if DEBUG Console.Write( " i=" + i + "; item.InternalID=" + item.InternalID ); #endif - m_tracks[track].addEvent( item ); + Track[track].addEvent( item ); inv_ids.Add( item.InternalID ); #if DEBUG Console.WriteLine( " => " + item.InternalID ); @@ -310,11 +334,11 @@ namespace Boare.Lib.Vsq { } //Tracks[track].Events.Sort(); updateTotalClocks(); - if ( min_clock < m_tracks[track].getEditedStart() ) { - m_tracks[track].setEditedStart( min_clock ); + if ( min_clock < Track[track].getEditedStart() ) { + Track[track].setEditedStart( min_clock ); } - if ( m_tracks[track].getEditedEnd() < max_clock ) { - m_tracks[track].setEditedEnd( max_clock ); + if ( Track[track].getEditedEnd() < max_clock ) { + Track[track].setEditedEnd( max_clock ); } return VsqCommand.generateCommandEventDeleteRange( track, inv_ids.ToArray() ); #endregion @@ -323,23 +347,23 @@ namespace Boare.Lib.Vsq { int internal_id = (int)command.Args[0]; int track = (int)command.Args[1]; VsqEvent[] original = new VsqEvent[1]; - for ( Iterator itr = m_tracks[track].getEventIterator(); itr.hasNext(); ) { + for ( Iterator itr = Track[track].getEventIterator(); itr.hasNext(); ) { VsqEvent item = (VsqEvent)itr.next(); if ( item.InternalID == internal_id ) { original[0] = (VsqEvent)item.Clone(); break; } } - if ( original[0].Clock < m_tracks[track].getEditedStart() ) { - m_tracks[track].setEditedStart( original[0].Clock ); + if ( original[0].Clock < Track[track].getEditedStart() ) { + Track[track].setEditedStart( original[0].Clock ); } - if ( m_tracks[track].getEditedEnd() < original[0].Clock + original[0].ID.Length ) { - m_tracks[track].setEditedEnd( original[0].Clock + original[0].ID.Length ); + if ( Track[track].getEditedEnd() < original[0].Clock + original[0].ID.Length ) { + Track[track].setEditedEnd( original[0].Clock + original[0].ID.Length ); } VsqCommand ret = VsqCommand.generateCommandEventAddRange( track, original ); - for ( int i = 0; i < this.m_tracks[track].getEventCount(); i++ ) { - if ( this.m_tracks[track].getEvent( i ).InternalID == internal_id ) { - m_tracks[track].removeEvent( i ); + for ( int i = 0; i < this.Track[track].getEventCount(); i++ ) { + if ( this.Track[track].getEvent( i ).InternalID == internal_id ) { + Track[track].removeEvent( i ); break; } } @@ -354,19 +378,19 @@ namespace Boare.Lib.Vsq { int min_clock = int.MaxValue; int max_clock = int.MinValue; for ( int j = 0; j < internal_ids.Length; j++ ) { - for ( int i = 0; i < m_tracks[track].getEventCount(); i++ ) { - if ( internal_ids[j] == m_tracks[track].getEvent( i ).InternalID ) { - inv.Add( (VsqEvent)m_tracks[track].getEvent( i ).Clone() ); - min_clock = Math.Min( min_clock, m_tracks[track].getEvent( i ).Clock ); - max_clock = Math.Max( max_clock, m_tracks[track].getEvent( i ).Clock + m_tracks[track].getEvent( i ).ID.Length ); - m_tracks[track].removeEvent( i ); + for ( int i = 0; i < Track[track].getEventCount(); i++ ) { + if ( internal_ids[j] == Track[track].getEvent( i ).InternalID ) { + inv.Add( (VsqEvent)Track[track].getEvent( i ).Clone() ); + min_clock = Math.Min( min_clock, Track[track].getEvent( i ).Clock ); + max_clock = Math.Max( max_clock, Track[track].getEvent( i ).Clock + Track[track].getEvent( i ).ID.Length ); + Track[track].removeEvent( i ); break; } } } updateTotalClocks(); - m_tracks[track].setEditedStart( min_clock ); - m_tracks[track].setEditedEnd( max_clock ); + Track[track].setEditedStart( min_clock ); + Track[track].setEditedEnd( max_clock ); return VsqCommand.generateCommandEventAddRange( track, inv.ToArray() ); #endregion } else if ( type == VsqCommandType.EventChangeClock ) { @@ -374,14 +398,14 @@ namespace Boare.Lib.Vsq { int track = (int)command.Args[0]; int internal_id = (int)command.Args[1]; int value = (int)command.Args[2]; - for ( Iterator itr = m_tracks[track].getEventIterator(); itr.hasNext(); ) { + for ( Iterator itr = Track[track].getEventIterator(); itr.hasNext(); ) { VsqEvent item = (VsqEvent)itr.next(); if ( item.InternalID == internal_id ) { VsqCommand ret = VsqCommand.generateCommandEventChangeClock( track, internal_id, item.Clock ); int min = Math.Min( item.Clock, value ); int max = Math.Max( item.Clock + item.ID.Length, value + item.ID.Length ); - m_tracks[track].setEditedStart( min ); - m_tracks[track].setEditedEnd( max ); + Track[track].setEditedStart( min ); + Track[track].setEditedEnd( max ); item.Clock = value; //this.Tracks[track].Events.Sort(); updateTotalClocks(); @@ -397,7 +421,7 @@ namespace Boare.Lib.Vsq { string phrase = (string)command.Args[2]; string phonetic_symbol = (string)command.Args[3]; bool protect_symbol = (bool)command.Args[4]; - for ( Iterator itr = m_tracks[track].getEventIterator(); itr.hasNext(); ) { + for ( Iterator itr = Track[track].getEventIterator(); itr.hasNext(); ) { VsqEvent item = (VsqEvent)itr.next(); if ( item.InternalID == internal_id ) { if ( item.ID.type == VsqIDType.Anote ) { @@ -405,8 +429,8 @@ namespace Boare.Lib.Vsq { item.ID.LyricHandle.L0.Phrase = phrase; item.ID.LyricHandle.L0.setPhoneticSymbol( phonetic_symbol ); item.ID.LyricHandle.L0.PhoneticSymbolProtected = protect_symbol; - m_tracks[track].setEditedStart( item.Clock ); - m_tracks[track].setEditedEnd( item.Clock + item.ID.Length ); + Track[track].setEditedStart( item.Clock ); + Track[track].setEditedEnd( item.Clock + item.ID.Length ); updateTotalClocks(); return ret; } @@ -419,14 +443,14 @@ namespace Boare.Lib.Vsq { int track = (int)command.Args[0]; int internal_id = (int)command.Args[1]; int note = (int)command.Args[2]; - for ( Iterator itr = m_tracks[track].getEventIterator(); itr.hasNext(); ) { + for ( Iterator itr = Track[track].getEventIterator(); itr.hasNext(); ) { VsqEvent item = (VsqEvent)itr.next(); if ( item.InternalID == internal_id ) { VsqCommand ret = VsqCommand.generateCommandEventChangeNote( track, internal_id, item.ID.Note ); item.ID.Note = note; updateTotalClocks(); - m_tracks[track].setEditedStart( item.Clock ); - m_tracks[track].setEditedEnd( item.Clock + item.ID.Length ); + Track[track].setEditedStart( item.Clock ); + Track[track].setEditedEnd( item.Clock + item.ID.Length ); return ret; } } @@ -438,14 +462,14 @@ namespace Boare.Lib.Vsq { int internal_id = (int)command.Args[1]; int clock = (int)command.Args[2]; int note = (int)command.Args[3]; - for ( Iterator itr = m_tracks[track].getEventIterator(); itr.hasNext(); ) { + for ( Iterator itr = Track[track].getEventIterator(); itr.hasNext(); ) { VsqEvent item = (VsqEvent)itr.next(); if ( item.InternalID == internal_id ) { VsqCommand ret = VsqCommand.generateCommandEventChangeClockAndNote( track, internal_id, item.Clock, item.ID.Note ); int min = Math.Min( item.Clock, clock ); int max = Math.Max( item.Clock + item.ID.Length, clock + item.ID.Length ); - m_tracks[track].setEditedStart( min ); - m_tracks[track].setEditedEnd( max ); + Track[track].setEditedStart( min ); + Track[track].setEditedEnd( max ); item.Clock = clock; item.ID.Note = note; //this.Tracks[track].Events.Sort(); @@ -471,14 +495,14 @@ namespace Boare.Lib.Vsq { start_clock = Math.Min( start_clock, item.Clock ); end_clock = Math.Max( end_clock, item.Clock ); } - m_tracks[track].setEditedStart( start_clock ); - m_tracks[track].setEditedEnd( end_clock ); - int start_value = m_tracks[track].getCurve( curve ).getElement( start_clock ); - int end_value = m_tracks[track].getCurve( curve ).getElement( end_clock ); - for ( Iterator i = m_tracks[track].getCurve( curve ).keyClockIterator(); i.hasNext(); ){ + Track[track].setEditedStart( start_clock ); + Track[track].setEditedEnd( end_clock ); + int start_value = Track[track].getCurve( curve ).getValue( start_clock ); + int end_value = Track[track].getCurve( curve ).getValue( end_clock ); + for ( Iterator i = Track[track].getCurve( curve ).keyClockIterator(); i.hasNext(); ){ int clock = (int)i.next(); if ( start_clock <= clock && clock <= end_clock ) { - edit.Add( new BPPair( clock, m_tracks[track].getCurve( curve ).getElement( clock ) ) ); + edit.Add( new BPPair( clock, Track[track].getCurve( curve ).getValue( clock ) ) ); } } bool start_found = false; @@ -519,16 +543,16 @@ namespace Boare.Lib.Vsq { return inv; } else if ( com.Count == 1 ) { bool found = false; - for ( Iterator itr = m_tracks[track].getCurve( curve ).keyClockIterator(); itr.hasNext(); ){ + for ( Iterator itr = Track[track].getCurve( curve ).keyClockIterator(); itr.hasNext(); ){ int clock = (int)itr.next(); if ( clock == com[0].Clock ) { found = true; - m_tracks[track].getCurve( curve ).add( clock, com[0].Value ); + Track[track].getCurve( curve ).add( clock, com[0].Value ); break; } } if ( !found ) { - m_tracks[track].getCurve( curve ).add( com[0].Clock, com[0].Value ); + Track[track].getCurve( curve ).add( com[0].Clock, com[0].Value ); } } else { int start_clock = com[0].Clock; @@ -536,17 +560,17 @@ namespace Boare.Lib.Vsq { bool removed = true; while ( removed ) { removed = false; - for ( Iterator itr = m_tracks[track].getCurve( curve ).keyClockIterator(); itr.hasNext(); ) { + for ( Iterator itr = Track[track].getCurve( curve ).keyClockIterator(); itr.hasNext(); ) { int clock = (int)itr.next(); if ( start_clock <= clock && clock <= end_clock ) { - m_tracks[track].getCurve( curve ).remove( clock ); + Track[track].getCurve( curve ).remove( clock ); removed = true; break; } } } foreach ( BPPair item in com ) { - m_tracks[track].getCurve( curve ).add( item.Clock, item.Value ); + Track[track].getCurve( curve ).add( item.Clock, item.Value ); } } return inv; @@ -572,14 +596,14 @@ namespace Boare.Lib.Vsq { start_clock = Math.Min( start_clock, item.Clock ); end_clock = Math.Max( end_clock, item.Clock ); } - m_tracks[track].setEditedStart( start_clock ); - m_tracks[track].setEditedEnd( end_clock ); - int start_value = m_tracks[track].getCurve( curve ).getElement( start_clock ); - int end_value = m_tracks[track].getCurve( curve ).getElement( end_clock ); - for ( Iterator itr = m_tracks[track].getCurve( curve ).keyClockIterator(); itr.hasNext(); ) { + Track[track].setEditedStart( start_clock ); + Track[track].setEditedEnd( end_clock ); + int start_value = Track[track].getCurve( curve ).getValue( start_clock ); + int end_value = Track[track].getCurve( curve ).getValue( end_clock ); + for ( Iterator itr = Track[track].getCurve( curve ).keyClockIterator(); itr.hasNext(); ) { int clock = (int)itr.next(); if ( start_clock <= clock && clock <= end_clock ) { - edit.Add( new BPPair( clock, m_tracks[track].getCurve( curve ).getElement( clock ) ) ); + edit.Add( new BPPair( clock, Track[track].getCurve( curve ).getValue( clock ) ) ); } } bool start_found = false; @@ -622,16 +646,16 @@ namespace Boare.Lib.Vsq { return inv; } else if ( com.Count == 1 ) { bool found = false; - for ( Iterator itr = m_tracks[track].getCurve( curve ).keyClockIterator(); itr.hasNext(); ) { + for ( Iterator itr = Track[track].getCurve( curve ).keyClockIterator(); itr.hasNext(); ) { int clock = (int)itr.next(); if ( clock == com[0].Clock ) { found = true; - m_tracks[track].getCurve( curve ).add( clock, com[0].Value ); + Track[track].getCurve( curve ).add( clock, com[0].Value ); break; } } if ( !found ) { - m_tracks[track].getCurve( curve ).add( com[0].Clock, com[0].Value ); + Track[track].getCurve( curve ).add( com[0].Clock, com[0].Value ); } } else { int start_clock = com[0].Clock; @@ -639,17 +663,17 @@ namespace Boare.Lib.Vsq { bool removed = true; while ( removed ) { removed = false; - for ( Iterator itr = m_tracks[track].getCurve( curve ).keyClockIterator(); itr.hasNext(); ) { + for ( Iterator itr = Track[track].getCurve( curve ).keyClockIterator(); itr.hasNext(); ) { int clock = (int)itr.next(); if ( start_clock <= clock && clock <= end_clock ) { - m_tracks[track].getCurve( curve ).remove( clock ); + Track[track].getCurve( curve ).remove( clock ); removed = true; break; } } } foreach ( BPPair item in com ) { - m_tracks[track].getCurve( curve ).add( item.Clock, item.Value ); + Track[track].getCurve( curve ).add( item.Clock, item.Value ); } } } @@ -660,14 +684,14 @@ namespace Boare.Lib.Vsq { int track = (int)command.Args[0]; List> veloc = (List>)command.Args[1]; List> inv = new List>(); - for ( Iterator itr = m_tracks[track].getEventIterator(); itr.hasNext(); ) { + for ( Iterator itr = Track[track].getEventIterator(); itr.hasNext(); ) { VsqEvent ev = (VsqEvent)itr.next(); foreach ( KeyValuePair add in veloc ) { if ( ev.InternalID == add.Key ) { inv.Add( new KeyValuePair( ev.InternalID, ev.ID.Dynamics ) ); ev.ID.Dynamics = add.Value; - m_tracks[track].setEditedStart( ev.Clock ); - m_tracks[track].setEditedEnd( ev.Clock + ev.ID.Length ); + Track[track].setEditedStart( ev.Clock ); + Track[track].setEditedEnd( ev.Clock + ev.ID.Length ); break; } } @@ -679,14 +703,14 @@ namespace Boare.Lib.Vsq { int track = (int)command.Args[0]; List> veloc = (List>)command.Args[1]; List> inv = new List>(); - for ( Iterator itr = m_tracks[track].getEventIterator(); itr.hasNext(); ) { + for ( Iterator itr = Track[track].getEventIterator(); itr.hasNext(); ) { VsqEvent ev = (VsqEvent)itr.next(); foreach ( KeyValuePair add in veloc ) { if ( ev.InternalID == add.Key ) { inv.Add( new KeyValuePair( ev.InternalID, ev.ID.DEMaccent ) ); ev.ID.DEMaccent = add.Value; - m_tracks[track].setEditedStart( ev.Clock ); - m_tracks[track].setEditedEnd( ev.Clock + ev.ID.Length ); + Track[track].setEditedStart( ev.Clock ); + Track[track].setEditedEnd( ev.Clock + ev.ID.Length ); break; } } @@ -698,14 +722,14 @@ namespace Boare.Lib.Vsq { int track = (int)command.Args[0]; List> veloc = (List>)command.Args[1]; List> inv = new List>(); - for ( Iterator itr = m_tracks[track].getEventIterator(); itr.hasNext(); ) { + for ( Iterator itr = Track[track].getEventIterator(); itr.hasNext(); ) { VsqEvent ev = (VsqEvent)itr.next(); foreach ( KeyValuePair add in veloc ) { if ( ev.InternalID == add.Key ) { inv.Add( new KeyValuePair( ev.InternalID, ev.ID.DEMdecGainRate ) ); ev.ID.DEMdecGainRate = add.Value; - m_tracks[track].setEditedStart( ev.Clock ); - m_tracks[track].setEditedEnd( ev.Clock + ev.ID.Length ); + Track[track].setEditedStart( ev.Clock ); + Track[track].setEditedEnd( ev.Clock + ev.ID.Length ); break; } } @@ -717,13 +741,13 @@ namespace Boare.Lib.Vsq { int track = (int)command.Args[0]; int internal_id = (int)command.Args[1]; int new_length = (int)command.Args[2]; - for ( Iterator itr = m_tracks[track].getEventIterator(); itr.hasNext(); ) { + for ( Iterator itr = Track[track].getEventIterator(); itr.hasNext(); ) { VsqEvent item = (VsqEvent)itr.next(); if ( item.InternalID == internal_id ) { VsqCommand ret = VsqCommand.generateCommandEventChangeLength( track, internal_id, item.ID.Length ); - m_tracks[track].setEditedStart( item.Clock ); + Track[track].setEditedStart( item.Clock ); int max = Math.Max( item.Clock + item.ID.Length, item.Clock + new_length ); - m_tracks[track].setEditedEnd( max ); + Track[track].setEditedEnd( max ); item.ID.Length = new_length; updateTotalClocks(); return ret; @@ -737,15 +761,15 @@ namespace Boare.Lib.Vsq { int internal_id = (int)command.Args[1]; int new_clock = (int)command.Args[2]; int new_length = (int)command.Args[3]; - for ( Iterator itr = m_tracks[track].getEventIterator(); itr.hasNext(); ) { + for ( Iterator itr = Track[track].getEventIterator(); itr.hasNext(); ) { VsqEvent item = (VsqEvent)itr.next(); if ( item.InternalID == internal_id ) { VsqCommand ret = VsqCommand.generateCommandEventChangeClockAndLength( track, internal_id, item.Clock, item.ID.Length ); int min = Math.Min( item.Clock, new_clock ); int max_length = Math.Max( item.ID.Length, new_length ); int max = Math.Max( item.Clock + max_length, new_clock + max_length ); - m_tracks[track].setEditedStart( min ); - m_tracks[track].setEditedEnd( max ); + Track[track].setEditedStart( min ); + Track[track].setEditedEnd( max ); item.ID.Length = new_length; item.Clock = new_clock; updateTotalClocks(); @@ -759,13 +783,13 @@ namespace Boare.Lib.Vsq { int track = (int)command.Args[0]; int internal_id = (int)command.Args[1]; VsqID value = (VsqID)command.Args[2]; - for ( Iterator itr = m_tracks[track].getEventIterator(); itr.hasNext(); ) { + for ( Iterator itr = Track[track].getEventIterator(); itr.hasNext(); ) { VsqEvent item = (VsqEvent)itr.next(); if ( item.InternalID == internal_id ) { VsqCommand ret = VsqCommand.generateCommandEventChangeIDContaints( track, internal_id, item.ID ); int max_length = Math.Max( item.ID.Length, value.Length ); - m_tracks[track].setEditedStart( item.Clock ); - m_tracks[track].setEditedEnd( item.Clock + max_length ); + Track[track].setEditedStart( item.Clock ); + Track[track].setEditedEnd( item.Clock + max_length ); item.ID = (VsqID)value.Clone(); if ( item.ID.type == VsqIDType.Singer ) { #if DEBUG @@ -773,23 +797,23 @@ namespace Boare.Lib.Vsq { #endif // 歌手変更の場合、次に現れる歌手変更の位置まで編集の影響が及ぶ bool found = false; - for ( Iterator itr2 = m_tracks[track].getSingerEventIterator(); itr2.hasNext(); ) { + for ( Iterator itr2 = Track[track].getSingerEventIterator(); itr2.hasNext(); ) { VsqEvent item2 = (VsqEvent)itr2.next(); if ( item.Clock < item2.Clock ) { - m_tracks[track].setEditedEnd( item2.Clock ); + Track[track].setEditedEnd( item2.Clock ); found = true; break; } } if ( !found ) { // 変更対象が、該当トラック最後の歌手変更イベントだった場合 - if ( m_tracks[track].getEventCount() >= 1 ) { - VsqEvent last_event = m_tracks[track].getEvent( m_tracks[track].getEventCount() - 1 ); - m_tracks[track].setEditedEnd( last_event.Clock + last_event.ID.Length ); + if ( Track[track].getEventCount() >= 1 ) { + VsqEvent last_event = Track[track].getEvent( Track[track].getEventCount() - 1 ); + Track[track].setEditedEnd( last_event.Clock + last_event.ID.Length ); } } #if DEBUG - Console.WriteLine( " EditedStart,EditedEnd=" + m_tracks[track].getEditedStart() + "," + m_tracks[track].getEditedEnd() ); + Console.WriteLine( " EditedStart,EditedEnd=" + Track[track].getEditedStart() + "," + Track[track].getEditedEnd() ); #endif } updateTotalClocks(); @@ -805,30 +829,30 @@ namespace Boare.Lib.Vsq { VsqID[] values = (VsqID[])command.Args[2]; VsqID[] inv_values = new VsqID[values.Length]; for ( int i = 0; i < internal_ids.Length; i++ ) { - for ( Iterator itr = m_tracks[track].getEventIterator(); itr.hasNext(); ) { + for ( Iterator itr = Track[track].getEventIterator(); itr.hasNext(); ) { VsqEvent item = (VsqEvent)itr.next(); if ( item.InternalID == internal_ids[i] ) { inv_values[i] = (VsqID)item.ID.Clone(); int max_length = Math.Max( item.ID.Length, values[i].Length ); - m_tracks[track].setEditedStart( item.Clock ); - m_tracks[track].setEditedEnd( item.Clock + max_length ); + Track[track].setEditedStart( item.Clock ); + Track[track].setEditedEnd( item.Clock + max_length ); item.ID = (VsqID)values[i].Clone(); if ( item.ID.type == VsqIDType.Singer ) { // 歌手変更の場合、次に現れる歌手変更の位置まで編集の影響が及ぶ bool found = false; - for ( Iterator itr2 = m_tracks[track].getSingerEventIterator(); itr2.hasNext(); ) { + for ( Iterator itr2 = Track[track].getSingerEventIterator(); itr2.hasNext(); ) { VsqEvent item2 = (VsqEvent)itr2.next(); if ( item.Clock < item2.Clock ) { - m_tracks[track].setEditedEnd( item2.Clock ); + Track[track].setEditedEnd( item2.Clock ); found = true; break; } } if ( !found ) { // 変更対象が、該当トラック最後の歌手変更イベントだった場合 - if ( m_tracks[track].getEventCount() >= 1 ) { - VsqEvent last_event = m_tracks[track].getEvent( m_tracks[track].getEventCount() - 1 ); - m_tracks[track].setEditedEnd( last_event.Clock + last_event.ID.Length ); + if ( Track[track].getEventCount() >= 1 ) { + VsqEvent last_event = Track[track].getEvent( Track[track].getEventCount() - 1 ); + Track[track].setEditedEnd( last_event.Clock + last_event.ID.Length ); } } } @@ -845,7 +869,7 @@ namespace Boare.Lib.Vsq { int internal_id = (int)command.Args[1]; int new_clock = (int)command.Args[2]; VsqID value = (VsqID)command.Args[3]; - for ( Iterator itr = m_tracks[track].getEventIterator(); itr.hasNext(); ) { + for ( Iterator itr = Track[track].getEventIterator(); itr.hasNext(); ) { VsqEvent item = (VsqEvent)itr.next(); if ( item.InternalID == internal_id ) { VsqCommand ret = VsqCommand.generateCommandEventChangeClockAndIDContaints( track, internal_id, item.Clock, item.ID ); @@ -854,8 +878,8 @@ namespace Boare.Lib.Vsq { int max = Math.Max( item.Clock + max_length, new_clock + max_length ); item.ID = (VsqID)value.Clone(); item.Clock = new_clock; - m_tracks[track].setEditedStart( min ); - m_tracks[track].setEditedEnd( max ); + Track[track].setEditedStart( min ); + Track[track].setEditedEnd( max ); updateTotalClocks(); return ret; } @@ -871,7 +895,7 @@ namespace Boare.Lib.Vsq { List inv_id = new List(); List inv_clock = new List(); for ( int i = 0; i < internal_ids.Length; i++ ) { - for ( Iterator itr = m_tracks[track].getEventIterator(); itr.hasNext(); ) { + for ( Iterator itr = Track[track].getEventIterator(); itr.hasNext(); ) { VsqEvent item = (VsqEvent)itr.next(); if ( item.InternalID == internal_ids[i] ) { inv_id.Add( (VsqID)item.ID.Clone() ); @@ -879,8 +903,8 @@ namespace Boare.Lib.Vsq { int max_length = Math.Max( item.ID.Length, values[i].Length ); int min = Math.Min( item.Clock, clocks[i] ); int max = Math.Max( item.Clock + max_length, clocks[i] + max_length ); - m_tracks[track].setEditedStart( min ); - m_tracks[track].setEditedEnd( max ); + Track[track].setEditedStart( min ); + Track[track].setEditedEnd( max ); item.ID = (VsqID)values[i].Clone(); item.Clock = clocks[i]; break; @@ -905,26 +929,60 @@ namespace Boare.Lib.Vsq { #region TrackCangeName int track = (int)command.Args[0]; string new_name = (string)command.Args[1]; - VsqCommand ret = VsqCommand.generateCommandTrackChangeName( track, m_tracks[track].Name ); - m_tracks[track].Name = new_name; + VsqCommand ret = VsqCommand.generateCommandTrackChangeName( track, Track[track].Name ); + Track[track].Name = new_name; return ret; #endregion } else if ( type == VsqCommandType.TrackReplace ) { #region TrackReplace int track = (int)command.Args[0]; VsqTrack item = (VsqTrack)command.Args[1]; - VsqCommand ret = VsqCommand.generateCommandTrackReplace( track, (VsqTrack)m_tracks[track].Clone() ); - m_tracks[track] = item; + VsqCommand ret = VsqCommand.generateCommandTrackReplace( track, Track[track] ); + Track[track] = item; updateTotalClocks(); return ret; #endregion - } else if ( type == VsqCommandType.TrackChangeRenderer ) { - #region TrackChangeRenderer + } else if ( type == VsqCommandType.TrackChangePlayMode ) { + #region TrackChangePlayMode int track = (int)command.Args[0]; - string renderer = (string)command.Args[1]; - string old_renderer = m_tracks[track].Renderer; - m_tracks[track].Renderer = renderer; - VsqCommand ret = VsqCommand.generateCommandTrackChangeRenderer( track, old_renderer ); + int play_mode = (int)command.Args[1]; + VsqCommand ret = VsqCommand.generateCommandTrackChangePlayMode( track, Track[track].getCommon().PlayMode ); + Track[track].getCommon().PlayMode = play_mode; + return ret; + #endregion + } else if ( type == VsqCommandType.EventReplace ) { + #region EventReplace + int track = (int)command.Args[0]; + VsqEvent item = (VsqEvent)command.Args[1]; + VsqCommand ret = null; + for ( int i = 0; i < Track[track].getEventCount(); i++ ) { + VsqEvent ve = Track[track].getEvent( i ); + if ( ve.InternalID == item.InternalID ) { + ret = VsqCommand.generateCommandEventReplace( track, ve ); + Track[track].setEvent( i, item ); + break; + } + } + return ret; + #endregion + } else if ( type == VsqCommandType.EventReplaceRange ) { + #region EventReplaceRange + int track = (int)command.Args[0]; + object[] items = (object[])command.Args[1]; + VsqCommand ret = null; + VsqEvent[] reverse = new VsqEvent[items.Length]; + for ( int i = 0; i < items.Length; i++ ) { + VsqEvent ve = (VsqEvent)items[i]; + for ( int j = 0; j < Track[track].getEventCount(); j++ ) { + VsqEvent ve2 = (VsqEvent)Track[track].getEvent( j ); + if ( ve2.InternalID == ve.InternalID ) { + reverse[i] = (VsqEvent)ve2.Clone(); + Track[track].setEvent( j, (VsqEvent)items[i] ); + break; + } + } + } + ret = VsqCommand.generateCommandEventReplaceRange( track, reverse ); return ret; #endregion } @@ -938,39 +996,42 @@ namespace Boare.Lib.Vsq { /// 編集対象のVsqFileインスタンス /// 削除を行う範囲の開始クロック /// 削除を行う範囲の終了クロック - public static void removePart( VsqFile vsq, int clock_start, int clock_end ) { + public virtual void removePart( int clock_start, int clock_end ) { int dclock = clock_end - clock_start; // テンポ情報の削除、シフト bool changed = true; - List buf = new List( vsq.getTempoList() ); - int tempo_at_clock_start = vsq.getTempoAt( clock_start ); - vsq.getTempoList().Clear(); + List buf = new List( TempoTable ); + int tempo_at_clock_end = getTempoAt( clock_end ); + TempoTable.Clear(); bool just_on_clock_end_added = false; for ( int i = 0; i < buf.Count; i++ ) { if ( buf[i].Clock < clock_start ) { - vsq.getTempoList().Add( (TempoTableEntry)buf[i].Clone() ); + TempoTable.Add( (TempoTableEntry)buf[i].Clone() ); } else if ( clock_end <= buf[i].Clock ) { TempoTableEntry tte = (TempoTableEntry)buf[i].Clone(); tte.Clock = tte.Clock - dclock; if ( clock_end == buf[i].Clock ) { - vsq.getTempoList().Add( tte ); + TempoTable.Add( tte ); just_on_clock_end_added = true; } else { if ( !just_on_clock_end_added ) { - vsq.getTempoList().Add( new TempoTableEntry( clock_end - dclock, tempo_at_clock_start, 0.0 ) ); + TempoTable.Add( new TempoTableEntry( clock_start, tempo_at_clock_end, 0.0 ) ); just_on_clock_end_added = true; } - vsq.getTempoList().Add( tte ); + TempoTable.Add( tte ); } } } - vsq.updateTempoInfo(); + if ( !just_on_clock_end_added ) { + TempoTable.Add( new TempoTableEntry( clock_start, tempo_at_clock_end, 0.0 ) ); + } + updateTempoInfo(); - for ( int track = 1; track < vsq.m_tracks.Count; track++ ) { + for ( int track = 1; track < Track.Count; track++ ) { // 削除する範囲に歌手変更イベントが存在するかどうかを検査。 VsqEvent t_last_singer = null; - for ( Iterator itr = vsq.m_tracks[track].getSingerEventIterator(); itr.hasNext(); ) { + for ( Iterator itr = Track[track].getSingerEventIterator(); itr.hasNext(); ) { VsqEvent ve = (VsqEvent)itr.next(); if ( clock_start <= ve.Clock && ve.Clock < clock_end ) { t_last_singer = ve; @@ -989,9 +1050,9 @@ namespace Boare.Lib.Vsq { // イベントの削除 while ( changed ) { changed = false; - for ( int i = 0; i < vsq.m_tracks[track].getEventCount(); i++ ) { - if ( clock_start <= vsq.m_tracks[track].getEvent( i ).Clock && vsq.m_tracks[track].getEvent( i ).Clock < clock_end ) { - vsq.m_tracks[track].removeEvent( i ); + for ( int i = 0; i < Track[track].getEventCount(); i++ ) { + if ( clock_start <= Track[track].getEvent( i ).Clock && Track[track].getEvent( i ).Clock < clock_end ) { + Track[track].removeEvent( i ); changed = true; break; } @@ -1000,11 +1061,11 @@ namespace Boare.Lib.Vsq { // クロックのシフト if ( last_singer != null ) { - vsq.m_tracks[track].addEvent( last_singer ); //歌手変更イベントを補う + Track[track].addEvent( last_singer ); //歌手変更イベントを補う } - for ( int i = 0; i < vsq.m_tracks[track].getEventCount(); i++ ) { - if ( clock_end <= vsq.m_tracks[track].getEvent( i ).Clock ) { - vsq.m_tracks[track].getEvent( i ).Clock -= dclock; + for ( int i = 0; i < Track[track].getEventCount(); i++ ) { + if ( clock_end <= Track[track].getEvent( i ).Clock ) { + Track[track].getEvent( i ).Clock -= dclock; } } @@ -1012,16 +1073,24 @@ namespace Boare.Lib.Vsq { if ( curve == "VEL" ) { continue; } - VsqBPList buf_bplist = (VsqBPList)vsq.m_tracks[track].getCurve( curve ).Clone(); - vsq.m_tracks[track].getCurve( curve ).clear(); + VsqBPList buf_bplist = (VsqBPList)Track[track].getCurve( curve ).Clone(); + Track[track].getCurve( curve ).clear(); + int value_at_end = buf_bplist.getValue( clock_end ); + bool at_end_added = false; for ( Iterator itr = buf_bplist.keyClockIterator(); itr.hasNext(); ) { int key = (int)itr.next(); if ( key < clock_start ) { - vsq.m_tracks[track].getCurve( curve ).add( key, buf_bplist.getElement( key ) ); + Track[track].getCurve( curve ).add( key, buf_bplist.getValue( key ) ); } else if ( clock_end <= key ) { - vsq.m_tracks[track].getCurve( curve ).add( key - dclock, buf_bplist.getElement( key ) ); + if ( key == clock_end ) { + at_end_added = true; + } + Track[track].getCurve( curve ).add( key - dclock, buf_bplist.getValue( key ) ); } } + if ( !at_end_added ) { + Track[track].getCurve( curve ).add( clock_end - dclock, value_at_end ); + } } } } @@ -1037,16 +1106,16 @@ namespace Boare.Lib.Vsq { return; } int dclock = (int)delta_clock; - for ( int i = 0; i < vsq.getTempoList().Count; i++ ) { - if ( vsq.getTempoList()[i].Clock > 0 ) { - vsq.getTempoList()[i].Clock =vsq.getTempoList()[i].Clock + dclock; + for ( int i = 0; i < vsq.TempoTable.Count; i++ ) { + if ( vsq.TempoTable[i].Clock > 0 ) { + vsq.TempoTable[i].Clock =vsq.TempoTable[i].Clock + dclock; } } vsq.updateTempoInfo(); - for ( int track = 1; track < vsq.m_tracks.Count; track++ ) { - for ( int i = 0; i < vsq.m_tracks[track].getEventCount(); i++ ) { - if ( vsq.m_tracks[track].getEvent( i ).Clock > 0 ) { - vsq.m_tracks[track].getEvent( i ).Clock += dclock; + for ( int track = 1; track < vsq.Track.Count; track++ ) { + for ( int i = 0; i < vsq.Track[track].getEventCount(); i++ ) { + if ( vsq.Track[track].getEvent( i ).Clock > 0 ) { + vsq.Track[track].getEvent( i ).Clock += dclock; } } foreach ( string curve in _CURVES ) { @@ -1055,12 +1124,12 @@ namespace Boare.Lib.Vsq { } // 順番に+=dclockしていくとVsqBPList内部のSortedListの値がかぶる可能性がある. - VsqBPList edit = vsq.m_tracks[track].getCurve( curve ); + VsqBPList edit = vsq.Track[track].getCurve( curve ); VsqBPList new_one = new VsqBPList( edit.getDefault(), edit.getMinimum(), edit.getMaximum() ); foreach( int key in edit.getKeys() ){ - new_one.add( key + dclock, edit.getElement( key ) ); + new_one.add( key + dclock, edit.getValue( key ) ); } - vsq.m_tracks[track].setCurve( curve, new_one ); + vsq.Track[track].setCurve( curve, new_one ); } } vsq.updateTotalClocks(); @@ -1070,31 +1139,34 @@ namespace Boare.Lib.Vsq { /// このインスタンスのコピーを作成します /// /// このインスタンスのコピー - public object Clone() { + public virtual object Clone() { VsqFile ret = new VsqFile(); - ret.m_tracks = new List(); - for ( int i = 0; i < m_tracks.Count; i++ ) { - ret.m_tracks.Add( (VsqTrack)m_tracks[i].Clone() ); + ret.Track = new List(); + for ( int i = 0; i < Track.Count; i++ ) { + ret.Track.Add( (VsqTrack)Track[i].Clone() ); } - ret.m_tempo_table = new List(); - for ( int i = 0; i < m_tempo_table.Count; i++ ) { - ret.m_tempo_table.Add( (TempoTableEntry)m_tempo_table[i].Clone() ); +#if USE_TEMPO_LIST + ret.m_tempo_table = (TempoTable)m_tempo_table.Clone(); +#else + ret.TempoTable = new List(); + for ( int i = 0; i < TempoTable.Count; i++ ) { + ret.TempoTable.Add( (TempoTableEntry)TempoTable[i].Clone() ); } - ret.m_timesig_table = new List(); - for ( int i = 0; i < m_timesig_table.Count; i++ ) { - ret.m_timesig_table.Add( (TimeSigTableEntry)m_timesig_table[i].Clone() ); +#endif + ret.TimesigTable = new List(); + for ( int i = 0; i < TimesigTable.Count; i++ ) { + ret.TimesigTable.Add( (TimeSigTableEntry)TimesigTable[i].Clone() ); } ret.m_tpq = m_tpq; ret.TotalClocks = TotalClocks; ret.m_base_tempo = m_base_tempo; ret.Master = (VsqMaster)Master.Clone(); ret.Mixer = (VsqMixer)Mixer.Clone(); - ret.m_premeasure_clocks = m_premeasure_clocks; + //ret.m_premeasure_clocks = m_premeasure_clocks; return ret; } private VsqFile() { - VsqUtil.loadSingerConfigs(); } private class BarLineIterator : Iterator { @@ -1110,6 +1182,12 @@ namespace Boare.Lib.Vsq { int bar_counter; public BarLineIterator( List list, int end_clock ) { + /*lock ( list ) { + m_list = new List(); + for ( int j = 0; j < list.Count; j++ ) { + m_list.Add( (TimeSigTableEntry)list[j].Clone() ); + } + }*/ m_list = list; m_end_clock = end_clock; i = 0; @@ -1180,7 +1258,7 @@ namespace Boare.Lib.Vsq { /// /// public Iterator getBarLineIterator( int end_clock ) { - return new BarLineIterator( getTimeSigList(), end_clock ); + return new BarLineIterator( TimesigTable, end_clock ); } /// @@ -1201,7 +1279,7 @@ namespace Boare.Lib.Vsq { /// プリメジャー部分の長さをクロックに変換した値を取得します. /// public int getPreMeasureClocks() { - return m_premeasure_clocks; + return calculatePreMeasureInClock(); } /// @@ -1209,18 +1287,18 @@ namespace Boare.Lib.Vsq { /// private int calculatePreMeasureInClock() { int pre_measure = Master.PreMeasure; - int last_bar_count = getTimeSigList()[0].BarCount; - int last_clock = getTimeSigList()[0].Clock; - int last_denominator = getTimeSigList()[0].Denominator; - int last_numerator = getTimeSigList()[0].Numerator; - for ( int i = 1; i < getTimeSigList().Count; i++ ) { - if ( getTimeSigList()[i].BarCount >= pre_measure ) { + int last_bar_count = TimesigTable[0].BarCount; + int last_clock = TimesigTable[0].Clock; + int last_denominator = TimesigTable[0].Denominator; + int last_numerator = TimesigTable[0].Numerator; + for ( int i = 1; i < TimesigTable.Count; i++ ) { + if ( TimesigTable[i].BarCount >= pre_measure ) { break; } else { - last_bar_count = getTimeSigList()[i].BarCount; - last_clock = getTimeSigList()[i].Clock; - last_denominator = getTimeSigList()[i].Denominator; - last_numerator = getTimeSigList()[i].Numerator; + last_bar_count = TimesigTable[i].BarCount; + last_clock = TimesigTable[i].Clock; + last_denominator = TimesigTable[i].Denominator; + last_numerator = TimesigTable[i].Numerator; } } @@ -1233,12 +1311,12 @@ namespace Boare.Lib.Vsq { /// /// /// - public double getSecFromClock( int clock ) { - for ( int i = getTempoList().Count - 1; i >= 0; i-- ) { - if ( getTempoList()[i].Clock < clock ) { - double init = getTempoList()[i].Time; - int dclock = clock - getTempoList()[i].Clock; - double sec_per_clock1 = getTempoList()[i].Tempo * 1e-6 / 480.0; + public double getSecFromClock( double clock ) { + for ( int i = TempoTable.Count - 1; i >= 0; i-- ) { + if ( TempoTable[i].Clock < clock ) { + double init = TempoTable[i].Time; + double dclock = clock - TempoTable[i].Clock; + double sec_per_clock1 = TempoTable[i].Tempo * 1e-6 / 480.0; return init + dclock * sec_per_clock1; } } @@ -1254,26 +1332,30 @@ namespace Boare.Lib.Vsq { /// public double getClockFromSec( double time ) { // timeにおけるテンポを取得 +#if USE_TEMPO_LIST + return m_tempo_table.getClockFromSec( time ); +#else int tempo = m_base_tempo; double base_clock = 0; double base_time = 0f; - if ( m_tempo_table.Count == 0 ) { + if ( TempoTable.Count == 0 ) { tempo = m_base_tempo; base_clock = 0; base_time = 0f; - } else if ( m_tempo_table.Count == 1 ) { - tempo = m_tempo_table[0].Tempo; - base_clock = m_tempo_table[0].Clock; - base_time = m_tempo_table[0].Time; + } else if ( TempoTable.Count == 1 ) { + tempo = TempoTable[0].Tempo; + base_clock = TempoTable[0].Clock; + base_time = TempoTable[0].Time; } else { - for ( int i = m_tempo_table.Count - 1; i >= 0; i-- ) { - if ( m_tempo_table[i].Time < time ) { - return m_tempo_table[i].Clock + (time - m_tempo_table[i].Time) * m_tpq * 1000000.0 / m_tempo_table[i].Tempo; + for ( int i = TempoTable.Count - 1; i >= 0; i-- ) { + if ( TempoTable[i].Time < time ) { + return TempoTable[i].Clock + (time - TempoTable[i].Time) * m_tpq * 1000000.0 / TempoTable[i].Tempo; } } } double dt = time - base_time; return base_clock + dt * m_tpq * 1000000.0 / (double)tempo; +#endif } /// @@ -1284,14 +1366,29 @@ namespace Boare.Lib.Vsq { /// public void getTimesigAt( int clock, out int numerator, out int denominator ) { int index = 0; - for ( int i = getTimeSigList().Count - 1; i >= 0; i-- ) { + for ( int i = TimesigTable.Count - 1; i >= 0; i-- ) { index = i; - if ( getTimeSigList()[i].Clock <= clock ) { + if ( TimesigTable[i].Clock <= clock ) { break; } } - numerator = getTimeSigList()[index].Numerator; - denominator = getTimeSigList()[index].Denominator; + numerator = TimesigTable[index].Numerator; + denominator = TimesigTable[index].Denominator; + } + + public void getTimesigAt( int clock, out int numerator, out int denominator, out int bar_count ) { + int index = 0; + for ( int i = TimesigTable.Count - 1; i >= 0; i-- ) { + index = i; + if ( TimesigTable[i].Clock <= clock ) { + break; + } + } + numerator = TimesigTable[index].Numerator; + denominator = TimesigTable[index].Denominator; + int diff = clock - TimesigTable[index].Clock; + int clock_per_bar = 480 * 4 / denominator * numerator; + bar_count = TimesigTable[index].BarCount + diff / clock_per_bar; } /// @@ -1301,13 +1398,13 @@ namespace Boare.Lib.Vsq { /// public int getTempoAt( int clock ) { int index = 0; - for ( int i = getTempoList().Count - 1; i >= 0; i-- ) { + for ( int i = TempoTable.Count - 1; i >= 0; i-- ) { index = i; - if ( getTempoList()[i].Clock <= clock ) { + if ( TempoTable[i].Clock <= clock ) { break; } } - return getTempoList()[index].Tempo; + return TempoTable[index].Tempo; } /// @@ -1317,16 +1414,16 @@ namespace Boare.Lib.Vsq { /// public int getClockFromBarCount( int bar_count ) { int index = 0; - for ( int i = getTimeSigList().Count - 1; i >= 0; i-- ) { + for ( int i = TimesigTable.Count - 1; i >= 0; i-- ) { index = i; - if ( getTimeSigList()[i].BarCount <= bar_count ) { + if ( TimesigTable[i].BarCount <= bar_count ) { break; } } - int numerator = getTimeSigList()[index].Numerator; - int denominator = getTimeSigList()[index].Denominator; - int init_clock = getTimeSigList()[index].Clock; - int init_bar_count = getTimeSigList()[index].BarCount; + int numerator = TimesigTable[index].Numerator; + int denominator = TimesigTable[index].Denominator; + int init_clock = TimesigTable[index].Clock; + int init_bar_count = TimesigTable[index].BarCount; int clock_per_bar = numerator * 480 * 4 / denominator; return init_clock + (bar_count - init_bar_count) * clock_per_bar; } @@ -1338,18 +1435,18 @@ namespace Boare.Lib.Vsq { /// public int getBarCountFromClock( int clock ) { int index = 0; - for ( int i = getTimeSigList().Count - 1; i >= 0; i-- ) { + for ( int i = TimesigTable.Count - 1; i >= 0; i-- ) { index = i; - if ( getTimeSigList()[i].Clock <= clock ) { + if ( TimesigTable[i].Clock <= clock ) { break; } } int bar_count = 0; if ( index >= 0 ) { - int last_clock = getTimeSigList()[index].Clock; - int t_bar_count = getTimeSigList()[index].BarCount; - int numerator = getTimeSigList()[index].Numerator; - int denominator = getTimeSigList()[index].Denominator; + int last_clock = TimesigTable[index].Clock; + int t_bar_count = TimesigTable[index].BarCount; + int numerator = TimesigTable[index].Numerator; + int denominator = TimesigTable[index].Denominator; int clock_per_bar = numerator * 480 * 4 / denominator; bar_count = t_bar_count + (clock - last_clock) / clock_per_bar; } @@ -1363,27 +1460,33 @@ namespace Boare.Lib.Vsq { return m_tpq; } - /// +#if USE_TEMPO_LIST + public TempoTable TempoTable { + return m_tempo_table; + } +#else + /*/// /// テンポの変更情報を格納したテーブルを取得します /// public List getTempoList() { - return m_tempo_table; - } + return TempoTable; + }*/ +#endif - /// + /*/// /// 拍子の変更情報を格納したテーブルを取得します /// public List getTimeSigList() { - return m_timesig_table; - } + return TimesigTable; + }*/ - public VsqTrack getTrack( int track ) { - return m_tracks[track]; - } + /*public VsqTrack Track( int track ) { + return Track[track]; + }*/ - public int getTrackCount() { - return m_tracks.Count; - } + /*public int getTrackCount() { + return Tracks.Count; + }*/ /// /// 空のvsqファイルを構築します @@ -1392,31 +1495,25 @@ namespace Boare.Lib.Vsq { /// /// /// - public VsqFile( int default_singer_program_change, int pre_measure, int numerator, int denominator, int tempo ) { - VsqUtil.loadSingerConfigs(); + public VsqFile( string singer, int pre_measure, int numerator, int denominator, int tempo ) { TotalClocks = pre_measure * 480 * 4 / denominator * numerator; m_tpq = 480; - m_tracks = new List(); - m_tracks.Add( new VsqTrack( tempo, numerator, denominator ) ); - string singer = "Miku"; - SingerConfig sc = VsqUtil.getSingerInfo( default_singer_program_change ); - if ( sc != null ) { - singer = sc.VOICENAME; - } - m_tracks.Add( new VsqTrack( "Voice1", singer ) ); + Track = new List(); + Track.Add( new VsqTrack( tempo, numerator, denominator ) ); + Track.Add( new VsqTrack( "Voice1", singer ) ); Master = new VsqMaster( pre_measure ); #if DEBUG Console.WriteLine( "VsqFile.ctor()" ); #endif Mixer = new VsqMixer( 0, 0, 0, 0 ); Mixer.Slave.Add( new VsqMixerEntry( 0, 0, 0, 0 ) ); - m_timesig_table = new List(); - m_timesig_table.Add( new TimeSigTableEntry( 0, numerator, denominator, 0 ) ); - m_tempo_table = new List(); - m_tempo_table.Add( new TempoTableEntry( 0, tempo, 0.0 ) ); + TimesigTable = new List(); + TimesigTable.Add( new TimeSigTableEntry( 0, numerator, denominator, 0 ) ); + TempoTable = new List(); + TempoTable.Add( new TempoTableEntry( 0, tempo, 0.0 ) ); m_base_tempo = tempo; - m_premeasure_clocks = calculatePreMeasureInClock(); + //m_premeasure_clocks = calculatePreMeasureInClock(); } /// @@ -1424,35 +1521,34 @@ namespace Boare.Lib.Vsq { /// /// public VsqFile( string _fpath ) { - VsqUtil.loadSingerConfigs(); - m_tempo_table = new List(); - m_timesig_table = new List(); + TempoTable = new List(); + TimesigTable = new List(); m_tpq = 480; // SMFをコンバートしたテキストファイルを作成 - using ( TextMemoryStream tms = new TextMemoryStream( FileAccess.ReadWrite ) ) { + //using ( TextMemoryStream tms = new TextMemoryStream( FileAccess.ReadWrite ) ) { MidiFile mf = new MidiFile( _fpath ); - m_tracks = new List(); + Track = new List(); int num_track = mf.getTrackCount(); for ( int i = 0; i < num_track; i++ ) { - m_tracks.Add( new VsqTrack( mf.getMidiEventList( i ) ) ); + Track.Add( new VsqTrack( mf.getMidiEventList( i ) ) ); } - } + //} - Master = (VsqMaster)m_tracks[1].getMaster().Clone(); - Mixer = (VsqMixer)m_tracks[1].getMixer().Clone(); - m_tracks[1].setMaster( null ); - m_tracks[1].setMixer( null ); + Master = (VsqMaster)Track[1].getMaster().Clone(); + Mixer = (VsqMixer)Track[1].getMixer().Clone(); + Track[1].setMaster( null ); + Track[1].setMixer( null ); #if DEBUG System.Diagnostics.Debug.WriteLine( "VsqFile.ctor()" ); #endif int master_track = -1; - for ( int i = 0; i < m_tracks.Count; i++ ) { + for ( int i = 0; i < Track.Count; i++ ) { #if DEBUG - System.Diagnostics.Debug.WriteLine( " m_tracks[i].Name=" + m_tracks[i].Name ); + System.Diagnostics.Debug.WriteLine( " m_tracks[i].Name=" + Track[i].Name ); #endif - if ( m_tracks[i].Name == "Master Track" ) { + if ( Track[i].Name == "Master Track" ) { master_track = i; break; } @@ -1464,48 +1560,73 @@ namespace Boare.Lib.Vsq { if ( master_track >= 0 ) { #region TempoListの作成 // MIDI event リストの取得 - List midi_event = m_tracks[master_track].getTempoList(); + List midi_event = mf.getMidiEventList( master_track );//.TempoTable; // とりあえずtempo_tableに格納 - prev_tempo = midi_event[0].Data[1] << 16 | midi_event[0].Data[2] << 8 | midi_event[0].Data[3];// midi_event[0].intValue[0]; - m_base_tempo = prev_tempo; + m_base_tempo = 500000; + prev_tempo = 500000; prev_index = 0; - m_tempo_table.Add( new TempoTableEntry( (int)midi_event[0].Clock/* midi_event[0].index*/, prev_tempo, 0.0 ) ); double thistime; prev_time = 0.0; - for ( int j = 1; j < midi_event.Count; j++ ) { - int current_tempo = midi_event[j].Data[1] << 16 | midi_event[j].Data[2] << 8 | midi_event[j].Data[3]; - int current_index = (int)midi_event[j].Clock; - thistime = prev_time + (double)(prev_tempo) * (double)(current_index - prev_index) / (m_tpq * 1000000.0); - m_tempo_table.Add( new TempoTableEntry( current_index, current_tempo, thistime ) ); - prev_tempo = current_tempo; - prev_index = current_index; - prev_time = thistime; + int count = -1; + for ( int j = 0; j < midi_event.Count; j++ ) { + if ( midi_event[j].FirstByte == 0xff && midi_event[j].Data.Length >= 4 && midi_event[j].Data[0] == 0x51 ) { + count++; + if ( count == 0 && midi_event[j].Clock != 0 ) { + TempoTable.Add( new TempoTableEntry( 0, 500000, 0.0 ) ); + m_base_tempo = 500000; + prev_tempo = 500000; + } + int current_tempo = midi_event[j].Data[1] << 16 | midi_event[j].Data[2] << 8 | midi_event[j].Data[3]; + int current_index = (int)midi_event[j].Clock; + thistime = prev_time + (double)(prev_tempo) * (double)(current_index - prev_index) / (m_tpq * 1000000.0); + TempoTable.Add( new TempoTableEntry( current_index, current_tempo, thistime ) ); + prev_tempo = current_tempo; + prev_index = current_index; + prev_time = thistime; + } } - m_tempo_table.Sort(); + TempoTable.Sort(); #endregion #region TimeSigTableの作成 - List time_sigs = m_tracks[master_track].getTimeSigList(); - int dnomi = time_sigs[0].Data[1]; - int numer = 1; - for ( int i = 0; i < time_sigs[0].Data[2]; i++ ) { + //List time_sigs = mf.getMidiEventList( master_track );//].TimesigTable; + int dnomi = 4;// time_sigs[0].Data[1]; + int numer = 4; + /*for ( int i = 0; i < time_sigs[0].Data[2]; i++ ) { numer = numer * 2; - } - m_timesig_table.Add( new TimeSigTableEntry( 0, numer, dnomi, 0 ) ); - for ( int j = 1; j < time_sigs.Count; j++ ) { - int numerator = m_timesig_table[j - 1].Numerator; - int denominator = m_timesig_table[j - 1].Denominator; - int clock = m_timesig_table[j - 1].Clock; - int bar_count = m_timesig_table[j - 1].BarCount; - - int dif = 480 * 4 / denominator * numerator;//1小節が何クロックか? - bar_count += ((int)time_sigs[j].Clock - clock) / dif; - dnomi = time_sigs[j].Data[1]; - numer = 1; - for ( int i = 0; i < time_sigs[j].Data[2]; i++ ) { - numer = numer * 2; + }*/ + //m_timesig_table.Add( new TimeSigTableEntry( 0, numer, dnomi, 0 ) ); + count = -1; + for ( int j = 0; j < midi_event.Count; j++ ) { + if ( midi_event[j].FirstByte == 0xff && midi_event[j].Data.Length >= 5 && midi_event[j].Data[0] == 0x58 ) { + count++; + numer = midi_event[j].Data[1]; + dnomi = 1; + for ( int i = 0; i < midi_event[j].Data[2]; i++ ) { + dnomi = dnomi * 2; + } + if ( count == 0 ){ + int numerator = 4; + int denominator = 4; + int clock = 0; + int bar_count = 0; + if ( midi_event[j].Clock == 0 ) { + TimesigTable.Add( new TimeSigTableEntry( 0, numer, dnomi, 0 ) ); + } else { + TimesigTable.Add( new TimeSigTableEntry( 0, 4, 4, 0 ) ); + TimesigTable.Add( new TimeSigTableEntry( 0, numer, dnomi, (int)midi_event[j].Clock / (480 * 4) ) ); + count++; + } + } else { + int numerator = TimesigTable[count - 1].Numerator; + int denominator = TimesigTable[count - 1].Denominator; + int clock = TimesigTable[count - 1].Clock; + int bar_count = TimesigTable[count - 1].BarCount; + int dif = 480 * 4 / denominator * numerator;//1小節が何クロックか? + bar_count += ((int)midi_event[j].Clock - clock) / dif; + TimesigTable.Add( new TimeSigTableEntry( (int)midi_event[j].Clock, numer, dnomi, bar_count ) ); + } } - m_timesig_table.Add( new TimeSigTableEntry( (int)time_sigs[j].Clock, numer, dnomi, bar_count ) ); } #endregion } @@ -1513,7 +1634,7 @@ namespace Boare.Lib.Vsq { // 曲の長さを計算 updateTempoInfo(); updateTimesigInfo(); - m_premeasure_clocks = calculatePreMeasureInClock(); + //m_premeasure_clocks = calculatePreMeasureInClock(); updateTotalClocks(); #if DEBUG System.Diagnostics.Debug.WriteLine( " m_total_clocks=" + TotalClocks ); @@ -1527,24 +1648,24 @@ namespace Boare.Lib.Vsq { #if DEBUG Console.WriteLine( "VsqFile.UpdateTimesigInfo()" ); #endif - if ( m_timesig_table[0].Clock != 0 ) { + if ( TimesigTable[0].Clock != 0 ) { throw new ApplicationException( "initial timesig does not found" ); } - m_timesig_table[0].Clock = 0; - m_timesig_table.Sort(); - for ( int j = 1; j < m_timesig_table.Count; j++ ) { - int numerator = m_timesig_table[j - 1].Numerator; - int denominator = m_timesig_table[j - 1].Denominator; - int clock = m_timesig_table[j - 1].Clock; - int bar_count = m_timesig_table[j - 1].BarCount; + TimesigTable[0].Clock = 0; + TimesigTable.Sort(); + for ( int j = 1; j < TimesigTable.Count; j++ ) { + int numerator = TimesigTable[j - 1].Numerator; + int denominator = TimesigTable[j - 1].Denominator; + int clock = TimesigTable[j - 1].Clock; + int bar_count = TimesigTable[j - 1].BarCount; int dif = 480 * 4 / denominator * numerator;//1小節が何クロックか? - clock += (m_timesig_table[j].BarCount - bar_count) * dif; - m_timesig_table[j].Clock = clock; + clock += (TimesigTable[j].BarCount - bar_count) * dif; + TimesigTable[j].Clock = clock; } - m_premeasure_clocks = calculatePreMeasureInClock(); #if DEBUG - for ( int i = 0; i < m_timesig_table.Count; i++ ) { - Console.WriteLine( " clock=" + m_timesig_table[i].Clock + "; bar_count=" + m_timesig_table[i].BarCount + "; " + m_timesig_table[i].Numerator + "/" + m_timesig_table[i].Denominator ); + Console.WriteLine( "TimesigTable;" ); + for ( int i = 0; i < TimesigTable.Count; i++ ) { + Console.WriteLine( " " + TimesigTable[i].Clock + " " + TimesigTable[i].Numerator + "/" + TimesigTable[i].Denominator ); } #endif } @@ -1553,42 +1674,34 @@ namespace Boare.Lib.Vsq { /// TempoTableの[*].Timeの部分を更新します /// public void updateTempoInfo() { - if ( m_tempo_table.Count == 0 ) { - m_tempo_table.Add( new TempoTableEntry( 0, getBaseTempo(), 0.0 ) ); + if ( TempoTable.Count == 0 ) { + TempoTable.Add( new TempoTableEntry( 0, getBaseTempo(), 0.0 ) ); } - m_tempo_table.Sort(); - if ( m_tempo_table[0].Clock != 0 ) { - m_tempo_table[0].Time = (double)getBaseTempo() * (double)m_tempo_table[0].Clock / (getTickPerQuarter() * 1000000.0); + TempoTable.Sort(); + if ( TempoTable[0].Clock != 0 ) { + TempoTable[0].Time = (double)getBaseTempo() * (double)TempoTable[0].Clock / (getTickPerQuarter() * 1000000.0); } else { - m_tempo_table[0].Time = 0.0; + TempoTable[0].Time = 0.0; } - double prev_time = m_tempo_table[0].Time; - int prev_clock = m_tempo_table[0].Clock; - int prev_tempo = m_tempo_table[0].Tempo; + double prev_time = TempoTable[0].Time; + int prev_clock = TempoTable[0].Clock; + int prev_tempo = TempoTable[0].Tempo; double inv_tpq_sec = 1.0 / (getTickPerQuarter() * 1000000.0); - for ( int i = 1; i < m_tempo_table.Count; i++ ) { - m_tempo_table[i].Time = prev_time + (double)prev_tempo * (double)(m_tempo_table[i].Clock - prev_clock) * inv_tpq_sec; - prev_time = m_tempo_table[i].Time; - prev_tempo = m_tempo_table[i].Tempo; - prev_clock = m_tempo_table[i].Clock; + for ( int i = 1; i < TempoTable.Count; i++ ) { + TempoTable[i].Time = prev_time + (double)prev_tempo * (double)(TempoTable[i].Clock - prev_clock) * inv_tpq_sec; + prev_time = TempoTable[i].Time; + prev_tempo = TempoTable[i].Tempo; + prev_clock = TempoTable[i].Clock; } -#if DEBUG - using ( StreamWriter sw = new StreamWriter( Path.Combine( System.Windows.Forms.Application.StartupPath, "vsq_tempo_info.txt" ) ) ) { - sw.WriteLine( "Clock\tTime\tTempo" ); - for ( int i = 0; i < m_tempo_table.Count; i++ ) { - sw.WriteLine( m_tempo_table[i].Clock + "\t" + m_tempo_table[i].Time + "\t" + m_tempo_table[i].Tempo ); - } - } -#endif } /// /// VsqFile.Executeの実行直後などに、m_total_clocksの値を更新する /// public void updateTotalClocks() { - int max = m_premeasure_clocks; - for( int i = 1; i < m_tracks.Count; i++ ){ - VsqTrack track = m_tracks[i]; + int max = getPreMeasureClocks(); + for( int i = 1; i < Track.Count; i++ ){ + VsqTrack track = Track[i]; for ( Iterator itr = track.getEventIterator(); itr.hasNext(); ) { VsqEvent ve = (VsqEvent)itr.next(); max = Math.Max( max, ve.Clock + ve.ID.Length ); @@ -1621,43 +1734,108 @@ namespace Boare.Lib.Vsq { /// public void printLyricTable( int track, string fpath ) { using ( StreamWriter sw = new StreamWriter( fpath ) ) { - for ( int i = 0; i < m_tracks[track].getEventCount(); i++ ) { + for ( int i = 0; i < Track[track].getEventCount(); i++ ) { int Length; // timesignal - int time_signal = m_tracks[track].getEvent( i ).Clock; + int time_signal = Track[track].getEvent( i ).Clock; // イベントで指定されたIDがLyricであった場合 - if ( m_tracks[track].getEvent( i ).ID.type == VsqIDType.Anote ) { + if ( Track[track].getEvent( i ).ID.type == VsqIDType.Anote ) { // 発音長を取得 - Length = m_tracks[track].getEvent( i ).ID.Length; + Length = Track[track].getEvent( i ).ID.Length; // tempo_tableから、発音開始時のtempoを取得 - int last = getTempoList().Count - 1; - int tempo = getTempoList()[last].Tempo; - int prev_index = getTempoList()[last].Clock; - double prev_time = getTempoList()[last].Time; - for ( int j = 1; j < getTempoList().Count; j++ ) { - if ( getTempoList()[j].Clock > time_signal ) { - tempo = getTempoList()[j - 1].Tempo; - prev_index = getTempoList()[j - 1].Clock; - prev_time = getTempoList()[j - 1].Time; + int last = TempoTable.Count - 1; + int tempo = TempoTable[last].Tempo; + int prev_index = TempoTable[last].Clock; + double prev_time = TempoTable[last].Time; + for ( int j = 1; j < TempoTable.Count; j++ ) { + if ( TempoTable[j].Clock > time_signal ) { + tempo = TempoTable[j - 1].Tempo; + prev_index = TempoTable[j - 1].Clock; + prev_time = TempoTable[j - 1].Time; break; } } - int current_index = m_tracks[track].getEvent( i ).Clock; + int current_index = Track[track].getEvent( i ).Clock; double start_time = prev_time + (double)(current_index - prev_index) * (double)tempo / (m_tpq * 1000000.0); // TODO: 単純に + Lengthしただけではまずいはず。要検討 double end_time = start_time + ((double)Length) * ((double)tempo) / (m_tpq * 1000000.0); - sw.WriteLine( m_tracks[track].getEvent( i ).Clock + "," + + sw.WriteLine( Track[track].getEvent( i ).Clock + "," + start_time.ToString( "0.000000" ) + "," + end_time.ToString( "0.000000" ) + "," + - m_tracks[track].getEvent( i ).ID.LyricHandle.L0.Phrase + "," + - m_tracks[track].getEvent( i ).ID.LyricHandle.L0.getPhoneticSymbol() ); + Track[track].getEvent( i ).ID.LyricHandle.L0.Phrase + "," + + Track[track].getEvent( i ).ID.LyricHandle.L0.getPhoneticSymbol() ); } } } } + public List generateMetaTextEvent( int track ) { + string _NL = "" + (char)0x0a; + List ret = new List(); + using ( TextMemoryStream sr = new TextMemoryStream( FileAccess.ReadWrite ) ) { + Track[track].printMetaText( sr, TotalClocks + 120, calculatePreMeasureInClock() ); + sr.rewind(); + int line_count = -1; + string tmp = ""; + if ( sr.peek() >= 0 ) { + tmp = sr.readLine(); + char[] line_char; + string line = ""; + while ( sr.peek() >= 0 ) { + line = sr.readLine(); + tmp += _NL + line; + while ( (tmp + getLinePrefix( line_count + 1 )).Length >= 127 ) { + line_count++; + tmp = getLinePrefix( line_count ) + tmp; + string work = tmp.Substring( 0, 127 ); + tmp = tmp.Substring( 127 ); + line_char = work.ToCharArray(); + MidiEvent add = new MidiEvent(); + add.Clock = 0; + add.FirstByte = 0xff; //ステータス メタ* + add.Data = new byte[line_char.Length + 1]; + add.Data[0] = 0x01; //メタテキスト + for ( int i = 0; i < line_char.Length; i++ ) { + add.Data[i + 1] = (byte)line_char[i]; + } + ret.Add( add ); + } + } + // 残りを出力 + line_count++; + tmp = getLinePrefix( line_count ) + tmp + _NL; + while ( tmp.Length > 127 ) { + string work = tmp.Substring( 0, 127 ); + tmp = tmp.Substring( 127 ); + line_char = work.ToCharArray(); + MidiEvent add = new MidiEvent(); + add.Clock = 0; + add.FirstByte = 0xff; + add.Data = new byte[line_char.Length + 1]; + add.Data[0] = 0x01; + for ( int i = 0; i < line_char.Length; i++ ) { + add.Data[i + 1] = (byte)line_char[i]; + } + ret.Add( add ); + line_count++; + tmp = getLinePrefix( line_count ); + } + line_char = tmp.ToCharArray(); + MidiEvent add0 = new MidiEvent(); + add0.FirstByte = 0xff; + add0.Data = new byte[line_char.Length + 1]; + add0.Data[0] = 0x01; + for ( int i = 0; i < line_char.Length; i++ ) { + add0.Data[i + 1] = (byte)line_char[i]; + } + ret.Add( add0 ); + } + } + return ret; + } + private static void printTrack( VsqFile vsq, int track, FileStream fs, int msPreSend ) { #if DEBUG Console.WriteLine( "PrintTrack" ); @@ -1673,62 +1851,28 @@ namespace Boare.Lib.Vsq { writeFlexibleLengthUnsignedLong( fs, 0x00 );//デルタタイム fs.WriteByte( 0xff );//ステータスタイプ fs.WriteByte( 0x03 );//イベントタイプSequence/Track Name - byte[] seq_name = bocoree.cp932.convert( vsq.m_tracks[track].Name ); + byte[] seq_name = bocoree.cp932.convert( vsq.Track[track].Name ); writeFlexibleLengthUnsignedLong( fs, (ulong)seq_name.Length );//seq_nameの文字数 fs.Write( seq_name, 0, seq_name.Length ); + //Meta Textを準備 - using ( TextMemoryStream sr = new TextMemoryStream( FileAccess.ReadWrite ) ) { - vsq.m_tracks[track].printMetaText( sr, vsq.TotalClocks + 120, vsq.calculatePreMeasureInClock() ); - sr.rewind(); - int line_count = -1; - string tmp = ""; - if ( sr.peek() >= 0 ) { - tmp = sr.readLine(); - char[] line_char; - string line = ""; - while ( sr.peek() >= 0 ) { - line = sr.readLine(); - tmp += _NL + line; - while ( (tmp + getLinePrefix( line_count )).Length >= 127 ) { - line_count++; - tmp = getLinePrefix( line_count ) + tmp; - string work = tmp.Substring( 0, 127 ); - tmp = tmp.Substring( 127 ); - line_char = work.ToCharArray(); - writeFlexibleLengthUnsignedLong( fs, 0x00 ); - fs.WriteByte( 0xff );//ステータスタイプ - fs.WriteByte( 0x01 );//イベントタイプMeta Text - writeFlexibleLengthUnsignedLong( fs, (ulong)line_char.Length );//データ長 - writeCharArray( fs, line_char );//メタテキスト本体 - } - } - // 残りを出力 - line_count++; - tmp = getLinePrefix( line_count ) + tmp + _NL; - while ( tmp.Length > 127 ) { - string work = tmp.Substring( 0, 127 ); - tmp = tmp.Substring( 127 ); - line_char = work.ToCharArray(); - writeFlexibleLengthUnsignedLong( fs, 0x00 ); - fs.WriteByte( 0xff ); - fs.WriteByte( 0x01 ); - writeFlexibleLengthUnsignedLong( fs, (ulong)line_char.Length ); - writeCharArray( fs, line_char ); - line_count++; - tmp = getLinePrefix( line_count ); - } - line_char = tmp.ToCharArray(); - writeFlexibleLengthUnsignedLong( fs, 0x00 ); - fs.WriteByte( 0xff ); - fs.WriteByte( 0x01 ); - writeFlexibleLengthUnsignedLong( fs, (ulong)line_char.Length ); - writeCharArray( fs, line_char ); - } + List meta = vsq.generateMetaTextEvent( track ); + long lastclock = 0; + for ( int i = 0; i < meta.Count; i++ ) { + writeFlexibleLengthUnsignedLong( fs, (ulong)(meta[i].Clock - lastclock) ); + meta[i].writeData( fs ); + lastclock = meta[i].Clock; } int last = 0; VsqNrpn[] data = generateNRPN( vsq, track, msPreSend ); NrpnData[] nrpns = VsqNrpn.convert( data ); +#if DEBUG + bocoree.debug.push_log( "VsqFile.printTrack; nrpns" ); + for ( int i = 0; i < nrpns.Length; i++ ) { + bocoree.debug.push_log( " clock,parameter,value=" + nrpns[i].getClock() + "," + Convert.ToString( nrpns[i].getParameter(), 16 ) + "," + Convert.ToString( nrpns[i].Value, 16 ) ); + } +#endif for ( int i = 0; i < nrpns.Length; i++ ) { writeFlexibleLengthUnsignedLong( fs, (ulong)(nrpns[i].getClock() - last) ); fs.WriteByte( 0xb0 ); @@ -1738,7 +1882,7 @@ namespace Boare.Lib.Vsq { } //トラックエンド - VsqEvent last_event = vsq.m_tracks[track].getEvent( vsq.m_tracks[track].getEventCount() - 1 ); + VsqEvent last_event = vsq.Track[track].getEvent( vsq.Track[track].getEventCount() - 1 ); int last_clock = last_event.Clock + last_event.ID.Length; writeFlexibleLengthUnsignedLong( fs, (ulong)last_clock ); fs.WriteByte( 0xff ); @@ -1771,23 +1915,32 @@ namespace Boare.Lib.Vsq { /// public static VsqNrpn[] generateExpressionNRPN( VsqFile vsq, int track, int msPreSend ) { List ret = new List(); - int count = vsq.m_tracks[track].getCurve( "DYN" ).getCount(); - byte delay0, delay1; - getMsbAndLsb( (ushort)msPreSend, out delay0, out delay1 ); - int start_clock = (int)vsq.getClockFromSec( msPreSend / 1000.0 ) + 1; - int start_value = vsq.m_tracks[track].getCurve( "DYN" ).getElement( start_clock ); - VsqNrpn add0 = new VsqNrpn( start_clock - vsq.getPresendClockAt( start_clock, msPreSend ), - (ushort)NRPN.CC_E_VESION_AND_DEVICE, - 0x00, 0x00 ); - add0.append( NRPN.CC_E_DELAY, delay0, delay1 ); - add0.append( NRPN.CC_E_EXPRESSION, (byte)start_value ); - ret.Add( add0 ); - int[] keys = vsq.m_tracks[track].getCurve( "DYN" ).getKeys(); - for ( int i = 0; i < keys.Length; i++ ) { - if ( keys[i] > start_clock ) { - VsqNrpn add = new VsqNrpn( keys[i] - vsq.getPresendClockAt( keys[i], msPreSend ), - (ushort)NRPN.CC_E_EXPRESSION, - (byte)vsq.m_tracks[track].getCurve( "DYN" ).getElement( keys[i] ) ); + VsqBPList dyn = vsq.Track[track].getCurve( "DYN" ); + int count = dyn.getCount(); + for ( int i = 0; i < count; i++ ) { + int clock = dyn.getKeyClock( i ); + int c = clock - vsq.getPresendClockAt( clock, msPreSend ); + if ( c >= 0 ){ + VsqNrpn add = new VsqNrpn( c, + NRPN.CC_E_EXPRESSION, + (byte)dyn.getElement( i ) ); + ret.Add( add ); + } + } + return ret.ToArray(); + } + + public static VsqNrpn[] generateFx2DepthNRPN( VsqFile vsq, int track, int msPreSend ) { + List ret = new List(); + VsqBPList fx2depth = vsq.Track[track].getCurve( "fx2depth" ); + int count = fx2depth.getCount(); + for ( int i = 0; i < count; i++ ) { + int clock = fx2depth.getKeyClock( i ); + int c = clock - vsq.getPresendClockAt( clock, msPreSend ); + if ( c >= 0 ) { + VsqNrpn add = new VsqNrpn( c, + NRPN.CC_FX2_EFFECT2_DEPTH, + (byte)fx2depth.getElement( i ) ); ret.Add( add ); } } @@ -1836,7 +1989,7 @@ namespace Boare.Lib.Vsq { VsqNrpn add = new VsqNrpn( i, (ushort)NRPN.CC_BS_VERSION_AND_DEVICE, 0x00, 0x00 ); add.append( NRPN.CC_BS_DELAY, delay0, delay1 ); add.append( NRPN.CC_BS_LANGUAGE_TYPE, (byte)ve.ID.IconHandle.Language ); - add.append( NRPN.PC_VERSION_AND_DEVICE, 0x00, 0x00 ); + //add.append( NRPN.PC_VERSION_AND_DEVICE, 0x00, 0x00 ); add.append( NRPN.PC_VOICE_TYPE, (byte)ve.ID.IconHandle.Program ); return new VsqNrpn[] { add }; } @@ -1848,8 +2001,9 @@ namespace Boare.Lib.Vsq { /// /// /// - public static VsqNrpn generateNoteNRPN( VsqFile vsq, VsqEvent ve, int msPreSend, byte note_loc ) { + public static VsqNrpn generateNoteNRPN( VsqFile vsq, int track, VsqEvent ve, int msPreSend, byte note_loc, bool add_delay_sign ) { int clock = ve.Clock; + string renderer = vsq.Track[track].getCommon().Version; double clock_msec = vsq.getSecFromClock( clock ) * 1000.0; @@ -1859,11 +2013,17 @@ namespace Boare.Lib.Vsq { ushort duration = (ushort)Math.Ceiling( msEnd - clock_msec ); byte duration0, duration1; getMsbAndLsb( duration, out duration0, out duration1 ); - byte delay0, delay1; - getMsbAndLsb( (ushort)msPreSend, out delay0, out delay1 ); - VsqNrpn add = new VsqNrpn( clock - vsq.getPresendClockAt( clock, msPreSend ), (ushort)NRPN.CVM_NM_DELAY, delay0, delay1 ); - add.append( NRPN.CVM_NM_NOTE_NUMBER, (byte)ve.ID.Note ); // Note number + VsqNrpn add; + if ( add_delay_sign ) { + byte delay0, delay1; + getMsbAndLsb( (ushort)msPreSend, out delay0, out delay1 ); + add = new VsqNrpn( clock - vsq.getPresendClockAt( clock, msPreSend ), NRPN.CVM_NM_VERSION_AND_DEVICE, 0x00, 0x00 ); + add.append( NRPN.CVM_NM_DELAY, delay0, delay1 ); + add.append( NRPN.CVM_NM_NOTE_NUMBER, (byte)ve.ID.Note ); // Note number + } else { + add = new VsqNrpn( clock - vsq.getPresendClockAt( clock, msPreSend ), NRPN.CVM_NM_NOTE_NUMBER, (byte)ve.ID.Note ); // Note number + } add.append( NRPN.CVM_NM_VELOCITY, (byte)ve.ID.Dynamics ); // Velocity add.append( NRPN.CVM_NM_NOTE_DURATION, duration0, duration1 ); // Note duration add.append( NRPN.CVM_NM_NOTE_LOCATION, note_loc ); // Note Location @@ -1885,6 +2045,9 @@ namespace Boare.Lib.Vsq { s += spl[j]; } char[] symbols = s.ToCharArray(); + if ( renderer.StartsWith( "DSB2" ) ) { + add.append( 0x5011, (byte)0x01 );//TODO: 0x5011の意味は解析中 + } add.append( NRPN.CVM_NM_PHONETIC_SYMBOL_BYTES, (byte)symbols.Length );// 0x12(Number of phonetic symbols in bytes) int count = -1; for ( int j = 0; j < spl.Length; j++ ) { @@ -1892,25 +2055,116 @@ namespace Boare.Lib.Vsq { for ( int k = 0; k < chars.Length; k++ ) { count++; if ( k == 0 ) { - add.append( (NRPN)((0x50 << 8) | (byte)(0x13 + count)), (byte)chars[k], (byte)ve.ID.LyricHandle.L0.getConsonantAdjustment()[j] ); // Phonetic symbol j + add.append( (ushort)((0x50 << 8) | (byte)(0x13 + count)), (byte)chars[k], (byte)ve.ID.LyricHandle.L0.getConsonantAdjustment()[j] ); // Phonetic symbol j } else { - add.append( (NRPN)((0x50 << 8) | (byte)(0x13 + count)), (byte)chars[k] ); // Phonetic symbol j + add.append( (ushort)((0x50 << 8) | (byte)(0x13 + count)), (byte)chars[k] ); // Phonetic symbol j + } + } + } + if ( !renderer.StartsWith( "DSB2" ) ) { + add.append( NRPN.CVM_NM_PHONETIC_SYMBOL_CONTINUATION, 0x7f ); // End of phonetic symbols + } + if ( renderer.StartsWith( "DSB3" ) ) { + int v1mean = ve.ID.PMBendDepth * 60 / 100; + if ( v1mean < 0 ) { + v1mean = 0; + } + if ( 60 < v1mean ) { + v1mean = 60; + } + int d1mean = (int)(0.3196 * ve.ID.PMBendLength + 8.0); + int d2mean = (int)(0.92 * ve.ID.PMBendLength + 28.0); + add.append( NRPN.CVM_NM_V1MEAN, (byte)v1mean );// 0x50(v1mean) + add.append( NRPN.CVM_NM_D1MEAN, (byte)d1mean );// 0x51(d1mean) + add.append( NRPN.CVM_NM_D1MEAN_FIRST_NOTE, 0x14 );// 0x52(d1meanFirstNote) + add.append( NRPN.CVM_NM_D2MEAN, (byte)d2mean );// 0x53(d2mean) + add.append( NRPN.CVM_NM_D4MEAN, 0x18 );// 0x54(d4mean) + add.append( NRPN.CVM_NM_PMEAN_ONSET_FIRST_NOTE, 0x0a ); // 055(pMeanOnsetFirstNote) + add.append( NRPN.CVM_NM_VMEAN_NOTE_TRNSITION, 0x0c ); // 0x56(vMeanNoteTransition) + add.append( NRPN.CVM_NM_PMEAN_ENDING_NOTE, 0x0c );// 0x57(pMeanEndingNote) + add.append( NRPN.CVM_NM_ADD_PORTAMENTO, (byte)ve.ID.PMbPortamentoUse );// 0x58(AddScoopToUpInternals&AddPortamentoToDownIntervals) + add.append( NRPN.CVM_NM_CHANGE_AFTER_PEAK, 0x32 );// 0x59(changeAfterPeak) + byte accent = (byte)(0x64 * ve.ID.DEMaccent / 100.0); + add.append( NRPN.CVM_NM_ACCENT, accent );// 0x5a(Accent) + } + if ( renderer.StartsWith( "UTU0" ) ) { + // エンベロープ + if ( ve.UstEvent != null ) { + UstEnvelope env = null; + if ( ve.UstEvent.Envelope != null ) { + env = ve.UstEvent.Envelope; + } else { + env = new UstEnvelope(); + } + int[] vals = null; + if ( env.Separator == "" ) { + vals = new int[7]; + } else { + vals = new int[10]; + } + vals[0] = env.p1; + vals[1] = env.p2; + vals[2] = env.p3; + vals[3] = env.v1; + vals[4] = env.v2; + vals[5] = env.v3; + vals[6] = env.v4; + if ( env.Separator != "" ) { + vals[7] = env.p4; + vals[8] = env.p5; + vals[9] = env.v5; + } + for ( int i = 0; i < vals.Length; i++ ) { + //(value3.msb & 0xf) << 28 | (value2.msb & 0x7f) << 21 | (value2.lsb & 0x7f) << 14 | (value1.msb & 0x7f) << 7 | (value1.lsb & 0x7f) + byte msb, lsb; + int v = vals[i]; + lsb = (byte)(v & 0x7f); + v = v >> 7; + msb = (byte)(v & 0x7f); + v = v >> 7; + add.append( NRPN.CVM_EXNM_ENV_DATA1, msb, lsb ); + lsb = (byte)(v & 0x7f); + v = v >> 7; + msb = (byte)(v & 0x7f); + v = v >> 7; + add.append( NRPN.CVM_EXNM_ENV_DATA2, msb, lsb ); + msb = (byte)(v & 0xf); + add.append( NRPN.CVM_EXNM_ENV_DATA3, msb ); + add.append( NRPN.CVM_EXNM_ENV_DATA_CONTINUATION, 0x00 ); + } + add.append( NRPN.CVM_EXNM_ENV_DATA_CONTINUATION, 0x7f ); + + // モジュレーション + byte m, l; + if ( -100 <= ve.UstEvent.Moduration && ve.UstEvent.Moduration <= 100 ) { + getMsbAndLsb( (ushort)(ve.UstEvent.Moduration + 100), out m, out l ); + add.append( NRPN.CVM_EXNM_MODURATION, m, l ); + } + + // 先行発声 + if ( ve.UstEvent.PreUtterance != 0 ) { + getMsbAndLsb( (ushort)(ve.UstEvent.PreUtterance + 8192), out m, out l ); + add.append( NRPN.CVM_EXNM_PRE_UTTERANCE, m, l ); + } + + // Flags + if ( ve.UstEvent.Flags != "" ) { + char[] arr = ve.UstEvent.Flags.ToCharArray(); + add.append( NRPN.CVM_EXNM_FLAGS_BYTES, (byte)arr.Length ); + for ( int i = 0; i < arr.Length; i++ ) { + byte b = (byte)arr[i]; + add.append( NRPN.CVM_EXNM_FLAGS, b ); + } + add.append( NRPN.CVM_EXNM_FLAGS_CONINUATION, 0x7f ); + } + + // オーバーラップ + if ( ve.UstEvent.VoiceOverlap != 0 ) { + getMsbAndLsb( (ushort)(ve.UstEvent.VoiceOverlap + 8192), out m, out l ); + add.append( NRPN.CVM_EXNM_VOICE_OVERLAP, m, l ); } } } - add.append( NRPN.CVM_NM_PHONETIC_SYMBOL_CONTINUATION, 0x7f ); // End of phonetic symbols - add.append( NRPN.CVM_NM_V1MEAN, 0x04 );// 0x50(v1mean) - add.append( NRPN.CVM_NM_D1MEAN, 0x08 );// 0x51(d1mean) - add.append( NRPN.CVM_NM_D1MEAN_FIRST_NOTE, 0x14 );// 0x52(d1meanFirstNote) - add.append( NRPN.CVM_NM_D2MEAN, 0x1c );// 0x53(d2mean) - add.append( NRPN.CVM_NM_D4MEAN, 0x18 );// 0x54(d4mean) - add.append( NRPN.CVM_NM_PMEAN_ONSET_FIRST_NOTE, 0x0a ); // 055(pMeanOnsetFirstNote) - add.append( NRPN.CVM_NM_VMEAN_NOTE_TRNSITION, 0x0c ); // 0x56(vMeanNoteTransition) - add.append( NRPN.CVM_NM_PMEAN_ENDING_NOTE, 0x0c );// 0x57(pMeanEndingNote) - add.append( NRPN.CVM_NM_ADD_PORTAMENTO, (byte)ve.ID.PMbPortamentoUse );// 0x58(AddScoopToUpInternals&AddPortamentoToDownIntervals) - add.append( NRPN.CVM_NM_CHANGE_AFTER_PEAK, 0x32 );// 0x59(changeAfterPeak) - byte accent = (byte)(0x64 * ve.ID.DEMaccent / 100.0); - add.append( NRPN.CVM_NM_ACCENT, accent );// 0x5a(Accent) add.append( NRPN.CVM_NM_NOTE_MESSAGE_CONTINUATION, 0x7f );// 0x7f(Note message continuation) return add; } @@ -1926,12 +2180,12 @@ namespace Boare.Lib.Vsq { /// public static VsqNrpn[] generateNRPN( VsqFile vsq, int track, int msPreSend, int clock_start, int clock_end ) { VsqFile temp = (VsqFile)vsq.Clone(); - removePart( temp, clock_end, vsq.TotalClocks ); + temp.removePart( clock_end, vsq.TotalClocks ); if ( 0 < clock_start ) { - removePart( temp, 0, clock_start ); + temp.removePart( 0, clock_start ); } temp.Master.PreMeasure = 1; - temp.m_premeasure_clocks = temp.getClockFromBarCount( 1 ); + //temp.m_premeasure_clocks = temp.getClockFromBarCount( 1 ); VsqNrpn[] ret = generateNRPN( temp, track, msPreSend ); temp = null; return ret; @@ -1948,21 +2202,23 @@ namespace Boare.Lib.Vsq { #if DEBUG Console.WriteLine( "GenerateNRPN(VsqTrack,int,int,int,int)" ); #endif - List list = new List(); - int count = vsq.m_tracks[track].getEventCount(); + VsqTrack target = vsq.Track[track]; + string version = target.getCommon().Version; + + int count = target.getEventCount(); int note_start = 0; - int note_end = vsq.m_tracks[track].getEventCount() - 1; - for ( int i = 0; i < vsq.m_tracks[track].getEventCount(); i++ ) { - if ( 0 <= vsq.m_tracks[track].getEvent( i ).Clock ) { + int note_end = target.getEventCount() - 1; + for ( int i = 0; i < target.getEventCount(); i++ ) { + if ( 0 <= target.getEvent( i ).Clock ) { note_start = i; break; } note_start = i; } - for ( int i = vsq.m_tracks[track].getEventCount() - 1; i >= 0; i-- ) { - if ( vsq.m_tracks[track].getEvent( i ).Clock <= vsq.TotalClocks ) { + for ( int i = target.getEventCount() - 1; i >= 0; i-- ) { + if ( target.getEvent( i ).Clock <= vsq.TotalClocks ) { note_end = i; break; } @@ -1971,53 +2227,97 @@ namespace Boare.Lib.Vsq { // 最初の歌手を決める int singer_event = -1; for ( int i = note_start; i >= 0; i-- ) { - if ( vsq.m_tracks[track].getEvent( i ).ID.type == VsqIDType.Singer ) { + if ( target.getEvent( i ).ID.type == VsqIDType.Singer ) { singer_event = i; break; } } if ( singer_event >= 0 ) { //見つかった場合 - list.AddRange( generateSingerNRPN( vsq, vsq.m_tracks[track].getEvent( singer_event ), 0 ) ); + list.AddRange( generateSingerNRPN( vsq, target.getEvent( singer_event ), 0 ) ); } else { //多分ありえないと思うが、歌手が不明の場合。 throw new ApplicationException( "first singer was not specified" ); - list.Add( new VsqNrpn( 0, (ushort)NRPN.CC_BS_LANGUAGE_TYPE, 0 ) ); - list.Add( new VsqNrpn( 0, (ushort)NRPN.PC_VOICE_TYPE, 0 ) ); + list.Add( new VsqNrpn( 0, NRPN.CC_BS_LANGUAGE_TYPE, 0 ) ); + list.Add( new VsqNrpn( 0, NRPN.PC_VOICE_TYPE, 0 ) ); } -#if DEBUG - Console.WriteLine( " note_start,note_end=" + note_start + "," + note_end ); -#endif - for ( int i = note_start; i <= note_end; i++ ) { - byte note_loc = 0x00; - if ( i == note_start ) { - if ( i == note_end ) { - note_loc = 0x03; - } else { - note_loc = 0x01; - } - } else if ( i == note_end ) { - note_loc = 0x02; - } - if ( vsq.m_tracks[track].getEvent( i ).ID.type == VsqIDType.Anote ) { - list.Add( generateNoteNRPN( vsq, - vsq.m_tracks[track].getEvent( i ), - msPreSend, - note_loc ) ); - list.AddRange( generateVibratoNRPN( vsq, - vsq.m_tracks[track].getEvent( i ), - msPreSend ) ); - } else if ( vsq.m_tracks[track].getEvent( i ).ID.type == VsqIDType.Singer ) { - if ( i > note_start && i != singer_event) { - list.AddRange( generateSingerNRPN( vsq, vsq.m_tracks[track].getEvent( i ), msPreSend ) ); - } - } - } list.AddRange( generateVoiceChangeParameterNRPN( vsq, track, msPreSend ) ); - list.AddRange( generateExpressionNRPN( vsq, track, msPreSend ) ); - list.AddRange( generatePitchBendSensitivityNRPN( vsq, track, msPreSend ) ); - list.AddRange( generatePitchBendNRPN( vsq, track, msPreSend ) ); + if ( version.StartsWith( "DSB2" ) ) { + list.AddRange( generateFx2DepthNRPN( vsq, track, msPreSend ) ); + } - list.Sort(); + int ms_presend = msPreSend; + if ( version.StartsWith( "UTU0" ) ) { + double sec_maxlen = 0.0; + for ( Iterator itr = target.getNoteEventIterator(); itr.hasNext(); ) { + VsqEvent ve = (VsqEvent)itr.next(); + double len = vsq.getSecFromClock( ve.Clock + ve.ID.Length ) - vsq.getSecFromClock( ve.Clock ); + sec_maxlen = Math.Max( sec_maxlen, len ); + } + ms_presend += (int)(sec_maxlen * 1000.0); + } + VsqBPList dyn = target.getCurve( "dyn" ); + if ( dyn.getCount() > 0 ) { + List listdyn = new List( generateExpressionNRPN( vsq, track, ms_presend ) ); + if ( listdyn.Count > 0 ) { + list.AddRange( listdyn ); + } + } + VsqBPList pbs = target.getCurve( "pbs" ); + if ( pbs.getCount() > 0 ) { + List listpbs = new List( generatePitchBendSensitivityNRPN( vsq, track, ms_presend ) ); + if ( listpbs.Count > 0 ) { + list.AddRange( listpbs ); + } + } + VsqBPList pit = target.getCurve( "pit" ); + if ( pit.getCount() > 0 ) { + List listpit = new List( generatePitchBendNRPN( vsq, track, ms_presend ) ); + if ( listpit.Count > 0 ) { + list.AddRange( listpit ); + } + } + + bool first = true; + int last_note_end = 0; + for ( int i = note_start; i <= note_end; i++ ) { + VsqEvent item = target.getEvent( i ); + if ( item.ID.type == VsqIDType.Anote ) { + byte note_loc = 0x03; + if ( item.Clock == last_note_end ) { + note_loc -= 0x02; + } + + // 次に現れる音符イベントを探す + int nextclock = item.Clock + item.ID.Length + 1; + for ( int j = i + 1; j < target.getEventCount(); j++ ) { + if ( target.getEvent( j ).ID.type == VsqIDType.Anote ) { + nextclock = target.getEvent( j ).Clock; + break; + } + } + if ( item.Clock + item.ID.Length == nextclock ) { + note_loc -= 0x01; + } + + list.Add( generateNoteNRPN( vsq, + track, + item, + msPreSend, + note_loc, + first ) ); + first = false; + list.AddRange( generateVibratoNRPN( vsq, + item, + msPreSend ) ); + last_note_end = item.Clock + item.ID.Length; + } else if ( item.ID.type == VsqIDType.Singer ) { + if ( i > note_start && i != singer_event ) { + list.AddRange( generateSingerNRPN( vsq, item, msPreSend ) ); + } + } + } + + list = VsqNrpn.sort( list ); List merged = new List(); for ( int i = 0; i < list.Count; i++ ) { merged.AddRange( list[i].expand() ); @@ -2034,30 +2334,17 @@ namespace Boare.Lib.Vsq { /// public static VsqNrpn[] generatePitchBendNRPN( VsqFile vsq, int track, int msPreSend ) { List ret = new List(); - int[] keys = vsq.m_tracks[track].getCurve( "PIT" ).getKeys(); - int count = keys.Length; - byte delay0, delay1; - getMsbAndLsb( (ushort)msPreSend, out delay0, out delay1 ); - int start_clock = (int)vsq.getClockFromSec( msPreSend / 1000.0 ) + 1;// 0 < vsq.m_premeasure_clocks ? vsq.m_premeasure_clocks : 0; - VsqNrpn add0 = new VsqNrpn( start_clock - vsq.getPresendClockAt( start_clock, msPreSend ), - (ushort)NRPN.PB_VERSION_AND_DEVICE, - 0x00, - 0x00 ); - add0.append( NRPN.PB_DELAY, delay0, delay1 ); - - ushort start_value = (ushort)(vsq.m_tracks[track].getCurve( "PIT" ).getElement( start_clock ) + 0x2000); - byte start_value0, start_value1; - getMsbAndLsb( start_value, out start_value0, out start_value1 ); - add0.append( NRPN.PB_PITCH_BEND, start_value0, start_value1 ); - ret.Add( add0 ); - - for ( int i = 0; i < keys.Length; i++ ) { - if ( keys[i] > start_clock ) { - ushort value = (ushort)(vsq.m_tracks[track].getCurve( "PIT" ).getElement( keys[i] ) + 0x2000); - byte value0, value1; - getMsbAndLsb( value, out value0, out value1 ); - VsqNrpn add = new VsqNrpn( keys[i] - vsq.getPresendClockAt( keys[i], msPreSend ), - (ushort)NRPN.PB_PITCH_BEND, + VsqBPList pit = vsq.Track[track].getCurve( "PIT" ); + int count = pit.getCount(); + for ( int i = 0; i < count; i++ ) { + int clock = pit.getKeyClock( i ); + ushort value = (ushort)(pit.getElement( i ) + 0x2000); + byte value0, value1; + getMsbAndLsb( value, out value0, out value1 ); + int c = clock - vsq.getPresendClockAt( clock, msPreSend ); + if ( c >= 0 ) { + VsqNrpn add = new VsqNrpn( c, + NRPN.PB_PITCH_BEND, value0, value1 ); ret.Add( add ); @@ -2075,24 +2362,15 @@ namespace Boare.Lib.Vsq { /// public static VsqNrpn[] generatePitchBendSensitivityNRPN( VsqFile vsq, int track, int msPreSend ) { List ret = new List(); - int[] keys = vsq.m_tracks[track].getCurve( "PBS" ).getKeys(); - int count = keys.Length; - byte delay0, delay1; - getMsbAndLsb( (ushort)msPreSend, out delay0, out delay1 ); - int start_clock = (int)vsq.getClockFromSec( msPreSend / 1000.0 ) + 1;// 0 < vsq.m_premeasure_clocks ? vsq.m_premeasure_clocks : 0; - int start_value = vsq.m_tracks[track].getCurve( "PBS" ).getElement( start_clock ); - VsqNrpn add0 = new VsqNrpn( start_clock - vsq.getPresendClockAt( start_clock, msPreSend ), - (ushort)NRPN.CC_PBS_VERSION_AND_DEVICE, - 0x00, - 0x00 ); - add0.append( NRPN.CC_PBS_DELAY, delay0, delay1 ); - add0.append( NRPN.CC_PBS_PITCH_BEND_SENSITIVITY, (byte)start_value, 0x00 ); - ret.Add( add0 ); - for ( int i = 0; i < keys.Length; i++ ) { - if ( keys[i] > start_clock ) { - VsqNrpn add = new VsqNrpn( keys[i] - vsq.getPresendClockAt( keys[i], msPreSend ), - (ushort)NRPN.CC_PBS_PITCH_BEND_SENSITIVITY, - (byte)vsq.m_tracks[track].getCurve( "PBS" ).getElement( keys[i] ), + VsqBPList pbs = vsq.Track[track].getCurve( "PBS" ); + int count = pbs.getCount(); + for ( int i = 0; i < count; i++ ) { + int clock = pbs.getKeyClock( i ); + int c = clock - vsq.getPresendClockAt( clock, msPreSend ); + if ( c >= 0 ) { + VsqNrpn add = new VsqNrpn( c, + NRPN.CC_PBS_PITCH_BEND_SENSITIVITY, + (byte)pbs.getElement( i ), 0x00 ); ret.Add( add ); } @@ -2114,26 +2392,26 @@ namespace Boare.Lib.Vsq { byte delay0, delay1; getMsbAndLsb( (ushort)msPreSend, out delay0, out delay1 ); VsqNrpn add2 = new VsqNrpn( vclock - vsq.getPresendClockAt( vclock, msPreSend ), - (ushort)NRPN.CC_VD_VERSION_AND_DEVICE, + NRPN.CC_VD_VERSION_AND_DEVICE, 0x00, 0x00 ); add2.append( NRPN.CC_VD_DELAY, delay0, delay1 ); add2.append( NRPN.CC_VD_VIBRATO_DEPTH, (byte)ve.ID.VibratoHandle.StartDepth ); add2.append( NRPN.CC_VR_VIBRATO_RATE, (byte)ve.ID.VibratoHandle.StartRate ); ret.Add( add2 ); - int vlength = ve.Clock + ve.ID.Length - ve.ID.VibratoDelay; + int vlength = ve.ID.Length - ve.ID.VibratoDelay; if ( ve.ID.VibratoHandle.RateBP.getCount() > 0 ) { for ( int i = 0; i < ve.ID.VibratoHandle.RateBP.getCount(); i++ ) { float percent = ve.ID.VibratoHandle.RateBP.getElement( i ).X; int cl = vclock + (int)(percent * vlength); - ret.Add( new VsqNrpn( cl, (ushort)NRPN.CC_VR_VIBRATO_RATE, (byte)ve.ID.VibratoHandle.RateBP.getElement( i ).Y ) ); + ret.Add( new VsqNrpn( cl - vsq.getPresendClockAt( cl, msPreSend ), NRPN.CC_VR_VIBRATO_RATE, (byte)ve.ID.VibratoHandle.RateBP.getElement( i ).Y ) ); } } if ( ve.ID.VibratoHandle.DepthBP.getCount() > 0 ) { for ( int i = 0; i < ve.ID.VibratoHandle.DepthBP.getCount(); i++ ) { float percent = ve.ID.VibratoHandle.DepthBP.getElement( i ).X; int cl = vclock + (int)(percent * vlength); - ret.Add( new VsqNrpn( cl, (ushort)NRPN.CC_VD_VIBRATO_DEPTH, (byte)ve.ID.VibratoHandle.DepthBP.getElement( i ).Y ) ); + ret.Add( new VsqNrpn( cl - vsq.getPresendClockAt( cl, msPreSend ), NRPN.CC_VD_VIBRATO_DEPTH, (byte)ve.ID.VibratoHandle.DepthBP.getElement( i ).Y ) ); } } } @@ -2149,75 +2427,42 @@ namespace Boare.Lib.Vsq { /// /// public static VsqNrpn[] generateVoiceChangeParameterNRPN( VsqFile vsq, int track, int msPreSend ) { - int premeasure_clock = vsq.m_premeasure_clocks; - byte delay0, delay1; - getMsbAndLsb( (ushort)msPreSend, out delay0, out delay1 ); + int premeasure_clock = vsq.getPreMeasureClocks(); + string renderer = vsq.Track[track].getCommon().Version; List res = new List(); - int start_clock = (0 < premeasure_clock) ? premeasure_clock : 0; - VsqNrpn ret = new VsqNrpn( start_clock - vsq.getPresendClockAt( start_clock, msPreSend ), - (ushort)NRPN.VCP_VERSION_AND_DEVICE, - 0x00, - 0x00 ); - ret.append( NRPN.VCP_DELAY, delay0, delay1 ); // Voice Change Parameter delay - ret.append( NRPN.VCP_VOICE_CHANGE_PARAMETER_ID, 0x31 ); // BRE - ret.append( NRPN.VCP_VOICE_CHANGE_PARAMETER, (byte)vsq.m_tracks[track].getCurve( "BRE" ).getElement( start_clock ) ); + string[] curves; + if ( renderer.StartsWith( "DSB3" ) ) { + curves = new string[] { "BRE", "BRI", "CLE", "POR", "OPE", "GEN" }; + } else if ( renderer.StartsWith( "DSB2" ) ) { + curves = new string[] { "BRE", "BRI", "CLE", "POR", "GEN", "harmonics", + "reso1amp", "reso1bw", "reso1freq", + "reso2amp", "reso2bw", "reso2freq", + "reso3amp", "reso3bw", "reso3freq", + "reso4amp", "reso4bw", "reso4freq" }; + } else { + curves = new string[] { "BRE", "BRI", "CLE", "POR", "GEN" }; + } - ret.append( NRPN.VCP_VOICE_CHANGE_PARAMETER_ID, 0x32 ); // BRI - ret.append( NRPN.VCP_VOICE_CHANGE_PARAMETER, (byte)vsq.m_tracks[track].getCurve( "BRI" ).getElement( start_clock ) ); - - ret.append( NRPN.VCP_VOICE_CHANGE_PARAMETER_ID, 0x33 ); // CLE - ret.append( NRPN.VCP_VOICE_CHANGE_PARAMETER, (byte)vsq.m_tracks[track].getCurve( "CLE" ).getElement( start_clock ) ); - - ret.append( NRPN.VCP_VOICE_CHANGE_PARAMETER_ID, 0x34 ); // POR - ret.append( NRPN.VCP_VOICE_CHANGE_PARAMETER, (byte)vsq.m_tracks[track].getCurve( "POR" ).getElement( start_clock ) ); - - ret.append( NRPN.VCP_VOICE_CHANGE_PARAMETER_ID, 0x35 ); // OPE - ret.append( NRPN.VCP_VOICE_CHANGE_PARAMETER, (byte)vsq.m_tracks[track].getCurve( "OPE" ).getElement( start_clock ) ); - - ret.append( NRPN.VCP_VOICE_CHANGE_PARAMETER_ID, 0x70 ); // GEN - ret.append( NRPN.VCP_VOICE_CHANGE_PARAMETER, (byte)vsq.m_tracks[track].getCurve( "GEN" ).getElement( start_clock ) ); - res.Add( ret ); - - foreach ( string vct in _CURVES ) { - byte lsb = 0x31; - switch ( vct ) { - case "DYN": - case "PBS": - case "PIT": - case "VEL": - continue; - case "BRE": - lsb = 0x31; - break; - case "BRI": - lsb = 0x32; - break; - case "CLE": - lsb = 0x33; - break; - case "POR": - lsb = 0x34; - break; - case "OPE": - lsb = 0x35; - break; - case "GEN": - lsb = 0x70; - break; - } - int[] keys = vsq.m_tracks[track].getCurve( vct ).getKeys(); - for ( int i = 0; i < keys.Length; i++ ) { - if ( keys[i] > start_clock ) { - VsqNrpn add = new VsqNrpn( keys[i] - vsq.getPresendClockAt( keys[i], msPreSend ), - (ushort)NRPN.VCP_VOICE_CHANGE_PARAMETER_ID, - lsb ); - add.append( NRPN.VCP_VOICE_CHANGE_PARAMETER, (byte)vsq.m_tracks[track].getCurve( vct ).getElement( keys[i] ) ); - res.Add( add ); + for ( int i = 0; i < curves.Length; i++ ) { + VsqBPList vbpl = vsq.Track[track].getCurve( curves[i] ); + if ( vbpl.getCount() > 0 ) { + byte lsb = NRPN.getVoiceChangeParameterID( curves[i] ); + int count = vbpl.getCount(); + for ( int j = 0; j < count; j++ ) { + int clock = vbpl.getKeyClock( j ); + int c = clock - vsq.getPresendClockAt( clock, msPreSend ); + if ( c >= 0 ){ + VsqNrpn add = new VsqNrpn( c, + NRPN.VCP_VOICE_CHANGE_PARAMETER_ID, + lsb ); + add.append( NRPN.VCP_VOICE_CHANGE_PARAMETER, (byte)vbpl.getElement( j ) ); + res.Add( add ); + } } } } - + res.Sort(); return res.ToArray(); } @@ -2226,11 +2471,29 @@ namespace Boare.Lib.Vsq { lsb = (byte)(value - (msb << 7)); } + public List generateTimeSig() { + List events = new List(); + foreach ( TimeSigTableEntry entry in TimesigTable ) { + events.Add( MidiEvent.generateTimeSigEvent( entry.Clock, entry.Numerator, entry.Denominator ) ); + //last_clock = Math.Max( last_clock, entry.Clock ); + } + return events; + } + + public List generateTempoChange() { + List events = new List(); + foreach ( TempoTableEntry entry in TempoTable ) { + events.Add( MidiEvent.generateTempoChangeEvent( entry.Clock, entry.Tempo ) ); + //last_clock = Math.Max( last_clock, entry.Clock ); + } + return events; + } + /// /// このインスタンスをファイルに出力します /// /// - public void write( string file ) { + public virtual void write( string file ) { write( file, 500 ); } @@ -2239,15 +2502,15 @@ namespace Boare.Lib.Vsq { /// /// /// プリセンドタイム(msec) - public void write( string file, int msPreSend ) { + public virtual void write( string file, int msPreSend ) { #if DEBUG Console.WriteLine( "VsqFile.Write(string)" ); #endif int last_clock = 0; - for ( int track = 1; track < m_tracks.Count; track++ ) { - if ( m_tracks[track].getEventCount() > 0 ) { - int index = m_tracks[track].getEventCount() - 1; - VsqEvent last = m_tracks[track].getEvent( index ); + for ( int track = 1; track < Track.Count; track++ ) { + if ( Track[track].getEventCount() > 0 ) { + int index = Track[track].getEventCount() - 1; + VsqEvent last = Track[track].getEvent( index ); last_clock = Math.Max( last_clock, last.Clock + last.ID.Length ); } } @@ -2267,7 +2530,7 @@ namespace Boare.Lib.Vsq { fs.WriteByte( 0x00 ); fs.WriteByte( 0x01 ); //トラック数 - writeUnsignedShort( fs, (ushort)this.m_tracks.Count ); + writeUnsignedShort( fs, (ushort)this.Track.Count ); //時間単位 fs.WriteByte( 0x01 ); fs.WriteByte( 0xe0 ); @@ -2287,11 +2550,11 @@ namespace Boare.Lib.Vsq { fs.Write( _MASTER_TRACK, 0, _MASTER_TRACK.Length ); List events = new List(); - foreach ( TimeSigTableEntry entry in m_timesig_table ) { + foreach ( TimeSigTableEntry entry in TimesigTable ) { events.Add( MidiEvent.generateTimeSigEvent( entry.Clock, entry.Numerator, entry.Denominator ) ); last_clock = Math.Max( last_clock, entry.Clock ); } - foreach ( TempoTableEntry entry in m_tempo_table ) { + foreach ( TempoTableEntry entry in TempoTable ) { events.Add( MidiEvent.generateTempoChangeEvent( entry.Clock, entry.Tempo ) ); last_clock = Math.Max( last_clock, entry.Clock ); } @@ -2322,10 +2585,10 @@ namespace Boare.Lib.Vsq { #region トラック VsqFile temp = (VsqFile)this.Clone(); - temp.m_tracks[1].setMaster( (VsqMaster)Master.Clone() ); - temp.m_tracks[1].setMixer( (VsqMixer)Mixer.Clone() ); + temp.Track[1].setMaster( (VsqMaster)Master.Clone() ); + temp.Track[1].setMixer( (VsqMixer)Mixer.Clone() ); printTrack( temp, 1, fs, msPreSend ); - for ( int track = 2; track < m_tracks.Count; track++ ) { + for ( int track = 2; track < Track.Count; track++ ) { printTrack( this, track, fs, msPreSend ); } #endregion @@ -2386,7 +2649,7 @@ namespace Boare.Lib.Vsq { /// ushort値をビッグエンディアンでfsに書き込みます /// /// - public void writeUnsignedShort( FileStream fs, ushort data ) { + public static void writeUnsignedShort( FileStream fs, ushort data ) { byte[] dat = BitConverter.GetBytes( data ); if ( BitConverter.IsLittleEndian ) { Array.Reverse( dat ); diff --git a/trunk/Boare.Lib.Vsq/VsqMetaText/Common.cs b/trunk/Boare.Lib.Vsq/VsqMetaText/Common.cs index da580ba..f06caa7 100644 --- a/trunk/Boare.Lib.Vsq/VsqMetaText/Common.cs +++ b/trunk/Boare.Lib.Vsq/VsqMetaText/Common.cs @@ -56,6 +56,10 @@ namespace Boare.Lib.Vsq { this.PlayMode = play_mode; } + public VsqCommon() + : this( "Miku", System.Drawing.Color.FromArgb( 179, 181, 123 ), 1, 1 ) { + } + /// /// MetaTextのテキストファイルからのコンストラクタ /// diff --git a/trunk/Boare.Lib.Vsq/VsqMetaText/Handle.cs b/trunk/Boare.Lib.Vsq/VsqMetaText/Handle.cs index f7c0f04..7c25b3b 100644 --- a/trunk/Boare.Lib.Vsq/VsqMetaText/Handle.cs +++ b/trunk/Boare.Lib.Vsq/VsqMetaText/Handle.cs @@ -29,6 +29,9 @@ namespace Boare.Lib.Vsq { public int Program; public int Language; + public IconHandle() { + } + public object Clone() { IconHandle ret = new IconHandle(); ret.Caption = Caption; @@ -61,7 +64,7 @@ namespace Boare.Lib.Vsq { public Lyric L0; public int Index; - internal LyricHandle() { + public LyricHandle() { } /// @@ -104,6 +107,8 @@ namespace Boare.Lib.Vsq { public int Length; public VibratoHandle(){ + StartRate = 64; + StartDepth = 64; RateBP = new VibratoBPList(); DepthBP = new VibratoBPList(); } @@ -140,8 +145,50 @@ namespace Boare.Lib.Vsq { } } + [Serializable] + public class NoteHeadHandle : ICloneable { + public int Index; + public string IconID; + public string IDS; + public int Original; + public string Caption; + public int Length; + public int Duration; + public int Depth; + + public NoteHeadHandle() { + } + + public object Clone() { + NoteHeadHandle result = new NoteHeadHandle(); + result.Index = Index; + result.IconID = IconID; + result.IDS = this.IDS; + result.Original = this.Original; + result.Caption = this.Caption; + result.Length = this.Length; + result.Duration = Duration; + result.Depth = Depth; + return result; + } + + public VsqHandle castToVsqHandle() { + VsqHandle ret = new VsqHandle(); + ret.m_type = VsqHandleType.NoteHeadHandle; + ret.Index = Index; + ret.IconID = IconID; + ret.IDS = IDS; + ret.Original = Original; + ret.Caption = Caption; + ret.Length = Length; + ret.Duration = Duration; + ret.Depth = Depth; + return ret; + } + } + /// - /// ハンドルを取り扱います。ハンドルにはLyricHandle、VibratoHandleおよびIconHandleがある + /// ハンドルを取り扱います。ハンドルにはLyricHandle、VibratoHandle、IconHandleおよびNoteHeadHandleがある /// [Serializable] public class VsqHandle { @@ -159,6 +206,8 @@ namespace Boare.Lib.Vsq { public VibratoBPList RateBP; public int Language; public int Program; + public int Duration; + public int Depth; public LyricHandle castToLyricHandle() { LyricHandle ret = new LyricHandle(); @@ -197,6 +246,18 @@ namespace Boare.Lib.Vsq { return ret; } + public NoteHeadHandle castToNoteHeadHandle() { + NoteHeadHandle ret = new NoteHeadHandle(); + ret.Caption = Caption; + ret.Depth = Depth; + ret.Duration = Duration; + ret.IconID = IconID; + ret.IDS = IDS; + ret.Length = Length; + ret.Original = Original; + return ret; + } + internal VsqHandle() { } @@ -235,6 +296,8 @@ namespace Boare.Lib.Vsq { int rate_bp_num = 0; Language = 0; Program = 0; + Duration = 0; + Depth = 64; string tmpDepthBPX = ""; string tmpDepthBPY = ""; @@ -247,6 +310,7 @@ namespace Boare.Lib.Vsq { spl = last_line.Split( new char[] { '=' } ); switch ( spl[0] ) { case "Language": + m_type = VsqHandleType.Singer; Language = int.Parse( spl[1] ); break; case "Program": @@ -283,6 +347,7 @@ namespace Boare.Lib.Vsq { tmpDepthBPY = spl[1]; break; case "StartRate": + m_type = VsqHandleType.Vibrato; StartRate = int.Parse( spl[1] ); break; case "RateBPNum": @@ -298,19 +363,26 @@ namespace Boare.Lib.Vsq { m_type = VsqHandleType.Lyric; L0 = new Lyric( spl[1] ); break; + case "Duration": + m_type = VsqHandleType.NoteHeadHandle; + Duration = int.Parse( spl[1] ); + break; + case "Depth": + Duration = int.Parse( spl[1] ); + break; } if ( sr.peek() < 0 ) { break; } last_line = sr.readLine(); } - if ( IDS != "normal" ) { + /*if ( IDS != "normal" ) { m_type = VsqHandleType.Singer; } else if ( IconID != "" ) { m_type = VsqHandleType.Vibrato; } else { m_type = VsqHandleType.Lyric; - } + }*/ // RateBPX, RateBPYの設定 if ( m_type == VsqHandleType.Vibrato ) { @@ -438,6 +510,15 @@ namespace Boare.Lib.Vsq { result += "Language=" + Language + Environment.NewLine; result += "Program=" + Program; break; + case VsqHandleType.NoteHeadHandle: + result += Environment.NewLine + "IconID=" + IconID + Environment.NewLine; + result += "IDS=" + IDS + Environment.NewLine; + result += "Original=" + Original + Environment.NewLine; + result += "Caption=" + Caption + Environment.NewLine; + result += "Length=" + Length + Environment.NewLine; + result += "Duration=" + Duration + Environment.NewLine; + result += "Depth=" + Depth; + break; default: break; } diff --git a/trunk/Boare.Lib.Vsq/VsqMetaText/ID.cs b/trunk/Boare.Lib.Vsq/VsqMetaText/ID.cs index 700395c..5b9f171 100644 --- a/trunk/Boare.Lib.Vsq/VsqMetaText/ID.cs +++ b/trunk/Boare.Lib.Vsq/VsqMetaText/ID.cs @@ -23,9 +23,9 @@ namespace Boare.Lib.Vsq { /// [Serializable] public class VsqID : ICloneable { - public int value; + internal int value; public VsqIDType type; - public int IconHandle_index; + internal int IconHandle_index; public IconHandle IconHandle; public int Length; public int Note; @@ -35,11 +35,13 @@ namespace Boare.Lib.Vsq { public int PMbPortamentoUse; public int DEMdecGainRate; public int DEMaccent; - public int LyricHandle_index; + internal int LyricHandle_index; public LyricHandle LyricHandle; - public int VibratoHandle_index; + internal int VibratoHandle_index; public VibratoHandle VibratoHandle; public int VibratoDelay; + internal int NoteHeadHandle_index; + public NoteHeadHandle NoteHeadHandle; public static VsqID EOS = new VsqID( -1 ); @@ -68,6 +70,9 @@ namespace Boare.Lib.Vsq { result.VibratoHandle = (VibratoHandle)this.VibratoHandle.Clone(); } result.VibratoDelay = this.VibratoDelay; + if ( NoteHeadHandle != null ) { + result.NoteHeadHandle = (NoteHeadHandle)NoteHeadHandle.Clone(); + } return result; } @@ -80,6 +85,9 @@ namespace Boare.Lib.Vsq { value = a_value; } + public VsqID() + : this( 0 ) { + } /// /// テキストファイルからのコンストラクタ @@ -94,6 +102,7 @@ namespace Boare.Lib.Vsq { this.IconHandle_index = -2; this.LyricHandle_index = -1; this.VibratoHandle_index = -1; + this.NoteHeadHandle_index = -1; this.Length = 0; this.Note = 0; this.Dynamics = 0; @@ -154,6 +163,10 @@ namespace Boare.Lib.Vsq { case "PMbPortamentoUse": PMbPortamentoUse = int.Parse( spl[1] ); break; + case "NoteHeadHandle": + NoteHeadHandle_index = VsqHandle.HandleIndexFromString( spl[1] ); + break; + } if ( sr.peek() < 0 ) { break; @@ -162,7 +175,6 @@ namespace Boare.Lib.Vsq { } } - public override string ToString() { string ret = "{Type=" + type; switch ( type ) { @@ -191,7 +203,6 @@ namespace Boare.Lib.Vsq { return ret; } - /// /// インスタンスをテキストファイルに出力します /// @@ -216,6 +227,9 @@ namespace Boare.Lib.Vsq { sw.writeLine( "VibratoHandle=h#" + VibratoHandle_index.ToString( "0000" ) ); sw.writeLine( "VibratoDelay=" + VibratoDelay ); } + if ( NoteHeadHandle != null ) { + sw.writeLine( "NoteHeadHandle=h#" + NoteHeadHandle_index.ToString( "0000" ) ); + } break; case VsqIDType.Singer: sw.writeLine( "IconHandle=h#" + IconHandle_index.ToString( "0000" ) ); diff --git a/trunk/Boare.Lib.Vsq/VsqMetaText/Lyric.cs b/trunk/Boare.Lib.Vsq/VsqMetaText/Lyric.cs index 5c72a74..d345c32 100644 --- a/trunk/Boare.Lib.Vsq/VsqMetaText/Lyric.cs +++ b/trunk/Boare.Lib.Vsq/VsqMetaText/Lyric.cs @@ -64,7 +64,7 @@ namespace Boare.Lib.Vsq { UnknownFloat = 0.000000f; } - private Lyric() { + public Lyric() { } /// @@ -97,6 +97,18 @@ namespace Boare.Lib.Vsq { } } + /// + /// XMLシリアライズ用 + /// + public string PhoneticSymbol { + get { + return getPhoneticSymbol(); + } + set { + setPhoneticSymbol( value ); + } + } + public string[] getPhoneticSymbolList() { string[] ret = new string[m_phonetic_symbol.Length]; for ( int i = 0; i < m_phonetic_symbol.Length; i++ ) { diff --git a/trunk/Boare.Lib.Vsq/VsqMetaText/Master.cs b/trunk/Boare.Lib.Vsq/VsqMetaText/Master.cs index e0aaf1f..657bee5 100644 --- a/trunk/Boare.Lib.Vsq/VsqMetaText/Master.cs +++ b/trunk/Boare.Lib.Vsq/VsqMetaText/Master.cs @@ -12,9 +12,8 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ using System; -using System.Collections.Generic; -using System.Text; using System.IO; +using System.Text; namespace Boare.Lib.Vsq { @@ -30,6 +29,10 @@ namespace Boare.Lib.Vsq { return res; } + public VsqMaster() + : this( 1 ) { + } + /// /// プリメジャー値を指定したコンストラクタ /// diff --git a/trunk/Boare.Lib.Vsq/VsqMetaText/Mixer.cs b/trunk/Boare.Lib.Vsq/VsqMetaText/Mixer.cs index 827e959..bc64d1c 100644 --- a/trunk/Boare.Lib.Vsq/VsqMetaText/Mixer.cs +++ b/trunk/Boare.Lib.Vsq/VsqMetaText/Mixer.cs @@ -13,8 +13,8 @@ */ using System; using System.Collections.Generic; -using System.Text; using System.IO; +using System.Text; namespace Boare.Lib.Vsq { @@ -57,6 +57,10 @@ namespace Boare.Lib.Vsq { Slave = new List(); } + public VsqMixer() + : this( 0, 0, 0, 0 ) { + } + /// /// テキストファイルからのコンストラクタ /// @@ -261,6 +265,10 @@ namespace Boare.Lib.Vsq { this.Mute = mute; this.Solo = solo; } + + public VsqMixerEntry() + : this( 0, 0, 0, 0 ) { + } } } diff --git a/trunk/Boare.Lib.Vsq/VsqMetaText/VsqMetaText.cs b/trunk/Boare.Lib.Vsq/VsqMetaText/VsqMetaText.cs index 67ecfa3..57362fd 100644 --- a/trunk/Boare.Lib.Vsq/VsqMetaText/VsqMetaText.cs +++ b/trunk/Boare.Lib.Vsq/VsqMetaText/VsqMetaText.cs @@ -13,10 +13,9 @@ */ using System; using System.Collections.Generic; -using System.Text; -using System.IO; using System.Drawing; -using System.Windows.Forms; +using System.IO; +using System.Text; namespace Boare.Lib.Vsq { @@ -26,9 +25,9 @@ namespace Boare.Lib.Vsq { [Serializable] public class VsqMetaText : ICloneable { public VsqCommon Common; - internal VsqMaster master; - internal VsqMixer mixer; - private VsqEventList m_events; + public VsqMaster master; + public VsqMixer mixer; + public VsqEventList Events; /// /// PIT。ピッチベンド(pitchBendBPList)。default=0 /// @@ -53,18 +52,26 @@ namespace Boare.Lib.Vsq { /// 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; + public VsqBPList reso1FreqBPList; + public VsqBPList reso2FreqBPList; + public VsqBPList reso3FreqBPList; + public VsqBPList reso4FreqBPList; + public VsqBPList reso1BWBPList; + public VsqBPList reso2BWBPList; + public VsqBPList reso3BWBPList; + public VsqBPList reso4BWBPList; + public VsqBPList reso1AmpBPList; + public VsqBPList reso2AmpBPList; + public VsqBPList reso3AmpBPList; + public VsqBPList reso4AmpBPList; + /// + /// Harmonics。(EpRSineBPList)default = 64 + /// + public VsqBPList harmonics; + /// + /// Effect2 Depth。 + /// + public VsqBPList fx2depth; /// /// GEN。ジェンダーファクター(genderFactorBPList)。default=64 /// @@ -89,10 +96,10 @@ namespace Boare.Lib.Vsq { 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 ( Events != null ) { + res.Events = new VsqEventList(); + for ( Iterator itr = Events.iterator(); itr.hasNext(); ) { + res.Events.add( (VsqEvent)((VsqEvent)itr.next()).Clone() ); } } if ( PIT != null ) { @@ -149,6 +156,12 @@ namespace Boare.Lib.Vsq { if ( reso4AmpBPList != null ) { res.reso4AmpBPList = (VsqBPList)reso4AmpBPList.Clone(); } + if ( harmonics != null ) { + res.harmonics = (VsqBPList)harmonics.Clone(); + } + if ( fx2depth != null ) { + res.fx2depth = (VsqBPList)fx2depth.Clone(); + } if ( GEN != null ) { res.GEN = (VsqBPList)GEN.Clone(); } @@ -162,7 +175,7 @@ namespace Boare.Lib.Vsq { } public VsqEventList getEventList() { - return m_events; + return Events; } internal VsqBPList getElement( string curve ) { @@ -185,6 +198,34 @@ namespace Boare.Lib.Vsq { return this.PIT; case "por": return this.POR; + case "harmonics": + return this.harmonics; + case "fx2depth": + return this.fx2depth; + case "reso1amp": + return this.reso1AmpBPList; + case "reso1bw": + return this.reso1BWBPList; + case "reso1freq": + return this.reso1FreqBPList; + case "reso2amp": + return this.reso2AmpBPList; + case "reso2bw": + return this.reso2BWBPList; + case "reso2freq": + return this.reso2FreqBPList; + case "reso3amp": + return this.reso2AmpBPList; + case "reso3bw": + return this.reso3BWBPList; + case "reso3freq": + return this.reso3FreqBPList; + case "reso4amp": + return this.reso4AmpBPList; + case "reso4bw": + return this.reso4BWBPList; + case "reso4freq": + return this.reso4FreqBPList; default: return null; } @@ -289,7 +330,7 @@ namespace Boare.Lib.Vsq { /// Singerプロパティに指定されている /// public string getSinger() { - for ( Iterator itr = m_events.iterator(); itr.hasNext(); ) { + for ( Iterator itr = Events.iterator(); itr.hasNext(); ) { VsqEvent item = (VsqEvent)itr.next(); if ( item.ID.type == VsqIDType.Singer ) { return item.ID.IconHandle.IDS; @@ -299,7 +340,7 @@ namespace Boare.Lib.Vsq { } public void setSinger( string value ) { - for ( Iterator itr = m_events.iterator(); itr.hasNext(); ) { + for ( Iterator itr = Events.iterator(); itr.hasNext(); ) { VsqEvent item = (VsqEvent)itr.next(); if ( item.ID.type == VsqIDType.Singer ) { item.ID.IconHandle.IDS = value; @@ -314,9 +355,9 @@ namespace Boare.Lib.Vsq { /// public int getIndexOfEOS() { int result; - if ( m_events.getCount() > 0 ) { - int ilast = m_events.getCount() - 1; - result = m_events.getElement( ilast ).Clock; + if ( Events.getCount() > 0 ) { + int ilast = Events.getCount() - 1; + result = Events.getElement( ilast ).Clock; } else { result = -1; } @@ -334,11 +375,11 @@ namespace Boare.Lib.Vsq { int current_id = -1; int current_handle = -1; List events = new List(); - for ( Iterator itr = m_events.iterator(); itr.hasNext(); ) { + for ( Iterator itr = Events.iterator(); itr.hasNext(); ) { events.Add( (VsqEvent)itr.next() ); } events.Sort(); - for( int i = 0; i < events.Count; i++ ){ + for ( int i = 0; i < events.Count; i++ ) { VsqEvent item = events[i]; VsqID id_item = (VsqID)item.ID.Clone(); current_id++; @@ -368,6 +409,14 @@ namespace Boare.Lib.Vsq { handle.Add( handle_item ); id_item.VibratoHandle_index = current_handle; } + // NoteHeadHandle + if ( item.ID.NoteHeadHandle != null ) { + current_handle++; + VsqHandle handle_item = item.ID.NoteHeadHandle.castToVsqHandle(); + handle_item.Index = current_handle; + handle.Add( handle_item ); + id_item.NoteHeadHandle_index = current_handle; + } id.Add( id_item ); } } @@ -398,6 +447,7 @@ namespace Boare.Lib.Vsq { for ( i = 0; i < handle.Count; i++ ) { handle[i].write( sw, encode ); } + string version = Common.Version; if ( PIT.getCount() > 0 ) { PIT.print( sw, start, "[PitchBendBPList]" ); } @@ -416,44 +466,52 @@ namespace Boare.Lib.Vsq { if ( CLE.getCount() > 0 ) { CLE.print( sw, start, "[EpRESlopeDepthBPList]" ); } + if ( version.StartsWith( "DSB2" ) ) { + if ( harmonics.getCount() > 0 ) { + harmonics.print( sw, start, "[EpRSineBPList]" ); + } + if ( fx2depth.getCount() > 0 ) { + fx2depth.print( sw, start, "[VibTremDepthBPList]" ); + } - 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 ( 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 ( 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 ( 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 ) { @@ -462,15 +520,17 @@ namespace Boare.Lib.Vsq { if ( POR.getCount() > 0 ) { POR.print( sw, start, "[PortamentoTimingBPList]" ); } - if ( OPE.getCount() > 0 ) { - OPE.print( sw, start, "[OpeningBPList]" ); + if ( version.StartsWith( "DSB3" ) ) { + 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(); ) { + for ( Iterator itr = Events.iterator(); itr.hasNext(); ) { temp.Add( (VsqEvent)itr.next() ); } temp.Sort(); @@ -514,75 +574,80 @@ namespace Boare.Lib.Vsq { 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() ); + PIT = new VsqBPList( 0, -8192, 8191 ); + //PIT.add( 0, PIT.getDefault() ); PBS = new VsqBPList( 2, 0, 24 ); - PBS.add( 0, PBS.getDefault() ); + //PBS.add( 0, PBS.getDefault() ); DYN = new VsqBPList( 64, 0, 127 ); - DYN.add( 0, DYN.getDefault() ); + //DYN.add( 0, DYN.getDefault() ); BRE = new VsqBPList( 0, 0, 127 ); - BRE.add( 0, BRE.getDefault() ); + //BRE.add( 0, BRE.getDefault() ); BRI = new VsqBPList( 64, 0, 127 ); - BRI.add( 0, BRI.getDefault() ); + //BRI.add( 0, BRI.getDefault() ); CLE = new VsqBPList( 0, 0, 127 ); - CLE.add( 0, CLE.getDefault() ); + //CLE.add( 0, CLE.getDefault() ); - reso1FreqBPList = new VsqBPList( 255, 0, 255 ); - reso1FreqBPList.add( 0, reso1FreqBPList.getDefault() ); + reso1FreqBPList = new VsqBPList( 64, 0, 127 ); + //reso1FreqBPList.add( 0, reso1FreqBPList.getDefault() ); - reso2FreqBPList = new VsqBPList( 255, 0, 255 ); - reso2FreqBPList.add( 0, reso2FreqBPList.getDefault() ); + reso2FreqBPList = new VsqBPList( 64, 0, 127 ); + //reso2FreqBPList.add( 0, reso2FreqBPList.getDefault() ); - reso3FreqBPList = new VsqBPList( 255, 0, 255 ); - reso3FreqBPList.add( 0, reso3FreqBPList.getDefault() ); + reso3FreqBPList = new VsqBPList( 64, 0, 127 ); + //reso3FreqBPList.add( 0, reso3FreqBPList.getDefault() ); - reso4FreqBPList = new VsqBPList( 255, 0, 255 ); - reso4FreqBPList.add( 0, reso4FreqBPList.getDefault() ); + reso4FreqBPList = new VsqBPList( 64, 0, 127 ); + //reso4FreqBPList.add( 0, reso4FreqBPList.getDefault() ); - reso1BWBPList = new VsqBPList( 255, 0, 255 ); - reso1BWBPList.add( 0, reso1BWBPList.getDefault() ); + reso1BWBPList = new VsqBPList( 64, 0, 127 ); + //reso1BWBPList.add( 0, reso1BWBPList.getDefault() ); - reso2BWBPList = new VsqBPList( 255, 0, 255 ); - reso2BWBPList.add( 0, reso2BWBPList.getDefault() ); + reso2BWBPList = new VsqBPList( 64, 0, 127 ); + //reso2BWBPList.add( 0, reso2BWBPList.getDefault() ); - reso3BWBPList = new VsqBPList( 255, 0, 255 ); - reso3BWBPList.add( 0, reso3BWBPList.getDefault() ); + reso3BWBPList = new VsqBPList( 64, 0, 127 ); + //reso3BWBPList.add( 0, reso3BWBPList.getDefault() ); - reso4BWBPList = new VsqBPList( 255, 0, 255 ); - reso4BWBPList.add( 0, reso4BWBPList.getDefault() ); + reso4BWBPList = new VsqBPList( 64, 0, 127 ); + //reso4BWBPList.add( 0, reso4BWBPList.getDefault() ); - reso1AmpBPList = new VsqBPList( 255, 0, 255 ); - reso1AmpBPList.add( 0, reso1AmpBPList.getDefault() ); + reso1AmpBPList = new VsqBPList( 64, 0, 127 ); + //reso1AmpBPList.add( 0, reso1AmpBPList.getDefault() ); - reso2AmpBPList = new VsqBPList( 255, 0, 255 ); - reso2AmpBPList.add( 0, reso2AmpBPList.getDefault() ); + reso2AmpBPList = new VsqBPList( 64, 0, 127 ); + //reso2AmpBPList.add( 0, reso2AmpBPList.getDefault() ); - reso3AmpBPList = new VsqBPList( 255, 0, 255 ); - reso3AmpBPList.add( 0, reso3AmpBPList.getDefault() ); + reso3AmpBPList = new VsqBPList( 64, 0, 127 ); + //reso3AmpBPList.add( 0, reso3AmpBPList.getDefault() ); - reso4AmpBPList = new VsqBPList( 255, 0, 255 ); - reso4AmpBPList.add( 0, reso4AmpBPList.getDefault() ); + reso4AmpBPList = new VsqBPList( 64, 0, 127 ); + //reso4AmpBPList.add( 0, reso4AmpBPList.getDefault() ); + + harmonics = new VsqBPList( 64, 0, 127 ); + //harmonics.add( 0, harmonics.getDefault() ); + + fx2depth = new VsqBPList( 64, 0, 127 ); GEN = new VsqBPList( 64, 0, 127 ); - GEN.add( 0, GEN.getDefault() ); + //GEN.add( 0, GEN.getDefault() ); POR = new VsqBPList( 64, 0, 127 ); - POR.add( 0, POR.getDefault() ); + //POR.add( 0, POR.getDefault() ); OPE = new VsqBPList( 127, 0, 127 ); - OPE.add( 0, OPE.getDefault() ); + //OPE.add( 0, OPE.getDefault() ); if ( is_first_track ) { master = new VsqMaster( pre_measure ); } else { master = null; } - m_events = new VsqEventList(); + Events = new VsqEventList(); VsqID id = new VsqID( 0 ); id.type = VsqIDType.Singer; id.IconHandle = new IconHandle(); @@ -593,31 +658,33 @@ namespace Boare.Lib.Vsq { id.IconHandle.Length = 1; id.IconHandle.Language = 0; id.IconHandle.Program = 0; - m_events.add( new VsqEvent( 0, id ) ); + 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 ); + PIT = new VsqBPList( 0, -8192, 8191 ); 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 ); + reso1FreqBPList = new VsqBPList( 64, 0, 127 ); + reso2FreqBPList = new VsqBPList( 64, 0, 127 ); + reso3FreqBPList = new VsqBPList( 64, 0, 127 ); + reso4FreqBPList = new VsqBPList( 64, 0, 127 ); + reso1BWBPList = new VsqBPList( 64, 0, 127 ); + reso2BWBPList = new VsqBPList( 64, 0, 127 ); + reso3BWBPList = new VsqBPList( 64, 0, 127 ); + reso4BWBPList = new VsqBPList( 64, 0, 127 ); + reso1AmpBPList = new VsqBPList( 64, 0, 127 ); + reso2AmpBPList = new VsqBPList( 64, 0, 127 ); + reso3AmpBPList = new VsqBPList( 64, 0, 127 ); + reso4AmpBPList = new VsqBPList( 64, 0, 127 ); + harmonics = new VsqBPList( 64, 0, 127 ); + fx2depth = new VsqBPList( 64, 0, 127 ); GEN = new VsqBPList( 64, 0, 127 ); POR = new VsqBPList( 64, 0, 127 ); OPE = new VsqBPList( 127, 0, 127 ); @@ -679,6 +746,12 @@ namespace Boare.Lib.Vsq { case "[EpRESlopeDepthBPList]": last_line = CLE.appendFromText( sr ); break; + case "[EpRSineBPList]": + last_line = harmonics.appendFromText( sr ); + break; + case "[VibTremDepthBPList]": + last_line = fx2depth.appendFromText( sr ); + break; case "[Reso1FreqBPList]": last_line = reso1FreqBPList.appendFromText( sr ); break; @@ -755,15 +828,18 @@ namespace Boare.Lib.Vsq { if ( __handle.ContainsKey( __id[i].VibratoHandle_index ) ) { __id[i].VibratoHandle = __handle[__id[i].VibratoHandle_index].castToVibratoHandle(); } + if ( __handle.ContainsKey( __id[i].NoteHeadHandle_index ) ) { + __id[i].NoteHeadHandle = __handle[__id[i].NoteHeadHandle_index].castToNoteHeadHandle(); + } } // idをeventListに埋め込み - m_events = new VsqEventList(); + 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() ) ); + Events.add( new VsqEvent( clock, (VsqID)__id[id_number].Clone() ) ); } } } @@ -805,7 +881,8 @@ namespace Boare.Lib.Vsq { public enum VsqHandleType { Lyric, Vibrato, - Singer + Singer, + NoteHeadHandle, } } diff --git a/trunk/Boare.Lib.Vsq/VsqNrpn.cs b/trunk/Boare.Lib.Vsq/VsqNrpn.cs index 3bf48c9..56a66a4 100644 --- a/trunk/Boare.Lib.Vsq/VsqNrpn.cs +++ b/trunk/Boare.Lib.Vsq/VsqNrpn.cs @@ -16,18 +16,19 @@ using System.Collections.Generic; namespace Boare.Lib.Vsq { - public class VsqNrpn : IComparable { + public struct VsqNrpn : IComparable { public int Clock; public ushort Nrpn; public byte DataMsb; public byte DataLsb; - public bool DataLsbSpecified = false; + public bool DataLsbSpecified; private List m_list; public VsqNrpn( int clock, ushort nrpn, byte data_msb ) { Clock = clock; Nrpn = nrpn; DataMsb = data_msb; + DataLsb = 0x0; DataLsbSpecified = false; m_list = new List(); } @@ -41,9 +42,6 @@ namespace Boare.Lib.Vsq { m_list = new List(); } - private VsqNrpn() { - } - public VsqNrpn[] expand() { List ret = new List(); if ( DataLsbSpecified ) { @@ -57,6 +55,51 @@ namespace Boare.Lib.Vsq { return ret.ToArray(); } + public static List sort( List list ) { + List ret = new List(); + list.Sort(); + if ( list.Count >= 2 ) { + List work = new List(); //workには、clockが同じNRPNだけが入る + int last_clock = list[0].Clock; + work.Add( list[0] ); + for ( int i = 1; i < list.Count; i++ ) { + if ( list[i].Clock == last_clock ) { + work.Add( list[i] ); + } else { + // まずworkを並べ替え + last_clock = list[i].Clock; + bool changed = true; + while ( changed ) { + changed = false; + for ( int j = 0; j < work.Count - 1; j++ ) { + byte nrpn_msb0 = (byte)((work[j].Nrpn >> 8) & 0xff); + byte nrpn_msb1 = (byte)((work[j + 1].Nrpn >> 8) & 0xff); + if ( nrpn_msb1 > nrpn_msb0 ) { + VsqNrpn buf = work[j]; + work[j] = work[j + 1]; + work[j + 1] = buf; + changed = true; + } + } + } + for ( int j = 0; j < work.Count; j++ ) { + ret.Add( work[j] ); + } + work.Clear(); + work.Add( list[i] ); + } + } + for ( int j = 0; j < work.Count; j++ ) { + ret.Add( work[j] ); + } + } else { + for ( int i = 0; i < list.Count; i++ ) { + ret.Add( list[i] ); + } + } + return ret; + } + public static VsqNrpn[] merge( VsqNrpn[] src1, VsqNrpn[] src2 ) { List ret = new List(); for ( int i = 0; i < src1.Length; i++ ) { @@ -104,12 +147,12 @@ namespace Boare.Lib.Vsq { return Clock - item.Clock; } - public void append( NRPN nrpn, byte data_msb ) { - m_list.Add( new VsqNrpn( Clock, (ushort)nrpn, data_msb ) ); + public void append( ushort nrpn, byte data_msb ) { + m_list.Add( new VsqNrpn( Clock, nrpn, data_msb ) ); } - public void append( NRPN nrpn, byte data_msb, byte data_lsb ) { - m_list.Add( new VsqNrpn( Clock, (ushort)nrpn, data_msb, data_lsb ) ); + public void append( ushort nrpn, byte data_msb, byte data_lsb ) { + m_list.Add( new VsqNrpn( Clock, nrpn, data_msb, data_lsb ) ); } } diff --git a/trunk/Boare.Lib.Vsq/VsqTrack.cs b/trunk/Boare.Lib.Vsq/VsqTrack.cs index 8136892..f1cb308 100644 --- a/trunk/Boare.Lib.Vsq/VsqTrack.cs +++ b/trunk/Boare.Lib.Vsq/VsqTrack.cs @@ -22,16 +22,14 @@ namespace Boare.Lib.Vsq { /// [Serializable] public partial class VsqTrack : ICloneable { - public object Tag; + public string Tag; /// /// トラックの名前。 /// public string Name; - private VsqMetaText m_meta_text; - private List m_midi_event; + public VsqMetaText MetaText; private int m_edited_start = int.MaxValue; private int m_edited_end = int.MinValue; - public string Renderer = "VOCALOID2"; private class SingerEventIterator : Iterator { VsqEventList m_list; @@ -133,13 +131,16 @@ namespace Boare.Lib.Vsq { } } + public void sortEvent() { + MetaText.Events.sort(); + } /// /// 歌手変更イベントを,曲の先頭から順に返すIteratorを取得します /// /// public Iterator getSingerEventIterator() { - return new SingerEventIterator( m_meta_text.getEventList() ); + return new SingerEventIterator( MetaText.getEventList() ); } /// @@ -147,7 +148,11 @@ namespace Boare.Lib.Vsq { /// /// public Iterator getNoteEventIterator() { - return new NoteEventIterator( m_meta_text.getEventList() ); + if ( MetaText == null ) { + return new NoteEventIterator( new VsqEventList() ); + } else { + return new NoteEventIterator( MetaText.getEventList() ); + } } /// @@ -158,7 +163,7 @@ namespace Boare.Lib.Vsq { /// /// public void printMetaText( TextMemoryStream sw, int eos, int start ) { - m_meta_text.print( sw, false, eos, start ); + MetaText.print( sw, false, eos, start ); } /// @@ -167,9 +172,9 @@ namespace Boare.Lib.Vsq { /// public void printMetaText( string file ) { TextMemoryStream tms = new TextMemoryStream( FileAccess.ReadWrite ); - int count = m_meta_text.getEventList().getCount(); - int clLast = m_meta_text.getEventList().getElement( count - 1 ).Clock + 480; - m_meta_text.print( tms, true, clLast, 0 ); + 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 ) { @@ -183,22 +188,73 @@ namespace Boare.Lib.Vsq { /// Masterを取得します /// public VsqMaster getMaster() { - return m_meta_text.master; + return MetaText.master; } internal void setMaster( VsqMaster value ) { - m_meta_text.master = value; + MetaText.master = value; } /// /// Mixerを取得します /// public VsqMixer getMixer() { - return m_meta_text.mixer; + return MetaText.mixer; } internal void setMixer( VsqMixer value ) { - m_meta_text.mixer = value; + MetaText.mixer = value; + } + + /// + /// Commonを取得します + /// + /// + public VsqCommon getCommon() { + return MetaText.Common; + } + + /// + /// 指定したトラックのレンダラーを変更します + /// + /// + /// + /// + public void changeRenderer( string new_renderer, List 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; } /// @@ -207,46 +263,45 @@ namespace Boare.Lib.Vsq { /// /// public VsqBPList getCurve( string curve ) { - return m_meta_text.getElement( curve ); + return MetaText.getElement( curve ); } public void setCurve( string curve, VsqBPList value ) { - m_meta_text.setElement( curve, value ); + MetaText.setElement( curve, value ); } public int getEventCount() { - return m_meta_text.getEventList().getCount(); + return MetaText.getEventList().getCount(); } public VsqEvent getEvent( int index ) { - return m_meta_text.getEventList().getElement( index ); + return MetaText.getEventList().getElement( index ); } public void setEvent( int index, VsqEvent item ) { - m_meta_text.getEventList().setElement( index, item ); + MetaText.getEventList().setElement( index, item ); } public void addEvent( VsqEvent item ) { - m_meta_text.getEventList().add( item ); + MetaText.getEventList().add( item ); } public Iterator getEventIterator() { - return new EventIterator( m_meta_text.getEventList() ); + return new EventIterator( MetaText.getEventList() ); } public void removeEvent( int index ) { - m_meta_text.getEventList().removeAt( index ); + MetaText.getEventList().removeAt( index ); } /// /// このトラックの,最後に編集が加えられた範囲の,開始位置(クロック)を取得します. - /// このインスタンスを保持しているVsqFileインスタンスのExecuteメソッドによって自動的に更新されます /// public int getEditedStart() { return m_edited_start; } - internal void setEditedStart( int value ) { + public void setEditedStart( int value ) { if ( value < m_edited_start ) { m_edited_start = value; } @@ -254,13 +309,12 @@ namespace Boare.Lib.Vsq { /// /// このトラックの,最後に編集が加えられた範囲の,終了位置(クロック)を取得します. - /// このインスタンスを保持しているVsqFileインスタンスのExecuteメソッドによって自動的に更新されます /// public int getEditedEnd() { return m_edited_end; } - internal void setEditedEnd( int value ) { + public void setEditedEnd( int value ) { if ( m_edited_end < value ) { m_edited_end = value; } @@ -281,21 +335,15 @@ namespace Boare.Lib.Vsq { public object Clone() { VsqTrack res = new VsqTrack(); res.Name = Name; - if ( m_meta_text != null ) { - res.m_meta_text = (VsqMetaText)m_meta_text.Clone(); - } - if ( m_midi_event != null ) { - res.m_midi_event = new List( m_midi_event ); + if ( MetaText != null ) { + res.MetaText = (VsqMetaText)MetaText.Clone(); } res.m_edited_start = m_edited_start; res.m_edited_end = m_edited_end; - res.Renderer = Renderer; + res.Tag = Tag; return res; } - private VsqTrack() { - } - /// /// Master Trackを構築 /// @@ -304,24 +352,7 @@ namespace Boare.Lib.Vsq { /// public VsqTrack( int tempo, int numerator, int denominator ) { this.Name = "Master Track"; - this.m_meta_text = null; - m_midi_event = new List(); - - // テンポを設定 - MidiEvent mi_tempo = new MidiEvent(); - mi_tempo.Clock = 0; - mi_tempo.FirstByte = 0xff; - byte b1 = (byte)(tempo & 0xff); - tempo = tempo >> 8; - byte b2 = (byte)(tempo & 0xff); - tempo = tempo >> 8; - byte b3 = (byte)(tempo & 0xff); - mi_tempo.Data = new byte[5] { 0x51, 0x03, b3, b2, b1 }; - m_midi_event.Add( mi_tempo ); - - // 拍子を設定 - MidiEvent mi_timesig = MidiEvent.generateTimeSigEvent( 0, numerator, denominator ); - m_midi_event.Add( mi_timesig ); + this.MetaText = null; } /// @@ -331,8 +362,11 @@ namespace Boare.Lib.Vsq { /// public VsqTrack( string name, string singer ) { Name = name; - m_meta_text = new VsqMetaText( name, singer ); - m_midi_event = new List(); + MetaText = new VsqMetaText( name, singer ); + } + + public VsqTrack() + : this( "Voice1", "Miku" ) { } /// @@ -341,29 +375,28 @@ namespace Boare.Lib.Vsq { /// public int getLyricLength() { int counter = 0; - for ( int i = 0; i < m_meta_text.getEventList().getCount(); i++ ) { - if ( m_meta_text.getEventList().getElement( i ).ID.type == VsqIDType.Anote ) { + for ( int i = 0; i < MetaText.getEventList().getCount(); i++ ) { + if ( MetaText.getEventList().getElement( i ).ID.type == VsqIDType.Anote ) { counter++; } } return counter; } - public VsqTrack( List midi_events ) { - m_midi_event = new List( midi_events ); + public VsqTrack( List midi_event ) { Name = ""; #if DEBUG bocoree.debug.push_log( "VsqTrack..ctor" ); #endif using ( TextMemoryStream sw = new TextMemoryStream() ) { - for ( int i = 0; i < m_midi_event.Count; i++ ) { - if ( m_midi_event[i].FirstByte == 0xff && m_midi_event[i].Data.Length > 0 ) { + 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 = m_midi_event[i].Data[0]; + byte type = midi_event[i].Data[0]; if ( type == 0x01 || type == 0x03 ) { - char[] ch = new char[m_midi_event[i].Data.Length - 1]; - for ( int j = 1; j < midi_events[i].Data.Length; j++ ) { - ch[j - 1] = (char)midi_events[i].Data[j]; + 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 ) { @@ -381,33 +414,9 @@ namespace Boare.Lib.Vsq { } } sw.rewind(); - m_meta_text = new VsqMetaText( sw ); + MetaText = new VsqMetaText( sw ); } } - - public List getTempoList() { - List list = new List(); - for ( int i = 0; i < m_midi_event.Count; i++ ) { - if ( m_midi_event[i].FirstByte == 0xff && m_midi_event[i].Data.Length >= 4 && m_midi_event[i].Data[0] == 0x51 ) { - list.Add( m_midi_event[i] ); - } - } - return list; - } - - /// - /// MidiEventの中から拍子情報を抽出します - /// - /// - public List getTimeSigList() { - List list = new List(); - for ( int i = 0; i < m_midi_event.Count; i++ ) { - if ( m_midi_event[i].FirstByte == 0xff && m_midi_event[i].Data.Length >= 5 && m_midi_event[i].Data[0] == 0x58 ) { - list.Add( m_midi_event[i] ); - } - } - return list; - } } } diff --git a/trunk/Boare.Lib.Vsq/makefile b/trunk/Boare.Lib.Vsq/makefile index 6db9f8e..c9ef407 100644 --- a/trunk/Boare.Lib.Vsq/makefile +++ b/trunk/Boare.Lib.Vsq/makefile @@ -1,21 +1,14 @@ CP=cp RM=rm -all: Boare.Lib.Vsq.dll libvsq.exe +all: Boare.Lib.Vsq.dll Boare.Lib.Vsq.dll: *.cs bocoree.dll gmcs -recurse:*.cs -target:library -define:MONO -out:Boare.Lib.Vsq.dll -r:bocoree.dll,System,System.Windows.Forms,System.Drawing -bocoree.dll: ../bocoree/bocoree.dll - cp ../bocoree/bocoree.dll bocoree.dll - -../bocoree/bocoree.dll: - cd ../bocoree/ && $(MAKE) - -libvsq.exe: common.cpp TextMemoryStream.cpp VsqCommon.cpp main.cpp - g++ common.cpp TextMemoryStream.cpp VsqCommon.cpp main.cpp -o libvsq.exe +#libvsq.exe: common.cpp TextMemoryStream.cpp VsqCommon.cpp main.cpp +# g++ common.cpp TextMemoryStream.cpp VsqCommon.cpp main.cpp -o libvsq.exe clean: $(RM) Boare.Lib.Vsq.dll $(RM) bocoree.dll - cd ../bocoree/ && $(MAKE) RM=$(RM) clean diff --git a/trunk/LipSync/LipSync/Editor/Form1.cs b/trunk/LipSync/LipSync/Editor/Form1.cs index be51d96..fc28fd0 100644 --- a/trunk/LipSync/LipSync/Editor/Form1.cs +++ b/trunk/LipSync/LipSync/Editor/Form1.cs @@ -712,7 +712,9 @@ namespace LipSync { } else { #region エントリがクリックされたとき copy_enabled = true;//エントリがクリックされたので、エントリの個数は1個以上! - if ( m_clicked.type != TimeTableType.vsq ) { + if ( m_clicked.type == TimeTableType.vsq ) { + cmenu.Items.Add( _( "Generate Lipsync from this track" ), null, new EventHandler( h_genMouthFromVsq ) ); + } else { cmenu.Items.Add( _( "Note OFF" ) + "(&O)", null, new EventHandler( h_noteOFF ) ); if ( m_clicked.type == TimeTableType.character ) { cmenu.Items.Add( _( "Image Preview" ), null, new EventHandler( h_previewImage ) ); @@ -2331,21 +2333,21 @@ namespace LipSync { VsqFile vsqFile = new VsqFile( openVsqDialog.FileName ); AppManager.SaveData.m_totalSec = (float)vsqFile.getTotalSec(); - AppManager.SaveData.m_timesig_ex = new List( vsqFile.getTimeSigList().ToArray() ); - AppManager.SaveData.m_tempo = new List( vsqFile.getTempoList().ToArray() ); + AppManager.SaveData.m_timesig_ex = new List( vsqFile.TimesigTable.ToArray() ); + AppManager.SaveData.m_tempo = new List( vsqFile.TempoTable.ToArray() ); AppManager.SaveData.m_base_tempo = vsqFile.getBaseTempo(); // 歌詞の含まれるトラック数を取得 { int most_lyrics = 0; - for ( int i = 0; i < vsqFile.getTrackCount(); i++ ) { - int track_num = vsqFile.getTrack( i ).getLyricLength(); + for ( int i = 0; i < vsqFile.Track.Count; i++ ) { + int track_num = vsqFile.Track[i].getLyricLength(); if ( most_lyrics < track_num ) { most_lyrics_track = i; most_lyrics = track_num; } if ( track_num > 0 ) { - track_name.Add( vsqFile.getTrack( i ).Name ); + track_name.Add( vsqFile.Track[i].Name ); tracks++; } } @@ -2353,8 +2355,8 @@ namespace LipSync { most_lyrics_track--; // tableを更新 - for ( int track = 0; track < vsqFile.getTrackCount(); track++ ) { - int lyrics = vsqFile.getTrack( track ).getLyricLength(); + for ( int track = 0; track < vsqFile.Track.Count; track++ ) { + int lyrics = vsqFile.Track[track].getLyricLength(); if ( lyrics <= 0 ) { continue; } @@ -2370,7 +2372,8 @@ namespace LipSync { } else { UstFile ust_file = new UstFile( openVsqDialog.FileName ); for ( int track = 0; track < ust_file.getTrackCount(); track++ ) { - foreach ( UstEvent ue in ust_file.getTrack( track ).getNoteEventEnumerator() ) { + for( Iterator itr = ust_file.getTrack( track ).getNoteEventIterator(); itr.hasNext(); ){ + UstEvent ue = (UstEvent)itr.next(); if ( ue.Lyric == "u" ) { ue.Lyric = "う"; } diff --git a/trunk/LipSync/LipSync/Editor/Form1Util.cs b/trunk/LipSync/LipSync/Editor/Form1Util.cs index 56e6cd4..f1027f7 100644 --- a/trunk/LipSync/LipSync/Editor/Form1Util.cs +++ b/trunk/LipSync/LipSync/Editor/Form1Util.cs @@ -267,10 +267,10 @@ namespace LipSync { AppManager.SaveData.m_totalSec = Math.Max( AppManager.SaveData.m_totalSec, (float)ust.getTotalSec() ); } else { VsqFile vsqFile = new VsqFile( filename ); - int tracks = vsqFile.getTrackCount(); + int tracks = vsqFile.Track.Count; string[] track_names = new string[tracks]; for ( int track = 0; track < tracks; track++ ) { - track_names[track] = vsqFile.getTrack( track ).Name; + track_names[track] = vsqFile.Track[track].Name; } using ( TrackSelecter selecter = new TrackSelecter( filename, track_names ) ) { selecter.ImportTempoAndTimesig = false; @@ -290,8 +290,8 @@ namespace LipSync { AppManager.SaveData.m_tempo.Clear(); AppManager.SaveData.m_tempo = null; } - AppManager.SaveData.m_timesig_ex = new List( vsqFile.getTimeSigList().ToArray() ); - AppManager.SaveData.m_tempo = new List( vsqFile.getTempoList().ToArray() ); + AppManager.SaveData.m_timesig_ex = new List( vsqFile.TimesigTable.ToArray() ); + AppManager.SaveData.m_tempo = new List( vsqFile.TempoTable.ToArray() ); AppManager.SaveData.m_base_tempo = vsqFile.getBaseTempo(); } } @@ -1258,7 +1258,7 @@ namespace LipSync { private void addTimeLineFromTrack( VsqFile vsqFile, int track_number, bool enable_undo ) { string tmp_lyric = Path.GetTempFileName(); vsqFile.printLyricTable( track_number, tmp_lyric ); - using ( TimeTable temp = new TimeTable( vsqFile.getTrack( track_number ).Name, 0, TimeTableType.vsq, null ) ) { + using ( TimeTable temp = new TimeTable( vsqFile.Track[track_number].Name, 0, TimeTableType.vsq, null ) ) { using ( StreamReader sr = new StreamReader( tmp_lyric ) ) { string line; while ( sr.Peek() >= 0 ) { diff --git a/trunk/bocoree/bocoree.csproj b/trunk/bocoree/bocoree.csproj index 971556f..01f9033 100644 --- a/trunk/bocoree/bocoree.csproj +++ b/trunk/bocoree/bocoree.csproj @@ -3,7 +3,7 @@ Debug AnyCPU - 9.0.21022 + 9.0.30729 2.0 {C8AAE632-9C6C-4372-8175-811528A66742} Library @@ -12,6 +12,9 @@ bocoree v2.0 512 + false + + true diff --git a/trunk/bocoree/makefile b/trunk/bocoree/makefile index ade002c..f69ea39 100644 --- a/trunk/bocoree/makefile +++ b/trunk/bocoree/makefile @@ -1,6 +1,6 @@ CP=cp RM=rm -SRC=cp932.cs fft.cs math.cs windows.cs wingdi.cs + bocoree.dll: *.cs gmcs -recurse:*.cs -unsafe+ -target:library -out:bocoree.dll -r:System,System.Drawing,System.Windows.Forms diff --git a/trunk/bocoree/misc.cs b/trunk/bocoree/misc.cs index a9edd59..b92b618 100644 --- a/trunk/bocoree/misc.cs +++ b/trunk/bocoree/misc.cs @@ -122,24 +122,43 @@ namespace bocoree { private static string s_path = ""; public static void force_logfile_path( string path ) { + try { + if ( s_debug_out != null ) { + s_debug_out.Close(); + s_debug_out = new StreamWriter( path ); + } + } catch { + } s_path = path; } public static void push_log( string s ) { - if ( s_debug_out == null ) { - if ( s_path == "" ) { - s_debug_out = new StreamWriter( Path.Combine( System.Windows.Forms.Application.StartupPath, "run.log" ) ); - } else { - s_debug_out = new StreamWriter( s_path ); + try { + if ( s_debug_out == null ) { + if ( s_path == "" ) { + s_debug_out = new StreamWriter( Path.Combine( System.Windows.Forms.Application.StartupPath, "run.log" ) ); + } else { + s_debug_out = new StreamWriter( s_path ); + } + s_debug_out.AutoFlush = true; + s_debug_out.WriteLine( "************************************************************************" ); + s_debug_out.WriteLine( " Date: " + DateTime.Now.ToString() ); + s_debug_out.WriteLine( "------------------------------------------------------------------------" ); } - s_debug_out.AutoFlush = true; - s_debug_out.WriteLine( "************************************************************************" ); - s_debug_out.WriteLine( " Date: " + DateTime.Now.ToString() ); - s_debug_out.WriteLine( "------------------------------------------------------------------------" ); + s_debug_out.WriteLine( s ); + } catch ( Exception ex ) { + Console.WriteLine( "bocoree.debug.push_log; log file I/O Exception" ); } - s_debug_out.WriteLine( s ); Console.WriteLine( s ); } + + public static void close() { + if ( s_debug_out != null ) { + s_debug_out.Close(); + s_debug_out = null; + s_path = ""; + } + } } } diff --git a/trunk/bocoree/windows.cs b/trunk/bocoree/windows.cs index fe0e9ec..e904bd2 100644 --- a/trunk/bocoree/windows.cs +++ b/trunk/bocoree/windows.cs @@ -36,7 +36,7 @@ namespace bocoree { public const int LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE = 0x00000040; [DllImport( "kernel32.dll" )] - public static extern IntPtr LoadLibraryExW( [MarshalAs( UnmanagedType.LPWStr)]string lpFileName, IntPtr hFile, uint dwFlags ); + public static extern IntPtr LoadLibraryExW( [MarshalAs( UnmanagedType.LPWStr )]string lpFileName, IntPtr hFile, uint dwFlags ); [DllImport( "kernel32.dll", CharSet = CharSet.Ansi, EntryPoint = "GetProcAddress", ExactSpelling = true )] public static extern IntPtr GetProcAddress( IntPtr hModule, string lpProcName ); @@ -158,8 +158,29 @@ namespace bocoree { #region windef.h public const int MAX_PATH = 260; #endregion - } + #region winuser.h + public const int WM_MOUSEMOVE = 512; + public const int WM_LBUTTONDOWN = 513; + public const int WM_LBUTTONUP = 514; + public const int WM_LBUTTONDBLCLK = 515; + public const int WM_RBUTTONDOWN = 516; + public const int WM_RBUTTONUP = 517; + public const int WM_RBUTTONDBLCLK = 518; + public const int WM_MBUTTONDOWN = 519; + public const int WM_MBUTTONUP = 520; + public const int WM_MBUTTONDBLCLK = 521; + public const int WM_MOUSEWHEEL = 522; + #endregion + + public const uint SHGFI_ICON = 0x100; + public const uint SHGFI_LARGEICON = 0x0; // 'Large icon + public const uint SHGFI_SMALLICON = 0x1; // 'Small icon + + [DllImport( "shell32.dll" )] + public static extern IntPtr SHGetFileInfo( string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbSizeFileInfo, uint uFlags ); + + } #region windef.h public struct FILETIME { @@ -168,4 +189,14 @@ namespace bocoree { } #endregion + [StructLayout( LayoutKind.Sequential )] + public struct SHFILEINFO { + public IntPtr hIcon; + public IntPtr iIcon; + public uint dwAttributes; + [MarshalAs( UnmanagedType.ByValTStr, SizeConst = 260 )] + public string szDisplayName; + [MarshalAs( UnmanagedType.ByValTStr, SizeConst = 80 )] + public string szTypeName; + } } \ No newline at end of file diff --git a/trunk/bocoree/wingdi.cs b/trunk/bocoree/wingdi.cs index 829d674..5b58ea2 100644 --- a/trunk/bocoree/wingdi.cs +++ b/trunk/bocoree/wingdi.cs @@ -30,6 +30,54 @@ namespace bocoree { public Int32 biYPelsPerMeter; public UInt32 biClrUsed; public UInt32 biClrImportant; + + public static BITMAPINFOHEADER Read( Stream stream ) { + BITMAPINFOHEADER bifh = new BITMAPINFOHEADER(); + byte[] buf = new byte[4]; + bifh.biSize = readUInt32( stream ); + bifh.biWidth = readInt32( stream ); + bifh.biHeight = readInt32( stream ); + bifh.biPlanes = readInt16( stream ); + bifh.biBitCount = readInt16( stream ); + bifh.biCompression = readUInt32( stream ); + bifh.biSizeImage = readUInt32( stream ); + bifh.biXPelsPerMeter = readInt32( stream ); + bifh.biYPelsPerMeter = readInt32( stream ); + bifh.biClrUsed = readUInt32( stream ); + bifh.biClrImportant = readUInt32( stream ); + return bifh; + } + + private static uint readUInt32( Stream fs ){ + byte[] buf = new byte[4]; + fs.Read( buf, 0, 4 ); + return BitConverter.ToUInt32( buf, 0 ); + } + + private static int readInt32( Stream fs ){ + byte[] buf = new byte[4]; + fs.Read( buf, 0, 4 ); + return BitConverter.ToInt32( buf, 0 ); + } + + private static ushort readUInt16( Stream fs ){ + byte[] buf = new byte[2]; + fs.Read( buf, 0, 2 ); + return BitConverter.ToUInt16( buf, 0 ); + } + + private static short readInt16( Stream fs ){ + byte[] buf = new byte[2]; + fs.Read( buf, 0, 2 ); + return BitConverter.ToInt16( buf, 0 ); + } + + public override string ToString() { + return "{biSize=" + biSize + ", biWidth=" + biWidth + ", biHeight=" + biHeight + ", biPlanes=" + biPlanes + ", biBitCount=" + biBitCount + + ", biCompression=" + biCompression + ", biSizeImage=" + biSizeImage + ", biXPelsPerMeter=" + biXPelsPerMeter + ", biYPelsPerMeter=" + biYPelsPerMeter + + ", biClrUsed=" + biClrUsed + ", biClrImportant=" + biClrImportant + "}"; + } + public void Write( BinaryWriter bw ) { bw.Write( biSize ); bw.Write( (uint)biWidth ); diff --git a/trunk/bocoree/winmm.cs b/trunk/bocoree/winmm.cs index 39036de..9ac0af5 100644 --- a/trunk/bocoree/winmm.cs +++ b/trunk/bocoree/winmm.cs @@ -13,6 +13,7 @@ */ using System; using System.Runtime.InteropServices; +using bocoree; namespace bocoree { @@ -131,138 +132,38 @@ namespace bocoree { public uint reserved; // reserved for driver } - /*typedef struct mmtime_tag -{ - UINT wType; // indicates the contents of the union - union - { - DWORD ms; // milliseconds - DWORD sample; // samples - DWORD cb; // byte count - DWORD ticks; // ticks in MIDI stream - - // SMPTE - struct - { - BYTE hour; // hours - BYTE min; // minutes - BYTE sec; // seconds - BYTE frame; // frames - BYTE fps; // frames per second - BYTE dummy; // pad -#ifdef _WIN32 - BYTE pad[2]; -#endif - } smpte; - - // MIDI - struct - { - DWORD songptrpos; // song pointer position - } midi; - } u; -}*/ [StructLayout( LayoutKind.Explicit )] public struct MMTIME { - [FieldOffset( 0 )] - public UInt32 wType; - [FieldOffset( 4 )] - public UInt32 ms; - [FieldOffset( 4 )] - public UInt32 sample; - [FieldOffset( 4 )] - public UInt32 cb; - [FieldOffset( 4 )] - public UInt32 ticks; - [FieldOffset( 4 )] - public Byte smpteHour; - [FieldOffset( 5 )] - public Byte smpteMin; - [FieldOffset( 6 )] - public Byte smpteSec; - [FieldOffset( 7 )] - public Byte smpteFrame; - [FieldOffset( 8 )] - public Byte smpteFps; - [FieldOffset( 9 )] - public Byte smpteDummy; - [FieldOffset( 10 )] - public Byte smptePad0; - [FieldOffset( 11 )] - public Byte smptePad1; - [FieldOffset( 4 )] - public UInt32 midiSongPtrPos; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1 )] - public unsafe struct _MMTIME { - public UINT wType; - byte b1; - byte b2; - byte b3; - byte b4; - byte b5; - byte b6; - byte b7; - byte b8; - - public struct SMPTE { - public BYTE hour; // hours - public BYTE min; // minutes - public BYTE sec; // seconds - public BYTE frame; // frames - public BYTE fps; // frames per second - public BYTE dummy; // pad - public fixed BYTE pad[2]; - } - - public SMPTE smpte { - get { - SMPTE ret = new SMPTE(); - ret.hour = b1; - ret.min = b2; - ret.sec = b3; - ret.frame = b4; - ret.fps = b5; - ret.dummy = b6; - ret.pad[0] = b7; - ret.pad[1] = b8; - return ret; - } - } - + [StructLayout( LayoutKind.Sequential, Pack = 1 )] public struct MIDI { public DWORD songptrpos; // song pointer position } - public MIDI midi { - get { - MIDI ret = new MIDI(); - ret.songptrpos = ms; - return ret; - } + [StructLayout( LayoutKind.Sequential, Pack = 1 )] + public unsafe struct SMPTE { + public BYTE hour; // hours + public BYTE min; // minutes + public BYTE sec; // seconds + public BYTE frame; // frames + public BYTE fps; // frames per second + public BYTE dummy; // pad + public fixed BYTE pad[2]; } - public uint ms { - get { - return (uint)b1 | (uint)(b2 << 8) | (uint)(b3 << 16) | (uint)(b4 << 32); - } - } - public uint sample { - get { - return ms; - } - } - public uint cb { - get { - return ms; - } - } - public uint ticks { - get { - return ms; - } - } + [FieldOffset( 0 )] + public uint wType; + [FieldOffset( 4 )] + public SMPTE smpte; + [FieldOffset( 4 )] + public MIDI midi; + [FieldOffset( 4 )] + public uint ms; + [FieldOffset( 4 )] + public uint sample; + [FieldOffset( 4 )] + public uint cb; + [FieldOffset( 4 )] + public uint ticks; } [StructLayout( LayoutKind.Sequential, CharSet = CharSet.Ansi )] @@ -279,7 +180,40 @@ namespace bocoree { } } + [StructLayout( LayoutKind.Sequential )] + public unsafe struct MIDIHDR { + public byte* lpData; + public DWORD dwBufferLength; + public DWORD dwBytesRecorded; + public DWORD dwUser; + public DWORD dwFlags; + public MIDIHDR* lpNext; + public DWORD reserved; + public DWORD dwOffset; + public fixed DWORD dwReserved[8]; + } + + [StructLayout( LayoutKind.Sequential )] + public struct MIDIOUTCAPSA { + public WORD wMid; + public WORD wPid; + public uint vDriverVersion; + [MarshalAs( UnmanagedType.ByValTStr, SizeConst = windows.MAXPNAMELEN )] + public string szPname; + public WORD wTechnology; + public WORD wVoices; + public WORD wNotes; + public WORD wChannelMask; + public DWORD dwSupport; + } + public static partial class windows { + private enum DllStatus { + Unknown, + Found, + NotFound, + } + public const uint JOYERR_NOERROR = 0; public const ushort JOY_RETURNX = 0x00000001; public const ushort JOY_RETURNY = 0x00000002; @@ -336,40 +270,496 @@ namespace bocoree { public const int WHDR_ENDLOOP = 0x00000008; /* loop end block */ public const int WHDR_INQUEUE = 0x00000010; /* reserved for driver */ - public const int TIME_MS = 0x0001; /* time in milliseconds */ - public const int TIME_SAMPLES= 0x0002; /* number of wave samples */ - public const int TIME_BYTES= 0x0004; /* current byte offset */ - public const int TIME_SMPTE = 0x0008; /* SMPTE time */ - public const int TIME_MIDI = 0x0010; /* MIDI time */ + public const int TIME_MS = 0x0001; /* time in milliseconds */ + public const int TIME_SAMPLES = 0x0002; /* number of wave samples */ + public const int TIME_BYTES = 0x0004; /* current byte offset */ + public const int TIME_SMPTE = 0x0008; /* SMPTE time */ + public const int TIME_MIDI = 0x0010; /* MIDI time */ public const int TIME_TICKS = 0x0020; /* Ticks within MIDI stream */ public const int MAXPNAMELEN = 32; public const int MAX_JOYSTICKOEMVXDNAME = 260; + public const uint MMSYSERR_NOERROR = 0; + public const uint MMSYSERR_ERROR = 1; + public const uint MMSYSERR_BADDEVICEID = 2; + public const uint MMSYSERR_NOTENABLED = 3; + public const uint MMSYSERR_ALLOCATED = 4; + public const uint MMSYSERR_INVALHANDLE = 5; + public const uint MMSYSERR_NODRIVER = 6; + public const uint MMSYSERR_NOMEM = 7; + public const uint MMSYSERR_NOTSUPPORTED = 8; + public const uint MMSYSERR_BADERRNUM = 9; + public const uint MMSYSERR_INVALFLAG = 10; + public const uint MMSYSERR_INVALPARAM = 11; + public const uint MMSYSERR_HANDLEBUSY = 12; + public const uint MMSYSERR_INVALIDALIAS = 13; + public const uint MMSYSERR_BADDB = 14; + public const uint MMSYSERR_KEYNOTFOUND = 15; + public const uint MMSYSERR_READERROR = 16; + public const uint MMSYSERR_WRITEERROR = 17; + public const uint MMSYSERR_DELETEERROR = 18; + public const uint MMSYSERR_VALNOTFOUND = 19; + public const uint MMSYSERR_NODRIVERCB = 20; + public const uint MMSYSERR_LASTERROR = 20; + + private static DllStatus status_winmm = DllStatus.Unknown; + private static DllStatus status_winmm_so = DllStatus.Unknown; + #region midi - [DllImport( "winmm.dll" )] - public static extern UINT midiInGetNumDevs(); - [DllImport( "winmm.dll" )] - public static unsafe extern MMRESULT midiInOpen( HMIDIIN* lphMidiIn, - UINT uDeviceID, - DWORD dwCallback, - DWORD dwCallbackInstance, - DWORD dwFlags ); + [DllImport( "winmm", EntryPoint = "midiInGetDevCaps", CharSet = CharSet.Ansi )] + [return: MarshalAs( UnmanagedType.U4 )] + private static extern uint __midiInGetDevCaps( [MarshalAs( UnmanagedType.U4 )]uint uDeviceID, ref MIDIINCAPS lpMidiInCaps, [MarshalAs( UnmanagedType.U4 )]uint cbMidiInCaps ); + + [DllImport( "winmm.dll.so", EntryPoint = "midiInGetDevCaps", CharSet = CharSet.Ansi )] + [return: MarshalAs( UnmanagedType.U4 )] + private static extern uint __so_midiInGetDevCaps( [MarshalAs( UnmanagedType.U4 )]uint uDeviceID, ref MIDIINCAPS lpMidiInCaps, [MarshalAs( UnmanagedType.U4 )]uint cbMidiInCaps ); + + public static uint midiInGetDevCaps( uint uDeviceID, ref MIDIINCAPS lpMidiInCaps, uint cbMidiInCaps ) { + uint ret = MMSYSERR_ERROR; + if ( status_winmm != DllStatus.NotFound ) { + try { + ret = __midiInGetDevCaps( uDeviceID, ref lpMidiInCaps, cbMidiInCaps ); + status_winmm = DllStatus.Found; + } catch ( DllNotFoundException ex ) { + status_winmm = DllStatus.NotFound; + } + } else if ( status_winmm_so != DllStatus.NotFound ) { + try { + ret = __so_midiInGetDevCaps( uDeviceID, ref lpMidiInCaps, cbMidiInCaps ); + } catch ( DllNotFoundException ex ) { + status_winmm_so = DllStatus.NotFound; + } + } + return ret; + } + + [DllImport( "winmm", EntryPoint = "midiInClose" )] + [return: MarshalAs( UnmanagedType.U4 )] + private static extern uint __midiInClose( uint hMidiIn ); + + [DllImport( "winmm.dll.so", EntryPoint = "midiInClose" )] + [return: MarshalAs( UnmanagedType.U4 )] + private static extern uint __so_midiInClose( uint hMidiIn ); + + public static uint midiInClose( uint hMidiIn ) { + uint ret = MMSYSERR_ERROR; + if ( status_winmm != DllStatus.NotFound ) { + try { + ret = __midiInClose( hMidiIn ); + } catch ( DllNotFoundException ex ) { + status_winmm = DllStatus.NotFound; + } + } else if ( status_winmm_so != DllStatus.NotFound ) { + try { + ret = __so_midiInClose( hMidiIn ); + } catch ( DllNotFoundException ex ) { + status_winmm_so = DllStatus.NotFound; + } + } + return ret; + } + + [DllImport( "winmm", EntryPoint = "midiInStart" )] + [return: MarshalAs( UnmanagedType.U4 )] + private static extern uint __midiInStart( uint hMidiIn ); + + [DllImport( "winmm.dll.so", EntryPoint = "midiInStart" )] + [return: MarshalAs( UnmanagedType.U4 )] + private static extern uint __so_midiInStart( uint hMidiIn ); + + public static uint midiInStart( uint hMidiIn ) { + uint ret = MMSYSERR_ERROR; + if ( status_winmm != DllStatus.NotFound ) { + try { + ret = __midiInStart( hMidiIn ); + } catch ( DllNotFoundException ex ) { + status_winmm = DllStatus.NotFound; + } + } else if ( status_winmm_so != DllStatus.NotFound ) { + try { + ret = __so_midiInStart( hMidiIn ); + } catch ( DllNotFoundException ex ) { + status_winmm_so = DllStatus.NotFound; + } + } + return ret; + } + + [DllImport( "winmm", EntryPoint = "midiInReset" )] + [return: MarshalAs( UnmanagedType.U4 )] + private static extern uint __midiInReset( uint hMidiIn ); + + [DllImport( "winmm.dll.so", EntryPoint = "midiInReset" )] + [return: MarshalAs( UnmanagedType.U4 )] + private static extern uint __so_midiInReset( uint hMidiIn ); + + public static uint midiInReset( uint hMidiIn ) { + uint ret = MMSYSERR_ERROR; + if ( status_winmm != DllStatus.NotFound ) { + try { + ret = __midiInReset( hMidiIn ); + } catch ( DllNotFoundException ex ) { + status_winmm = DllStatus.NotFound; + } + } else if ( status_winmm_so != DllStatus.NotFound ) { + try { + ret = __so_midiInReset( hMidiIn ); + } catch ( DllNotFoundException ex ) { + status_winmm_so = DllStatus.NotFound; + } + } + return ret; + } + + [DllImport( "winmm", EntryPoint = "midiInGetNumDevs" )] + [return: MarshalAs( UnmanagedType.U4 )] + private static extern uint __midiInGetNumDevs(); + + [DllImport( "winmm.dll.so", EntryPoint = "midiInGetNumDevs" )] + [return: MarshalAs( UnmanagedType.U4 )] + private static extern uint __so_midiInGetNumDevs(); + + public static uint midiInGetNumDevs() { + uint ret = 0; + if ( status_winmm != DllStatus.NotFound ) { + try { + ret = __midiInGetNumDevs(); + } catch ( DllNotFoundException ex ) { + status_winmm = DllStatus.NotFound; + } + } else if ( status_winmm_so != DllStatus.NotFound ) { + try { + ret = __so_midiInGetNumDevs(); + } catch ( DllNotFoundException ex ) { + status_winmm_so = DllStatus.NotFound; + } + } + return ret; + } + + [DllImport( "winmm", EntryPoint = "midiInOpen" )] + private static extern uint __midiInOpen( ref uint lphMidiIn, + int uDeviceID, + IntPtr dwCallback, + int dwCallbackInstance, + int dwFlags ); + + [DllImport( "winmm.dll.so", EntryPoint = "midiInOpen" )] + private static extern uint __so_midiInOpen( ref uint lphMidiIn, + int uDeviceID, + IntPtr dwCallback, + int dwCallbackInstance, + int dwFlags ); + + public static uint midiInOpen( ref uint lphMidiIn, + int uDeviceID, + IntPtr dwCallback, + int dwCallbackInstance, + int dwFlags ) { + uint ret = MMSYSERR_ERROR; + if ( status_winmm != DllStatus.NotFound ) { + try { + ret = __midiInOpen( ref lphMidiIn, uDeviceID, dwCallback, dwCallbackInstance, dwFlags ); + } catch ( DllNotFoundException ex ) { + status_winmm = DllStatus.NotFound; + } + } else if ( status_winmm_so != DllStatus.NotFound ) { + try { + ret = __so_midiInOpen( ref lphMidiIn, uDeviceID, dwCallback, dwCallbackInstance, dwFlags ); + } catch ( DllNotFoundException ex ) { + status_winmm_so = DllStatus.NotFound; + } + } + return ret; + } + + [DllImport( "winmm", EntryPoint = "midiOutGetNumDevs" )] + [return: MarshalAs( UnmanagedType.U4 )] + private static extern uint __midiOutGetNumDevs(); + + [DllImport( "winmm.dll.so", EntryPoint = "midiOutGetNumDevs" )] + [return: MarshalAs( UnmanagedType.U4 )] + private static extern uint __so_midiOutGetNumDevs(); + + public static uint midiOutGetNumDevs() { + uint ret = MMSYSERR_ERROR; + if ( status_winmm != DllStatus.NotFound ) { + try { + ret = __midiOutGetNumDevs(); + } catch ( DllNotFoundException ex ) { + status_winmm = DllStatus.NotFound; + } + } else if ( status_winmm_so != DllStatus.NotFound ) { + try { + ret = __so_midiOutGetNumDevs(); + } catch ( DllNotFoundException ex ) { + status_winmm_so = DllStatus.NotFound; + } + } + return ret; + } + + [DllImport( "winmm", EntryPoint = "midiOutGetDevCapsA", CharSet = CharSet.Ansi )] + [return: MarshalAs( UnmanagedType.U4 )] + private static extern uint __midiOutGetDevCapsA( [MarshalAs( UnmanagedType.U4 )] uint uDeviceID, + ref MIDIOUTCAPSA pMidiOutCaps, + [MarshalAs( UnmanagedType.U4 )] uint cbMidiOutCaps ); + + [DllImport( "winmm.dll.so", EntryPoint = "midiOutGetDevCapsA", CharSet = CharSet.Ansi )] + [return: MarshalAs( UnmanagedType.U4 )] + private static extern uint __so_midiOutGetDevCapsA( [MarshalAs( UnmanagedType.U4 )] uint uDeviceID, + ref MIDIOUTCAPSA pMidiOutCaps, + [MarshalAs( UnmanagedType.U4 )] uint cbMidiOutCaps ); + + public static uint midiOutGetDevCapsA( uint uDeviceID, ref MIDIOUTCAPSA pMidiOutCaps, uint cbMidiOutCaps ) { + uint ret = MMSYSERR_ERROR; + if ( status_winmm != DllStatus.NotFound ) { + try { + ret = __midiOutGetDevCapsA( uDeviceID, ref pMidiOutCaps, cbMidiOutCaps ); + } catch ( DllNotFoundException ex ) { + status_winmm = DllStatus.NotFound; + } + } else if ( status_winmm_so != DllStatus.NotFound ) { + try { + ret = __so_midiOutGetDevCapsA( uDeviceID, ref pMidiOutCaps, cbMidiOutCaps ); + } catch ( DllNotFoundException ex ) { + status_winmm_so = DllStatus.NotFound; + } + } + return ret; + } + + [DllImport( "winmm", EntryPoint = "midiOutOpen" )] + [return: MarshalAs( UnmanagedType.U4 )] + private static extern uint __midiOutOpen( [MarshalAs( UnmanagedType.SysUInt )] ref IntPtr lphMidiOut, + [MarshalAs( UnmanagedType.U4 )] uint uDeviceID, + [MarshalAs( UnmanagedType.FunctionPtr )] Delegate dwCallback, + [MarshalAs( UnmanagedType.U4 )] uint dwInstance, + [MarshalAs( UnmanagedType.U4 )] uint dwFlags ); + + [DllImport( "winmm.dll.so", EntryPoint = "midiOutOpen" )] + [return: MarshalAs( UnmanagedType.U4 )] + private static extern uint __so_midiOutOpen( [MarshalAs( UnmanagedType.SysUInt )] ref IntPtr lphMidiOut, + [MarshalAs( UnmanagedType.U4 )] uint uDeviceID, + [MarshalAs( UnmanagedType.FunctionPtr )] Delegate dwCallback, + [MarshalAs( UnmanagedType.U4 )] uint dwInstance, + [MarshalAs( UnmanagedType.U4 )] uint dwFlags ); + + public static uint midiOutOpen( ref IntPtr lphMidiOut, + uint uDeviceID, + Delegate dwCallback, + uint dwInstance, + uint dwFlags ) { + uint ret = MMSYSERR_ERROR; + if ( status_winmm != DllStatus.NotFound ) { + try { + ret = __midiOutOpen( ref lphMidiOut, uDeviceID, dwCallback, dwInstance, dwFlags ); + } catch ( DllNotFoundException ex ) { + status_winmm = DllStatus.NotFound; + } + } else if ( status_winmm_so != DllStatus.NotFound ) { + try { + ret = __so_midiOutOpen( ref lphMidiOut, uDeviceID, dwCallback, dwInstance, dwFlags ); + } catch ( DllNotFoundException ex ) { + status_winmm_so = DllStatus.NotFound; + } + } + return ret; + } + + [DllImport( "winmm", EntryPoint = "midiOutClose" )] + [return: MarshalAs( UnmanagedType.U4 )] + private static extern uint __midiOutClose( [MarshalAs( UnmanagedType.SysUInt )] IntPtr hMidiOut ); + + [DllImport( "winmm.dll.so", EntryPoint = "midiOutClose" )] + [return: MarshalAs( UnmanagedType.U4 )] + private static extern uint __so_midiOutClose( [MarshalAs( UnmanagedType.SysUInt )] IntPtr hMidiOut ); + + public static uint midiOutClose( IntPtr hMidiOut ) { + uint ret = MMSYSERR_ERROR; + if ( status_winmm != DllStatus.NotFound ) { + try { + ret = __midiOutClose( hMidiOut ); + } catch ( DllNotFoundException ex ) { + status_winmm = DllStatus.NotFound; + } + } else if ( status_winmm_so != DllStatus.NotFound ) { + try { + ret = __so_midiOutClose( hMidiOut ); + } catch ( DllNotFoundException ex ) { + status_winmm_so = DllStatus.NotFound; + } + } + return ret; + } + + [DllImport( "winmm", EntryPoint = "midiOutShortMsg" )] + [return: MarshalAs( UnmanagedType.U4 )] + private static extern uint __midiOutShortMsg( [MarshalAs( UnmanagedType.SysUInt )] IntPtr hMidiOut, [MarshalAs( UnmanagedType.U4 )] uint dwMsg ); + + [DllImport( "winmm.dll.so", EntryPoint = "midiOutShortMsg" )] + [return: MarshalAs( UnmanagedType.U4 )] + private static extern uint __so_midiOutShortMsg( [MarshalAs( UnmanagedType.SysUInt )] IntPtr hMidiOut, [MarshalAs( UnmanagedType.U4 )] uint dwMsg ); + + public static uint midiOutShortMsg( IntPtr hMidiOut, uint dwMsg ) { + uint ret = MMSYSERR_ERROR; + if ( status_winmm != DllStatus.NotFound ) { + try { + ret = __midiOutShortMsg( hMidiOut, dwMsg ); + } catch ( DllNotFoundException ex ) { + status_winmm = DllStatus.NotFound; + } + } else if ( status_winmm_so != DllStatus.NotFound ) { + try { + ret = __so_midiOutShortMsg( hMidiOut, dwMsg ); + } catch ( DllNotFoundException ex ) { + status_winmm_so = DllStatus.NotFound; + } + } + return ret; + } + + [DllImport( "winmm", EntryPoint = "midiOutLongMsg" )] + [return: MarshalAs( UnmanagedType.U4 )] + private static extern uint __midiOutLongMsg( [MarshalAs( UnmanagedType.SysUInt )] IntPtr hMidiOut, ref MIDIHDR lpMidiOutHdr, [MarshalAs( UnmanagedType.U4 )] uint uSize ); + + [DllImport( "winmm.dll.so", EntryPoint = "midiOutLongMsg" )] + [return: MarshalAs( UnmanagedType.U4 )] + private static extern uint __so_midiOutLongMsg( [MarshalAs( UnmanagedType.SysUInt )] IntPtr hMidiOut, ref MIDIHDR lpMidiOutHdr, [MarshalAs( UnmanagedType.U4 )] uint uSize ); + + public static uint midiOutLongMsg( IntPtr hMidiOut, ref MIDIHDR lpMidiOutHdr, uint uSize ) { + uint ret = MMSYSERR_ERROR; + if ( status_winmm != DllStatus.NotFound ) { + try { + ret = __midiOutLongMsg( hMidiOut, ref lpMidiOutHdr, uSize ); + } catch ( DllNotFoundException ex ) { + status_winmm = DllStatus.NotFound; + } + } else if ( status_winmm_so != DllStatus.NotFound ) { + try { + ret = __so_midiOutLongMsg( hMidiOut, ref lpMidiOutHdr, uSize ); + } catch ( DllNotFoundException ex ) { + status_winmm_so = DllStatus.NotFound; + } + } + return ret; + } + + [DllImport( "winmm", EntryPoint = "midiOutPrepareHeader" )] + [return: MarshalAs( UnmanagedType.U4 )] + private static extern uint __midiOutPrepareHeader( [MarshalAs( UnmanagedType.SysUInt )] IntPtr hMidiOut, ref MIDIHDR lpMidiOutHdr, [MarshalAs( UnmanagedType.U4 )] uint uSize ); + + [DllImport( "winmm.dll.so", EntryPoint = "midiOutPrepareHeader" )] + [return: MarshalAs( UnmanagedType.U4 )] + private static extern uint __so_midiOutPrepareHeader( [MarshalAs( UnmanagedType.SysUInt )] IntPtr hMidiOut, ref MIDIHDR lpMidiOutHdr, [MarshalAs( UnmanagedType.U4 )] uint uSize ); + + public static uint midiOutPrepareHeader( IntPtr hMidiOut, ref MIDIHDR lpMidiOutHdr, uint uSize ) { + uint ret = MMSYSERR_ERROR; + if ( status_winmm != DllStatus.NotFound ) { + try { + ret = __midiOutPrepareHeader( hMidiOut, ref lpMidiOutHdr, uSize ); + } catch ( DllNotFoundException ex ) { + status_winmm = DllStatus.NotFound; + } + } else if ( status_winmm_so != DllStatus.NotFound ) { + try { + ret = __so_midiOutPrepareHeader( hMidiOut, ref lpMidiOutHdr, uSize ); + } catch ( DllNotFoundException ex ) { + status_winmm_so = DllStatus.NotFound; + } + } + return ret; + } + + [DllImport( "winmm", EntryPoint = "midiOutUnprepareHeader" )] + [return: MarshalAs( UnmanagedType.U4 )] + private static extern uint __midiOutUnprepareHeader( [MarshalAs( UnmanagedType.SysUInt )] IntPtr hMidiOut, ref MIDIHDR lpMidiOutHdr, [MarshalAs( UnmanagedType.U4 )] uint uSize ); + + [DllImport( "winmm.dll.so", EntryPoint = "midiOutUnprepareHeader" )] + [return: MarshalAs( UnmanagedType.U4 )] + private static extern uint __so_midiOutUnprepareHeader( [MarshalAs( UnmanagedType.SysUInt )] IntPtr hMidiOut, ref MIDIHDR lpMidiOutHdr, [MarshalAs( UnmanagedType.U4 )] uint uSize ); + + public static uint midiOutUnprepareHeader( IntPtr hMidiOut, ref MIDIHDR lpMidiOutHdr, uint uSize ) { + uint ret = MMSYSERR_ERROR; + if ( status_winmm != DllStatus.NotFound ) { + try { + ret = __midiOutUnprepareHeader( hMidiOut, ref lpMidiOutHdr, uSize ); + } catch ( DllNotFoundException ex ) { + status_winmm = DllStatus.NotFound; + } + } else if ( status_winmm_so != DllStatus.NotFound ) { + try { + ret = __so_midiOutUnprepareHeader( hMidiOut, ref lpMidiOutHdr, uSize ); + } catch ( DllNotFoundException ex ) { + status_winmm_so = DllStatus.NotFound; + } + } + return ret; + } #endregion #region joy - [DllImport( "winmm.dll" )] + [DllImport( "winmm", EntryPoint = "joyGetNumDevs" )] [return: MarshalAs( UnmanagedType.U4 )] - public static extern uint joyGetNumDevs(); + private static extern uint __joyGetNumDevs(); - [DllImport( "winmm.dll" )] - public static extern uint joyGetPos( uint uJoyID, ref JOYINFO pji ); + public static uint joyGetNumDevs() { + uint ret = 0; + if ( status_winmm != DllStatus.NotFound ) { + try { + ret = __joyGetNumDevs(); + } catch ( DllNotFoundException ex ) { + status_winmm = DllStatus.NotFound; + } + } + return ret; + } - [DllImport( "winmm.dll" )] - public static extern uint joyGetDevCapsW( uint uJoyID, ref JOYCAPSW pjc, uint cbjc ); + [DllImport( "winmm", EntryPoint = "joyGetPos" )] + private static extern uint __joyGetPos( uint uJoyID, ref JOYINFO pji ); - [DllImport( "winmm.dll" )] - public static extern uint joyGetPosEx( uint uJoyID, ref JOYINFOEX pji ); + public static uint joyGetPos( uint uJoyID, ref JOYINFO pji ) { + uint ret = MMSYSERR_ERROR; + if ( status_winmm != DllStatus.NotFound ) { + try { + ret = __joyGetPos( uJoyID, ref pji ); + } catch ( DllNotFoundException ex ) { + status_winmm = DllStatus.NotFound; + } + } + return ret; + } + + [DllImport( "winmm", EntryPoint = "joyGetDevCapsW" )] + private static extern uint __joyGetDevCapsW( uint uJoyID, ref JOYCAPSW pjc, uint cbjc ); + + public static uint joyGetDevCapsW( uint uJoyID, ref JOYCAPSW pjc, uint cbjc ) { + uint ret = MMSYSERR_ERROR; + if ( status_winmm != DllStatus.NotFound ) { + try { + ret = __joyGetDevCapsW( uJoyID, ref pjc, cbjc ); + } catch ( DllNotFoundException ex ) { + status_winmm = DllStatus.NotFound; + } + } + return ret; + } + + [DllImport( "winmm", EntryPoint = "joyGetPosEx" )] + private static extern uint __joyGetPosEx( uint uJoyID, ref JOYINFOEX pji ); + + public static uint joyGetPosEx( uint uJoyID, ref JOYINFOEX pji ) { + uint ret = MMSYSERR_ERROR; + if ( status_winmm != DllStatus.NotFound ) { + try { + ret = __joyGetPosEx( uJoyID, ref pji ); + } catch ( DllNotFoundException ex ) { + status_winmm = DllStatus.NotFound; + } + } + return ret; + } #endregion #region wave @@ -384,16 +774,16 @@ namespace bocoree { IntPtr dwInstance, uint dwFlags ); //public static extern uint waveOutOpen( ref IntPtr phwo, UINT uDeviceID, ref WAVEFORMATEX pwfx, delegateWaveOutProc dwCallback, IntPtr dwInstance, uint fdwOpen ); - [DllImport("winmm.dll")] - public static extern uint waveOutPrepareHeader( IntPtr hwo, ref WAVEHDR pwh, UINT cbwh); - [DllImport( "winmm.dll")] - public static extern uint waveOutGetPosition( IntPtr hwo, ref MMTIME pmmt, UINT cbmmt); - [DllImport("winmm.dll")] - public static extern uint waveOutReset( IntPtr hwo); - [DllImport("winmm.dll")] - public static extern uint waveOutUnprepareHeader( IntPtr hwo, ref WAVEHDR pwh, UINT cbwh); - [DllImport("winmm.dll")] - public static extern uint waveOutClose( IntPtr hwo); + [DllImport( "winmm.dll" )] + public static extern uint waveOutPrepareHeader( IntPtr hwo, ref WAVEHDR pwh, UINT cbwh ); + [DllImport( "winmm.dll" )] + public static extern uint waveOutGetPosition( IntPtr hwo, ref MMTIME pmmt, UINT cbmmt ); + [DllImport( "winmm.dll" )] + public static extern uint waveOutReset( IntPtr hwo ); + [DllImport( "winmm.dll" )] + public static extern uint waveOutUnprepareHeader( IntPtr hwo, ref WAVEHDR pwh, UINT cbwh ); + [DllImport( "winmm.dll" )] + public static extern uint waveOutClose( IntPtr hwo ); #endregion #region mci