mirror of
https://git.femboyfinancial.jp/james/lipsync.git
synced 2024-11-28 13:11:59 -08:00
391 lines
15 KiB
C#
391 lines
15 KiB
C#
|
/*
|
|||
|
* 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 {
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Represents the voice language of singer.
|
|||
|
/// </summary>
|
|||
|
public enum VsqVoiceLanguage : int {
|
|||
|
/// <summary>
|
|||
|
/// Default value, equivalent to "Japanese".
|
|||
|
/// </summary>
|
|||
|
Default = 0,
|
|||
|
/// <summary>
|
|||
|
/// Japanese
|
|||
|
/// </summary>
|
|||
|
Japanese = 0,
|
|||
|
/// <summary>
|
|||
|
/// English
|
|||
|
/// </summary>
|
|||
|
English = 1,
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Static library to treat the information of VOCALOID2 system.
|
|||
|
/// </summary>
|
|||
|
public static class VsqUtil {
|
|||
|
/// <summary>
|
|||
|
/// Maximum number of singers which can be allowed in VOCALOID2 system.
|
|||
|
/// </summary>
|
|||
|
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<int, SingerConfig> s_singer_configs = null;
|
|||
|
private static List<SingerConfig> s_installed_singers = new List<SingerConfig>();
|
|||
|
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 );
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets the list of installed singers which is installed in the computer.
|
|||
|
/// </summary>
|
|||
|
/// <returns></returns>
|
|||
|
public static SingerConfig[] getInstalledSingers() {
|
|||
|
return s_installed_singers.ToArray();
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets the list of singer configs.
|
|||
|
/// </summary>
|
|||
|
/// <returns></returns>
|
|||
|
public static Dictionary<int, SingerConfig> getSingerConfigs() {
|
|||
|
Dictionary<int, SingerConfig> ret = new Dictionary<int, SingerConfig>();
|
|||
|
foreach ( KeyValuePair<int, SingerConfig> kvp in s_singer_configs ) {
|
|||
|
ret.Add( kvp.Key, kvp.Value );
|
|||
|
}
|
|||
|
return ret;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets the path of VOCALOID Editor.
|
|||
|
/// </summary>
|
|||
|
public static string getEditorPath() {
|
|||
|
if ( !s_initialized ) {
|
|||
|
init();
|
|||
|
}
|
|||
|
return s_editor_path;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets the voice language of specified program change
|
|||
|
/// </summary>
|
|||
|
/// <param name="program_change">program change to get the voice language</param>
|
|||
|
/// <returns></returns>
|
|||
|
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;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets the name of original singer of specified program change.
|
|||
|
/// </summary>
|
|||
|
/// <param name="program_change"></param>
|
|||
|
/// <returns></returns>
|
|||
|
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 "";
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets the VsqID of program change.
|
|||
|
/// </summary>
|
|||
|
/// <param name="program_change"></param>
|
|||
|
/// <returns></returns>
|
|||
|
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;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets the singer information of pecified program change.
|
|||
|
/// </summary>
|
|||
|
/// <param name="program_change"></param>
|
|||
|
/// <returns></returns>
|
|||
|
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;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Loads the singer config from ExpDbPath.
|
|||
|
/// This method will automatically called when GetSingerInfo method or GetSingerID method is called in first time.
|
|||
|
/// </summary>
|
|||
|
public static void loadSingerConfigs() {
|
|||
|
if ( s_singer_configs == null ) {
|
|||
|
loadSingerConfigs( getExpDbPath() );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Loads the list of singer configuration from the specified path.
|
|||
|
/// Keys in the dictionary "s_singer_configs" represents the program change of each singer.
|
|||
|
/// </summary>
|
|||
|
/// <param name="path"></param>
|
|||
|
/// <returns></returns>
|
|||
|
private static void loadSingerConfigs( string path ) {
|
|||
|
#if DEBUG
|
|||
|
bocoree.debug.push_log( "SingerConfig+LoadSingerConfigs(String)" );
|
|||
|
#endif
|
|||
|
s_singer_configs = new Dictionary<int, SingerConfig>();
|
|||
|
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<string> voiceidstrs = new List<string>();
|
|||
|
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
|
|||
|
}
|
|||
|
|
|||
|
/// <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>
|
|||
|
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];
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets the path of VOCALOID2 Playback VSTi dll.
|
|||
|
/// </summary>
|
|||
|
/// <returns></returns>
|
|||
|
public static string getDllPathVsti2() {
|
|||
|
if ( !s_initialized ) {
|
|||
|
init();
|
|||
|
}
|
|||
|
return s_dll2_path;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets the path of VOCALOID1 Playback VSTi dll.
|
|||
|
/// </summary>
|
|||
|
/// <returns></returns>
|
|||
|
public static string getDllPathVsti1() {
|
|||
|
if ( !s_initialized ) {
|
|||
|
init();
|
|||
|
}
|
|||
|
return s_dll1_path;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Initializes the library.
|
|||
|
/// </summary>
|
|||
|
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
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets the path of directories in which singer expression database is installed.
|
|||
|
/// </summary>
|
|||
|
/// <returns></returns>
|
|||
|
public static string getExpDbPath() {
|
|||
|
if ( !s_initialized ) {
|
|||
|
init();
|
|||
|
}
|
|||
|
return s_exp_db_dir;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
}
|