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

827 lines
37 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

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

/*
* VocaloSysUtil.s
* Copyright (c) 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;
using Microsoft.Win32;
using bocoree;
namespace Boare.Lib.Vsq {
using boolean = Boolean;
public static class VocaloSysUtil{
private static SingerConfigSys s_singer_config_sys1;
private static SingerConfigSys s_singer_config_sys2;
private static ExpressionConfigSys s_exp_config_sys1;
private static ExpressionConfigSys s_exp_config_sys2;
private static String s_path_vsti1 = "";
private static String s_path_vsti2 = "";
private static String s_path_editor1 = "";
private static String s_path_editor2 = "";
static VocaloSysUtil() {
try {
Vector<String> dir1 = new Vector<String>();
RegistryKey key1 = Registry.LocalMachine.OpenSubKey( "SOFTWARE\\VOCALOID", false );
String path_voicedb1 = "";
String path_expdb1 = "";
Vector<String> installed_singers1 = new Vector<String>();
if ( key1 != null ) {
String header1 = "HKLM\\SOFTWARE\\VOCALOID";
print( key1, header1, dir1 );
key1.Close();
extract( dir1,
header1,
out s_path_vsti1,
out path_voicedb1,
out path_expdb1,
out s_path_editor1,
installed_singers1 );
}
s_singer_config_sys1 = new SingerConfigSys( path_voicedb1, installed_singers1.toArray( new String[] { } ) );
s_exp_config_sys1 = new ExpressionConfigSys( path_expdb1 );
}catch( Exception ex ){
Console.WriteLine( "VocaloSysUtil..cctor; ex=" + ex );
s_singer_config_sys1 = new SingerConfigSys( "", new String[] { } );
s_exp_config_sys1 = new ExpressionConfigSys( "" );
}
try{
Vector<String> dir2 = new Vector<String>();
RegistryKey key2 = Registry.LocalMachine.OpenSubKey( "SOFTWARE\\VOCALOID2", false );
String path_voicedb2 = "";
String path_expdb2 = "";
Vector<String> installed_singers2 = new Vector<String>();
if ( key2 != null ) {
String header2 = "HKLM\\SOFTWARE\\VOCALOID2";
print( key2, header2, dir2 );
key2.Close();
extract( dir2,
header2,
out s_path_vsti2,
out path_voicedb2,
out path_expdb2,
out s_path_editor2,
installed_singers2 );
}
s_singer_config_sys2 = new SingerConfigSys( path_voicedb2, installed_singers2.toArray( new String[] { } ) );
s_exp_config_sys2 = new ExpressionConfigSys( path_expdb2 );
} catch ( Exception ex ) {
Console.WriteLine( "VocaloSysUtil..cctor; ex=" + ex );
s_singer_config_sys2 = new SingerConfigSys( "", new String[] { } );
s_exp_config_sys2 = new ExpressionConfigSys( "" );
}
}
private static void extract( Vector<String> dir,
String header,
out String path_vsti,
out String path_voicedb,
out String path_expdb,
out String path_editor,
Vector<String> installed_singers ) {
Vector<String> application = new Vector<String>();
Vector<String> expression = new Vector<String>();
Vector<String> voice = new Vector<String>();
path_vsti = "";
path_expdb = "";
path_voicedb = "";
path_editor = "";
for( Iterator itr = dir.iterator(); itr.hasNext(); ) {
String s = (String)itr.next();
if ( s.StartsWith( header + "\\APPLICATION" ) ) {
application.add( s.Substring( (header + "\\APPLICATION").Length ) );
} else if ( s.StartsWith( header + "\\DATABASE\\EXPRESSION" ) ) {
expression.add( s.Substring( (header + "\\DATABASE\\EXPRESSION").Length ) );
} else if ( s.StartsWith( header + "\\DATABASE\\VOICE" ) ) {
voice.add( s.Substring( (header + "\\DATABASE\\VOICE\\").Length ) );
}
}
// path_vstiを取得
for( Iterator itr = application.iterator(); itr.hasNext(); ){
String s = (String)itr.next();
String[] spl = s.Split( '\t' );
if ( spl.Length >= 3 && spl[1].Equals( "PATH" ) ){
if ( spl[2].ToLower().EndsWith( ".dll" ) ) {
path_vsti = spl[2];
} else if ( spl[2].ToLower().EndsWith( ".exe" ) ) {
path_editor = spl[2];
}
}
}
// path_vicedbを取得
Vector<String> voice_ids = new Vector<String>();
// 最初はpath_voicedbの取得と、idBHXXXXXXXXXXXXXXXXのようなシリアルを取得
for( Iterator itr = voice.iterator(); itr.hasNext(); ){
String s = (String)itr.next();
String[] spl = s.Split( '\t' );
if ( spl.Length >= 2 ) {
if ( spl[0].Equals( "VOICEDIR" ) ) {
path_voicedb = spl[1];
} else if ( spl.Length >= 3 ) {
String[] spl2 = spl[0].Split( '\\' );
if ( spl2.Length == 1 ) {
if ( !voice_ids.contains( spl2[0] ) ) {
voice_ids.add( spl2[0] );
}
}
}
}
}
// 取得したシリアルを元に、installed_singersを取得
for( Iterator itr = voice_ids.iterator(); itr.hasNext(); ) {
String s = (String)itr.next();
String install_dir = "";
for( Iterator itr2 = voice.iterator(); itr2.hasNext(); ){
String s2 = (String)itr2.next();
if ( s2.StartsWith( header + "\\" + s + "\t" ) ) {
String[] spl = s2.Split( '\t' );
if ( spl.Length >= 3 && spl[1].Equals( "INSTALLDIR" ) ) {
install_dir = Path.Combine( spl[2], s );
break;
}
}
}
if ( install_dir.Equals( "" ) ) {
install_dir = Path.Combine( path_voicedb, s );
}
installed_singers.add( install_dir );
}
// path_expdbを取得
Vector<String> exp_ids = new Vector<String>();
// 最初はpath_expdbの取得と、idBHXXXXXXXXXXXXXXXXのようなシリアルを取得
for( Iterator itr = expression.iterator(); itr.hasNext(); ){
String s = (String)itr.next();
String[] spl = s.Split( '\t' );
if ( spl.Length >= 2 ) {
if ( spl[0].Equals( "EXPRESSIONDIR" ) ) {
path_expdb = spl[1];
} else if ( spl.Length >= 3 ) {
String[] spl2 = spl[0].Split( '\\' );
if ( spl2.Length == 1 ) {
if ( !exp_ids.contains( spl2[0] ) ) {
exp_ids.add( spl2[0] );
}
}
}
}
}
// 取得したシリアルを元に、installed_singersを取得
/*foreach ( String s in exp_ids ) {
String install_dir = "";
foreach ( String s2 in expression ) {
if ( s2.StartsWith( header + "\\" + s + "\t" ) ) {
String[] spl = s2.Split( '\t' );
if ( spl.Length >= 3 && spl[1].Equals( "INSTALLDIR" ) ) {
install_dir = Path.Combine( spl[2], s );
break;
}
}
}
if ( install_dir.Equals( "" ) ) {
install_dir = Path.Combine( path_expdb, s );
}
installed_singers.Add( install_dir );
}*/
#if DEBUG
Console.WriteLine( "path_vsti=" + path_vsti );
Console.WriteLine( "path_voicedb=" + path_voicedb );
Console.WriteLine( "path_expdb=" + path_expdb );
Console.WriteLine( "installed_singers=" );
for( Iterator itr = installed_singers.iterator(); itr.hasNext(); ){
String s = (String)itr.next();
Console.WriteLine( " " + s );
}
#endif
}
// レジストリkey内の値を再帰的に検索し、ファイルfpに順次出力する
private static void print( RegistryKey key, String parent_name, Vector<String> list ){
if ( key == null ) {
return;
}
// 直下のキー内を再帰的にリストアップ
String[] subkeys = key.GetSubKeyNames();
foreach( String s in subkeys ){
RegistryKey subkey = key.OpenSubKey( s, false );
print( subkey, parent_name + "\\" + s, list );
subkey.Close();
}
// 直下の値を出力
String[] valuenames = key.GetValueNames();
foreach( String s in valuenames ){
RegistryValueKind kind = key.GetValueKind( s );
if ( kind == RegistryValueKind.String ){
String str = parent_name + "\t" + s + "\t" + (String)key.GetValue( s, "" );
list.add( str );
}
}
}
/// <summary>
/// Gets the name of original singer of specified program change.
/// </summary>
/// <param name="singer"></param>
/// <returns></returns>
public static String getOriginalSinger1( String singer ) {
String voiceidstr = "";
SingerConfig[] singer_configs = s_singer_config_sys1.getSingerConfigs();
for ( int i = 0; i < singer_configs.Length; i++ ) {
if ( singer.Equals( singer_configs[i].VOICENAME ) ) {
voiceidstr = singer_configs[i].VOICEIDSTR;
break;
}
}
if ( voiceidstr.Equals( "" ) ) {
return "";
}
SingerConfig[] installed_singers = s_singer_config_sys1.getInstalledSingers();
for ( int i = 0; i < installed_singers.Length; i++ ) {
if ( voiceidstr.Equals( installed_singers[i].VOICEIDSTR ) ) {
return installed_singers[i].VOICENAME;
}
}
return "";
}
/// <summary>
/// Gets the name of original singer of specified program change.
/// </summary>
/// <param name="singer"></param>
/// <returns></returns>
public static String getOriginalSinger2( String singer ) {
String voiceidstr = "";
SingerConfig[] singer_configs = s_singer_config_sys2.getSingerConfigs();
for ( int i = 0; i < singer_configs.Length; i++ ) {
if ( singer.Equals( singer_configs[i].VOICENAME ) ) {
voiceidstr = singer_configs[i].VOICEIDSTR;
break;
}
}
if ( voiceidstr.Equals( "" ) ) {
return "";
}
SingerConfig[] installed_singers = s_singer_config_sys2.getInstalledSingers();
for ( int i = 0; i < installed_singers.Length; i++ ) {
if ( voiceidstr.Equals( installed_singers[i].VOICEIDSTR ) ) {
return installed_singers[i].VOICENAME;
}
}
return "";
}
public static VsqID getSingerID1( String singer ) {
return s_singer_config_sys1.getSingerID( singer );
}
public static VsqID getSingerID2( String singer ) {
return s_singer_config_sys2.getSingerID( singer );
}
public static String getEditorPath1() {
return s_path_editor1;
}
public static String getEditorPath2() {
return s_path_editor2;
}
public static String getDllPathVsti1() {
return s_path_vsti1;
}
public static String getDllPathVsti2() {
return s_path_vsti2;
}
public static SingerConfig[] getSingerConfigs1() {
return s_singer_config_sys1.getSingerConfigs();
}
public static SingerConfig[] getSingerConfigs2() {
return s_singer_config_sys2.getSingerConfigs();
}
/// <summary>
/// Gets the voice language of specified program change
/// </summary>
/// <param name="name">name of singer</param>
/// <returns></returns>
public static VsqVoiceLanguage getLanguageFromName( String name ) {
switch ( name.ToLower() ) {
case "meiko":
case "kaito":
case "miku":
case "rin":
case "len":
case "rin_act2":
case "len_act2":
case "gackpoid":
case "luka_jpn":
case "megpoid":
return VsqVoiceLanguage.Japanese;
case "sweet_ann":
case "prima":
case "luka_eng":
case "sonika":
return VsqVoiceLanguage.English;
}
return VsqVoiceLanguage.Default;
}
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 );
}
/// <summary>
/// Transform the byte array(length=8) to unsigned long, assuming that the byte array is little endian.
/// </summary>
/// <param name="oct"></param>
/// <returns></returns>
public 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];
}
}
public static class VocaloSysUtil_ {
private static boolean s_initialized = false;
private static String s_dll_path2 = "";
private static String s_editor_path2 = "";
private static String s_voicedbdir2 = "";
private static Vector<SingerConfig> s_installed_singers2 = new Vector<SingerConfig>();
private static Vector<SingerConfig> s_singer_configs2 = new Vector<SingerConfig>();
private static String s_dll_path1 = "";
private static String s_editor_path1 = "";
private static String s_voicedbdir1 = "";
private static Vector<SingerConfig> s_installed_singers1 = new Vector<SingerConfig>();
private static Vector<SingerConfig> s_singer_configs1 = new Vector<SingerConfig>();
private const int MAX_SINGERS = 0x4000;
static VocaloSysUtil_() {
init_vocalo2();
init_vocalo1();
}
/// <summary>
/// Gets the name of original singer of specified program change.
/// </summary>
/// <param name="singer"></param>
/// <returns></returns>
public static String getOriginalSinger1( String singer ) {
String voiceidstr = "";
for ( int i = 0; i < s_singer_configs1.size(); i++ ) {
if ( singer.Equals( s_singer_configs1.get( i ).VOICENAME ) ) {
voiceidstr = s_singer_configs1.get( i ).VOICEIDSTR;
}
}
if ( voiceidstr.Equals( "" ) ) {
return "";
}
for ( int i = 0; i < s_installed_singers1.size(); i++ ) {
if ( voiceidstr.Equals( s_installed_singers1.get( i ).VOICEIDSTR ) ) {
return s_installed_singers1.get( i ).VOICENAME;
}
}
return "";
}
/// <summary>
/// Gets the name of original singer of specified program change.
/// </summary>
/// <param name="singer"></param>
/// <returns></returns>
public static String getOriginalSinger2( String singer ) {
String voiceidstr = "";
for ( int i = 0; i < s_singer_configs2.size(); i++ ) {
if ( singer.Equals( s_singer_configs2.get( i ).VOICENAME ) ) {
voiceidstr = s_singer_configs2.get( i ).VOICEIDSTR;
}
}
if ( voiceidstr.Equals( "" ) ) {
return "";
}
for ( int i = 0; i < s_installed_singers2.size(); i++ ) {
if ( voiceidstr.Equals( s_installed_singers2.get( i ).VOICEIDSTR ) ) {
return s_installed_singers2.get( i ).VOICENAME;
}
}
return "";
}
/// <summary>
/// Gets the voice language of specified program change
/// </summary>
/// <param name="name">name of singer</param>
/// <returns></returns>
public static VsqVoiceLanguage getLanguageFromName( String name ) {
switch ( name ) {
case "MEIKO":
case "KAITO":
case "Miku":
case "Rin":
case "Len":
case "Rin_ACT2":
case "Len_ACT2":
case "Gackpoid":
case "Luka_JPN":
case "Megpoid":
return VsqVoiceLanguage.Japanese;
case "Sweet_Ann":
case "Prima":
case "Luka_ENG":
return VsqVoiceLanguage.English;
}
return VsqVoiceLanguage.Default;
}
public static VsqID getSingerID1( String singer_name ) {
VsqID ret = new VsqID( 0 );
ret.type = VsqIDType.Singer;
SingerConfig sc = null;
for ( int i = 0; i < s_singer_configs1.size(); i++ ) {
if ( s_singer_configs1.get( i ).VOICENAME.Equals( singer_name ) ) {
sc = s_singer_configs1.get( i );
break;
}
}
if ( sc == null ) {
sc = new SingerConfig();
}
int lang = 0;
for ( Iterator itr = s_installed_singers1.iterator(); itr.hasNext(); ){
SingerConfig sc2 = (SingerConfig)itr.next();
if ( sc.VOICEIDSTR.Equals( sc2.VOICEIDSTR ) ) {
lang = (int)getLanguageFromName( sc.VOICENAME );
break;
}
}
ret.IconHandle = new IconHandle();
ret.IconHandle.IconID = "$0701" + sc.Program.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 = sc.Program;
ret.IconHandle.Caption = "";
return ret;
}
public static VsqID getSingerID2( String singer_name ) {
VsqID ret = new VsqID( 0 );
ret.type = VsqIDType.Singer;
SingerConfig sc = null;
for ( int i = 0; i < s_singer_configs2.size(); i++ ) {
if ( s_singer_configs2.get( i ).VOICENAME.Equals( singer_name ) ) {
sc = s_singer_configs2.get( i );
break;
}
}
if ( sc == null ) {
sc = new SingerConfig();
}
int lang = 0;
for ( Iterator itr = s_installed_singers2.iterator(); itr.hasNext(); ){
SingerConfig sc2 = (SingerConfig)itr.next();
if ( sc.VOICEIDSTR.Equals( sc2.VOICEIDSTR ) ) {
lang = (int)getLanguageFromName( sc.VOICENAME );
break;
}
}
ret.IconHandle = new IconHandle();
ret.IconHandle.IconID = "$0701" + sc.Program.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 = sc.Program;
ret.IconHandle.Caption = "";
return ret;
}
public static SingerConfig[] getSingerConfigs1() {
return s_singer_configs1.toArray( new SingerConfig[]{} );
}
public static SingerConfig[] getSingerConfigs2() {
return s_singer_configs2.toArray( new SingerConfig[]{} );
}
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 );
}
public static String getEditorPath2() {
return s_editor_path2;
}
public static String getEditorPath1() {
return s_editor_path1;
}
public static String getDllPathVsti2() {
return s_dll_path2;
}
public static String getDllPathVsti1() {
return s_dll_path1;
}
/// <summary>
/// VOCALOID1システムのプロパティを取得
/// </summary>
private static void init_vocalo1() {
// vocaloid1 dll path
RegistryKey v1application = null;
v1application = Registry.LocalMachine.OpenSubKey( "SOFTWARE\\VOCALOID\\APPLICATION", false );
if ( v1application != null ) {
String[] keys = v1application.GetSubKeyNames();
for ( int i = 0; i < keys.Length; i++ ) {
RegistryKey key = v1application.OpenSubKey( keys[i], false );
if ( key != null ) {
String name = (String)key.GetValue( "PATH" );
if ( name.ToLower().EndsWith( "\\vocaloid.dll" ) ) {
s_dll_path1 = name;
} else if ( name.ToLower().EndsWith( "\\vocaloid.exe" ) ) {
s_editor_path1 = name;
}
key.Close();
}
}
v1application.Close();
}
// voicedbdir for vocaloid1
RegistryKey v1database = Registry.LocalMachine.OpenSubKey( "SOFTWARE\\VOCALOID\\DATABASE\\VOICE", false );
if ( v1database != null ) {
s_voicedbdir1 = (String)v1database.GetValue( "VOICEDIR", "" );
#if DEBUG
Console.WriteLine( "s_voicedbdir1=" + s_voicedbdir1 );
#endif
// インストールされている歌手のVOICEIDSTRを列挙
String[] singer_voiceidstrs = v1database.GetSubKeyNames();
Vector<String> vvoice_keys = new Vector<String>();
Vector<SingerConfig> vvoice_values = new Vector<SingerConfig>();
foreach ( String voiceidstr in singer_voiceidstrs ) {
RegistryKey singer = v1database.OpenSubKey( voiceidstr );
if ( singer == null ) {
continue;
}
RegistryKey vvoice = singer.OpenSubKey( "vvoice" );
if ( vvoice != null ) {
String[] vvoices = vvoice.GetValueNames();
// インストールされた歌手の.vvdを読みにいく
// installdir以下の、拡張子.vvdのファイルを探す
foreach ( String file in Directory.GetFiles( Path.Combine( s_voicedbdir1, voiceidstr ), "*.vvd" ) ) {
SingerConfig config = SingerConfig.fromVvd( file, 0 ); //とりあえずプログラムチェンジは0
s_installed_singers1.add( config );
}
// vvoice*.vvdを読みにいく。
foreach ( String s in vvoices ) {
#if DEBUG
Console.WriteLine( "s=" + s );
#endif
String file = Path.Combine( s_voicedbdir1, s + ".vvd" );
if ( File.Exists( file ) ) {
SingerConfig config = SingerConfig.fromVvd( file, 0 );
vvoice_keys.add( s );
vvoice_values.add( config );
}
}
}
singer.Close();
}
// voice.mapを読み込んで、s_singer_configs1のプログラムチェンジを更新する
String map = Path.Combine( s_voicedbdir1, "voice.map" );
if ( File.Exists( map ) ) {
using ( FileStream fs = new FileStream( map, 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 ) {
#if DEBUG
Console.WriteLine( "value=" + value );
#endif
for ( int j = 0; j < vvoice_keys.size(); j++ ) {
if ( vvoice_keys.get( j ).Equals( "vvoice" + value ) ) {
vvoice_values.get( j ).Program = i;
}
}
}
}
}
}
// s_installed_singers1のSingerConfigのProgramとOriginalを適当に頒番する
for ( int i = 0; i < s_installed_singers1.size(); i++ ) {
s_installed_singers1.get( i ).Program = i;
s_installed_singers1.get( i ).Original = i;
}
// s_singer_configs1を更新
for ( int i = 0; i < vvoice_values.size(); i++ ) {
for ( int j = 0; j < s_installed_singers1.size(); j++ ) {
if ( vvoice_values.get( i ).VOICEIDSTR.Equals( s_installed_singers1.get( j ).VOICEIDSTR ) ) {
vvoice_values.get( i ).Original = s_installed_singers1.get( j ).Program;
break;
}
}
s_singer_configs1.add( vvoice_values.get( i ) );
}
v1database.Close();
}
#if DEBUG
Console.WriteLine( "installed" );
for ( Iterator itr = s_installed_singers1.iterator(); itr.hasNext(); ){
SingerConfig sc = (SingerConfig)itr.next();
Console.WriteLine( "VOICENAME=" + sc.VOICENAME + "; VOICEIDSTR=" + sc.VOICEIDSTR + "; Program=" + sc.Program + "; Original=" + sc.Original );
}
Console.WriteLine( "singer configs" );
for ( Iterator itr = s_singer_configs1.iterator(); itr.hasNext(); ){
SingerConfig sc = (SingerConfig)itr.next();
Console.WriteLine( "VOICENAME=" + sc.VOICENAME + "; VOICEIDSTR=" + sc.VOICEIDSTR + "; Program=" + sc.Program + "; Original=" + sc.Original );
}
#endif
}
/// <summary>
/// VOCALOID2システムのプロパティを取得
/// </summary>
private static void init_vocalo2() {
// 最初はvstiとeditorのパスを取得
RegistryKey v2application = Registry.LocalMachine.OpenSubKey( "SOFTWARE\\VOCALOID2\\APPLICATION", false );
if ( v2application == null ) {
v2application = Registry.LocalMachine.OpenSubKey( "SOFTWARE\\VOCALOID2_DEMO\\APPLICATION", false );
}
if ( v2application != null ) {
String[] keys = v2application.GetSubKeyNames();
for ( int i = 0; i < keys.Length; i++ ) {
RegistryKey key = v2application.OpenSubKey( keys[i], false );
if ( key != null ) {
String name = (String)key.GetValue( "PATH" );
if ( name.ToLower().EndsWith( "\\vocaloid2.dll" ) ) {
s_dll_path2 = name;
} else if ( name.ToLower().EndsWith( "\\vocaloid2_demo.dll" ) ) {
s_dll_path2 = name;
} else if ( name.ToLower().EndsWith( "\\vocaloid2.exe" ) ) {
s_editor_path2 = name;
}
key.Close();
}
}
v2application.Close();
}
// 歌声データベースを取得
RegistryKey v2database = Registry.LocalMachine.OpenSubKey( "SOFTWARE\\VOCALOID2\\DATABASE\\VOICE", false );
if ( v2database != null ) {
// データベースというよりもvoice.mapが保存されているパスを取得
s_voicedbdir2 = (String)v2database.GetValue( "VOICEDIR", "" );
// インストールされている歌手のVOICEIDSTRを列挙
String[] singer_voiceidstrs = v2database.GetSubKeyNames();
Vector<String> vvoice_keys = new Vector<String>();
Vector<SingerConfig> vvoice_values = new Vector<SingerConfig>();
foreach ( String voiceidstr in singer_voiceidstrs ) {
RegistryKey singer = v2database.OpenSubKey( voiceidstr );
if ( singer == null ) {
continue;
}
String installdir = (String)singer.GetValue( "INSTALLDIR", "" );
#if DEBUG
Console.WriteLine( "installdir=" + installdir );
#endif
RegistryKey vvoice = singer.OpenSubKey( "vvoice" );
if ( vvoice != null ) {
String[] vvoices = vvoice.GetValueNames();
// インストールされた歌手の.vvdを読みにいく
// installdir以下の、拡張子.vvdのファイルを探す
foreach ( String file in Directory.GetFiles( Path.Combine( installdir, voiceidstr ), "*.vvd" ) ) {
SingerConfig config = SingerConfig.fromVvd( file, 0 ); //とりあえずプログラムチェンジは0
s_installed_singers2.add( config );
}
// vvoice*.vvdを読みにいく。場所は、installdirではなく、s_voicedbdir2
foreach ( String s in vvoices ) {
String file = Path.Combine( s_voicedbdir2, s + ".vvd" );
if ( File.Exists( file ) ) {
SingerConfig config = SingerConfig.fromVvd( file, 0 );
vvoice_keys.add( s );
vvoice_values.add( config );
}
}
}
singer.Close();
}
// voice.mapを読み込んで、s_singer_configs2のプログラムチェンジを更新する
String map = Path.Combine( s_voicedbdir2, "voice.map" );
if ( File.Exists( map ) ) {
using ( FileStream fs = new FileStream( map, 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 ) {
#if DEBUG
Console.WriteLine( "value=" + value );
#endif
for ( int j = 0; j < vvoice_keys.size(); j++ ) {
if ( vvoice_keys.get( j ).Equals( "vvoice" + value ) ) {
vvoice_values.get( j ).Program = i;
}
}
}
}
}
}
// s_installed_singers2のSingerConfigのProgramとOriginalを適当に頒番する
for ( int i = 0; i < s_installed_singers2.size(); i++ ) {
s_installed_singers2.get( i ).Program = i;
s_installed_singers2.get( i ).Original = i;
}
// s_singer_configs2を更新
for ( int i = 0; i < vvoice_values.size(); i++ ) {
for ( int j = 0; j < s_installed_singers2.size(); j++ ) {
if ( vvoice_values.get( i ).VOICEIDSTR.Equals( s_installed_singers2.get( j ).VOICEIDSTR ) ) {
vvoice_values.get( i ).Original = s_installed_singers2.get( j ).Program;
break;
}
}
s_singer_configs2.add( vvoice_values.get( i ) );
}
v2database.Close();
}
#if DEBUG
Console.WriteLine( "installed" );
for ( Iterator itr = s_installed_singers2.iterator(); itr.hasNext(); ){
SingerConfig sc = (SingerConfig)itr.next();
Console.WriteLine( "VOICENAME=" + sc.VOICENAME + "; VOICEIDSTR=" + sc.VOICEIDSTR + "; Program=" + sc.Program + "; Original=" + sc.Original );
}
Console.WriteLine( "singer configs" );
for ( Iterator itr = s_singer_configs2.iterator(); itr.hasNext(); ){
SingerConfig sc = (SingerConfig)itr.next();
Console.WriteLine( "VOICENAME=" + sc.VOICENAME + "; VOICEIDSTR=" + sc.VOICEIDSTR + "; Program=" + sc.Program + "; Original=" + sc.Original );
}
#endif
}
/// <summary>
/// Transform the byte array(length=8) to unsigned long, assuming that the byte array is little endian.
/// </summary>
/// <param name="oct"></param>
/// <returns></returns>
public 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];
}
}
}