lipsync/Boare.Lib.Vsq/VsqBPList.cs
2024-05-20 00:17:44 +00:00

543 lines
17 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.

/*
* VsqBPList.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.
*/
#if JAVA
package org.kbinani.vsq;
import java.util.*;
import java.io.*;
import org.kbinani.*;
#else
using System;
using bocoree;
using bocoree.java.io;
using bocoree.java.util;
namespace Boare.Lib.Vsq {
using boolean = System.Boolean;
using Integer = System.Int32;
#endif
#if JAVA
public class VsqBPList implements Cloneable, Serializable{
#else
[Serializable]
public class VsqBPList : ICloneable {
#endif
private Vector<Integer> m_clock = new Vector<Integer>();
private Vector<VsqBPPair> m_items = new Vector<VsqBPPair>();
private int m_default = 0;
private int m_maximum = 127;
private int m_minimum = 0;
private long m_max_id = 0;
class KeyClockIterator : Iterator {
private VsqBPList m_list;
private int m_pos;
public KeyClockIterator( VsqBPList list ) {
m_list = list;
m_pos = -1;
}
public boolean hasNext() {
if ( m_pos + 1 < m_list.m_clock.size() ) {
return true;
} else {
return false;
}
}
public Object next() {
m_pos++;
return m_list.m_clock.get( m_pos );
}
public void remove() {
if ( 0 <= m_pos && m_pos < m_list.m_clock.size() ) {
int key = m_list.m_clock.get( m_pos );
m_list.m_clock.removeElementAt( m_pos );
m_list.m_items.removeElementAt( m_pos );
}
}
}
/// <summary>
/// コンストラクタ。デフォルト値はココで指定する。
/// </summary>
/// <param name="default_value"></param>
public VsqBPList( int default_value, int minimum, int maximum ) {
m_default = default_value;
m_maximum = maximum;
m_minimum = minimum;
m_max_id = 0;
}
#if JAVA
public VsqBPList(){
this( 0, 0, 64 );
#else
public VsqBPList()
: this( 0, 0, 64 ) {
#endif
}
#if !JAVA
public int Default {
get {
return getDefault();
}
set {
setDefault( value );
}
}
#endif
public long getMaxID() {
return m_max_id;
}
/// <summary>
/// このBPListのデフォルト値を取得します
/// </summary>
public int getDefault() {
return m_default;
}
public void setDefault( int value ) {
m_default = value;
}
/// <summary>
/// データ点のIDを一度クリアし新たに番号付けを行います
/// IDはRedo,Undo用コマンドが使用するためこのメソッドを呼ぶとRedo,Undo操作が破綻するXMLからのデシリアライズ直後のみ使用するべき
/// </summary>
public void renumberIDs() {
m_max_id = 0;
int count = m_items.size();
for ( int i = 0; i < count; i++ ) {
m_max_id++;
VsqBPPair v = m_items.get( i );
v.id = m_max_id;
m_items.set( i, v );
}
}
#if !JAVA
/// <summary>
/// XMLシリアライズ用
/// </summary>
public String Data {
get {
return getData();
}
set {
setData( value );
}
}
#endif
public String getData() {
String ret = "";
int count = -1;
int size = m_clock.size();
for ( int i = 0; i < size; i++ ) {
count++;
ret += (count == 0 ? "" : ",") + m_clock.get( i ) + "=" + m_items.get( i ).value;
}
return ret;
}
public void setData( String value ) {
m_clock.clear();
m_items.clear();
m_max_id = 0;
String[] spl = PortUtil.splitString( value, ',' );
for ( int i = 0; i < spl.Length; i++ ) {
String[] spl2 = PortUtil.splitString( spl[i], '=' );
if ( spl2.Length < 2 ) {
continue;
}
try {
int clock = PortUtil.parseInt( spl2[0] );
m_clock.add( clock );
m_items.add( new VsqBPPair( PortUtil.parseInt( spl2[1] ), m_max_id + 1 ) );
m_max_id++;
} catch ( Exception ex ) {
#if DEBUG
PortUtil.println( " ex=" + ex );
PortUtil.println( " i=" + i + "; spl2[0]=" + spl2[0] + "; spl2[1]=" + spl2[1] );
#endif
}
}
}
/// <summary>
/// このVsqBPListの同一コピーを作成します
/// </summary>
/// <returns></returns>
public Object clone() {
VsqBPList res = new VsqBPList( m_default, m_minimum, m_maximum );
int count = m_clock.size();
for ( int i = 0; i < count; i++ ) {
res.m_clock.add( m_clock.get( i ) );
#if JAVA
res.m_items.add( (VsqBPPair)m_items.get( i ).clone() );
#else
res.m_items.add( m_items.get( i ) );
#endif
}
res.m_max_id = m_max_id;
return res;
}
#if !JAVA
public object Clone() {
return clone();
}
#endif
#if !JAVA
public int Maximum {
get {
return getMaximum();
}
set {
setMaximum( value );
}
}
#endif
/// <summary>
/// このリストに設定された最大値を取得します。
/// </summary>
public int getMaximum() {
return m_maximum;
}
public void setMaximum( int value ) {
m_maximum = value;
}
#if !JAVA
public int Minimum {
get {
return getMinimum();
}
set {
setMinimum( value );
}
}
#endif
/// <summary>
/// このリストに設定された最小値を取得します
/// </summary>
public int getMinimum() {
return m_minimum;
}
public void setMinimum( int value ) {
m_minimum = value;
}
public void remove( int clock ) {
int index = m_clock.indexOf( clock );
removeElementAt( index );
}
public void removeElementAt( int index ) {
if ( index >= 0 ) {
m_clock.removeElementAt( index );
m_items.removeElementAt( index );
}
}
public boolean isContainsKey( int clock ) {
return m_clock.contains( clock );
}
/* public int[] getKeys() {
Vector<Integer> t = new Vector<Integer>();
foreach( int key in m_list.Keys ){
t.add( key );
}
return t.toArray( new Integer[]{} );
}*/
/// <summary>
/// 時刻clockのデータを時刻new_clockに移動します。
/// 時刻clockにデータがなければ何もしない。
/// 時刻new_clockに既にデータがある場合、既存のデータは削除される。
/// </summary>
/// <param name="clock"></param>
/// <param name="new_clock"></param>
public void move( int clock, int new_clock, int new_value ) {
int index = m_clock.indexOf( clock );
if ( index < 0 ) {
return;
}
VsqBPPair item = m_items.get( index );
m_clock.removeElementAt( index );
m_items.removeElementAt( index );
int index_new = m_clock.indexOf( new_clock );
if ( index_new >= 0 ) {
item.value = new_value;
m_items.set( index_new, item );
return;
} else {
m_clock.add( new_clock );
Collections.sort( m_clock );
index_new = m_clock.indexOf( new_clock );
item.value = new_value;
m_items.insertElementAt( item, index_new );
}
}
public void clear() {
m_clock.clear();
m_items.clear();
}
public int getElement( int index ) {
return getElementA( index );
}
public int getElementA( int index ) {
return m_items.get( index ).value;
}
public VsqBPPair getElementB( int index ) {
return m_items.get( index );
}
public int getKeyClock( int index ) {
return m_clock.get( index );
}
public int findValueFromID( long id ) {
int c = m_items.size();
for ( int i = 0; i < c; i++ ) {
VsqBPPair item = m_items.get( i );
if ( item.id == id ) {
return item.value;
}
}
return m_default;
}
/// <summary>
/// 指定したid値を持つVsqBPPairを検索し、その結果を返します。
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public VsqBPPairSearchContext findElement( long id ) {
VsqBPPairSearchContext context = new VsqBPPairSearchContext();
int c = m_items.size();
for ( int i = 0; i < c; i++ ) {
VsqBPPair item = m_items.get( i );
if ( item.id == id ) {
context.clock = m_clock.get( i );
context.index = i;
context.point = item;
return context;
}
}
context.clock = -1;
context.index = -1;
context.point = new VsqBPPair( m_default, -1 );
return context;
}
public void setValueForID( long id, int value ) {
int c = m_items.size();
for ( int i = 0; i < c; i++ ) {
VsqBPPair item = m_items.get( i );
if ( item.id == id ) {
item.value = value;
m_items.set( i, item );
break;
}
}
}
public int getValue( int clock, ByRef<Integer> index ) {
int count = m_clock.size();
if ( count == 0 ) {
return m_default;
} else {
if ( index.value < 0 ) {
index.value = 0;
}
for ( int i = index.value; i < count; i++ ) {
int keyclock = m_clock.get( i );
if ( clock < keyclock ) {
if ( i > 0 ) {
index.value = i;
return m_items.get( i - 1 ).value;
} else {
index.value = i;
return m_default;
}
}
}
index.value = count - 1;
return m_items.get( count - 1 ).value;
}
}
private void printCor( ITextWriter writer, int start_clock, String header )
#if JAVA
throws IOException
#endif
{
writer.writeLine( header );
int c = m_clock.size();
for ( int i = 0; i < c; i++ ) {
int key = m_clock.get( i );
if ( start_clock <= key ) {
int val = m_items.get( i ).value;
writer.writeLine( key + "=" + val );
}
}
}
/// <summary>
/// このBPListの内容をテキストファイルに書き出します
/// </summary>
/// <param name="writer"></param>
public void print( BufferedWriter writer, int start, String header )
#if JAVA
throws IOException
#endif
{
printCor( new WrappedStreamWriter( writer ), start, header );
}
/// <summary>
/// このBPListの内容をテキストファイルに書き出します
/// </summary>
/// <param name="writer"></param>
public void print( TextMemoryStream writer, int start, String header )
#if JAVA
throws IOException
#endif
{
printCor( writer, start, header );
}
/// <summary>
/// テキストファイルからデータ点を読込み、現在のリストに追加します
/// </summary>
/// <param name="reader"></param>
/// <returns></returns>
public String appendFromText( TextMemoryStream reader ) {
String last_line = reader.readLine();
while ( !last_line.StartsWith( "[" ) ) {
String[] spl = PortUtil.splitString( last_line, new char[] { '=' } );
int clock = PortUtil.parseInt( spl[0] );
int value = PortUtil.parseInt( spl[1] );
this.add( clock, value );
if ( reader.peek() < 0 ) {
break;
} else {
last_line = reader.readLine();
}
}
return last_line;
}
public int size() {
return m_clock.size();
}
public Iterator keyClockIterator() {
return new KeyClockIterator( this );
}
public long add( int clock, int value ) {
int index = m_clock.indexOf( clock );
if ( index >= 0 ) {
VsqBPPair v = m_items.get( index );
v.value = value;
m_items.set( index, v );
return v.id;
} else {
m_clock.add( clock );
Collections.sort( m_clock );
index = m_clock.indexOf( clock );
m_max_id++;
m_items.insertElementAt( new VsqBPPair( value, m_max_id ), index );
return m_max_id;
}
}
public void addWithID( int clock, int value, long id ) {
int index = m_clock.indexOf( clock );
if ( index >= 0 ) {
VsqBPPair v = m_items.get( index );
v.value = value;
v.id = id;
m_items.set( index, v );
} else {
m_clock.add( clock );
Collections.sort( m_clock );
index = m_clock.indexOf( clock );
m_items.insertElementAt( new VsqBPPair( value, id ), index );
m_max_id = Math.Max( m_max_id, id );
}
}
public void removeWithID( long id ) {
int c = m_items.size();
for ( int i = 0; i < c; i++ ) {
if ( m_items.get( i ).id == id ) {
m_items.removeElementAt( i );
m_clock.removeElementAt( i );
break;
}
}
}
public int getValue( int clock ) {
int index = m_clock.indexOf( clock );
if ( index >= 0 ) {
return m_items.get( index ).value;
} else {
int count = m_clock.size();
if ( count <= 0 ) {
return m_default;
} else {
int draft = -1;
for ( int i = 0; i < count; i++ ) {
int c = m_clock.get( i );
if ( clock < c ) {
break;
}
draft = i;
}
if ( draft < 0 ) {
return m_default;
} else {
return m_items.get( draft ).value;
}
}
}
}
}
#if !JAVA
}
#endif