/* * VsqUtil.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.Text; using System.Collections.Generic; using bocoree; namespace Boare.Lib.Vsq { /// /// Represents the voice language of singer. /// public enum VsqVoiceLanguage : int { /// /// Default value, equivalent to "Japanese". /// Default = 0, /// /// Japanese /// Japanese = 0, /// /// English /// English = 1, } /// /// Static library to treat the information of VOCALOID2 system. /// public static class VsqUtil { /// /// Maximum number of singers which can be allowed in VOCALOID2 system. /// public const uint MAX_SINGERS = 0x4000; private static string s_dll2_path = ""; private static string s_dll1_path = ""; private static string s_exp_db_dir = ""; private static bool s_initialized = false; private static Dictionary s_singer_configs = null; private static List s_installed_singers = new List(); private static string s_editor_path = ""; public static double getAmplifyCoeffFromPanLeft( int pan ) { return pan / -64.0 + 1.0; } public static double getAmplifyCoeffFromPanRight( int pan ) { return pan / 64.0 + 1.0; } public static double getAmplifyCoeffFromFeder( int feder ) { return Math.Exp( -1.26697245e-02 + 1.18448420e-01 * feder / 10.0 ); } /// /// Gets the list of installed singers which is installed in the computer. /// /// public static SingerConfig[] getInstalledSingers() { return s_installed_singers.ToArray(); } /// /// Gets the list of singer configs. /// /// public static Dictionary getSingerConfigs() { Dictionary ret = new Dictionary(); foreach ( KeyValuePair kvp in s_singer_configs ) { ret.Add( kvp.Key, kvp.Value ); } return ret; } /// /// Gets the path of VOCALOID Editor. /// public static string getEditorPath() { if ( !s_initialized ) { init(); } return s_editor_path; } /// /// Gets the voice language of specified program change /// /// program change to get the voice language /// public static VsqVoiceLanguage getLanguage( int program_change ) { string name = getOriginalSinger( program_change ); switch ( name ) { case "Miku": case "Rin": case "Len": case "Rin_ACT2": case "Len_ACT2": case "Gackpoid": case "Luka_JPN": return VsqVoiceLanguage.Japanese; case "Sweet_Ann": case "Prima": case "Luka_ENG": return VsqVoiceLanguage.English; } return VsqVoiceLanguage.Default; } /// /// Gets the name of original singer of specified program change. /// /// /// public static string getOriginalSinger( int program_change ) { if ( s_singer_configs == null ) { loadSingerConfigs(); } if ( s_singer_configs.ContainsKey( program_change ) ) { SingerConfig sc = getSingerInfo( program_change ); string voiceidstr = sc.VOICEIDSTR; foreach ( SingerConfig installed in s_installed_singers ) { if ( installed.VOICEIDSTR == voiceidstr ) { return installed.VOICENAME; } } } return ""; } /// /// Gets the VsqID of program change. /// /// /// public static VsqID getSingerID( int program_change ) { VsqID ret = new VsqID( 0 ); ret.type = VsqIDType.Singer; SingerConfig sc = getSingerInfo( program_change ); int lang = 0; foreach ( SingerConfig sc2 in s_installed_singers ) { if ( sc.VOICEIDSTR == sc2.VOICEIDSTR ) { switch ( sc2.VOICENAME ) { case "Miku": lang = 0; break; } } } ret.IconHandle = new IconHandle(); ret.IconHandle.IconID = "$0701" + program_change.ToString( "0000" ); ret.IconHandle.IDS = sc.VOICENAME; ret.IconHandle.Index = 0; ret.IconHandle.Language = lang; ret.IconHandle.Length = 1; ret.IconHandle.Original = sc.Original; ret.IconHandle.Program = program_change; ret.IconHandle.Caption = ""; return ret; } /// /// Gets the singer information of pecified program change. /// /// /// public static SingerConfig getSingerInfo( int program_change ) { if ( s_singer_configs == null ) { loadSingerConfigs(); } if ( s_singer_configs.ContainsKey( program_change ) ) { return s_singer_configs[program_change]; } else { return null; } } /// /// Loads the singer config from ExpDbPath. /// This method will automatically called when GetSingerInfo method or GetSingerID method is called in first time. /// public static void loadSingerConfigs() { if ( s_singer_configs == null ) { loadSingerConfigs( getExpDbPath() ); } } /// /// Loads the list of singer configuration from the specified path. /// Keys in the dictionary "s_singer_configs" represents the program change of each singer. /// /// /// private static void loadSingerConfigs( string path ) { #if DEBUG bocoree.debug.push_log( "SingerConfig+LoadSingerConfigs(String)" ); #endif s_singer_configs = new Dictionary(); string map_file = Path.Combine( path, "voice.map" ); if ( !File.Exists( map_file ) ) { return; } using ( FileStream fs = new FileStream( map_file, FileMode.Open, FileAccess.Read ) ) { byte[] dat = new byte[8]; fs.Seek( 0x20, SeekOrigin.Begin ); for ( int i = 0; i < MAX_SINGERS; i++ ) { fs.Read( dat, 0, 8 ); ulong value = makelong_le( dat ); if ( value >= 1 ) { string file = Path.Combine( path, "vvoice" + value + ".vvd" ); if ( File.Exists( file ) ) { s_singer_configs.Add( i, new SingerConfig( file, (int)(value - 1) ) ); } } } } List voiceidstrs = new List(); foreach ( SingerConfig sc in s_singer_configs.Values ) { if ( !voiceidstrs.Contains( sc.VOICEIDSTR ) ) { voiceidstrs.Add( sc.VOICEIDSTR ); } } foreach ( string s in voiceidstrs ) { string dir = Path.Combine( path, s ); string[] files = Directory.GetFiles( dir, "*.vvd" ); foreach ( string s2 in files ) { string file = Path.Combine( dir, s2 ); if ( File.Exists( file ) ) { s_installed_singers.Add( new SingerConfig( file, -1 ) ); } } } #if DEBUG bocoree.debug.push_log( " s_singer_configs" ); foreach ( SingerConfig sc in s_singer_configs.Values ) { bocoree.debug.push_log( " VOICENAME=" + sc.VOICENAME ); } bocoree.debug.push_log( " s_installed_singers" ); foreach( SingerConfig sc in s_installed_singers ){ bocoree.debug.push_log( " VOICENAME=" + sc.VOICENAME ); } #endif } /// /// Transform the byte array(length=8) to unsigned long, assuming that the byte array is little endian. /// /// /// private static ulong makelong_le( byte[] oct ) { return (ulong)oct[7] << 56 | (ulong)oct[6] << 48 | (ulong)oct[5] << 40 | (ulong)oct[4] << 32 | (ulong)oct[3] << 24 | (ulong)oct[2] << 16 | (ulong)oct[1] << 8 | (ulong)oct[0]; } /// /// Gets the path of VOCALOID2 Playback VSTi dll. /// /// public static string getDllPathVsti2() { if ( !s_initialized ) { init(); } return s_dll2_path; } /// /// Gets the path of VOCALOID1 Playback VSTi dll. /// /// public static string getDllPathVsti1() { if ( !s_initialized ) { init(); } return s_dll1_path; } /// /// Initializes the library. /// private static void init() { try { #if DEBUG bocoree.debug.push_log( "VsqUtil+Init()" ); #endif // vocaloid2 dll path Microsoft.Win32.RegistryKey regkey_dll = null; regkey_dll = Microsoft.Win32.Registry.LocalMachine.OpenSubKey( "SOFTWARE\\VOCALOID2\\APPLICATION", false ); if ( regkey_dll == null ) { regkey_dll = Microsoft.Win32.Registry.LocalMachine.OpenSubKey( "SOFTWARE\\VOCALOID2_DEMO\\APPLICATION", false ); } if ( regkey_dll != null ) { string[] keys = regkey_dll.GetSubKeyNames(); for ( int i = 0; i < keys.Length; i++ ) { Microsoft.Win32.RegistryKey key = regkey_dll.OpenSubKey( keys[i], false ); if ( key != null ) { string name = (string)key.GetValue( "PATH" ); if ( name.ToLower().EndsWith( "\\vocaloid2.dll" ) ) { s_dll2_path = name; } else if ( name.ToLower().EndsWith( "\\vocaloid2_demo.dll" ) ) { s_dll2_path = name; } else if ( name.ToLower().EndsWith( "\\vocaloid2.exe" ) ) { s_editor_path = name; } key.Close(); } } regkey_dll.Close(); } // vocaloid1 dll path Microsoft.Win32.RegistryKey regkey_dll1 = null; regkey_dll1 = Microsoft.Win32.Registry.LocalMachine.OpenSubKey( "SOFTWARE\\VOCALOID\\APPLICATION", false ); if ( regkey_dll1 != null ){ string[] keys = regkey_dll1.GetSubKeyNames(); for ( int i = 0; i < keys.Length; i++ ) { Microsoft.Win32.RegistryKey key = regkey_dll1.OpenSubKey( keys[i], false ); if ( key != null ) { string name = (string)key.GetValue( "PATH" ); if ( name.ToLower().EndsWith( "\\vocaloid.dll" ) ) { s_dll1_path = name; key.Close(); break; } key.Close(); } } regkey_dll1.Close(); } // voicedbdir Microsoft.Win32.RegistryKey regkey_voicedb = Microsoft.Win32.Registry.LocalMachine.OpenSubKey( "SOFTWARE\\VOCALOID2\\DATABASE\\VOICE", false ); if ( regkey_voicedb == null ) { regkey_voicedb = Microsoft.Win32.Registry.LocalMachine.OpenSubKey( "SOFTWARE\\VOCALOID2_DEMO\\DATABASE\\VOICE", false ); } if ( regkey_voicedb != null ) { string[] keys = regkey_voicedb.GetSubKeyNames(); for ( int i = 0; i < keys.Length; i++ ) { Microsoft.Win32.RegistryKey key = regkey_voicedb.OpenSubKey( keys[i], false ); if ( key != null ) { string name = (string)key.GetValue( "INSTALLDIR" ); if ( name.ToLower().EndsWith( "\\voicedbdir" ) ) { s_exp_db_dir = name; break; } key.Close(); } } regkey_voicedb.Close(); } } catch ( Exception ex ) { bocoree.debug.push_log( "VsqUtil.Init" ); bocoree.debug.push_log( " ex=" + ex ); } finally { s_initialized = true; #if DEBUG bocoree.debug.push_log( " s_dll2_path=" + s_dll2_path ); bocoree.debug.push_log( " s_exp_db_dir=" + s_exp_db_dir ); #endif } } /// /// Gets the path of directories in which singer expression database is installed. /// /// public static string getExpDbPath() { if ( !s_initialized ) { init(); } return s_exp_db_dir; } } }