mirror of
https://git.femboyfinancial.jp/james/lipsync.git
synced 2024-11-25 03:52:02 -08:00
179 lines
6.1 KiB
C#
179 lines
6.1 KiB
C#
/*
|
|
* TempoTableEntry.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.Collections.Generic;
|
|
|
|
namespace Boare.Lib.Vsq {
|
|
|
|
public class TempoTable : ICloneable {
|
|
private struct TempoTableEntry : IComparable<TempoTableEntry> {
|
|
public int Clock;
|
|
public int Tempo;
|
|
public double Time;
|
|
|
|
public TempoTableEntry( int clock, int tempo, double time ) {
|
|
Clock = clock;
|
|
Tempo = tempo;
|
|
Time = time;
|
|
}
|
|
|
|
public int CompareTo( TempoTableEntry item ) {
|
|
return Clock - item.Clock;
|
|
}
|
|
}
|
|
|
|
private List<TempoTableEntry> m_tempo_table;
|
|
private int m_base_tempo;
|
|
private int m_tpq;
|
|
|
|
private TempoTable() {
|
|
}
|
|
|
|
public TempoTable( int base_tempo, int clock_per_quoter ) {
|
|
m_base_tempo = base_tempo;
|
|
m_tpq = clock_per_quoter;
|
|
m_tempo_table = new List<TempoTableEntry>();
|
|
m_tempo_table.Add( new TempoTableEntry( 0, base_tempo, 0.0 ) );
|
|
}
|
|
|
|
public object Clone() {
|
|
TempoTable ret = new TempoTable();
|
|
ret.m_base_tempo = m_base_tempo;
|
|
ret.m_tpq = m_tpq;
|
|
ret.m_tempo_table = new List<TempoTableEntry>();
|
|
for ( int i = 0; i < m_tempo_table.Count; i++ ) {
|
|
ret.m_tempo_table.Add( m_tempo_table[i] );
|
|
}
|
|
ret.update();
|
|
return ret;
|
|
}
|
|
|
|
public void add( int clock, int tempo ) {
|
|
bool found = false;
|
|
for ( int i = 0; i < m_tempo_table.Count; i++ ) {
|
|
if ( m_tempo_table[i].Clock == clock ) {
|
|
found = true;
|
|
m_tempo_table[i] = new TempoTableEntry( clock, tempo, 0.0 );
|
|
break;
|
|
}
|
|
}
|
|
if ( !found ) {
|
|
m_tempo_table.Add( new TempoTableEntry( clock, tempo, 0.0 ) );
|
|
}
|
|
m_tempo_table.Sort();
|
|
update();
|
|
}
|
|
|
|
public void clear( int base_tempo ) {
|
|
m_tempo_table.Clear();
|
|
m_tempo_table.Add( new TempoTableEntry( 0, base_tempo, 0.0 ) );
|
|
}
|
|
|
|
private void update() {
|
|
for ( int i = 0; i < m_tempo_table.Count; i++ ) {
|
|
long sum = 0;
|
|
for ( int k = 0; k < i; k++ ) {
|
|
sum += (m_tempo_table[k].Tempo * (m_tempo_table[k + 1].Clock - m_tempo_table[k].Clock));
|
|
}
|
|
double time = sum / (m_tpq * 1e6);
|
|
m_tempo_table[i] = new TempoTableEntry( m_tempo_table[i].Clock, m_tempo_table[i].Tempo, time );
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 指定した時刻における、クロックを取得します
|
|
/// </summary>
|
|
/// <param name="time"></param>
|
|
/// <returns></returns>
|
|
public double getClockFromSec( double time ) {
|
|
// timeにおけるテンポを取得
|
|
int tempo = m_base_tempo;
|
|
double base_clock = 0;
|
|
double base_time = 0f;
|
|
if ( m_tempo_table.Count == 0 ) {
|
|
tempo = m_base_tempo;
|
|
base_clock = 0;
|
|
base_time = 0f;
|
|
} else if ( m_tempo_table.Count == 1 ) {
|
|
tempo = m_tempo_table[0].Tempo;
|
|
base_clock = m_tempo_table[0].Clock;
|
|
base_time = m_tempo_table[0].Time;
|
|
} else {
|
|
for ( int i = m_tempo_table.Count - 1; i >= 0; i-- ) {
|
|
if ( m_tempo_table[i].Time < time ) {
|
|
return m_tempo_table[i].Clock + (time - m_tempo_table[i].Time) * m_tpq * 1000000.0 / m_tempo_table[i].Tempo;
|
|
}
|
|
}
|
|
}
|
|
double dt = time - base_time;
|
|
return base_clock + dt * m_tpq * 1000000.0 / (double)tempo;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 指定したクロックにおける、clock=0からの演奏経過時間(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 = m_base_tempo * 1e-6 / 480.0;
|
|
return clock * sec_per_clock;
|
|
}
|
|
|
|
public int getBaseTempo() {
|
|
return m_base_tempo;
|
|
}
|
|
}
|
|
|
|
[Serializable]
|
|
public class TempoTableEntry : IComparable<TempoTableEntry>, ICloneable {
|
|
public int Clock;
|
|
public int Tempo;
|
|
public double Time;
|
|
|
|
public object Clone() {
|
|
return new TempoTableEntry( Clock, Tempo, Time );
|
|
}
|
|
|
|
public TempoTableEntry( int clock, int _tempo, double _time ) {
|
|
this.Clock = clock;
|
|
this.Tempo = _tempo;
|
|
this.Time = _time;
|
|
}
|
|
|
|
public TempoTableEntry() {
|
|
}
|
|
|
|
public int CompareTo( TempoTableEntry entry ) {
|
|
return this.Clock - entry.Clock;
|
|
}
|
|
|
|
public bool Equals( TempoTableEntry entry ) {
|
|
if ( this.Clock == entry.Clock ) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|