/* * SingerConfig.cs * Copyright (c) 2008-2009 kbinani * * This file is part of Boare.Lib.Vsq. * * Boare.Lib.Vsq is free software; you can redistribute it and/or * modify it under the terms of the BSD License. * * Boare.Lib.Vsq is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ using System; using System.IO; using System.Collections.Generic; namespace Boare.Lib.Vsq { 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++ ) { byte M = (byte)(dat[i] >> 4); byte L = (byte)(dat[i] - (M << 4)); byte newM = endecode_vvd_m( M ); byte newL = endecode_vvd_l( L ); dat[i] = (byte)((newM << 4) | newL); } } static byte endecode_vvd_l( byte value ) { switch ( value ) { case 0x0: return 0xa; case 0x1: return 0xb; case 0x2: return 0x8; case 0x3: return 0x9; case 0x4: return 0xe; case 0x5: return 0xf; case 0x6: return 0xc; case 0x7: return 0xd; case 0x8: return 0x2; case 0x9: return 0x3; case 0xa: return 0x0; case 0xb: return 0x1; case 0xc: return 0x6; case 0xd: return 0x7; case 0xe: return 0x4; case 0xf: return 0x5; } return 0x0; } static byte endecode_vvd_m( byte value ) { switch ( value ) { case 0x0: return 0x1; case 0x1: return 0x0; case 0x2: return 0x3; case 0x3: return 0x2; case 0x4: return 0x5; case 0x5: return 0x4; case 0x6: return 0x7; case 0x7: return 0x6; case 0x8: return 0x9; case 0x9: return 0x8; case 0xa: return 0xb; case 0xb: return 0xa; case 0xc: return 0xd; case 0xd: return 0xc; case 0xe: return 0xf; case 0xf: return 0xe; } return 0x0; } 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 ); int length = (int)fs.Length; byte[] dat = new byte[length]; fs.Read( dat, 0, length ); decode_vvd_bytes( ref dat ); for ( int i = 0; i < dat.Length - 1; i++ ) { if ( dat[i] == 0x17 && dat[i + 1] == 0x10 ) { dat[i] = 0x0d; dat[i + 1] = 0x0a; } } string str = bocoree.cp932.convert( dat ); string crlf = ((char)0x0d).ToString() + ((char)0x0a).ToString(); string[] spl = str.Split( new string[] { crlf }, StringSplitOptions.RemoveEmptyEntries ); foreach ( string s in spl ) { int first = s.IndexOf( '"' ); int first_end = get_quated_string( s, first ); int second = s.IndexOf( '"', first_end + 1 ); int second_end = get_quated_string( s, second ); char[] chs = s.ToCharArray(); string id = new string( chs, first, first_end - first + 1 ); string value = new string( chs, second, second_end - second + 1 ); id = id.Substring( 1, id.Length - 2 ); value = value.Substring( 1, value.Length - 2 ); value = value.Replace( "\\\"", "\"" ); if ( id == "ID" ) { sc.ID = value; } else if ( id == "FORMAT" ) { sc.FORMAT = value; } else if ( id == "VOICEIDSTR" ) { sc.VOICEIDSTR = value; } else if ( id == "VOICENAME" ) { sc.VOICENAME = value; } else if ( id == "Breathiness" ) { try { sc.Breathiness = int.Parse( value ); } catch { } } else if ( id == "Brightness" ) { try { sc.Brightness = int.Parse( value ); } catch { } } else if ( id == "Clearness" ) { try { sc.Clearness = int.Parse( value ); } catch { } } else if ( id == "Opening" ) { try { sc.Opening = int.Parse( value ); } catch { } } else if ( id == "Gender:Factor" ) { try { sc.GenderFactor = int.Parse( value ); } catch { } } } } catch { } finally { if ( fs != null ) { fs.Close(); } } return sc; } /// /// 位置positionにある'"'から,次に現れる'"'の位置を調べる.エスケープされた\"はスキップされる.'"'が見つからなかった場合-1を返す /// /// /// /// static int get_quated_string( string s, int position ) { if ( position < 0 ) { return -1; } char[] chs = s.ToCharArray(); if ( position >= chs.Length ) { return -1; } if ( chs[position] != '"' ) { return -1; } int end = -1; for ( int i = position + 1; i < chs.Length; i++ ) { if ( chs[i] == '"' && chs[i - 1] != '\\' ) { end = i; break; } } return end; } public string[] ToStringArray() { List ret = new List(); ret.Add( "\"ID\":=:\"" + ID + "\"" ); ret.Add( "\"FORMAT\":=:\"" + FORMAT + "\"" ); ret.Add( "\"VOICEIDSTR\":=:\"" + VOICEIDSTR + "\"" ); ret.Add( "\"VOICENAME\":=:\"" + VOICENAME.Replace( "\"", "\\\"" ) + "\"" ); ret.Add( "\"Breathiness\":=:\"" + Breathiness + "\"" ); ret.Add( "\"Brightness\":=:\"" + Brightness + "\"" ); ret.Add( "\"Clearness\":=:\"" + Clearness + "\"" ); ret.Add( "\"Opening\":=:\"" + Opening + "\"" ); 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; } } }