mirror of
https://git.femboyfinancial.jp/james/lipsync.git
synced 2024-11-25 20:11:59 -08:00
287 lines
12 KiB
C#
287 lines
12 KiB
C#
/*
|
||
* UstFile.cs
|
||
* Copyright (c) 2009 kbinani, PEX
|
||
*
|
||
* 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 System.Text;
|
||
|
||
using bocoree;
|
||
|
||
namespace Boare.Lib.Vsq{
|
||
|
||
public class UstFile : ICloneable {
|
||
public object Tag;
|
||
private float m_tempo = 120.00f;
|
||
private string m_project_name = "";
|
||
private string m_voice_dir = "";
|
||
private string m_out_file = "";
|
||
private string m_cache_dir = "";
|
||
private string m_tool1 = "";
|
||
private string m_tool2 = "";
|
||
private List<UstTrack> m_tracks = new List<UstTrack>();
|
||
private List<TempoTableEntry> m_tempo_table;
|
||
|
||
public UstFile( string path ){
|
||
cp932reader sr = new cp932reader( path );
|
||
string line = sr.ReadLine();
|
||
if ( line != "[#SETTING]" ) {
|
||
throw new Exception( "invalid ust file" );
|
||
}
|
||
UstTrack track = new UstTrack();
|
||
int type = 0; //0 => reading "SETTING" section
|
||
while( true ) {
|
||
UstEvent ue = null;
|
||
if ( type == 1 ) {
|
||
ue = new UstEvent();
|
||
}
|
||
if ( line == "[#TRACKEND]" ) {
|
||
break;
|
||
}
|
||
line = sr.ReadLine(); // "[#" ’¼‰º‚Ì<E2809A>s
|
||
while( !line.StartsWith( "[#" ) ){
|
||
string[] spl = line.Split( "=".ToCharArray(), 2 );
|
||
if ( type == 0 ) {
|
||
// reading "SETTING" section
|
||
if ( spl[0] == "Tempo" ) {
|
||
m_tempo = 125f;
|
||
float v = 125f;
|
||
if ( float.TryParse( spl[1], out v ) ) {
|
||
m_tempo = v;
|
||
}
|
||
} else if ( spl[0] == "ProjectName" ) {
|
||
m_project_name = spl[1];
|
||
} else if ( spl[0] == "VoiceDir" ) {
|
||
m_voice_dir = spl[1];
|
||
} else if ( spl[0] == "OutFile" ) {
|
||
m_out_file = spl[1];
|
||
} else if ( spl[0] == "CacheDir" ) {
|
||
m_cache_dir = spl[1];
|
||
} else if ( spl[0] == "Tool1" ) {
|
||
m_tool1 = spl[1];
|
||
} else if ( spl[0] == "Tool2" ) {
|
||
m_tool2 = spl[1];
|
||
}
|
||
} else if ( type == 1 ) {
|
||
// readin event section
|
||
if ( spl[0] == "Length" ) {
|
||
ue.Length = 0;
|
||
int v = 0;
|
||
if ( int.TryParse( spl[1], out v ) ){
|
||
ue.Length =v;
|
||
}
|
||
} else if ( spl[0] == "Lyric" ) {
|
||
ue.Lyric = spl[1];
|
||
} else if ( spl[0] == "NoteNum" ) {
|
||
ue.Note = 0;
|
||
int v = 0;
|
||
if ( int.TryParse( spl[1], out v ) ) {
|
||
ue.Note = v;
|
||
}
|
||
} else if ( spl[0] == "Intensity" ) {
|
||
ue.Intensity =64;
|
||
int v = 64;
|
||
if ( int.TryParse( spl[1], out v ) ) {
|
||
ue.Intensity = v;
|
||
}
|
||
} else if ( spl[0] == "PBType" ) {
|
||
ue.PBType = 5;
|
||
int v = 5;
|
||
if ( int.TryParse( spl[1], out v ) ) {
|
||
ue.PBType = v;
|
||
}
|
||
} else if ( spl[0] == "Piches" ) {
|
||
string[] spl2 = spl[1].Split( ",".ToCharArray() );
|
||
float[] t = new float[spl2.Length];
|
||
for ( int i = 0; i < spl2.Length; i++ ) {
|
||
float v = 0;
|
||
float.TryParse( spl2[i], out v );
|
||
t[i] = v;
|
||
}
|
||
ue.Pitches = t;
|
||
} else if ( spl[0] == "Tempo" ) {
|
||
ue.Tempo = 125f;
|
||
float v;
|
||
if ( float.TryParse( spl[1], out v ) ){
|
||
ue.Tempo = v;
|
||
}
|
||
} else if ( spl[0] == "VBR" ) {
|
||
ue.Vibrato = new UstVibrato( line );
|
||
/*
|
||
PBW=50,50,46,48,56,50,50,50,50
|
||
PBS=-87
|
||
PBY=-15.9,-20,-31.5,-26.6
|
||
PBM=,s,r,j,s,s,s,s,s
|
||
*/
|
||
} else if ( spl[0] == "PBW" || spl[0] == "PBS" || spl[0] == "PBY" || spl[0] == "PBM" ) {
|
||
if ( ue.Portamento == null ) {
|
||
ue.Portamento = new UstPortamento();
|
||
}
|
||
ue.Portamento.ParseLine( line );
|
||
} else if ( spl[0] == "Envelope" ) {
|
||
ue.Envelope = new UstEnvelope( line );
|
||
//PreUtterance=1
|
||
//VoiceOverlap=6
|
||
} else if ( spl[0] == "VoiceOverlap" ) {
|
||
if ( spl[1] != "" ) {
|
||
ue.VoiceOverlap = int.Parse( spl[1] );
|
||
}
|
||
} else if ( spl[0] == "PreUtterance" ) {
|
||
if ( spl[1] != "" ) {
|
||
ue.PreUtterance = int.Parse( spl[1] );
|
||
}
|
||
} else if ( spl[0] == "Flags" ) {
|
||
ue.Flags = line.Substring( 6 );
|
||
}
|
||
}
|
||
line = sr.ReadLine();
|
||
}
|
||
if ( type == 0 ) {
|
||
type = 1;
|
||
} else if ( type == 1 ) {
|
||
track.addEvent( ue );
|
||
}
|
||
}
|
||
m_tracks.Add( track );
|
||
sr.Close();
|
||
updateTempoInfo();
|
||
}
|
||
|
||
private UstFile(){
|
||
}
|
||
|
||
public string getProjectName() {
|
||
return m_project_name;
|
||
}
|
||
|
||
public int getBaseTempo() {
|
||
return (int)(6e7 / m_tempo);
|
||
}
|
||
|
||
public double getTotalSec() {
|
||
int max = 0;
|
||
for ( int track = 0; track < m_tracks.Count; track++ ) {
|
||
int count = 0;
|
||
for ( int i = 0; i < m_tracks[track].getEventCount(); i++ ) {
|
||
count += (int)m_tracks[track].getEvent( i ).Length;
|
||
}
|
||
max = Math.Max( max, count );
|
||
}
|
||
return getSecFromClock( max );
|
||
}
|
||
|
||
public List<TempoTableEntry> getTempoList() {
|
||
return m_tempo_table;
|
||
}
|
||
|
||
public UstTrack getTrack( int track ) {
|
||
return m_tracks[track];
|
||
}
|
||
|
||
public int getTrackCount() {
|
||
return m_tracks.Count;
|
||
}
|
||
|
||
/// <summary>
|
||
/// TempoTable‚Ì[*].Time‚Ì•”•ª‚ð<E2809A>X<EFBFBD>V‚µ‚Ü‚·
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
public void updateTempoInfo() {
|
||
m_tempo_table = new List<TempoTableEntry>();
|
||
if ( m_tracks.Count <= 0 ) {
|
||
return;
|
||
}
|
||
int clock = 0;
|
||
double time = 0.0;
|
||
int last_tempo_clock = 0; //<2F>ÅŒã‚ÉTempo’l‚ª‘ã“ü‚³‚ê‚Ä‚¢‚½ƒCƒxƒ“ƒg‚̃Nƒ<4E>ƒbƒN
|
||
float last_tempo = m_tempo; //<2F>ÅŒã‚É‘ã“ü‚³‚ê‚Ä‚¢‚½ƒeƒ“ƒ|‚Ì’l
|
||
for ( int i = 0; i < m_tracks[0].getEventCount(); i++ ) {
|
||
if ( m_tracks[0].getEvent( i ).Tempo > 0f ) {
|
||
time += (clock - last_tempo_clock) / (8.0 * last_tempo);
|
||
if ( m_tempo_table.Count == 0 && clock != 0 ) {
|
||
m_tempo_table.Add( new TempoTableEntry( 0, (int)(6e7 / m_tempo), 0.0 ) );
|
||
}
|
||
m_tempo_table.Add( new TempoTableEntry( clock, (int)(6e7 / m_tracks[0].getEvent( i ).Tempo), time ) );
|
||
last_tempo = m_tracks[0].getEvent( i ).Tempo;
|
||
last_tempo_clock = clock;
|
||
}
|
||
clock += (int)m_tracks[0].getEvent( i ).Length;
|
||
}
|
||
#if DEBUG
|
||
using ( StreamWriter sw = new StreamWriter( Path.Combine( System.Windows.Forms.Application.StartupPath, "ust_tempo_info.txt" ) ) ) {
|
||
sw.WriteLine( "Clock\tTime\tTempo" );
|
||
for ( int i = 0; i < m_tempo_table.Count; i++ ) {
|
||
sw.WriteLine( m_tempo_table[i].Clock + "\t" + m_tempo_table[i].Time + "\t" + m_tempo_table[i].Tempo );
|
||
}
|
||
}
|
||
#endif
|
||
}
|
||
|
||
/// <summary>
|
||
/// Žw’肵‚½ƒNƒ<4E>ƒbƒN‚É‚¨‚¯‚é<E2809A>Aclock=0‚©‚ç‚̉‰‘tŒo‰ßŽžŠÔ(sec)
|
||
/// </summary>
|
||
/// <param name="clock"></param>
|
||
/// <returns></returns>
|
||
public double getSecFromClock( int clock ) {
|
||
for ( int i = m_tempo_table.Count - 1; i >= 0; i-- ) {
|
||
if ( m_tempo_table[i].Clock < clock ) {
|
||
double init = m_tempo_table[i].Time;
|
||
int dclock = clock - m_tempo_table[i].Clock;
|
||
double sec_per_clock1 = m_tempo_table[i].Tempo * 1e-6 / 480.0;
|
||
return init + dclock * sec_per_clock1;
|
||
}
|
||
}
|
||
double sec_per_clock = 0.125 / m_tempo;
|
||
return clock * sec_per_clock;
|
||
}
|
||
|
||
public void write( string file ) {
|
||
StreamWriter sw = new StreamWriter( file, false, Encoding.GetEncoding( "Shift_JIS" ) );
|
||
sw.WriteLine( "[#SETTING]" );
|
||
sw.WriteLine( "Tempo=" + m_tempo );
|
||
sw.WriteLine( "Tracks=1" );
|
||
sw.WriteLine( "ProjectName=" + m_project_name );
|
||
sw.WriteLine( "VoiceDir=" + m_voice_dir );
|
||
sw.WriteLine( "OutFile=" + m_out_file );
|
||
sw.WriteLine( "CacheDir=" + m_cache_dir );
|
||
sw.WriteLine( "Tool1=" + m_tool1 );
|
||
sw.WriteLine( "Tool2=" + m_tool2 );
|
||
for ( int i = 0; i < m_tracks[0].getEventCount(); i++ ) {
|
||
m_tracks[0].getEvent( i ).print( sw, (uint)i );
|
||
}
|
||
sw.WriteLine( "[#TRACKEND]" );
|
||
sw.Close();
|
||
}
|
||
|
||
public object Clone(){
|
||
UstFile ret = new UstFile();
|
||
ret.m_tempo = m_tempo;
|
||
ret.m_project_name = m_project_name;
|
||
ret.m_voice_dir = m_voice_dir;
|
||
ret.m_out_file = m_out_file;
|
||
ret.m_cache_dir = m_cache_dir;
|
||
ret.m_tool1 = m_tool1;
|
||
ret.m_tool2 = m_tool2;
|
||
for ( int i = 0; i < m_tracks.Count; i++ ) {
|
||
ret.m_tracks[i] = (UstTrack)m_tracks[i].Clone();
|
||
}
|
||
ret.m_tempo_table = new List<TempoTableEntry>();
|
||
for ( int i = 0; i < m_tempo_table.Count; i++ ) {
|
||
ret.m_tempo_table.Add( (TempoTableEntry)m_tempo_table[i].Clone() );
|
||
}
|
||
return ret;
|
||
}
|
||
}
|
||
|
||
}
|