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

792 lines
34 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;
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() {
Vector<String> dir1 = new Vector<String>();
RegistryKey key1 = Registry.LocalMachine.OpenSubKey( "SOFTWARE\\VOCALOID", false );
String header1 = "HKLM\\SOFTWARE\\VOCALOID";
print( key1, header1, dir1 );
key1.Close();
String path_voicedb1;
String path_expdb1;
Vector<String> installed_singers1 = new Vector<String>();
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() );
s_exp_config_sys1 = new ExpressionConfigSys( path_expdb1 );
Vector<String> dir2 = new Vector<String>();
RegistryKey key2 = Registry.LocalMachine.OpenSubKey( "SOFTWARE\\VOCALOID2", false );
String header2 = "HKLM\\SOFTWARE\\VOCALOID2";
print( key2, header2 , dir2 );
key2.Close();
String path_voicedb2;
String path_expdb2;
Vector<String> installed_singers2 = new Vector<String>();
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() );
s_exp_config_sys2 = new ExpressionConfigSys( path_expdb2 );
}
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 = "";
foreach ( String s in dir ) {
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を取得
foreach ( String s in application ) {
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のようなシリアルを取得
foreach ( String s in voice ) {
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を取得
foreach ( String s in voice_ids ) {
String install_dir = "";
foreach ( String s2 in voice ) {
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のようなシリアルを取得
foreach ( String s in expression ) {
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=" );
foreach ( String s in installed_singers ) {
Console.WriteLine( " " + s );
}
#endif
}
// レジストリkey内の値を再帰的に検索し、ファイルfpに順次出力する
private static void print( RegistryKey key, String parent_name, Vector<String> list ){
// 直下のキー内を再帰的にリストアップ
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 bool s_initialized = false;
private static string s_dll_path2 = "";
private static string s_editor_path2 = "";
private static string s_voicedbdir2 = "";
private static List<SingerConfig> s_installed_singers2 = new List<SingerConfig>();
private static List<SingerConfig> s_singer_configs2 = new List<SingerConfig>();
private static string s_dll_path1 = "";
private static string s_editor_path1 = "";
private static string s_voicedbdir1 = "";
private static List<SingerConfig> s_installed_singers1 = new List<SingerConfig>();
private static List<SingerConfig> s_singer_configs1 = new List<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.Count; i++ ) {
if ( singer == s_singer_configs1[i].VOICENAME ) {
voiceidstr = s_singer_configs1[i].VOICEIDSTR;
}
}
if ( voiceidstr == "" ) {
return "";
}
for ( int i = 0; i < s_installed_singers1.Count; i++ ) {
if ( voiceidstr == s_installed_singers1[i].VOICEIDSTR ) {
return s_installed_singers1[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.Count; i++ ) {
if ( singer == s_singer_configs2[i].VOICENAME ) {
voiceidstr = s_singer_configs2[i].VOICEIDSTR;
}
}
if ( voiceidstr == "" ) {
return "";
}
for ( int i = 0; i < s_installed_singers2.Count; i++ ) {
if ( voiceidstr == s_installed_singers2[i].VOICEIDSTR ) {
return s_installed_singers2[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.Count; i++ ) {
if ( s_singer_configs1[i].VOICENAME == singer_name ) {
sc = s_singer_configs1[i];
break;
}
}
if ( sc == null ) {
sc = new SingerConfig();
}
int lang = 0;
foreach ( SingerConfig sc2 in s_installed_singers1 ) {
if ( sc.VOICEIDSTR == 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.Count; i++ ) {
if ( s_singer_configs2[i].VOICENAME == singer_name ) {
sc = s_singer_configs2[i];
break;
}
}
if ( sc == null ) {
sc = new SingerConfig();
}
int lang = 0;
foreach ( SingerConfig sc2 in s_installed_singers2 ) {
if ( sc.VOICEIDSTR == 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();
}
public static SingerConfig[] getSingerConfigs2() {
return s_singer_configs2.ToArray();
}
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();
List<string> vvoice_keys = new List<string>();
List<SingerConfig> vvoice_values = new List<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.Count; j++ ) {
if ( vvoice_keys[j] == "vvoice" + value ) {
vvoice_values[j].Program = i;
}
}
}
}
}
}
// s_installed_singers1のSingerConfigのProgramとOriginalを適当に頒番する
for ( int i = 0; i < s_installed_singers1.Count; i++ ) {
s_installed_singers1[i].Program = i;
s_installed_singers1[i].Original = i;
}
// s_singer_configs1を更新
for ( int i = 0; i < vvoice_values.Count; i++ ) {
for ( int j = 0; j < s_installed_singers1.Count; j++ ) {
if ( vvoice_values[i].VOICEIDSTR == s_installed_singers1[j].VOICEIDSTR ) {
vvoice_values[i].Original = s_installed_singers1[j].Program;
break;
}
}
s_singer_configs1.Add( vvoice_values[i] );
}
v1database.Close();
}
#if DEBUG
Console.WriteLine( "installed" );
foreach ( SingerConfig sc in s_installed_singers1 ) {
Console.WriteLine( "VOICENAME=" + sc.VOICENAME + "; VOICEIDSTR=" + sc.VOICEIDSTR + "; Program=" + sc.Program + "; Original=" + sc.Original );
}
Console.WriteLine( "singer configs" );
foreach ( SingerConfig sc in s_singer_configs1 ) {
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();
List<string> vvoice_keys = new List<string>();
List<SingerConfig> vvoice_values = new List<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.Count; j++ ) {
if ( vvoice_keys[j] == "vvoice" + value ) {
vvoice_values[j].Program = i;
}
}
}
}
}
}
// s_installed_singers2のSingerConfigのProgramとOriginalを適当に頒番する
for ( int i = 0; i < s_installed_singers2.Count; i++ ) {
s_installed_singers2[i].Program = i;
s_installed_singers2[i].Original = i;
}
// s_singer_configs2を更新
for ( int i = 0; i < vvoice_values.Count; i++ ) {
for ( int j = 0; j < s_installed_singers2.Count; j++ ) {
if ( vvoice_values[i].VOICEIDSTR == s_installed_singers2[j].VOICEIDSTR ) {
vvoice_values[i].Original = s_installed_singers2[j].Program;
break;
}
}
s_singer_configs2.Add( vvoice_values[i] );
}
v2database.Close();
}
#if DEBUG
Console.WriteLine( "installed" );
foreach ( SingerConfig sc in s_installed_singers2 ) {
Console.WriteLine( "VOICENAME=" + sc.VOICENAME + "; VOICEIDSTR=" + sc.VOICEIDSTR + "; Program=" + sc.Program + "; Original=" + sc.Original );
}
Console.WriteLine( "singer configs" );
foreach ( SingerConfig sc in s_singer_configs2 ) {
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];
}
}
}