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

287 lines
12 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.

/*
* 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>ÅŒãÉTempolªã“ü³êÄ¢½ƒ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;
}
}
}