git-svn-id: http://svn.sourceforge.jp/svnroot/lipsync@6 b1f601f4-4f45-0410-8980-aecacb008692

This commit is contained in:
kbinani 2009-06-25 14:16:22 +00:00
parent 775d25e7fa
commit 90d1578878
373 changed files with 111302 additions and 0 deletions

View File

@ -0,0 +1,50 @@
/*
* AuthorListEntry.cs
* Copyright (c) 2007-2009 kbinani
*
* This file is part of Boare.Lib.AppUtil.
*
* Boare.Lib.AppUtil is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* Boare.Lib.AppUtil 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.Drawing;
namespace Boare.Lib.AppUtil {
public class AuthorListEntry {
string m_name;
FontStyle m_style;
public AuthorListEntry( string name, FontStyle style )
: this( name ) {
m_style = style;
}
public AuthorListEntry( string name ) {
m_name = name;
m_style = FontStyle.Regular;
}
public AuthorListEntry() {
m_name = "";
m_style = FontStyle.Regular;
}
public string Name {
get {
return m_name;
}
}
public FontStyle Style {
get {
return m_style;
}
}
}
}

View File

@ -0,0 +1,66 @@
/*
* BHScrollBar.Designer.cs
* Copyright (c) 2009 kbinani
*
* This file is part of Boare.Lib.AppUtil.
*
* Boare.Lib.AppUtil is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* Boare.Lib.AppUtil 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.
*/
namespace Boare.Lib.AppUtil {
partial class BHScrollBar {
/// <summary>
/// 必要なデザイナ変数です。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 使用中のリソースをすべてクリーンアップします。
/// </summary>
/// <param name="disposing">マネージ リソースが破棄される場合 true、破棄されない場合は false です。</param>
protected override void Dispose( bool disposing ) {
if ( disposing && (components != null) ) {
components.Dispose();
}
base.Dispose( disposing );
}
#region
/// <summary>
/// デザイナ サポートに必要なメソッドです。このメソッドの内容を
/// コード エディタで変更しないでください。
/// </summary>
private void InitializeComponent() {
this.hScroll = new System.Windows.Forms.HScrollBar();
this.SuspendLayout();
//
// hScroll
//
this.hScroll.Dock = System.Windows.Forms.DockStyle.Fill;
this.hScroll.Location = new System.Drawing.Point( 0, 0 );
this.hScroll.Name = "hScroll";
this.hScroll.Size = new System.Drawing.Size( 333, 16 );
this.hScroll.TabIndex = 0;
this.hScroll.ValueChanged += new System.EventHandler( this.hScroll_ValueChanged );
//
// BHScrollBar
//
this.AutoScaleDimensions = new System.Drawing.SizeF( 6F, 12F );
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add( this.hScroll );
this.Name = "BHScrollBar";
this.Size = new System.Drawing.Size( 333, 16 );
this.ResumeLayout( false );
}
#endregion
private System.Windows.Forms.HScrollBar hScroll;
}
}

View File

@ -0,0 +1,86 @@
/*
* BHScrollBar.cs
* Copyright (c) 2009 kbinani
*
* This file is part of Boare.Lib.AppUtil.
*
* Boare.Lib.AppUtil is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* Boare.Lib.AppUtil 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.Windows.Forms;
namespace Boare.Lib.AppUtil {
/// <summary>
/// Valueの値が正しくMinimumからMaximumの間を動くスクロールバー
/// </summary>
public partial class BHScrollBar : UserControl {
int m_max = 100;
int m_min = 0;
public event EventHandler ValueChanged;
public BHScrollBar() {
InitializeComponent();
}
public int Value {
get {
return hScroll.Value;
}
set {
hScroll.Value = value;
}
}
public int LargeChange {
get {
return hScroll.LargeChange;
}
set {
hScroll.LargeChange = value;
hScroll.Maximum = m_max + value;
}
}
public int SmallChange {
get {
return hScroll.SmallChange;
}
set {
hScroll.SmallChange = value;
}
}
public int Maximum {
get {
return m_max;
}
set {
m_max = value;
hScroll.Maximum = m_max + hScroll.LargeChange;
}
}
public int Minimum {
get {
return m_min;
}
set {
m_min = value;
}
}
private void hScroll_ValueChanged( object sender, EventArgs e ) {
if ( ValueChanged != null ) {
ValueChanged( this, e );
}
}
}
}

View File

@ -0,0 +1,506 @@
/*
* BSplitContainer.cs
* Copyright (c) 2008-2009 kbinani
*
* This file is part of Boare.Lib.AppUtil.
*
* Boare.Lib.AppUtil is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* Boare.Lib.AppUtil 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.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
namespace Boare.Lib.AppUtil {
[Serializable]
public partial class BSplitContainer : ContainerControl {
private Orientation m_orientation = Orientation.Horizontal;
private int m_splitter_distance = 50;
private int m_panel1_min = 25;
private int m_panel2_min = 25;
private int m_splitter_width = 4;
private bool m_splitter_moving = false;
private int m_splitter_distance_draft = 50;
private BSplitterPanel m_panel1;
private BSplitterPanel m_panel2;
private System.ComponentModel.IContainer components = null;
private bool m_splitter_fixed = false;
private Pen m_panel1_border = null;
private Pen m_panel2_border = null;
private System.Windows.Forms.FixedPanel m_fixed_panel;
private PictureBox m_lbl_splitter;
private int m_panel2_distance = 1;
private double m_distance_rate = 0.5;
public event SplitterEventHandler SplitterMoved;
[Browsable(false)]
public event ControlEventHandler ControlAdded;
public BSplitContainer() {
InitializeComponent();
if ( m_orientation == Orientation.Horizontal ) {
m_lbl_splitter.Cursor = Cursors.VSplit;
} else {
m_lbl_splitter.Cursor = Cursors.HSplit;
}
if ( m_orientation == Orientation.Horizontal ) {
m_panel2_distance = this.Width - m_splitter_distance;
} else {
m_panel2_distance = this.Height - m_splitter_distance;
}
m_distance_rate = m_splitter_distance / (double)(m_splitter_distance + m_panel2_distance);
}
public System.Windows.Forms.FixedPanel FixedPanel {
get {
return m_fixed_panel;
}
set {
System.Windows.Forms.FixedPanel old = m_fixed_panel;
m_fixed_panel = value;
if ( m_fixed_panel != FixedPanel.None && m_fixed_panel != old ) {
if ( m_fixed_panel == FixedPanel.Panel1 ) {
m_panel2.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
if ( m_orientation == Orientation.Vertical ) {
m_panel1.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
} else {
m_panel1.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left;
}
} else {
m_panel1.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
if ( m_orientation == Orientation.Vertical ) {
m_panel2.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
} else {
m_panel2.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Right;
}
}
}
}
}
public bool IsSplitterFixed {
get {
return m_splitter_fixed;
}
set {
m_splitter_fixed = value;
if ( m_splitter_fixed ) {
m_lbl_splitter.Cursor = Cursors.Default;
} else {
if ( m_orientation == Orientation.Horizontal ) {
m_lbl_splitter.Cursor = Cursors.VSplit;
} else {
m_lbl_splitter.Cursor = Cursors.HSplit;
}
}
}
}
/// <summary>
/// 使用中のリソースをすべてクリーンアップします。
/// </summary>
/// <param name="disposing">マネージ リソースが破棄される場合 true、破棄されない場合は false です。</param>
protected override void Dispose( bool disposing ) {
if ( disposing && (components != null) ) {
components.Dispose();
}
base.Dispose( disposing );
}
/// <summary>
/// デザイナ サポートに必要なメソッドです。このメソッドの内容を
/// コード エディタで変更しないでください。
/// </summary>
private void InitializeComponent() {
this.m_lbl_splitter = new System.Windows.Forms.PictureBox();
this.m_panel2 = new Boare.Lib.AppUtil.BSplitterPanel();
this.m_panel1 = new Boare.Lib.AppUtil.BSplitterPanel();
((System.ComponentModel.ISupportInitialize)(this.m_lbl_splitter)).BeginInit();
this.SuspendLayout();
//
// m_lbl_splitter
//
this.m_lbl_splitter.BackColor = System.Drawing.Color.Transparent;
this.m_lbl_splitter.Location = new System.Drawing.Point( 0, 0 );
this.m_lbl_splitter.Name = "m_lbl_splitter";
this.m_lbl_splitter.Size = new System.Drawing.Size( 100, 50 );
this.m_lbl_splitter.TabIndex = 0;
this.m_lbl_splitter.TabStop = false;
this.m_lbl_splitter.MouseMove += new System.Windows.Forms.MouseEventHandler( this.m_lbl_splitter_MouseMove );
this.m_lbl_splitter.MouseDown += new System.Windows.Forms.MouseEventHandler( this.m_lbl_splitter_MouseDown );
this.m_lbl_splitter.MouseUp += new System.Windows.Forms.MouseEventHandler( this.m_lbl_splitter_MouseUp );
//
// m_panel2
//
this.m_panel2.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.m_panel2.BorderColor = System.Drawing.Color.Black;
this.m_panel2.Location = new System.Drawing.Point( 0, 103 );
this.m_panel2.Margin = new System.Windows.Forms.Padding( 0 );
this.m_panel2.Name = "m_panel2";
this.m_panel2.Size = new System.Drawing.Size( 441, 245 );
this.m_panel2.TabIndex = 1;
this.m_panel2.BorderStyleChanged += new System.EventHandler( this.m_panel2_BorderStyleChanged );
this.m_panel2.SizeChanged += new System.EventHandler( this.m_panel2_SizeChanged );
//
// m_panel1
//
this.m_panel1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.m_panel1.BorderColor = System.Drawing.Color.Black;
this.m_panel1.Location = new System.Drawing.Point( 0, 0 );
this.m_panel1.Margin = new System.Windows.Forms.Padding( 0, 0, 0, 4 );
this.m_panel1.Name = "m_panel1";
this.m_panel1.Size = new System.Drawing.Size( 441, 99 );
this.m_panel1.TabIndex = 0;
this.m_panel1.BorderStyleChanged += new System.EventHandler( this.m_panel1_BorderStyleChanged );
this.m_panel1.SizeChanged += new System.EventHandler( this.m_panel1_SizeChanged );
//
// SplitContainerEx
//
this.Controls.Add( this.m_panel2 );
this.Controls.Add( this.m_panel1 );
this.Controls.Add( this.m_lbl_splitter );
this.Size = new System.Drawing.Size( 441, 348 );
this.Paint += new System.Windows.Forms.PaintEventHandler( this.SplitContainerEx_Paint );
((System.ComponentModel.ISupportInitialize)(this.m_lbl_splitter)).EndInit();
this.ResumeLayout( false );
}
private void SplitContainerEx_Paint( object sender, PaintEventArgs e ) {
bool panel1_visible = true;
if ( Orientation == Orientation.Horizontal ) {
if ( m_panel1.Width == 0 ) {
panel1_visible = false;
}
} else {
if ( m_panel1.Height == 0 ) {
panel1_visible = false;
}
}
if ( m_panel1.BorderStyle == BorderStyle.FixedSingle && panel1_visible ) {
if ( m_panel1_border == null ) {
m_panel1_border = new Pen( m_panel1.BorderColor );
} else {
if ( !m_panel1.BorderColor.Equals( m_panel1_border.Color ) ) {
m_panel1_border = new Pen( m_panel1.BorderColor );
}
}
e.Graphics.DrawRectangle( m_panel1_border,
new Rectangle( m_panel1.Left - 1, m_panel1.Top - 1, m_panel1.Width + 1, m_panel1.Height + 1) );
}
bool panel2_visible = true;
if ( Orientation == Orientation.Horizontal ) {
if ( m_panel2.Width == 0 ) {
panel2_visible = false;
}
} else {
if ( m_panel2.Height == 0 ) {
panel2_visible = false;
}
}
if ( m_panel2.BorderStyle == BorderStyle.FixedSingle && panel2_visible ) {
if ( m_panel2_border == null ) {
m_panel2_border = new Pen( m_panel2.BorderColor );
} else {
if ( !m_panel2.BorderColor.Equals( m_panel2_border.Color ) ) {
m_panel2_border = new Pen( m_panel2.BorderColor );
}
}
e.Graphics.DrawRectangle( m_panel2_border,
new Rectangle( m_panel2.Left - 1, m_panel2.Top - 1, m_panel2.Width + 1, m_panel2.Height + 1 ) );
}
}
private void m_panel2_BorderStyleChanged( object sender, EventArgs e ) {
UpdateLayout( m_splitter_distance, m_splitter_width, m_panel1_min, m_panel2_min, false );
}
private void m_panel1_BorderStyleChanged( object sender, EventArgs e ) {
UpdateLayout( m_splitter_distance, m_splitter_width, m_panel1_min, m_panel2_min, false );
}
private void m_panel2_SizeChanged( object sender, EventArgs e ) {
m_panel2.Invalidate( true );
}
private void m_panel1_SizeChanged( object sender, EventArgs e ) {
m_panel1.Invalidate( true );
}
public int Panel1MinSize {
get {
return m_panel1_min;
}
set {
int min_splitter_distance = value;
if ( m_splitter_distance < min_splitter_distance && min_splitter_distance > 0 ) {
m_splitter_distance = min_splitter_distance;
}
UpdateLayout( m_splitter_distance, m_splitter_width, value, m_panel2_min, false );
}
}
public int Panel2MinSize {
get {
return m_panel2_min;
}
set {
int max_splitter_distance = (m_orientation == Orientation.Horizontal) ?
this.Width - m_splitter_width - value :
this.Height - m_splitter_width - value;
if ( m_splitter_distance > max_splitter_distance && max_splitter_distance > 0 ) {
m_splitter_distance = max_splitter_distance;
}
UpdateLayout( m_splitter_distance, m_splitter_width, m_panel1_min, value, false );
}
}
public int SplitterWidth {
get {
return m_splitter_width;
}
set {
if ( value < 1 ) {
value = 1;
}
UpdateLayout( m_splitter_distance, value, m_panel1_min, m_panel2_min, false );
}
}
private bool UpdateLayout( int splitter_distance, int splitter_width, int panel1_min, int panel2_min, bool check_only ) {
Point mouse = this.PointToClient( Control.MousePosition );
int pad1 = (m_panel1.BorderStyle == BorderStyle.FixedSingle) ? 1 : 0;
int pad2 = (m_panel2.BorderStyle == BorderStyle.FixedSingle) ? 1 : 0;
if ( m_orientation == Orientation.Horizontal ) {
int p1 = splitter_distance;
if ( p1 < 0 ) {
p1 = 0;
} else if ( this.Width < p1 + splitter_width ) {
p1 = this.Width - splitter_width;
}
int p2 = this.Width - p1 - splitter_width;
if ( check_only ) {
if ( p1 < panel1_min || p2 < panel2_min ) {
return false;
}
} else {
if ( p1 < panel1_min ) {
p1 = panel1_min;
}
p2 = this.Width - p1 - splitter_width;
if ( p2 < panel2_min ) {
p2 = panel2_min;
//return false;
}
}
if ( !check_only ) {
m_panel1.Left = pad1;
m_panel1.Top = pad1;
m_panel1.Width = (p1 - 2 * pad1 >= 0) ? (p1 - 2 * pad1) : 0;
m_panel1.Height = (this.Height - 2 * pad1 >= 0) ? (this.Height - 2 * pad1) : 0;
m_panel2.Left = p1 + splitter_width + pad2;
m_panel2.Top = pad2;
m_panel2.Width = (p2 - 2 * pad2 >= 0) ? (p2 - 2 * pad2) : 0;
m_panel2.Height = (this.Height - 2 * pad2 >= 0) ? (this.Height - 2 * pad2) : 0;
m_splitter_distance = p1;
m_panel2_distance = this.Width - m_splitter_distance;
m_distance_rate = m_splitter_distance / (double)(m_splitter_distance + m_panel2_distance);
if ( SplitterMoved != null ) {
SplitterMoved( this, new SplitterEventArgs( mouse.X, mouse.Y, p1, 0 ) );
}
m_splitter_width = splitter_width;
m_panel1_min = panel1_min;
m_panel2_min = panel2_min;
m_lbl_splitter.Left = p1;
m_lbl_splitter.Top = 0;
m_lbl_splitter.Width = splitter_width;
m_lbl_splitter.Height = this.Height;
}
return true;
} else {
int p1 = splitter_distance;
if ( p1 < 0 ) {
p1 = 0;
} else if ( this.Height < p1 + splitter_width ) {
p1 = this.Height - splitter_width;
}
int p2 = this.Height - p1 - splitter_width;
if ( check_only ) {
if ( p1 < panel1_min || p2 < panel2_min ) {
return false;
}
} else {
if ( p1 < panel1_min ) {
p1 = panel1_min;
}
p2 = this.Height - p1 - splitter_width;
if ( p2 < panel2_min ) {
p2 = panel2_min;
//return false;
}
}
if ( !check_only ) {
m_panel1.Left = pad1;
m_panel1.Top = pad1;
m_panel1.Width = (this.Width - 2 * pad1 >= 0) ? (this.Width - 2 * pad1) : 0;
m_panel1.Height = (p1 - 2 * pad1 >= 0) ? (p1 - 2 * pad1) : 0;
m_panel2.Left = pad2;
m_panel2.Top = p1 + splitter_width + pad2;
m_panel2.Width = (this.Width - 2 * pad2 >= 0) ? (this.Width - 2 * pad2) : 0;
m_panel2.Height = (p2 - 2 * pad2 >= 0) ? (p2 - 2 * pad2) : 0;
m_splitter_distance = p1;
m_panel2_distance = this.Height - m_splitter_distance;
m_distance_rate = m_splitter_distance / (double)(m_splitter_distance + m_panel2_distance);
if ( SplitterMoved != null ) {
SplitterMoved( this, new SplitterEventArgs( mouse.X, mouse.Y, 0, p1 ) );
}
m_splitter_width = splitter_width;
m_panel1_min = panel1_min;
m_panel2_min = panel2_min;
m_lbl_splitter.Left = 0;
m_lbl_splitter.Top = p1;
m_lbl_splitter.Width = this.Width;
m_lbl_splitter.Height = splitter_width;
}
return true;
}
}
public int SplitterDistance {
get {
return m_splitter_distance;
}
set {
UpdateLayout( value, m_splitter_width, m_panel1_min, m_panel2_min, false );
if ( m_orientation == Orientation.Horizontal ) {
m_panel2_distance = this.Width - m_splitter_distance;
} else {
m_panel2_distance = this.Height - m_splitter_distance;
}
}
}
public Orientation Orientation {
get {
return m_orientation;
}
set {
if ( m_orientation != value ) {
m_orientation = value;
UpdateLayout( m_splitter_distance, m_splitter_width, m_panel1_min, m_panel2_min, false );
if ( m_orientation == Orientation.Horizontal ) {
m_lbl_splitter.Cursor = Cursors.VSplit;
} else {
m_lbl_splitter.Cursor = Cursors.HSplit;
}
}
}
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public BSplitterPanel Panel1 {
get {
return m_panel1;
}
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public BSplitterPanel Panel2 {
get {
return m_panel2;
}
}
protected override void OnSizeChanged( EventArgs e ) {
#if DEBUG
Console.WriteLine( "BSplitContainer+OnSizeChanged" );
//Console.WriteLine( " FixedPanel=" + FixedPanel );
//Console.WriteLine( " m_splitter_distance=" + m_splitter_distance );
Console.WriteLine( " Width=" + Width );
Console.WriteLine( " Height=" + Height );
//Console.WriteLine( " m_panel2_distance=" + m_panel2_distance );
#endif
base.OnSizeChanged( e );
if ( Width <= 0 || Height <= 0 ) {
return;
}
if ( m_fixed_panel == FixedPanel.Panel2 ) {
if ( m_orientation == Orientation.Horizontal ) {
m_splitter_distance = this.Width - m_panel2_distance;
} else {
m_splitter_distance = this.Height - m_panel2_distance;
}
} else if ( m_fixed_panel == FixedPanel.None ) {
#if DEBUG
//Console.WriteLine( " m_distance_rate=" + m_distance_rate );
#endif
if ( m_orientation == Orientation.Horizontal ) {
m_splitter_distance = (int)(this.Width * m_distance_rate);
} else {
m_splitter_distance = (int)(this.Height * m_distance_rate);
}
}
UpdateLayout( m_splitter_distance, m_splitter_width, m_panel1_min, m_panel2_min, false );
}
private void m_lbl_splitter_MouseDown( object sender, MouseEventArgs e ) {
if ( !m_splitter_fixed ) {
m_splitter_moving = true;
m_splitter_distance_draft = m_splitter_distance;
this.Cursor = (m_orientation == Orientation.Horizontal) ? Cursors.VSplit : Cursors.HSplit;
m_lbl_splitter.BackColor = SystemColors.ControlDark;
m_lbl_splitter.BringToFront();
}
}
private void m_lbl_splitter_MouseUp( object sender, MouseEventArgs e ) {
if ( m_splitter_moving ) {
m_splitter_moving = false;
UpdateLayout( m_splitter_distance_draft, m_splitter_width, m_panel1_min, m_panel2_min, false );
this.Cursor = Cursors.Default;
m_lbl_splitter.BackColor = SystemColors.Control;
}
}
private void m_lbl_splitter_MouseMove( object sender, MouseEventArgs e ) {
base.OnMouseMove( e );
if ( m_splitter_fixed ) {
return;
}
Point mouse_local = this.PointToClient( Control.MousePosition );
if ( m_splitter_moving ) {
int new_distance = m_splitter_distance;
if ( m_orientation == Orientation.Horizontal ) {
new_distance = mouse_local.X;
} else {
new_distance = mouse_local.Y;
}
if ( UpdateLayout( new_distance, m_splitter_width, m_panel1_min, m_panel2_min, true ) ) {
m_splitter_distance_draft = new_distance;
if ( m_orientation == Orientation.Horizontal ) {
m_lbl_splitter.Left = m_splitter_distance_draft;
} else {
m_lbl_splitter.Top = m_splitter_distance_draft;
}
}
}
}
}
}

View File

@ -0,0 +1,96 @@
/*
* BSplitterPanel.cs
* Copyright (c) 2008-2009 kbinani
*
* This file is part of Boare.Lib.AppUtil.
*
* Boare.Lib.AppUtil is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* Boare.Lib.AppUtil 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.ComponentModel;
using System.Windows.Forms;
using System.Drawing;
namespace Boare.Lib.AppUtil {
public class BSplitterPanel : Panel {
private BorderStyle m_border_style = BorderStyle.None;
private Color m_border_color = Color.Black;
public event EventHandler BorderStyleChanged;
public BSplitterPanel()
: base() {
base.AutoScroll = false;
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public Color BorderColor {
get {
return m_border_color;
}
set {
m_border_color = value;
}
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public new BorderStyle BorderStyle {
get {
return m_border_style;
}
set {
BorderStyle old = m_border_style;
m_border_style = value;
if ( m_border_style == BorderStyle.Fixed3D ) {
base.BorderStyle = BorderStyle.Fixed3D;
} else if ( m_border_style == BorderStyle.FixedSingle ) {
base.BorderStyle = BorderStyle.None;
base.Padding = new Padding( 1 );
} else {
base.Padding = new Padding( 0 );
base.BorderStyle = BorderStyle.None;
}
if ( old != m_border_style && BorderStyleChanged != null ) {
BorderStyleChanged( this, new EventArgs() );
}
}
}
[Browsable(false)]
public new int Width {
get {
return base.Width;
}
internal set {
base.Width = value;
}
}
[Browsable(false)]
public new int Height {
get {
return base.Height;
}
internal set {
base.Height = value;
}
}
[Browsable(false)]
public new Rectangle Bounds {
get {
return base.Bounds;
}
internal set {
base.Bounds = value;
}
}
}
}

View File

@ -0,0 +1,289 @@
/*
* BTrackBar.cs
* Copyright (c) 2009 kbinani
*
* This file is part of Boare.Lib.AppUtil.
*
* Boare.Lib.AppUtil is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* Boare.Lib.AppUtil 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.
*/
//#define BENCH
using System;
using System.Windows.Forms;
using System.Reflection;
namespace Boare.Lib.AppUtil {
/// <summary>
/// Valueの型を変えられるTrackBar
/// </summary>
public class BTrackBar<T> : UserControl where T : struct, IComparable<T> {
const int _MAX = 10000;
private T m_value;
private T m_min;
private T m_max;
private T m_tick_frequency;
private MethodInfo m_parser = null;
private ValueType m_value_type = ValueType.int_;
private TrackBarEx m_track_bar;
private Type m_type = typeof( int );
private enum ValueType {
sbyte_,
byte_,
shoft_,
ushort_,
int_,
uint_,
long_,
ulong_,
}
public event EventHandler ValueChanged;
private static void test() {
System.Windows.Forms.TrackBar tb = new System.Windows.Forms.TrackBar();
BTrackBar<int> tb2 = new BTrackBar<int>();
}
public BTrackBar() {
InitializeComponent();
T value_type = new T();
if ( value_type is byte ) {
m_value_type = BTrackBar<T>.ValueType.byte_;
} else if ( value_type is sbyte ) {
m_value_type = BTrackBar<T>.ValueType.sbyte_;
} else if ( value_type is short ) {
m_value_type = BTrackBar<T>.ValueType.shoft_;
} else if ( value_type is ushort ) {
m_value_type = BTrackBar<T>.ValueType.ushort_;
} else if ( value_type is int ) {
m_value_type = BTrackBar<T>.ValueType.int_;
} else if ( value_type is uint ) {
m_value_type = BTrackBar<T>.ValueType.uint_;
} else if ( value_type is long ) {
m_value_type = BTrackBar<T>.ValueType.long_;
} else if ( value_type is ulong ) {
m_value_type = BTrackBar<T>.ValueType.ulong_;
} else {
throw new NotSupportedException( "generic type T must be byte, sbyte, short, ushort, int, uint, long or ulong" );
}
m_type = value_type.GetType();
m_parser = typeof( T ).GetMethod( "Parse", new Type[] { typeof( string ) } );
if ( m_parser == null ) {
throw new ApplicationException( "this error never occurs; m_type=" + m_value_type );
}
#if BENCH
// Benchmark1: string parser
int _COUNT = 100000;
MethodInfo parser_double = typeof( double ).GetMethod( "Parse", new Type[] { typeof( string ) } );
Console.WriteLine( "parsed \"123.456\" = " + ((double)parser_double.Invoke( typeof( double ), new object[] { "123.456" } )) );
DateTime start = DateTime.Now;
for ( int i = 0; i < _COUNT; i++ ) {
double v = (double)parser_double.Invoke( typeof( double ), new object[] { "123.456" } );
}
Console.WriteLine( "Benchmark1; " + DateTime.Now.Subtract( start ).TotalMilliseconds / (double)_COUNT + "ms" );
// Benchmark2: BinaryFormatter
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
System.IO.MemoryStream ms = new System.IO.MemoryStream( 64 );
const double cdbbl = 123.456;
bf.Serialize( ms, cdbbl );
_COUNT = 10000;
ms.Seek( 0, System.IO.SeekOrigin.Begin );
Console.WriteLine( "deserilized = " + ((double)bf.Deserialize( ms )) );
start = DateTime.Now;
for ( int i = 0; i < _COUNT; i++ ) {
ms.Seek( 0, System.IO.SeekOrigin.Begin );
double v = (double)bf.Deserialize( ms );
}
Console.WriteLine( "Benchmark2; " + DateTime.Now.Subtract( start ).TotalMilliseconds / (double)_COUNT + "ms" );
// Benchmark3: Convert class
object obj = cdbbl;
Console.WriteLine( "Converted = " + Convert.ToDouble( obj ) );
_COUNT = 100000;
start = DateTime.Now;
for ( int i = 0; i < _COUNT; i++ ) {
double v = Convert.ToDouble( obj );
}
Console.WriteLine( "Benchmark3; " + DateTime.Now.Subtract( start ).TotalMilliseconds / (double)_COUNT + "ms" );
#endif
}
public T Maximum {
get {
return m_max;
}
set {
if ( value.CompareTo( m_min ) < 0 ) {
throw new ArgumentOutOfRangeException( "Maximum" );
}
m_max = value;
if ( m_max.CompareTo( m_value ) < 0 ) {
Value = m_max;
}
}
}
public T Minimum {
get {
return m_min;
}
set {
if ( value.CompareTo( m_max ) > 0 ) {
throw new ArgumentOutOfRangeException( "Minimum" );
}
m_min = value;
if ( m_min.CompareTo( m_value ) > 0 ) {
Value = m_min;
}
}
}
public TickStyle TickStyle {
get {
return m_track_bar.TickStyle;
}
set {
m_track_bar.TickStyle = value;
}
}
public T TickFrequency {
get {
return m_tick_frequency;
}
set {
m_tick_frequency = value;
double max = asDouble( m_max );
double min = asDouble( m_min );
double stride = asDouble( m_tick_frequency );
double rate = (max - min) / stride;
Console.WriteLine( "BTrackBar+set__TickFrequency" );
Console.WriteLine( " rate=" + rate );
int freq = (int)(_MAX / rate);
Console.WriteLine( " freq=" + freq );
Console.WriteLine( " m_track_bar.Maximum=" + m_track_bar.Maximum );
m_track_bar.TickFrequency = freq;
}
}
public T Value {
get {
return m_value;
}
set {
if ( value.CompareTo( m_max ) > 0 ) {
throw new ArgumentOutOfRangeException( "Value" );
}
if ( value.CompareTo( m_min ) < 0 ) {
throw new ArgumentOutOfRangeException( "Value" );
}
T old = m_value;
m_value = value;
if ( old.CompareTo( m_value ) != 0 && ValueChanged != null ) {
ValueChanged( this, new EventArgs() );
}
}
}
private double asDouble( T value ) {
object o = value;
return Convert.ToDouble( o );
}
private T add( T value1, T value2 ) {
object o1 = value1;
object o2 = value2;
switch ( m_value_type ) {
case BTrackBar<T>.ValueType.sbyte_:
sbyte sb1 = Convert.ToSByte( o1 );
sbyte sb2 = Convert.ToSByte( o2 );
object sb_r = (sb1 + sb2);
return (T)sb_r;
case BTrackBar<T>.ValueType.byte_:
byte b1 = Convert.ToByte( o1 );
byte b2 = Convert.ToByte( o2 );
object b_r = (b1 + b2);
return (T)b_r;
case BTrackBar<T>.ValueType.shoft_:
short s1 = Convert.ToInt16( o1 );
short s2 = Convert.ToInt16( o2 );
object s_r = (s1 + s2);
return (T)s_r;
case BTrackBar<T>.ValueType.ushort_:
ushort us1 = Convert.ToUInt16( o1 );
ushort us2 = Convert.ToUInt16( o2 );
object us_r = (us1 + us2);
return (T)us_r;
case BTrackBar<T>.ValueType.int_:
int i1 = Convert.ToInt32( o1 );
int i2 = Convert.ToInt32( o2 );
object i_r = (i1 + i2);
return (T)i_r;
case BTrackBar<T>.ValueType.uint_:
uint ui1 = Convert.ToUInt32( o1 );
uint ui2 = Convert.ToUInt32( o2 );
object ui_r = ui1 + ui2;
return (T)ui_r;
case BTrackBar<T>.ValueType.long_:
long l1 = Convert.ToInt64( o1 );
long l2 = Convert.ToInt64( o2 );
object l_r = l1 + l2;
return (T)l_r;
case BTrackBar<T>.ValueType.ulong_:
ulong ul1 = Convert.ToUInt64( o1 );
ulong ul2 = Convert.ToUInt64( o2 );
object ul_r = ul1 + ul2;
return (T)ul_r;
}
return new T();
}
private void InitializeComponent() {
this.m_track_bar = new TrackBarEx();
((System.ComponentModel.ISupportInitialize)(this.m_track_bar)).BeginInit();
this.SuspendLayout();
//
// trackBar
//
this.m_track_bar.Dock = System.Windows.Forms.DockStyle.Fill;
this.m_track_bar.Location = new System.Drawing.Point( 0, 0 );
this.m_track_bar.Name = "trackBar";
this.m_track_bar.Size = new System.Drawing.Size( 286, 55 );
this.m_track_bar.TabIndex = 0;
this.m_track_bar.Maximum = _MAX;
this.m_track_bar.Minimum = 0;
this.m_track_bar.TickFrequency = 1;
this.m_track_bar.SmallChange = 1;
this.m_track_bar.m_wheel_direction = false;
//
// BTrackBar
//
this.Controls.Add( this.m_track_bar );
this.Name = "BTrackBar";
this.Size = new System.Drawing.Size( 286, 55 );
((System.ComponentModel.ISupportInitialize)(this.m_track_bar)).EndInit();
this.ResumeLayout( false );
this.PerformLayout();
}
}
internal class TrackBarEx : TrackBar {
public bool m_wheel_direction = true;
protected override void OnMouseWheel( MouseEventArgs e ) {
if ( m_wheel_direction ) {
base.OnMouseWheel( new MouseEventArgs( e.Button, e.Clicks, e.X, e.Y, e.Delta ) );
} else {
base.OnMouseWheel( new MouseEventArgs( e.Button, e.Clicks, e.X, e.Y, -e.Delta ) );
}
}
}
}

View File

@ -0,0 +1,67 @@
/*
* BHScrollBar.Designer.cs
* Copyright (c) 2009 kbinani
*
* This file is part of Boare.Lib.AppUtil.
*
* Boare.Lib.AppUtil is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* Boare.Lib.AppUtil 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.
*/
namespace Boare.Lib.AppUtil {
partial class BVScrollBar {
/// <summary>
/// 必要なデザイナ変数です。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 使用中のリソースをすべてクリーンアップします。
/// </summary>
/// <param name="disposing">マネージ リソースが破棄される場合 true、破棄されない場合は false です。</param>
protected override void Dispose( bool disposing ) {
if ( disposing && (components != null) ) {
components.Dispose();
}
base.Dispose( disposing );
}
#region
/// <summary>
/// デザイナ サポートに必要なメソッドです。このメソッドの内容を
/// コード エディタで変更しないでください。
/// </summary>
private void InitializeComponent() {
this.vScroll = new System.Windows.Forms.VScrollBar();
this.SuspendLayout();
//
// hScroll
//
this.vScroll.Dock = System.Windows.Forms.DockStyle.Fill;
this.vScroll.Location = new System.Drawing.Point( 0, 0 );
this.vScroll.Name = "hScroll";
this.vScroll.Size = new System.Drawing.Size( 16, 205 );
this.vScroll.TabIndex = 0;
this.vScroll.ValueChanged += new System.EventHandler( this.vScroll_ValueChanged );
//
// BHScrollBar
//
this.AutoScaleDimensions = new System.Drawing.SizeF( 6F, 12F );
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add( this.vScroll );
this.Name = "BHScrollBar";
this.Size = new System.Drawing.Size( 16, 205 );
this.ResumeLayout( false );
}
#endregion
private System.Windows.Forms.VScrollBar vScroll;
}
}

View File

@ -0,0 +1,86 @@
/*
* BVScrollBar.cs
* Copyright (c) 2009 kbinani
*
* This file is part of Boare.Lib.AppUtil.
*
* Boare.Lib.AppUtil is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* Boare.Lib.AppUtil 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.Windows.Forms;
namespace Boare.Lib.AppUtil {
/// <summary>
/// Valueの値が正しくMinimumからMaximumの間を動くスクロールバー
/// </summary>
public partial class BVScrollBar : UserControl {
int m_max = 100;
int m_min = 0;
public event EventHandler ValueChanged;
public BVScrollBar() {
InitializeComponent();
}
public int Value {
get {
return vScroll.Value;
}
set {
vScroll.Value = value;
}
}
public int LargeChange {
get {
return vScroll.LargeChange;
}
set {
vScroll.LargeChange = value;
vScroll.Maximum = m_max + value;
}
}
public int SmallChange {
get {
return vScroll.SmallChange;
}
set {
vScroll.SmallChange = value;
}
}
public int Maximum {
get {
return m_max;
}
set {
m_max = value;
vScroll.Maximum = m_max + vScroll.LargeChange;
}
}
public int Minimum {
get {
return m_min;
}
set {
m_min = value;
}
}
private void vScroll_ValueChanged( object sender, EventArgs e ) {
if ( ValueChanged != null ) {
ValueChanged( this, e );
}
}
}
}

View File

@ -0,0 +1,159 @@
/*
* BitmapEx.cs
* Copyright (c) 2008-2009 kbinani
*
* This file is part of Boare.Lib.AppUtil.
*
* Boare.Lib.AppUtil is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* Boare.Lib.AppUtil 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.Drawing;
using System.Drawing.Imaging;
using System.IO;
namespace Boare.Lib.AppUtil {
public unsafe class BitmapEx : IDisposable {
private Bitmap m_base;
private bool m_locked = false;
private BitmapData m_bd;
private int m_stride;
private int m_byte_per_pixel;
public int Width {
get {
return m_base.Width;
}
}
public int Height {
get {
return m_base.Height;
}
}
public void Dispose() {
EndLock();
m_base.Dispose();
}
public void EndLock() {
if ( m_locked ) {
m_base.UnlockBits( m_bd );
m_locked = false;
}
}
public Bitmap GetBitmap() {
return (Bitmap)m_base.Clone();
}
public Color GetPixel( int x, int y ) {
if ( !m_locked ) {
BeginLock();
}
int location = y * m_stride + m_byte_per_pixel * x;
byte* dat = (byte*)m_bd.Scan0;
byte b = dat[location];
byte g = dat[location + 1];
byte r = dat[location + 2];
byte a = 255;
if ( m_base.PixelFormat == PixelFormat.Format32bppArgb ) {
a = dat[location + 3];
}
return Color.FromArgb( a, r, g, b );
}
public void SetPixel( int x, int y, Color color ) {
if ( !m_locked ) {
BeginLock();
}
int location = y * m_stride + m_byte_per_pixel * x;
byte* dat = (byte*)m_bd.Scan0;
dat[location] = (byte)color.B;
dat[location + 1] = (byte)color.G;
dat[location + 2] = (byte)color.R;
if ( m_base.PixelFormat == PixelFormat.Format32bppArgb ) {
dat[location + 3] = (byte)color.A;
}
}
public void BeginLock(){
if ( !m_locked ) {
m_bd = m_base.LockBits( new Rectangle( 0, 0, m_base.Width, m_base.Height ),
ImageLockMode.ReadWrite,
m_base.PixelFormat );
m_stride = m_bd.Stride;
switch ( m_base.PixelFormat ) {
case PixelFormat.Format24bppRgb:
m_byte_per_pixel = 3;
break;
case PixelFormat.Format32bppArgb:
m_byte_per_pixel = 4;
break;
default:
throw new Exception( "unsuported pixel format" );
}
m_locked = true;
}
}
~BitmapEx() {
m_base.Dispose();
}
public BitmapEx( Image original ) {
m_base = new Bitmap( original );
}
public BitmapEx( string filename ) {
m_base = new Bitmap( filename );
}
public BitmapEx( Stream stream ) {
m_base = new Bitmap( stream );
}
public BitmapEx( Image original, Size newSize ) {
m_base = new Bitmap( original, newSize );
}
public BitmapEx( int width, int height ) {
m_base = new Bitmap( width, height );
}
public BitmapEx( Stream stream, bool useIcm ) {
m_base = new Bitmap( stream, useIcm );
}
public BitmapEx( string filename, bool useIcm ) {
m_base = new Bitmap( filename, useIcm );
}
public BitmapEx( Type type, string resource ) {
m_base = new Bitmap( type, resource );
}
public BitmapEx( Image original, int width, int height ) {
m_base = new Bitmap( original, width, height );
}
public BitmapEx( int width, int height, Graphics g ) {
m_base = new Bitmap( width, height, g );
}
public BitmapEx( int width, int height, PixelFormat format ) {
m_base = new Bitmap( width, height, format );
}
public BitmapEx( int width, int height, int stride, PixelFormat format, IntPtr scan0 ) {
m_base = new Bitmap( width, height, stride, format, scan0 );
}
}
}

View File

@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.21022</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{0C58B068-272F-4390-A14F-3D72AFCF3DFB}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Boare.Lib.AppUtil</RootNamespace>
<AssemblyName>Boare.Lib.AppUtil</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>Boare.Lib.AppUtil.xml</DocumentationFile>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>Boare.Lib.AppUtil.xml</DocumentationFile>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<PlatformTarget>x86</PlatformTarget>
<OutputPath>bin\x86\Debug\</OutputPath>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefineConstants>DEBUG</DefineConstants>
<DocumentationFile>bin\x86\Debug\Boare.Lib.AppUtil.XML</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<PlatformTarget>x86</PlatformTarget>
<OutputPath>bin\x86\Release\</OutputPath>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin\x86\Release\Boare.Lib.AppUtil.XML</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data.DataSetExtensions">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="AuthorListEntry.cs" />
<Compile Include="BHScrollBar.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="BHScrollBar.Designer.cs">
<DependentUpon>BHScrollBar.cs</DependentUpon>
</Compile>
<Compile Include="BitmapEx.cs" />
<Compile Include="ColorBar.cs" />
<Compile Include="CubicSpline.cs" />
<Compile Include="InputBox.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="InputBox.Designer.cs">
<DependentUpon>InputBox.cs</DependentUpon>
</Compile>
<Compile Include="ISO639.cs" />
<Compile Include="Messaging.cs" />
<Compile Include="MessageBody.cs" />
<Compile Include="Misc.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="BSplitContainer.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="BSplitterPanel.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="BTrackBar.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="VersionInfo.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="VersionInfo.Designer.cs">
<DependentUpon>VersionInfo.cs</DependentUpon>
</Compile>
<Compile Include="BVScrollBar.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="BVScrollBar.Designer.cs">
<DependentUpon>BVScrollBar.cs</DependentUpon>
</Compile>
<Compile Include="XmlSerializeWithDescription.cs" />
<Compile Include="XmlStaticMemberSerializer.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\bocoree\bocoree.csproj">
<Project>{C8AAE632-9C6C-4372-8175-811528A66742}</Project>
<Name>bocoree</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,275 @@
/*
* CubicSpline.cs
* Copyright (c) 2008-2009 kbinani
*
* This file is part of Boare.Lib.AppUtil.
*
* Boare.Lib.AppUtil is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* Boare.Lib.AppUtil 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;
namespace Boare.Lib.AppUtil {
public class CubicSpline : ICloneable, IDisposable {
int m_num_key;
public double[] m_key, m_sp3_a, m_sp3_b, m_sp3_c, m_sp3_d;
double m_default;
public void Dispose() {
m_key = null;
m_sp3_a = null;
m_sp3_b = null;
m_sp3_c = null;
m_sp3_d = null;
GC.Collect();
m_num_key = 0;
}
public object Clone() {
CubicSpline ret = new CubicSpline( m_key, m_sp3_d );
ret.DefaultValue = m_default;
return ret;
}
public double DefaultValue {
get {
return m_default;
}
set {
m_default = value;
}
}
public double GetValue( double x ) {
int status;
double a, b, c, d, xx;
int i, index;
status = 0;
if ( this.m_num_key == -1 ) {
status = -2;
return 0.0;
}
if ( x < this.m_key[0] || this.m_key[this.m_num_key] < x ) {
status = -1;
return 0.0;
}//end if
index = -1;
for ( i = 0; i < this.m_num_key; i++ ) {// do i = 0, sp3%noOfKey - 1
if ( this.m_key[i] <= x && x <= this.m_key[i + 1] ) {// if(sp3%key(i) <= x .and. x <= sp3%key(i + 1))then
index = i;
break;// exit
}//end if
}//end do
xx = x - this.m_key[index];// xx = x - sp3%key(index)
a = this.m_sp3_a[index];// a = sp3%a(index)
b = this.m_sp3_b[index];// b = sp3%b(index)
c = this.m_sp3_c[index];// c = sp3%c(index)
d = this.m_sp3_d[index];// d = sp3%d(index)
return ((a * xx + b) * xx + c) * xx + d;// ans = ((a * xx + b) * xx + c) * xx + d
}//end subroutine spline3_val
/// <summary>配列の形で与えられるデータ点から3次のスプライン補間で用いる各区域のxの多項式の係数を計算します</summary>
/// <param name="x">データ点のx座標を格納した配列</param>
/// <param name="y">データ点のy座標を格納した配列</param>
public CubicSpline( double[] x, double[] y ) {
//integer, intent(in) :: n
//real(8), intent(in) :: x(0:n), y(0:n)
//integer, intent(out) :: status
int n = x.Length - 1;
int status;
m_num_key = -1;
m_default = 0.0;
double[] h, v, a, b, c, u, tmp, xx, yy;//real(8), allocatable :: h(:), v(:), a(:), b(:), c(:), u(:), tmp(:), xx(:), yy(:)
double buff1, buff2;//real(8) buff1, buff2
int i, iostatus, nn, j;//integer i, iostatus, nn, j
status = 0;
nn = n;
xx = new double[n + 1];
yy = new double[n + 1];//allocate(xx(0:n), yy(0:n))
xx = x;
yy = y;//yy(0:n) = y(0:n)
//nullify(sp3%a)
//nullify(sp3%b)
//nullify(sp3%c)
//nullify(sp3%d)
//nullify(sp3%key)
while ( true ) {//do
iostatus = 0;
for ( i = 1; i <= nn - 1; i++ ) {// do i = 1, nn - 1
if ( xx[i + 1] - x[i] == 0.0 ) {// if(xx(i + 1) - xx(i) == 0.0d0)then
for ( j = i; j <= nn - 2; j++ ) {// do j = i, nn - 2
xx[j] = xx[j + 1];// xx(j) = xx(j + 1)
yy[j] = yy[j + 1];// yy(j) = yy(j + 1)
}// end do
iostatus = -1;
// create the copy of xx
//if(allocated(tmp))then
//deallocate(tmp)
//end if
tmp = new double[nn];// allocate(tmp(0:nn - 1))
for ( int k = 0; k < nn; k++ ) {
tmp[k] = xx[k];
}// tmp(0:nn - 1) = xx(0:nn - 1)
// deallocate(xx)
xx = new double[nn];// allocate(xx(0:nn - 1))
for ( int k = 0; k < nn; k++ ) {
xx[k] = tmp[k];
}// xx(0:nn - 1) = tmp(0:nn - 1)
// create the copy of yy
for ( int k = 0; k < nn; k++ ) {
tmp[k] = yy[k];
}// tmp(0:nn - 1) = yy(0:nn - 1)
//deallocate(yy)
yy = new double[nn];// allocate(yy(0:nn - 1))
for ( int k = 0; k < nn; k++ ) {
yy[k] = tmp[k];
}// yy(0:nn - 1) = tmp(0:nn - 1)
break;// exit
}//end if
}//end do
if ( iostatus == 0 ) {// if(iostatus == 0)then
break;// exit
} else {// else
nn = nn - 1;// nn = nn - 1
}// end if
}// end do
//allocate(h(0:nn - 1), v(1:nn - 1), a(1:nn - 1), b(1:nn - 1), c(1:nn - 1), u(1:nn - 1))
h = new double[nn];
v = new double[nn - 1];
a = new double[nn - 1];
b = new double[nn - 1];
c = new double[nn - 1];
u = new double[nn - 1];
// executed in debug mode ******************************************************************************************************
//if(spline_debug_flag == 1)then ! **
//open(unit = 26, file = 'spline_debug.txt') ! **
//end if ! **
// *****************************************************************************************************************************
// calculate h_j
for ( i = 0; i < nn; i++ ) {// do i = 0, nn - 1
h[i] = xx[i + 1] - xx[i];// h(i) = xx(i + 1) - xx(i)
if ( h[i] <= 0.0 ) {// if(h(i) <= 0.0d0)then
this.m_key = new double[1];
this.m_sp3_a = new double[1];
this.m_sp3_b = new double[1];
this.m_sp3_c = new double[1];
this.m_sp3_d = new double[1];
return;
}
}
// calculate v_j
for ( i = 1; i < nn; i++ ) {// do i = 1, nn - 1
buff1 = yy[i + 1] - yy[i];// buff1 = yy(i + 1) - yy(i)
buff2 = yy[i] - y[i - 1];// buff2 = yy(i) - yy(i - 1)
if ( buff1 == 0.0 ) {// if(buff1 == 0.0d0)then
if ( buff2 == 0.0 ) {// if(buff2 == 0.0d0)then
v[i - 1] = 0;// v(i) = 0.0d0
} else {// else
v[i - 1] = 6.0 * (-(yy[i] - yy[i - 1]) / h[i - 1]);// v(i) = 6.0d0 * (- (yy(i) - yy(i - 1)) / h(i - 1))
}// end if
} else {// else
if ( buff2 == 0.0 ) {// if(buff2 == 0.0d0)then
v[i - 1] = 6.0 * ((yy[i + 1] - yy[i]) / h[i]);// v(i) = 6.0d0 * ((yy(i + 1) - yy(i)) / h(i))
} else {// else
v[i - 1] = 6.0 * ((yy[i + 1] - yy[i]) / h[i] - (yy[i] - yy[i - 1]) / h[i - 1]);// v(i) = 6.0d0 * ((yy(i + 1) - yy(i)) / h(i) - (yy(i) - yy(i - 1)) / h(i - 1))
}// end if
}// end if
}//end do
for ( i = 1; i < nn; i++ ) {// do i = 1, nn - 1
a[i - 1] = 2.0 * (h[i - 1] + h[i]);// a(i) = 2.0d0 * (h(i - 1) + h(i))
b[i - 1] = h[i - 1];// b(i) = h(i - 1)
c[i - 1] = h[i];// c(i) = h(i)
}// end do
LUDecTDM( nn - 1, a, b, c, v, out u );// call LUDecTDM(nn - 1, a, b, c, v, u)
m_num_key = nn;// sp3%noOfKey = nn
this.m_sp3_a = new double[nn];// allocate(sp3%a(0:nn - 1))
this.m_sp3_b = new double[nn];// allocate(sp3%b(0:nn - 1))
this.m_sp3_c = new double[nn];// allocate(sp3%c(0:nn - 1))
this.m_sp3_d = new double[nn];// allocate(sp3%d(0:nn - 1))
this.m_key = new double[nn + 1];// allocate(sp3%key(0:nn))
this.m_sp3_a[0] = u[0] / (6.0 * h[0]);// sp3%a(0) = u(1) / (6.0d0 * h(0))
this.m_sp3_b[0] = 0.0;// sp3%b(0) = 0.0d0
this.m_sp3_c[0] = (yy[1] - yy[0]) / h[0] - h[0] * u[0] / 6.0;// sp3%c(0) = (yy(1) - yy(0)) / h(0) - h(0) * u(1) / 6.0d0
this.m_sp3_a[nn - 1] = -u[nn - 2] / (6.0 * h[nn - 1]);// sp3%a(nn - 1) = -u(nn - 1) / (6.0d0 * h(nn - 1))
this.m_sp3_b[nn - 1] = u[nn - 2] * 0.5;// sp3%b(nn - 1) = u(nn - 1) * 0.5d0
this.m_sp3_c[nn - 1] = (yy[nn] - yy[nn - 1]) / h[nn - 1] - h[nn - 1] * u[nn - 2] / 3.0;// sp3%c(nn - 1) = (yy(nn) - yy(nn - 1)) / h(nn - 1) - h(nn - 1) * u(nn - 1) / 3.0d0
for ( i = 1; i <= nn - 2; i++ ) {// do i = 1, nn - 2
this.m_sp3_a[i] = (u[i] - u[i - 1]) / (6.0 * h[i]);// sp3%a(i) = (u(i + 1) - u(i)) / (6.0d0 * h(i))
this.m_sp3_b[i] = u[i - 1] * 0.5;// sp3%b(i) = u(i) * 0.5d0
this.m_sp3_c[i] = (yy[i + 1] - yy[i]) / h[i] - h[i] * (2.0 * u[i - 1] + u[i]) / 6.0;// sp3%c(i) = (yy(i + 1) - yy(i)) / h(i) - h(i) * (2.0d0 * u(i) + u(i + 1)) / 6.0d0
}//end do
this.m_key = xx;
// sp3%key(0:nn) = xx(0:nn)
for ( int k = 0; k < nn; k++ ) {
this.m_sp3_d[k] = yy[k];
}// sp3%d(0:nn - 1) = yy(0:nn - 1)
}
/// <summary>
/// This subroutine solves system of linear equation(only for
/// tridiagonal matrix system) by LU decompression method.
/// Meanings of variables are defined below.
/// ( a1 c1 0 ) ( x1 ) ( y1 )
/// ( b2 a2 c2 ) ( x2 ) ( y2 )
/// ( b3 a3 c3 ) ( x3 ) ( y3 )
/// ( ... ) ( ...) = ( ...)
/// ( bN-1 aN-1 cN-1 ) (xN-1) (yN-1)
/// ( 0 bN aN ) ( xN ) ( yN )
/// </summary>
/// <param name="N"></param>
/// <param name="a"></param>
/// <param name="b"></param>
/// <param name="c"></param>
/// <param name="y"></param>
/// <param name="x"></param>
private static void LUDecTDM( int N, double[] a, double[] b, double[] c, double[] y, out double[] x ) {
double[] d = new double[N];
double[] z = new double[N];
double[] l = new double[N];
int i;
x = new double[N];
d[0] = a[0];// d(1) = a(1)
for ( i = 1; i < N; i++ ) {// do i = 2, N
l[i] = b[i] / d[i - 1];// l(i) = b(i) / d(i - 1)
d[i] = a[i] - l[i] * c[i - 1];// d(i) = a(i) - l(i) * c(i - 1)
}// end do
z[0] = y[0];// z(1) = y(1)
for ( i = 1; i < N; i++ ) {// do i = 2, N
z[i] = y[i] - l[i] * z[i - 1];// z(i) = y(i) - l(i) * z(i - 1)
}// end do
x[N - 1] = z[N - 1] / d[N - 1];// x(N) = z(N) / d(N)
for ( i = N - 2; i >= 0; i-- ) {// do i = N - 1, 1, -1
x[i] = (z[i] - c[i] * x[i + 1]) / d[i];// x(i) = (z(i) - c(i) * x(i + 1)) / d(i)
}// end do
}
}
}

View File

@ -0,0 +1,29 @@
/*
* ISO639.cs
* Copyright (c) 2008-2009 kbinani
*
* This file is part of Boare.Lib.AppUtil.
*
* Boare.Lib.AppUtil is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* Boare.Lib.AppUtil 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.Globalization;
namespace Boare.Lib.AppUtil {
internal class iso639 {
public static bool CheckValidity( string code_string ) {
try {
CultureInfo c = CultureInfo.CreateSpecificCulture( code_string );
} catch {
return false;
}
return true;
}
}
}

View File

@ -0,0 +1,113 @@
/*
* InputBox.Designer.cs
* Copyright (c) 2008-2009 kbinani
*
* This file is part of Boare.Lib.AppUtil.
*
* Boare.Lib.AppUtil is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* Boare.Lib.AppUtil 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.
*/
namespace Boare.Lib.AppUtil {
partial class InputBox {
/// <summary>
/// 必要なデザイナ変数です。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 使用中のリソースをすべてクリーンアップします。
/// </summary>
/// <param name="disposing">マネージ リソースが破棄される場合 true、破棄されない場合は false です。</param>
protected override void Dispose( bool disposing ) {
if ( disposing && (components != null) ) {
components.Dispose();
}
base.Dispose( disposing );
}
#region Windows
/// <summary>
/// デザイナ サポートに必要なメソッドです。このメソッドの内容を
/// コード エディタで変更しないでください。
/// </summary>
private void InitializeComponent() {
this.txtInput = new System.Windows.Forms.TextBox();
this.btnOk = new System.Windows.Forms.Button();
this.lblMessage = new System.Windows.Forms.Label();
this.btnCancel = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// txtInput
//
this.txtInput.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.txtInput.Location = new System.Drawing.Point( 12, 24 );
this.txtInput.Name = "txtInput";
this.txtInput.Size = new System.Drawing.Size( 309, 19 );
this.txtInput.TabIndex = 0;
//
// btnOk
//
this.btnOk.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.btnOk.Location = new System.Drawing.Point( 246, 49 );
this.btnOk.Name = "btnOk";
this.btnOk.Size = new System.Drawing.Size( 75, 23 );
this.btnOk.TabIndex = 1;
this.btnOk.Text = "OK";
this.btnOk.UseVisualStyleBackColor = true;
this.btnOk.Click += new System.EventHandler( this.btnOk_Click );
//
// lblMessage
//
this.lblMessage.AutoSize = true;
this.lblMessage.Location = new System.Drawing.Point( 12, 9 );
this.lblMessage.Name = "lblMessage";
this.lblMessage.Size = new System.Drawing.Size( 0, 12 );
this.lblMessage.TabIndex = 2;
//
// btnCancel
//
this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.btnCancel.Location = new System.Drawing.Point( -100, 49 );
this.btnCancel.Name = "btnCancel";
this.btnCancel.Size = new System.Drawing.Size( 75, 23 );
this.btnCancel.TabIndex = 3;
this.btnCancel.Text = "Cancel";
this.btnCancel.UseVisualStyleBackColor = true;
//
// InputBox
//
this.AcceptButton = this.btnOk;
this.AutoScaleDimensions = new System.Drawing.SizeF( 6F, 12F );
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.btnCancel;
this.ClientSize = new System.Drawing.Size( 333, 82 );
this.Controls.Add( this.btnCancel );
this.Controls.Add( this.lblMessage );
this.Controls.Add( this.btnOk );
this.Controls.Add( this.txtInput );
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "InputBox";
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.Text = "InputBox";
this.ResumeLayout( false );
this.PerformLayout();
}
#endregion
private System.Windows.Forms.TextBox txtInput;
private System.Windows.Forms.Button btnOk;
private System.Windows.Forms.Label lblMessage;
private System.Windows.Forms.Button btnCancel;
}
}

View File

@ -0,0 +1,37 @@
/*
* InputBox.cs
* Copyright (c) 2008-2009 kbinani
*
* This file is part of Boare.Lib.AppUtil.
*
* Boare.Lib.AppUtil is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* Boare.Lib.AppUtil 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.Windows.Forms;
namespace Boare.Lib.AppUtil {
public partial class InputBox : Form {
public InputBox( string message ) {
InitializeComponent();
lblMessage.Text = message;
}
public string Result {
get {
return txtInput.Text;
}
set {
txtInput.Text = value;
}
}
private void btnOk_Click( object sender, EventArgs e ) {
DialogResult = DialogResult.OK;
}
}
}

View File

@ -0,0 +1,21 @@
/*
* MathEx.cs
* Copyright (c) 2008 kbinani
*
* This file is part of Boare.Lib.AppUtil.
*
* Boare.Lib.AppUtil is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* Boare.Lib.AppUtil 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;
using System.Text;
namespace Boare.Lib.AppUtil {
}

View File

@ -0,0 +1,162 @@
/*
* MessageBody.cs
* Copyright (c) 2008-2009 kbinani
*
* This file is part of Boare.Lib.AppUtil.
*
* Boare.Lib.AppUtil is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* Boare.Lib.AppUtil 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;
using System.Text;
using System.IO;
namespace Boare.Lib.AppUtil {
public class MessageBody {
public string lang;
public string po_header = "";
public Dictionary<string, string> list = new Dictionary<string,string>();
public MessageBody( string lang_ ) {
lang = lang_;
}
public MessageBody( string lang, string[] ids, string[] messages ) {
this.lang = lang;
list = new Dictionary<string, string>();
for( int i = 0; i < ids.Length; i++ ) {
list.Add( ids[i], messages[i] );
}
}
public MessageBody( string lang_, string file ) {
lang = lang_;
//Dictionary<string, string> list = new Dictionary<string, string>();
po_header = "";
using ( StreamReader sr = new StreamReader( file ) ) {
while ( sr.Peek() >= 0 ) {
string msgid;
string first_line = sr.ReadLine();
string last_line = ReadTillMessageEnd( sr, first_line, "msgid", out msgid );
string msgstr;
last_line = ReadTillMessageEnd( sr, last_line, "msgstr", out msgstr );
//if ( msgid.Length > 0 && msgstr.Length > 0 ) {
if ( msgid.Length > 0 ) {
if ( list.ContainsKey( msgid ) ) {
list[msgid] = msgstr;
} else {
list.Add( msgid, msgstr );
}
} else {
po_header = msgstr;
}
}
}
string[] ids = new string[list.Keys.Count];
string[] msgs = new string[ids.Length];
int i = -1;
foreach ( string id in list.Keys ) {
i++;
ids[i] = id;
msgs[i] = list[ids[i]];
}
}
public string GetMessage( string id ) {
if ( list.ContainsKey( id ) ) {
string ret = list[id];
if ( ret == "" ) {
return id;
} else {
return list[id];
}
}
return id;
}
public void Write( string file ) {
using ( StreamWriter sw = new StreamWriter( file ) ) {
if ( po_header != "" ) {
sw.WriteLine( "msgid \"\"" );
sw.WriteLine( "msgstr \"\"" );
sw.WriteLine( po_header );
sw.WriteLine();
} else {
sw.WriteLine( "msgid \"\"" );
sw.WriteLine( "msgstr \"\"" );
sw.WriteLine( "\"Content-Type: text/plain; charset=UTF-8\\n\"" );
sw.WriteLine( "\"Content-Transfer-Encoding: 8bit\\n\"" );
sw.WriteLine();
}
foreach ( string key in list.Keys ) {
string skey = key.Replace( "\n", "\\n\"\n\"" );
sw.WriteLine( "msgid \"" + skey + "\"" );
string s = list[key];
s = s.Replace( "\n", "\\n\"\n\"" );
sw.WriteLine( "msgstr \"" + s + "\"" );
sw.WriteLine();
}
}
}
private static void SeparateEntryAndMessage( string source, out string entry, out string message ) {
string line = source.Trim();
entry = "";
message = "";
if ( line.Length <= 0 ) {
return;
}
int index_space = line.IndexOf( ' ' );
int index_dquoter = line.IndexOf( '"' );
int index = Math.Min( index_dquoter, index_space );
entry = line.Substring( 0, index );
message = line.Substring( index_dquoter + 1 );
message = message.Substring( 0, message.Length - 1 );
}
private static string ReadTillMessageEnd( StreamReader sr, string first_line, string entry, out string msg ) {
msg = "";
string line = first_line;
bool entry_found = false;
if ( line.StartsWith( entry ) ) {
string dum, dum2;
SeparateEntryAndMessage( line, out dum, out dum2 );
msg += dum2;
} else {
while ( sr.Peek() >= 0 ) {
line = sr.ReadLine();
if ( line.StartsWith( "#" ) ) {
continue;
}
if ( line.StartsWith( entry ) ) {
string dum, dum2;
SeparateEntryAndMessage( line, out dum, out dum2 );
msg += dum2;
break;
}
}
}
string ret = "";
while ( sr.Peek() >= 0 ) {
line = sr.ReadLine();
if ( !line.StartsWith( "\"" ) ) {
msg = msg.Replace( "\\\"", "\"" );
msg = msg.Replace( "\\n", "\n" );
return line;
}
int index = line.LastIndexOf( "\"" );
msg += line.Substring( 1, index - 1 );
}
msg = msg.Replace( "\\\"", "\"" );
msg = msg.Replace( "\\n", "\n" );
return line;
}
}
}

View File

@ -0,0 +1,107 @@
/*
* Messaging.cs
* Copyright (c) 2008-2009 kbinani
*
* This file is part of Boare.Lib.AppUtil.
*
* Boare.Lib.AppUtil is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* Boare.Lib.AppUtil 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;
using System.IO;
using System.Windows.Forms;
namespace Boare.Lib.AppUtil {
public static class Messaging {
private static string s_lang = "";
private static List<MessageBody> s_messages = new List<MessageBody>();
public static string[] GetKeys( string lang ) {
foreach ( MessageBody dict in s_messages ) {
if ( lang == dict.lang ) {
List<string> list = new List<string>();
foreach ( string key in dict.list.Keys ) {
list.Add( key );
}
return list.ToArray();
}
}
return null;
}
public static string[] GetRegisteredLanguage() {
List<string> res = new List<string>();
foreach ( MessageBody dict in s_messages ) {
res.Add( dict.lang );
}
return res.ToArray();
}
public static string Language {
get {
if ( s_lang != "" ) {
return s_lang;
} else {
s_lang = "en";
return s_lang;
}
}
set {
if ( value != "" ) {
s_lang = value;
} else {
s_lang = "en";
}
}
}
/// <summary>
/// 現在の実行ディレクトリにある言語設定ファイルを全て読込み、メッセージリストに追加します
/// </summary>
public static void LoadMessages() {
LoadMessages( Application.StartupPath );
}
/// <summary>
/// 指定されたディレクトリにある言語設定ファイルを全て読込み、メッセージリストに追加します
/// </summary>
/// <param name="directory"></param>
public static void LoadMessages( string directory ) {
DirectoryInfo current = new DirectoryInfo( directory );
s_messages.Clear();
#if DEBUG
Console.WriteLine( "Messaging+LoadMessages()" );
#endif
foreach ( FileInfo fi in current.GetFiles( "*.po" ) ) {
string fname = fi.FullName;
#if DEBUG
Console.WriteLine( " fname=" + fname );
#endif
AppendFromFile( fname );
}
}
public static void AppendFromFile( string file ) {
s_messages.Add( new MessageBody( Path.GetFileNameWithoutExtension( file ), file ) );
}
public static string GetMessage( string id ) {
if ( s_lang.Length <= 0 ) {
s_lang = "en";
}
foreach ( MessageBody mb in s_messages ) {
if ( mb.lang == s_lang ) {
return mb.GetMessage( id );
}
}
return id;
}
}
}

View File

@ -0,0 +1,325 @@
/*
* Misc.cs
* Copyright (c) 2008-2009 kbinani
*
* This file is part of Boare.Lib.AppUtil.
*
* Boare.Lib.AppUtil is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* Boare.Lib.AppUtil 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;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using System.Drawing.Imaging;
using System.Reflection;
using System.IO;
namespace Boare.Lib.AppUtil {
public static partial class Misc {
/// <summary>
/// 指定したディレクトリに作成可能な、一時ファイル名を取得します
/// </summary>
/// <param name="directory">ディレクトリ</param>
/// <returns></returns>
public static string GetTempFileNameIn( string directory ) {
for ( uint i = uint.MinValue; i <= uint.MaxValue; i++ ) {
string file = Path.Combine( directory, "temp" + i );
if ( !File.Exists( file ) ) {
return file;
}
}
return "";
}
/// <summary>
/// 指定したディレクトリに作成可能な、一時ファイル名を取得します
/// </summary>
/// <param name="directory">ディレクトリ</param>
/// <param name="extention">拡張子ex. ".txt"</param>
/// <returns></returns>
public static string GetTempFileNameIn( string directory, string extention ){
for ( uint i = uint.MinValue; i <= uint.MaxValue; i++ ) {
string file = Path.Combine( directory, "temp" + i + extention );
if ( !File.Exists( file ) ) {
return file;
}
}
return "";
}
/// <summary>
/// 指定した画像ファイルから新しいBitmapオブジェクトを作成します
/// </summary>
/// <param name="file"></param>
/// <returns></returns>
public static Bitmap BitmapFromStream( string file ) {
if ( !File.Exists( file ) ) {
return null;
}
FileStream fs = new FileStream( file, FileMode.Open );
Bitmap ret = new Bitmap( fs );
fs.Close();
return ret;
}
/// <summary>
/// 指定した画像ファイルから新しいImageオブジェクトを作成します
/// </summary>
/// <param name="file"></param>
/// <returns></returns>
public static Image ImageFromStream( string file ) {
if ( !File.Exists( file ) ) {
return null;
}
FileStream fs = new FileStream( file, FileMode.Open );
Image ret = Image.FromStream( fs );
fs.Close();
return ret;
}
/// <summary>
/// ImageFormatからデフォルトの拡張子を取得します
/// </summary>
/// <param name="format"></param>
/// <returns></returns>
public static string GetExtensionFromImageFormat( ImageFormat format ) {
switch ( format.ToString().ToLower() ) {
case "bmp":
return "bmp";
case "emf":
return "emf";
case "gif":
return "gif";
case "jpeg":
return "jpg";
case "png":
return "png";
case "tiff":
return "tiff";
case "wmf":
return "wmf";
default:
return "";
}
}
/// <summary>
/// System.Drawimg.Imaging.ImageFormatで使用可能なフォーマットの一覧を取得します
/// </summary>
/// <returns></returns>
public static ImageFormat[] GetImageFormats() {
#if DEBUG
Console.WriteLine( "GetImageFormats()" );
#endif
PropertyInfo[] properties = typeof( System.Drawing.Imaging.ImageFormat ).GetProperties();
List<ImageFormat> ret = new List<ImageFormat>();
foreach ( PropertyInfo pi in properties ) {
if ( pi.PropertyType.Equals( typeof( System.Drawing.Imaging.ImageFormat ) ) ) {
ImageFormat ifmt = (System.Drawing.Imaging.ImageFormat)pi.GetValue( null, null );
#if DEBUG
Console.WriteLine( ifmt.ToString() );
#endif
ret.Add( ifmt );
}
}
return ret.ToArray();
}
public static void RgbToHsv( int r, int g, int b, out double h, out double s, out double v ) {
RgbToHsv( r / 255.0, g / 255.0, b / 255.0, out h, out s, out v );
}
public static void RgbToHsv( double r, double g, double b, out double h, out double s, out double v ) {
double tmph, imax, imin;
const double sqrt3 = 1.7320508075688772935274463415059;
imax = Math.Max( r, Math.Max( g, b ) );
imin = Math.Min( r, Math.Min( g, b ) );
if ( imax == 0.0 ) {
h = 0;
s = 0;
v = 0;
return;
} else if ( imax == imin ) {
tmph = 0;
} else {
if ( r == imax ) {
tmph = 60.0 * (g - b) / (imax - imin);
} else if ( g == imax ) {
tmph = 60.0 * (b - r) / (imax - imin) + 120.0;
} else {
tmph = 60.0 * (r - g) / (imax - imin) + 240.0;
}
}
while ( tmph < 0.0 ) {
tmph = tmph + 360.0;
}
while ( tmph >= 360.0 ) {
tmph = tmph - 360.0;
}
h = tmph / 360.0;
s = (imax - imin) / imax;
v = imax;
}
/*public static void RgbToHsv( double r, double g, double b, out double h, out double s, out double v ) {
double tmph, imax, imin;
const double sqrt3 = 1.7320508075688772935274463415059;
const double deg2rad = 180.0 / Math.PI;
imax = Math.Max( r, Math.Max( g, b ) );
imin = Math.Min( r, Math.Min( g, b ) );
if ( imax == 0.0 ) {
h = 0;
s = 0;
v = 0;
return;
} else if ( imax == imin ) {
tmph = 0;
} else {
double x = 2.0 * r - g - b;
double y = sqrt3 * (g - b);
if ( x == 0.0 ) {
if ( y > 0.0 ) {
tmph = 90.0;
} else {
tmph = 270.0;
}
} else {
tmph = Math.Atan2( y, x );
tmph = tmph * deg2rad;
}
}
while ( tmph < 0.0 ) {
tmph = tmph + 360.0;
}
while ( tmph >= 360.0 ) {
tmph = tmph - 360.0;
}
h = tmph / 360.0;
s = (imax - imin) / imax;
v = imax;
}*/
public static Color HsvToColor( double h, double s, double v ) {
double dr, dg, db;
HsvToRgb( h, s, v, out dr, out dg, out db );
return Color.FromArgb( (int)(dr * 255), (int)(dg * 255), (int)(db * 255) );
}
public static void HsvToRgb( double h, double s, double v, out byte r, out byte g, out byte b ) {
double dr, dg, db;
HsvToRgb( h, s, v, out dr, out dg, out db );
r = (byte)(dr * 255);
g = (byte)(dg * 255);
b = (byte)(db * 255);
}
public static void HsvToRgb( double h, double s, double v, out double r, out double g, out double b ) {
double f, p, q, t, hh;
int hi;
r = g = b = 0.0;
if ( s == 0 ) {
r = v;
g = v;
b = v;
} else {
hh = h * 360.0;
hi = (int)(hh / 60.0) % 6;
f = hh / 60.0 - (double)(hi);
p = v * (1.0 - s);
q = v * (1.0 - f * s);
t = v * (1.0 - (1.0 - f) * s);
switch ( hi ) {
case 0:
r = v;
g = t;
b = p;
break;
case 1:
r = q;
g = v;
b = p;
break;
case 2:
r = p;
g = v;
b = t;
break;
case 3:
r = p;
g = q;
b = v;
break;
case 4:
r = t;
g = p;
b = v;
break;
case 5:
r = v;
g = p;
b = q;
break;
}
}
}
/// <summary>
/// 指定された文字列を指定されたフォントで描画したときのサイズを計測します。
/// </summary>
/// <param name="text"></param>
/// <param name="font"></param>
/// <returns></returns>
public static Size MeasureString( string text, Font font ) {
using ( Bitmap dumy = new Bitmap( 1, 1 ) )
using ( Graphics g = Graphics.FromImage( dumy ) ) {
SizeF tmp = g.MeasureString( text, font );
return new Size( (int)tmp.Width, (int)tmp.Height );
}
}
/// <summary>
/// 指定したコントロールと、その子コントロールのフォントを変更します
/// </summary>
/// <param name="c"></param>
/// <param name="font"></param>
public static void ApplyFontRecurse( Control c, Font font ) {
c.Font = font;
for ( int i = 0; i < c.Controls.Count; i++ ) {
ApplyFontRecurse( c.Controls[i], font );
}
}
/// <summary>
///
/// </summary>
/// <param name="start1"></param>
/// <param name="end1"></param>
/// <param name="start2"></param>
/// <param name="end2"></param>
/// <returns></returns>
public static bool IsOverwrapped( double start1, double end1, double start2, double end2 ) {
if ( start2 <= start1 && start1 < end2 ) {
return true;
} else if ( start2 < end1 && end1 < end2 ) {
return true;
} else {
if ( start1 <= start2 && start2 < end1 ) {
return true;
} else if ( start1 < end2 && end2 < end1 ) {
return true;
} else {
return false;
}
}
}
}
}

View File

@ -0,0 +1,29 @@
/*
* AssemblyInfo.cs
* Copyright (c) 2008-2009 kbinani
*
* This file is part of Boare.Lib.AppUtil.
*
* Boare.Lib.AppUtil is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* Boare.Cadencii 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.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle( "Boare.Lib.AppUtil" )]
[assembly: AssemblyDescription( "" )]
[assembly: AssemblyConfiguration( "" )]
[assembly: AssemblyCompany( "Boare" )]
[assembly: AssemblyProduct( "Boare.Lib.AppUtil" )]
[assembly: AssemblyCopyright( "Copyright © 2008-2009" )]
[assembly: AssemblyTrademark( "" )]
[assembly: AssemblyCulture( "" )]
[assembly: ComVisible( false )]
[assembly: Guid( "1d456f8c-100a-4f4b-b53f-d09a32ce6bfc" )]
[assembly: AssemblyVersion( "1.0.0.0" )]
[assembly: AssemblyFileVersion( "1.0.1" )]

View File

@ -0,0 +1,136 @@
/*
* VersionInfo.Designer.cs
* Copyright (c) 2008-2009 kbinani
*
* This file is part of Boare.Lib.AppUtil.
*
* Boare.Lib.AppUtil is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* Boare.Lib.AppUtil 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.Drawing;
namespace Boare.Lib.AppUtil {
partial class VersionInfo {
/// <summary>
/// 必要なデザイナ変数です。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 使用中のリソースをすべてクリーンアップします。
/// </summary>
/// <param name="disposing">マネージ リソースが破棄される場合 true、破棄されない場合は false です。</param>
protected override void Dispose( bool disposing ) {
if( disposing && (components != null) ) {
components.Dispose();
}
base.Dispose( disposing );
}
#region Windows
/// <summary>
/// デザイナ サポートに必要なメソッドです。このメソッドの内容を
/// コード エディタで変更しないでください。
/// </summary>
private void InitializeComponent() {
this.components = new System.ComponentModel.Container();
this.btnFlip = new System.Windows.Forms.Button();
this.btnOK = new System.Windows.Forms.Button();
this.timer = new System.Windows.Forms.Timer( this.components );
this.btnSaveAuthorList = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// btnFlip
//
this.btnFlip.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.btnFlip.Location = new System.Drawing.Point( 13, 391 );
this.btnFlip.Name = "btnFlip";
this.btnFlip.Size = new System.Drawing.Size( 75, 21 );
this.btnFlip.TabIndex = 2;
this.btnFlip.Text = "クレジット";
this.btnFlip.UseVisualStyleBackColor = true;
this.btnFlip.Click += new System.EventHandler( this.btnFlip_Click );
//
// btnOK
//
this.btnOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnOK.DialogResult = System.Windows.Forms.DialogResult.OK;
this.btnOK.Location = new System.Drawing.Point( 211, 391 );
this.btnOK.Name = "btnOK";
this.btnOK.Size = new System.Drawing.Size( 75, 21 );
this.btnOK.TabIndex = 1;
this.btnOK.Text = "OK";
this.btnOK.UseVisualStyleBackColor = true;
this.btnOK.Click += new System.EventHandler( this.btnOK_Click );
//
// timer
//
this.timer.Interval = 30;
this.timer.Tick += new System.EventHandler( this.timer_Tick );
//
// btnSaveAuthorList
//
this.btnSaveAuthorList.Location = new System.Drawing.Point( 123, 391 );
this.btnSaveAuthorList.Name = "btnSaveAuthorList";
this.btnSaveAuthorList.Size = new System.Drawing.Size( 43, 21 );
this.btnSaveAuthorList.TabIndex = 3;
this.btnSaveAuthorList.Text = "button1";
this.btnSaveAuthorList.UseVisualStyleBackColor = true;
this.btnSaveAuthorList.Visible = false;
//
// VersionInfoEx
//
this.AcceptButton = this.btnOK;
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
this.ClientSize = new System.Drawing.Size( 300, 426 );
this.Controls.Add( this.btnSaveAuthorList );
this.Controls.Add( this.btnOK );
this.Controls.Add( this.btnFlip );
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.KeyPreview = true;
this.MaximizeBox = false;
this.MaximumSize = new System.Drawing.Size( 306, 451 );
this.MinimizeBox = false;
this.MinimumSize = new System.Drawing.Size( 306, 451 );
this.Name = "VersionInfoEx";
this.ShowIcon = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "VersionInfoEx";
this.Paint += new System.Windows.Forms.PaintEventHandler( this.VersionInfoEx_Paint );
this.KeyDown += new System.Windows.Forms.KeyEventHandler( this.VersionInfoEx_KeyDown );
this.FontChanged += new System.EventHandler( this.VersionInfoEx_FontChanged );
this.ResumeLayout( false );
}
#endregion
public void ApplyLanguage() {
string about = string.Format( _( "About {0}" ), m_app_name );
string credit = _( "Credit" );
Size size1 = Misc.MeasureString( about, btnFlip.Font );
Size size2 = Misc.MeasureString( credit, btnFlip.Font );
m_button_width_about = Math.Max( 75, (int)(size1.Width * 1.3) );
m_button_width_credit = Math.Max( 75, (int)(size2.Width * 1.3) );
if( m_credit_mode ) {
btnFlip.Width = m_button_width_about;
btnFlip.Text = about;
} else {
btnFlip.Width = m_button_width_credit;
btnFlip.Text = credit;
}
this.Text = about;
}
private System.Windows.Forms.Button btnFlip;
private System.Windows.Forms.Button btnOK;
private System.Windows.Forms.Timer timer;
private System.Windows.Forms.Button btnSaveAuthorList;
}
}

View File

@ -0,0 +1,262 @@
/*
* VersionInfo.cs
* Copyright (c) 2008-2009 kbinani
*
* This file is part of Boare.Lib.AppUtil.
*
* Boare.Lib.AppUtil is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* Boare.Lib.AppUtil 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.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace Boare.Lib.AppUtil {
public partial class VersionInfo : Form {
DateTime m_scroll_started;
private AuthorListEntry[] m_credit;
const float m_speed = 35f;
string m_version;
bool m_credit_mode = false;
float m_last_t = 0f;
float m_last_speed = 0f;
float m_shift = 0f;
int m_button_width_about = 75;
int m_button_width_credit = 75;
Bitmap m_scroll;
const int m_height = 380;
readonly Color m_background = Color.White;
private string m_app_name = "";
private Color m_app_name_color = Color.Black;
private Color m_version_color = Color.FromArgb( 105, 105, 105 );
private bool m_shadow_enablde = true;
public VersionInfo( string app_name, string version ) {
m_version = version;
m_app_name = app_name;
InitializeComponent();
ApplyLanguage();
this.SetStyle( ControlStyles.DoubleBuffer, true );
this.SetStyle( ControlStyles.UserPaint, true );
this.SetStyle( ControlStyles.AllPaintingInWmPaint, true );
m_credit = new AuthorListEntry[] { };
btnSaveAuthorList.Visible = false;
#if DEBUG
GenerateAuthorList();
btnSaveAuthorList.Visible = true;
btnSaveAuthorList.Click += new EventHandler( btnSaveAuthorList_Click );
#endif
}
public bool SaveAuthorListVisible {
set {
btnSaveAuthorList.Visible = value;
}
}
public static string _( string s ) {
return Messaging.GetMessage( s );
}
/// <summary>
/// バージョン番号表示の文字色を取得または設定します
/// </summary>
public Color VersionColor {
get {
return m_version_color;
}
set {
m_version_color = value;
}
}
/// <summary>
/// アプリケーション名表示の文字色を取得または設定します
/// </summary>
public Color AppNameColor {
get {
return m_app_name_color;
}
set {
m_app_name_color = value;
}
}
public Bitmap Credit {
set {
m_scroll = value;
}
}
public string AppName {
get {
return m_app_name;
}
set {
m_app_name = value;
}
}
public AuthorListEntry[] AuthorList {
set {
m_credit = value;
#if DEBUG
GenerateAuthorList();
#endif
}
}
private void GenerateAuthorList() {
const float shadow_shift = 2f;
const string font_name = "Arial";
const int font_size = 10;
Font font = new Font( font_name, font_size );
Size size = Boare.Lib.AppUtil.Misc.MeasureString( "Qjqp", font );
float width = this.Width;
float height = size.Height;
StringFormat sf = new StringFormat();
m_scroll = new Bitmap( (int)width, (int)(40f + m_credit.Length * height * 1.1f) );
using ( Graphics g = Graphics.FromImage( m_scroll ) ) {
sf.Alignment = StringAlignment.Center;
if ( m_shadow_enablde ) {
g.DrawString( m_app_name,
new Font( font_name, (int)(font_size * 1.1f), FontStyle.Bold ),
new SolidBrush( Color.FromArgb( 40, Color.Black ) ),
new RectangleF( shadow_shift, shadow_shift, width, height ),
sf );
}
g.DrawString( m_app_name,
new Font( font_name, (int)(font_size * 1.1f), FontStyle.Bold ),
Brushes.Black,
new RectangleF( 0f, 0f, width, height ),
sf );
for ( int i = 0; i < m_credit.Length; i++ ) {
if ( m_shadow_enablde ) {
g.DrawString( m_credit[i].Name,
new Font( font_name, font_size, m_credit[i].Style ),
new SolidBrush( Color.FromArgb( 40, Color.Black ) ),
new RectangleF( 0f + shadow_shift, 40f + i * height * 1.1f + shadow_shift, width, height ),
sf );
}
g.DrawString( m_credit[i].Name,
new Font( font_name, font_size, m_credit[i].Style ),
Brushes.Black,
new RectangleF( 0f, 40f + i * height * 1.1f, width, height ),
sf );
}
}
}
void btnSaveAuthorList_Click( object sender, EventArgs e ) {
#if DEBUG
using ( SaveFileDialog dlg = new SaveFileDialog() ){
if( dlg.ShowDialog() == DialogResult.OK ){
m_scroll.Save( dlg.FileName, System.Drawing.Imaging.ImageFormat.Png );
}
}
#endif
}
private void btnOK_Click( object sender, EventArgs e ) {
this.DialogResult = DialogResult.OK;
this.Close();
}
private void btnFlip_Click( object sender, EventArgs e ) {
m_credit_mode = !m_credit_mode;
if ( m_credit_mode ) {
btnFlip.Width = m_button_width_about;
btnFlip.Text = string.Format( _( "About {0}" ), m_app_name );
m_scroll_started = DateTime.Now;
m_last_speed = 0f;
m_last_t = 0f;
m_shift = 0f;
timer.Enabled = true;
} else {
timer.Enabled = false;
btnFlip.Width = m_button_width_credit;
btnFlip.Text = _( "Credit" );
}
this.Invalidate();
}
private void timer_Tick( object sender, EventArgs e ) {
this.Invalidate();
}
private void VersionInfoEx_Paint( object sender, PaintEventArgs e ) {
try {
Graphics g = e.Graphics;
g.Clip = new Region( new Rectangle( 0, 0, this.Width, m_height ) );
g.Clear( m_background );
if ( m_credit_mode ) {
float times = (float)(((DateTime.Now).Subtract( m_scroll_started )).TotalSeconds) - 3f;
float speed = (float)((2.0 - bocoree.math.erfcc( times * 0.8 )) / 2.0) * m_speed;
float dt = times - m_last_t;
m_shift += (speed + m_last_speed) * dt / 2f;
m_last_t = times;
m_last_speed = speed;
float dx = (this.Width - m_scroll.Width) * 0.5f;
if ( m_scroll != null ) {
g.DrawImage( m_scroll,
dx, 90f - m_shift,
m_scroll.Width, m_scroll.Height );
if ( 90f - m_shift + m_scroll.Height < 0 ) {
m_shift = -m_height * 1.5f;
}
}
int grad_height = 60;
Rectangle top = new Rectangle( 0, 0, this.Width, grad_height );
using ( LinearGradientBrush lgb = new LinearGradientBrush( top, Color.White, Color.Transparent, LinearGradientMode.Vertical ) ) {
g.FillRectangle( lgb, top );
}
Rectangle bottom = new Rectangle( 0, m_height - grad_height, this.Width, grad_height );
g.Clip = new Region( new Rectangle( 0, m_height - grad_height + 1, this.Width, grad_height - 1 ) );
using ( LinearGradientBrush lgb = new LinearGradientBrush( bottom, Color.Transparent, Color.White, LinearGradientMode.Vertical ) ) {
g.FillRectangle( lgb, bottom );
}
g.ResetClip();
} else {
g.DrawString(
m_app_name,
new Font( "Century Gorhic", 24, FontStyle.Bold ),
new SolidBrush( m_app_name_color ),
new PointF( 20, 110 ) );
g.DrawString(
"version " + m_version,
new Font( "Arial", 10 ),
new SolidBrush( m_version_color ),
new PointF( 25, 150 ) );
}
} catch ( Exception ex ) {
#if DEBUG
Console.WriteLine( "VersionInfoEx_Paint" );
Console.WriteLine( ex.StackTrace );
#endif
}
}
private void VersionInfoEx_KeyDown( object sender, KeyEventArgs e ) {
if ( (e.KeyCode & Keys.Escape) == Keys.Escape ) {
this.DialogResult = DialogResult.Cancel;
this.Close();
}
}
private void VersionInfoEx_FontChanged( object sender, EventArgs e ) {
Font font = this.Font;
for ( int i = 0; i < this.Controls.Count; i++ ) {
Misc.ApplyFontRecurse( this.Controls[i], font );
}
}
}
}

View File

@ -0,0 +1,215 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Reflection;
using System.IO;
namespace Boare.Lib.AppUtil {
/// <summary>
/// フィールド、またはプロパティの概要を格納するattribute
/// </summary>
[AttributeUsage( AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false )]
public class XmlItemDescription : Attribute {
private string m_value = "";
private string m_attribute_name = "description";
public XmlItemDescription( string Value ) {
m_value = Value;
}
public XmlItemDescription( string AttributeName, string Value ) {
m_value = Value;
m_attribute_name = AttributeName;
}
public string AttributeName {
get {
return m_attribute_name;
}
}
public string Value {
get {
return m_value;
}
}
}
/// <summary>
/// フィールドおよびプロパティを、XmlItemDescription属性の文字列を付加しながらXmlシリアライズする
/// </summary>
public class XmlSerializeWithDescription {
[XmlItemDescription( "mio" )]
private string foo;
private XmlTextWriter m_writer;
private Type m_type;
public XmlSerializeWithDescription() {
}
public void Serialize( Stream stream, object obj ) {
m_writer = new XmlTextWriter( stream, null );
m_writer.Formatting = Formatting.Indented;
m_writer.Indentation = 4;
m_writer.IndentChar = ' ';
m_writer.WriteStartDocument();
m_writer.WriteStartElement( obj.GetType().Name );
PrintItemRecurse( obj );
m_writer.WriteEndElement();
m_writer.WriteEndDocument();
m_writer.Flush();
}
private void PrintItemRecurse( object obj ) {
Type t = obj.GetType();
if ( !TryWriteValueType( obj ) ){
if ( t.IsGenericType ) {
List<int> f = new List<int>();
Type list_type = f.GetType().GetGenericTypeDefinition();
#if DEBUG
Console.WriteLine( "t.GetGenericTypeDefinition().Equals( list_type )=" + t.GetGenericTypeDefinition().Equals( list_type ) );
#endif
if ( t.GetGenericTypeDefinition().Equals( list_type ) ) {
Type[] gen = t.GetGenericArguments();
#if DEBUG
Console.WriteLine( "gen.Length=" + gen.Length );
#endif
if ( gen.Length == 1 ) {
PropertyInfo count_property = t.GetProperty( "Count", typeof( int ) );
int count = (int)count_property.GetValue( obj, new object[] { } );
#if DEBUG
Console.WriteLine( "count=" + count );
Console.WriteLine( "Properties" );
foreach ( PropertyInfo pi in t.GetProperties() ) {
Console.WriteLine( " " + pi );
}
Console.WriteLine( "Methods" );
foreach ( MethodInfo mi in t.GetMethods() ) {
Console.WriteLine( " " + mi );
}
#endif
Type returntype = gen[0];
MethodInfo indexer = t.GetMethod( "get_Item", new Type[] { typeof( int ) } );
string name = "";
if ( returntype.Equals( typeof( Boolean ) ) ) {
name = "boolean";
} else if ( returntype.Equals( typeof( DateTime ) ) ) {
name = "dateTime";
} else if ( returntype.Equals( typeof( Decimal ) ) ) {
name = "decimal";
} else if ( returntype.Equals( typeof( Double ) ) ) {
name = "double";
} else if ( returntype.Equals( typeof( Int32 ) ) ) {
name = "int";
} else if ( returntype.Equals( typeof( Int64 ) ) ) {
name = "long";
} else if ( returntype.Equals( typeof( Single ) ) ) {
name = "float";
} else if ( returntype.Equals( typeof( String ) ) ) {
name = "string";
} else if ( returntype.IsEnum ) {
name = returntype.Name;
}
if ( indexer != null && name != "" ) {
for ( int i = 0; i < count; i++ ) {
object value = indexer.Invoke( obj, new object[] { i } );
m_writer.WriteStartElement( name );
TryWriteValueType( value );
m_writer.WriteEndElement();
}
}
}
}
} else {
foreach ( FieldInfo fi in t.GetFields() ) {
if ( fi.IsPrivate || fi.IsStatic ) {
continue;
}
object[] attr = fi.GetCustomAttributes( typeof( XmlItemDescription ), false );
XmlItemDescription xid = null;
if ( attr.Length > 0 ) {
xid = (XmlItemDescription)attr[0];
}
WriteContents( fi.Name, fi.GetValue( obj ), xid );
#if DEBUG
m_writer.Flush();
#endif
}
foreach ( PropertyInfo pi in t.GetProperties() ) {
if ( !pi.CanRead | !pi.CanWrite ) {
continue;
}
if ( !pi.GetSetMethod().IsPublic | !pi.GetGetMethod().IsPublic ) {
continue;
}
if ( pi.GetSetMethod().IsStatic | pi.GetGetMethod().IsStatic ) {
continue;
}
object[] attr = pi.GetCustomAttributes( typeof( XmlItemDescription ), false );
XmlItemDescription xid = null;
if ( attr.Length > 0 ) {
xid = (XmlItemDescription)attr[0];
}
WriteContents( pi.Name, pi.GetValue( obj, new object[] { } ), xid );
#if DEBUG
m_writer.Flush();
#endif
}
}
}
}
private bool TryWriteValueType( object obj ) {
Type t = obj.GetType();
if ( t.Equals( typeof( Boolean ) ) ) {
m_writer.WriteValue( (Boolean)obj );
return true;
} else if ( t.Equals( typeof( DateTime ) ) ) {
m_writer.WriteValue( (DateTime)obj );
return true;
} else if ( t.Equals( typeof( Decimal ) ) ) {
m_writer.WriteValue( (Decimal)obj );
return true;
} else if ( t.Equals( typeof( Double ) ) ) {
m_writer.WriteValue( (Double)obj );
return true;
} else if ( t.Equals( typeof( Int32 ) ) ) {
m_writer.WriteValue( (Int32)obj );
return true;
} else if ( t.Equals( typeof( Int64 ) ) ) {
m_writer.WriteValue( (Int64)obj );
return true;
} else if ( t.Equals( typeof( Single ) ) ) {
m_writer.WriteValue( (Single)obj );
return true;
} else if ( t.Equals( typeof( String ) ) ) {
m_writer.WriteString( (String)obj );
return true;
} else if ( t.IsEnum ) {
string val = Enum.GetName( t, obj );
m_writer.WriteString( val );
return true;
} else {
return false;
}
}
private void WriteContents( string name, object next_obj, XmlItemDescription xid ) {
m_writer.WriteStartElement( name );
if ( xid != null ) {
m_writer.WriteAttributeString( xid.AttributeName, xid.Value );
}
PrintItemRecurse( next_obj );
m_writer.WriteEndElement();
}
private void test() {
System.Xml.Serialization.XmlSerializer xs = new System.Xml.Serialization.XmlSerializer( typeof( int ) );
}
}
}

View File

@ -0,0 +1,209 @@
/*
* XmlStaticMemberSerializer.cs
* Copyright (c) 2009 kbinani
*
* This file is part of Boare.Lib.AppUtil.
*
* Boare.Lib.AppUtil is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* Boare.Lib.AppUtil 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.CodeDom.Compiler;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Xml.Serialization;
using Microsoft.CSharp;
namespace Boare.Lib.AppUtil {
/// <summary>
/// クラスのstaticメンバーのxmlシリアライズ/デシリアライズを行うclass
/// </summary>
public class XmlStaticMemberSerializer {
/// <summary>
/// ターゲットとなるクラスから,シリアライズするメンバーを抽出する時に使用
/// </summary>
private class MemberEntry {
/// <summary>
/// プロパティ/フィールドの名前
/// </summary>
public string Name;
/// <summary>
/// プロパティ/フィールドの型
/// </summary>
public Type Type;
/// <summary>
/// プロパティ/フィールドのデフォルト値
/// </summary>
public object Default;
public MemberEntry( string name, Type type, object default_ ) {
Name = name;
Type = type;
Default = default_;
}
}
/// <summary>
/// シリアライズする対象の型staticメンバーだけなのでインスタンスではなく型を保持
/// </summary>
private Type m_item;
/// <summary>
/// シリアライズ/デシリアライズするための内部型
/// </summary>
private Type m_config_type = null;
/// <summary>
/// m_config_typeで初期化されたシリアライザ
/// </summary>
private XmlSerializer m_xs = null;
private XmlStaticMemberSerializer() {
}
/// <summary>
/// 指定された型をシリアライズするための初期化を行います
/// </summary>
/// <param name="item"></param>
public XmlStaticMemberSerializer( Type item ) {
m_item = item;
}
/// <summary>
/// シリアライズを行い,ストリームに書き込みます
/// </summary>
/// <param name="stream"></param>
public void Serialize( Stream stream ) {
if ( m_config_type == null ) {
GenerateConfigType();
}
ConstructorInfo ci = m_config_type.GetConstructor( new Type[]{} );
object config = ci.Invoke( new object[]{} );
foreach ( FieldInfo target in m_config_type.GetFields() ) {
foreach ( PropertyInfo pi in m_item.GetProperties( BindingFlags.Public | BindingFlags.Static ) ) {
if ( target.Name == pi.Name && target.FieldType.Equals( pi.PropertyType ) && pi.CanRead && pi.CanWrite ) {
target.SetValue( config, pi.GetValue( m_item, new object[] { } ) );
break;
}
}
foreach ( FieldInfo fi in m_item.GetFields( BindingFlags.Public | BindingFlags.Static ) ) {
if ( target.Name == fi.Name && target.FieldType.Equals( fi.FieldType ) ) {
target.SetValue( config, fi.GetValue( m_item ) );
break;
}
}
}
m_xs.Serialize( stream, config );
}
/// <summary>
/// 指定したストリームを使って,デシリアライズを行います
/// </summary>
/// <param name="stream"></param>
public void Deserialize( Stream stream ) {
if ( m_config_type == null ) {
GenerateConfigType();
}
object config = m_xs.Deserialize( stream );
if ( config == null ) {
throw new ApplicationException( "failed serializing internal config object" );
}
foreach ( FieldInfo target in m_config_type.GetFields() ) {
foreach ( PropertyInfo pi in m_item.GetProperties( BindingFlags.Public | BindingFlags.Static ) ) {
if ( target.Name == pi.Name && target.FieldType.Equals( pi.PropertyType ) && pi.CanRead && pi.CanWrite ) {
pi.SetValue( m_item, target.GetValue( config ), new object[] { } );
break;
}
}
foreach ( FieldInfo fi in m_item.GetFields( BindingFlags.Public | BindingFlags.Static ) ) {
if ( target.Name == fi.Name && target.FieldType.Equals( fi.FieldType ) ) {
fi.SetValue( m_item, target.GetValue( config ) );
break;
}
}
}
}
/// <summary>
/// シリアライズ用の内部型をコンパイルしm_xsが使用できるようにします
/// </summary>
private void GenerateConfigType() {
List<MemberEntry> config_names = CollectScriptConfigEntries( m_item );
string code = GenerateClassCodeForXmlSerialization( config_names, m_item );
CSharpCodeProvider provider = new CSharpCodeProvider();
CompilerParameters parameters = new CompilerParameters();
parameters.ReferencedAssemblies.Add( "System.Windows.Forms.dll" );
parameters.ReferencedAssemblies.Add( "System.dll" );
parameters.ReferencedAssemblies.Add( "System.Drawing.dll" );
parameters.ReferencedAssemblies.Add( "System.Xml.dll" );
parameters.GenerateInMemory = true;
parameters.GenerateExecutable = false;
parameters.IncludeDebugInformation = true;
CompilerResults results = provider.CompileAssemblyFromSource( parameters, code );
Assembly asm = results.CompiledAssembly;
if ( asm.GetTypes().Length <= 0 ) {
m_config_type = null;
m_xs = null;
throw new ApplicationException( "failed generating internal xml serizlizer" );
} else {
m_config_type = (asm.GetTypes())[0];
m_xs = new XmlSerializer( m_config_type );
}
}
/// <summary>
/// 設定ファイルから読込むための型情報を蒐集
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
private static List<MemberEntry> CollectScriptConfigEntries( Type item ) {
List<MemberEntry> config_names = new List<MemberEntry>();
foreach ( PropertyInfo pi in item.GetProperties( BindingFlags.Static | BindingFlags.Public ) ) {
object[] attrs = pi.GetCustomAttributes( true );
foreach ( object obj in attrs ) {
if ( obj.GetType().Equals( typeof( System.Xml.Serialization.XmlIgnoreAttribute ) ) ) {
continue;
}
}
if ( pi.CanRead && pi.CanWrite ) {
config_names.Add( new MemberEntry( pi.Name, pi.PropertyType, pi.GetValue( item, new object[] { } ) ) );
}
}
foreach ( FieldInfo fi in item.GetFields( BindingFlags.Static | BindingFlags.Public ) ) {
object[] attrs = fi.GetCustomAttributes( true );
foreach ( object obj in attrs ) {
if ( obj.GetType().Equals( typeof( System.Xml.Serialization.XmlIgnoreAttribute ) ) ) {
continue;
}
}
config_names.Add( new MemberEntry( fi.Name, fi.FieldType, fi.GetValue( item ) ) );
}
return config_names;
}
/// <summary>
/// 指定した型から、Reflectionを使ってxmlシリアライズ用のクラスをコンパイルするためのC#コードを作成します
/// </summary>
/// <param name="implemented"></param>
/// <returns></returns>
private static string GenerateClassCodeForXmlSerialization( List<MemberEntry> config_names, Type item ) {
// XmlSerialization用の型を作成
string code = "";
code += "using System;\n";
code += "namespace Boare.Lib.AppUtil{\n";
code += " public class StaticMembersOf" + item.Name + "{\n";
foreach ( MemberEntry entry in config_names ) {
code += " public " + entry.Type.ToString() + " " + entry.Name + ";\n";
}
code += " }\n";
code += "}\n";
return code;
}
}
}

View File

@ -0,0 +1,17 @@
OPT=
CP=cp
RM=rm
Boare.Lib.AppUtil.dll: *.cs bocoree.dll
gmcs $(OPT) -recurse:*.cs -unsafe+ -target:library -out:Boare.Lib.AppUtil.dll \
-r:bocoree.dll,System.Drawing,System.Windows.Forms
bocoree.dll: ../bocoree/bocoree.dll
cp ../bocoree/bocoree.dll bocoree.dll
../bocoree/bocoree.dll:
cd ../bocoree/ && $(MAKE) OPT=$(OPT)
clean:
$(RM) Boare.Lib.AppUtil.dll
$(RM) bocoree.dll

View File

@ -0,0 +1,359 @@
/*
* AviReader.cs
* Copyright (c) 2007-2009 kbinani
*
* This file is part of Boare.Lib.Media.
*
* Boare.Lib.Media is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* Boare.Lib.Media 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.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.IO;
using System.Windows.Forms;
using bocoree;
namespace Boare.Lib.Media {
/// <summary>
/// Extract bitmaps from AVI files
/// </summary>
public class AviReader {
private int firstFrame = 0, countFrames = 0;
private int aviFile = 0;
private int getFrameObject;
private IntPtr aviStream;
private bool m_opened = false;
private AVISTREAMINFOW streamInfo;
private string m_fileName = "";
public string FileName {
get {
return m_fileName;
}
}
public int CountFrames {
get {
return countFrames;
}
}
public uint dwRate {
get {
return streamInfo.dwRate;
}
}
public uint dwScale {
get {
return streamInfo.dwScale;
}
}
[Obsolete]
public float FrameRate {
get {
return (float)streamInfo.dwRate / (float)streamInfo.dwScale;
}
}
public Size BitmapSize {
get {
return new Size( (int)streamInfo.rect_right, (int)streamInfo.rect_bottom );
}
}
/// <summary>
/// Opens an AVI file and creates a GetFrame object
/// </summary>
/// <param name="fileName">Name of the AVI file</param>
public void Open( string fileName ) {
//Intitialize AVI library
VFW.AVIFileInit();
//Open the file
int result = VFW.AVIFileOpenW(
ref aviFile, fileName,
(int)windows.OF_SHARE_DENY_WRITE, 0 );
if ( result != 0 ) {
throw new Exception( "Exception in AVIFileOpen: " + result.ToString() );
}
//Get the video stream
result = VFW.AVIFileGetStream(
aviFile,
out aviStream,
(int)VFW.streamtypeVIDEO, 0 );
if ( result != 0 ) {
throw new Exception( "Exception in AVIFileGetStream: " + result.ToString() );
}
firstFrame = VFW.AVIStreamStart( aviStream.ToInt32() );
countFrames = VFW.AVIStreamLength( aviStream.ToInt32() );
streamInfo = new AVISTREAMINFOW();
result = VFW.AVIStreamInfo( aviStream.ToInt32(), ref streamInfo, Marshal.SizeOf( streamInfo ) );
if ( result != 0 ) {
throw new Exception( "Exception in AVIStreamInfo: " + result.ToString() );
}
//Open frames
BITMAPINFOHEADER bih = new BITMAPINFOHEADER();
bih.biBitCount = 24;
bih.biClrImportant = 0;
bih.biClrUsed = 0;
bih.biCompression = 0; //BI_RGB;
bih.biHeight = (Int32)streamInfo.rect_bottom;
bih.biWidth = (Int32)streamInfo.rect_right;
bih.biPlanes = 1;
bih.biSize = (UInt32)Marshal.SizeOf( bih );
bih.biXPelsPerMeter = 0;
bih.biYPelsPerMeter = 0;
getFrameObject = VFW.AVIStreamGetFrameOpen( aviStream, ref bih ); //force function to return 24bit DIBS
//getFrameObject = Avi.AVIStreamGetFrameOpen(aviStream, 0); //return any bitmaps
if ( getFrameObject == 0 ) {
throw new Exception( "Exception in AVIStreamGetFrameOpen!" );
}
m_opened = true;
m_fileName = fileName;
}
/// <summary>Closes all streams, files and libraries</summary>
public void Close() {
if ( getFrameObject != 0 ) {
VFW.AVIStreamGetFrameClose( getFrameObject );
getFrameObject = 0;
}
if ( aviStream != IntPtr.Zero ) {
VFW.AVIStreamRelease( aviStream );
aviStream = IntPtr.Zero;
}
if ( aviFile != 0 ) {
VFW.AVIFileRelease( aviFile );
aviFile = 0;
}
VFW.AVIFileExit();
m_opened = false;
m_fileName = "";
}
private void dispTime( string message, DateTime start ) {
DateTime current = DateTime.Now;
TimeSpan ts = current.Subtract( start );
System.Diagnostics.Debug.WriteLine( message + "; " + ts.TotalSeconds + "s" );
}
public bool Opened {
get {
return m_opened;
}
}
public void ExportToArray( int position, out byte[] bitmapData, out int width, out int height, out int bit_count ) {
if ( position > countFrames ) {
throw new Exception( "Invalid frame position" );
}
//Decompress the frame and return a pointer to the DIB
int pDib = VFW.AVIStreamGetFrame( getFrameObject, firstFrame + position );
//Copy the bitmap header into a managed struct
BITMAPINFOHEADER bih = new BITMAPINFOHEADER();
bih = (BITMAPINFOHEADER)Marshal.PtrToStructure( new IntPtr( pDib ), bih.GetType() );
if ( bih.biSizeImage < 1 ) {
throw new Exception( "Exception in AVIStreamGetFrame: Not bitmap decompressed." );
}
//Copy the image
bitmapData = new byte[bih.biSizeImage];
int address = pDib + Marshal.SizeOf( bih );
Marshal.Copy( new IntPtr( address ), bitmapData, 0, bitmapData.Length );
width = bih.biWidth;
height = bih.biHeight;
bit_count = bih.biBitCount;
}
public Bitmap Export( int position ) {
if ( position > countFrames ) {
throw new Exception( "Invalid frame position" );
}
//Decompress the frame and return a pointer to the DIB
int pDib = VFW.AVIStreamGetFrame( getFrameObject, firstFrame + position );
if ( pDib == 0 ) {
//throw new Exception( "AVIStreamGetFrame; failed" );
return null;
}
//Copy the bitmap header into a managed struct
BITMAPINFOHEADER bih = new BITMAPINFOHEADER();
bih = (BITMAPINFOHEADER)Marshal.PtrToStructure( new IntPtr( pDib ), bih.GetType() );
if ( bih.biSizeImage < 1 ) {
throw new Exception( "Exception in AVIStreamGetFrame: Not bitmap decompressed." );
}
Bitmap result = new Bitmap( bih.biWidth, bih.biHeight );
BitmapData dat = result.LockBits(
new Rectangle( 0, 0, bih.biWidth, bih.biHeight ),
ImageLockMode.ReadWrite,
PixelFormat.Format24bppRgb );
//Copy the image
int address = pDib + Marshal.SizeOf( bih );
int length = dat.Stride * dat.Height;
byte[] target = new byte[length];
Marshal.Copy( new IntPtr( address ), target, 0, length );
Marshal.Copy( target, 0, dat.Scan0, length );
result.UnlockBits( dat );
result.RotateFlip( RotateFlipType.RotateNoneFlipY );
return result;
}
public unsafe void ExportEx( Bitmap bmp, int position ) {
if ( position > countFrames ) {
throw new Exception( "Invalid frame position" );
}
//Decompress the frame and return a pointer to the DIB
int pDib = VFW.AVIStreamGetFrame( getFrameObject, firstFrame + position );
if ( pDib == 0 ) {
//throw new Exception( "AVIStreamGetFrame; failed" );
return;
}
//Copy the bitmap header into a managed struct
BITMAPINFOHEADER bih = new BITMAPINFOHEADER();
bih = (BITMAPINFOHEADER)Marshal.PtrToStructure( new IntPtr( pDib ), bih.GetType() );
if ( bih.biSizeImage < 1 ) {
throw new Exception( "Exception in AVIStreamGetFrame: Not bitmap decompressed." );
}
BitmapData dat = bmp.LockBits(
new Rectangle( 0, 0, bih.biWidth, bih.biHeight ),
ImageLockMode.ReadWrite,
PixelFormat.Format24bppRgb );
//Copy the image
int address = pDib + Marshal.SizeOf( bih );
int length = dat.Stride * dat.Height;
CopyMemory( dat.Scan0, new IntPtr( address ), length );
//Marshal.Copy( new IntPtr( address ), target, 0, length );
//Marshal.Copy( target, 0, dat.Scan0, length );
bmp.UnlockBits( dat );
bmp.RotateFlip( RotateFlipType.RotateNoneFlipY );
}
[DllImport( "kernel32.dll" )]
private static extern void CopyMemory(
IntPtr destination, IntPtr source, int length );
public unsafe void Export( Bitmap bmp, int position ) {
if ( position > countFrames ) {
throw new Exception( "Invalid frame position" );
}
//Decompress the frame and return a pointer to the DIB
int pDib = VFW.AVIStreamGetFrame( getFrameObject, firstFrame + position );
if ( pDib == 0 ) {
//throw new Exception( "AVIStreamGetFrame; failed" );
return;
}
//Copy the bitmap header into a managed struct
BITMAPINFOHEADER bih = new BITMAPINFOHEADER();
bih = (BITMAPINFOHEADER)Marshal.PtrToStructure( new IntPtr( pDib ), bih.GetType() );
if ( bih.biSizeImage < 1 ) {
throw new Exception( "Exception in AVIStreamGetFrame: Not bitmap decompressed." );
}
BitmapData dat = bmp.LockBits(
new Rectangle( 0, 0, bih.biWidth, bih.biHeight ),
ImageLockMode.WriteOnly,
bmp.PixelFormat );
//Copy the image
int address = pDib + Marshal.SizeOf( bih );
int length = dat.Stride * dat.Height;
byte[] target = new byte[length];
Marshal.Copy( new IntPtr( address ), target, 0, length );
Marshal.Copy( target, 0, dat.Scan0, length );
bmp.UnlockBits( dat );
bmp.RotateFlip( RotateFlipType.RotateNoneFlipY );
}
/// <summary>Exports a frame into a bitmap file</summary>
/// <param name="position">Position of the frame</param>
/// <param name="dstFileName">Name ofthe file to store the bitmap</param>
public void ExportBitmap( int position, String dstFileName ) {
if ( position > countFrames ) {
throw new Exception( "Invalid frame position" );
}
//Decompress the frame and return a pointer to the DIB
int pDib = VFW.AVIStreamGetFrame( getFrameObject, firstFrame + position );
//Copy the bitmap header into a managed struct
BITMAPINFOHEADER bih = new BITMAPINFOHEADER();
bih = (BITMAPINFOHEADER)Marshal.PtrToStructure( new IntPtr( pDib ), bih.GetType() );
/*if(bih.biBitCount < 24){
throw new Exception("Not enough colors! DIB color depth is less than 24 bit.");
}else */
if ( bih.biSizeImage < 1 ) {
throw new Exception( "Exception in AVIStreamGetFrame: Not bitmap decompressed." );
}
//Copy the image
byte[] bitmapData = new byte[bih.biSizeImage];
int address = pDib + Marshal.SizeOf( bih );
for ( int offset = 0; offset < bitmapData.Length; offset++ ) {
bitmapData[offset] = Marshal.ReadByte( new IntPtr( address ) );
address++;
}
//Copy bitmap info
byte[] bitmapInfo = new byte[Marshal.SizeOf( bih )];
IntPtr ptr;
ptr = Marshal.AllocHGlobal( bitmapInfo.Length );
Marshal.StructureToPtr( bih, ptr, false );
address = ptr.ToInt32();
for ( int offset = 0; offset < bitmapInfo.Length; offset++ ) {
bitmapInfo[offset] = Marshal.ReadByte( new IntPtr( address ) );
address++;
}
//Create file header
BITMAPFILEHEADER bfh = new BITMAPFILEHEADER();
bfh.bfType = Util.BMP_MAGIC_COOKIE;
bfh.bfSize = (Int32)(55 + bih.biSizeImage); //size of file as written to disk
bfh.bfReserved1 = 0;
bfh.bfReserved2 = 0;
bfh.bfOffBits = Marshal.SizeOf( bih ) + Marshal.SizeOf( bfh );
//Create or overwrite the destination file
FileStream fs = new FileStream( dstFileName, System.IO.FileMode.Create );
BinaryWriter bw = new BinaryWriter( fs );
//Write header
bw.Write( bfh.bfType );
bw.Write( bfh.bfSize );
bw.Write( bfh.bfReserved1 );
bw.Write( bfh.bfReserved2 );
bw.Write( bfh.bfOffBits );
//Write bitmap info
bw.Write( bitmapInfo );
//Write bitmap data
bw.Write( bitmapData );
bw.Close();
fs.Close();
}
}
}

View File

@ -0,0 +1,550 @@
/*
* AviWriter.cs
* Copyright (c) 2007-2009 kbinani
*
* This file is part of Boare.Lib.Media.
*
* Boare.Lib.Media is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* Boare.Lib.Media 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.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
using bocoree;
namespace Boare.Lib.Media {
public unsafe class AviWriterVcm : IAviWriter {
private const long _THRESHOLD = 1000000000L; //AVIXリストの最大サイズ(byte)
private MainAVIHeader m_main_header;
private AVIStreamHeader m_stream_header;
private BinaryWriter m_stream;
private int m_current_chunk = 0;
private long m_position_in_chunk = 0L;
private long m_split_sreshold = 160000000L; //AVIリストの最大サイズ(byte)
private AVISTDINDEX m_std_index;
private AVISUPERINDEX m_super_index;
private int m_linesize;//bitmapの1行分のデータサイズ(byte)
private bool m_is_first = true;
private long m_riff_position;//"RIFF*"の*が記入されているファイルの絶対位置。RIFF-AVI のときは必ず4。RIFF-AVIXの時は変化する
private long m_movi_position;
private long m_next_framedata_position;//次に00dbデータを記入するべき場所
private long m_avix_position;
private int m_junk_length;
private uint m_scale;
private uint m_rate;
private bool m_compressed = false;
private IntPtr m_hwnd = IntPtr.Zero;
private uint m_stream_fcc_handler = 808810089;
private string m_file;
//private int m_addr_compvar;
//private COMPVARS m_compvar;
private COMPVARS* m_compvar;
private BITMAPINFO* m_bitmapinfo_in;
private BITMAPINFO* m_bitmapinfo_out;
private IntPtr m_p_compvar;
private IntPtr m_p_bitmapinfo_in;
private IntPtr m_p_bitmapinfo_out;
private uint m_bih_compression = 0;
private long m_super_index_position;
private bool m_closed = false;
private bool m_opened = false;
private bool m_is_transparent = false;
/// <summary>
/// 現在記入中のmoviチャンクのサイズ
/// </summary>
private long m_this_movi_size = 0;
private static bool s_vfw_bug_compati = false;
public Size Size {
get {
return new Size( (int)m_main_header.dwWidth, (int)m_main_header.dwHeight );
}
}
public uint Scale {
get {
return m_scale;
}
}
public uint Rate {
get {
return m_rate;
}
}
/// <summary>
/// Video For Windows APIとバグコンパチブルな動作をするかどうかを表す値を取得または設定します
/// </summary>
public static bool VfwBugCompatible {
get {
return s_vfw_bug_compati;
}
set {
s_vfw_bug_compati = value;
}
}
internal float frameRate {
get {
return (float)m_rate / (float)m_scale;
}
}
/// <summary>
/// 指定したAVI_CONTAINER構造体にAVIファイルの情報を格納すると共に
/// ファイルにヘッダー情報を書き込みます.
/// </summary>
/// <param name="file">書き込み対象のファイル</param>
/// <param name="scale"></param>
/// <param name="rate"></param>
/// <param name="compressed"></param>
public unsafe bool Open( string file, uint scale, uint rate, int width, int height, bool compressed, bool transparent, IntPtr hWnd ) {
#if DEBUG
Console.WriteLine( "AviWriterEx.Open(string,uint,uint,bool,IntPtr)" );
#endif
m_stream = new BinaryWriter( new FileStream( file, FileMode.Create, FileAccess.Write ) );
float fps = (float)rate / (float)scale;
m_main_header.dwMicroSecPerFrame = (uint)(1.0e6 / fps);// ! 1秒は10^6μ秒
m_main_header.dwReserved1 = 0;
m_main_header.dwFlags = 2064;
m_main_header.dwInitialFrames = 0;
m_main_header.dwStreams = 0;
m_main_header.dwScale = scale;
m_main_header.dwRate = rate;
m_main_header.dwStart = 0;
m_main_header.dwLength = 0;
m_rate = rate;
m_scale = scale;
Util.fwrite( "RIFF", m_stream );
Util.WriteDWORD( 0, m_stream );
Util.fwrite( "AVI ", m_stream );
Util.fwrite( "LIST", m_stream );
Util.WriteDWORD( 0x9cc, m_stream );
Util.fwrite( "hdrl", m_stream );
m_current_chunk = 0;
m_position_in_chunk = 0L;
m_std_index = new AVISTDINDEX( 0L );
m_super_index = new AVISUPERINDEX( 0 );
m_riff_position = 0x4;
m_compressed = compressed;
m_is_transparent = transparent;
m_stream_fcc_handler = 0;
m_hwnd = hWnd;
m_file = file;
m_opened = true;
if ( m_is_first ) {
int stride = 0;
using ( Bitmap b = new Bitmap( width, height, m_is_transparent ? PixelFormat.Format32bppArgb : PixelFormat.Format24bppRgb ) ) {
BitmapData bd = b.LockBits( new Rectangle( 0, 0, width, height ),
ImageLockMode.ReadOnly,
b.PixelFormat );
stride = bd.Stride;
b.UnlockBits( bd );
}
m_is_first = false;
m_main_header.dwWidth = (uint)width;
m_main_header.dwHeight = (uint)height;
m_main_header.dwMaxBytesPerSec = (uint)(stride * height * frameRate);
m_main_header.dwStreams = 1;
m_main_header.dwSuggestedBufferSize = (uint)(stride * height);
m_linesize = stride;
m_stream_header.fccType = Util.mmioFOURCC( "vids" );
m_stream_header.fccHandler = 0;
m_stream_header.dwFlags = 0;
m_stream_header.dwReserved1 = 0;
m_stream_header.dwInitialFrames = 0;
m_stream_header.dwScale = m_scale;
m_stream_header.dwRate = m_rate;
m_stream_header.dwStart = 0;
m_stream_header.dwSuggestedBufferSize = m_main_header.dwSuggestedBufferSize;
m_stream_header.dwQuality = 0;
m_stream_header.dwSampleSize = 0;
Util.aviWriteMainHeader( m_main_header, m_stream );
Util.fwrite( "LIST", m_stream );
Util.WriteDWORD( 0x874, m_stream );
Util.fwrite( "strl", m_stream );
Util.aviWriteStreamHeader( m_stream_header, m_main_header, m_stream );
Util.fwrite( "strf", m_stream );
BITMAPINFOHEADER bih = new BITMAPINFOHEADER(); //(BITMAPINFOHEADER)Marshal.PtrToStructure( Marshal.AllocHGlobal( sizeof( BITMAPINFOHEADER ) ), typeof( BITMAPINFOHEADER ) );
bih.biSize = (uint)(Marshal.SizeOf( bih ));
bih.biWidth = width;
bih.biHeight = height;
bih.biPlanes = 1;
bih.biBitCount = m_is_transparent ? (short)32 : (short)24;
bih.biCompression = 0;//BI_RGB
bih.biSizeImage = (uint)(stride * height);
bih.biXPelsPerMeter = 0;
bih.biYPelsPerMeter = 0;
bih.biClrUsed = 0;
bih.biClrImportant = 0;
if ( m_compressed ) {
m_p_compvar = Marshal.AllocHGlobal( sizeof( COMPVARS ) );
m_compvar = (COMPVARS*)m_p_compvar.ToPointer();
byte[] buf = new byte[sizeof( COMPVARS )];
for ( int i = 0; i < buf.Length; i++ ) {
buf[i] = 0x0;
}
Marshal.Copy( buf, 0, m_p_compvar, buf.Length );
m_compvar->cbSize = sizeof( COMPVARS );
int ret = VCM.ICCompressorChoose( m_hwnd, 0, IntPtr.Zero, IntPtr.Zero, m_compvar, "Select Video Compressor" );
if ( ret == 0 ) {
m_opened = false;
Marshal.FreeHGlobal( m_p_compvar );
m_stream.Close();
return false;
}
if ( m_compvar->hic != 0 ) {
m_p_bitmapinfo_in = Marshal.AllocHGlobal( sizeof( BITMAPINFO ) );
m_bitmapinfo_in = (BITMAPINFO*)m_p_bitmapinfo_in.ToPointer();
buf = new byte[sizeof( BITMAPINFO )];
for ( int i = 0; i < buf.Length; i++ ) {
buf[i] = 0x0;
}
Marshal.Copy( buf, 0, m_p_bitmapinfo_in, buf.Length );
m_bitmapinfo_in->bmiHeader = bih;
uint dwSize = VCM.ICCompressGetFormatSize( m_compvar->hic, m_bitmapinfo_in );
#if DEBUG
Console.WriteLine( "m_compvar->hic=" + m_compvar->hic );
Console.WriteLine( "ICCompressGetFormatSize=" + dwSize );
#endif
m_p_bitmapinfo_out = Marshal.AllocHGlobal( (int)dwSize );
m_bitmapinfo_out = (BITMAPINFO*)m_p_bitmapinfo_out.ToPointer();
buf = new byte[dwSize];
for ( int i = 0; i < buf.Length; i++ ) {
buf[i] = 0x0;
}
Marshal.Copy( buf, 0, m_p_bitmapinfo_out, buf.Length );
VCM.ICCompressGetFormat( m_compvar->hic, m_bitmapinfo_in, m_bitmapinfo_out );
m_bih_compression = m_bitmapinfo_out->bmiHeader.biCompression;
#if DEBUG
Console.WriteLine( "AddFrame(Bitmap)" );
Console.WriteLine( " biout.biSize=" + m_bitmapinfo_out->bmiHeader.biSize );
#endif
VCM.ICSeqCompressFrameStart( m_compvar, m_bitmapinfo_in );
bih = m_bitmapinfo_out->bmiHeader;
Util.WriteDWORD( bih.biSize, m_stream );// infoHeaderのサイズ
m_bitmapinfo_out->Write( m_stream );
} else {
m_compressed = false;
Util.WriteDWORD( bih.biSize, m_stream );// infoHeaderのサイズ
bih.Write( m_stream );
}
} else {
Util.WriteDWORD( bih.biSize, m_stream );// infoHeaderのサイズ
bih.Write( m_stream );
}
m_super_index_position = m_stream.BaseStream.Position;
Util.fwrite( "indx", m_stream ); //fcc
Util.WriteDWORD( 0x7f8, m_stream ); // cb
Util.WriteWORD( (byte)0x4, m_stream ); // wLongsPerEntry
Util.WriteBYTE( 0x0, m_stream ); // bIndexSubType
Util.WriteBYTE( Util.AVI_INDEX_OF_INDEXES, m_stream );// bIndexType
Util.WriteDWORD( 0x0, m_stream ); // nEntriesInUse
Util.fwrite( "00db", m_stream ); // dwChunkId
Util.WriteDWORD( 0x0, m_stream );
Util.WriteDWORD( 0x0, m_stream );
Util.WriteDWORD( 0x0, m_stream );
for ( int ii = 1; ii <= 126; ii++ ) {
Util.WriteQWORD( 0x0, m_stream );
Util.WriteDWORD( 0x0, m_stream );
Util.WriteDWORD( 0x0, m_stream );
}
Util.fwrite( "LIST", m_stream );
Util.WriteDWORD( 0x104, m_stream );
Util.fwrite( "odml", m_stream );
Util.fwrite( "dmlh", m_stream );
Util.WriteDWORD( 0xf8, m_stream );
Util.WriteDWORD( 0x0, m_stream );//ここ後で更新するべき
for ( int ii = 1; ii <= 61; ii++ ) {
Util.WriteDWORD( 0x0, m_stream );
}
Util.fwrite( "JUNK", m_stream );
Util.WriteDWORD( 0x60c, m_stream );
Util.WriteDWORD( 0, m_stream );//"This"が将来登録されたらやばいので
string msg = "This file was generated by AviWriter@Boare.Lib.Media;VfwBugCompatible=" + VfwBugCompatible;
const int tlen = 1544;
int remain = tlen - msg.Length;
Util.fwrite( msg, m_stream );
for ( int i = 1; i <= remain; i++ ) {
m_stream.Write( (byte)0 );
}
m_junk_length = 0xff4;
Util.fwrite( "LIST", m_stream );
m_movi_position = m_stream.BaseStream.Position;
Util.WriteDWORD( 0, m_stream );// call bmpQWordWrite( 0, avi%fp ) !// ******************ココの数字は一番最後に書き換える必要あり20402043あとdwTotalFrames4851
Util.fwrite( "movi", m_stream );
m_next_framedata_position = m_stream.BaseStream.Position;
m_std_index.SetBaseOffset( (ulong)m_next_framedata_position );
m_super_index.nEntriesInUse++;
}
return true;
}
public bool Open( string file, uint scale, uint rate, int width, int height, IntPtr hwnd ) {
return Open( file, scale, rate, width, height, false, false, hwnd );
}
//todo: AVIMainHeader.dwTotalFramesに、ファイル全体のフレーム数を入れる仕様違反
//todo: AVIStreamHeader.dwLengthに、ファイル全体のフレーム数を入れる仕様違反
/// <summary>
/// 全てのインデックスを更新し、ファイルが(動画ファイルとして)使用できる状態にします
/// この関数を読んだあとでもさらにaviAddFrame関数を使うことでフレームを追加することが出来ます
/// </summary>
public void UpdateIndex() {
_avisuperindex_entry entry = m_super_index.aIndex[m_current_chunk];
entry.qwOffset = (ulong)m_stream.BaseStream.Position;
entry.dwSize = m_std_index.cb;
m_super_index.aIndex[m_current_chunk] = entry;
if ( m_stream.BaseStream.Position != m_next_framedata_position ) {
m_stream.BaseStream.Seek( m_next_framedata_position, SeekOrigin.Begin );
}
m_std_index.Write( m_stream );
int frames = (int)m_super_index.aIndex[m_current_chunk].dwDuration;
m_avix_position = m_stream.BaseStream.Position;
if ( m_current_chunk == 0 ) {
uint i, step, number;
step = m_main_header.dwSuggestedBufferSize + 8;
Util.fwrite( "idx1", m_stream );
Util.WriteDWORD( (uint)(16 * frames), m_stream );
for ( i = 1; i <= frames; i++ ) {
Util.fwrite( "00db", m_stream );
Util.WriteDWORD( Util.AVIF_HASINDEX, m_stream );
Util.WriteDWORD( (uint)(4 + (i - 1) * step), m_stream );
Util.WriteDWORD( m_main_header.dwSuggestedBufferSize, m_stream );
}
m_avix_position = m_stream.BaseStream.Position;
number = (uint)frames;
m_stream.Seek( 0x30, SeekOrigin.Begin );
Util.WriteDWORD( number, m_stream );
m_stream.Seek( 0x8c, SeekOrigin.Begin );
Util.WriteDWORD( number, m_stream );
//odml dlmhのdwTotalFrames
m_stream.Seek( 0x8e8, SeekOrigin.Begin );
Util.WriteDWORD( (uint)frames, m_stream );
// LIST****moviの****の数値を計算
number = 4;//"movi"
number += (uint)(m_this_movi_size + 8 * frames);// (uint)(frames * (m_linesize * m_main_header.dwHeight + 8));//フレーム数*(フレームのサイズ+"00db"+00dbチャンクのサイズ)
number += 4 + 4 + (uint)m_std_index.cb; //ix00のサイズ
m_stream.BaseStream.Seek( m_movi_position, SeekOrigin.Begin );
Util.WriteDWORD( number, m_stream );
//number = 4096 + (this.mainHeader.dwSuggestedBufferSize + 24) * this.noOfFrame;
//avi_writeIsolate( this.fp, number, 4 ); // RIFF****AVI の ****部分
number = (uint)m_junk_length/* 0xff4*/; //JUNKの終わりまでのサイズ。これは固定
number += 4;//"movi"
number += (uint)(m_this_movi_size + 8 * frames);//00db...の合計サイズ
number += 4 + 4 + (uint)m_std_index.cb;
number += (uint)(4 + 4 + 16 * frames);//idx1のサイズ
m_stream.BaseStream.Seek( m_riff_position, SeekOrigin.Begin );
Util.WriteDWORD( number, m_stream );
UpdateIndexOfIndex();
} else {
// LIST****moviの****を更新
uint number = 4;
number += (uint)(m_this_movi_size + frames * 8);
number += 8 + (uint)m_std_index.cb;
m_stream.BaseStream.Seek( m_movi_position, SeekOrigin.Begin );
Util.WriteDWORD( number, m_stream );
// odml dlmhのdwTotalFrames
uint frames2 = 0;
for ( int j = 0; j <= m_current_chunk; j++ ) {
frames2 += (uint)m_super_index.aIndex[j].dwDuration;
}
m_stream.BaseStream.Seek( 0x8e8, SeekOrigin.Begin );
Util.WriteDWORD( frames2, m_stream );
m_stream.Seek( 48, SeekOrigin.Begin );
Util.WriteDWORD( frames2, m_stream );
m_stream.Seek( 140, SeekOrigin.Begin );
Util.WriteDWORD( frames2, m_stream );
//RIFF****AVIXの****を更新
long num2 = m_junk_length + number;
m_stream.BaseStream.Seek( m_riff_position, SeekOrigin.Begin );
Util.WriteDWORD( (uint)num2, m_stream );
UpdateIndexOfIndex();
}
}
/// <summary>
/// aviファイルを閉じます
/// </summary>
public unsafe void Close() {
UpdateIndex();
m_stream.Close();
if ( m_compressed ) {
m_stream_fcc_handler = m_compvar->fccHandler;
VCM.ICSeqCompressFrameEnd( m_compvar );
VCM.ICCompressorFree( m_compvar );
using ( FileStream fs = new FileStream( m_file, FileMode.Open ) ) {
fs.Seek( 0x70, SeekOrigin.Begin );
{
byte ch3 = (byte)(m_stream_fcc_handler >> 24);
uint b = (uint)(m_stream_fcc_handler - (ch3 << 24));
byte ch2 = (byte)(b >> 16);
b = (uint)(b - (ch2 << 16));
byte ch1 = (byte)(b >> 8);
byte ch0 = (byte)(b - (ch1 << 8));
fs.Write( new byte[] { ch0, ch1, ch2, ch3 }, 0, 4 );
}
fs.Seek( 0xbc, SeekOrigin.Begin );
{
byte ch3 = (byte)(m_bih_compression >> 24);
uint b = (uint)(m_bih_compression - (ch3 << 24));
byte ch2 = (byte)(b >> 16);
b = (uint)(b - (ch2 << 16));
byte ch1 = (byte)(b >> 8);
byte ch0 = (byte)(b - (ch1 << 8));
fs.Write( new byte[] { ch0, ch1, ch2, ch3 }, 0, 4 );
}
}
}
m_closed = true;
}
~AviWriterVcm() {
if ( m_opened && !m_closed ) {
Close();
}
}
/// <summary>
/// 最初の[AVI :AVI[LIST:hdrl[LIST:strl]]]に書き込まれているsuper indexチャンク[indx]を更新します
/// </summary>
private void UpdateIndexOfIndex() {
m_stream.Seek( (int)m_super_index_position, SeekOrigin.Begin );
m_super_index.Write( m_stream );
}
/// <summary>
/// aviファイルにフレームを1つ追加します
/// </summary>
/// <param name="bmp"></param>
public unsafe void AddFrame( Bitmap bmp ) {
int width, height, lineSize;
BitmapData bmpDat;
if ( m_is_transparent ) {
bmpDat = bmp.LockBits( new Rectangle( 0, 0, bmp.Width, bmp.Height ),
ImageLockMode.ReadOnly,
PixelFormat.Format32bppArgb );
} else {
bmpDat = bmp.LockBits( new Rectangle( 0, 0, (int)bmp.Width, (int)bmp.Height ),
ImageLockMode.ReadOnly,
PixelFormat.Format24bppRgb );
}
if ( m_next_framedata_position != m_stream.BaseStream.Position ) {
m_stream.BaseStream.Seek( m_next_framedata_position, SeekOrigin.Begin );
}
long chunk_size = m_next_framedata_position - m_riff_position;
if ( (m_current_chunk == 0 && chunk_size > m_split_sreshold) ||
(m_current_chunk > 0 && chunk_size > _THRESHOLD) ) {
// AVIXリストへの書き込みに移行
UpdateIndex();
m_stream.BaseStream.Seek( m_avix_position, SeekOrigin.Begin );
Util.fwrite( "RIFF", m_stream );
m_riff_position = m_stream.BaseStream.Position;
Util.WriteDWORD( 0, m_stream );
Util.fwrite( "AVIX", m_stream );
long current = m_stream.BaseStream.Position;
if ( (current + 12) % 0x800 != 0 ) {
long additional = (current + 20) % 0x800;
additional = 0x800 - ((current + 20) % 0x800);
m_junk_length = (int)additional + 20;
Util.fwrite( "JUNK", m_stream );
Util.WriteDWORD( (uint)additional, m_stream );
for ( long ii = 0; ii < additional; ii++ ) {
Util.WriteBYTE( (byte)0, m_stream );
}
} else {
m_junk_length = 0;
}
m_junk_length = 0;
Util.fwrite( "LIST", m_stream );
m_movi_position = m_stream.BaseStream.Position;
Util.WriteDWORD( 0, m_stream );//後で更新するべき
Util.fwrite( "movi", m_stream );
m_next_framedata_position = m_stream.BaseStream.Position;
m_std_index.aIndex.Clear();
m_std_index.SetBaseOffset( (ulong)m_next_framedata_position );
m_current_chunk++;
m_super_index.nEntriesInUse++;
}
// フレームを書き込む処理
width = (int)m_main_header.dwWidth;
height = (int)m_main_header.dwHeight;
if ( width != bmpDat.Width ) {
return;
}
if ( height != bmpDat.Height ) {
return;
}
lineSize = bmpDat.Stride;
if ( m_compressed ) {
int is_key_frame = 0;
int size = bmpDat.Stride * bmpDat.Height;
try {
IntPtr dat = VCM.ICSeqCompressFrame( m_compvar, 0, bmpDat.Scan0, &is_key_frame, &size );
if ( !dat.Equals( IntPtr.Zero ) ) {
byte[] ndat = new byte[size];
Marshal.Copy( dat, ndat, 0, size );
m_std_index.AddIndex( (uint)((ulong)m_stream.BaseStream.Position - m_std_index.qwBaseOffset) + 8, (uint)size );
Util.fwrite( "00db", m_stream );
Util.WriteDWORD( (uint)size, m_stream );
m_stream.Write( ndat, 0, size );
m_this_movi_size += size;
}
} catch {
}
} else {
m_std_index.AddIndex( (uint)((ulong)m_stream.BaseStream.Position - m_std_index.qwBaseOffset) + 8, (uint)(lineSize * height) );
Util.fwrite( "00db", m_stream );
int address = bmpDat.Scan0.ToInt32();
byte[] bitmapData = new byte[bmpDat.Stride * bmpDat.Height];
Marshal.Copy( new IntPtr( address ), bitmapData, 0, bitmapData.Length );
Util.WriteDWORD( m_main_header.dwSuggestedBufferSize, m_stream );
m_stream.Write( bitmapData );
m_this_movi_size += bitmapData.Length;
}
m_next_framedata_position = m_stream.BaseStream.Position;
_avisuperindex_entry entry = m_super_index.aIndex[m_current_chunk];
entry.dwDuration++;
m_super_index.aIndex[m_current_chunk] = entry;
m_stream.Flush();
bmp.UnlockBits( bmpDat );
}
}
}

View File

@ -0,0 +1,496 @@
/*
* VfwAviWriter.cs
* Copyright (c) 2009 kbinani
*
* This file is part of Boare.Lib.Media.
*
* Boare.Lib.Media is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* Boare.Lib.Media 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.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.IO;
namespace Boare.Lib.Media {
public class AviWriterVfw : IAviWriter {
private int m_file_handle = 0;
private IntPtr m_video = new IntPtr( 0 );
private IntPtr m_video_compressed = new IntPtr( 0 );
private IntPtr m_audio = new IntPtr( 0 );
private IntPtr m_audio_compressed = new IntPtr( 0 );
private uint m_scale;
private uint m_rate;
private int m_count = 0;
private UInt32 m_width = 0;
private UInt32 m_stride = 0;
private UInt32 m_height = 0;
private static readonly UInt32 _STREAM_TYPE_VIDEO = (UInt32)mmioFOURCC( 'v', 'i', 'd', 's' );
private static readonly UInt32 _STREAM_TYPE_AUDIO = (UInt32)mmioFOURCC( 'a', 'u', 'd', 's' );
private uint m_strh_fcc = 0;
private string m_file = "";
private const int OF_READ = 0;
private const int OF_READWRITE = 2;
private const int OF_WRITE = 1;
private const int OF_SHARE_COMPAT = 0;
private const int OF_SHARE_DENY_NONE = 64;
private const int OF_SHARE_DENY_READ = 48;
private const int OF_SHARE_DENY_WRITE = 32;
private const int OF_SHARE_EXCLUSIVE = 16;
private const int OF_CREATE = 4096;
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
private struct AVISTREAMINFOW {
public UInt32 fccType, fccHandler, dwFlags, dwCaps;
public UInt16 wPriority, wLanguage;
public UInt32 dwScale, dwRate,
dwStart, dwLength, dwInitialFrames, dwSuggestedBufferSize,
dwQuality, dwSampleSize, rect_left, rect_top,
rect_right, rect_bottom, dwEditCount, dwFormatChangeCount;
public UInt16 szName0, szName1, szName2, szName3, szName4, szName5,
szName6, szName7, szName8, szName9, szName10, szName11,
szName12, szName13, szName14, szName15, szName16, szName17,
szName18, szName19, szName20, szName21, szName22, szName23,
szName24, szName25, szName26, szName27, szName28, szName29,
szName30, szName31, szName32, szName33, szName34, szName35,
szName36, szName37, szName38, szName39, szName40, szName41,
szName42, szName43, szName44, szName45, szName46, szName47,
szName48, szName49, szName50, szName51, szName52, szName53,
szName54, szName55, szName56, szName57, szName58, szName59,
szName60, szName61, szName62, szName63;
}
// vfw.h
[Serializable]
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
public struct AVICOMPRESSOPTIONS {
public UInt32 fccType;
public UInt32 fccHandler;
public UInt32 dwKeyFrameEvery; // only used with AVICOMRPESSF_KEYFRAMES
public UInt32 dwQuality;
public UInt32 dwBytesPerSecond; // only used with AVICOMPRESSF_DATARATE
public UInt32 dwFlags;
public IntPtr lpFormat;
public UInt32 cbFormat;
public IntPtr lpParms;
public UInt32 cbParms;
public UInt32 dwInterleaveEvery;
public override string ToString() {
return "fccType=" + fccType + "\n" +
"fccHandler=" + fccHandler + "\n" +
"dwKeyFrameEvery=" + dwKeyFrameEvery + "\n" +
"dwQuality=" + dwQuality + "\n" +
"dwBytesPerSecond=" + dwBytesPerSecond + "\n" +
"dwFlags=" + dwFlags + "\n" +
"lpFormat=" + lpFormat + "\n" +
"cbFormat=" + cbFormat + "\n" +
"lpParms=" + lpParms + "\n" +
"cbParms=" + cbParms + "\n" +
"dwInterleaveEvery=" + dwInterleaveEvery;
}
}
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
public struct BITMAPINFOHEADER {
public UInt32 biSize;
public Int32 biWidth;
public Int32 biHeight;
public Int16 biPlanes;
public Int16 biBitCount;
public UInt32 biCompression;
public UInt32 biSizeImage;
public Int32 biXPelsPerMeter;
public Int32 biYPelsPerMeter;
public UInt32 biClrUsed;
public UInt32 biClrImportant;
}
public Size Size {
get {
return new Size( (int)m_width, (int)m_height );
}
}
public uint Scale {
get {
return m_scale;
}
}
public uint Rate {
get {
return m_rate;
}
}
public class AviException : ApplicationException {
public AviException( string s )
: base( s ) {
}
public AviException( string s, Int32 hr )
: base( s ) {
if ( hr == AVIERR_BADPARAM ) {
err_msg = "AVIERR_BADPARAM";
} else {
err_msg = "unknown";
}
}
public string ErrMsg() {
return err_msg;
}
private const Int32 AVIERR_BADPARAM = -2147205018;
private string err_msg;
}
public bool Open( string file_name, uint scale, uint rate, int width, int height, IntPtr hwnd ) {
m_file = file_name;
this.m_scale = scale;
this.m_rate = rate;
this.m_width = (UInt32)width;
this.m_height = (UInt32)height;
using ( Bitmap bmp = new Bitmap( width, height, PixelFormat.Format24bppRgb ) ) {
BitmapData bmpDat = bmp.LockBits( new Rectangle( 0, 0, width, height ), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb );
this.m_stride = (UInt32)bmpDat.Stride;
bmp.UnlockBits( bmpDat );
}
AVIFileInit();
int hr = AVIFileOpenW( ref m_file_handle, file_name, OF_WRITE | OF_CREATE, 0 );
if ( hr != 0 ) {
throw new AviException( "error for AVIFileOpenW" );
}
CreateStream();
return SetOptions( hwnd );
}
public void AddFrame( Bitmap bmp ) {
BitmapData bmpDat = bmp.LockBits( new Rectangle( 0, 0, (int)m_width, (int)m_height ),
ImageLockMode.ReadOnly,
PixelFormat.Format24bppRgb );
int hr = AVIStreamWrite( m_video_compressed, m_count, 1,
bmpDat.Scan0,
(Int32)(m_stride * m_height),
0,
0,
0 );
if ( hr != 0 ) {
throw new AviException( "AVIStreamWrite" );
}
bmp.UnlockBits( bmpDat );
m_count++;
}
unsafe public static AVICOMPRESSOPTIONS RequireVideoCompressOption( AVICOMPRESSOPTIONS current_option ) {
AviWriterVfw temp = new AviWriterVfw();
temp.m_scale = 1000;
temp.m_rate = 30 * temp.m_scale;
int width = 10, height = 10;
temp.m_width = (UInt32)width;
temp.m_height = (UInt32)height;
using ( Bitmap bmp = new Bitmap( width, height, PixelFormat.Format24bppRgb ) ) {
BitmapData bmpDat = bmp.LockBits( new Rectangle( 0, 0, width, height ), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb );
temp.m_stride = (UInt32)bmpDat.Stride;
bmp.UnlockBits( bmpDat );
}
AVIFileInit();
string temp_file = Path.GetTempFileName() + ".avi";// .aviを付けないと、AVIFileOpenWが失敗する
int hr = AVIFileOpenW( ref temp.m_file_handle, temp_file, OF_WRITE | OF_CREATE, 0 );
if ( hr != 0 ) {
throw new AviException( "error for AVIFileOpenW" );
}
temp.CreateStream();
AVICOMPRESSOPTIONS opts = new AVICOMPRESSOPTIONS();
opts.fccType = 0; //fccType_;
opts.fccHandler = 0;//fccHandler_;
opts.dwKeyFrameEvery = 0;
opts.dwQuality = 0; // 0 .. 10000
opts.dwFlags = 0; // AVICOMRPESSF_KEYFRAMES = 4
opts.dwBytesPerSecond = 0;
opts.lpFormat = new IntPtr( 0 );
opts.cbFormat = 0;
opts.lpParms = new IntPtr( 0 );
opts.cbParms = 0;
opts.dwInterleaveEvery = 0;
opts = current_option;
AVICOMPRESSOPTIONS* p = &opts;
AVICOMPRESSOPTIONS** pp = &p;
IntPtr x = temp.m_video;
IntPtr* ptr_ps = &x;
AVISaveOptions( IntPtr.Zero, 0, 1, ptr_ps, pp );
//MessageBox.Show( "AVISaveOptions ok" );
AVICOMPRESSOPTIONS copied = new AVICOMPRESSOPTIONS();
copied = opts;
AVIStreamRelease( temp.m_video );
//MessageBox.Show( "AVIStreamRelease(temp.m_video) ok" );
AVIFileRelease( temp.m_file_handle );
//MessageBox.Show( "AVIFileRelease ok" );
AVIFileExit();
//MessageBox.Show( "AVIFileExit ok" );
File.Delete( temp_file );
//MessageBox.Show( "File.Delete(fileName) ok" );
return copied;
}
/// <summary>
/// オーディオ圧縮の設定ダイアログを表示し、オーディオ圧縮の設定を取得します
/// </summary>
/// <returns></returns>
unsafe public static AVICOMPRESSOPTIONS RequireAudioCompressOption() {
string temp_file = Path.GetTempFileName();
byte[] buf = new byte[] {
82, 73, 70, 70, 94, 0, 0, 0, 87, 65, 86, 69, 102, 109, 116, 32, 16, 0, 0, 0, 1,
0, 1, 0, 64, 31, 0, 0, 64, 31, 0, 0, 1, 0, 8, 0, 100, 97, 116, 97, 58, 0, 0, 0,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
};
using ( FileStream fs = new FileStream( temp_file, FileMode.Create ) ) {
fs.Write( buf, 0, buf.Length );
}
AVIFileInit();
//MessageBox.Show( "AVIFileInit ok" );
IntPtr audio;
int hr = AVIStreamOpenFromFileW( out audio, temp_file, _STREAM_TYPE_AUDIO, 0, OF_READ, 0 );
//MessageBox.Show( "AVIStreamOpenFromFileW ok" );
AVICOMPRESSOPTIONS opts = new AVICOMPRESSOPTIONS();
opts.fccType = _STREAM_TYPE_AUDIO; //fccType_;
opts.fccHandler = 0;//fccHandler_;
opts.dwKeyFrameEvery = 0;
opts.dwQuality = 0; // 0 .. 10000
opts.dwFlags = 0; // AVICOMRPESSF_KEYFRAMES = 4
opts.dwBytesPerSecond = 0;
opts.lpFormat = new IntPtr( 0 );
opts.cbFormat = 0;
opts.lpParms = new IntPtr( 0 );
opts.cbParms = 0;
opts.dwInterleaveEvery = 0;
AVICOMPRESSOPTIONS* p = &opts;
AVICOMPRESSOPTIONS** pp = &p;
IntPtr x = audio;
IntPtr* ptr_ps = &x;
AVISaveOptions( IntPtr.Zero, 0, 1, ptr_ps, pp );
//MessageBox.Show( "AVISaveOptions ok" );
AVICOMPRESSOPTIONS copied = new AVICOMPRESSOPTIONS();
copied = opts;
AVIStreamRelease( audio );
//MessageBox.Show( "AVIStreamRelease(audio) ok" );
AVIFileExit();
//MessageBox.Show( "AVIFileExit ok" );
File.Delete( temp_file );
return copied;
}
public void Close() {
AVIStreamRelease( m_video );
AVIStreamRelease( m_video_compressed );
AVIFileRelease( m_file_handle );
AVIFileExit();
using ( FileStream fs = new FileStream( m_file, FileMode.Open ) ) {
fs.Seek( 0x70, SeekOrigin.Begin );
byte ch3 = (byte)(m_strh_fcc >> 24);
uint b = (uint)(m_strh_fcc - (ch3 << 24));
byte ch2 = (byte)(b >> 16);
b = (uint)(b - (ch2 << 16));
byte ch1 = (byte)(b >> 8);
byte ch0 = (byte)(b - (ch1 << 8));
fs.Write( new byte[] { ch0, ch1, ch2, ch3 }, 0, 4 );
}
}
private void CreateStream() {
// video stream
AVISTREAMINFOW strhdr = new AVISTREAMINFOW();
strhdr.fccType = _STREAM_TYPE_VIDEO;
strhdr.fccHandler = 0;// fccHandler_;
strhdr.dwFlags = 0;
strhdr.dwCaps = 0;
strhdr.wPriority = 0;
strhdr.wLanguage = 0;
strhdr.dwScale = m_scale;
strhdr.dwRate = m_rate;
strhdr.dwStart = 0;
strhdr.dwLength = 0;
strhdr.dwInitialFrames = 0;
strhdr.dwSuggestedBufferSize = m_height * m_stride;
strhdr.dwQuality = 0xffffffff;
strhdr.dwSampleSize = 0;
strhdr.rect_top = 0;
strhdr.rect_left = 0;
strhdr.rect_bottom = m_height;
strhdr.rect_right = m_width;
strhdr.dwEditCount = 0;
strhdr.dwFormatChangeCount = 0;
strhdr.szName0 = 0;
strhdr.szName1 = 0;
int hr = AVIFileCreateStream( m_file_handle, out m_video, ref strhdr );
if ( hr != 0 ) {
throw new AviException( "AVIFileCreateStream; Video" );
}
#if DEBUG
Console.WriteLine( "AviWrierVfw+CreateStream" );
Console.WriteLine( " strhdr.fccHandler=" + strhdr.fccHandler );
#endif
}
internal static void CalcScaleAndRate( decimal fps, out uint scale, out uint rate ) {
scale = 100;
rate = (uint)(fps * 1000m);
int max = (int)(Math.Log10( uint.MaxValue ));
for ( int i = 0; i <= max; i++ ) {
scale = (uint)pow10( i );
rate = (uint)(fps * scale);
decimal t_fps = (decimal)rate / (decimal)scale;
if ( t_fps == fps ) {
return;
}
}
}
private static int pow10( int x ) {
int result = 1;
for ( int i = 1; i <= x; i++ ) {
result = result * 10;
}
return result;
}
unsafe private bool SetOptions( IntPtr hwnd ) {
// VIDEO
AVICOMPRESSOPTIONS opts = new AVICOMPRESSOPTIONS();
opts.fccType = 0;
opts.fccHandler = 0;
opts.dwKeyFrameEvery = 0;
opts.dwQuality = 0;
opts.dwFlags = 0;
opts.dwBytesPerSecond = 0;
opts.lpFormat = new IntPtr( 0 );
opts.cbFormat = 0;
opts.lpParms = new IntPtr( 0 );
opts.cbParms = 0;
opts.dwInterleaveEvery = 0;
AVICOMPRESSOPTIONS* p = &opts;
AVICOMPRESSOPTIONS** pp;
pp = &p;
IntPtr x = m_video;
IntPtr* ptr_ps;
ptr_ps = &x;
if ( AVISaveOptions( hwnd, 0, 1, ptr_ps, pp ) == 0 ) {
return false;
}
int hr = AVIMakeCompressedStream( out m_video_compressed, m_video, ref opts, 0 );
if ( hr != 0 ) {
throw new AviException( "AVIMakeCompressedStream; Video" );
}
m_strh_fcc = opts.fccHandler;
#if DEBUG
Console.WriteLine( "AviWriterVfw+SetOptions" );
Console.WriteLine( " opts.fccHandler=" + opts.fccHandler );
#endif
// TODO: AVISaveOptionsFree(...)
BITMAPINFO bi = new BITMAPINFO();
bi.bmiHeader.biSize = 40;
bi.bmiHeader.biWidth = (Int32)m_width;
bi.bmiHeader.biHeight = (Int32)m_height;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 24;
bi.bmiHeader.biCompression = 0;
bi.bmiHeader.biSizeImage = m_stride * m_height;
bi.bmiHeader.biXPelsPerMeter = 0;
bi.bmiHeader.biYPelsPerMeter = 0;
bi.bmiHeader.biClrUsed = 0;
bi.bmiHeader.biClrImportant = 0;
hr = AVIStreamSetFormat( m_video_compressed, 0, ref bi, sizeof( BITMAPINFO ) );
if ( hr != 0 ) {
throw new AviException( "AVIStreamSetFormat", hr );
}
#if DEBUG
Console.WriteLine( " bi.bmiHeader.biCompression=" + bi.bmiHeader.biCompression );
#endif
return true;
}
[DllImport( "avifil32.dll" )]
private static extern int AVIStreamOpenFromFileW( out IntPtr ppavi,
[MarshalAs( UnmanagedType.LPWStr )]string szfile,
uint fccType,
int lParam,
int mode,
int dumy );
[DllImport( "avifil32.dll" )]
private static extern void AVIFileInit();
[DllImport( "avifil32.dll" )]
private static extern int AVIFileOpenW( ref int ptr_pfile,
[MarshalAs( UnmanagedType.LPWStr )]string fileName,
int flags,
int dummy );
[DllImport( "avifil32.dll" )]
private static extern int AVIFileCreateStream(
int ptr_pfile, out IntPtr ptr_ptr_avi, ref AVISTREAMINFOW ptr_streaminfo );
[DllImport( "avifil32.dll" )]
private static extern int AVIMakeCompressedStream(
out IntPtr ppsCompressed, IntPtr aviStream, ref AVICOMPRESSOPTIONS ao, int dummy );
[DllImport( "avifil32.dll" )]
private static extern int AVIStreamSetFormat(
IntPtr aviStream, Int32 lPos, ref BITMAPINFO lpFormat, Int32 cbFormat );
[DllImport( "avifil32.dll" )]
unsafe private static extern int AVISaveOptions(
IntPtr hwnd, UInt32 flags, int nStreams, IntPtr* ptr_ptr_avi, AVICOMPRESSOPTIONS** ao );
[DllImport( "avifil32.dll" )]
private static extern int AVIStreamWrite( IntPtr aviStream,
Int32 lStart,
Int32 lSamples,
IntPtr lpBuffer,
Int32 cbBuffer,
Int32 dwFlags,
Int32 dummy1,
Int32 dummy2 );
[DllImport( "avifil32.dll" )]
private static extern int AVIStreamRelease( IntPtr aviStream );
[DllImport( "avifil32.dll" )]
private static extern int AVIFileRelease( int pfile );
[DllImport( "avifil32.dll" )]
private static extern void AVIFileExit();
public static Int32 mmioFOURCC( char ch0, char ch1, char ch2, char ch3 ) {
return ((Int32)(byte)(ch0) | ((byte)(ch1) << 8) | ((byte)(ch2) << 16) | ((byte)(ch3) << 24));
}
}
}

View File

@ -0,0 +1,92 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.21022</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{F4F8F601-4E3D-43F5-A8A8-AA1FB7F48452}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Boare.Lib.Media</RootNamespace>
<AssemblyName>Boare.Lib.Media</AssemblyName>
<FileUpgradeFlags>
</FileUpgradeFlags>
<OldToolsVersion>2.0</OldToolsVersion>
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>Boare.Lib.Media.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>Boare.Lib.Media.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<PlatformTarget>x86</PlatformTarget>
<OutputPath>bin\x86\Debug\</OutputPath>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefineConstants>DEBUG</DefineConstants>
<DocumentationFile>bin\x86\Debug\Boare.Lib.Media.XML</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<PlatformTarget>x86</PlatformTarget>
<OutputPath>bin\x86\Release\</OutputPath>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin\x86\Release\Boare.Lib.Media.XML</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="AviReader.cs" />
<Compile Include="AviWriterVcm.cs" />
<Compile Include="IAviWriter.cs" />
<Compile Include="MediaPlayer.cs" />
<Compile Include="MidiInDevice.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RawAvi2Writer.cs" />
<Compile Include="PipedAviWriter.cs" />
<Compile Include="Util.cs" />
<Compile Include="VCM.cs" />
<Compile Include="VFW.cs" />
<Compile Include="AviWriterVfw.cs" />
<Compile Include="Wave.cs" />
<Compile Include="WavePlay.cs" />
<Compile Include="WaveReader.cs" />
<Compile Include="WaveWriter.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\bocoree\bocoree.csproj">
<Project>{C8AAE632-9C6C-4372-8175-811528A66742}</Project>
<Name>bocoree</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -0,0 +1,34 @@
/*
* IAviWriter.cs
* Copyright (c) 2009 kbinani
*
* This file is part of LipSync.
*
* LipSync is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* LipSync 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.Drawing;
namespace Boare.Lib.Media {
public interface IAviWriter {
void AddFrame( Bitmap frame );
void Close();
bool Open( string file, uint scale, uint rate, int width, int height, IntPtr hwnd );
Size Size {
get;
}
uint Scale {
get;
}
uint Rate {
get;
}
}
}

View File

@ -0,0 +1,416 @@
/*
* MediaPlayer.cs
* Copyright (c) 2007-2009 kbinani
*
* This file is part of Boare.Lib.Media.
*
* Boare.Lib.Media is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* Boare.Lib.Media 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.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace Boare.Lib.Media {
/// <summary>
/// Sound player using mciSendSring command operation
/// </summary>
public class MediaPlayer : IDisposable {
private string m_filename = "";
const int FALSE = 0;
const int TRUE = 1;
bool pausing = false;
int m_volume = 1000;
bool mute = false;
string m_alias = "";
bool m_loaded = false;
float m_speed = 1.0f;
bool m_playing = false;
/// <summary>
/// the number of Load failure
/// </summary>
int m_load_failed = 0;
~MediaPlayer() {
Dispose();
}
public void Dispose() {
if ( m_loaded ) {
Close();
}
m_playing = false;
}
/// <summary>
/// Gets or Sets the speed
/// </summary>
public float Speed {
get {
return m_speed;
}
set {
m_speed = value;
SetSpeed( m_speed );
}
}
/// <summary>
/// Sets the speed
/// </summary>
/// <param name="speed">the value of speed to set</param>
private void SetSpeed( float speed ) {
w_mciSendString( "set " + m_alias + " speed " + (int)(speed * 1000.0f) );
}
/// <summary>
/// Gets or Sets the volume (0 &gt;= volume &gt;= 1000)
/// </summary>
public int Volume {
get {
if ( mute ) {
return 0;
} else {
return m_volume;
}
}
set {
m_volume = value;
SetVolume( m_volume );
}
}
/// <summary>
/// Sets the volume (0 &gt;= volume &gt;= 1000)
/// </summary>
/// <param name="value"></param>
private void SetVolume( int value ) {
ReLoad();
w_mciSendString( "setaudio " + m_alias + " volume to " + value );
}
/// <summary>
/// Gets the volume (0 &lt;= volume &lt;= 1000)
/// </summary>
/// <returns></returns>
private int GetVolume() {
ReLoad();
string str;
bool ret = w_mciSendString( "status " + m_alias + " volume", out str );
int v = m_volume;
if ( ret ) {
int v1;
if ( int.TryParse( str, out v1 ) ) {
v = v1;
}
}
#if DEBUG
Console.WriteLine( "MediaPlayer+GetVolume()" );
Console.WriteLine( " str=" + str );
Console.WriteLine( " volume=" + v );
#endif
return v;
}
/// <summary>
/// Gets or Sets whether sound is muted or not
/// </summary>
public bool IsMuted {
get {
return mute;
}
set {
bool old = mute;
mute = value;
if ( old != mute ) {
if ( mute ) {
SetVolume( 0 );
} else {
SetVolume( m_volume );
}
}
}
}
/// <summary>
/// Gets the pass of the sound file
/// </summary>
public string SoundLocation {
get {
return m_filename;
}
}
/// <summary>
/// external declaration of mciSendString
/// </summary>
/// <param name="s1">Command String</param>
/// <param name="s2">Return String</param>
/// <param name="i1">Return String Size</param>
/// <param name="i2">Callback Hwnd</param>
/// <returns>true when successed, false if not</returns>
[DllImport( "winmm.dll" )]
extern static int mciSendString( string s1, StringBuilder s2, int i1, int i2 );
/// <summary>
/// mciSendString wrapper with exception handling
/// </summary>
/// <param name="command">command sending to MCI</param>
/// <param name="result">returned string of mciSendString</param>
/// <returns>command successedd or not</returns>
static bool w_mciSendString( string command, out string result ) {
StringBuilder sb = new StringBuilder( 32 );
int io_status = 0;
result = "";
try {
io_status = mciSendString( command, sb, sb.Capacity, 0 );
result = sb.ToString();
} catch {
return false;
}
if ( io_status == 0 ) {
return true;
} else {
return false;
}
}
static bool w_mciSendString( string command ) {
string ret;
return w_mciSendString( command, out ret );
}
/// <summary>
/// Closes sound file temporary
/// </summary>
/// <returns></returns>
public void UnLoad() {
if ( m_filename != "" ) {
Stop();
w_mciSendString( "close " + m_alias );
m_loaded = false;
}
}
/// <summary>
/// Opens sound file which was closed with "UnLoad" method
/// </summary>
/// <returns></returns>
public void ReLoad() {
if ( m_filename != "" && !m_loaded && m_load_failed < 10 ) {
if ( Load( m_filename ) ) {
m_loaded = true;
if ( mute ) {
SetVolume( 0 );
} else {
SetVolume( m_volume );
}
}
}
}
/// <summary>
/// Opens sound file
/// </summary>
/// <param name="filename">Path of sound file to open</param>
/// <returns>successed opening the file or not</returns>
public bool Load( string filename ) {
#if DEBUG
Console.WriteLine( "MediaPlayer+Load(String)" );
Console.WriteLine( " filename=" + filename );
#endif
if ( m_filename != "" ) {
Close();
}
this.m_filename = filename;
m_alias = bocoree.misc.getmd5( m_filename );
#if DEBUG
Console.WriteLine( " m_alias=" + m_alias );
#endif
bool ret = w_mciSendString( "open \"" + filename + "\" type MPEGVIDEO2 alias " + m_alias );
if ( !ret ) {
ret = w_mciSendString( "open \"" + filename + "\" type MPEGVIDEO alias " + m_alias );
if ( !ret ) {
ret = w_mciSendString( "open \"" + filename + "\" alias " + m_alias );
}
}
#if DEBUG
Console.WriteLine( " w_mciSendString result=" + ret );
#endif
if ( ret ) {
m_loaded = true;
} else {
m_load_failed++;
}
#if DEBUG
m_volume = GetVolume();
Console.WriteLine( " m_volume=" + m_volume );
#endif
SetVolume( m_volume );
return ret;
}
/// <summary>
/// Plays sound from specified second
/// </summary>
/// <param name="time">Sound position start to play</param>
/// <returns>true if play command successed</returns>
public bool PlayFrom( double time ) {
if ( m_filename == "" ) {
return false;
}
long position = (long)(time * 1000);
if ( !m_loaded ) {
ReLoad();
}
/*if ( mute ) {
EnterMute();
} else {
ExitMute();
}*/
SetSpeed( m_speed );
m_playing = true;
return w_mciSendString( "play " + m_alias + " from " + position.ToString() );
}
/// <summary>
/// Closes sound file
/// </summary>
/// <returns>true if successed closing sound file</returns>
public bool Close() {
if ( m_filename == "" ) {
return false;
}
Stop();
m_filename = "";
m_loaded = false;
return w_mciSendString( "close " + m_alias );
}
/// <summary>
/// Plays sound from time 0 second
/// </summary>
/// <returns>true if successed to play</returns>
public bool Play() {
if ( m_filename == "" ) {
return false;
}
if ( !m_loaded ) {
ReLoad();
}
/*if ( mute ) {
EnterMute();
} else {
ExitMute();
}*/
SetSpeed( m_speed );
m_playing = true;
if ( pausing ) {
//return w_mciSendString( "resume \"" + m_filename + "\"", null, 0, 0 );
return w_mciSendString( "resume " + m_alias );
} else {
//return w_mciSendString( "play \"" + m_filename + "\"", null, 0, 0 );
return w_mciSendString( "play " + m_alias );
}
}
/// <summary>
/// Seeks to specified position
/// </summary>
/// <param name="pos_second">position to seek in second</param>
/// <returns>true if successed to seek</returns>
public bool Seek( double pos_second ) {
if ( m_filename == "" ) {
return false;
}
if ( !m_loaded ) {
ReLoad();
}
long position = (long)(pos_second * 1000.0);
bool ret = w_mciSendString( "seek " + m_alias + " to " + position );
return ret;
}
/// <summary>
/// Pauses sound
/// </summary>
/// <returns>true if successed to pause</returns>
public bool Pause() {
if ( m_filename == "" ) {
return false;
}
if ( !m_loaded ) {
ReLoad();
}
m_playing = false;
pausing = true;
//return w_mciSendString( "pause \"" + m_filename + "\"", null, 0, 0 );
return w_mciSendString( "pause " + m_alias );
}
/// <summary>
/// Gets the current playing position in millisecond
/// </summary>
/// <returns>playing position in millisecond</returns>
public int GetPosition() {
if ( this.SoundLocation == "" ) {
return -1;
}
if ( !m_loaded ) {
ReLoad();
}
string ret;
w_mciSendString( "status " + m_alias + " position", out ret );
int pos;
try {
pos = int.Parse( ret );
} catch {
pos = -1;
}
return pos;
}
/// <summary>
/// Gets the sound length in millisecond
/// </summary>
/// <returns>Sound length in millisecond</returns>
public int GetLength() {
if ( this.SoundLocation == "" ) {
return -1;
}
if ( !m_loaded ) {
ReLoad();
}
string ret;
w_mciSendString( "status " + m_alias + " length", out ret );
int length = -1;
if ( int.TryParse( ret, out length ) ) {
return length;
} else {
return -1;
}
}
/// <summary>
/// Stops sound
/// </summary>
/// <returns>true if successed to stop</returns>
public bool Stop() {
m_playing = false;
return w_mciSendString( "stop " + m_alias );
}
public bool IsPlaying {
get {
return m_playing;
}
}
}
}

View File

@ -0,0 +1,164 @@
/*
* MidiInDevice.cs
* Copyright (c) 2009 kbinani
*
* This file is part of Boare.Lib.Media.
*
* Boare.Lib.Media is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* Boare.Lib.Media 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.Runtime.InteropServices;
using System.Collections.Generic;
using bocoree;
namespace Boare.Lib.Media {
public delegate void MidiReceivedEventHandler( DateTime time, byte[] data );
public class MidiInDevice : IDisposable {
delegate void MidiInProcDelegate( uint hMidiIn, uint wMsg, int dwInstance, int dwParam1, int dwParam2 );
private const int CALLBACK_EVENT = 0x50000;
private const int CALLBACK_FUNCTION = 0x30000;
private const int CALLBACK_NULL = 0;
private const int CALLBACK_TASK = 0x20000;
private const int CALLBACK_THREAD = 0x20000;
private const int CALLBACK_TYPEMASK = 0x70000;
private const int CALLBACK_WINDOW = 0x10000;
private volatile MidiInProcDelegate m_delegate;
private IntPtr m_delegate_pointer;
private uint m_hmidiin = 0;
private int m_port_number;
private const int MM_MIM_CLOSE = 0x3c2;
private const int MM_MIM_DATA = 0x3c3;
private const int MM_MIM_ERROR = 0x3c5;
private const int MM_MIM_LONGDATA = 0x3c4;
private const int MM_MIM_LONGERROR = 0x3c6;
private const int MM_MIM_OPEN = 0x3c1;
public event MidiReceivedEventHandler MidiReceived;
public MidiInDevice( int port_number ) {
m_port_number = port_number;
m_delegate = new MidiInProcDelegate( MidiInProc );
m_delegate_pointer = Marshal.GetFunctionPointerForDelegate( m_delegate );
windows.midiInOpen( ref m_hmidiin, port_number, m_delegate_pointer, 0, CALLBACK_FUNCTION );
}
public void Start() {
if ( m_hmidiin > 0 ) {
try {
windows.midiInStart( m_hmidiin );
} catch ( Exception ex ) {
debug.push_log( "MidiInDevice.Start" );
debug.push_log( " ex=" + ex );
}
}
}
public void Stop() {
if ( m_hmidiin > 0 ) {
try {
windows.midiInReset( m_hmidiin );
} catch ( Exception ex ) {
debug.push_log( "MidiInDevice.Stop" );
debug.push_log( " ex=" + ex );
}
}
}
public void Close() {
if ( m_hmidiin > 0 ) {
try {
windows.midiInClose( m_hmidiin );
} catch ( Exception ex ) {
debug.push_log( "MidiInDevice.Close" );
debug.push_log( " ex=" + ex );
}
}
m_hmidiin = 0;
}
public void Dispose() {
Close();
}
public static int GetNumDevs() {
try {
int i = (int)windows.midiInGetNumDevs();
return i;
} catch ( Exception ex ) {
debug.push_log( "MidiInDevice.GetNumDevs" );
debug.push_log( " ex=" + ex );
}
return 0;
}
public static MIDIINCAPS[] GetMidiInDevices() {
List<MIDIINCAPS> ret = new List<MIDIINCAPS>();
uint num = 0;
try {
num = windows.midiInGetNumDevs();
} catch {
num = 0;
}
for ( uint i = 0; i < num; i++ ) {
MIDIINCAPS m = new MIDIINCAPS();
uint r = windows.midiInGetDevCaps( i, ref m, (uint)Marshal.SizeOf( m ) );
ret.Add( m );
}
return ret.ToArray();
}
private void MidiInProc( uint hMidiIn, uint wMsg, int dwInstance, int dwParam1, int dwParam2 ) {
try {
switch ( wMsg ) {
case MM_MIM_OPEN:
return;
case MM_MIM_CLOSE:
return;
case MM_MIM_DATA:
int receive = dwParam1;
DateTime now = DateTime.Now;
switch ( receive & 0xF0 ) {
case 0x80:
case 0x90:
case 0xa0:
case 0xb0:
case 0xe0:
if ( MidiReceived != null ) {
MidiReceived( now, new byte[] { (byte)(receive & 0xff),
(byte)((receive & 0xffff) >> 8),
(byte)((receive & ((2 << 24) - 1)) >> 16) } );
}
break;
case 0xc0:
case 0xd0:
if ( MidiReceived != null ) {
MidiReceived( now, new byte[] { (byte)( receive & 0xff ),
(byte)((receive & 0xffff) >> 8) } );
}
break;
}
return;
case MM_MIM_LONGDATA:
return;
case MM_MIM_ERROR:
return;
case MM_MIM_LONGERROR:
return;
}
} catch ( Exception ex ) {
debug.push_log( "MidiInDevice.MidiInProc" );
debug.push_log( " ex=" + ex );
}
}
}
}

View File

@ -0,0 +1,251 @@
/*
* PipedAviWriter.cs
* Copyright (c) 2008-2009 kbinani
*
* This file is part of Boare.Lib.Media.
*
* Boare.Lib.Media is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* Boare.Lib.Media 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 !MONO
#define TEST
using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
//using System.IO.Pipes;
using System.Runtime.InteropServices;
using System.Threading;
using bocoree;
namespace Boare.Lib.Media {
public class PipedAviWriter {
private const string _PIPE_NAME = "fifo";
private uint m_scale = 1;
private uint m_rate = 30;
#if TEST
private FileStream m_stream = null;
#else
private NamedPipeServerStream m_stream = null;
#endif
private MainAVIHeader m_main_avi_header;
private uint m_bitmapsize;
private bool m_header_written = false;
private ulong m_frames;
private Thread m_ffmpeg = null;
private PixelFormat m_pix_fmt = PixelFormat.Format24bppRgb;
private int m_bit_count = 24;
public bool AddFrame( Bitmap bmp ) {
if ( bmp.PixelFormat != m_pix_fmt ) {
return false;
}
BitmapData bdat = bmp.LockBits( new Rectangle( 0, 0, bmp.Width, bmp.Height ),
ImageLockMode.ReadOnly,
bmp.PixelFormat );
BinaryWriter bw = new BinaryWriter( new MemoryStream() );
if ( !m_header_written ) {
m_bitmapsize = (uint)(bdat.Stride * bdat.Height);
//m_stream.SetLength( (long)(0xdc + (m_bitmapsize + 0x8) * m_frames) );
/*m_main_avi_header.dwWidth = (uint)bdat.Width;
m_main_avi_header.dwHeight = (uint)bdat.Height;// bmp%infoHeader%Height
m_main_avi_header.dwMaxBytesPerSec = (uint)((float)bdat.Stride * (float)bdat.Height * (float)m_rate / (float)m_scale);
m_main_avi_header.dwStreams = 1;
m_main_avi_header.dwSuggestedBufferSize = (uint)(bdat.Stride * bdat.Height);
AVIStreamHeader stream_header = new AVIStreamHeader();
stream_header.fccType = Util.mmioFOURCC( "vids" );
stream_header.fccHandler = 0;
stream_header.dwFlags = 0;
stream_header.dwReserved1 = 0;
stream_header.dwInitialFrames = 0;
stream_header.dwScale = m_scale;
stream_header.dwRate = m_rate;
stream_header.dwStart = 0;
stream_header.dwSuggestedBufferSize = m_main_avi_header.dwSuggestedBufferSize;
stream_header.dwQuality = 0;
stream_header.dwSampleSize = 0;
BITMAPINFOHEADER bih = new BITMAPINFOHEADER(); //(BITMAPINFOHEADER)Marshal.PtrToStructure( Marshal.AllocHGlobal( sizeof( BITMAPINFOHEADER ) ), typeof( BITMAPINFOHEADER ) );
bih.biSize = (uint)(Marshal.SizeOf( bih ));
bih.biWidth = bdat.Width;
bih.biHeight = bdat.Height;
bih.biPlanes = 1;
bih.biBitCount = m_pix_fmt == PixelFormat.Format24bppRgb ? (short)24 : (short)32;
bih.biCompression = 0;//BI_RGB
bih.biSizeImage = (uint)(bdat.Stride * bdat.Height);
bih.biXPelsPerMeter = 0;
bih.biYPelsPerMeter = 0;
bih.biClrUsed = 0;
bih.biClrImportant = 0;
bw.Write( "RIFF".ToCharArray() );
bw.Write( (uint)(0xdc + (m_bitmapsize + 0x8) * m_frames) );
bw.Write( "AVI ".ToCharArray() );
bw.Write( "LIST".ToCharArray() );
bw.Write( (uint)0xc0 );
bw.Write( "hdrl".ToCharArray() );
bw.Write( "avih".ToCharArray() );
bw.Write( (uint)0x38 );
m_main_avi_header.Write( bw.BaseStream );
bw.Write( "LIST".ToCharArray() );
bw.Write( (uint)0x7C );
bw.Write( "strl".ToCharArray() );
bw.Write( "strh".ToCharArray() );
bw.Write( (uint)0x38 );
stream_header.Write( bw.BaseStream );
bw.Write( (uint)0x0 );
bw.Write( (uint)0x0 );
bw.Write( "strf".ToCharArray() );
bw.Write( (uint)0x28 );
bih.Write( bw.BaseStream );
bw.Write( "LIST".ToCharArray() );
bw.Write( (uint)((m_bitmapsize + 0x8) * m_frames) );
bw.Write( "movi".ToCharArray() );*/
m_header_written = true;
}
//bw.Write( "00db" );
//bw.Write( (uint)m_bitmapsize );
int address = bdat.Scan0.ToInt32();
byte[] bitmapData = new byte[bdat.Stride * bdat.Height];
Marshal.Copy( new IntPtr( address ), bitmapData, 0, bitmapData.Length );
//bw.Write( (uint)m_main_avi_header.dwSuggestedBufferSize );
bw.Write( "BM".ToCharArray() );
bw.Write( m_bitmapsize );
bw.Write( (uint)0x0 );
bw.Write( (uint)0x36 );
BITMAPINFOHEADER bih = new BITMAPINFOHEADER(); //(BITMAPINFOHEADER)Marshal.PtrToStructure( Marshal.AllocHGlobal( sizeof( BITMAPINFOHEADER ) ), typeof( BITMAPINFOHEADER ) );
bih.biSize = (uint)(Marshal.SizeOf( bih ));
bih.biWidth = bdat.Width;
bih.biHeight = bdat.Height;
bih.biPlanes = 1;
bih.biBitCount = m_pix_fmt == PixelFormat.Format24bppRgb ? (short)24 : (short)32;
bih.biCompression = 0;//BI_RGB
bih.biSizeImage = (uint)(bdat.Stride * bdat.Height);
bih.biXPelsPerMeter = 0;
bih.biYPelsPerMeter = 0;
bih.biClrUsed = 0;
bih.biClrImportant = 0;
bih.Write( bw );
bw.Write( bitmapData, 0, bitmapData.Length );
//const int _BUF_LEN = 512;
byte[] buf = new byte[m_bitmapsize + 6];
bw.BaseStream.Seek( 0, SeekOrigin.Begin );
int len = bw.BaseStream.Read( buf, 0, (int)(m_bitmapsize + 6) );
if ( len > 0 ) {
m_stream.BeginWrite( buf, 0, len, null, null );
}
m_stream.Flush();
bw.Close();
bmp.UnlockBits( bdat );
return true;
}
private void WriteFourCC( string value ) {
byte[] b = new byte[4];
for ( int i = 0; i < 4; i++ ) {
b[i] = (byte)value[i];
}
m_stream.Write( b, 0, 4 );
}
private void Write4Byte( uint value ) {
byte[] b;
b = BitConverter.GetBytes( value );
if ( !BitConverter.IsLittleEndian ) {
Array.Reverse( b );
}
m_stream.Write( b, 0, 4 );
}
public void Close() {
if ( m_stream != null ) {
#if !TEST
m_stream.Disconnect();
#endif
m_stream.Close();
}
if ( m_ffmpeg != null ) {
if ( m_ffmpeg.IsAlive ) {
m_ffmpeg.Abort();
while ( m_ffmpeg.IsAlive ) {
}
}
}
}
public void Open( uint scale, uint rate, ulong frames, PixelFormat pix_fmt ) {
if ( m_stream != null ) {
m_stream.Close();
}
#if TEST
m_stream = new FileStream( "test.out.avi", FileMode.Create );
#else
m_stream = new NamedPipeServerStream( _PIPE_NAME, PipeDirection.Out, 1, PipeTransmissionMode.Byte, PipeOptions.None, 1, 1 );
#endif
m_scale = scale;
m_rate = rate;
m_frames = frames;
m_main_avi_header.dwMicroSecPerFrame = (uint)(1.0e6 * (double)scale / (double)rate);// ! 1秒は10^6μ秒
m_main_avi_header.dwReserved1 = 0;
m_main_avi_header.dwFlags = 2064;
m_main_avi_header.dwInitialFrames = 0;
m_main_avi_header.dwStreams = 0;
m_main_avi_header.dwScale = scale;
m_main_avi_header.dwRate = rate;
m_main_avi_header.dwStart = 0;
m_main_avi_header.dwLength = 0;
m_main_avi_header.dwTotalFrames = (uint)m_frames;
m_pix_fmt = pix_fmt;
if ( m_pix_fmt != PixelFormat.Format24bppRgb && m_pix_fmt != PixelFormat.Format32bppArgb ) {
throw new ApplicationException( "pixel format not supported" );
}
#if !TEST
m_ffmpeg = new Thread( new ThreadStart( FFmpegEnc ) );
m_ffmpeg.Start();
m_stream.WaitForConnection();
#endif
}
private void FFmpegEnc() {
Thread.Sleep( 1000 );
Process client = new Process();
client.StartInfo.FileName = "ffmpeg";
// windowsの場合
client.StartInfo.Arguments = @"-f image2pipe -vcodec bmp -i \\.\pipe\" + _PIPE_NAME + " -isync -an -f avi -y test.avi";
// その他
// client.StartInfo.Arguments = @"-i " + _PIPE_NAME + " -y test.mp3";
client.StartInfo.RedirectStandardOutput = true;
client.StartInfo.UseShellExecute = false;
client.Start();
StreamReader sr = client.StandardOutput;
string line = "";
while ( (line = sr.ReadLine()) != null ) {
Console.WriteLine( line );
}
}
}
}
#endif

View File

@ -0,0 +1,29 @@
/*
* AssemblyInfo.cs
* Copyright (c) 2008-2009 kbinani
*
* This file is part of Boare.Lib.Media.
*
* Boare.Lib.Media is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* Boare.Cadencii 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.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle( "Boare.Lib.Media" )]
[assembly: AssemblyDescription( "" )]
[assembly: AssemblyConfiguration( "" )]
[assembly: AssemblyCompany( "Boare" )]
[assembly: AssemblyProduct( "Boare.Lib.Media" )]
[assembly: AssemblyCopyright( "Copyright © 2008-2009" )]
[assembly: AssemblyTrademark( "" )]
[assembly: AssemblyCulture( "" )]
[assembly: ComVisible( false )]
[assembly: Guid( "92853599-3628-440d-b15f-798fde36cf23" )]
[assembly: AssemblyVersion( "1.0.0.0" )]
[assembly: AssemblyFileVersion( "1.0.0" )]

View File

@ -0,0 +1,542 @@
/*
* RawAvi2Writer.cs
* Copyright (c) 2007-2009 kbinani
*
* This file is part of Boare.Lib.Media.
*
* Boare.Lib.Media is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* Boare.Lib.Media 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;
using System.Text;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
#if DEBUG
using System.Windows.Forms;
#endif
using bocoree;
namespace Boare.Lib.Media {
public struct _avistdindex_entry {
public UInt32 dwOffset;
public UInt32 dwSize;
}
public struct AVISTDINDEX {
public readonly string fcc;
//private UInt32 m_cb;
public UInt32 cb {
get {
if ( aIndex == null ) {
return 24;
} else {
return (uint)(24 + 8 * aIndex.Count);
}
}
}
public readonly UInt16 wLongsPerEntry;
public readonly byte bIndexSubType;
public readonly byte bIndexType;
//private UInt32 m_nEntriesInUse;
public UInt32 nEntriesInUse {
get {
if ( aIndex == null ) {
return 0;
} else {
return (uint)aIndex.Count;
}
}
}
public readonly string dwChunkId;
public UInt64 qwBaseOffset;
public readonly UInt32 dwReserved3;
public List<_avistdindex_entry> aIndex;
public AVISTDINDEX( ulong BaseOffset ) {
fcc = "ix00";
wLongsPerEntry = 2;
bIndexSubType = 0;
bIndexType = Util.AVI_INDEX_OF_CHUNKS;
dwChunkId = "00db";
qwBaseOffset = BaseOffset;
dwReserved3 = 0;
//m_nEntriesInUse = 0;
aIndex = new List<_avistdindex_entry>();
}
public void SetBaseOffset( UInt64 base_offset ) {
this.qwBaseOffset = base_offset;
}
public void AddIndex( uint dwOffset, uint dwSize ) {
_avistdindex_entry entry = new _avistdindex_entry();
entry.dwOffset = dwOffset;
entry.dwSize = dwSize;
this.aIndex.Add( entry );
}
public void Write( BinaryWriter fp ) {
Util.fwrite( fcc, fp );
Util.WriteDWORD( (uint)cb, fp );
Util.WriteWORD( wLongsPerEntry, fp );
Util.WriteBYTE( bIndexSubType, fp );
Util.WriteBYTE( bIndexType, fp );
Util.WriteDWORD( (uint)nEntriesInUse, fp );
Util.fwrite( dwChunkId, fp );
Util.WriteQWORD( (ulong)qwBaseOffset, fp );
Util.WriteDWORD( (uint)dwReserved3, fp );
foreach ( _avistdindex_entry entry in aIndex ) {
Util.WriteDWORD( (uint)entry.dwOffset, fp );
Util.WriteDWORD( (uint)entry.dwSize, fp );
}
}
}
public struct _avisuperindex_entry {
public UInt64 qwOffset;
public UInt32 dwSize;
public UInt32 dwDuration;
}
public struct AVISUPERINDEX {
public readonly string fcc;
//public UInt32 cb;
public UInt32 cb {
get {
if ( aIndex == null ) {
return 24;
} else {
return (uint)(24 + 16 * aIndex.Count);
}
}
}
public readonly UInt16 wLongsPerEntry;
public byte bIndexSubType;
public byte bIndexType;
public UInt32 nEntriesInUse;
public readonly string dwChunkId;
public UInt32 dwReserved1;
public UInt32 dwReserved2;
public UInt32 dwReserved3;
public List<_avisuperindex_entry> aIndex;
public AVISUPERINDEX( int dumy ) {
this.fcc = "indx";
this.wLongsPerEntry = 4;
this.bIndexSubType = 0;
this.bIndexType = Util.AVI_INDEX_OF_INDEXES;
this.nEntriesInUse = 0;
this.dwChunkId = "00db";
this.dwReserved1 = 0;
this.dwReserved2 = 0;
this.dwReserved3 = 0;
this.aIndex = new List<_avisuperindex_entry>();
_avisuperindex_entry entry = new _avisuperindex_entry();
entry.qwOffset = 0;
entry.dwSize = 0;
entry.dwDuration = 0;
for ( int i = 0; i < 126; i++ ) {
this.aIndex.Add( entry );
}
}
public void Write( BinaryWriter fp ) {
Util.fwrite( fcc, fp );
Util.WriteDWORD( (uint)cb, fp );//ここほんとは(int)cb
Util.WriteWORD( wLongsPerEntry, fp );
Util.WriteBYTE( bIndexSubType, fp );
Util.WriteBYTE( bIndexType, fp );
Util.WriteDWORD( (uint)nEntriesInUse, fp );
Util.fwrite( dwChunkId, fp );
Util.WriteDWORD( (uint)dwReserved1, fp );
Util.WriteDWORD( (uint)dwReserved2, fp );
Util.WriteDWORD( (uint)dwReserved3, fp );
foreach ( _avisuperindex_entry entry in aIndex ) {
Util.WriteQWORD( (ulong)entry.qwOffset, fp );
Util.WriteDWORD( (uint)entry.dwSize, fp );
Util.WriteDWORD( (uint)entry.dwDuration, fp );
}
}
}
public class RawAvi2Writer {
public MainAVIHeader m_main_header;
public AVIStreamHeader m_stream_header;
//long currentIndex;
BinaryWriter m_stream;
//int frameRate;
//int noOfFrame;
int m_current_chunk = 0;
long m_position_in_chunk = 0L;
const long SRESHOLD = 1000000000L; //AVIXリストの最大サイズ(byte)
long m_split_sreshold = 160000000L; //AVIリストの最大サイズ(byte)
AVISTDINDEX m_std_index;
AVISUPERINDEX m_super_index;
int m_linesize;//bitmapの1行分のデータサイズ(byte)
bool m_is_first = true;
long m_riff_position;//"RIFF*"の*が記入されているファイルの絶対位置。RIFF-AVI のときは必ず4。RIFF-AVIXの時は変化する
long m_movi_position;
long m_next_framedata_position;//次に00dbデータを記入するべき場所
long m_avix_position;
int m_junk_length;
uint m_scale;
uint m_rate;
internal float frameRate {
get {
return (float)m_rate / (float)m_scale;
}
}
/// <summary>
/// 指定したAVI_CONTAINER構造体にAVIファイルの情報を格納すると共に
/// ファイルにヘッダー情報を書き込みます.
/// </summary>
/// <param name="file">書き込み対象のファイル</param>
/// <param name="frameRate">AVIファイルのフレームレート</param>
public void Open( string file, uint scale, uint rate ) {
this.m_stream = new BinaryWriter( new FileStream( file, FileMode.Create, FileAccess.Write ) );
float fps = (float)rate / (float)scale;
this.m_main_header.dwMicroSecPerFrame = (uint)(1.0e6 / fps);// ! 1秒は10^6μ秒
this.m_main_header.dwReserved1 = 0;
this.m_main_header.dwFlags = 2064;
this.m_main_header.dwInitialFrames = 0;
this.m_main_header.dwStreams = 0;
this.m_main_header.dwScale = scale;
this.m_main_header.dwRate = rate;
this.m_main_header.dwStart = 0;
this.m_main_header.dwLength = 0;
this.m_rate = rate;
this.m_scale = scale;
//this.noOfFrame = 0;
Util.fwrite( "RIFF", this.m_stream );
Util.WriteDWORD( 0, this.m_stream );
Util.fwrite( "AVI ", this.m_stream );
Util.fwrite( "LIST", this.m_stream );
Util.WriteDWORD( 0x9cc, this.m_stream );
Util.fwrite( "hdrl", this.m_stream );
m_current_chunk = 0;
m_position_in_chunk = 0L;
m_std_index = new AVISTDINDEX( 0L );
m_super_index = new AVISUPERINDEX( 0 );
m_riff_position = 0x4;
}
/*[Obsolete]
public void Open( string file, float frameRate ) {
uint scale, rate;
AviWriter.CalcScaleAndRate( (decimal)frameRate, out scale, out rate );
Open( file, scale, rate );
}*/
//todo: AVIMainHeader.dwTotalFramesに、ファイル全体のフレーム数を入れる仕様違反
//todo: AVIStreamHeader.dwLengthに、ファイル全体のフレーム数を入れる仕様違反
/// <summary>
/// 全てのインデックスを更新し、ファイルが(動画ファイルとして)使用できる状態にします
/// この関数を読んだあとでもさらにaviAddFrame関数を使うことでフレームを追加することが出来ます
/// </summary>
public void UpdateIndex() {
_avisuperindex_entry entry = m_super_index.aIndex[m_current_chunk];
entry.qwOffset = (ulong)m_stream.BaseStream.Position;
entry.dwSize = m_std_index.cb;
m_super_index.aIndex[m_current_chunk] = entry;
if ( m_stream.BaseStream.Position != m_next_framedata_position ) {
m_stream.BaseStream.Seek( m_next_framedata_position, SeekOrigin.Begin );
}
m_std_index.Write( m_stream );
int frames = (int)m_super_index.aIndex[m_current_chunk].dwDuration;
m_avix_position = m_stream.BaseStream.Position;
if ( m_current_chunk == 0 ) {
uint i, step, number;
step = this.m_main_header.dwSuggestedBufferSize + 8;
Util.fwrite( "idx1", this.m_stream );
Util.WriteDWORD( (uint)(16 * frames), this.m_stream );
for ( i = 1; i <= frames; i++ ) {
Util.fwrite( "00db", this.m_stream );
Util.WriteDWORD( Util.AVIF_HASINDEX, this.m_stream );
Util.WriteDWORD( (uint)(4 + (i - 1) * step), this.m_stream );
Util.WriteDWORD( this.m_main_header.dwSuggestedBufferSize, this.m_stream );
}// end do
m_avix_position = m_stream.BaseStream.Position;
number = (uint)frames;
//avi_writeIsolate( this.fp, number, 48 ); // AVIMainHeader.dwTotalFrames
m_stream.Seek( 48, SeekOrigin.Begin );
Util.WriteDWORD( number, m_stream );
//avi_writeIsolate( this.fp, number, 140 ); // AVIStreamHeader.dwLength
m_stream.Seek( 140, SeekOrigin.Begin );
Util.WriteDWORD( number, m_stream );
//odml dlmhのdwTotalFrames
m_stream.Seek( 0x8e8, SeekOrigin.Begin );
Util.WriteDWORD( (uint)frames, m_stream );
// LIST****moviの****の数値を計算
number = 4;//"movi"
number += (uint)(frames * (m_linesize * m_main_header.dwHeight + 8));//フレーム数*(フレームのサイズ+"00db"+00dbチャンクのサイズ)
number += 4 + 4 + (uint)m_std_index.cb; //ix00のサイズ
//number += 4 + 4 + 16 * frames;//idx1のサイズ
//avi_writeIsolate( this.fp, number, 2040 ); // LIST****movi の ****部分
m_stream.BaseStream.Seek( m_movi_position, SeekOrigin.Begin );
Util.WriteDWORD( number, m_stream );
//number = 4096 + (this.mainHeader.dwSuggestedBufferSize + 24) * this.noOfFrame;
//avi_writeIsolate( this.fp, number, 4 ); // RIFF****AVI の ****部分
number = (uint)m_junk_length/* 0xff4*/; //JUNKの終わりまでのサイズ。これは固定
number += 4;//"movi"
number += (uint)(frames * (m_linesize * m_main_header.dwHeight + 8));//00db...の合計サイズ
number += 4 + 4 + (uint)m_std_index.cb;
number += (uint)(4 + 4 + 16 * frames);//idx1のサイズ
m_stream.BaseStream.Seek( m_riff_position, SeekOrigin.Begin );
Util.WriteDWORD( number, m_stream );
UpdateIndexOfIndex();
} else {
// LIST****moviの****を更新
int number = 4;
number += (int)(frames * (m_linesize * m_main_header.dwHeight + 8));
number += 8 + (int)m_std_index.cb;
m_stream.BaseStream.Seek( m_movi_position, SeekOrigin.Begin );
Util.WriteDWORD( (uint)number, m_stream );
// odml dlmhのdwTotalFrames
uint frames2 = 0;
for ( int j = 0; j <= m_current_chunk; j++ ) {
frames2 += (uint)m_super_index.aIndex[j].dwDuration;
}
m_stream.BaseStream.Seek( 0x8e8, SeekOrigin.Begin );
Util.WriteDWORD( frames2, m_stream );
//avi_writeIsolate( this.fp, number, 48 ); // AVIMainHeader.dwTotalFrames
m_stream.Seek( 48, SeekOrigin.Begin );
Util.WriteDWORD( frames2, m_stream );
//avi_writeIsolate( this.fp, number, 140 ); // AVIStreamHeader.dwLength
m_stream.Seek( 140, SeekOrigin.Begin );
Util.WriteDWORD( frames2, m_stream );
//RIFF****AVIXの****を更新
long num2 = m_junk_length + number;
m_stream.BaseStream.Seek( m_riff_position, SeekOrigin.Begin );
Util.WriteDWORD( (uint)num2, m_stream );
UpdateIndexOfIndex();
}
}
/// <summary>
/// aviファイルを閉じます
/// </summary>
public void Close() {
UpdateIndex();
this.m_stream.Close();
}
/// <summary>
/// 最初の[AVI :AVI[LIST:hdrl[LIST:strl]]]に書き込まれているsuper indexチャンク[indx]を更新します
/// </summary>
private void UpdateIndexOfIndex() {
m_stream.Seek( 0xd4, SeekOrigin.Begin );
m_super_index.Write( m_stream );
}
/// <summary>
/// aviファイルにフレームを1つ追加します
/// </summary>
/// <param name="bmp"></param>
public void AddFrame( Bitmap bmp ) {
int i, width, height, lineSize;
// BitmapDataからビットマップデータと、BITMPAINFOHEADERを取り出す
BitmapData bmpDat = bmp.LockBits(
new Rectangle( 0, 0, (int)bmp.Width, (int)bmp.Height ), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb );
int address = bmpDat.Scan0.ToInt32();
byte[] bitmapData = new byte[bmpDat.Stride * bmpDat.Height];
Marshal.Copy( new IntPtr( address ), bitmapData, 0, bitmapData.Length );
if ( m_is_first ) {//then
m_is_first = false;
this.m_main_header.dwWidth = (uint)bmpDat.Width;// bmp%infoHeader%Width
this.m_main_header.dwHeight = (uint)bmpDat.Height;// bmp%infoHeader%Height
this.m_main_header.dwMaxBytesPerSec = (uint)(bmpDat.Stride * bmpDat.Height * this.frameRate);// bmp%infoHeader%SizeImage * avi%frameRate
this.m_main_header.dwStreams = 1;
this.m_main_header.dwSuggestedBufferSize = (uint)(bmpDat.Stride * bmpDat.Height);// bmp.infoHeader%SizeImage
m_linesize = bmpDat.Stride;
this.m_stream_header.fccType = Util.mmioFOURCC( "vids" );
this.m_stream_header.fccHandler = 0;
this.m_stream_header.dwFlags = 0;
this.m_stream_header.dwReserved1 = 0;
this.m_stream_header.dwInitialFrames = 0;
this.m_stream_header.dwScale = m_scale;
this.m_stream_header.dwRate = m_rate;
this.m_stream_header.dwStart = 0;
this.m_stream_header.dwSuggestedBufferSize = this.m_main_header.dwSuggestedBufferSize;
this.m_stream_header.dwQuality = 0;
this.m_stream_header.dwSampleSize = 0;
Util.aviWriteMainHeader( m_main_header, m_stream );
Util.fwrite( "LIST", this.m_stream );// i = fwrite( 'LIST', 1, 4, avi%fp )
Util.WriteDWORD( 0x874, this.m_stream );// call bmpQWordWrite( 130, avi%fp )
Util.fwrite( "strl", this.m_stream );// i = fwrite( 'strl', 1, 4, avi%fp )
Util.aviWriteStreamHeader( m_stream_header, m_main_header, m_stream );// avi )
Util.fwrite( "strf", this.m_stream );// i = fwrite( 'strf', 1, 4, avi%fp )
Util.WriteDWORD( 0x28, this.m_stream ); //call bmpQWordWrite( 40, avi%fp ) !// infoHeaderのサイズ
BITMAPINFOHEADER bih = new BITMAPINFOHEADER();
bih.biSize = (uint)(Marshal.SizeOf( bih ));
bih.biWidth = bmpDat.Width;
bih.biHeight = bmpDat.Height;
bih.biPlanes = 1;
bih.biBitCount = 24;
bih.biCompression = 0;//BI_RGB
bih.biSizeImage = (uint)(bmpDat.Stride * bmpDat.Height);
bih.biXPelsPerMeter = 0;
bih.biYPelsPerMeter = 0;
bih.biClrUsed = 0;
bih.biClrImportant = 0;
bih.Write( m_stream );
/*fwrite( "strn", this.fp );
WriteDWORD( 6, this.fp );
fwrite( "VIDEO", this.fp );
WriteBYTE( 0, this.fp );*/
Util.fwrite( "indx", this.m_stream ); //fcc
Util.WriteDWORD( 0x7f8, this.m_stream ); // cb
Util.WriteWORD( (byte)0x4, this.m_stream ); // wLongsPerEntry
Util.WriteBYTE( 0x0, this.m_stream ); // bIndexSubType
Util.WriteBYTE( Util.AVI_INDEX_OF_INDEXES, this.m_stream );// bIndexType
Util.WriteDWORD( 0x0, this.m_stream ); // nEntriesInUse
Util.fwrite( "00db", this.m_stream ); // dwChunkId
Util.WriteDWORD( 0x0, this.m_stream );
Util.WriteDWORD( 0x0, this.m_stream );
Util.WriteDWORD( 0x0, this.m_stream );
for ( int ii = 1; ii <= 126; ii++ ) {
Util.WriteQWORD( 0x0, this.m_stream );
Util.WriteDWORD( 0x0, this.m_stream );
Util.WriteDWORD( 0x0, this.m_stream );
}
Util.fwrite( "LIST", this.m_stream );
Util.WriteDWORD( 0x104, m_stream );
Util.fwrite( "odml", this.m_stream );
Util.fwrite( "dmlh", m_stream );
Util.WriteDWORD( 0xf8, m_stream );
Util.WriteDWORD( 0x0, m_stream );//ここ後で更新するべき
for ( int ii = 1; ii <= 61; ii++ ) {
Util.WriteDWORD( 0x0, m_stream );
}
Util.fwrite( "JUNK", this.m_stream );// i = fwrite( 'JUNK', 1, 4, avi%fp )
Util.WriteDWORD( 0x60c, m_stream );
Util.WriteDWORD( 0, m_stream );//"This"が将来登録されたらやばいので
Util.fwrite( "This file was generated by RawAvi@LipSync", this.m_stream );
//WriteDWORD( 1503, this.fp );// call bmpQWordWrite( 1802, avi%fp )
for ( i = 1; i <= 1503; i++ ) {//do i = 1, 1802
this.m_stream.Write( (byte)0 );// call fputc( 0, avi%fp )
}//end do
m_junk_length = 0xff4;
Util.fwrite( "LIST", this.m_stream );// i = fwrite( 'LIST', 1, 4, avi%fp )
m_movi_position = m_stream.BaseStream.Position;
Util.WriteDWORD( 0, this.m_stream );// call bmpQWordWrite( 0, avi%fp ) !// ******************ココの数字は一番最後に書き換える必要あり20402043あとdwTotalFrames4851
Util.fwrite( "movi", this.m_stream );// i = fwrite( 'movi', 1, 4, avi%fp )
m_next_framedata_position = m_stream.BaseStream.Position;
m_std_index.SetBaseOffset( (ulong)m_next_framedata_position );
m_super_index.nEntriesInUse++;
}//end if
if ( m_next_framedata_position != m_stream.BaseStream.Position ) {
m_stream.BaseStream.Seek( m_next_framedata_position, SeekOrigin.Begin );
}
long chunk_size = m_next_framedata_position - m_riff_position;
#if DEBUG
// MessageBox.Show( "chunk_size=" + chunk_size );
#endif
if ( (m_current_chunk == 0 && chunk_size > m_split_sreshold) ||
(m_current_chunk > 0 && chunk_size > SRESHOLD )) {
// AVIXリストへの書き込みに移行
UpdateIndex();
m_stream.BaseStream.Seek( m_avix_position, SeekOrigin.Begin );
Util.fwrite( "RIFF", m_stream );
m_riff_position = m_stream.BaseStream.Position;
#if DEBUG
// fp.Flush();
// MessageBox.Show( "m_riff_position=" + m_riff_position );
#endif
Util.WriteDWORD( 0, m_stream );
Util.fwrite( "AVIX", m_stream );
long current = m_stream.BaseStream.Position;
if ( (current + 12) % 0x800 != 0 ) {
long additional = (current + 20) % 0x800;
additional = 0x800 - ((current + 20) % 0x800);
m_junk_length = (int)additional + 20;
Util.fwrite( "JUNK", m_stream );
Util.WriteDWORD( (uint)additional, m_stream );
for ( long ii = 0; ii < additional; ii++ ) {
Util.WriteBYTE( (byte)0, m_stream );
}
} else {
m_junk_length = 0;
}
m_junk_length = 0;
Util.fwrite( "LIST", m_stream );
m_movi_position = m_stream.BaseStream.Position;
Util.WriteDWORD( 0, m_stream );//後で更新するべき
Util.fwrite( "movi", m_stream );
m_next_framedata_position = m_stream.BaseStream.Position;
m_std_index.aIndex.Clear();
m_std_index.SetBaseOffset( (ulong)m_next_framedata_position );
m_current_chunk++;
m_super_index.nEntriesInUse++;
}
// フレームを書き込む処理
width = (int)this.m_main_header.dwWidth;
height = (int)this.m_main_header.dwHeight;
if ( width != bmpDat.Width ) {//then
//aviAddFrame = -1
return;
}//end if
if ( height != bmpDat.Height ) {//then
//aviAddframe = -1
return;
}//end if
lineSize = bmpDat.Stride;// int( (width * 24 + 31) / 32 ) * 4
m_std_index.AddIndex( (uint)((ulong)m_stream.BaseStream.Position - m_std_index.qwBaseOffset) + 8, (uint)(lineSize * height) );
Util.fwrite( "00db", this.m_stream );// i = fwrite( '00db', 1, 4, avi%fp )
Util.WriteDWORD( m_main_header.dwSuggestedBufferSize, m_stream );// call bmpQWordWrite( avi%mainHeader%dwSuggestedBufferSize, avi%fp )
m_stream.Write( bitmapData );
m_next_framedata_position = m_stream.BaseStream.Position;
_avisuperindex_entry entry = m_super_index.aIndex[m_current_chunk];
entry.dwDuration++;
m_super_index.aIndex[m_current_chunk] = entry;// avi%noOfFrame = avi%noOfFrame + 1
this.m_stream.Flush();// aviAddFrame = fflush( avi%fp )
bmp.UnlockBits( bmpDat );
}// end function
}
}

View File

@ -0,0 +1,222 @@
/*
* Util.cs
* Copyright (c) 2007-2009 kbinani
*
* This file is part of Boare.Lib.Media.
*
* Boare.Lib.Media is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* Boare.Lib.Media 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 bocoree;
namespace Boare.Lib.Media {
internal static class Util {
public const byte AVI_INDEX_OF_INDEXES = 0x00; //when each entry in aIndex
// array points to an index chunk
public const byte AVI_INDEX_OF_CHUNKS = 0x01; // when each entry in aIndex
// array points to a chunk in the file
public const byte AVI_INDEX_IS_DATA = 0x80; // when each entry is aIndex is
// really the data
public const byte AVI_INDEX_2FIELD = 0x01; // when fields within frames
// are also indexed
public const int AVIF_HASINDEX = 16; // Indicates the AVI file has an “idx1” chunk.
public const int AVIF_MUSTUSEINDEX = 32; // Indicates the index should be used to determine the order of presentation of the data.
public const int AVIF_ISINTERLEAVED = 256; // Indicates the AVI file is interleaved.
public const int AVIF_WASCAPTUREFILE = 65536; // Indicates the AVI file is a specially allocated file used for capturing real-time video.
public const int AVIF_COPYRIGHTED = 131072; // Indicates the AVI file contains copyrighted data.
public const int AVIF_TRUSTCKTYPE = 2048; // Use CKType to find key frames
public const int BMP_MAGIC_COOKIE = 19778; //ascii string "BM"
/*// <summary>
/// 指定されたBITMAP型変数の情報ヘッダーをファイルに書き込みます
/// </summary>
/// <param name="bmp"></param>
/// <param name="fp"></param>
public static void bmpWriteInfoHeader( BITMAPINFOHEADER infoHeader, BinaryWriter stream ) {
//type(INFO_HEADER), intent(in) :: infoHeader
//type(FILE), intent(inout) :: fp
Util.WriteDWORD( (uint)infoHeader.biSize, stream );
Util.WriteDWORD( (uint)infoHeader.biWidth, stream );
Util.WriteDWORD( (uint)infoHeader.biHeight, stream );
Util.WriteWORD( (ushort)infoHeader.biPlanes, stream );
Util.WriteWORD( (ushort)(infoHeader.biBitCount), stream );
Util.WriteDWORD( (uint)infoHeader.biCompression, stream );
Util.WriteDWORD( (uint)infoHeader.biSizeImage, stream );
Util.WriteDWORD( (uint)infoHeader.biXPelsPerMeter, stream );
Util.WriteDWORD( (uint)infoHeader.biYPelsPerMeter, stream );
Util.WriteDWORD( (uint)infoHeader.biClrUsed, stream );
Util.WriteDWORD( (uint)infoHeader.biClrImportant, stream );
}*/
/// <summary>
/// ファイルにAVIStreamHeader構造体の値を書き込みます
/// </summary>
public static void aviWriteStreamHeader( AVIStreamHeader streamHeader, MainAVIHeader mainHeader, BinaryWriter stream ) {
//type(AVI_CONTAINER), intent(inout) :: avi
Util.fwrite( "strh", stream );
Util.WriteDWORD( 56, stream );// call bmpQWordWrite( 56, avi%fp ) !// AVIStreamHeaderのサイズ
//fwrite( streamHeader.fccType, fp );// i = fwrite( avi%streamHeader%fccType, 1, 4, avi%fp )
Util.WriteDWORD( (uint)streamHeader.fccType, stream );
//fwrite( streamHeader.fccHandler, fp );// i = fwrite( streamHeader.fccHandler, 1, 4, fp );
Util.WriteDWORD( (uint)streamHeader.fccHandler, stream );
//WriteDWORD( 0, fp );
Util.WriteDWORD( streamHeader.dwFlags, stream );
//WriteDWORD( streamHeader.dwReserved1, fp );
Util.WriteWORD( 0, stream );//wPriority
Util.WriteWORD( 0, stream );//wLanghage
Util.WriteDWORD( streamHeader.dwInitialFrames, stream );
Util.WriteDWORD( streamHeader.dwScale, stream );
Util.WriteDWORD( streamHeader.dwRate, stream );
Util.WriteDWORD( streamHeader.dwStart, stream );
Util.WriteDWORD( streamHeader.dwLength, stream );
Util.WriteDWORD( streamHeader.dwSuggestedBufferSize, stream );
Util.WriteDWORD( streamHeader.dwQuality, stream );
Util.WriteDWORD( streamHeader.dwSampleSize, stream );
Util.WriteWORD( 0, stream );//left
Util.WriteWORD( 0, stream );//top
Util.WriteWORD( (ushort)mainHeader.dwWidth, stream );//right
Util.WriteWORD( (ushort)mainHeader.dwHeight, stream );//bottom
}
/// <summary>
/// ファイルにMainAviHeader構造体の値を書き込みます
/// </summary>
public static void aviWriteMainHeader( MainAVIHeader mainHeader, BinaryWriter stream ) {
//type(AVI_CONTAINER), intent(inout) :: avi
Util.fwrite( "avih", stream );// i = fwrite( 'avih', 1, 4, avi%fp )
Util.WriteDWORD( 56, stream ); // MainAVIHeaderのサイズ
Util.WriteDWORD( mainHeader.dwMicroSecPerFrame, stream );
Util.WriteDWORD( 0/*this.mainHeader.dwMaxBytesPerSec*/, stream );
Util.WriteDWORD( mainHeader.dwReserved1, stream );
Util.WriteDWORD( mainHeader.dwFlags, stream );
Util.WriteDWORD( mainHeader.dwTotalFrames, stream );
Util.WriteDWORD( mainHeader.dwInitialFrames, stream );
Util.WriteDWORD( mainHeader.dwStreams, stream );
Util.WriteDWORD( 0/*this.mainHeader.dwSuggestedBufferSize*/, stream );
Util.WriteDWORD( mainHeader.dwWidth, stream );
Util.WriteDWORD( mainHeader.dwHeight, stream );
Util.WriteDWORD( mainHeader.dwScale, stream );
Util.WriteDWORD( mainHeader.dwRate, stream );
Util.WriteDWORD( mainHeader.dwStart, stream );
Util.WriteDWORD( mainHeader.dwLength, stream );
}//end subroutine
public static void fwrite( string str, BinaryWriter fp ) {
int length = str.Length;
if ( length <= 0 ) {
return;
}
foreach ( char ch in str ) {
fp.Write( (byte)ch );
}
}
/// <summary>
/// BYTE値を1byte分ファイルに書き込みます
/// </summary>
/// <param name="number"></param>
/// <param name="fp"></param>
public static void WriteBYTE( byte number, BinaryWriter fp ) {
fp.Write( number );
}
/// <summary>
/// integer(2)のDWORD値を2byte分ファイルに書き込みます
/// </summary>
/// <param name="number"></param>
/// <param name="fp"></param>
public static void WriteWORD( ushort number, BinaryWriter fp ) {
byte k1, k2;
k1 = (byte)(number >> 8);
k2 = (byte)(number - (k1 << 8));
fp.Write( k2 );
fp.Write( k1 );
}
/// <summary>
/// integer(4)のDWORD値を4byte分ファイルに書き込みます
/// </summary>
/// <param name="number"></param>
/// <param name="fp"></param>
public static void WriteDWORD( uint number, BinaryWriter fp ) {
uint tmp;
byte k1, k2, k3, k4;
k1 = (byte)(number >> 24);
number -= (uint)(k1 << 24);
k2 = (byte)(number >> 16);
number -= (uint)(k2 << 16);
k3 = (byte)(number >> 8);
k4 = (byte)(number - (k3 << 8));
fp.Write( k4 );
fp.Write( k3 );
fp.Write( k2 );
fp.Write( k1 );
}
/// <summary>
/// integer(8)のQWORD値を8byte分ファイルに書き込みます
/// </summary>
/// <param name="number"></param>
/// <param name="fp"></param>
public static void WriteQWORD( ulong number, BinaryWriter fp ) {
byte k1, k2, k3, k4, k5, k6, k7, k8;
k1 = (byte)(number >> 56);
number -= (ulong)k1 << 56;
k2 = (byte)(number >> 48);
number -= (ulong)k2 << 48;
k3 = (byte)(number >> 40);
number -= (ulong)k3 << 40;
k4 = (byte)(number >> 32);
number -= (ulong)k4 << 32;
k5 = (byte)(number >> 24);
number -= (ulong)k5 << 24;
k6 = (byte)(number >> 16);
number -= (ulong)k6 << 16;
k7 = (byte)(number >> 8);
k8 = (byte)(number - (ulong)(k7 << 8));
fp.Write( k8 );
fp.Write( k7 );
fp.Write( k6 );
fp.Write( k5 );
fp.Write( k4 );
fp.Write( k3 );
fp.Write( k2 );
fp.Write( k1 );
}
public static uint mmioFOURCC( string fcc ) {
char[] str = new char[4];
for ( int i = 0; i < 4; i++ ) {
if ( i < fcc.Length ) {
str[i] = fcc[i];
} else {
str[i] = ' ';
}
}
return mmioFOURCC( str[0], str[1], str[2], str[3] );
}
public static uint mmioFOURCC( char ch0, char ch1, char ch2, char ch3 ) {
return (uint)((byte)(ch0) | ((byte)(ch1) << 8) | ((byte)(ch2) << 16) | ((byte)(ch3) << 24));
}
}
}

View File

@ -0,0 +1,238 @@
/*
* VCM.cs
* Copyright (c) 2007-2009 kbinani
*
* This file is part of Boare.Lib.Media.
*
* Boare.Lib.Media is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* Boare.Lib.Media 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;
using System.Text;
using System.Runtime.InteropServices;
using System.IO;
using bocoree;
namespace Boare.Lib.Media {
public class VCM {
public const uint ICMODE_QUERY = 4;
public const uint ICMF_CHOOSE_ALLCOMPRESSORS = 0x08;
public static readonly uint ICTYPE_VIDEO = Util.mmioFOURCC( 'v', 'i', 'd', 'c' );
public static readonly uint ICTYPE_AUDIO = Util.mmioFOURCC( 'a', 'u', 'd', 'c' );
public const uint ICM_COMPRESS_GET_FORMAT = 0x4004;
[DllImport( "msvfw32.dll" )]
public static extern UInt32 ICOpen( UInt32 fccType, UInt32 fccHandler, uint wMode );
[DllImport( "msvfw32.dll" )]
public static unsafe extern int ICGetInfo( UInt32 hic, ICINFO* icinfo, int size );
/*unsafe public static int ICGetInfo( UInt32 hic, ref ICINFO icinfo, int size ) {
IntPtr pt = new IntPtr( 0 );
int r = w_ICGetInfo( hic, &pt, size );
ICINFO result = new ICINFO();
result = (ICINFO)Marshal.PtrToStructure( pt, result.GetType() );
icinfo = result;
return r;
}*/
[DllImport( "msvfw32.dll" )]
public static extern int ICClose( UInt32 hic );
[DllImport( "msvfw32.dll" )]
public static unsafe extern int ICCompressorChoose(
IntPtr hwnd,
UInt32 uiFlags,
IntPtr pvIn,
IntPtr lpData,
COMPVARS* pc,
string lpszTitle
);
[DllImport( "msvfw32.dll" )]
public static unsafe extern int ICSeqCompressFrameStart(
COMPVARS* pc,
BITMAPINFO* lpbiIn
);
[DllImport( "msvfw32.dll" )]
public static unsafe extern void ICSeqCompressFrameEnd( COMPVARS* pc );
[DllImport( "msvfw32.dll" )]
public static unsafe extern void ICCompressorFree( COMPVARS* pc );
[DllImport( "msvfw32.dll" )]
public static unsafe extern IntPtr ICSeqCompressFrame(
COMPVARS* pc,
UInt32 uiFlags,
IntPtr lpBits,
Int32* pfKey,
Int32* plSize
);
[DllImport( "msvfw32.dll" )]
public static unsafe extern UIntPtr ICSendMessage( UInt32 hic, UInt32 wMsg, IntPtr dw1, IntPtr dw2 );
public static unsafe uint ICCompressGetFormatSize( UInt32 hic, BITMAPINFO* lpbi ) {
return ICCompressGetFormat( hic, lpbi, (BITMAPINFO*)0 );
}
public static unsafe uint ICCompressGetFormat( UInt32 hic, BITMAPINFO* lpbiInput, BITMAPINFO* lpbiOutput ) {
return (uint)ICSendMessage( hic, ICM_COMPRESS_GET_FORMAT, (IntPtr)lpbiInput, (IntPtr)lpbiOutput );
}
}
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
public struct ICINFO {
public UInt32 dwSize;
public UInt32 fccType;
public UInt32 fccHandler;
public UInt32 dwFlags;
public UInt32 dwVersion;
public UInt32 dwVersionICM;
private sz16 szName;
private sz128 szDescription;
private sz128 szDriver;
public string Name {
get {
string t = szName.Value;
//return t.ToCharArray();
return t;
}
}
public string Description {
get {
string t = szDescription.Value;
//return t.ToCharArray();
return t;
}
}
public string Driver {
get {
string t = szDriver.Value;
//return t.ToCharArray();
return t;
}
}
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
private struct sz4 {
UInt16 UInt16_1;
UInt16 UInt16_2;
UInt16 UInt16_3;
UInt16 UInt16_4;
public string Value {
get {
return "" + (char)UInt16_1 + (char)UInt16_2 + (char)UInt16_3 + (char)UInt16_4;
}
}
}
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
private struct sz16 {
sz4 sz4_1;
sz4 sz4_2;
sz4 sz4_3;
sz4 sz4_4;
public string Value {
get {
return sz4_1.Value + sz4_2.Value + sz4_3.Value + sz4_4.Value;
}
}
}
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
private struct sz64 {
sz16 sz16_1;
sz16 sz16_2;
sz16 sz16_3;
sz16 sz16_4;
public string Value {
get {
return sz16_1.Value + sz16_2.Value + sz16_3.Value + sz16_4.Value;
}
}
}
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
private struct sz128 {
sz64 sz64_1;
sz64 sz64_2;
public string Value {
get {
return sz64_1.Value + sz64_2.Value;
}
}
}
}
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
public unsafe struct COMPVARS {
public Int32 cbSize;
public UInt32 dwFlags;
public UInt32 hic; // 元はHIC
public UInt32 fccType;
public UInt32 fccHandler;
public BITMAPINFOHEADER* lpbiIn;
public BITMAPINFOHEADER* lpbiOut;
public void* lpBitsOut;
public void* lpBitsPrev;
public Int32 lFrame;
public Int32 lKey;
public Int32 lDataRate;
public Int32 lQ;
public Int32 lKeyCount;
public void* lpState;
public Int32 cbState;
public override string ToString() {
return "{cbSize=" + cbSize +
",dwFlags=" + dwFlags +
",hic=" + hic +
",fccType=" + fccType +
",fccHandler=" + fccHandler +
",lpbiIn=" + ((int)lpbiIn).ToString() +
",lpbiOut=" + ((int)lpbiOut).ToString() +
",lpBitsOut=" + ((int)lpBitsOut).ToString() +
",lpBitsPrev=" + ((int)lpBitsPrev).ToString() +
",lFrame=" + lFrame +
",lKey=" + lKey +
",lDataRate=" + lDataRate +
",lQ=" + lQ +
",lKeyCount=" + lKeyCount +
",lpState=" + ((int)lpState).ToString() +
",cbState=" + cbState + "}";
}
}
[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct BITMAPINFO {
public BITMAPINFOHEADER bmiHeader;
public RGBQUAD bmiColors;
public unsafe void Write( BinaryWriter bw ) {
bmiHeader.Write( bw );
int remain = (int)((bmiHeader.biSize - sizeof( BITMAPINFOHEADER )) / sizeof( RGBQUAD ));
fixed ( RGBQUAD* rgbq = &bmiColors ) { // これ以外に,「落ちないやり方」が無かった.メモリーが連続していることを祈るのみ
for ( int i = 0; i < remain; i++ ) {
bw.Write( rgbq[i].rgbBlue );
bw.Write( rgbq[i].rgbGreen );
bw.Write( rgbq[i].rgbRed );
bw.Write( rgbq[i].rgbReserved );
}
}
}
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct RGBQUAD {
public byte rgbBlue;
public byte rgbGreen;
public byte rgbRed;
public byte rgbReserved;
}
}

View File

@ -0,0 +1,384 @@
/*
* VFW.cs
* Copyright (c) 2007-2009 kbinani
*
* This file is part of Boare.Lib.Media.
*
* Boare.Lib.Media is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* Boare.Lib.Media 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;
using System.IO;
using System.Runtime.InteropServices;
using bocoree;
namespace Boare.Lib.Media {
public static class VFW {
public static UInt32 streamtypeVIDEO = Util.mmioFOURCC( 'v', 'i', 'd', 's' );
public static UInt32 streamtypeAUDIO = Util.mmioFOURCC( 'a', 'u', 'd', 's' );
[DllImport( "avifil32.dll" )]
public static extern int AVIStreamOpenFromFileW(
out IntPtr ppavi,
[MarshalAs( UnmanagedType.LPWStr )]string szfile,
uint fccType,
int lParam,
int mode,
int dumy
);
[DllImport( "avifil32.dll" )]
public static extern void AVIFileInit();
[DllImport( "avifil32.dll" )]
public static extern int AVIFileOpenW( ref int ptr_pfile, [MarshalAs( UnmanagedType.LPWStr )]string fileName, int flags, int dummy );
[DllImport( "avifil32.dll" )]
public static extern int AVIFileCreateStream(
int ptr_pfile, out IntPtr ptr_ptr_avi, ref AVISTREAMINFOW ptr_streaminfo );
[DllImport( "avifil32.dll" )]
public static extern int AVIMakeCompressedStream(
out IntPtr ppsCompressed, IntPtr aviStream, ref AVICOMPRESSOPTIONS ao, int dummy );
[DllImport( "avifil32.dll" )]
public static extern int AVIStreamSetFormat(
IntPtr aviStream, Int32 lPos, ref BITMAPINFOHEADER lpFormat, Int32 cbFormat );
[DllImport( "avifil32.dll" )]
public static unsafe extern int AVISaveOptions(
IntPtr hwnd, UInt32 flags, int nStreams, IntPtr* ptr_ptr_avi, AVICOMPRESSOPTIONS** ao );
[DllImport( "avifil32.dll" )]
public static extern int AVIStreamWrite(
IntPtr aviStream, Int32 lStart, Int32 lSamples, IntPtr lpBuffer,
Int32 cbBuffer, Int32 dwFlags, Int32 dummy1, Int32 dummy2 );
[DllImport( "avifil32.dll" )]
public static extern int AVIStreamRelease( IntPtr aviStream );
[DllImport( "avifil32.dll" )]
public static extern int AVIFileRelease( int pfile );
[DllImport( "avifil32.dll" )]
public static extern void AVIFileExit();
//Get a pointer to a GETFRAME object (returns 0 on error)
[DllImport( "avifil32.dll" )]
public static extern int AVIStreamGetFrameOpen(
IntPtr pAVIStream,
ref BITMAPINFOHEADER bih );
//Get a stream from an open AVI file
[DllImport( "avifil32.dll" )]
public static extern int AVIFileGetStream(
int pfile,
out IntPtr ppavi,
int fccType,
int lParam );
//Get the start position of a stream
[DllImport( "avifil32.dll", PreserveSig = true )]
public static extern int AVIStreamStart( int pavi );
//Get the length of a stream in frames
[DllImport( "avifil32.dll", PreserveSig = true )]
public static extern int AVIStreamLength( int pavi );
//Get information about an open stream
[DllImport( "avifil32.dll" )]
public static extern int AVIStreamInfo(
int pAVIStream,
ref AVISTREAMINFOW psi,
int lSize );
//Get a pointer to a packed DIB (returns 0 on error)
[DllImport( "avifil32.dll" )]
public static extern int AVIStreamGetFrame(
int pGetFrameObj,
int lPos );
//Release the GETFRAME object
[DllImport( "avifil32.dll" )]
public static extern int AVIStreamGetFrameClose(
int pGetFrameObj );
}
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
public struct AVISTREAMINFOW {
public UInt32 fccType, fccHandler, dwFlags, dwCaps;
public UInt16 wPriority, wLanguage;
public UInt32 dwScale, dwRate,
dwStart, dwLength, dwInitialFrames, dwSuggestedBufferSize,
dwQuality, dwSampleSize, rect_left, rect_top,
rect_right, rect_bottom, dwEditCount, dwFormatChangeCount;
public UInt16 szName0, szName1, szName2, szName3, szName4, szName5,
szName6, szName7, szName8, szName9, szName10, szName11,
szName12, szName13, szName14, szName15, szName16, szName17,
szName18, szName19, szName20, szName21, szName22, szName23,
szName24, szName25, szName26, szName27, szName28, szName29,
szName30, szName31, szName32, szName33, szName34, szName35,
szName36, szName37, szName38, szName39, szName40, szName41,
szName42, szName43, szName44, szName45, szName46, szName47,
szName48, szName49, szName50, szName51, szName52, szName53,
szName54, szName55, szName56, szName57, szName58, szName59,
szName60, szName61, szName62, szName63;
}
[Serializable]
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
public struct AVICOMPRESSOPTIONS {
public UInt32 fccType;
public UInt32 fccHandler;
public UInt32 dwKeyFrameEvery; // only used with AVICOMRPESSF_KEYFRAMES
public UInt32 dwQuality;
public UInt32 dwBytesPerSecond; // only used with AVICOMPRESSF_DATARATE
public UInt32 dwFlags;
public IntPtr lpFormat;
public UInt32 cbFormat;
public IntPtr lpParms;
public UInt32 cbParms;
public UInt32 dwInterleaveEvery;
new public string ToString() {
return "fccType=" + fccType + "\n" +
"fccHandler=" + fccHandler + "\n" +
"dwKeyFrameEvery=" + dwKeyFrameEvery + "\n" +
"dwQuality=" + dwQuality + "\n" +
"dwBytesPerSecond=" + dwBytesPerSecond + "\n" +
"dwFlags=" + dwFlags + "\n" +
"lpFormat=" + lpFormat + "\n" +
"cbFormat=" + cbFormat + "\n" +
"lpParms=" + lpParms + "\n" +
"cbParms=" + cbParms + "\n" +
"dwInterleaveEvery=" + dwInterleaveEvery;
}
}
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
public struct AVIStreamHeader {
public uint fccType;// character(len = 4) fccType
public uint fccHandler;//character(len = 4) fccHandler
public uint dwFlags;
public uint dwReserved1;
public uint dwInitialFrames;
public uint dwScale;
public uint dwRate;
public uint dwStart;
public uint dwLength;
public uint dwSuggestedBufferSize;
public uint dwQuality;
public uint dwSampleSize;
public void Write( Stream s ) {
bool bigendian = !BitConverter.IsLittleEndian;
byte[] b;
b = BitConverter.GetBytes( fccType );
s.Write( b, 0, 4 );
b = BitConverter.GetBytes( fccHandler );
s.Write( b, 0, 4 );
b = BitConverter.GetBytes( dwFlags );
if ( bigendian ) {
Array.Reverse( b );
}
s.Write( b, 0, 4 );
b = BitConverter.GetBytes( dwReserved1 );
if ( bigendian ) {
Array.Reverse( b );
}
s.Write( b, 0, 4 );
b = BitConverter.GetBytes( dwInitialFrames );
if ( bigendian ) {
Array.Reverse( b );
}
s.Write( b, 0, 4 );
b = BitConverter.GetBytes( dwScale );
if ( bigendian ) {
Array.Reverse( b );
}
s.Write( b, 0, 4 );
b = BitConverter.GetBytes( dwRate );
if ( bigendian ) {
Array.Reverse( b );
}
s.Write( b, 0, 4 );
b = BitConverter.GetBytes( dwStart );
if ( bigendian ) {
Array.Reverse( b );
}
s.Write( b, 0, 4 );
b = BitConverter.GetBytes( dwLength );
if ( bigendian ) {
Array.Reverse( b );
}
s.Write( b, 0, 4 );
b = BitConverter.GetBytes( dwSuggestedBufferSize );
if ( bigendian ) {
Array.Reverse( b );
}
s.Write( b, 0, 4 );
b = BitConverter.GetBytes( dwQuality );
if ( bigendian ) {
Array.Reverse( b );
}
s.Write( b, 0, 4 );
b = BitConverter.GetBytes( dwSampleSize );
if ( bigendian ) {
Array.Reverse( b );
}
s.Write( b, 0, 4 );
}
}
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
public struct MainAVIHeader {
public uint dwMicroSecPerFrame; // specifies the period between video frames. This value indicates the overall timing for the file.
public uint dwMaxBytesPerSec; // specifies the approximate maximum data rate of the file.
public uint dwReserved1;
public uint dwFlags; // AVIF_HASINDEX, AVIF_MUSTUSEINDEX, AVIF_ISINTERLEAVED, AVIF_WASCAPTUREFILE, AVIF_COPYRIGHTED
public uint dwTotalFrames; // specifies the total number of frames of data in file.
public uint dwInitialFrames; // used for interleaved files. If you are creating interleaved files, specify the number of frames in the file prior to the initial frame of the AVI sequence in this field.
public uint dwStreams; // specifies the number of streams in the file. For example, a file with audio and video has 2 streams.
public uint dwSuggestedBufferSize; // specifies the suggested buffer size for reading the file.
public uint dwWidth; // specify the width of the AVI file in pixels.
public uint dwHeight; // specify the height of the AVI file in pixels.
public uint dwScale; // used to specify the general time scale that the file will use.
public uint dwRate; // used to specify the general time scale that the file will use.
public uint dwStart; // specify the starting time of the AVI file and the length of the file. The units are
public uint dwLength; // defined by dwRate and dwScale. The dwStart field is usually set to zero.
public void Write( Stream s ) {
byte[] b;
bool bigendian = !BitConverter.IsLittleEndian;
// dwMicroSecPerFrame
b = BitConverter.GetBytes( dwMicroSecPerFrame );
if ( bigendian ) {
Array.Reverse( b );
}
s.Write( b, 0, 4 );
// dwMaxBytesPerSec
b = BitConverter.GetBytes( dwMaxBytesPerSec );
if ( bigendian ) {
Array.Reverse( b );
}
s.Write( b, 0, 4 );
// dwReserved1
b = BitConverter.GetBytes( dwReserved1 );
if ( bigendian ) {
Array.Reverse( b );
}
s.Write( b, 0, 4 );
// dwFlags
b = BitConverter.GetBytes( dwFlags );
if ( bigendian ) {
Array.Reverse( b );
}
s.Write( b, 0, 4 );
// dwtotalFrames
b = BitConverter.GetBytes( dwTotalFrames );
if ( bigendian ) {
Array.Reverse( b );
}
s.Write( b, 0, 4 );
// dwInitialFrames
b = BitConverter.GetBytes( dwInitialFrames );
if ( bigendian ) {
Array.Reverse( b );
}
s.Write( b, 0, 4 );
// dwStreams
b = BitConverter.GetBytes( dwStreams );
if ( bigendian ) {
Array.Reverse( b );
}
s.Write( b, 0, 4 );
// dwSuggestedBufferSize
b = BitConverter.GetBytes( dwSuggestedBufferSize );
if ( bigendian ) {
Array.Reverse( b );
}
s.Write( b, 0, 4 );
// dwWidth
b = BitConverter.GetBytes( dwWidth );
if ( bigendian ) {
Array.Reverse( b );
}
s.Write( b, 0, 4 );
// dwHeight
b = BitConverter.GetBytes( dwHeight );
if ( bigendian ) {
Array.Reverse( b );
}
s.Write( b, 0, 4 );
// dwScale
b = BitConverter.GetBytes( dwScale );
if ( bigendian ) {
Array.Reverse( b );
}
s.Write( b, 0, 4 );
// dwrate
b = BitConverter.GetBytes( dwRate );
if ( bigendian ) {
Array.Reverse( b );
}
s.Write( b, 0, 4 );
// dwStart
b = BitConverter.GetBytes( dwStart );
if ( bigendian ) {
Array.Reverse( b );
}
s.Write( b, 0, 4 );
// dwLength
b = BitConverter.GetBytes( dwLength );
if ( bigendian ) {
Array.Reverse( b );
}
s.Write( b, 0, 4 );
}
}
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
public struct BITMAPFILEHEADER {
public Int16 bfType; //"magic cookie" - must be "BM"
public Int32 bfSize;
public Int16 bfReserved1;
public Int16 bfReserved2;
public Int32 bfOffBits;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,626 @@
/*
* WavePlay.cs
* Copyright (c) 2009 kbinani
*
* This file is part of Boare.Lib.Media.
*
* Boare.Lib.Media is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* Boare.Lib.Media 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.Runtime.InteropServices;
using bocoree;
namespace Boare.Lib.Media {
public delegate void FirstBufferWrittenCallback();
public unsafe class WavePlay {
const int _NUM_BUF = 3; // バッファの数
int s_block_size; // 1個のバッファのサイズ(サンプル)
int s_sample_rate; // サンプリングレート
WAVEFORMATEX s_wave_formatx; // WAVEファイルヘッダ
//IntPtr s_ptr_wave_formatx;
IntPtr s_hwave_out; // WAVE再生デバイス
WAVEHDR[] s_wave_header = new WAVEHDR[_NUM_BUF];// WAVEヘッダ
IntPtr[] s_ptr_wave_header = new IntPtr[_NUM_BUF];
uint*[] s_wave = new uint*[_NUM_BUF]; // バッファ
IntPtr[] s_ptr_wave = new IntPtr[_NUM_BUF];
bool[] s_done = new bool[_NUM_BUF];
int s_current_buffer; // 次回書き込むべきバッファのインデクス
uint s_processed_count; // 初回はバッファを_NUM_BUF個全部埋めなければいけないので、最初の _NUM_BUF + 1 回はカウントを行う。そのためのカウンタ
bool s_abort_required; // 再生の中断が要求された時立つフラグ
int s_buffer_loc; // 書き込み中のバッファ内の、現在位置
bool s_playing; // 再生中かどうかを表すフラグ
int s_error_samples; // appendされた波形データの内、先頭のs_error_samples分を省く。通常の使い方なら常に0だが、vocaloid2 vstiで使う場合、プリセンド分を除いてwaveOutWriteしなければいけないので非0になる。
int s_last_buffer; // 最後に再生されるバッファの番号。負値の場合、append_lastが未だ呼ばれていないことを意味する。
FirstBufferWrittenCallback s_first_buffer_written_callback; // 最初のバッファが書き込まれたとき呼び出されるコールバック関数
WaveReader[] s_wave_reader;
int s_num_wave_reader; // s_wave_readerの個数
float*[] s_another_wave_l;
IntPtr[] s_ptr_another_wave_l;
float*[] s_another_wave_r;
IntPtr[] s_ptr_another_wave_r;
long s_wave_read_offset_samples;
float* s_wave_buffer_l;
IntPtr s_ptr_wave_buffer_l;
float* s_wave_buffer_r;
IntPtr s_ptr_wave_buffer_r;
delegateWaveOutProc s_wave_callback;
/// コールバック関数
void wave_callback( IntPtr hwo, uint uMsg, uint dwInstance, uint dwParam1, uint dwParam2 ) {
#if DEBUG
Console.WriteLine( "WavePlay.wave_callback; uMsg=" + uMsg );
#endif
if ( uMsg == windows.MM_WOM_DONE ) {
int index_done = 0;
WAVEHDR whdr = (WAVEHDR)Marshal.PtrToStructure( new IntPtr( dwParam1 ), typeof( WAVEHDR ) );
int dwuser = whdr.dwUser.ToInt32();
if ( dwuser >= _NUM_BUF ) {
index_done = dwuser - _NUM_BUF;
} else {
index_done = dwuser;
}
#if DEBUG
bocoree.debug.push_log( "dwuser=" + dwuser );
bocoree.debug.push_log( "index_done=" + index_done );
#endif
s_done[index_done] = true;
if ( s_last_buffer == index_done ) {
s_playing = false;
}
if ( dwuser >= _NUM_BUF ) {
s_wave_header[index_done].dwUser = new IntPtr( index_done );
}
#if DEBUG
bocoree.debug.push_log( "whdr.dwUser=" + whdr.dwUser.ToInt32() );
bocoree.debug.push_log( "dwParam1=0x" + Convert.ToString( dwParam1, 16 ) + "; dwParam2=0x" + Convert.ToString( dwParam2, 16 ) );
#endif
}
}
void append_cor( float** a_data, uint length, double amp_left, double amp_right, bool is_last_mode ) {
#if DEBUG
bocoree.debug.push_log( "append_cor *************************************************************" );
bocoree.debug.push_log( " length=" + length );
bocoree.debug.push_log( " s_hwave_out=0x" + Convert.ToString( s_hwave_out.ToInt32(), 16 ) );
#endif
s_playing = true;
int jmax = (int)length;
int remain = 0;
IntPtr ptr_data = IntPtr.Zero;
IntPtr ptr_data0 = IntPtr.Zero;
IntPtr ptr_data1 = IntPtr.Zero;
ptr_data = Marshal.AllocHGlobal( sizeof( float* ) * 2 );
float** data = (float**)ptr_data.ToPointer();// new float*[2];
bool cleaning_required = false;
if ( s_error_samples > 0 ) {
if ( s_error_samples >= length ) {
s_error_samples -= (int)length;
return;
}
cleaning_required = true;
int actual_length = (int)length - s_error_samples;
#if DEBUG
bocoree.debug.push_log( " actual_length=" + actual_length );
#endif
ptr_data0 = Marshal.AllocHGlobal( sizeof( float ) * actual_length );
ptr_data1 = Marshal.AllocHGlobal( sizeof( float ) * actual_length );
data[0] = (float*)ptr_data0.ToPointer();
data[1] = (float*)ptr_data1.ToPointer();
for ( int i = 0; i < actual_length; i++ ) {
data[0][i] = a_data[0][i + s_error_samples];
data[1][i] = a_data[1][i + s_error_samples];
}
s_error_samples = 0;
length = (uint)actual_length;
jmax = (int)length;
} else {
data = a_data;
}
if ( length + s_buffer_loc >= s_block_size ) {
jmax = s_block_size - s_buffer_loc;
remain = (int)length - (int)jmax;
}
float aright = (float)amp_right;
float aleft = (float)amp_left;
for ( int j = 0; j < jmax; j++ ) {
s_wave_buffer_l[j + s_buffer_loc] = data[1][j];
s_wave_buffer_r[j + s_buffer_loc] = data[0][j];
}
s_buffer_loc += jmax;
if ( s_buffer_loc >= s_block_size ) {
// バッファー充填完了バッファーを転送し、waveOutWriteが書き込めるタイミングまで待機
#if DEBUG
bocoree.debug.push_log( "append_cor; waiting(1) " + s_current_buffer + "..." );
#endif
while ( true ) {
if ( s_abort_required ) {
s_abort_required = false;
goto clean_and_exit;
}
if ( s_done[s_current_buffer] ) {
break;
}
}
#if DEBUG
bocoree.debug.push_log( "append_cor; ...exit" );
#endif
s_processed_count++;
mix( (int)s_processed_count, aleft, aright );
if ( s_processed_count == _NUM_BUF ) {
s_done[0] = false;
#if DEBUG
bocoree.debug.push_log( "calling waveOutWrite...; s_hawve_out=0x" + Convert.ToString( s_hwave_out.ToInt32(), 16 ) );
#endif
uint ret = windows.waveOutWrite( s_hwave_out, ref s_wave_header[0], (uint)sizeof( WAVEHDR ) );
#if DEBUG
bocoree.debug.push_log( "...done; ret=" + ret );
#endif
#if DEBUG
bocoree.debug.push_log( "(s_first_buffer_wirtten_callback==null)=" + (s_first_buffer_written_callback == null) );
#endif
if ( s_first_buffer_written_callback != null ) {
#if DEBUG
bocoree.debug.push_log( "append_cor; calling s_first_buffer_written_callback" );
#endif
s_first_buffer_written_callback();
}
for ( int buffer_index = 1; buffer_index < _NUM_BUF; buffer_index++ ) {
s_done[buffer_index] = false;
#if DEBUG
bocoree.debug.push_log( "calling waveOutWrite...; s_hawve_out=0x" + Convert.ToString( s_hwave_out.ToInt32(), 16 ) );
#endif
uint ret2 = windows.waveOutWrite( s_hwave_out, ref s_wave_header[buffer_index], (uint)sizeof( WAVEHDR ) );
#if DEBUG
bocoree.debug.push_log( "...done; ret2=" + ret2 );
#endif
}
s_current_buffer = _NUM_BUF - 1;
} else if ( s_processed_count > _NUM_BUF ) {
s_done[s_current_buffer] = false;
#if DEBUG
bocoree.debug.push_log( "calling waveOutWrite...; s_hawve_out=0x" + Convert.ToString( s_hwave_out.ToInt32(), 16 ) );
#endif
uint ret3 = windows.waveOutWrite( s_hwave_out, ref s_wave_header[s_current_buffer], (uint)sizeof( WAVEHDR ) );
#if DEBUG
bocoree.debug.push_log( "...done; ret3=" + ret3 );
#endif
}
s_current_buffer++;
if ( s_current_buffer >= _NUM_BUF ) {
s_current_buffer = 0;
}
s_buffer_loc = 0;
}
if ( remain > 0 ) {
for ( int j = jmax; j < length; j++ ) {
s_wave_buffer_l[j - jmax] = data[1][j];
s_wave_buffer_r[j - jmax] = data[0][j];
}
if ( is_last_mode ) {
for ( int j = (int)length - jmax; j < s_block_size; j++ ) {
s_wave_buffer_l[j] = 0.0f;
s_wave_buffer_r[j] = 0.0f;
}
}
s_buffer_loc = remain;
}
if ( is_last_mode ) {
if ( s_processed_count < _NUM_BUF ) {
// _NUM_BUFブロック分のデータを未だ全て受信していない場合。バッファが未だひとつも書き込まれていないので
// 0番のブロックから順に書き込む
s_processed_count++;
mix( (int)s_processed_count, aleft, aright );
s_done[0] = false;
#if DEBUG
bocoree.debug.push_log( "calling waveOutWrite...; s_hawve_out=0x" + Convert.ToString( s_hwave_out.ToInt32(), 16 ) );
#endif
uint ret35 = windows.waveOutWrite( s_hwave_out, ref s_wave_header[0], (uint)sizeof( WAVEHDR ) );
#if DEBUG
bocoree.debug.push_log( "...done; ret35=" + ret35 );
bocoree.debug.push_log( "(s_first_buffer_written_callback==null)=" + (s_first_buffer_written_callback == null) );
#endif
if ( s_first_buffer_written_callback != null ) {
#if DEBUG
bocoree.debug.push_log( "append_cor; calling s_first_buffer_written_callback" );
#endif
s_first_buffer_written_callback();
}
for ( int i = 1; i < _NUM_BUF - 1; i++ ) {
s_processed_count++;
mix( (int)s_processed_count, aleft, aright );
s_done[i] = false;
#if DEBUG
bocoree.debug.push_log( "calling waveOutWrite...; s_hawve_out=0x" + Convert.ToString( s_hwave_out.ToInt32(), 16 ) );
#endif
uint ret36 = windows.waveOutWrite( s_hwave_out, ref s_wave_header[i], (uint)sizeof( WAVEHDR ) );
#if DEBUG
bocoree.debug.push_log( "...done; ret36=" + ret36 );
#endif
}
}
ulong zero = MAKELONG( 0, 0 );
for ( int j = s_buffer_loc; j < s_block_size; j++ ) {
s_wave_buffer_l[j] = 0.0f;
s_wave_buffer_r[j] = 0.0f;
}
#if DEBUG
bocoree.debug.push_log( "append_cor; waiting(3) " + s_current_buffer + "..." );
#endif
while ( !s_done[s_current_buffer] ) {
if ( s_abort_required ) {
s_abort_required = false;
goto clean_and_exit;
}
}
#if DEBUG
bocoree.debug.push_log( "append_cor; ...exit" );
#endif
s_processed_count++;
mix( (int)s_processed_count, aleft, aright );
s_done[s_current_buffer] = false;
#if DEBUG
bocoree.debug.push_log( "calling waveOutWrite...; s_hawve_out=0x" + Convert.ToString( s_hwave_out.ToInt32(), 16 ) );
#endif
uint ret4 = windows.waveOutWrite( s_hwave_out, ref s_wave_header[s_current_buffer], (uint)sizeof( WAVEHDR ) );
#if DEBUG
bocoree.debug.push_log( "...done; ret4=" + ret4 );
#endif
}
clean_and_exit:
if ( is_last_mode ) {
s_last_buffer = s_current_buffer;
}
if ( cleaning_required ) {
Marshal.FreeHGlobal( ptr_data0 ); //delete [] data[0];
Marshal.FreeHGlobal( ptr_data1 ); //delete [] data[1];
Marshal.FreeHGlobal( ptr_data ); //delete [] data;
}
}
void mix( int processed_count, float amp_left, float amp_right ) {
int current_buffer = (processed_count - 1) % _NUM_BUF;
for ( int k = 0; k < s_num_wave_reader; k++ ) {
s_wave_reader[k].Read( s_block_size * (processed_count - 1) + (int)s_wave_read_offset_samples,
s_block_size,
out s_ptr_another_wave_l[k],
out s_ptr_another_wave_r[k] );
}
for ( int i = 0; i < s_block_size; i++ ) {
float l = s_wave_buffer_l[i] * amp_left;
float r = s_wave_buffer_r[i] * amp_right;
for ( int k = 0; k < s_num_wave_reader; k++ ) {
l += s_another_wave_l[k][i];
r += s_another_wave_r[k][i];
}
s_wave[current_buffer][i] = MAKELONG( (ushort)(r * 32768.0f), (ushort)(l * 32768.0f) );
}
}
string util_get_errmsg( uint msg ) {
//IntPtr ptr_err = Marshal.AllocHGlobal( sizeof( byte ) * 260 );
//byte* err = (byte*)ptr_err.ToPointer();
//System.Text.StringBuilder sb = new System.Text.StringBuilder( 260 );
string ret = "";
windows.mciGetErrorStringA( msg, ret, 260 );
/*int len = 260;
for ( int i = 1; i < 260; i++ ) {
if ( err[i] == '\0' ) {
len = i - 1;
break;
}
}*/
//string ret = new string( err );
//string ret = sb.ToString();
//Marshal.FreeHGlobal( ptr_err );
return ret;
}
private WavePlay() {
}
/// 初期化関数
public WavePlay( int block_size, int sample_rate ) {
#if DEBUG
Console.WriteLine( "waveplay..ctor" );
#endif
s_block_size = block_size;
s_sample_rate = sample_rate;
//s_ptr_wave_formatx = Marshal.AllocHGlobal( sizeof( WAVEFORMATEX ) );
s_wave_formatx = new WAVEFORMATEX();
//Marshal.PtrToStructure( s_ptr_wave_formatx, s_wave_formatx );
s_wave_formatx.cbSize = (ushort)sizeof( WAVEFORMATEX );
#if DEBUG
Console.WriteLine( " s_wave_fomratx.cbSize=" + s_wave_formatx.cbSize );
Console.WriteLine( " sizeof( WAVEHDR )=" + sizeof( WAVEHDR ) );
#endif
s_wave_formatx.wFormatTag = windows.WAVE_FORMAT_PCM;
s_wave_formatx.nChannels = 2;
s_wave_formatx.wBitsPerSample = 16;
s_wave_formatx.nBlockAlign = (ushort)(s_wave_formatx.nChannels * s_wave_formatx.wBitsPerSample / 8);
s_wave_formatx.nSamplesPerSec = (uint)s_sample_rate;
s_wave_formatx.nAvgBytesPerSec = s_wave_formatx.nSamplesPerSec * s_wave_formatx.nBlockAlign;
s_wave_callback = new delegateWaveOutProc( wave_callback );
s_hwave_out = IntPtr.Zero;
Console.WriteLine( " calling waveOutOpen..." );
uint ret = windows.waveOutOpen( ref s_hwave_out,
windows.WAVE_MAPPER,
ref s_wave_formatx,
s_wave_callback,
IntPtr.Zero,
(uint)windows.CALLBACK_FUNCTION );
Console.WriteLine( " ...done; ret=" + ret );
#if DEBUG
bocoree.debug.push_log( " s_hwave_out=0x" + Convert.ToString( s_hwave_out.ToInt32(), 16 ) );
#endif
for ( int k = 0; k < _NUM_BUF; k++ ) {
s_ptr_wave[k] = Marshal.AllocHGlobal( sizeof( uint ) * s_block_size );
s_wave[k] = (uint*)s_ptr_wave[k];// = (ulong*)calloc( sizeof( ulong ), s_block_size );
s_ptr_wave_header[k] = Marshal.AllocHGlobal( sizeof( WAVEHDR ) );
s_wave_header[k] = (WAVEHDR)Marshal.PtrToStructure( s_ptr_wave_header[k], typeof( WAVEHDR ) );
s_wave_header[k].lpData = s_ptr_wave[k];
s_wave_header[k].dwBufferLength = (uint)(sizeof( uint ) * s_block_size);
s_wave_header[k].dwFlags = windows.WHDR_BEGINLOOP | windows.WHDR_ENDLOOP;
s_wave_header[k].dwLoops = 1;
#if DEBUG
Console.WriteLine( "calling waveOutPrepareHeader..." );
#endif
uint ret2 = windows.waveOutPrepareHeader( s_hwave_out, ref s_wave_header[k], (uint)sizeof( WAVEHDR ) );
#if DEBUG
Console.WriteLine( "...done; ret2=" + ret2 );
#endif
s_wave_header[k].dwUser = new IntPtr( k );
}
#if DEBUG
bocoree.debug.push_log( " exit waveplay..ctor; s_hwave_out=0x" + Convert.ToString( s_hwave_out.ToInt32(), 16 ) );
#endif
}
/// 波形データをバッファに追加する。バッファが再生中などの理由で即座に書き込めない場合、バッファが書き込み可能となるまで待機させられる
public void append( float** data, uint length, double amp_left, double amp_right ) {
append_cor( data, length, amp_left, amp_right, false );
}
public void flush_and_exit( double amp_left, double amp_right ) {
append_cor( (float**)0, 0, amp_left, amp_right, true );
}
/// 再生中断を要求する
public void abort() {
s_abort_required = true;
reset();
for ( int k = 0; k < _NUM_BUF; k++ ) {
if ( s_ptr_wave[k] != IntPtr.Zero ) {
for ( int i = 0; i < s_block_size; i++ ) {
s_wave[k][i] = 0;
}
//memset( s_wave[k], 0, s_block_size * sizeof( ulong ) );
}
}
s_buffer_loc = 0;
s_current_buffer = 0;
s_processed_count = 0;
}
/// 現在の再生位置を取得する。再生中でない場合負の値となる。
public float get_play_time() {
#if DEBUG
bocoree.debug.push_log( "WavePlay.get_play_time" );
#endif
if ( s_playing ) {
MMTIME mmt = new MMTIME();
mmt.cb = (uint)sizeof( MMTIME );
mmt.wType = windows.TIME_MS;
uint ret = windows.waveOutGetPosition( s_hwave_out, ref mmt, (uint)sizeof( MMTIME ) );
#if DEBUG
bocoree.debug.push_log( " ret=" + ret );
#endif
float ms = 0.0f;
switch ( mmt.wType ) {
case windows.TIME_MS:
return mmt.ms * 0.001f;
case windows.TIME_SAMPLES:
return (float)mmt.sample / (float)s_wave_formatx.nSamplesPerSec;
case windows.TIME_BYTES:
return (float)mmt.cb / (float)s_wave_formatx.nAvgBytesPerSec;
default:
return -1.0f;
}
} else {
return -1.0f;
}
}
/// リセットする。abort関数でも呼び出される。
public void reset() {
s_playing = false;
if ( s_hwave_out.ToInt32() != 0 ) {
for ( int k = 0; k < _NUM_BUF; k++ ) {
s_wave_header[k].dwUser = new IntPtr( _NUM_BUF + k );
}
windows.waveOutReset( s_hwave_out );
uint zero = MAKELONG( 0, 0 );
for ( int k = 0; k < _NUM_BUF; k++ ) {
for ( int i = 0; i < s_block_size; i++ ) {
s_wave[k][i] = zero;
}
}
}
for ( int i = 0; i < s_num_wave_reader; i++ ) {
s_wave_reader[i].Close();
}
}
/// 再生のための準備を行う。この関数を呼び出した後は、バッファが再生開始されるまでget_play_timeの戻り値は0となる負値にならない
/// 戻り値は、filesに指定されたファイルの内、最も再生時間の長いwaveファイルの、合計サンプル数
public int on_your_mark( string[] files, long wave_read_offset_samples ) {
#if DEBUG
bocoree.debug.push_log( "on_your_mark; s_hwave_out=0x" + Convert.ToString( s_hwave_out.ToInt32(), 16 ) );
#endif
int num_files = files.Length;
reset();
s_wave_read_offset_samples = wave_read_offset_samples;
for ( int k = 0; k < _NUM_BUF; k++ ) {
s_wave_header[k].dwUser = new IntPtr( k );
s_done[k] = true;
}
s_abort_required = false;
s_buffer_loc = 0;
s_current_buffer = 0;
s_processed_count = 0;
s_playing = true;
s_last_buffer = -1;
if ( (int)s_ptr_wave_buffer_l.ToPointer() == 0 ) {
s_ptr_wave_buffer_l = Marshal.AllocHGlobal( sizeof( float ) * s_block_size );// s_wave_buffer_l = new float[s_block_size];
s_wave_buffer_l = (float*)s_ptr_wave_buffer_l.ToPointer();
}
if ( (int)s_ptr_wave_buffer_r.ToPointer() == 0 ) {
s_ptr_wave_buffer_r = Marshal.AllocHGlobal( sizeof( float ) * s_block_size ); //s_wave_buffer_r = new float[s_block_size];
s_wave_buffer_r = (float*)s_ptr_wave_buffer_r.ToPointer();
}
if ( s_wave_reader != null ) {
for ( int i = 0; i < s_num_wave_reader; i++ ) {
s_wave_reader[i].Close();
}
//delete [] s_wave_reader;
}
s_wave_reader = new WaveReader[num_files];
if ( s_another_wave_l != null ) {
for ( int i = 0; i < s_num_wave_reader; i++ ) {
Marshal.FreeHGlobal( s_ptr_another_wave_l[i] );// delete [] s_another_wave_l[i];
}
//delete [] s_another_wave_l;
}
if ( s_another_wave_r != null ) {
for ( int i = 0; i < s_num_wave_reader; i++ ) {
Marshal.FreeHGlobal( s_ptr_another_wave_r[i] ); //delete [] s_another_wave_r[i];
}
//delete [] s_another_wave_r;
}
s_another_wave_l = new float*[num_files];
s_another_wave_r = new float*[num_files];
int max_samples = 0;
for ( int i = 0; i < num_files; i++ ) {
// waveファイルヘッダを読込む
/*int len = files[i].Length;
wchar_t *name = new wchar_t[len + 1];
array<wchar_t> ^buf = files[i]->ToCharArray();
for( int k = 0; k < len; k++ ){
name[k] = buf[k];
}
name[len] = '\0';*/
s_wave_reader[i].Open( files[i] );
int samples = s_wave_reader[i].TotalSamples;
if ( samples > max_samples ) {
max_samples = samples;
}
//delete [] name;
// バッファを用意
s_ptr_another_wave_l[i] = Marshal.AllocHGlobal( sizeof( float ) * s_block_size );
s_another_wave_l[i] = (float*)s_ptr_another_wave_l[i].ToPointer();
s_ptr_another_wave_r[i] = Marshal.AllocHGlobal( sizeof( float ) * s_block_size );
s_another_wave_r[i] = (float*)s_ptr_another_wave_r[i].ToPointer();
//s_another_wave_l[i] = new float[s_block_size];
//s_another_wave_r[i] = new float[s_block_size];
}
s_num_wave_reader = num_files;
return max_samples;
}
public void set_error_samples( int error_samples ) {
s_error_samples = error_samples;
}
/// コールバック関数を設定する
public void set_first_buffer_written_callback( FirstBufferWrittenCallback proc ) {
s_first_buffer_written_callback = proc;
}
public void terminate() {
if ( s_hwave_out.ToInt32() != 0 ) {
windows.waveOutReset( s_hwave_out );
#if DEBUG
bocoree.debug.push_log( "waveplay::terminate; waveOutReset" );
#endif
for ( int k = 0; k < _NUM_BUF; k++ ) {
windows.waveOutUnprepareHeader( s_hwave_out, ref s_wave_header[k], (uint)sizeof( WAVEHDR ) );
}
windows.waveOutClose( s_hwave_out );
}
for ( int i = 0; i < _NUM_BUF; i++ ) {
if ( s_ptr_wave[i].ToInt32() != 0 ) {
Marshal.FreeHGlobal( s_ptr_wave[i] ); //delete [] s_wave[i];
}
}
}
/// 現在再生中かどうかを取得する
public bool is_alive() {
return s_playing;
}
/// ブロックサイズを変更します
public bool change_block_size( int block_size ) {
if ( s_playing ) {
return false;
}
if ( block_size <= 0 ) {
return false;
}
for ( int k = 0; k < _NUM_BUF; k++ ) {
if ( s_ptr_wave[k].ToInt32() != 0 ) {
Marshal.FreeHGlobal( s_ptr_wave[k] );// delete [] s_wave[k];
}
s_ptr_wave[k] = Marshal.AllocHGlobal( sizeof( uint ) * block_size );
s_wave[k] = (uint*)s_ptr_wave[k].ToPointer();// calloc( sizeof( ulong ), block_size );
s_wave_header[k].lpData = s_ptr_wave[k];
s_wave_header[k].dwBufferLength = (uint)(sizeof( uint ) * block_size);
}
// s_wave_buffer_l, s_wave_buffer_rは、NULLならばon_your_markで初期化されるので、開放だけやっておけばOK
if ( s_ptr_wave_buffer_l.ToInt32() != 0 ) {
Marshal.FreeHGlobal( s_ptr_wave_buffer_l ); //delete [] s_wave_buffer_l;
}
if ( s_ptr_wave_buffer_r.ToInt32() != 0 ) {
Marshal.FreeHGlobal( s_ptr_wave_buffer_r ); //delete[] s_wave_buffer_r;
}
// s_another_wave_l, s_another_wave_rは、on_your_markで全自動で初期化されるので特に操作の必要なし
s_block_size = block_size;
return true;
}
uint MAKELONG( ushort a, ushort b ) {
return (uint)(a & 0xffff) | (uint)((b & 0xffff) << 16);
}
}
}

View File

@ -0,0 +1,283 @@
/*
* WaveReader.cs
* Copyright (c) 2009 kbinani
*
* This file is part of Boare.Lib.Media.
*
* Boare.Lib.Media is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* Boare.Lib.Media 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.Runtime.InteropServices;
namespace Boare.Lib.Media {
public class WaveReader : IDisposable{
private int m_channel;
private int m_byte_per_sample;
private bool m_opened;
private FileStream m_stream;
private int m_total_samples;
public WaveReader() {
m_opened = false;
}
public WaveReader( string file ) {
Open( file );
}
public void Dispose() {
Close();
}
public bool Open( string file ) {
if ( m_opened ) {
m_stream.Close();
}
m_stream = new FileStream( file, FileMode.Open );
// RIFF
byte[] buf = new byte[4];
m_stream.Read( buf, 0, 4 );
if ( buf[0] != 'R' || buf[1] != 'I' || buf[2] != 'F' || buf[3] != 'F' ) {
m_stream.Close();
return false;
}
// ファイルサイズ - 8最後に記入
m_stream.Read( buf, 0, 4 );
// WAVE
m_stream.Read( buf, 0, 4 );
if ( buf[0] != 'W' || buf[1] != 'A' || buf[2] != 'V' || buf[3] != 'E' ) {
m_stream.Close();
return false;
}
// fmt
m_stream.Read( buf, 0, 4 );
if ( buf[0] != 'f' || buf[1] != 'm' || buf[2] != 't' || buf[3] != ' ' ) {
m_stream.Close();
return false;
}
// fmt チャンクのサイズ
m_stream.Read( buf, 0, 4 );
// format ID
m_stream.Read( buf, 0, 2 );
// チャンネル数
m_stream.Read( buf, 0, 2 );
m_channel = buf[1] << 8 | buf[0];
// サンプリングレート
m_stream.Read( buf, 0, 4 );
// データ速度
m_stream.Read( buf, 0, 4 );
// ブロックサイズ
m_stream.Read( buf, 0, 2 );
// サンプルあたりのビット数
m_stream.Read( buf, 0, 2 );
int bit_per_sample = buf[1] << 8 | buf[0];
m_byte_per_sample = bit_per_sample / 8;
// 拡張部分
m_stream.Read( buf, 0, 2 );
// data
m_stream.Read( buf, 0, 4 );
if ( buf[0] != 'd' || buf[1] != 'a' || buf[2] != 't' || buf[3] != 'a' ) {
m_stream.Close();
return false;
}
// size of data chunk
m_stream.Read( buf, 0, 4 );
int size = BitConverter.ToInt32( buf, 0 );
m_total_samples = size / (m_channel * m_byte_per_sample);
m_opened = true;
return true;
}
public int TotalSamples {
get {
return m_total_samples;
}
}
public void Read( int start, int length, out float[] left, out float[] right ) {
left = new float[length];
right = new float[length];
if ( !m_opened ) {
return;
}
int loc = 0x2e + m_byte_per_sample * m_channel * start;
m_stream.Seek( loc, SeekOrigin.Begin );
if ( m_byte_per_sample == 2 ) {
if ( m_channel == 2 ) {
byte[] buf = new byte[4];
for ( int i = 0; i < length; i++ ) {
int ret = m_stream.Read( buf, 0, 4 );
if ( ret < 4 ) {
for ( int j = i; j < length; j++ ) {
left[j] = 0.0f;
right[j] = 0.0f;
}
break;
}
short l = (short)(buf[0] | buf[1] << 8);
short r = (short)(buf[2] | buf[3] << 8);
left[i] = l / 32768.0f;
right[i] = r / 32768.0f;
}
} else {
byte[] buf = new byte[2];
for ( int i = 0; i < length; i++ ) {
int ret = m_stream.Read( buf, 0, 2 );
if ( ret < 2 ) {
for ( int j = i; j < length; j++ ) {
left[j] = 0.0f;
right[j] = 0.0f;
}
break;
}
short l = (short)(buf[0] | buf[1] << 8);
left[i] = l / 32768.0f;
right[i] = left[i];
}
}
} else {
if ( m_channel == 2 ) {
byte[] buf = new byte[2];
for ( int i = 0; i < length; i++ ) {
int ret = m_stream.Read( buf, 0, 2 );
if ( ret < 2 ) {
for ( int j = i; j < length; j++ ) {
left[j] = 0.0f;
right[j] = 0.0f;
}
break;
}
left[i] = (buf[0] - 64.0f) / 64.0f;
right[i] = (buf[1] - 64.0f) / 64.0f;
}
} else {
byte[] buf = new byte[1];
for ( int i = 0; i < length; i++ ) {
int ret = m_stream.Read( buf, 0, 1 );
if ( ret < 1 ) {
for ( int j = i; j < length; j++ ) {
left[j] = 0.0f;
right[j] = 0.0f;
}
break;
}
left[i] = (buf[0] - 64.0f) / 64.0f;
right[i] = left[i];
}
}
}
}
public unsafe void Read( int start, int length, out IntPtr ptr_left, out IntPtr ptr_right ) {
ptr_left = Marshal.AllocHGlobal( sizeof( float ) * length );
ptr_right = Marshal.AllocHGlobal( sizeof( float ) * length );
float* left = (float*)ptr_left.ToPointer();
float* right = (float*)ptr_right.ToPointer();
if ( !m_opened ) {
return;
}
int loc = 0x2e + m_byte_per_sample * m_channel * start;
m_stream.Seek( loc, SeekOrigin.Begin );
if ( m_byte_per_sample == 2 ) {
if ( m_channel == 2 ) {
byte[] buf = new byte[4];
for ( int i = 0; i < length; i++ ) {
int ret = m_stream.Read( buf, 0, 4 );
if ( ret < 4 ) {
for ( int j = i; j < length; j++ ) {
left[j] = 0.0f;
right[j] = 0.0f;
}
break;
}
short l = (short)(buf[0] | buf[1] << 8);
short r = (short)(buf[2] | buf[3] << 8);
left[i] = l / 32768.0f;
right[i] = r / 32768.0f;
}
} else {
byte[] buf = new byte[2];
for ( int i = 0; i < length; i++ ) {
int ret = m_stream.Read( buf, 0, 2 );
if ( ret < 2 ) {
for ( int j = i; j < length; j++ ) {
left[j] = 0.0f;
right[j] = 0.0f;
}
break;
}
short l = (short)(buf[0] | buf[1] << 8);
left[i] = l / 32768.0f;
right[i] = left[i];
}
}
} else {
if ( m_channel == 2 ) {
byte[] buf = new byte[2];
for ( int i = 0; i < length; i++ ) {
int ret = m_stream.Read( buf, 0, 2 );
if ( ret < 2 ) {
for ( int j = i; j < length; j++ ) {
left[j] = 0.0f;
right[j] = 0.0f;
}
break;
}
left[i] = (buf[0] - 64.0f) / 64.0f;
right[i] = (buf[1] - 64.0f) / 64.0f;
}
} else {
byte[] buf = new byte[1];
for ( int i = 0; i < length; i++ ) {
int ret = m_stream.Read( buf, 0, 1 );
if ( ret < 1 ) {
for ( int j = i; j < length; j++ ) {
left[j] = 0.0f;
right[j] = 0.0f;
}
break;
}
left[i] = (buf[0] - 64.0f) / 64.0f;
right[i] = left[i];
}
}
}
}
public void Close() {
m_opened = false;
if ( m_stream != null ) {
m_stream.Close();
}
}
~WaveReader() {
Close();
}
}
}

View File

@ -0,0 +1,384 @@
/*
* WaveWriter.cs
* Copyright (c) 2009 kbinani
*
* This file is part of Boare.Lib.Media.
*
* Boare.Lib.Media is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* Boare.Lib.Media 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;
namespace Boare.Lib.Media {
public class WaveWriter : IDisposable {
private WaveChannel m_channel;
private ushort m_bit_per_sample;
private uint m_sample_rate;
private uint m_total_samples = 0;
private FileStream m_stream = null;
private string m_path = "";
public WaveWriter( string path ) :
this ( path, WaveChannel.Stereo, 16, 44100 ) {
}
public WaveWriter( string path, WaveChannel channel, ushort bit_per_sample, uint sample_rate ) {
m_path = path;
m_stream = new FileStream( m_path, FileMode.Create );
m_channel = channel;
m_bit_per_sample = bit_per_sample;
m_sample_rate = sample_rate;
m_total_samples = 0;
WriteHeader();
}
/// <summary>
/// Writes header of WAVE file
/// </summary>
private void WriteHeader() {
// RIFF
m_stream.WriteByte( 0x52 ); // loc=0x00
m_stream.WriteByte( 0x49 );
m_stream.WriteByte( 0x46 );
m_stream.WriteByte( 0x46 );
// ファイルサイズ - 8最後に記入
m_stream.WriteByte( 0x00 ); // loc=0x04
m_stream.WriteByte( 0x00 );
m_stream.WriteByte( 0x00 );
m_stream.WriteByte( 0x00 );
// WAVE
m_stream.WriteByte( 0x57 ); // loc=0x08
m_stream.WriteByte( 0x41 );
m_stream.WriteByte( 0x56 );
m_stream.WriteByte( 0x45 );
// fmt
m_stream.WriteByte( 0x66 ); // loc=0x0c
m_stream.WriteByte( 0x6d );
m_stream.WriteByte( 0x74 );
m_stream.WriteByte( 0x20 );
// fmt チャンクのサイズ
m_stream.WriteByte( 0x12 ); // loc=0x10
m_stream.WriteByte( 0x00 );
m_stream.WriteByte( 0x00 );
m_stream.WriteByte( 0x00 );
// format ID
m_stream.WriteByte( 0x01 ); // loc=0x14
m_stream.WriteByte( 0x00 );
// チャンネル数
if ( m_channel == WaveChannel.Monoral ) {
m_stream.WriteByte( 0x01 ); // loc=0x16
m_stream.WriteByte( 0x00 );
} else {
m_stream.WriteByte( 0x02 ); //loc=0x16
m_stream.WriteByte( 0x00 );
}
// サンプリングレート
byte[] buf = BitConverter.GetBytes( m_sample_rate );
WriteByteArray( m_stream, buf, 4 ); // 0x18
// データ速度
ushort block_size = (ushort)(m_bit_per_sample / 8 * (int)m_channel);
uint data_rate = m_sample_rate * block_size;
buf = BitConverter.GetBytes( data_rate );
WriteByteArray( m_stream, buf, 4 );//loc=0x1c
// ブロックサイズ
buf = BitConverter.GetBytes( block_size );
WriteByteArray( m_stream, buf, 2 ); //0x20
// サンプルあたりのビット数
buf = BitConverter.GetBytes( m_bit_per_sample );
WriteByteArray( m_stream, buf, 2 ); //loc=0x22
// 拡張部分
m_stream.WriteByte( 0x00 ); //loc=0x24
m_stream.WriteByte( 0x00 );
// data
m_stream.WriteByte( 0x64 ); //loc=0x26
m_stream.WriteByte( 0x61 );
m_stream.WriteByte( 0x74 );
m_stream.WriteByte( 0x61 );
// size of data chunk
uint size = block_size * m_total_samples;
buf = BitConverter.GetBytes( size );
WriteByteArray( m_stream, buf, 4 );
}
public void Close(){
if ( m_stream != null ) {
// 最後にWAVEチャンクのサイズ
uint position = (uint)m_stream.Position;
m_stream.Seek( 4, SeekOrigin.Begin );
byte[] buf = BitConverter.GetBytes( position - 8 );
WriteByteArray( m_stream, buf, 4 );
// size of data chunk
ushort block_size = (ushort)(m_bit_per_sample / 8 * (int)m_channel);
uint size = block_size * m_total_samples;
m_stream.Seek( 42, SeekOrigin.Begin );
buf = BitConverter.GetBytes( size );
WriteByteArray( m_stream, buf, 4 );
m_stream.Close();
}
}
public uint SampleRate {
get {
return m_sample_rate;
}
}
public void Dispose() {
Close();
}
public void Append( float[] L ) {
int total = L.Length;
if ( m_bit_per_sample == 8 ) {
if ( m_channel == WaveChannel.Monoral ) {
for ( int i = 0; i < total; i++ ) {
m_stream.WriteByte( (byte)((L[i] + 1.0f) * 127.5f) );
}
} else {
for ( int i = 0; i < total; i++ ) {
byte b = (byte)((L[i] + 1.0f) * 127.5f);
m_stream.WriteByte( b );
m_stream.WriteByte( b );
}
}
} else {
byte[] buf;
if ( m_channel == WaveChannel.Monoral ) {
for ( int i = 0; i < total; i++ ) {
buf = BitConverter.GetBytes( (short)(L[i] * 32768f) );
WriteByteArray( m_stream, buf, 2 );
}
} else {
for ( int i = 0; i < total; i++ ) {
buf = BitConverter.GetBytes( (short)(L[i] * 32768f) );
WriteByteArray( m_stream, buf, 2 );
WriteByteArray( m_stream, buf, 2 );
}
}
}
m_total_samples += (uint)total;
}
public void Append( double[] L ) {
int total = L.Length;
if ( m_bit_per_sample == 8 ) {
if ( m_channel == WaveChannel.Monoral ) {
for ( int i = 0; i < total; i++ ) {
m_stream.WriteByte( (byte)((L[i] + 1.0) * 127.5) );
}
} else {
for ( int i = 0; i < total; i++ ) {
byte b = (byte)((L[i] + 1.0) * 127.5);
m_stream.WriteByte( b );
m_stream.WriteByte( b );
}
}
} else {
byte[] buf;
if ( m_channel == WaveChannel.Monoral ) {
for ( int i = 0; i < total; i++ ) {
buf = BitConverter.GetBytes( (short)(L[i] * 32768.0) );
WriteByteArray( m_stream, buf, 2 );
}
} else {
for ( int i = 0; i < total; i++ ) {
buf = BitConverter.GetBytes( (short)(L[i] * 32768.0) );
WriteByteArray( m_stream, buf, 2 );
WriteByteArray( m_stream, buf, 2 );
}
}
}
m_total_samples += (uint)total;
}
public void Append( float[] L, float[] R ) {
int total = Math.Min( L.Length, R.Length );
if ( m_bit_per_sample == 8 ) {
if ( m_channel == WaveChannel.Monoral ) {
for ( int i = 0; i < total; i++ ) {
m_stream.WriteByte( (byte)((L[i] + R[i] + 2.0f) * 63.75f) );
}
} else {
for ( int i = 0; i < total; i++ ) {
m_stream.WriteByte( (byte)((L[i] + 1.0f) * 127.5f) );
m_stream.WriteByte( (byte)((R[i] + 1.0f) * 127.5f) );
}
}
} else {
byte[] buf;
if ( m_channel == WaveChannel.Monoral ) {
for ( int i = 0; i < total; i++ ) {
buf = BitConverter.GetBytes( (short)((L[i] + R[i]) * 16384f) );
WriteByteArray( m_stream, buf, 2 );
}
} else {
for ( int i = 0; i < total; i++ ) {
buf = BitConverter.GetBytes( (short)(L[i] * 32768f) );
WriteByteArray( m_stream, buf, 2 );
buf = BitConverter.GetBytes( (short)(R[i] * 32768f) );
WriteByteArray( m_stream, buf, 2 );
}
}
}
m_total_samples += (uint)total;
}
public unsafe void Append( float* L, float* R, int length ) {
if ( m_bit_per_sample == 8 ) {
if ( m_channel == WaveChannel.Monoral ) {
for ( int i = 0; i < length; i++ ) {
m_stream.WriteByte( (byte)((L[i] + R[i] + 2.0f) * 63.75f) );
}
} else {
for ( int i = 0; i < length; i++ ) {
m_stream.WriteByte( (byte)((L[i] + 1.0f) * 127.5f) );
m_stream.WriteByte( (byte)((R[i] + 1.0f) * 127.5f) );
}
}
} else {
byte[] buf;
if ( m_channel == WaveChannel.Monoral ) {
for ( int i = 0; i < length; i++ ) {
buf = BitConverter.GetBytes( (short)((L[i] + R[i]) * 16384f) );
WriteByteArray( m_stream, buf, 2 );
}
} else {
for ( int i = 0; i < length; i++ ) {
buf = BitConverter.GetBytes( (short)(L[i] * 32768f) );
WriteByteArray( m_stream, buf, 2 );
buf = BitConverter.GetBytes( (short)(R[i] * 32768f) );
WriteByteArray( m_stream, buf, 2 );
}
}
}
m_total_samples += (uint)length;
}
public void Append( double[] L, double[] R ) {
int total = Math.Min( L.Length, R.Length );
if ( m_bit_per_sample == 8 ) {
if ( m_channel == WaveChannel.Monoral ) {
for ( int i = 0; i < total; i++ ) {
m_stream.WriteByte( (byte)((L[i] + R[i] + 2.0) * 63.75) );
}
} else {
for ( int i = 0; i < total; i++ ) {
m_stream.WriteByte( (byte)((L[i] + 1.0) * 127.5) );
m_stream.WriteByte( (byte)((R[i] + 1.0) * 127.5) );
}
}
} else {
byte[] buf;
if ( m_channel == WaveChannel.Monoral ) {
for ( int i = 0; i < total; i++ ) {
buf = BitConverter.GetBytes( (short)((L[i] + R[i]) * 16384.0) );
WriteByteArray( m_stream, buf, 2 );
}
} else {
for ( int i = 0; i < total; i++ ) {
buf = BitConverter.GetBytes( (short)(L[i] * 32768.0) );
WriteByteArray( m_stream, buf, 2 );
buf = BitConverter.GetBytes( (short)(R[i] * 32768.0) );
WriteByteArray( m_stream, buf, 2 );
}
}
}
m_total_samples += (uint)total;
}
public void Append( byte[] L, byte[] R ) {
int total = Math.Min( L.Length, R.Length );
if ( m_bit_per_sample == 8 ) {
if ( m_channel == WaveChannel.Monoral ) {
for ( int i = 0; i < total; i++ ) {
m_stream.WriteByte( (byte)((L[i] + R[i]) / 2) );
}
} else {
for ( int i = 0; i < total; i++ ) {
m_stream.WriteByte( L[i] );
m_stream.WriteByte( R[i] );
}
}
} else {
byte[] buf;
if ( m_channel == WaveChannel.Monoral ) {
for ( int i = 0; i < total; i++ ) {
buf = BitConverter.GetBytes( (short)((L[i] + R[i]) * 128.5f - 32768f) );
WriteByteArray( m_stream, buf, 2 );
}
} else {
for ( int i = 0; i < total; i++ ) {
buf = BitConverter.GetBytes( (short)(L[i] * 257f - 32768f) );
WriteByteArray( m_stream, buf, 2 );
buf = BitConverter.GetBytes( (short)(R[i] * 257f - 32768f) );
WriteByteArray( m_stream, buf, 2 );
}
}
}
m_total_samples += (uint)total;
}
public void Append( short[] L, short[] R ) {
int total = Math.Min( L.Length, R.Length );
if ( m_bit_per_sample == 8 ) {
if ( m_channel == WaveChannel.Monoral ) {
for ( int i = 0; i < total; i++ ) {
m_stream.WriteByte( (byte)(((L[i] + R[i]) / 2f + 32768f) / 255f) );
}
} else {
for ( int i = 0; i < total; i++ ) {
m_stream.WriteByte( (byte)((L[i] + 32768f) / 255f) );
m_stream.WriteByte( (byte)((R[i] + 32768f) / 255f) );
}
}
} else {
byte[] buf;
if ( m_channel == WaveChannel.Monoral ) {
for ( int i = 0; i < total; i++ ) {
buf = BitConverter.GetBytes( (L[i] + R[i]) / 2 );
WriteByteArray( m_stream, buf, 2 );
}
} else {
for ( int i = 0; i < total; i++ ) {
buf = BitConverter.GetBytes( L[i] );
WriteByteArray( m_stream, buf, 2 );
buf = BitConverter.GetBytes( R[i] );
WriteByteArray( m_stream, buf, 2 );
}
}
}
m_total_samples += (uint)total;
}
private static void WriteByteArray( FileStream fs, byte[] dat, int limit ) {
fs.Write( dat, 0, (dat.Length > limit) ? limit : dat.Length );
if ( dat.Length < limit ) {
for ( int i = 0; i < limit - dat.Length; i++ ) {
fs.WriteByte( 0x00 );
}
}
}
}
}

View File

@ -0,0 +1,17 @@
CP=cp
RM=rm
SRC=AviReader.cs AviWriter.cs RawAvi2Writer.cs AviWriterEx.cs VCM.cs Util.cs VFW.cs MediaPlayer.cs Wave.cs
OPT=
Boare.Lib.Media.dll: *.cs bocoree.dll
gmcs $(OPT) -recurse:*.cs -unsafe+ -target:library -out:Boare.Lib.Media.dll -r:bocoree.dll,System,System.Drawing,System.Windows.Forms -define:MONO
bocoree.dll: ../bocoree/bocoree.dll
cp ../bocoree/bocoree.dll bocoree.dll
../bocoree/bocoree.dll:
cd ../bocoree/ && $(MAKE) OPT=$(OPT)
clean:
$(RM) Boare.Lib.Media.dll
$(RM) bocoree.dll

View File

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.21022</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{D861973B-3BC6-4F52-83BE-49A8C269C09F}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Boare.Lib.Swf</RootNamespace>
<AssemblyName>Boare.Lib.Swf</AssemblyName>
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Xml.Linq">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data.DataSetExtensions">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="RECT.cs" />
<Compile Include="SB.cs" />
<Compile Include="SwfWriter.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Util.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// アセンブリに関する一般情報は以下の属性セットをとおして制御されます。
// アセンブリに関連付けられている情報を変更するには、
// これらの属性値を変更してください。
[assembly: AssemblyTitle( "Boare.Lib.Swf" )]
[assembly: AssemblyDescription( "" )]
[assembly: AssemblyConfiguration( "" )]
[assembly: AssemblyCompany( "" )]
[assembly: AssemblyProduct( "Boare.Lib.Swf" )]
[assembly: AssemblyCopyright( "Copyright © 2008" )]
[assembly: AssemblyTrademark( "" )]
[assembly: AssemblyCulture( "" )]
// ComVisible を false に設定すると、その型はこのアセンブリ内で COM コンポーネントから
// 参照不可能になります。COM からこのアセンブリ内の型にアクセスする場合は、
// その型の ComVisible 属性を true に設定してください。
[assembly: ComVisible( false )]
// 次の GUID は、このプロジェクトが COM に公開される場合の、typelib の ID です
[assembly: Guid( "73d3cbb6-bae0-4703-9ef3-a18b1df0c08b" )]
// アセンブリのバージョン情報は、以下の 4 つの値で構成されています:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// すべての値を指定するか、下のように '*' を使ってビルドおよびリビジョン番号を
// 既定値にすることができます:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion( "1.0.0.0" )]
[assembly: AssemblyFileVersion( "0.0a0" )]

View File

@ -0,0 +1,63 @@
/*
* RECT.cs
* Copyright (c) 2008-2009 kbinani
*
* This file is part of Boare.Lib.Swf.
*
* Boare.Lib.Swf is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* Boare.Lib.Swf 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;
namespace Boare.Lib.Swf{
public struct RECT{
private int m_xmin;
private int m_xmax;
private int m_ymin;
private int m_ymax;
private int Xmin {
get {
return m_xmin;
}
set {
m_xmin = value;
}
}
private int Xmax {
get {
return m_xmax;
}
set {
m_xmax = value;
}
}
private int Ymin {
get {
return m_ymin;
}
set {
m_ymin = value;
}
}
private int Ymax {
get {
return m_ymax;
}
set {
m_ymax = value;
}
}
}
}

54
trunk/Boare.Lib.Swf/SB.cs Normal file
View File

@ -0,0 +1,54 @@
/*
* SB.cs
* Copyright (c) 2008-2009 kbinani
*
* This file is part of Boare.Lib.Swf.
*
* Boare.Lib.Swf is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* Boare.Lib.Swf 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 Boare.Lib.Swf;
namespace Boare.Lib.Swf {
using UI8 = System.Byte;
using UI32 = System.UInt32;
using UI16 = System.UInt16;
using SI8 = System.SByte;
using SI16 = System.Int16;
using SI32 = System.Int32;
/// <summary>
/// Signed-bit Value
/// </summary>
struct SB {
private byte[] m_value;
public void SetValue( SI8 value ) {
}
public SI32 GetSI32Value() {
if ( m_value == null ) {
return 0;
} else {
throw new NotImplementedException();
}
}
public SI16 GetSI16Value() {
if ( m_value == null ) {
return 0;
} else {
throw new NotImplementedException();
}
}
}
}

View File

@ -0,0 +1,81 @@
/*
* SwfWriter.cs
* Copyright (c) 2008-2009 kbinani
*
* This file is part of Boare.Lib.Swf.
*
* Boare.Lib.Swf is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* Boare.Lib.Swf 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;
namespace Boare.Lib.Swf {
using UI8 = System.Byte;
using UI32 = System.UInt32;
using UI16 = System.UInt16;
using SI8 = System.SByte;
using SI16 = System.Int16;
using SI32 = System.Int32;
public class SwfWriter : IDisposable {
private const UI8 m_version = 0x6;
private UI16 m_frame_rate;
private UI16 m_frame_count;
private FileStream m_stream;
public SwfWriter( FileStream s ) {
m_stream = s;
// swf header
s.WriteByte( 0x46 ); // Signature
s.WriteByte( 0x57 ); // Signature
s.WriteByte( 0x53 ); // Signature
s.WriteByte( m_version ); // Version
s.WriteByte( 0x0 ); // FileLength
}
public void Close() {
if ( m_stream != null ) {
m_stream.Close();
}
}
public void Dispose() {
Close();
}
public static int GetEncodedU32( byte[] pos ) {
int result = pos[0];
if ( (result & 0x00000080) == 0x0 ) {
return result;
}
result = (result & 0x0000007f) | pos[1] << 7;
if ( (result & 0x00004000) == 0x0 ) {
return result;
}
result = (result & 0x00003fff) | pos[2] << 14;
if ( (result & 0x00200000) == 0x0 ) {
return result;
}
result = (result & 0x001fffff) | pos[3] << 21;
if ( (result & 0x10000000) == 0x0 ) {
return result;
}
result = (result & 0x0fffffff) | pos[4] << 28;
return result;
}
}
}

View File

@ -0,0 +1,22 @@
/*
* Util.cs
* Copyright (c) 2008-2009 kbinani
*
* This file is part of Boare.Lib.Swf.
*
* Boare.Lib.Swf is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* Boare.Lib.Swf 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;
namespace Boare.Lib.Swf {
class Util {
}
}

View File

@ -0,0 +1,8 @@
RM=rm
CP=cp
Boare.Lib.Swf.dll: RECT.cs SB.cs SwfWriter.cs Util.cs
gmcs -target:library -out:Boare.Lib.Swf.dll \
RECT.cs SB.cs SwfWriter.cs Util.cs
clean:
$(RM) Boare.Lib.Swf.dll

View File

@ -0,0 +1,47 @@
/*
* BPPair.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;
namespace Boare.Lib.Vsq {
/// <summary>
/// Stores the paired value of "Clock" and integer. Mainly used in VsqBPList
/// </summary>
[Serializable]
public class BPPair : IComparable<BPPair> {
public int Clock;
public int Value;
/// <summary>
/// このインスタンスと、指定したオブジェクトを比較します
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public int CompareTo( BPPair item ) {
if ( Clock > item.Clock ) {
return 1;
} else if ( Clock < item.Clock ) {
return -1;
} else {
return 0;
}
}
public BPPair( int clock_, int value_ ) {
Clock = clock_;
Value = value_;
}
}
}

View File

@ -0,0 +1,114 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.21022</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{673347F3-6FC2-4F82-9273-BF158E0F8CB1}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Boare.Lib.Vsq</RootNamespace>
<AssemblyName>Boare.Lib.Vsq</AssemblyName>
<FileUpgradeFlags>
</FileUpgradeFlags>
<OldToolsVersion>2.0</OldToolsVersion>
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>Boare.Lib.Vsq.xml</DocumentationFile>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>Boare.Lib.Vsq.xml</DocumentationFile>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<PlatformTarget>x86</PlatformTarget>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG</DefineConstants>
<DocumentationFile>bin\x86\Debug\Boare.Lib.Vsq.XML</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<PlatformTarget>x86</PlatformTarget>
<OutputPath>bin\x86\Release\</OutputPath>
<DocumentationFile>bin\x86\Release\Boare.Lib.Vsq.XML</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="BPPair.cs" />
<Compile Include="PortUtil.cs" />
<Compile Include="NRPN.cs" />
<Compile Include="SingerConfig.cs" />
<Compile Include="SMF\MidiFile.cs" />
<Compile Include="SymbolTable.cs" />
<Compile Include="UstEvent.cs" />
<Compile Include="UstFile.cs" />
<Compile Include="UstTrack.cs" />
<Compile Include="VibratoBPList.cs" />
<Compile Include="VibratoBPPair.cs" />
<Compile Include="VibratoType.cs" />
<Compile Include="VsqEventList.cs" />
<Compile Include="VsqNrpn.cs" />
<Compile Include="NrpnData.cs" />
<Compile Include="VsqCommandType.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TempoTableEntry.cs" />
<Compile Include="TextMemoryStream.cs" />
<Compile Include="TimeSigTableEntry.cs" />
<Compile Include="VsqBarLineType.cs" />
<Compile Include="VsqBPList.cs" />
<Compile Include="VsqCommand.cs" />
<Compile Include="VsqEvent.cs" />
<Compile Include="VsqFile.cs" />
<Compile Include="VsqMetaText\Common.cs" />
<Compile Include="VsqMetaText\Handle.cs" />
<Compile Include="VsqMetaText\ID.cs" />
<Compile Include="VsqMetaText\Lyric.cs" />
<Compile Include="VsqMetaText\Master.cs" />
<Compile Include="VsqMetaText\Mixer.cs" />
<Compile Include="VsqMetaText\VsqMetaText.cs" />
<Compile Include="VsqNote.cs" />
<Compile Include="VsqPhoneticSymbol.cs" />
<Compile Include="VsqTrack.cs" />
<Compile Include="VsqUtil.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\bocoree\bocoree.csproj">
<Project>{C8AAE632-9C6C-4372-8175-811528A66742}</Project>
<Name>bocoree</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
<PropertyGroup>
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
</Project>

249
trunk/Boare.Lib.Vsq/NRPN.cs Normal file
View File

@ -0,0 +1,249 @@
/*
* NRPN.cs
* Copyright (c) 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.
*/
namespace Boare.Lib.Vsq {
public enum NRPN : ushort {
/// <summary>
/// (0x5000) Version number(MSB) &amp;, Device number(LSB)
/// </summary>
CVM_NM_VERSION_AND_DEVICE = 0x5000,
/// <summary>
/// (0x5001) Delay in millisec(MSB, LSB)
/// </summary>
CVM_NM_DELAY = 0x5001,
/// <summary>
/// (0x5002) Note number(MSB)
/// </summary>
CVM_NM_NOTE_NUMBER = 0x5002,
/// <summary>
/// (0x5003) Velocity(MSB)
/// </summary>
CVM_NM_VELOCITY = 0x5003,
/// <summary>
/// (0x5004) Note Duration in millisec(MSB, LSB)
/// </summary>
CVM_NM_NOTE_DURATION = 0x5004,
/// <summary>
/// (0x5005) Note Location(MSB)
/// </summary>
CVM_NM_NOTE_LOCATION = 0x5005,
/// <summary>
/// (0x500c) Index of Vibrato DB(MSB: ID_H00, LSB:ID_L00)
/// </summary>
CVM_NM_INDEX_OF_VIBRATO_DB = 0x500c,
/// <summary>
/// (0x500d) Vibrato configuration(MSB: Index of Vibrato Type, LSB: Duration &amp;, Configuration parameter of vibrato)
/// </summary>
CVM_NM_VIBRATO_CONFIG = 0x500d,
/// <summary>
/// (0x500e) Vibrato Delay(MSB)
/// </summary>
CVM_NM_VIBRATO_DELAY = 0x500e,
/// <summary>
/// (0x5012) Number of phonetic symbols in bytes(MSB)
/// </summary>
CVM_NM_PHONETIC_SYMBOL_BYTES = 0x5012,
/// <summary>
/// (0x5013) Phonetic symbol 1(MSB:Phonetic symbol 1, LSB: Consonant adjustment 1)
/// </summary>
CVM_NM_PHONETIC_SYMBOL1 = 0x5013,
/// <summary>
/// (0x504f) Phonetic symbol continuation(MSB, 0x7f=end, 0x00=continue)
/// </summary>
CVM_NM_PHONETIC_SYMBOL_CONTINUATION = 0x504f,
/// <summary>
/// (0x5050) v1mean in Cent/5(MSB)
/// </summary>
CVM_NM_V1MEAN = 0x5050,
/// <summary>
/// (0x5051) d1mean in millisec/5(MSB)
/// </summary>
CVM_NM_D1MEAN = 0x5051,
/// <summary>
/// (0x5052) d1meanFirstNote in millisec/5(MSB)
/// </summary>
CVM_NM_D1MEAN_FIRST_NOTE = 0x5052,
/// <summary>
/// (0x5053) d2mean in millisec/5(MSB)
/// </summary>
CVM_NM_D2MEAN = 0x5053,
/// <summary>
/// (0x5054) d4mean in millisec/5(MSB)
/// </summary>
CVM_NM_D4MEAN = 0x5054,
/// <summary>
/// (0x5055) pMeanOnsetFirstNote in Cent/5(MSB)
/// </summary>
CVM_NM_PMEAN_ONSET_FIRST_NOTE = 0x5055,
/// <summary>
/// (0x5056) vMeanNoteTransition in Cent/5(MSB)
/// </summary>
CVM_NM_VMEAN_NOTE_TRNSITION = 0x5056,
/// <summary>
/// (0x5057) pMeanEndingNote in Cent/5(MSB)
/// </summary>
CVM_NM_PMEAN_ENDING_NOTE = 0x5057,
/// <summary>
/// (0x5058) AddScooptoUpIntervals &amp;, AddPortamentoToDownIntervals(MSB)
/// </summary>
CVM_NM_ADD_PORTAMENTO = 0x5058,
/// <summary>
/// (0x5059) changAfterPeak(MSB)
/// </summary>
CVM_NM_CHANGE_AFTER_PEAK = 0x5059,
/// <summary>
/// (0x505a) Accent(MSB)
/// </summary>
CVM_NM_ACCENT = 0x505a,
/// <summary>
/// (0x597f) Note message continuation(MSB)
/// </summary>
CVM_NM_NOTE_MESSAGE_CONTINUATION = 0x507f,
/// <summary>
/// (0x6000) Version number &amp;, Device number(MSB, LSB)
/// </summary>
CC_BS_VERSION_AND_DEVICE = 0x6000,
/// <summary>
/// (0x6001) Delay in millisec(MSB, LSB)
/// </summary>
CC_BS_DELAY = 0x6001,
/// <summary>
/// (0x6002) Laugnage type(MSB, optional LSB)
/// </summary>
CC_BS_LANGUAGE_TYPE = 0x6002,
/// <summary>
/// (0x6100) Version number &amp;, device number(MSB, LSB)
/// </summary>
CC_CV_VERSION_AND_DEVICE = 0x6100,
/// <summary>
/// (0x6101) Delay in millisec(MSB, LSB)
/// </summary>
CC_CV_DELAY = 0x6101,
/// <summary>
/// (0x6102) Volume value(MSB)
/// </summary>
CC_CV_VOLUME = 0x6102,
/// <summary>
/// (0x6200) Version number &amp;, device number(MSB, LSB)
/// </summary>
CC_P_VERSION_AND_DEVICE = 0x6200,
/// <summary>
/// (0x6201) Delay in millisec(MSB, LSB)
/// </summary>
CC_P_DELAY = 0x6201,
/// <summary>
/// (0x6202) Pan value(MSB)
/// </summary>
CC_PAN = 0x6202,
/// <summary>
/// (0x6300) Version number &amp;, device number(MSB, LSB)
/// </summary>
CC_E_VESION_AND_DEVICE = 0x6300,
/// <summary>
/// (0x6301) Delay in millisec(MSB, LSB)
/// </summary>
CC_E_DELAY = 0x6301,
/// <summary>
/// (0x6302) Expression vlaue(MSB)
/// </summary>
CC_E_EXPRESSION = 0x6302,
/// <summary>
/// (0x6400) Version number &amp;, device number(MSB, LSB)
/// </summary>
CC_VR_VERSION_AND_DEVICE = 0x6400,
/// <summary>
/// (0x6401) Delay in millisec(MSB, LSB)
/// </summary>
CC_VR_DELAY = 0x6401,
/// <summary>
/// (0x6402) Vibrato Rate value(MSB)
/// </summary>
CC_VR_VIBRATO_RATE = 0x6402,
/// <summary>
/// (0x6500) Version number &amp;, device number(MSB, LSB)
/// </summary>
CC_VD_VERSION_AND_DEVICE = 0x6500,
/// <summary>
/// (0x6501) Delay in millisec(MSB, LSB)
/// </summary>
CC_VD_DELAY = 0x6501,
/// <summary>
/// (0x6502) Vibrato Depth value(MSB)
/// </summary>
CC_VD_VIBRATO_DEPTH = 0x6502,
/// <summary>
/// (0x6700) Version number &amp;, device number(MSB, LSB)
/// </summary>
CC_PBS_VERSION_AND_DEVICE = 0x6700,
/// <summary>
/// (0x6701) Delay in millisec(MSB, LSB)
/// </summary>
CC_PBS_DELAY = 0x6701,
/// <summary>
/// (0x6702) Pitch Bend Sensitivity(MSB, LSB)
/// </summary>
CC_PBS_PITCH_BEND_SENSITIVITY = 0x6702,
/// <summary>
/// (0x5300) Version number &amp;, device number(MSB, LSB)
/// </summary>
PC_VERSION_AND_DEVICE = 0x5300,
/// <summary>
/// (0x5301) Delay in millisec(MSB, LSB)
/// </summary>
PC_DELAY = 0x5301,
/// <summary>
/// (0x5302) Voice Type(MSB)
/// </summary>
PC_VOICE_TYPE = 0x5302,
/// <summary>
/// (0x5400) Version number &amp;, device number(MSB, LSB)
/// </summary>
PB_VERSION_AND_DEVICE = 0x5400,
/// <summary>
/// (0x5401) Delay in millisec(MSB, LSB)
/// </summary>
PB_DELAY = 0x5401,
/// <summary>
/// (0x5402) Pitch Bend value(MSB, LSB)
/// </summary>
PB_PITCH_BEND = 0x5402,
/// <summary>
/// (0x5500) Version number &amp;, device number(MSB, LSB)
/// </summary>
VCP_VERSION_AND_DEVICE = 0x5500,
/// <summary>
/// (0x5501) Delay in millisec(MSB, LSB)
/// </summary>
VCP_DELAY = 0x5501,
/// <summary>
/// (0x5502) Voice Change Parameter ID(MSB)
/// </summary>
VCP_VOICE_CHANGE_PARAMETER_ID = 0x5502,
/// <summary>
/// (0x5503) Voice Change Parameter value(MSB)
/// </summary>
VCP_VOICE_CHANGE_PARAMETER = 0x5503,
}
}

View File

@ -0,0 +1,36 @@
/*
* NrpnData.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.
*/
namespace Boare.Lib.Vsq {
public class NrpnData {
int m_clock;
byte m_parameter;
public byte Value;
public NrpnData( int clock_, byte parameter, byte value ) {
m_clock = clock_;
m_parameter = parameter;
Value = value;
}
public int getClock(){
return m_clock;
}
public byte getParameter(){
return m_parameter;
}
}
}

View File

@ -0,0 +1,55 @@
/*
* PortUtil.cs
* Copyright (c) 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 interface Iterator {
bool hasNext();
object next();
void remove();
}
public class ListIterator<T> : Iterator {
private List<T> m_list;
private int m_pos;
public ListIterator( List<T> list ) {
m_list = list;
m_pos = -1;
}
public Boolean hasNext() {
if ( m_list != null && 0 <= m_pos + 1 && m_pos + 1 < m_list.Count ) {
return true;
} else {
return false;
}
}
public Object next() {
if ( m_list == null ) {
return null;
}
m_pos++;
return m_list[m_pos];
}
public void remove() {
m_list.RemoveAt( m_pos );
}
}
}

View File

@ -0,0 +1,29 @@
/*
* AssemblyInfo.cs
* Copyright (c) 2007-2009 kbinani
*
* This file is part of Boare.Vsq.Lib.
*
* Boare.Vsq.Lib is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* Boare.Cadencii 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.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle( "Boare.Lib.Vsq" )]
[assembly: AssemblyDescription( "" )]
[assembly: AssemblyConfiguration( "" )]
[assembly: AssemblyCompany( "Boare" )]
[assembly: AssemblyProduct( "Boare.Lib.Vsq" )]
[assembly: AssemblyCopyright( "Copyright © 2007-2009" )]
[assembly: AssemblyTrademark( "" )]
[assembly: AssemblyCulture( "" )]
[assembly: ComVisible( false )]
[assembly: Guid( "b8b57651-e1db-421c-b518-16d661bcc863" )]
[assembly: AssemblyVersion( "1.0.0.0" )]
[assembly: AssemblyFileVersion( "1.2.0" )]

View File

@ -0,0 +1,316 @@
/*
* MidiFile.cs
* Copyright (c) 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.Collections.Generic;
namespace Boare.Lib.Vsq {
/// <summary>
/// midiイベント。メタイベントは、メタイベントのデータ長をData[1]に格納せず、生のデータをDataに格納するので、注意が必要
/// </summary>
public struct MidiEvent : IComparable<MidiEvent> {
public long Clock;
public byte FirstByte;
public byte[] Data;
private static void writeDeltaClock( Stream stream, long number ) {
bool[] bits = new bool[64];
long val = 0x1;
bits[0] = (number & val) == val;
for ( int i = 1; i < 64; i++ ) {
val = val << 1;
bits[i] = (number & val) == val;
}
int first = 0;
for ( int i = 63; i >= 0; i-- ) {
if ( bits[i] ) {
first = i;
break;
}
}
// 何バイト必要か?
int bytes = first / 7 + 1;
for ( int i = 1; i <= bytes; i++ ) {
uint num = 0;
uint count = 0x80;
for ( int j = (bytes - i + 1) * 7 - 1; j >= (bytes - i + 1) * 7 - 6 - 1; j-- ) {
count = count >> 1;
if ( bits[j] ) {
num += count;
}
}
if ( i != bytes ) {
num += 0x80;
}
stream.WriteByte( (byte)num );
}
}
private static long readDeltaClock( Stream stream ) {
long ret = 0;
while ( true ) {
byte d = (byte)stream.ReadByte();
ret = (ret << 7) | ((long)d & 0x7f);
if ( (d & 0x80) == 0x00 ) {
break;
}
}
return ret;
}
public static MidiEvent read( Stream stream, ref long last_clock, ref byte last_status_byte ) {
long delta_clock = readDeltaClock( stream );
last_clock += delta_clock;
byte first_byte = (byte)stream.ReadByte();
if ( first_byte < 0x80 ) {
// ランニングステータスが適用される
stream.Seek( -1, SeekOrigin.Current );
first_byte = last_status_byte;
} else {
last_status_byte = first_byte;
}
byte ctrl = (byte)(first_byte & (byte)0xf0);
if ( ctrl == 0x80 || ctrl == 0x90 || ctrl == 0xA0 || ctrl == 0xB0 || ctrl == 0xE0 || first_byte == 0xF2 ) {
// 3byte使用するチャンネルメッセージ
// 0x8*: ノートオフ
// 0x9*: ノートオン
// 0xA*: ポリフォニック・キープレッシャ
// 0xB*: コントロールチェンジ
// 0xE*: ピッチベンドチェンジ
// 3byte使用するシステムメッセージ
// 0xF2: ソングポジション・ポインタ
MidiEvent me = new MidiEvent();
me.Clock = last_clock;
me.FirstByte = first_byte;
me.Data = new byte[2];
stream.Read( me.Data, 0, 2 );
return me;
} else if ( ctrl == 0xC0 || ctrl == 0xD0 || first_byte == 0xF1 || first_byte == 0xF2 ) {
// 2byte使用するチャンネルメッセージ
// 0xC*: プログラムチェンジ
// 0xD*: チャンネルプレッシャ
// 2byte使用するシステムメッセージ
// 0xF1: クォータフレーム
// 0xF3: ソングセレクト
MidiEvent me = new MidiEvent();
me.Clock = last_clock;
me.FirstByte = first_byte;
me.Data = new byte[1];
stream.Read( me.Data, 0, 1 );
return me;
} else if ( first_byte == 0xF6 ) {
// 1byte使用するシステムメッセージ
// 0xF6: チューンリクエスト
// 0xF7: エンドオブエクスクルーシブこのクラスではF0ステータスのSysExの一部として取り扱う
// 0xF8: タイミングクロック
// 0xFA: スタート
// 0xFB: コンティニュー
// 0xFC: ストップ
// 0xFE: アクティブセンシング
// 0xFF: システムリセット
MidiEvent me = new MidiEvent();
me.Clock = last_clock;
me.FirstByte = first_byte;
me.Data = new byte[0];
return me;
} else if ( first_byte == 0xff ) {
// メタイベント
byte meta_event_type = (byte)stream.ReadByte();
long meta_event_length = readDeltaClock( stream );
MidiEvent me = new MidiEvent();
me.Clock = last_clock;
me.FirstByte = first_byte;
me.Data = new byte[meta_event_length + 1];
me.Data[0] = meta_event_type;
stream.Read( me.Data, 1, (int)meta_event_length );
return me;
} else if ( first_byte == 0xf0 ) {
// f0ステータスのSysEx
MidiEvent me = new MidiEvent();
me.Clock = last_clock;
me.FirstByte = first_byte;
long sysex_length = readDeltaClock( stream );
me.Data = new byte[sysex_length + 1];
stream.Read( me.Data, 0, (int)(sysex_length + 1) );
return me;
} else if ( first_byte == 0xf7 ) {
// f7ステータスのSysEx
MidiEvent me = new MidiEvent();
me.Clock = last_clock;
me.FirstByte = first_byte;
long sysex_length = readDeltaClock( stream );
me.Data = new byte[sysex_length];
stream.Read( me.Data, 0, (int)sysex_length );
return me;
} else {
throw new ApplicationException( "don't know how to process first_byte: 0x" + Convert.ToString( first_byte, 16 ) );
}
}
public void writeData( Stream stream ) {
stream.WriteByte( FirstByte );
if ( FirstByte == 0xff ) {
stream.WriteByte( Data[0] );
writeDeltaClock( stream, Data.Length - 1 );
//stream.WriteByte( (byte)(Data.Length - 1) );
stream.Write( Data, 1, Data.Length - 1 );
} else {
stream.Write( Data, 0, Data.Length );
}
}
public int CompareTo( MidiEvent item ) {
return (int)(Clock - item.Clock);
}
public static MidiEvent generateTimeSigEvent( int clock, int numerator, int denominator ) {
MidiEvent ret = new MidiEvent();
ret.Clock = clock;
ret.FirstByte = 0xff;
byte b_numer = (byte)(Math.Log( numerator, 2 ) + 0.1);
ret.Data = new byte[5] { 0x58, (byte)denominator, b_numer, 0x18, 0x08 };
return ret;
}
public static MidiEvent generateTempoChangeEvent( int clock, int tempo ) {
MidiEvent ret = new MidiEvent();
ret.Clock = clock;
ret.FirstByte = 0xff;
byte b1 = (byte)(tempo & 0xff);
tempo = tempo >> 8;
byte b2 = (byte)(tempo & 0xff);
tempo = tempo >> 8;
byte b3 = (byte)(tempo & 0xff);
ret.Data = new byte[4] { 0x51, b3, b2, b1 };
return ret;
}
}
public class MidiFile : IDisposable {
private List<List<MidiEvent>> m_events;
private ushort m_format;
private ushort m_time_format;
public MidiFile( string path )
: this( new FileStream( path, FileMode.Open ) ) {
}
public MidiFile( Stream stream ) {
// ヘッダ
byte[] byte4 = new byte[4];
stream.Read( byte4, 0, 4 );
if ( makeUInt32( byte4 ) != 0x4d546864 ) {
throw new ApplicationException( "header error: MThd" );
}
// データ長
stream.Read( byte4, 0, 4 );
uint length = makeUInt32( byte4 );
// フォーマット
stream.Read( byte4, 0, 2 );
m_format = makeUint16( byte4 );
// トラック数
int tracks = 0;
stream.Read( byte4, 0, 2 );
tracks = (int)makeUint16( byte4 );
// 時間分解能
stream.Read( byte4, 0, 2 );
m_time_format = makeUint16( byte4 );
// 各トラックを読込み
m_events = new List<List<MidiEvent>>();
for ( int track = 0; track < tracks; track++ ) {
// ヘッダー
stream.Read( byte4, 0, 4 );
if ( makeUInt32( byte4 ) != 0x4d54726b ) {
throw new ApplicationException( "header error; MTrk" );
}
m_events.Add( new List<MidiEvent>() );
// チャンクサイズ
stream.Read( byte4, 0, 4 );
long size = (long)makeUInt32( byte4 );
long startpos = stream.Position;
// チャンクの終わりまで読込み
long clock = 0;
byte last_status_byte = 0x00;
while ( stream.Position < startpos + size ) {
m_events[track].Add( MidiEvent.read( stream, ref clock, ref last_status_byte ) );
}
}
stream.Close();
}
/*public void Write( string path ) {
}*/
public List<MidiEvent> getMidiEventList( int track ) {
if ( m_events == null ) {
return new List<MidiEvent>();
} else if ( 0 <= track && track < m_events.Count ) {
return m_events[track];
} else {
return new List<MidiEvent>();
}
}
public int getTrackCount() {
if ( m_events == null ) {
return 0;
} else {
return m_events.Count;
}
}
public void Dispose() {
Close();
}
public void Close() {
if ( m_events != null ) {
for ( int i = 0; i < m_events.Count; i++ ) {
m_events[i].Clear();
}
m_events.Clear();
}
}
private static UInt32 makeUInt32( byte[] value ) {
return (uint)((uint)((uint)((uint)(value[0] << 8) | value[1]) << 8 | value[2]) << 8 | value[3]);
}
private static UInt16 makeUint16( byte[] value ) {
return (ushort)((ushort)(value[0] << 8) | value[1]);
}
private static long readDeltaClock( Stream stream ) {
byte[] b;
long ret = 0;
while ( true ) {
byte d = (byte)stream.ReadByte();
ret = (ret << 7) | ((long)d & 0x7f);
if ( (d & 0x80) == 0x00 ) {
break;
}
}
return ret;
}
}
}

View File

@ -0,0 +1,244 @@
/*
* SingerConfig.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.Collections.Generic;
namespace Boare.Lib.Vsq {
public class SingerConfig {
public string ID;
public string FORMAT;
public string VOICEIDSTR;
public string VOICENAME;
public int Breathiness;
public int Brightness;
public int Clearness;
public int Opening;
public int GenderFactor;
public int Original;
public static void decode_vvd_bytes( ref byte[] dat ) {
for ( int i = 0; i < dat.Length; i++ ) {
byte M = (byte)(dat[i] >> 4);
byte L = (byte)(dat[i] - (M << 4));
byte newM = endecode_vvd_m( M );
byte newL = endecode_vvd_l( L );
dat[i] = (byte)((newM << 4) | newL);
}
}
static byte endecode_vvd_l( byte value ) {
switch ( value ) {
case 0x0:
return 0xa;
case 0x1:
return 0xb;
case 0x2:
return 0x8;
case 0x3:
return 0x9;
case 0x4:
return 0xe;
case 0x5:
return 0xf;
case 0x6:
return 0xc;
case 0x7:
return 0xd;
case 0x8:
return 0x2;
case 0x9:
return 0x3;
case 0xa:
return 0x0;
case 0xb:
return 0x1;
case 0xc:
return 0x6;
case 0xd:
return 0x7;
case 0xe:
return 0x4;
case 0xf:
return 0x5;
}
return 0x0;
}
static byte endecode_vvd_m( byte value ) {
switch ( value ) {
case 0x0:
return 0x1;
case 0x1:
return 0x0;
case 0x2:
return 0x3;
case 0x3:
return 0x2;
case 0x4:
return 0x5;
case 0x5:
return 0x4;
case 0x6:
return 0x7;
case 0x7:
return 0x6;
case 0x8:
return 0x9;
case 0x9:
return 0x8;
case 0xa:
return 0xb;
case 0xb:
return 0xa;
case 0xc:
return 0xd;
case 0xd:
return 0xc;
case 0xe:
return 0xf;
case 0xf:
return 0xe;
}
return 0x0;
}
public SingerConfig( string file, int original ) {
original = original;
ID = "VOCALOID:VIRTUAL:VOICE";
FORMAT = "2.0.0.0";
VOICEIDSTR = "";
VOICENAME = "Miku";
Breathiness = 0;
Brightness = 0;
Clearness = 0;
Opening = 0;
GenderFactor = 0;
original = 0;
FileStream fs = null;
try {
fs = new FileStream( file, FileMode.Open, FileAccess.Read );
int length = (int)fs.Length;
byte[] dat = new byte[length];
fs.Read( dat, 0, length );
decode_vvd_bytes( ref dat );
for ( int i = 0; i < dat.Length - 1; i++ ) {
if ( dat[i] == 0x17 && dat[i + 1] == 0x10 ) {
dat[i] = 0x0d;
dat[i + 1] = 0x0a;
}
}
string str = bocoree.cp932.convert( dat );
string crlf = ((char)0x0d).ToString() + ((char)0x0a).ToString();
string[] spl = str.Split( new string[] { crlf }, StringSplitOptions.RemoveEmptyEntries );
foreach ( string s in spl ) {
int first = s.IndexOf( '"' );
int first_end = get_quated_string( s, first );
int second = s.IndexOf( '"', first_end + 1 );
int second_end = get_quated_string( s, second );
char[] chs = s.ToCharArray();
string id = new string( chs, first, first_end - first + 1 );
string value = new string( chs, second, second_end - second + 1 );
id = id.Substring( 1, id.Length - 2 );
value = value.Substring( 1, value.Length - 2 );
value = value.Replace( "\\\"", "\"" );
if ( id == "ID" ) {
ID = value;
} else if ( id == "FORMAT" ) {
FORMAT = value;
} else if ( id == "VOICEIDSTR" ) {
VOICEIDSTR = value;
} else if ( id == "VOICENAME" ) {
VOICENAME = value;
} else if ( id == "Breathiness" ) {
try {
Breathiness = int.Parse( value );
} catch {
}
} else if ( id == "Brightness" ) {
try {
Brightness = int.Parse( value );
} catch {
}
} else if ( id == "Clearness" ) {
try {
Clearness = int.Parse( value );
} catch {
}
} else if ( id == "Opening" ) {
try {
Opening = int.Parse( value );
} catch {
}
} else if ( id == "Gender:Factor" ) {
try {
GenderFactor = int.Parse( value );
} catch {
}
}
}
} catch {
} finally {
if ( fs != null ) {
fs.Close();
}
}
}
/// <summary>
/// 位置positionにある'"'から,次に現れる'"'の位置を調べる.エスケープされた\"はスキップされる.'"'が見つからなかった場合-1を返す
/// </summary>
/// <param name="s"></param>
/// <param name="position"></param>
/// <returns></returns>
static int get_quated_string( string s, int position ) {
if ( position < 0 ) {
return -1;
}
char[] chs = s.ToCharArray();
if ( position >= chs.Length ) {
return -1;
}
if ( chs[position] != '"' ) {
return -1;
}
int end = -1;
for ( int i = position + 1; i < chs.Length; i++ ) {
if ( chs[i] == '"' && chs[i - 1] != '\\' ) {
end = i;
break;
}
}
return end;
}
public new string[] ToString() {
List<string> ret = new List<string>();
ret.Add( "\"ID\":=:\"" + ID + "\"" );
ret.Add( "\"FORMAT\":=:\"" + FORMAT + "\"" );
ret.Add( "\"VOICEIDSTR\":=:\"" + VOICEIDSTR + "\"" );
ret.Add( "\"VOICENAME\":=:\"" + VOICENAME.Replace( "\"", "\\\"" ) + "\"" );
ret.Add( "\"Breathiness\":=:\"" + Breathiness + "\"" );
ret.Add( "\"Brightness\":=:\"" + Brightness + "\"" );
ret.Add( "\"Clearness\":=:\"" + Clearness + "\"" );
ret.Add( "\"Opening\":=:\"" + Opening + "\"" );
ret.Add( "\"Gender:Factor\":=:\"" + GenderFactor + "\"" );
return ret.ToArray();
}
}
}

View File

@ -0,0 +1,676 @@
/*
* SymbolTable.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 System.Windows.Forms;
using bocoree;
namespace Boare.Lib.Vsq {
public class SymbolTable : ICloneable {
private Dictionary<string, string> m_dict;
private string m_name;
private bool m_enabled;
#region Static Field
private static SortedList<int, SymbolTable> s_table = new SortedList<int, SymbolTable>();
private static SymbolTable s_default_jp = null;
private static bool s_initialized = false;
public static readonly string[,] _KEY_JP = {
{"あ", "a"},
{"い", "i"},
{"う", "M"},
{"え", "e"},
{"お", "o"},
{"か", "k a"},
{"き", "k' i"},
{"く", "k M"},
{"け", "k e"},
{"こ", "k o"},
{"さ", "s a"},
{"し", "S i"},
{"す", "s M"},
{"せ", "s e"},
{"そ", "s o"},
{"た", "t a"},
{"ち", "tS i"},
{"つ", "ts M"},
{"て", "t e"},
{"と", "t o"},
{"な", "n a"},
{"に", "J i"},
{"ぬ", "n M"},
{"ね", "n e"},
{"の", "n o"},
{"は", "h a"},
{"ひ", "C i"},
{"ふ", @"p\ M"},
{"へ", "h e"},
{"ほ", "h o"},
{"ま", "m a"},
{"み", "m' i"},
{"む", "m M"},
{"め", "m e"},
{"も", "m o"},
{"や", "j a"},
{"ゆ", "j M"},
{"よ", "j o"},
{"ら", "4 a"},
{"り", "4' i"},
{"る", "4 M"},
{"れ", "4 e "},
{"ろ", "4 o"},
{"わ", "w a"},
{"ゐ", "w i"},
{"ゑ", "w e"},
{"を", "o"},
{"ぁ", "a"},
{"ぃ", "i"},
{"ぅ", "M"},
{"ぇ", "e"},
{"ぉ", "o"},
{"が", "g a"},
{"ぎ", "g' i"},
{"ぐ", "g M"},
{"げ", "g e"},
{"ご", "g o"},
{"ざ", "dz a"},
{"じ", "dZ i"},
{"ず", "dz M"},
{"ぜ", "dz e"},
{"ぞ", "dz o"},
{"だ", "d a"},
{"ぢ", "dZ i"},
{"づ", "dz M"},
{"で", "d e"},
{"ど", "d o"},
{"ば", "b a"},
{"び", "b' i"},
{"ぶ", "b M"},
{"べ", "b e"},
{"ぼ", "b o"},
{"ぱ", "p a"},
{"ぴ", "p' i"},
{"ぷ", "p M"},
{"ぺ", "p e"},
{"ぽ", "p o"},
{"いぇ", "j e"},
{"うぃ", "w i"},
{"うぇ", "w e"},
{"うぉ", "w o"},
{"きゃ", "k' a"},
{"きゅ", "k' M"},
{"きぇ", "k' e"},
{"きょ", "k' o"},
{"しゃ", "S a"},
{"しゅ", "S M"},
{"しぇ", "S e"},
{"しょ", "S o"},
{"ちゃ", "tS a"},
{"ちゅ", "tS M"},
{"ちぇ", "tS e"},
{"ちょ", "tS o"},
{"にゃ", "J a"},
{"にゅ", "J M"},
{"にぇ", "J e"},
{"にょ", "J o"},
{"ひゃ", "C a"},
{"ひゅ", "C M"},
{"ひぇ", "C e"},
{"ひょ", "C o"},
{"ふゃ", @"p\' a"},
{"ふぃ", @"p\' i"},
{"ふゅ", @"p\' M"},
{"ふぇ", @"p\ e"},
{"みゃ", "m' a"},
{"みゅ", "m' M"},
{"みぇ", "m' e"},
{"みょ", "m' o"},
{"りゃ", "4' a"},
{"りゅ", "4' M"},
{"りぇ", "4' e"},
{"りょ", "4' o"},
{"ぎゃ", "g' a"},
{"ぎゅ", "g' M"},
{"ぎぇ", "g' e"},
{"ぎょ", "g' o"},
{"じゃ", "dZ a"},
{"じゅ", "dZ M"},
{"じぇ", "dZ e"},
{"じょ", "dZ o"},
{"びゃ", "b' a"},
{"びゅ", "b' M"},
{"びぇ", "b' e"},
{"びょ", "b' o"},
{"ぴゃ", "p' a"},
{"ぴゅ", "p' M"},
{"ぴぇ", "p' e"},
{"ぴょ", "p' o"},
{"ふぁ", @"p\ a"},
{"ふぉ", @"p\ o"},
{"てゃ", "t' a"},
{"てぃ", "t' i"},
{"てゅ", "t' M"},
{"てぇ", "t' e"},
{"てょ", "t' o"},
{"でゃ", "d' a"},
{"でぃ", "d' i"},
{"でゅ", "d' M"},
{"でぇ", "d' e"},
{"でょ", "d' o"},
{"すぃ", "s i"},
{"ずぃ", "dz i"},
{"とぅ", "t M"},
{"どぅ", "d M"},
{"ゃ", "j a"},
{"ゅ", "j M"},
{"ょ", "j o"},
{"ん", "n"},
{"ア", "a"},
{"イ", "i"},
{"ウ", "M"},
{"エ", "e"},
{"オ", "o"},
{"カ", "k a"},
{"キ", "k' i"},
{"ク", "k M"},
{"ケ", "k e"},
{"コ", "k o"},
{"サ", "s a"},
{"シ", "S i"},
{"ス", "s M"},
{"セ", "s e"},
{"ソ", "s o"},
{"タ", "t a"},
{"チ", "tS i"},
{"ツ", "ts M"},
{"テ", "t e"},
{"ト", "t o"},
{"ナ", "n a"},
{"ニ", "J i"},
{"ヌ", "n M"},
{"ネ", "n e"},
{"", "n o"},
{"ハ", "h a"},
{"ヒ", "C i"},
{"フ", @"p\ M"},
{"ヘ", "h e"},
{"ホ", "h o"},
{"マ", "m a"},
{"ミ", "m' i"},
{"ム", "m M"},
{"メ", "m e"},
{"モ", "m o"},
{"ヤ", "j a"},
{"ユ", "j M"},
{"ヨ", "j o"},
{"ラ", "4 a"},
{"リ", "4' i"},
{"ル", "4 M"},
{"レ", "4 e "},
{"ロ", "4 o"},
{"ワ", "w a"},
{"ヰ", "w i"},
{"ヱ", "w e"},
{"ヲ", "o"},
{"ァ", "a"},
{"ィ", "i"},
{"ゥ", "M"},
{"ェ", "e"},
{"ォ", "o"},
{"ガ", "g a"},
{"ギ", "g' i"},
{"グ", "g M"},
{"ゲ", "g e"},
{"ゴ", "g o"},
{"ザ", "dz a"},
{"ジ", "dZ i"},
{"ズ", "dz M"},
{"ゼ", "dz e"},
{"ゾ", "dz o"},
{"ダ", "d a"},
{"ヂ", "dZ i"},
{"ヅ", "dz M"},
{"デ", "d e"},
{"ド", "d o"},
{"バ", "b a"},
{"ビ", "b' i"},
{"ブ", "b M"},
{"ベ", "b e"},
{"ボ", "b o"},
{"パ", "p a"},
{"ピ", "p' i"},
{"プ", "p M"},
{"ペ", "p e"},
{"ポ", "p o"},
{"イェ", "j e"},
{"ウィ", "w i"},
{"ウェ", "w e"},
{"ウォ", "w o"},
{"キャ", "k' a"},
{"キュ", "k' M"},
{"キェ", "k' e"},
{"キョ", "k' o"},
{"シャ", "S a"},
{"シュ", "S M"},
{"シェ", "S e"},
{"ショ", "S o"},
{"チャ", "tS a"},
{"チュ", "tS M"},
{"チェ", "tS e"},
{"チョ", "tS o"},
{"ニャ", "J a"},
{"ニュ", "J M"},
{"ニェ", "J e"},
{"ニョ", "J o"},
{"ヒャ", "C a"},
{"ヒュ", "C M"},
{"ヒェ", "C e"},
{"ヒョ", "C o"},
{"フャ", @"p\' a"},
{"フィ", @"p\' i"},
{"フュ", @"p\' M"},
{"フェ", @"p\ e"},
{"ミャ", "m' a"},
{"ミュ", "m' M"},
{"ミェ", "m' e"},
{"ミョ", "m' o"},
{"リャ", "4' a"},
{"リュ", "4' M"},
{"リェ", "4' e"},
{"リョ", "4' o"},
{"ギャ", "g' a"},
{"ギュ", "g' M"},
{"ギェ", "g' e"},
{"ギョ", "g' o"},
{"ジャ", "dZ a"},
{"ジュ", "dZ M"},
{"ジェ", "dZ e"},
{"ジョ", "dZ o"},
{"ビャ", "b' a"},
{"ビュ", "b' M"},
{"ビェ", "b' e"},
{"ビョ", "b' o"},
{"ピャ", "p' a"},
{"ピュ", "p' M"},
{"ピェ", "p' e"},
{"ピョ", "p' o"},
{"ファ", @"p\ a"},
{"フォ", @"p\ o"},
{"テャ", "t' a"},
{"ティ", "t' i"},
{"テュ", "t' M"},
{"テェ", "t' e"},
{"テョ", "t' o"},
{"デャ", "d' a"},
{"ディ", "d' i"},
{"デュ", "d' M"},
{"デェ", "d' e"},
{"デョ", "d' o"},
{"スィ", "s i"},
{"ズィ", "dz i"},
{"トゥ", "t M"},
{"ドゥ", "d M"},
{"ャ", "j a"},
{"ュ", "j M"},
{"ョ", "j o"},
{"ン", "n"},
{"ヴ", "b M"},
{"a", "a"},
{"e", "e"},
{"i", "i"},
{"m", "n"},
{"n", "n"},
{"o", "o"},
{"u", "M"},
{"A", "a"},
{"E", "e"},
{"I", "i"},
{"M", "n"},
{"N", "n"},
{"O", "o"},
{"U", "M"},
{"ka", "k a"},
{"ki", "k' i"},
{"ku", "k M"},
{"ke", "k e"},
{"ko", "k o"},
{"kya", "k' a"},
{"kyu", "k' M"},
{"kyo", "k' o"},
{"sa", "s a"},
{"si", "s i"},
{"su", "s M"},
{"se", "s e"},
{"so", "s o"},
{"ta", "t a"},
{"ti", "t' i"},
{"tu", "t M"},
{"te", "t e"},
{"to", "t o"},
{"tya", "t' a"},
{"tyu", "t' M"},
{"tyo", "t' o"},
{"na", "n a"},
{"ni", "J i"},
{"nu", "n M"},
{"ne", "n e"},
{"no", "n o"},
{"nya", "J a"},
{"nyu", "J M"},
{"nyo", "J o"},
{"ha", "h a"},
{"hi", "C i"},
{"he", "h e"},
{"ho", "h o"},
{"hya", "C a"},
{"hyu", "C M"},
{"hyo", "C o"},
{"ma", "m a"},
{"mi", "m' i"},
{"mu", "m M"},
{"me", "m e"},
{"mo", "m o"},
{"mya", "m' a"},
{"myu", "m' M"},
{"myo", "m' o"},
{"ya", "j a"},
{"yu", "j M"},
{"ye", "j e"},
{"yo", "j o"},
{"ra", "4 a"},
{"ri", "4' i"},
{"ru", "4 M"},
{"re", "4 e"},
{"ro", "4 o"},
{"rya", "4' a"},
{"ryu", "4' M"},
{"ryo", "4' o"},
{"wa", "w a"},
{"wi", "w i"},
{"we", "w e"},
{"wo", "w o"},
{"ga", "g a"},
{"gi", "g' i"},
{"gu", "g M"},
{"ge", "g e"},
{"go", "g o"},
{"gya", "g' a"},
{"gyu", "g' M"},
{"gyo", "g' o"},
{"za", "dz a"},
{"zi", "dz i"},
{"zu", "dz M"},
{"ze", "dz e"},
{"zo", "dz o"},
{"da", "d a"},
{"di", "d' i"},
{"du", "d M"},
{"de", "d e"},
{"do", "d o"},
{"dya", "d' a"},
{"dyu", "d' M"},
{"dyo", "d' o"},
{"ba", "b a"},
{"bi", "b' i"},
{"bu", "b M"},
{"be", "b e"},
{"bo", "b o"},
{"bya", "b' a"},
{"byu", "b' M"},
{"byo", "b' o"},
{"pa", "p a"},
{"pi", "p' i"},
{"pu", "p M"},
{"pe", "p e"},
{"po", "p o"},
{"pya", "p' a"},
{"pyu", "p' M"},
{"pyo", "p' o"},
{"sha", "S a"},
{"shi", "S i"},
{"shu", "S M"},
{"sho", "S o"},
{"tsu", "ts M"},
{"cha", "tS a"},
{"chi", "tS i"},
{"chu", "tS M"},
{"cho", "tS o"},
{"fu", @"p\ M"},
{"ja", "dZ a"},
{"ji", "dZ i"},
{"ju", "dZ M"},
{"jo", "dZ o"},
};
#endregion
#region Static Method and Property
public static SymbolTable getSymbolTable( int index ) {
if ( !s_initialized ) {
loadDictionary();
}
if ( 0 <= index && index < s_table.Count ) {
return s_table[index];
} else {
return null;
}
}
public static void loadDictionary() {
#if DEBUG
Console.WriteLine( "SymbolTable.LoadDictionary()" );
#endif
s_default_jp = new SymbolTable( "DEFAULT_JP", _KEY_JP, true );
s_table.Clear();
s_table.Add( 0, s_default_jp );
int count = 0;
// 辞書フォルダからの読込み
string editor_path = VsqUtil.getEditorPath();
if ( editor_path.Length > 0 ) {
string path = Path.Combine( Path.GetDirectoryName( editor_path ), "UDIC" );
if ( !Directory.Exists( path ) ) {
return;
}
string[] files = Directory.GetFiles( path, "*.udc" );
for ( int i = 0; i < files.Length; i++ ) {
files[i] = Path.GetFileName( files[i] );
#if DEBUG
Console.WriteLine( " files[i]=" + files[i] );
#endif
count++;
string dict = Path.Combine( path, files[i] );
s_table.Add( count, new SymbolTable( dict, true, false ) );
}
}
// 起動ディレクトリ
string path2 = Path.Combine( Application.StartupPath, "udic" );
if ( Directory.Exists( path2 ) ) {
string[] files2 = Directory.GetFiles( path2, "*.eudc" );
for ( int i = 0; i < files2.Length; i++ ) {
files2[i] = Path.GetFileName( files2[i] );
#if DEBUG
Console.WriteLine( " files2[i]=" + files2[i] );
#endif
count++;
string dict = Path.Combine( path2, files2[i] );
s_table.Add( count, new SymbolTable( dict, false, false ) );
}
}
s_initialized = true;
}
public static bool attatch( string phrase, out string result ) {
#if DEBUG
Console.WriteLine( "SymbolTable.Attatch" );
Console.WriteLine( " phrase=" + phrase );
#endif
for ( int i = 0; i < s_table.Keys.Count; i++ ) {
int key = s_table.Keys[i];
if ( s_table[key].isEnabled() ) {
if ( s_table[key].attatchImp( phrase, out result ) ) {
return true;
}
}
}
result = "a";
return false;
}
public static int getCount() {
if ( !s_initialized ) {
loadDictionary();
}
return s_table.Count;
}
public static void changeOrder( KeyValuePair<string, bool>[] list ) {
#if DEBUG
Console.WriteLine( "SymbolTable.Sort()" );
#endif
SortedList<int, SymbolTable> buff = new SortedList<int, SymbolTable>();
foreach ( int key in s_table.Keys ) {
buff.Add( key, (SymbolTable)s_table[key].Clone() );
}
s_table.Clear();
for ( int i = 0; i < list.Length; i++ ) {
#if DEBUG
Console.WriteLine( " list[i]=" + list[i].Key + "," + list[i].Value );
#endif
for ( int j = 0; j < buff.Keys.Count; j++ ) {
int key = buff.Keys[j];
if ( buff[key].getName() == list[i].Key ) {
buff[key].setEnabled( list[i].Value );
s_table.Add( i, buff[key] );
break;
}
}
}
}
#endregion
public object Clone() {
SymbolTable ret = new SymbolTable();
ret.m_dict = new Dictionary<string, string>();
foreach ( string key in m_dict.Keys ) {
ret.m_dict.Add( key, m_dict[key] );
}
ret.m_name = m_name;
ret.m_enabled = m_enabled;
return ret;
}
private SymbolTable() {
}
public string getName() {
return m_name;
}
public bool isEnabled() {
return m_enabled;
}
public void setEnabled( bool value ){
m_enabled = value;
}
public SymbolTable( string path, bool is_udc_mode, bool enabled ) {
m_dict = new Dictionary<string, string>();
m_enabled = enabled;
if ( !File.Exists( path ) ) {
return;
}
m_name = Path.GetFileName( path );
cp932reader sr1 = null;
StreamReader sr2 = null;
try {
if ( is_udc_mode ) {
sr1 = new cp932reader( path );
if ( sr1 == null ) {
return;
}
} else {
sr2 = new StreamReader( path, Encoding.UTF8 );
if ( sr2 == null ) {
return;
}
}
string line;
int peek = (is_udc_mode) ? sr1.Peek() : sr2.Peek();
while ( peek >= 0 ) {
line = (is_udc_mode) ? sr1.ReadLine() : sr2.ReadLine();
if ( !line.StartsWith( "//" ) ) {
string[] spl = line.Split( "\t".ToCharArray(), 2, StringSplitOptions.RemoveEmptyEntries );
if ( spl.Length >= 2 ) {
if ( m_dict.ContainsKey( spl[0] ) ) {
bocoree.debug.push_log( "SymbolTable..ctor" );
bocoree.debug.push_log( " dictionary already contains key: " + spl[0] );
} else {
m_dict.Add( spl[0], spl[1] );
}
}
}
peek = (is_udc_mode) ? sr1.Peek() : sr2.Peek();
}
} catch ( Exception ex ) {
bocoree.debug.push_log( "SymbolTable..ctor" );
bocoree.debug.push_log( " " + ex );
} finally {
if ( sr1 != null ) {
sr1.Close();
}
if ( sr2 != null ) {
sr2.Close();
}
}
}
private bool attatchImp( string phrase, out string result ) {
string s = phrase.ToLower();
if ( m_dict.ContainsKey( s ) ) {
result = m_dict[s];
return true;
} else {
result = "a";
return false;
}
}
private SymbolTable( string name, string[,] key, bool enabled ) {
#if DEBUG
Console.WriteLine( "SymolTable.ctor(string,string[,])" );
Console.WriteLine( " key.GetLength(0)=" + key.GetLength( 0 ) );
#endif
m_enabled = enabled;
m_name = name;
m_dict = new Dictionary<string, string>();
for ( int i = 0; i < key.GetLength( 0 ); i++ ) {
if ( m_dict.ContainsKey( key[i, 0] ) ) {
#if DEBUG
throw new ApplicationException( "dictionary already contains key: " + key[i, 0] );
#endif
} else {
m_dict.Add( key[i, 0], key[i, 1] );
}
}
}
}
}

View File

@ -0,0 +1,48 @@
/*
* 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 {
[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 int CompareTo( TempoTableEntry entry ) {
return this.Clock - entry.Clock;
}
public bool Equals( TempoTableEntry entry ) {
if ( this.Clock == entry.Clock ) {
return true;
} else {
return false;
}
}
}
}

View File

@ -0,0 +1,127 @@
/*
* TextMemoryStream.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;
namespace Boare.Lib.Vsq {
/// <summary>
/// メモリー上でテキストファイルを扱うためのクラス.
/// </summary>
public class TextMemoryStream : IDisposable {
FileAccess m_access;
MemoryStream m_ms = null;
Encoding m_enc;
byte[] NEW_LINE;
/// <summary>
///
/// </summary>
/// <param name="s"></param>
public void write( string value ) {
byte[] buff = m_enc.GetBytes( value );
m_ms.Write( buff, 0, buff.Length );
}
public void rewind() {
m_ms.Seek( 0, SeekOrigin.Begin );
}
public void writeLine( string s ) {
byte[] buff = m_enc.GetBytes( s + Environment.NewLine );
m_ms.Write( buff, 0, buff.Length );
}
public void close() {
if ( m_ms != null ) {
m_ms.Close();
}
}
public int peek() {
long current = m_ms.Position;
int ret = m_ms.ReadByte();
m_ms.Seek( current, SeekOrigin.Begin );
return ret;
}
public string readLine() {
List<byte> buffer = new List<byte>();
byte value;
int ret;
ret = m_ms.ReadByte();
while ( ret >= 0 ) {
value = (byte)ret;
if ( value == NEW_LINE[0] ) {
byte next;
long current = m_ms.Position; //0x0Dを検出した直後のストリームの位置
for ( int i = 1; i < NEW_LINE.Length; i++ ) {
ret = m_ms.ReadByte();
if ( ret >= 0 ) {
next = (byte)ret;
if ( next != NEW_LINE[i] ) {
m_ms.Seek( current, SeekOrigin.Begin );
break;
}
}
}
break;
}
buffer.Add( value );
ret = m_ms.ReadByte();
}
return Encoding.Unicode.GetString( buffer.ToArray() );
}
public void Dispose() {
if ( m_ms != null ) {
m_ms.Close();
}
}
public TextMemoryStream( string path, Encoding encode ) {
m_access = FileAccess.Read;
m_ms = new MemoryStream();
m_enc = encode;
if ( File.Exists( path ) ) {
using ( StreamReader sr = new StreamReader( path, encode ) ) {
while ( sr.Peek() >= 0 ) {
string line = sr.ReadLine();
byte[] buffer = m_enc.GetBytes( line + Environment.NewLine );
m_ms.Write( buffer, 0, buffer.Length );
}
}
m_ms.Seek( 0, SeekOrigin.Begin );
}
NEW_LINE = m_enc.GetBytes( Environment.NewLine );
}
public TextMemoryStream( FileAccess access ) {
m_access = access;
m_ms = new MemoryStream();
m_enc = Encoding.Unicode;
NEW_LINE = m_enc.GetBytes( Environment.NewLine );
}
public TextMemoryStream() {
m_access = FileAccess.Write;
m_ms = new MemoryStream();
m_enc = Encoding.Unicode;
NEW_LINE = m_enc.GetBytes( Environment.NewLine );
}
}
}

View File

@ -0,0 +1,61 @@
/*
* TimeSigTableEntry.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;
namespace Boare.Lib.Vsq{
[Serializable]
public class TimeSigTableEntry : IComparable<TimeSigTableEntry>, ICloneable {
/// <summary>
/// クロック数
/// </summary>
public int Clock;
/// <summary>
/// 拍子の分子
/// </summary>
public int Numerator;
/// <summary>
/// 拍子の分母
/// </summary>
public int Denominator;
/// <summary>
/// 何小節目か
/// </summary>
public int BarCount;
public TimeSigTableEntry(
int clock,
int numerator,
int denominator,
int bar_count ) {
Clock = clock;
Numerator = numerator;
Denominator = denominator;
BarCount = bar_count;
}
public override string ToString() {
return "{Clock=" + Clock + ", Numerator=" + Numerator + ", Denominator=" + Denominator + ", BarCount=" + BarCount + "}";
}
public object Clone() {
return new TimeSigTableEntry( Clock, Numerator, Denominator, BarCount );
}
public int CompareTo( TimeSigTableEntry item ) {
return this.BarCount - item.BarCount;
}
}
}

View File

@ -0,0 +1,74 @@
/*
* UstEvent.cs
* Copyright (c) 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.Collections.Generic;
using System.Text;
namespace Boare.Lib.Vsq {
public class UstEvent : ICloneable {
public object Tag;
public int Length = 0;
public string Lyric = "";
public int Note = -1;
public int Intensity = -1;
public int PBType = -1;
public float[] Pitches = null;
public float Tempo = -1;
public object Clone() {
UstEvent ret = new UstEvent();
ret.Length = Length;
ret.Lyric = Lyric;
ret.Note = Note;
ret.Intensity = Intensity;
ret.PBType = PBType;
if ( Pitches != null ) {
ret.Pitches = new float[Pitches.Length];
for ( int i = 0; i < Pitches.Length; i++ ) {
ret.Pitches[i] = Pitches[i];
}
}
ret.Tempo = Tempo;
return ret;
}
public void print( StreamWriter sw, uint index ) {
sw.WriteLine( string.Format( "[#{0:d4}]", index ) );
sw.WriteLine( "Length=" + Length );
sw.WriteLine( "Lyric=" + Lyric );
sw.WriteLine( "NoteNum=" + Note );
if ( Intensity >= 0 ) {
sw.WriteLine( "Intensity=" + Intensity );
}
if ( PBType >= 0 && Pitches != null ) {
sw.WriteLine( "PBType=" + PBType );
sw.Write( "Piches=" );
for ( int i = 0; i < Pitches.Length; i++ ) {
if ( i == 0 ) {
sw.Write( Pitches[i] );
} else {
sw.Write( "," + Pitches[i] );
}
}
sw.WriteLine();
}
if ( Tempo > 0 ) {
sw.WriteLine( "Tempo=" + Tempo );
}
}
}
}

View File

@ -0,0 +1,259 @@
/*
* 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 = 125.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(); // "[#" 直下の行
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;
}
}
}
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の部分を更新します
/// </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; //最後にTempo値が代入されていたイベントのクロック
float last_tempo = m_tempo; //最後に代入されていたテンポの値
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>
/// 指定したクロックにおける、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 = 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;
}
}
}

View File

@ -0,0 +1,60 @@
/*
* UstTrack.cs
* Copyright (c) 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 UstTrack : ICloneable {
public object Tag;
private List<UstEvent> m_events;
public UstTrack(){
m_events = new List<UstEvent>();
}
public UstEvent getEvent( int index ) {
return m_events[index];
}
public void setEvent( int index, UstEvent item ) {
m_events[index] = item;
}
public void addEvent( UstEvent item ) {
m_events.Add( item );
}
public void removeEvent( int index ) {
m_events.RemoveAt( index );
}
public int getEventCount() {
return m_events.Count;
}
public Iterator getNoteEventIterator() {
return new ListIterator<UstEvent>( m_events );
}
public object Clone() {
UstTrack ret = new UstTrack();
for ( int i = 0; i < m_events.Count; i++ ) {
ret.m_events[i] = (UstEvent)m_events[i].Clone();
}
return ret;
}
}
}

View File

@ -0,0 +1,62 @@
/*
* VibratoBPList.cs
* Copyright (c) 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 VibratoBPList : ICloneable {
private List<VibratoBPPair> m_list;
public VibratoBPList() {
m_list = new List<VibratoBPPair>();
}
public VibratoBPList( float[] x, int[] y ){
if ( x == null ){
throw new ArgumentNullException( "x" );
}
if ( y == null ){
throw new ArgumentNullException( "y" );
}
int len = Math.Min( x.Length, y.Length );
m_list = new List<VibratoBPPair>( len );
for ( int i = 0; i < len; i++ ) {
m_list.Add( new VibratoBPPair( x[i], y[i] ) );
}
m_list.Sort();
}
public object Clone() {
VibratoBPList ret = new VibratoBPList();
for ( int i = 0; i < m_list.Count; i++ ) {
ret.m_list.Add( new VibratoBPPair( m_list[i].X, m_list[i].Y ) );
}
return ret;
}
public int getCount() {
return m_list.Count;
}
public VibratoBPPair getElement( int index ) {
return m_list[index];
}
public void setElement( int index, VibratoBPPair value ) {
m_list[index] = value;
}
}
}

View File

@ -0,0 +1,38 @@
/*
* VibratoBPPair.cs
* Copyright (c) 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;
namespace Boare.Lib.Vsq {
public class VibratoBPPair : IComparable<VibratoBPPair> {
public float X;
public int Y;
public VibratoBPPair( float x, int y ) {
X = x;
Y = y;
}
public int CompareTo( VibratoBPPair item ) {
float v = X - item.X;
if ( v > 0.0f ) {
return 1;
} else if ( v < 0.0f ) {
return -1;
}
return 0;
}
}
}

View File

@ -0,0 +1,351 @@
/*
* VibratoType.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;
namespace Boare.Lib.Vsq {
/// <summary>
/// ビブラートのプリセット・タイプを表します
/// </summary>
public enum VibratoType : int {
/// <summary>
/// NormalType1
/// </summary>
NormalType1 = 1,
/// <summary>
/// NrormalType2
/// </summary>
NormalType2,
/// <summary>
/// NormalType3
/// </summary>
NormalType3,
/// <summary>
/// NormalType4
/// </summary>
NormalType4,
/// <summary>
/// ExtremeType1
/// </summary>
ExtremeType1,
/// <summary>
/// ExtremeType2
/// </summary>
ExtremeType2,
/// <summary>
/// ExtremeType3
/// </summary>
ExtremeType3,
/// <summary>
/// ExtremeType4
/// </summary>
ExtremeType4,
/// <summary>
/// FastType1
/// </summary>
FastType1,
/// <summary>
/// FastType2
/// </summary>
FastType2,
/// <summary>
/// FastType3
/// </summary>
FastType3,
/// <summary>
/// FastType4
/// </summary>
FastType4,
/// <summary>
/// SlightType1
/// </summary>
SlightType1,
/// <summary>
/// SlightType2
/// </summary>
SlightType2,
/// <summary>
/// SlightType3
/// </summary>
SlightType3,
/// <summary>
/// SlightType4
/// </summary>
SlightType4,
}
/// <summary>
/// VibratoTypeのためのユーティリティを集めたスタティック・クラス
/// </summary>
public static class VibratoTypeUtil {
/// <summary>
/// IconID文字列からVibratoTypeを調べます
/// </summary>
/// <param name="icon_id"></param>
/// <returns></returns>
public static VibratoType getVibratoTypeFromIconID( string icon_id ) {
switch ( icon_id ) {
case "$04040001":
return VibratoType.NormalType1;
case "$04040002":
return VibratoType.NormalType2;
case "$04040003":
return VibratoType.NormalType3;
case "$0400004":
return VibratoType.NormalType4;
case "$04040005":
return VibratoType.ExtremeType1;
case "$04040006":
return VibratoType.ExtremeType2;
case "$04040007":
return VibratoType.ExtremeType3;
case "$04040008":
return VibratoType.ExtremeType4;
case "$04040009":
return VibratoType.FastType1;
case "$0404000a":
return VibratoType.FastType2;
case "$0404000b":
return VibratoType.FastType3;
case "$0404000c":
return VibratoType.FastType4;
case "$0404000d":
return VibratoType.SlightType1;
case "$0404000e":
return VibratoType.SlightType2;
case "$0404000f":
return VibratoType.SlightType3;
case "$04040010":
return VibratoType.SlightType4;
}
return VibratoType.NormalType1;
}
/// <summary>
/// 指定されたVibratoTypeを表すIconIDを取得します
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public static string getIconIDFromVibratoType( VibratoType type ) {
switch ( type ) {
case VibratoType.NormalType1:
return "$04040001";
case VibratoType.NormalType2:
return "$04040002";
case VibratoType.NormalType3:
return "$04040003";
case VibratoType.NormalType4:
return "$0400004";
case VibratoType.ExtremeType1:
return "$04040005";
case VibratoType.ExtremeType2:
return "$04040006";
case VibratoType.ExtremeType3:
return "$04040007";
case VibratoType.ExtremeType4:
return "$04040008";
case VibratoType.FastType1:
return "$04040009";
case VibratoType.FastType2:
return "$0404000a";
case VibratoType.FastType3:
return "$0404000b";
case VibratoType.FastType4:
return "$0404000c";
case VibratoType.SlightType1:
return "$0404000d";
case VibratoType.SlightType2:
return "$0404000e";
case VibratoType.SlightType3:
return "$0404000f";
case VibratoType.SlightType4:
return "$04040010";
}
return "";
}
/// <summary>
/// ビブラートのプリセットタイプからVibratoHandleを作成します
/// </summary>
/// <param name="type"></param>
/// <param name="vibrato_clocks"></param>
/// <returns></returns>
public static VibratoHandle getDefaultVibratoHandle( VibratoType type, int vibrato_clocks ) {
VibratoHandle res = new VibratoHandle();
res.Length = vibrato_clocks;
res.Original = 1;
//res.DepthBPNum = 0;
//res.RateBPNum = 0;
res.Caption = ToString( type );
res.IconID = getIconIDFromVibratoType( type );
switch ( type ) {
case VibratoType.NormalType1:
res.IDS = "normal";
res.StartDepth = 64;
res.StartRate = 50;
break;
case VibratoType.NormalType2:
res.IDS = "normal";
res.StartDepth = 40;
res.StartRate = 40;
break;
case VibratoType.NormalType3:
res.IDS = "normal";
res.StartDepth = 127;
res.StartRate = 50;
break;
case VibratoType.NormalType4:
res.IDS = "normal";
res.StartDepth = 64;
//res.DepthBPNum = 57;
res.DepthBP = new VibratoBPList( new float[57] { 0.603900f, 0.612500f, 0.616400f, 0.621100f, 0.625000f, 0.633600f, 0.637500f, 0.641400f, 0.646100f, 0.653900f, 0.658600f, 0.666400f, 0.670300f, 0.675000f, 0.678900f, 0.683600f, 0.691400f, 0.696100f, 0.703900f, 0.708600f, 0.712500f, 0.716400f, 0.721100f, 0.725000f, 0.728900f, 0.737500f, 0.746100f, 0.750000f, 0.758600f, 0.762500f, 0.766400f, 0.771100f, 0.775000f, 0.783600f, 0.791400f, 0.795300f, 0.800000f, 0.803900f, 0.808600f, 0.812500f, 0.821100f, 0.828900f, 0.837500f, 0.841400f, 0.846100f, 0.850000f, 0.853900f, 0.862500f, 0.866400f, 0.875000f, 0.878900f, 0.883600f, 0.887500f, 0.891400f, 0.896100f, 0.900000f, 1.000000f },
new int[57] { 64, 63, 62, 61, 59, 58, 57, 56, 55, 54, 52, 51, 50, 49, 48, 47, 45, 44, 43, 42, 41, 40, 39, 38, 37, 35, 34, 32, 31, 30, 29, 28, 27, 25, 24, 23, 22, 21, 20, 19, 17, 15, 14, 13, 12, 11, 10, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0 } );
res.StartRate = 50;
//res.RateBPNum = 52;
res.RateBP = new VibratoBPList( new float[52] { 0.600000f, 0.612500f, 0.616400f, 0.621100f, 0.628900f, 0.633600f, 0.637500f, 0.641400f, 0.653900f, 0.658600f, 0.662500f, 0.666400f, 0.675000f, 0.683600f, 0.687500f, 0.691400f, 0.700000f, 0.703900f, 0.708600f, 0.712500f, 0.725000f, 0.728900f, 0.732800f, 0.737500f, 0.746100f, 0.750000f, 0.758600f, 0.762500f, 0.771100f, 0.775000f, 0.778900f, 0.783600f, 0.795300f, 0.800000f, 0.803900f, 0.808600f, 0.816400f, 0.821100f, 0.828900f, 0.833600f, 0.841400f, 0.846100f, 0.850000f, 0.853900f, 0.866400f, 0.871100f, 0.875000f, 0.878900f, 0.887500f, 0.891400f, 0.900000f, 1.000000f },
new int[52] { 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0 } );
break;
case VibratoType.ExtremeType1:
res.IDS = "extreme";
res.StartDepth = 64;
res.StartRate = 64;
break;
case VibratoType.ExtremeType2:
res.IDS = "extreme";
res.StartDepth = 32;
res.StartRate = 32;
break;
case VibratoType.ExtremeType3:
res.IDS = "extreme";
res.StartDepth = 100;
res.StartRate = 50;
break;
case VibratoType.ExtremeType4:
res.IDS = "extreme";
res.StartDepth = 64;
//res.DepthBPNum = 57;
res.DepthBP = new VibratoBPList( new float[57] { 0.603900f, 0.612500f, 0.616400f, 0.621100f, 0.625000f, 0.633600f, 0.637500f, 0.641400f, 0.646100f, 0.653900f, 0.658600f, 0.666400f, 0.670300f, 0.675000f, 0.678900f, 0.683600f, 0.691400f, 0.696100f, 0.703900f, 0.708600f, 0.712500f, 0.716400f, 0.721100f, 0.725000f, 0.728900f, 0.737500f, 0.746100f, 0.750000f, 0.758600f, 0.762500f, 0.766400f, 0.771100f, 0.775000f, 0.783600f, 0.791400f, 0.795300f, 0.800000f, 0.803900f, 0.808600f, 0.812500f, 0.821100f, 0.828900f, 0.837500f, 0.841400f, 0.846100f, 0.850000f, 0.853900f, 0.862500f, 0.866400f, 0.875000f, 0.878900f, 0.883600f, 0.887500f, 0.891400f, 0.896100f, 0.900000f, 1.000000f },
new int[57] { 64, 63, 62, 61, 59, 58, 57, 56, 55, 54, 52, 51, 50, 49, 48, 47, 45, 44, 43, 42, 41, 40, 39, 38, 37, 35, 34, 32, 31, 30, 29, 28, 27, 25, 24, 23, 22, 21, 20, 19, 17, 15, 14, 13, 12, 11, 10, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0 } );
res.StartRate = 64;
//res.RateBPNum = 57;
res.RateBP = new VibratoBPList( new float[57] { 0.603900f, 0.612500f, 0.616400f, 0.621100f, 0.625000f, 0.633600f, 0.637500f, 0.641400f, 0.646100f, 0.653900f, 0.658600f, 0.666400f, 0.670300f, 0.675000f, 0.678900f, 0.683600f, 0.691400f, 0.696100f, 0.703900f, 0.708600f, 0.712500f, 0.716400f, 0.721100f, 0.725000f, 0.728900f, 0.737500f, 0.746100f, 0.750000f, 0.758600f, 0.762500f, 0.766400f, 0.771100f, 0.775000f, 0.783600f, 0.791400f, 0.795300f, 0.800000f, 0.803900f, 0.808600f, 0.812500f, 0.821100f, 0.828900f, 0.837500f, 0.841400f, 0.846100f, 0.850000f, 0.853900f, 0.862500f, 0.866400f, 0.875000f, 0.878900f, 0.883600f, 0.887500f, 0.891400f, 0.896100f, 0.900000f, 1.000000f },
new int[57] { 64, 63, 62, 61, 59, 58, 57, 56, 55, 54, 52, 51, 50, 49, 48, 47, 45, 44, 43, 42, 41, 40, 39, 38, 37, 35, 34, 32, 31, 30, 29, 28, 27, 25, 24, 23, 22, 21, 20, 19, 17, 15, 14, 13, 12, 11, 10, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0 } );
break;
case VibratoType.FastType1:
res.IDS = "fast";
res.StartDepth = 64;
res.StartRate = 64;
break;
case VibratoType.FastType2:
res.IDS = "fast";
res.StartDepth = 40;
res.StartRate = 50;
break;
case VibratoType.FastType3:
res.IDS = "fast";
res.StartDepth = 80;
res.StartRate = 70;
break;
case VibratoType.FastType4:
res.IDS = "fast";
res.StartDepth = 64;
//res.DepthBPNum = 57;
res.DepthBP = new VibratoBPList( new float[57] { 0.603900f, 0.612500f, 0.616400f, 0.621100f, 0.625000f, 0.633600f, 0.637500f, 0.641400f, 0.646100f, 0.653900f, 0.658600f, 0.666400f, 0.670300f, 0.675000f, 0.678900f, 0.683600f, 0.691400f, 0.696100f, 0.703900f, 0.708600f, 0.712500f, 0.716400f, 0.721100f, 0.725000f, 0.728900f, 0.737500f, 0.746100f, 0.750000f, 0.758600f, 0.762500f, 0.766400f, 0.771100f, 0.775000f, 0.783600f, 0.791400f, 0.795300f, 0.800000f, 0.803900f, 0.808600f, 0.812500f, 0.821100f, 0.828900f, 0.837500f, 0.841400f, 0.846100f, 0.850000f, 0.853900f, 0.862500f, 0.866400f, 0.875000f, 0.878900f, 0.883600f, 0.887500f, 0.891400f, 0.896100f, 0.900000f, 1.000000f },
new int[57] { 64, 63, 62, 61, 59, 58, 57, 56, 55, 54, 52, 51, 50, 49, 48, 47, 45, 44, 43, 42, 41, 40, 39, 38, 37, 35, 34, 32, 31, 30, 29, 28, 27, 25, 24, 23, 22, 21, 20, 19, 17, 15, 14, 13, 12, 11, 10, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0 } );
res.StartRate = 64;
//res.RateBPNum = 57;
res.RateBP = new VibratoBPList( new float[57] { 0.603900f, 0.612500f, 0.616400f, 0.621100f, 0.625000f, 0.633600f, 0.637500f, 0.641400f, 0.646100f, 0.653900f, 0.658600f, 0.666400f, 0.670300f, 0.675000f, 0.678900f, 0.683600f, 0.691400f, 0.696100f, 0.703900f, 0.708600f, 0.712500f, 0.716400f, 0.721100f, 0.725000f, 0.728900f, 0.737500f, 0.746100f, 0.750000f, 0.758600f, 0.762500f, 0.766400f, 0.771100f, 0.775000f, 0.783600f, 0.791400f, 0.795300f, 0.800000f, 0.803900f, 0.808600f, 0.812500f, 0.821100f, 0.828900f, 0.837500f, 0.841400f, 0.846100f, 0.850000f, 0.853900f, 0.862500f, 0.866400f, 0.875000f, 0.878900f, 0.883600f, 0.887500f, 0.891400f, 0.896100f, 0.900000f, 1.000000f },
new int[57] { 64, 63, 62, 61, 59, 58, 57, 56, 55, 54, 52, 51, 50, 49, 48, 47, 45, 44, 43, 42, 41, 40, 39, 38, 37, 35, 34, 32, 31, 30, 29, 28, 27, 25, 24, 23, 22, 21, 20, 19, 17, 15, 14, 13, 12, 11, 10, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0 } );
break;
case VibratoType.SlightType1:
res.IDS = "slight";
res.StartDepth = 64;
res.StartRate = 64;
break;
case VibratoType.SlightType2:
res.IDS = "slight";
res.StartDepth = 40;
res.StartRate = 64;
break;
case VibratoType.SlightType3:
res.IDS = "slight";
res.StartDepth = 72;
res.StartRate = 64;
break;
case VibratoType.SlightType4:
res.IDS = "slight";
res.StartDepth = 64;
//res.DepthBPNum = 57;
res.DepthBP = new VibratoBPList( new float[57] { 0.604300f, 0.612500f, 0.616800f, 0.620700f, 0.625000f, 0.633200f, 0.637500f, 0.641800f, 0.645700f, 0.654300f, 0.658200f, 0.666800f, 0.670700f, 0.675000f, 0.679300f, 0.683200f, 0.691800f, 0.695700f, 0.704300f, 0.708200f, 0.712500f, 0.716800f, 0.720700f, 0.725000f, 0.729300f, 0.737500f, 0.745700f, 0.750000f, 0.758200f, 0.762500f, 0.766800f, 0.770700f, 0.775000f, 0.783200f, 0.791800f, 0.795700f, 0.800000f, 0.804300f, 0.808200f, 0.812500f, 0.820700f, 0.829300f, 0.837500f, 0.841800f, 0.845700f, 0.850000f, 0.854300f, 0.862500f, 0.866800f, 0.875000f, 0.879300f, 0.883200f, 0.887500f, 0.891800f, 0.895700f, 0.900000f, 1.000000f },
new int[57] { 64, 63, 62, 61, 59, 58, 57, 56, 55, 54, 52, 51, 50, 49, 48, 47, 45, 44, 43, 42, 41, 40, 39, 38, 37, 35, 34, 32, 31, 30, 29, 28, 27, 25, 24, 23, 22, 21, 20, 19, 17, 15, 14, 13, 12, 11, 10, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0 } );
res.StartRate = 64;
//res.RateBPNum = 57;
res.RateBP = new VibratoBPList( new float[57] { 0.604300f, 0.612500f, 0.616800f, 0.620700f, 0.625000f, 0.633200f, 0.637500f, 0.641800f, 0.645700f, 0.654300f, 0.658200f, 0.666800f, 0.670700f, 0.675000f, 0.679300f, 0.683200f, 0.691800f, 0.695700f, 0.704300f, 0.708200f, 0.712500f, 0.716800f, 0.720700f, 0.725000f, 0.729300f, 0.737500f, 0.745700f, 0.750000f, 0.758200f, 0.762500f, 0.766800f, 0.770700f, 0.775000f, 0.783200f, 0.791800f, 0.795700f, 0.800000f, 0.804300f, 0.808200f, 0.812500f, 0.820700f, 0.829300f, 0.837500f, 0.841800f, 0.845700f, 0.850000f, 0.854300f, 0.862500f, 0.866800f, 0.875000f, 0.879300f, 0.883200f, 0.887500f, 0.891800f, 0.895700f, 0.900000f, 1.000000f },
new int[57] { 64, 63, 62, 61, 59, 58, 57, 56, 55, 54, 52, 51, 50, 49, 48, 47, 45, 44, 43, 42, 41, 40, 39, 38, 37, 35, 34, 32, 31, 30, 29, 28, 27, 25, 24, 23, 22, 21, 20, 19, 17, 15, 14, 13, 12, 11, 10, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0 } );
break;
}
return res;
}
/// <summary>
/// 指定されたVibratoTypeを文字列に変換します
/// </summary>
/// <param name="value"></param>
/// <example>
/// <code>
/// string str = VibratoTypeUtil.ToString( VibratoType.NormalType1 );
/// // str = "[Normal] Type 1"
/// </code>
/// </example>
/// <returns></returns>
public static string ToString( VibratoType value ) {
switch ( value ) {
case VibratoType.NormalType1:
return "[Normal] Type 1";
case VibratoType.NormalType2:
return "[Normal] Type 2";
case VibratoType.NormalType3:
return "[Normal] Type 3";
case VibratoType.NormalType4:
return "[Normal] Type 4";
case VibratoType.ExtremeType1:
return "[Extreme] Type 1";
case VibratoType.ExtremeType2:
return "[Extreme] Type 2";
case VibratoType.ExtremeType3:
return "[Extreme] Type 3";
case VibratoType.ExtremeType4:
return "[Extreme] Type 4";
case VibratoType.FastType1:
return "[Fast] Type 1";
case VibratoType.FastType2:
return "[Fast] Type 2";
case VibratoType.FastType3:
return "[Fast] Type 3";
case VibratoType.FastType4:
return "[Fast] Type 4";
case VibratoType.SlightType1:
return "[Slight] Type 1";
case VibratoType.SlightType2:
return "[Slight] Type 2";
case VibratoType.SlightType3:
return "[Slight] Type 3";
case VibratoType.SlightType4:
return "[Slight] Type 4";
}
return "";
}
}
}

View File

@ -0,0 +1,228 @@
/*
* 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.
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace Boare.Lib.Vsq {
/// <summary>
/// BPListのデータ部分を取り扱うためのクラス。
/// </summary>
[Serializable]
public class VsqBPList : ICloneable {
private SortedList<int, int> m_list = new SortedList<int, int>();
private int m_default = 0;
private int m_maximum = 127;
private int m_minimum = 0;
private class KeyClockIterator : Iterator {
private SortedList<int, int> m_list;
private int m_pos;
public KeyClockIterator( SortedList<int, int> list ) {
m_list = list;
m_pos = -1;
}
public bool hasNext() {
if ( m_pos + 1 < m_list.Keys.Count ) {
return true;
} else {
return false;
}
}
public object next() {
m_pos++;
return m_list.Keys[m_pos];
}
public void remove() {
if ( 0 <= m_pos && m_pos < m_list.Keys.Count ) {
int key = m_list.Keys[m_pos];
m_list.Remove( key );
}
}
}
/// <summary>
/// このVsqBPListの同一コピーを作成します
/// </summary>
/// <returns></returns>
public object Clone() {
VsqBPList res = new VsqBPList( m_default, m_minimum, m_maximum );
foreach ( int key in m_list.Keys ) {
res.m_list.Add( key, m_list[key] );
}
return res;
}
/// <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;
}
/// <summary>
/// このリストに設定された最大値を取得します。
/// </summary>
public int getMaximum() {
return m_maximum;
}
/// <summary>
/// このリストに設定された最小値を取得します
/// </summary>
public int getMinimum() {
return m_minimum;
}
public Iterator keyClockIterator() {
return new KeyClockIterator( m_list );
}
public void remove( int clock ) {
if ( m_list.ContainsKey( clock ) ) {
m_list.Remove( clock );
}
}
public bool isContainsKey( int clock ) {
return m_list.ContainsKey( clock );
}
public int getCount() {
return m_list.Count;
}
public int[] getKeys() {
List<int> t = new List<int>( m_list.Keys );
return t.ToArray();
}
public void clear() {
m_list.Clear();
}
/// <summary>
/// 新しいデータ点を追加します。
/// </summary>
/// <param name="clock"></param>
/// <param name="value"></param>
public void add( int clock, int value ) {
lock ( m_list ) {
if ( m_list.ContainsKey( clock ) ) {
m_list[clock] = value;
} else {
m_list.Add( clock, value );
}
}
}
public int getElement( int clock ) {
if ( m_list.Count == 0 ) {
return getDefault();
} else {
if ( m_list.ContainsKey( clock ) ) {
return m_list[clock];
} else {
int index = 0;
int prev = 0;
foreach ( int key in m_list.Keys ) {
if ( clock < key ) {
index = prev;
break;
}
prev = key;
}
if ( m_list.ContainsKey( index ) ) {
return m_list[index];
} else {
return m_default;
}
}
}
}
/// <summary>
/// このBPListのデフォルト値を取得します
/// </summary>
public int getDefault() {
return m_default;
}
/// <summary>
/// このBPListの内容をテキストファイルに書き出します
/// </summary>
/// <param name="writer"></param>
public void print( StreamWriter writer ) {
bool first = true;
foreach ( int key in m_list.Keys ) {
int val = m_list[key];
if ( first ) {
writer.WriteLine( key + "=" + val );
first = false;
} else {
writer.WriteLine( key + "=" + val );
}
}
}
/// <summary>
/// このBPListの内容をテキストファイルに書き出します
/// </summary>
/// <param name="writer"></param>
public void print( TextMemoryStream writer, int start, string header ) {
bool first = true;
foreach ( int key in m_list.Keys ) {
if ( start <= key ) {
if ( first ) {
writer.writeLine( header );
first = false;
}
int val = m_list[key];
writer.writeLine( key + "=" + val );
}
}
}
/// <summary>
/// テキストファイルからデータ点を読込み、現在のリストに追加します
/// </summary>
/// <param name="reader"></param>
/// <returns></returns>
public string appendFromText( TextMemoryStream reader ) {
string last_line = reader.readLine();
while ( !last_line.StartsWith( "[" ) ) {
string[] spl = last_line.Split( new char[] { '=' } );
int i1 = int.Parse( spl[0] );
int i2 = int.Parse( spl[1] );
m_list.Add( i1, i2 );
if ( reader.peek() < 0 ) {
break;
} else {
last_line = reader.readLine();
}
}
return last_line;
}
}
}

View File

@ -0,0 +1,54 @@
/*
* VsqBarLineType.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;
namespace Boare.Lib.Vsq {
public struct VsqBarLineType {
private int m_clock;
private bool m_is_separator;
private int m_denominator;
private int m_numerator;
private int m_bar_count;
public int getBarCount() {
return m_bar_count;
}
public int getLocalDenominator() {
return m_denominator;
}
public int getLocalNumerator() {
return m_numerator;
}
public int clock() {
return m_clock;
}
public bool isSeparator() {
return m_is_separator;
}
public VsqBarLineType( int clock, bool is_separator, int denominator, int numerator, int bar_count ) {
m_clock = clock;
m_is_separator = is_separator;
m_denominator = denominator;
m_numerator = numerator;
m_bar_count = bar_count;
}
}
}

View File

@ -0,0 +1,498 @@
/*
* VsqCommand.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.VECapture 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 {
/// <summary>
///
/// </summary>
[Serializable]
public class VsqCommand {
public VsqCommandType Type;
/// <summary>
/// コマンドの処理内容を保持します。Args具体的な内容は、処理するクラスごとに異なります
/// </summary>
public object[] Args;
/// <summary>
/// 後続するコマンド
/// </summary>
public List<VsqCommand> Children = new List<VsqCommand>();
/// <summary>
/// このコマンドの親
/// </summary>
public VsqCommand Parent = null;
/// <summary>
/// VsqCommandはgenerateCommand*からコンストラクトしなければならない。
/// なので、無引数のコンストラクタを隠蔽するためのもの。
/// </summary>
internal VsqCommand() {
}
public static VsqCommand generateCommandTrackChangeRenderer( int track, string renderer ) {
VsqCommand command = new VsqCommand();
command.Type = VsqCommandType.TrackChangeRenderer;
command.Args = new object[2];
command.Args[0] = track;
command.Args[1] = renderer;
return command;
}
public static VsqCommand generateCommandRoot() {
VsqCommand command = new VsqCommand();
command.Type = VsqCommandType.Root;
command.Args = null;
return command;
}
public static VsqCommand generateCommandReplace( VsqFile vsq ) {
VsqCommand command = new VsqCommand();
command.Args = new object[1];
command.Type = VsqCommandType.Replace;
command.Args[0] = (VsqFile)vsq.Clone();
return command;
}
public static VsqCommand generateCommandTrackReplace( int track, VsqTrack item ) {
VsqCommand command = new VsqCommand();
command.Type = VsqCommandType.TrackReplace;
command.Args = new object[2];
command.Args[0] = track;
command.Args[1] = (VsqTrack)item.Clone();
return command;
}
public static VsqCommand generateCommandUpdateTimesig( int bar_count, int new_barcount, int numerator, int denominator ) {
VsqCommand command = new VsqCommand();
command.Type = VsqCommandType.UpdateTimesig;
command.Args = new object[4];
command.Args[0] = bar_count;
command.Args[1] = numerator;
command.Args[2] = denominator;
command.Args[3] = new_barcount;
return command;
}
public static VsqCommand generateCommandUpdateTimesigRange( int[] bar_counts, int[] new_barcounts, int[] numerators, int[] denominators ) {
VsqCommand command = new VsqCommand();
command.Type = VsqCommandType.UpdateTimesigRange;
command.Args = new object[4];
command.Args[0] = (int[])bar_counts.Clone();
command.Args[1] = (int[])numerators.Clone();
command.Args[2] = (int[])denominators.Clone();
command.Args[3] = (int[])new_barcounts.Clone();
return command;
}
public static VsqCommand generateCommandUpdateTempoRange( int[] clocks, int[] new_clocks, int[] tempos ) {
VsqCommand command = new VsqCommand();
command.Type = VsqCommandType.UpdateTempoRange;
command.Args = new object[3];
command.Args[0] = (int[])clocks.Clone();
command.Args[1] = (int[])tempos.Clone();
command.Args[2] = (int[])new_clocks.Clone();
return command;
}
public static VsqCommand generateCommandUpdateTempo( int clock, int new_clock, int tempo ) {
VsqCommand command = new VsqCommand();
command.Type = VsqCommandType.UpdateTempo;
command.Args = new object[3];
command.Args[0] = clock;
command.Args[1] = tempo;
command.Args[2] = new_clock;
return command;
}
public static VsqCommand generateCommandChangePreMeasure( int pre_measure ) {
VsqCommand command = new VsqCommand();
command.Type = VsqCommandType.ChangePreMeasure;
command.Args = new object[1];
command.Args[0] = pre_measure;
return command;
}
public static VsqCommand generateCommandDeleteTrack( int track ) {
VsqCommand command = new VsqCommand();
command.Type = VsqCommandType.DeleteTrack;
command.Args = new object[1];
command.Args[0] = track;
return command;
}
/// <summary>
/// トラックを追加するコマンドを発行しますtrackはClone()して渡さなくてもよい
/// </summary>
/// <param name="track"></param>
/// <returns></returns>
public static VsqCommand generateCommandAddTrack( VsqTrack track, VsqMixerEntry mixer, int position ) {
VsqCommand command = new VsqCommand();
command.Type = VsqCommandType.AddTrack;
command.Args = new object[5];
command.Args[0] = track;
command.Args[1] = mixer;
command.Args[2] = position;
return command;
}
/// <summary>
/// トラック名を変更するコマンドを作成します
/// </summary>
/// <param name="track"></param>
/// <param name="new_name"></param>
/// <returns></returns>
public static VsqCommand generateCommandTrackChangeName( int track, string new_name ) {
VsqCommand command = new VsqCommand();
command.Type = VsqCommandType.TrackChangeName;
command.Args = new object[2];
command.Args[0] = track;
command.Args[1] = new_name;
return command;
}
/// <summary>
/// VsqIDとClockを同時に変更するコマンドを発行します
/// </summary>
/// <param name="track"></param>
/// <param name="internal_ids"></param>
/// <param name="clocks"></param>
/// <param name="values"></param>
/// <returns></returns>
public static VsqCommand generateCommandEventChangeClockAndIDContaintsRange( int track, int[] internal_ids, int[] clocks, VsqID[] values ) {
VsqCommand command = new VsqCommand();
command.Type = VsqCommandType.EventChangeClockAndIDContaintsRange;
int count = internal_ids.Length;
command.Args = new object[4];
command.Args[0] = track;
command.Args[1] = (int[])internal_ids.Clone();
command.Args[2] = (int[])clocks.Clone();
command.Args[3] = (VsqID[])values.Clone();
return command;
}
/// <summary>
/// VsqIDとClockを同時に変更するコマンドを発行します
/// </summary>
/// <param name="track"></param>
/// <param name="internal_id"></param>
/// <param name="clock"></param>
/// <param name="value"></param>
/// <returns></returns>
public static VsqCommand generateCommandEventChangeClockAndIDContaints( int track, int internal_id, int clock, VsqID value ) {
VsqCommand command = new VsqCommand();
command.Type = VsqCommandType.EventChangeClockAndIDContaints;
command.Args = new object[4];
command.Args[0] = track;
command.Args[1] = internal_id;
command.Args[2] = clock;
command.Args[3] = (VsqID)value.Clone();
return command;
}
/// <summary>
/// VsqIDの内容を変更するコマンドを発行します。
/// </summary>
/// <param name="track"></param>
/// <param name="internal_ids"></param>
/// <param name="values"></param>
/// <returns></returns>
public static VsqCommand generateCommandEventChangeIDContaintsRange( int track, int[] internal_ids, VsqID[] values ) {
VsqCommand command = new VsqCommand();
command.Type = VsqCommandType.EventChangeIDContaintsRange;
command.Args = new object[3];
command.Args[0] = track;
command.Args[1] = (int[])internal_ids.Clone();
VsqID[] list = new VsqID[values.Length];
for ( int i = 0; i < values.Length; i++ ) {
list[i] = (VsqID)values[i].Clone();
}
command.Args[2] = list;
return command;
}
/// <summary>
/// VsqIDの内容を変更するコマンドを発行します。
/// </summary>
/// <param name="track"></param>
/// <param name="internal_id"></param>
/// <param name="value"></param>
/// <returns></returns>
public static VsqCommand generateCommandEventChangeIDContaints( int track, int internal_id, VsqID value ) {
VsqCommand command = new VsqCommand();
command.Type = VsqCommandType.EventChangeIDContaints;
command.Args = new object[3];
command.Args[0] = track;
command.Args[1] = internal_id;
command.Args[2] = (VsqID)value.Clone();
return command;
}
/// <summary>
/// ノートの長さを変更するコマンドを発行します
/// </summary>
/// <param name="track"></param>
/// <param name="internal_id"></param>
/// <param name="new_clock"></param>
/// <param name="new_length"></param>
/// <returns></returns>
public static VsqCommand generateCommandEventChangeClockAndLength( int track, int internal_id, int new_clock, int new_length ) {
VsqCommand command = new VsqCommand();
command.Type = VsqCommandType.EventChangeClockAndLength;
command.Args = new object[4];
command.Args[0] = track;
command.Args[1] = internal_id;
command.Args[2] = new_clock;
command.Args[3] = new_length;
return command;
}
/// <summary>
/// ノートの長さを変更するコマンドを発行します
/// </summary>
/// <param name="track"></param>
/// <param name="internal_id"></param>
/// <param name="new_length"></param>
/// <returns></returns>
public static VsqCommand generateCommandEventChangeLength( int track, int internal_id, int new_length ) {
VsqCommand command = new VsqCommand();
command.Type = VsqCommandType.EventChangeLength;
command.Args = new object[3];
command.Args[0] = track;
command.Args[1] = internal_id;
command.Args[2] = new_length;
return command;
}
/// <summary>
/// 指定したトラックの,音符のベロシティ(VEL)を変更するコマンドを発行します.
/// リストvelocityには音符を指定するInteralIDと変更したいベロシティの値のペアを登録します
/// </summary>
/// <param name="track"></param>
/// <param name="velocity"></param>
/// <returns></returns>
public static VsqCommand generateCommandEventChangeVelocity( int track, List<KeyValuePair<int, int>> velocity ) {
VsqCommand command = new VsqCommand();
command.Type = VsqCommandType.EventChangeVelocity;
command.Args = new object[2];
command.Args[0] = track;
List<KeyValuePair<int, int>> list = new List<KeyValuePair<int, int>>();
foreach ( KeyValuePair<int, int> item in velocity ) {
list.Add( new KeyValuePair<int, int>( item.Key, item.Value ) );
}
command.Args[1] = list;
return command;
}
/// <summary>
/// 指定したトラックの、音符のアクセント(Accent)を変更するコマンドを発行します。
/// リストaccent_listには、音符を指定するInternalIDと、変更したいアクセント値のペアを登録します
/// </summary>
/// <param name="track"></param>
/// <param name="accent_list"></param>
/// <returns></returns>
public static VsqCommand generateCommandEventChangeAccent( int track, List<KeyValuePair<int, int>> accent_list ) {
VsqCommand command = new VsqCommand();
command.Type = VsqCommandType.EventChangeAccent;
command.Args = new object[2];
command.Args[0] = track;
List<KeyValuePair<int, int>> list = new List<KeyValuePair<int, int>>();
foreach ( KeyValuePair<int, int> item in accent_list ) {
list.Add( new KeyValuePair<int, int>( item.Key, item.Value ) );
}
command.Args[1] = list;
return command;
}
/// <summary>
/// 指定したトラックの、音符のディケイ(Decay)を変更するコマンドを発行します。
/// リストdecay_listには、音符を指定するInternalIDと、変更したいディケイ値のペアを登録します
/// </summary>
/// <param name="track"></param>
/// <param name="decay_list"></param>
/// <returns></returns>
public static VsqCommand generateCommandEventChangeDecay( int track, List<KeyValuePair<int, int>> decay_list ) {
VsqCommand command = new VsqCommand();
command.Type = VsqCommandType.EventChangeDecay;
command.Args = new object[2];
command.Args[0] = track;
List<KeyValuePair<int, int>> list = new List<KeyValuePair<int, int>>();
foreach ( KeyValuePair<int, int> item in decay_list ) {
list.Add( new KeyValuePair<int, int>( item.Key, item.Value ) );
}
command.Args[1] = list;
return command;
}
/// <summary>
/// vsqファイルのカーブを編集するコマンドを発行します
/// </summary>
/// <param name="track"></param>
/// <param name="target"></param>
/// <param name="edit"></param>
/// <returns></returns>
public static VsqCommand generateCommandTrackEditCurve( int track, string target, List<BPPair> edit ) {
VsqCommand command = new VsqCommand();
command.Type = VsqCommandType.TrackEditCurve;
command.Args = new object[5];
command.Args[0] = track;
command.Args[1] = target;
List<BPPair> copied = new List<BPPair>();
foreach ( BPPair item in edit ) {
copied.Add( item );
}
command.Args[2] = copied;
return command;
}
public static VsqCommand generateCommandTrackEditCurveRange( int track, string[] targets, List<BPPair>[] edits ) {
VsqCommand command = new VsqCommand();
command.Type = VsqCommandType.TrackEditCurveRange;
command.Args = new object[3];
command.Args[0] = track;
command.Args[1] = (string[])targets.Clone();
List<BPPair>[] cpy = new List<BPPair>[targets.Length];
for ( int i = 0; i < edits.Length; i++ ) {
List<BPPair> copied = new List<BPPair>();
foreach ( BPPair item in edits[i] ) {
copied.Add( new BPPair( item.Clock, item.Value ) );
}
cpy[i] = copied;
}
command.Args[2] = cpy;
return command;
}
/// <summary>
/// 特定位置のイベントの歌詞と発音記号を変更するコマンドを発行します。
/// </summary>
/// <param name="track"></param>
/// <param name="internal_id"></param>
/// <param name="phrase"></param>
/// <param name="phonetic_symbol"></param>
/// <returns></returns>
public static VsqCommand generateCommandEventChangeLyric( int track, int internal_id, string phrase, string phonetic_symbol, bool protect_symbol ) {
VsqCommand command = new VsqCommand();
command.Type = VsqCommandType.EventChangeLyric;
command.Args = new object[5];
command.Args[0] = track;
command.Args[1] = internal_id;
command.Args[2] = phrase;
command.Args[3] = phonetic_symbol;
command.Args[4] = protect_symbol;
return command;
}
/// <summary>
/// ノートのクロック位置を変更するコマンドを発行します
/// </summary>
/// <param name="track"></param>
/// <param name="internal_id"></param>
/// <param name="value"></param>
/// <returns></returns>
public static VsqCommand generateCommandEventChangeClock( int track, int internal_id, int value ) {
VsqCommand command = new VsqCommand();
command.Type = VsqCommandType.EventChangeClock;
command.Args = new object[3];
command.Args[0] = track;
command.Args[1] = internal_id;
command.Args[2] = value;
return command;
}
public static VsqCommand generateCommandEventDeleteRange( int track, int[] internal_ids ) {
VsqCommand command = new VsqCommand();
command.Type = VsqCommandType.EventDeleteRange;
command.Args = new object[2];
command.Args[0] = (int[])internal_ids.Clone();
command.Args[1] = track;
return command;
}
/// <summary>
/// ノートを削除するコマンドを発行します
/// </summary>
/// <param name="clock"></param>
/// <returns></returns>
public static VsqCommand generateCommandEventDelete( int track, int internal_id ) {
VsqCommand command = new VsqCommand();
command.Type = VsqCommandType.EventDelete;
command.Args = new object[2];
command.Args[1] = track;
command.Args[0] = internal_id;
return command;
}
public static VsqCommand generateCommandEventAddRange( int track, VsqEvent[] items ) {
VsqCommand command = new VsqCommand();
command.Type = VsqCommandType.EventAddRange;
command.Args = new object[2];
command.Args[0] = track;
command.Args[1] = (VsqEvent[])items.Clone();
return command;
}
/// <summary>
/// ノートを追加するコマンドを発行します。
/// </summary>
/// <param name="track"></param>
/// <param name="item"></param>
/// <returns></returns>
public static VsqCommand generateCommandEventAdd( int track, VsqEvent item ) {
VsqCommand command = new VsqCommand();
command.Type = VsqCommandType.EventAdd;
command.Args = new object[2];
command.Args[0] = track;
command.Args[1] = (VsqEvent)item.Clone();
return command;
}
/// <summary>
/// ノートの音程を変更するコマンドを発行します
/// </summary>
/// <param name="track"></param>
/// <param name="internal_id"></param>
/// <param name="value"></param>
/// <returns></returns>
public static VsqCommand generateCommandEventChangeNote( int track, int internal_id, int note ) {
VsqCommand command = new VsqCommand();
command.Type = VsqCommandType.EventChangeNote;
command.Args = new object[3];
command.Args[0] = track;
command.Args[1] = internal_id;
command.Args[2] = note;
return command;
}
/// <summary>
/// ノートの音程とクロックを変更するコマンドを発行します
/// </summary>
/// <param name="track"></param>
/// <param name="internal_id"></param>
/// <param name="value"></param>
/// <returns></returns>
public static VsqCommand generateCommandEventChangeClockAndNote( int track, int internal_id, int clock, int note ) {
VsqCommand command = new VsqCommand();
command.Type = VsqCommandType.EventChangeClockAndNote;
command.Args = new object[4];
command.Args[0] = track;
command.Args[1] = internal_id;
command.Args[2] = clock;
command.Args[3] = note;
return command;
}
}
}

View File

@ -0,0 +1,50 @@
/*
* VsqCommandType.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.
*/
namespace Boare.Lib.Vsq {
public enum VsqCommandType {
Root,
ChangePreMeasure,
EventAdd,
EventDelete,
EventChangeClock,
EventChangeLyric,
EventChangeNote,
EventChangeClockAndNote,
TrackEditCurve,
TrackEditCurveRange,
EventChangeVelocity,
EventChangeAccent,
EventChangeDecay,
EventChangeLength,
EventChangeClockAndLength,
EventChangeIDContaints,
EventChangeClockAndIDContaints,
TrackChangeName,
AddTrack,
DeleteTrack,
EventChangeClockAndIDContaintsRange,
EventDeleteRange,
EventAddRange,
UpdateTempo,
UpdateTempoRange,
UpdateTimesig,
UpdateTimesigRange,
EventChangeIDContaintsRange,
TrackReplace,
Replace,
TrackChangeRenderer,
}
}

View File

@ -0,0 +1,70 @@
/*
* VsqEvent.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;
namespace Boare.Lib.Vsq {
/// <summary>
/// vsqファイルのメタテキスト内に記述されるイベント。
/// </summary>
[Serializable]
public class VsqEvent : IComparable<VsqEvent>, ICloneable {
public object Tag;
/// <summary>
/// 内部で使用するインスタンス固有のID
/// </summary>
public int InternalID;
public int Clock;
public VsqID ID;
/// <summary>
/// このオブジェクトのコピーを作成します
/// </summary>
/// <returns></returns>
public object Clone() {
VsqEvent ret = new VsqEvent( Clock, ID );
ret.InternalID = InternalID;
return ret;
}
public int CompareTo( VsqEvent item ) {
int ret = this.Clock - item.Clock;
if ( ret == 0 ) {
if ( this.ID != null && item.ID != null ) {
return (int)this.ID.type - (int)item.ID.type;
} else {
return ret;
}
} else {
return ret;
}
}
public VsqEvent( string line ) {
string[] spl = line.Split( new char[] { '=' } );
Clock = int.Parse( spl[0] );
if ( spl[1] == "EOS" ) {
ID = VsqID.EOS;
}
}
public VsqEvent( int clock, VsqID id /*, int internal_id*/ ) {
Clock = clock;
ID = (VsqID)id.Clone();
//InternalID = internal_id;
InternalID = 0;
}
}
}

View File

@ -0,0 +1,90 @@
/*
* VsqEventList.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 {
/// <summary>
/// 固有ID付きのVsqEventのリストを取り扱う
/// </summary>
[Serializable]
public class VsqEventList {
private List<VsqEvent> m_list;
private List<int> m_ids;
/// <summary>
/// コンストラクタ
/// </summary>
public VsqEventList() {
m_list = new List<VsqEvent>();
m_ids = new List<int>();
}
public void clear() {
m_list.Clear();
m_ids.Clear();
}
public Iterator iterator() {
return new ListIterator<VsqEvent>( m_list );
}
public void add( VsqEvent item ) {
int new_id = getNextId( 0 );
item.InternalID = new_id;
m_list.Add( item );
m_ids.Add( new_id );
m_list.Sort();
for ( int i = 0; i < m_list.Count; i++ ) {
m_ids[i] = m_list[i].InternalID;
}
}
public void removeAt( int index ) {
m_list.RemoveAt( index );
m_ids.RemoveAt( index );
}
private int getNextId( int next ) {
int index = -1;
List<int> current = new List<int>( m_ids );
int nfound = 0;
while ( true ) {
index++;
if ( !current.Contains( index ) ) {
nfound++;
if ( nfound == next + 1 ) {
return index;
} else {
current.Add( index );
}
}
}
}
public int getCount() {
return m_list.Count;
}
public VsqEvent getElement( int index ) {
return m_list[index];
}
public void setElement( int index, VsqEvent value ) {
m_list[index] = value;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,149 @@
/*
* VsqMetaText/Common.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;
using System.Text;
using System.IO;
using System.Drawing;
namespace Boare.Lib.Vsq {
/// <summary>
/// vsqファイルのメタテキストの[Common]セクションに記録される内容を取り扱う
/// </summary>
[Serializable]
public class VsqCommon : ICloneable {
public string Version;
public string Name;
public string Color;
public int DynamicsMode;
public int PlayMode;
public object Clone() {
string[] spl = Color.Split( ",".ToCharArray(), 3 );
int r = int.Parse( spl[0] );
int g = int.Parse( spl[1] );
int b = int.Parse( spl[2] );
System.Drawing.Color color = System.Drawing.Color.FromArgb( r, g, b );
VsqCommon res = new VsqCommon( Name, color, DynamicsMode, PlayMode );
res.Version = Version;
return res;
}
/// <summary>
/// 各パラメータを指定したコンストラクタ
/// </summary>
/// <param name="name">トラック名</param>
/// <param name="color">Color値意味は不明</param>
/// <param name="dynamics_mode">DynamicsModeデフォルトは1</param>
/// <param name="play_mode">PlayModeデフォルトは1</param>
public VsqCommon( string name, Color color, int dynamics_mode, int play_mode ) {
this.Version = "DSB301";
this.Name = name;
this.Color = color.R + "," + color.G + "," + color.B;
this.DynamicsMode = dynamics_mode;
this.PlayMode = play_mode;
}
/// <summary>
/// MetaTextのテキストファイルからのコンストラクタ
/// </summary>
/// <param name="sr">読み込むテキストファイル</param>
/// <param name="last_line">読み込んだ最後の行が返される</param>
public VsqCommon( TextMemoryStream sr, ref string last_line ) {
Version = "";
Name = "";
Color = "0,0,0";
DynamicsMode = 0;
PlayMode = 0;
last_line = sr.readLine();
string[] spl;
while ( !last_line.StartsWith( "[" ) ) {
spl = last_line.Split( new char[] { '=' } );
switch ( spl[0] ) {
case "Version":
this.Version = spl[1];
break;
case "Name":
this.Name = spl[1];
break;
case "Color":
this.Color = spl[1];
break;
case "DynamicsMode":
this.DynamicsMode = int.Parse( spl[1] );
break;
case "PlayMode":
this.PlayMode = int.Parse( spl[1] );
break;
}
if ( sr.peek() < 0 ) {
break;
}
last_line = sr.readLine();
}
}
/// <summary>
/// インスタンスの内容をテキストファイルに出力します
/// </summary>
/// <param name="sw">出力先</param>
public void write( TextMemoryStream sw ) {
sw.writeLine( "[Common]" );
sw.writeLine( "Version=" + Version );
sw.writeLine( "Name=" + Name );
sw.writeLine( "Color=" + Color );
sw.writeLine( "DynamicsMode=" + DynamicsMode );
sw.writeLine( "PlayMode=" + PlayMode );
}
/// <summary>
/// VsqCommon構造体を構築するテストを行います
/// </summary>
/// <returns>テストに成功すればtrue、そうでなければfalse</returns>
public static bool test() {
string fpath = Path.GetTempFileName();
StreamWriter sw = new StreamWriter( fpath, false, Encoding.Unicode );
sw.WriteLine( "Version=DSB301" );
sw.WriteLine( "Name=Voice1" );
sw.WriteLine( "Color=181,162,123" );
sw.WriteLine( "DynamicsMode=1" );
sw.WriteLine( "PlayMode=1" );
sw.WriteLine( "[Master]" );
sw.Close();
VsqCommon vsqCommon;
string last_line = "";
using ( TextMemoryStream sr = new TextMemoryStream( fpath, Encoding.Unicode ) ) {
vsqCommon = new VsqCommon( sr, ref last_line );
}
bool result;
if ( vsqCommon.Version == "DSB301" &&
vsqCommon.Name == "Voice1" &&
vsqCommon.Color == "181,162,123" &&
vsqCommon.DynamicsMode == 1 &&
vsqCommon.PlayMode == 1 &&
last_line == "[Master]" ) {
result = true;
} else {
result = false;
}
File.Delete( fpath );
return result;
}
}
}

View File

@ -0,0 +1,151 @@
/*
* VsqMetaText/Common.cs
* Copyright (c) 2008 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;
using System.Text;
using System.IO;
using System.Drawing;*/
package com.boare.vsq;
/// <summary>
/// vsqファイルのメタテキストの[Common]セクションに記録される内容を取り扱う
/// </summary>
public class VsqCommon implements Cloneable {
public String Version;
public String Name;
public String Color;
public int DynamicsMode;
public int PlayMode;
public Object clone() {
String[] spl = Color.Split( ",".ToCharArray(), 3 );
int r = Integer.parseInt( spl[0] );
int g = Integer.parseInt( spl[1] );
int b = Integer.parseInt( spl[2] );
System.Drawing.Color color = System.Drawing.Color.FromArgb( r, g, b );
VsqCommon res = new VsqCommon( Name, color, DynamicsMode, PlayMode );
res.Version = Version;
return res;
}
/// <summary>
/// 各パラメータを指定したコンストラクタ
/// </summary>
/// <param name="name">トラック名</param>
/// <param name="color">Color値意味は不明</param>
/// <param name="dynamics_mode">DynamicsModeデフォルトは1</param>
/// <param name="play_mode">PlayModeデフォルトは1</param>
public VsqCommon( string name, Color color, int dynamics_mode, int play_mode ) {
this.Version = "DSB301";
this.Name = name;
this.Color = color.R + "," + color.G + "," + color.B;
this.DynamicsMode = dynamics_mode;
this.PlayMode = play_mode;
}
/// <summary>
/// MetaTextのテキストファイルからのコンストラクタ
/// </summary>
/// <param name="sr">読み込むテキストファイル</param>
/// <param name="last_line">読み込んだ最後の行が返される</param>
public VsqCommon( TextMemoryStream sr, ref string last_line ) {
Version = "";
Name = "";
Color = "0,0,0";
DynamicsMode = 0;
PlayMode = 0;
last_line = sr.ReadLine();
string[] spl;
while ( !last_line.StartsWith( "[" ) ) {
spl = last_line.Split( new char[] { '=' } );
switch ( spl[0] ) {
case "Version":
this.Version = spl[1];
break;
case "Name":
this.Name = spl[1];
break;
case "Color":
this.Color = spl[1];
break;
case "DynamicsMode":
this.DynamicsMode = Integer.parseInt( spl[1] );
break;
case "PlayMode":
this.PlayMode = Integer.parseInt( spl[1] );
break;
}
if ( sr.Peek() < 0 ) {
break;
}
last_line = sr.ReadLine();
}
}
/// <summary>
/// インスタンスの内容をテキストファイルに出力します
/// </summary>
/// <param name="sw">出力先</param>
public void write( TextMemoryStream sw ) {
sw.WriteLine( "[Common]" );
sw.WriteLine( "Version=" + Version );
sw.WriteLine( "Name=" + Name );
sw.WriteLine( "Color=" + Color );
sw.WriteLine( "DynamicsMode=" + DynamicsMode );
sw.WriteLine( "PlayMode=" + PlayMode );
}
/// <summary>
/// VsqCommon構造体を構築するテストを行います
/// </summary>
/// <returns>テストに成功すればtrueそうでなければfalse</returns>
public static bool test() {
string fpath = Path.GetTempFileName();
StreamWriter sw = new StreamWriter( fpath, false, Encoding.Unicode );
sw.WriteLine( "Version=DSB301" );
sw.WriteLine( "Name=Voice1" );
sw.WriteLine( "Color=181,162,123" );
sw.WriteLine( "DynamicsMode=1" );
sw.WriteLine( "PlayMode=1" );
sw.WriteLine( "[Master]" );
sw.Close();
VsqCommon vsqCommon;
string last_line = "";
using ( TextMemoryStream sr = new TextMemoryStream( fpath, Encoding.Unicode ) ) {
vsqCommon = new VsqCommon( sr, ref last_line );
}
bool result;
if ( vsqCommon.Version == "DSB301" &&
vsqCommon.Name == "Voice1" &&
vsqCommon.Color == "181,162,123" &&
vsqCommon.DynamicsMode == 1 &&
vsqCommon.PlayMode == 1 &&
last_line == "[Master]" ) {
result = true;
} else {
result = false;
}
File.Delete( fpath );
return result;
}
}

View File

@ -0,0 +1,448 @@
/*
* VsqMetaText/Handle.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;
using System.Text;
using System.IO;
namespace Boare.Lib.Vsq {
[Serializable]
public class IconHandle : ICloneable {
public string Caption;
public string IconID;
public string IDS;
public int Index;
public int Length;
public int Original;
public int Program;
public int Language;
public object Clone() {
IconHandle ret = new IconHandle();
ret.Caption = Caption;
ret.IconID = IconID;
ret.IDS = IDS;
ret.Index = Index;
ret.Language = Language;
ret.Length = Length;
ret.Original = Original;
ret.Program = Program;
return ret;
}
public VsqHandle castToVsqHandle() {
VsqHandle ret = new VsqHandle();
ret.m_type = VsqHandleType.Singer;
ret.Caption = Caption;
ret.IconID = IconID;
ret.IDS = IDS;
ret.Index = Index;
ret.Language = Language;
ret.Length = Length;
ret.Program = Program;
return ret;
}
}
[Serializable]
public class LyricHandle : ICloneable {
public Lyric L0;
public int Index;
internal LyricHandle() {
}
/// <summary>
/// type = Lyric用のhandleのコンストラクタ
/// </summary>
/// <param name="phrase">歌詞</param>
/// <param name="phonetic_symbol">発音記号</param>
public LyricHandle( string phrase, string phonetic_symbol ) {
L0 = new Lyric( phrase, phonetic_symbol );
}
public object Clone() {
LyricHandle ret = new LyricHandle();
ret.Index = Index;
ret.L0 = (Lyric)L0.Clone();
return ret;
}
public VsqHandle castToVsqHandle() {
VsqHandle ret = new VsqHandle();
ret.m_type = VsqHandleType.Lyric;
ret.L0 = (Lyric)L0.Clone();
ret.Index = Index;
return ret;
}
}
[Serializable]
public class VibratoHandle : ICloneable {
public int StartDepth;
public VibratoBPList DepthBP;
public int StartRate;
public VibratoBPList RateBP;
public int Index;
public string IconID;
public string IDS;
public int Original;
public string Caption;
public int Length;
public VibratoHandle(){
RateBP = new VibratoBPList();
DepthBP = new VibratoBPList();
}
public object Clone() {
VibratoHandle result = new VibratoHandle();
result.Index = Index;
result.IconID = IconID;
result.IDS = this.IDS;
result.Original = this.Original;
result.Caption = this.Caption;
result.Length = this.Length;
result.StartDepth = this.StartDepth;
result.DepthBP = (VibratoBPList)DepthBP.Clone();
result.StartRate = this.StartRate;
result.RateBP = (VibratoBPList)RateBP.Clone();
return result;
}
public VsqHandle castToVsqHandle() {
VsqHandle ret = new VsqHandle();
ret.m_type = VsqHandleType.Vibrato;
ret.Index = Index;
ret.IconID = IconID;
ret.IDS = IDS;
ret.Original = Original;
ret.Caption = Caption;
ret.Length = Length;
ret.StartDepth = StartDepth;
ret.StartRate = StartRate;
ret.DepthBP = (VibratoBPList)DepthBP.Clone();
ret.RateBP = (VibratoBPList)RateBP.Clone();
return ret;
}
}
/// <summary>
/// ハンドルを取り扱います。ハンドルにはLyricHandle、VibratoHandleおよびIconHandleがある
/// </summary>
[Serializable]
public class VsqHandle {
public VsqHandleType m_type;
public int Index;
public string IconID;
public string IDS;
public Lyric L0;
public int Original;
public string Caption;
public int Length;
public int StartDepth;
public VibratoBPList DepthBP;
public int StartRate;
public VibratoBPList RateBP;
public int Language;
public int Program;
public LyricHandle castToLyricHandle() {
LyricHandle ret = new LyricHandle();
ret.L0 = (Lyric)L0;
ret.Index = Index;
return ret;
}
public VibratoHandle castToVibratoHandle() {
VibratoHandle ret = new VibratoHandle();
ret.Index = Index;
ret.Caption = Caption;
ret.DepthBP = (VibratoBPList)DepthBP.Clone();
ret.IconID = IconID;
ret.IDS = IDS;
ret.Index = Index;
ret.Length = Length;
ret.Original = Original;
ret.RateBP = (VibratoBPList)RateBP.Clone();
ret.StartDepth = StartDepth;
ret.StartRate = StartRate;
return ret;
}
public IconHandle castToIconHandle() {
IconHandle ret = new IconHandle();
ret.Index = Index;
ret.Caption = Caption;
ret.IconID = IconID;
ret.IDS = IDS;
ret.Index = Index;
ret.Language = Language;
ret.Length = Length;
ret.Original = Original;
ret.Program = Program;
return ret;
}
internal VsqHandle() {
}
/// <summary>
/// インスタンスをストリームに書き込みます。
/// encode=trueの場合、2バイト文字をエンコードして出力します。
/// </summary>
/// <param name="sw">書き込み対象</param>
/// <param name="encode">2バイト文字をエンコードするか否かを指定するフラグ</param>
public void write( TextMemoryStream sw, bool encode ) {
sw.writeLine( this.ToString( encode ) );
}
/// <summary>
/// FileStreamから読み込みながらコンストラクト
/// </summary>
/// <param name="sr">読み込み対象</param>
public VsqHandle( TextMemoryStream sr, int value, ref string last_line ) {
this.Index = value;
string[] spl;
string[] spl2;
// default値で梅
m_type = VsqHandleType.Vibrato;
IconID = "";
IDS = "normal";
L0 = new Lyric( "" );
Original = 0;
Caption = "";
Length = 0;
StartDepth = 0;
DepthBP = null;
int depth_bp_num = 0;
StartRate = 0;
RateBP = null;
int rate_bp_num = 0;
Language = 0;
Program = 0;
string tmpDepthBPX = "";
string tmpDepthBPY = "";
string tmpRateBPX = "";
string tmpRateBPY = "";
// "["にぶち当たるまで読込む
last_line = sr.readLine();
while ( !last_line.StartsWith( "[" ) ) {
spl = last_line.Split( new char[] { '=' } );
switch ( spl[0] ) {
case "Language":
Language = int.Parse( spl[1] );
break;
case "Program":
Program = int.Parse( spl[1] );
break;
case "IconID":
IconID = spl[1];
break;
case "IDS":
IDS = spl[1];
break;
case "Original":
Original = int.Parse( spl[1] );
break;
case "Caption":
Caption = spl[1];
for ( int i = 2; i < spl.Length; i++ ) {
Caption += "=" + spl[i];
}
break;
case "Length":
Length = int.Parse( spl[1] );
break;
case "StartDepth":
StartDepth = int.Parse( spl[1] );
break;
case "DepthBPNum":
depth_bp_num = int.Parse( spl[1] );
break;
case "DepthBPX":
tmpDepthBPX = spl[1];
break;
case "DepthBPY":
tmpDepthBPY = spl[1];
break;
case "StartRate":
StartRate = int.Parse( spl[1] );
break;
case "RateBPNum":
rate_bp_num = int.Parse( spl[1] );
break;
case "RateBPX":
tmpRateBPX = spl[1];
break;
case "RateBPY":
tmpRateBPY = spl[1];
break;
case "L0":
m_type = VsqHandleType.Lyric;
L0 = new Lyric( spl[1] );
break;
}
if ( sr.peek() < 0 ) {
break;
}
last_line = sr.readLine();
}
if ( IDS != "normal" ) {
m_type = VsqHandleType.Singer;
} else if ( IconID != "" ) {
m_type = VsqHandleType.Vibrato;
} else {
m_type = VsqHandleType.Lyric;
}
// RateBPX, RateBPYの設定
if ( m_type == VsqHandleType.Vibrato ) {
if ( rate_bp_num > 0 ) {
float[] rate_bp_x = new float[rate_bp_num];
spl2 = tmpRateBPX.Split( new char[] { ',' } );
for ( int i = 0; i < rate_bp_num; i++ ) {
rate_bp_x[i] = float.Parse( spl2[i] );
}
int[] rate_bp_y = new int[rate_bp_num];
spl2 = tmpRateBPY.Split( new char[] { ',' } );
for ( int i = 0; i < rate_bp_num; i++ ) {
rate_bp_y[i] = int.Parse( spl2[i] );
}
RateBP = new VibratoBPList( rate_bp_x, rate_bp_y );
} else {
//m_rate_bp_x = null;
//m_rate_bp_y = null;
RateBP = new VibratoBPList();
}
// DepthBPX, DepthBPYの設定
if ( depth_bp_num > 0 ) {
float[] depth_bp_x = new float[depth_bp_num];
spl2 = tmpDepthBPX.Split( new char[] { ',' } );
for ( int i = 0; i < depth_bp_num; i++ ) {
depth_bp_x[i] = float.Parse( spl2[i] );
}
int[] depth_bp_y = new int[depth_bp_num];
spl2 = tmpDepthBPY.Split( new char[] { ',' } );
for ( int i = 0; i < depth_bp_num; i++ ) {
depth_bp_y[i] = int.Parse( spl2[i] );
}
DepthBP = new VibratoBPList( depth_bp_x, depth_bp_y );
} else {
DepthBP = new VibratoBPList();
//m_depth_bp_x = null;
//m_depth_bp_y = null;
}
} else {
DepthBP = new VibratoBPList();
RateBP = new VibratoBPList();
}
}
/// <summary>
/// ハンドル指定子(例えば"h#0123"という文字列)からハンドル番号を取得します
/// </summary>
/// <param name="_string">ハンドル指定子</param>
/// <returns>ハンドル番号</returns>
public static int HandleIndexFromString( string _string ) {
string[] spl = _string.Split( new char[] { '#' } );
return int.Parse( spl[1] );
}
/// <summary>
/// インスタンスをテキストファイルに出力します
/// </summary>
/// <param name="sw">出力先</param>
public void Print( StreamWriter sw ) {
string result = this.ToString();
sw.WriteLine( result );
}
/// <summary>
/// インスタンスをコンソール画面に出力します
/// </summary>
private void Print() {
string result = this.ToString();
Console.WriteLine( result );
}
/// <summary>
/// インスタンスを文字列に変換します
/// </summary>
/// <param name="encode">2バイト文字をエンコードするか否かを指定するフラグ</param>
/// <returns>インスタンスを変換した文字列</returns>
public string ToString( bool encode ) {
string result = "";
result += "[h#" + Index.ToString( "0000" ) + "]";
switch ( m_type ) {
case VsqHandleType.Lyric:
result += Environment.NewLine + "L0=" + L0.ToString( encode );
break;
case VsqHandleType.Vibrato:
result += Environment.NewLine + "IconID=" + IconID + Environment.NewLine;
result += "IDS=" + IDS + Environment.NewLine;
result += "Original=" + Original + Environment.NewLine;
result += "Caption=" + Caption + Environment.NewLine;
result += "Length=" + Length + Environment.NewLine;
result += "StartDepth=" + StartDepth + Environment.NewLine;
result += "DepthBPNum=" + DepthBP.getCount() + Environment.NewLine;
if ( DepthBP.getCount() > 0 ) {
result += "DepthBPX=" + DepthBP.getElement( 0 ).X.ToString( "0.000000" );
for ( int i = 1; i < DepthBP.getCount(); i++ ) {
result += "," + DepthBP.getElement( i ).X.ToString( "0.000000" );
}
result += Environment.NewLine + "DepthBPY=" + DepthBP.getElement( 0 ).Y;
for ( int i = 1; i < DepthBP.getCount(); i++ ) {
result += "," + DepthBP.getElement( i ).Y;
}
result += Environment.NewLine;
}
result += "StartRate=" + StartRate + Environment.NewLine;
result += "RateBPNum=" + RateBP.getCount();
if ( RateBP.getCount() > 0 ) {
result += Environment.NewLine + "RateBPX=" + RateBP.getElement( 0 ).X.ToString( "0.000000" );
for ( int i = 1; i < RateBP.getCount(); i++ ) {
result += "," + RateBP.getElement( i ).X.ToString( "0.000000" );
}
result += Environment.NewLine + "RateBPY=" + RateBP.getElement( 0 ).Y;
for ( int i = 1; i < RateBP.getCount(); i++ ) {
result += "," + RateBP.getElement( i ).Y;
}
}
break;
case VsqHandleType.Singer:
result += Environment.NewLine + "IconID=" + IconID + Environment.NewLine;
result += "IDS=" + IDS + Environment.NewLine;
result += "Original=" + Original + Environment.NewLine;
result += "Caption=" + Caption + Environment.NewLine;
result += "Length=" + Length + Environment.NewLine;
result += "Language=" + Language + Environment.NewLine;
result += "Program=" + Program;
break;
default:
break;
}
return result;
}
}
}

View File

@ -0,0 +1,272 @@
/*
* VsqMetaText/ID.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;
using System.Text;
using System.IO;
namespace Boare.Lib.Vsq {
/// <summary>
/// メタテキストに埋め込まれるIDを表すクラス。
/// </summary>
[Serializable]
public class VsqID : ICloneable {
public int value;
public VsqIDType type;
public int IconHandle_index;
public IconHandle IconHandle;
public int Length;
public int Note;
public int Dynamics;
public int PMBendDepth;
public int PMBendLength;
public int PMbPortamentoUse;
public int DEMdecGainRate;
public int DEMaccent;
public int LyricHandle_index;
public LyricHandle LyricHandle;
public int VibratoHandle_index;
public VibratoHandle VibratoHandle;
public int VibratoDelay;
public static VsqID EOS = new VsqID( -1 );
/// <summary>
/// このインスタンスの簡易コピーを取得します。
/// </summary>
/// <returns>このインスタンスの簡易コピー</returns>
public object Clone() {
VsqID result = new VsqID( this.value );
result.type = this.type;
if ( this.IconHandle != null ) {
result.IconHandle = (IconHandle)this.IconHandle.Clone();
}
result.Length = this.Length;
result.Note = this.Note;
result.Dynamics = this.Dynamics;
result.PMBendDepth = this.PMBendDepth;
result.PMBendLength = this.PMBendLength;
result.PMbPortamentoUse = this.PMbPortamentoUse;
result.DEMdecGainRate = this.DEMdecGainRate;
result.DEMaccent = this.DEMaccent;
if ( this.LyricHandle != null ) {
result.LyricHandle = (LyricHandle)this.LyricHandle.Clone();
}
if ( this.VibratoHandle != null ) {
result.VibratoHandle = (VibratoHandle)this.VibratoHandle.Clone();
}
result.VibratoDelay = this.VibratoDelay;
return result;
}
/// <summary>
/// IDの番号ID#****の****)を指定したコンストラクタ。
/// </summary>
/// <param name="a_value">IDの番号</param>
public VsqID( int a_value ) {
value = a_value;
}
/// <summary>
/// テキストファイルからのコンストラクタ
/// </summary>
/// <param name="sr">読み込み対象</param>
/// <param name="value"></param>
/// <param name="last_line">読み込んだ最後の行が返されます</param>
public VsqID( TextMemoryStream sr, int value, ref string last_line ) {
string[] spl;
this.value = value;
this.type = VsqIDType.Unknown;
this.IconHandle_index = -2;
this.LyricHandle_index = -1;
this.VibratoHandle_index = -1;
this.Length = 0;
this.Note = 0;
this.Dynamics = 0;
this.PMBendDepth = 0;
this.PMBendLength = 0;
this.PMbPortamentoUse = 0;
this.DEMdecGainRate = 0;
this.DEMaccent = 0;
//this.LyricHandle_index = -2;
//this.VibratoHandle_index = -2;
this.VibratoDelay = 0;
last_line = sr.readLine();
while ( !last_line.StartsWith( "[" ) ) {
spl = last_line.Split( new char[] { '=' } );
switch ( spl[0] ) {
case "Type":
if ( spl[1] == "Anote" ) {
type = VsqIDType.Anote;
} else if ( spl[1] == "Singer" ) {
type = VsqIDType.Singer;
} else {
type = VsqIDType.Unknown;
}
break;
case "Length":
this.Length = int.Parse( spl[1] );
break;
case "Note#":
this.Note = int.Parse( spl[1] );
break;
case "Dynamics":
this.Dynamics = int.Parse( spl[1] );
break;
case "PMBendDepth":
this.PMBendDepth = int.Parse( spl[1] );
break;
case "PMBendLength":
this.PMBendLength = int.Parse( spl[1] );
break;
case "DEMdecGainRate":
this.DEMdecGainRate = int.Parse( spl[1] );
break;
case "DEMaccent":
this.DEMaccent = int.Parse( spl[1] );
break;
case "LyricHandle":
this.LyricHandle_index = VsqHandle.HandleIndexFromString( spl[1] );
break;
case "IconHandle":
this.IconHandle_index = VsqHandle.HandleIndexFromString( spl[1] );
break;
case "VibratoHandle":
this.VibratoHandle_index = VsqHandle.HandleIndexFromString( spl[1] );
break;
case "VibratoDelay":
this.VibratoDelay = int.Parse( spl[1] );
break;
case "PMbPortamentoUse":
PMbPortamentoUse = int.Parse( spl[1] );
break;
}
if ( sr.peek() < 0 ) {
break;
}
last_line = sr.readLine();
}
}
public override string ToString() {
string ret = "{Type=" + type;
switch ( type ) {
case VsqIDType.Anote:
ret += ", Length=" + Length;
ret += ", Note#=" + Note;
ret += ", Dynamics=" + Dynamics;
ret += ", PMBendDepth=" + PMBendDepth ;
ret += ", PMBendLength=" + PMBendLength ;
ret += ", PMbPortamentoUse=" + PMbPortamentoUse ;
ret += ", DEMdecGainRate=" + DEMdecGainRate ;
ret += ", DEMaccent=" + DEMaccent ;
if ( LyricHandle != null ) {
ret += ", LyricHandle=h#" + LyricHandle_index.ToString( "0000" ) ;
}
if ( VibratoHandle != null ) {
ret += ", VibratoHandle=h#" + VibratoHandle_index.ToString( "0000" );
ret += ", VibratoDelay=" + VibratoDelay ;
}
break;
case VsqIDType.Singer:
ret += ", IconHandle=h#" + IconHandle_index.ToString( "0000" );
break;
}
ret += "}";
return ret;
}
/// <summary>
/// インスタンスをテキストファイルに出力します
/// </summary>
/// <param name="sw">出力先</param>
public void write( TextMemoryStream sw ) {
sw.writeLine( "[ID#" + value.ToString( "0000" ) + "]" );
sw.writeLine( "Type=" + type );
switch( type ){
case VsqIDType.Anote:
sw.writeLine( "Length=" + Length );
sw.writeLine( "Note#=" + Note );
sw.writeLine( "Dynamics=" + Dynamics );
sw.writeLine( "PMBendDepth=" + PMBendDepth );
sw.writeLine( "PMBendLength=" + PMBendLength );
sw.writeLine( "PMbPortamentoUse=" + PMbPortamentoUse );
sw.writeLine( "DEMdecGainRate=" + DEMdecGainRate );
sw.writeLine( "DEMaccent=" + DEMaccent );
if ( LyricHandle != null ) {
sw.writeLine( "LyricHandle=h#" + LyricHandle_index.ToString( "0000" ) );
}
if ( VibratoHandle != null ) {
sw.writeLine( "VibratoHandle=h#" + VibratoHandle_index.ToString( "0000" ) );
sw.writeLine( "VibratoDelay=" + VibratoDelay );
}
break;
case VsqIDType.Singer:
sw.writeLine( "IconHandle=h#" + IconHandle_index.ToString( "0000" ) );
break;
}
}
/// <summary>
/// VsqIDを構築するテストを行います。
/// </summary>
/// <returns>テストに成功すればtrue、そうでなければfalseを返します</returns>
public static bool test() {
string fpath = Path.GetTempFileName();
using ( StreamWriter sw = new StreamWriter( fpath, false, Encoding.Unicode ) ) {
sw.WriteLine( "Type=Anote" );
sw.WriteLine( "Length=320" );
sw.WriteLine( "Note#=67" );
sw.WriteLine( "Dynamics=64" );
sw.WriteLine( "PMBendDepth=8" );
sw.WriteLine( "PMBendLength=1" );
sw.WriteLine( "PMbPortamentoUse=1" );
sw.WriteLine( "DEMdecGainRate=50" );
sw.WriteLine( "DEMaccent=50" );
sw.WriteLine( "LyricHandle=h#0111" );
sw.WriteLine( "[ID#0104]" );
}
string last_line = "";
bool result;
using ( TextMemoryStream sr = new TextMemoryStream( fpath, Encoding.Unicode ) ) {
VsqID vsqID = new VsqID( sr, 103, ref last_line );
if ( vsqID.type == VsqIDType.Anote &&
vsqID.Length == 320 &&
vsqID.Note == 67 &&
vsqID.Dynamics == 64 &&
vsqID.PMBendDepth == 8 &&
vsqID.PMBendLength == 1 &&
vsqID.PMbPortamentoUse == 1 &&
vsqID.DEMdecGainRate == 50 &&
vsqID.DEMaccent == 50 &&
vsqID.LyricHandle_index == 111 &&
last_line == "[ID#0104]" ) {
result = true;
} else {
result = false;
}
}
File.Delete( fpath );
return result;
}
}
}

View File

@ -0,0 +1,210 @@
/*
* VsqMetaText/Lyric.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;
using System.Text;
using System.IO;
using System.Windows.Forms;
using bocoree;
namespace Boare.Lib.Vsq {
/// <summary>
/// VsqHandleに格納される歌詞の情報を扱うクラス。
/// </summary>
[Serializable]
public class Lyric {
/// <summary>
/// この歌詞のフレーズ
/// </summary>
public string Phrase;
private string[] m_phonetic_symbol;
public float UnknownFloat;
private int[] m_consonant_adjustment;
public bool PhoneticSymbolProtected;
public int[] getConsonantAdjustment() {
return m_consonant_adjustment;
}
/// <summary>
/// このオブジェクトの簡易コピーを取得します。
/// </summary>
/// <returns>このインスタンスの簡易コピー</returns>
public Lyric Clone() {
Lyric result = new Lyric();
result.Phrase = this.Phrase;
result.m_phonetic_symbol = (string[])this.m_phonetic_symbol.Clone();
result.UnknownFloat = this.UnknownFloat;
result.m_consonant_adjustment = (int[])this.m_consonant_adjustment.Clone();
result.PhoneticSymbolProtected = PhoneticSymbolProtected;
return result;
}
/// <summary>
/// 歌詞、発音記号を指定したコンストラクタ
/// </summary>
/// <param name="phrase">歌詞</param>
/// <param name="phonetic_symbol">発音記号</param>
public Lyric( string phrase, string phonetic_symbol ) {
Phrase = phrase;
setPhoneticSymbol( phonetic_symbol );
UnknownFloat = 0.000000f;
}
private Lyric() {
}
/// <summary>
/// この歌詞の発音記号を取得します。
/// </summary>
public string getPhoneticSymbol() {
string ret = m_phonetic_symbol[0];
for ( int i = 1; i < m_phonetic_symbol.Length; i++ ) {
ret += " " + m_phonetic_symbol[i];
}
return ret;
}
/// <summary>
/// この歌詞の発音記号を設定します。
/// </summary>
public void setPhoneticSymbol( string value ) {
string s = value.Replace( " ", " " );
m_phonetic_symbol = s.Split( " ".ToCharArray(), 16 );
for ( int i = 0; i < m_phonetic_symbol.Length; i++ ) {
m_phonetic_symbol[i] = m_phonetic_symbol[i].Replace( @"\\", @"\" );
}
m_consonant_adjustment = new int[m_phonetic_symbol.Length];
for ( int i = 0; i < m_phonetic_symbol.Length; i++ ) {
if ( VsqPhoneticSymbol.isConsonant( m_phonetic_symbol[i] ) ) {
m_consonant_adjustment[i] = 64;
} else {
m_consonant_adjustment[i] = 0;
}
}
}
public string[] getPhoneticSymbolList() {
string[] ret = new string[m_phonetic_symbol.Length];
for ( int i = 0; i < m_phonetic_symbol.Length; i++ ) {
ret[i] = m_phonetic_symbol[i];
}
return ret;
}
/// <summary>
/// 文字列からのコンストラクタ
/// </summary>
/// <param name="_line">生成元の文字列</param>
public Lyric( string _line ) {
byte[] b = new byte[_line.Length];
for ( int i = 0; i < _line.Length; i++ ) {
b[i] = (byte)_line[i];
}
string s = cp932.convert( b );
string[] spl = s.Split( new char[] { ',' } );
int c_length = spl.Length - 3;
if ( spl.Length < 4 ) {
Phrase = "a";
setPhoneticSymbol( "a" );
UnknownFloat = 0.0f;
PhoneticSymbolProtected = false;
} else {
Phrase = spl[0];
if ( Phrase.StartsWith( "\"" ) ) {
Phrase = Phrase.Substring( 1 );
}
if ( Phrase.EndsWith( "\"" ) ) {
Phrase = Phrase.Substring( 0, Phrase.Length - 1 );
}
string symbols = spl[1];
if ( symbols.StartsWith( "\"" ) ) {
symbols = symbols.Substring( 1 );
}
if ( symbols.EndsWith( "\"" ) ) {
symbols = symbols.Substring( 0, symbols.Length - 1 );
}
setPhoneticSymbol( symbols );
UnknownFloat = float.Parse( spl[2] );
PhoneticSymbolProtected = (spl[spl.Length - 1] == "0") ? false : true;
}
}
/// <summary>
/// 与えられた文字列の中の2バイト文字を\x**の形式にエンコードします。
/// </summary>
/// <param name="item">エンコード対象</param>
/// <returns>エンコードした文字列</returns>
public static char[] encode( string item ) {
//Encoding sjis = Encoding.GetEncoding( 932 );
byte[] bytea = cp932.convert( item );// sjis.GetBytes( item );
string result = "";
for ( int i = 0; i < bytea.Length; i++ ) {
if ( isprint( (char)bytea[i] ) ) {
result += (char)bytea[i];
} else {
result += "\\x" + Convert.ToString( bytea[i], 16 );
}
}
char[] res = result.ToCharArray();
return res;
}
/// <summary>
/// このインスタンスを文字列に変換します
/// </summary>
/// <param name="a_encode">2バイト文字をエンコードするか否かを指定するフラグ</param>
/// <returns>変換後の文字列</returns>
public string ToString( bool a_encode ) {
string result;
if ( a_encode ) {
string njp = new string( encode( this.Phrase ) );
result = "\"" + njp + "\",\"" + this.getPhoneticSymbol() + "\"," + UnknownFloat.ToString( "0.000000" );
} else {
result = "\"";
byte[] dat = cp932.convert( this.Phrase );
for ( int i = 0; i < dat.Length; i++ ) {
result += (char)dat[i];
}
result += "\",\"" + this.getPhoneticSymbol() + "\"," + UnknownFloat.ToString( "0.000000" );
result = result.Replace( @"\\", @"\" );
}
for ( int i = 0; i < m_consonant_adjustment.Length; i++ ) {
result += "," + m_consonant_adjustment[i];
}
if ( PhoneticSymbolProtected ) {
result += ",1";
} else {
result += ",0";
}
return result;
}
/// <summary>
/// 文字がプリント出力可能かどうかを判定します
/// </summary>
/// <param name="ch"></param>
/// <returns></returns>
private static bool isprint( char ch ) {
if ( 32 <= (int)ch && (int)ch <= 126 ) {
return true;
} else {
return false;
}
}
}
}

View File

@ -0,0 +1,100 @@
/*
* VsqMetaText/Master.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;
using System.Text;
using System.IO;
namespace Boare.Lib.Vsq {
/// <summary>
/// vsqファイルのメタテキストの[Master]に記録される内容を取り扱う
/// </summary>
[Serializable]
public class VsqMaster : ICloneable {
public int PreMeasure;
public object Clone() {
VsqMaster res = new VsqMaster( PreMeasure );
return res;
}
/// <summary>
/// プリメジャー値を指定したコンストラクタ
/// </summary>
/// <param name="pre_measure"></param>
public VsqMaster( int pre_measure ) {
this.PreMeasure = pre_measure;
}
/// <summary>
/// テキストファイルからのコンストラクタ
/// </summary>
/// <param name="sr">読み込み元</param>
/// <param name="last_line">最後に読み込んだ行が返されます</param>
public VsqMaster( TextMemoryStream sr, ref string last_line ) {
PreMeasure = 0;
string[] spl;
last_line = sr.readLine();
while ( !last_line.StartsWith( "[" ) ) {
spl = last_line.Split( new char[] { '=' } );
switch ( spl[0] ) {
case "PreMeasure":
this.PreMeasure = int.Parse( spl[1] );
break;
}
if ( sr.peek() < 0 ) {
break;
}
last_line = sr.readLine();
}
}
/// <summary>
/// インスタンスの内容をテキストファイルに出力します
/// </summary>
/// <param name="sw">出力先</param>
public void write( TextMemoryStream sw ) {
sw.writeLine( "[Master]" );
sw.writeLine( "PreMeasure=" + PreMeasure );
}
/// <summary>
/// VsqMasterのインスタンスを構築するテストを行います
/// </summary>
/// <returns>テストに成功すればtrue、そうでなければfalseを返します</returns>
public static bool test() {
string fpath = Path.GetTempFileName();
using ( StreamWriter sw = new StreamWriter( fpath, false, Encoding.Unicode ) ) {
sw.WriteLine( "PreMeasure=2" );
sw.WriteLine( "[Mixer]" );
}
bool result;
using ( TextMemoryStream sr = new TextMemoryStream( fpath, Encoding.Unicode ) ) {
string last_line = "";
VsqMaster vsqMaster = new VsqMaster( sr, ref last_line );
if ( vsqMaster.PreMeasure == 2 &&
last_line == "[Mixer]" ) {
result = true;
} else {
result = false;
}
}
File.Delete( fpath );
return result;
}
}
}

View File

@ -0,0 +1,266 @@
/*
* VsqMetaText/Mixer.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;
using System.Text;
using System.IO;
namespace Boare.Lib.Vsq {
/// <summary>
/// vsqファイルのメタテキストの[Mixer]セクションに記録される内容を取り扱う
/// </summary>
[Serializable]
public class VsqMixer : ICloneable {
public int MasterFeder;
public int MasterPanpot;
public int MasterMute;
public int OutputMode;
/// <summary>
/// vsqファイルの各トラックのfader, panpot, muteおよびoutputmode値を保持します
/// </summary>
public List<VsqMixerEntry> Slave = new List<VsqMixerEntry>();
public object Clone() {
VsqMixer res = new VsqMixer( MasterFeder, MasterPanpot, MasterMute, OutputMode );
res.Slave = new List<VsqMixerEntry>();
foreach ( VsqMixerEntry item in Slave ) {
res.Slave.Add( (VsqMixerEntry)item.Clone() );
}
return res;
}
/// <summary>
/// 各パラメータを指定したコンストラクタ
/// </summary>
/// <param name="master_fader">MasterFader値</param>
/// <param name="master_panpot">MasterPanpot値</param>
/// <param name="master_mute">MasterMute値</param>
/// <param name="output_mode">OutputMode値</param>
public VsqMixer( int master_fader, int master_panpot, int master_mute, int output_mode ) {
this.MasterFeder = master_fader;
this.MasterMute = master_mute;
this.MasterPanpot = master_panpot;
this.OutputMode = output_mode;
Slave = new List<VsqMixerEntry>();
}
/// <summary>
/// テキストファイルからのコンストラクタ
/// </summary>
/// <param name="sr">読み込み対象</param>
/// <param name="last_line">最後に読み込んだ行が返されます</param>
public VsqMixer( TextMemoryStream sr, ref string last_line ) {
MasterFeder = 0;
MasterPanpot = 0;
MasterMute = 0;
OutputMode = 0;
//Tracks = 1;
int tracks = 0;
string[] spl;
string buffer = "";
last_line = sr.readLine();
while ( !last_line.StartsWith( "[" ) ) {
spl = last_line.Split( new char[] { '=' } );
switch ( spl[0] ) {
case "MasterFeder":
MasterFeder = int.Parse( spl[1] );
break;
case "MasterPanpot":
MasterPanpot = int.Parse( spl[1] );
break;
case "MasterMute":
MasterMute = int.Parse( spl[1] );
break;
case "OutputMode":
OutputMode = int.Parse( spl[1] );
break;
case "Tracks":
tracks = int.Parse( spl[1] );
break;
default:
if ( spl[0].StartsWith( "Feder" ) ||
spl[0].StartsWith( "Panpot" ) ||
spl[0].StartsWith( "Mute" ) ||
spl[0].StartsWith( "Solo" ) ) {
buffer += spl[0] + "=" + spl[1] + Environment.NewLine;
}
break;
}
if ( sr.peek() < 0 ) {
break;
}
last_line = sr.readLine();
}
Slave = new List<VsqMixerEntry>();
for ( int i = 0; i < tracks; i++ ) {
Slave.Add( new VsqMixerEntry( 0, 0, 0, 0 ) );
}
spl = buffer.Split( new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries );
string[] spl2;
for ( int i = 0; i < spl.Length; i++ ) {
string ind = "";
int index;
spl2 = spl[i].Split( new char[] { '=' } );
if ( spl2[0].StartsWith( "Feder" ) ) {
ind = spl2[0].Replace( "Feder", "" );
index = int.Parse( ind );
Slave[index].Feder = int.Parse( spl2[1] );
} else if ( spl2[0].StartsWith( "Panpot" ) ) {
ind = spl2[0].Replace( "Panpot", "" );
index = int.Parse( ind );
Slave[index].Panpot = int.Parse( spl2[1] );
} else if ( spl2[0].StartsWith( "Mute" ) ) {
ind = spl2[0].Replace( "Mute", "" );
index = int.Parse( ind );
Slave[index].Mute = int.Parse( spl2[1] );
} else if ( spl2[0].StartsWith( "Solo" ) ) {
ind = spl2[0].Replace( "Solo", "" );
index = int.Parse( ind );
Slave[index].Solo = int.Parse( spl2[1] );
}
}
}
/// <summary>
/// このインスタンスをテキストファイルに出力します
/// </summary>
/// <param name="sw">出力対象</param>
public void write( TextMemoryStream sw ) {
sw.writeLine( "[Mixer]" );
sw.writeLine( "MasterFeder=" + MasterFeder );
sw.writeLine( "MasterPanpot=" + MasterPanpot );
sw.writeLine( "MasterMute=" + MasterMute );
sw.writeLine( "OutputMode=" + OutputMode );
sw.writeLine( "Tracks=" + Slave.Count );
for ( int i = 0; i < Slave.Count; i++ ) {
sw.writeLine( "Feder" + i + "=" + Slave[i].Feder );
sw.writeLine( "Panpot" + i + "=" + Slave[i].Panpot );
sw.writeLine( "Mute" + i + "=" + Slave[i].Mute );
sw.writeLine( "Solo" + i + "=" + Slave[i].Solo );
}
}
/// <summary>
/// VsqMixerのインスタンスを構築するテストを行います
/// </summary>
/// <returns>テストに成功すればtrue、そうでなければfalseを返します</returns>
public static bool test() {
string fpath = Path.GetTempFileName();
StreamWriter sw = new StreamWriter( fpath, false, Encoding.Unicode );
sw.WriteLine( "MasterFeder=12" );
sw.WriteLine( "MasterPanpot=13" );
sw.WriteLine( "MasterMute=14" );
sw.WriteLine( "OutputMode=15" );
sw.WriteLine( "Tracks=8" );
sw.WriteLine( "Feder0=1" );
sw.WriteLine( "Panpot0=2" );
sw.WriteLine( "Mute0=3" );
sw.WriteLine( "Solo0=4" );
sw.WriteLine( "Feder1=5" );
sw.WriteLine( "Panpot1=6" );
sw.WriteLine( "Mute1=7" );
sw.WriteLine( "Solo1=8" );
sw.WriteLine( "Feder2=9" );
sw.WriteLine( "Panpot2=10" );
sw.WriteLine( "Mute2=11" );
sw.WriteLine( "Solo2=12" );
sw.WriteLine( "Feder3=13" );
sw.WriteLine( "Panpot3=14" );
sw.WriteLine( "Mute3=15" );
sw.WriteLine( "Solo3=16" );
sw.WriteLine( "Feder4=17" );
sw.WriteLine( "Panpot4=18" );
sw.WriteLine( "Mute4=19" );
sw.WriteLine( "Solo4=20" );
sw.WriteLine( "Feder5=21" );
sw.WriteLine( "Panpot5=22" );
sw.WriteLine( "Mute5=23" );
sw.WriteLine( "Solo5=24" );
sw.WriteLine( "Feder6=25" );
sw.WriteLine( "Panpot6=26" );
sw.WriteLine( "Mute6=27" );
sw.WriteLine( "Solo6=28" );
sw.WriteLine( "Feder7=29" );
sw.WriteLine( "Panpot7=30" );
sw.WriteLine( "Mute7=31" );
sw.WriteLine( "Solo7=32" );
sw.WriteLine( "[EventList]" );
sw.Close();
TextMemoryStream sr = new TextMemoryStream( fpath, Encoding.Unicode );
string last_line = "";
VsqMixer vsqMixer = new VsqMixer( sr, ref last_line );
if( vsqMixer.MasterFeder == 12 &&
vsqMixer.MasterPanpot == 13 &&
vsqMixer.MasterMute == 14 &&
vsqMixer.OutputMode == 15 &&
vsqMixer.Slave.Count == 8 ){
for( int i = 0; i < vsqMixer.Slave.Count; i++ ){
int start = 4 * i;
if ( vsqMixer.Slave[i].Feder != start + 1 ||
vsqMixer.Slave[i].Panpot != start + 2 ||
vsqMixer.Slave[i].Mute != start + 3 ||
vsqMixer.Slave[i].Solo != start + 4 ) {
sr.close();
File.Delete( fpath );
return false;
}
}
}else{
sr.close();
File.Delete( fpath );
return false;
}
sr.close();
File.Delete( fpath );
return true;
}
}
/// <summary>
/// VsqMixerのSlave要素に格納される各エントリ
/// </summary>
[Serializable]
public class VsqMixerEntry : ICloneable {
public int Feder;
public int Panpot;
public int Mute;
public int Solo;
public object Clone() {
VsqMixerEntry res = new VsqMixerEntry( Feder, Panpot, Mute, Solo );
return res;
}
/// <summary>
/// 各パラメータを指定したコンストラクタ
/// </summary>
/// <param name="feder">Feder値</param>
/// <param name="panpot">Panpot値</param>
/// <param name="mute">Mute値</param>
/// <param name="solo">Solo値</param>
public VsqMixerEntry( int feder, int panpot, int mute, int solo ) {
this.Feder = feder;
this.Panpot = panpot;
this.Mute = mute;
this.Solo = solo;
}
}
}

View File

@ -0,0 +1,811 @@
/*
* VsqMetaText/VsqMetaText.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;
using System.Text;
using System.IO;
using System.Drawing;
using System.Windows.Forms;
namespace Boare.Lib.Vsq {
/// <summary>
/// vsqのメタテキストの中身を処理するためのクラス
/// </summary>
[Serializable]
public class VsqMetaText : ICloneable {
public VsqCommon Common;
internal VsqMaster master;
internal VsqMixer mixer;
private VsqEventList m_events;
/// <summary>
/// PIT。ピッチベンド(pitchBendBPList)。default=0
/// </summary>
public VsqBPList PIT;
/// <summary>
/// PBS。ピッチベンドセンシティビティ(pitchBendSensBPList)。dfault=2
/// </summary>
public VsqBPList PBS;
/// <summary>
/// DYN。ダイナミクス(dynamicsBPList)。default=64
/// </summary>
public VsqBPList DYN;
/// <summary>
/// BRE。ブレシネス(epRResidualBPList)。default=0
/// </summary>
public VsqBPList BRE;
/// <summary>
/// BRI。ブライトネス(epRESlopeBPList)。default=64
/// </summary>
public VsqBPList BRI;
/// <summary>
/// CLE。クリアネス(epRESlopeDepthBPList)。default=0
/// </summary>
public VsqBPList CLE;
private VsqBPList reso1FreqBPList;
private VsqBPList reso2FreqBPList;
private VsqBPList reso3FreqBPList;
private VsqBPList reso4FreqBPList;
private VsqBPList reso1BWBPList;
private VsqBPList reso2BWBPList;
private VsqBPList reso3BWBPList;
private VsqBPList reso4BWBPList;
private VsqBPList reso1AmpBPList;
private VsqBPList reso2AmpBPList;
private VsqBPList reso3AmpBPList;
private VsqBPList reso4AmpBPList;
/// <summary>
/// GEN。ジェンダーファクター(genderFactorBPList)。default=64
/// </summary>
public VsqBPList GEN;
/// <summary>
/// POR。ポルタメントタイミング(portamentoTimingBPList)。default=64
/// </summary>
public VsqBPList POR;
/// <summary>
/// OPE。オープニング(openingBPList)。default=127
/// </summary>
public VsqBPList OPE;
public object Clone() {
VsqMetaText res = new VsqMetaText();
if ( Common != null ) {
res.Common = (VsqCommon)Common.Clone();
}
if ( master != null ) {
res.master = (VsqMaster)master.Clone();
}
if ( mixer != null ) {
res.mixer = (VsqMixer)mixer.Clone();
}
if ( m_events != null ) {
res.m_events = new VsqEventList();
for ( Iterator itr = m_events.iterator(); itr.hasNext(); ) {
res.m_events.add( (VsqEvent)((VsqEvent)itr.next()).Clone() );
}
}
if ( PIT != null ) {
res.PIT = (VsqBPList)PIT.Clone();
}
if ( PBS != null ) {
res.PBS = (VsqBPList)PBS.Clone();
}
if ( DYN != null ) {
res.DYN = (VsqBPList)DYN.Clone();
}
if ( BRE != null ) {
res.BRE = (VsqBPList)BRE.Clone();
}
if ( BRI != null ) {
res.BRI = (VsqBPList)BRI.Clone();
}
if ( CLE != null ) {
res.CLE = (VsqBPList)CLE.Clone();
}
if ( reso1FreqBPList != null ) {
res.reso1FreqBPList = (VsqBPList)reso1FreqBPList.Clone();
}
if ( reso2FreqBPList != null ) {
res.reso2FreqBPList = (VsqBPList)reso2FreqBPList.Clone();
}
if ( reso3FreqBPList != null ) {
res.reso3FreqBPList = (VsqBPList)reso3FreqBPList.Clone();
}
if ( reso4FreqBPList != null ) {
res.reso4FreqBPList = (VsqBPList)reso4FreqBPList.Clone();
}
if ( reso1BWBPList != null ) {
res.reso1BWBPList = (VsqBPList)reso1BWBPList.Clone();
}
if ( reso2BWBPList != null ) {
res.reso2BWBPList = (VsqBPList)reso2BWBPList.Clone();
}
if ( reso3BWBPList != null ) {
res.reso3BWBPList = (VsqBPList)reso3BWBPList.Clone();
}
if ( reso4BWBPList != null ) {
res.reso4BWBPList = (VsqBPList)reso4BWBPList.Clone();
}
if ( reso1AmpBPList != null ) {
res.reso1AmpBPList = (VsqBPList)reso1AmpBPList.Clone();
}
if ( reso2AmpBPList != null ) {
res.reso2AmpBPList = (VsqBPList)reso2AmpBPList.Clone();
}
if ( reso3AmpBPList != null ) {
res.reso3AmpBPList = (VsqBPList)reso3AmpBPList.Clone();
}
if ( reso4AmpBPList != null ) {
res.reso4AmpBPList = (VsqBPList)reso4AmpBPList.Clone();
}
if ( GEN != null ) {
res.GEN = (VsqBPList)GEN.Clone();
}
if ( POR != null ) {
res.POR = (VsqBPList)POR.Clone();
}
if ( OPE != null ) {
res.OPE = (VsqBPList)OPE.Clone();
}
return res;
}
public VsqEventList getEventList() {
return m_events;
}
internal VsqBPList getElement( string curve ) {
switch ( curve.Trim().ToLower() ) {
case "bre":
return this.BRE;
case "bri":
return this.BRI;
case "cle":
return this.CLE;
case "dyn":
return this.DYN;
case "gen":
return this.GEN;
case "ope":
return this.OPE;
case "pbs":
return this.PBS;
case "pit":
return this.PIT;
case "por":
return this.POR;
default:
return null;
}
}
internal void setElement( string curve, VsqBPList value ) {
switch ( curve.Trim().ToLower() ) {
case "bre":
this.BRE = value;
break;
case "bri":
this.BRI = value;
break;
case "cle":
this.CLE = value;
break;
case "dyn":
this.DYN = value;
break;
case "gen":
this.GEN = value;
break;
case "ope":
this.OPE = value;
break;
case "pbs":
this.PBS = value;
break;
case "pit":
this.PIT = value;
break;
case "por":
this.POR = value;
break;
}
}
/// <summary>
/// Editor画面上で上からindex番目のカーブを表すBPListを求めます
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public VsqBPList getCurve( int index ) {
switch ( index ) {
case 1:
return DYN;
case 2:
return BRE;
case 3:
return BRI;
case 4:
return CLE;
case 5:
return OPE;
case 6:
return GEN;
case 7:
return POR;
case 8:
return PIT;
case 9:
return PBS;
default:
return null;
}
}
/// <summary>
/// Editor画面上で上からindex番目のカーブの名前を調べます
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public static string getCurveName( int index ) {
switch ( index ) {
case 0:
return "VEL";
case 1:
return "DYN";
case 2:
return "BRE";
case 3:
return "BRI";
case 4:
return "CLE";
case 5:
return "OPE";
case 6:
return "GEN";
case 7:
return "POR";
case 8:
return "PIT";
case 9:
return "PBS";
default:
return "";
}
}
/// <summary>
/// Singerプロパティに指定されている
/// </summary>
public string getSinger() {
for ( Iterator itr = m_events.iterator(); itr.hasNext(); ) {
VsqEvent item = (VsqEvent)itr.next();
if ( item.ID.type == VsqIDType.Singer ) {
return item.ID.IconHandle.IDS;
}
}
return "";
}
public void setSinger( string value ) {
for ( Iterator itr = m_events.iterator(); itr.hasNext(); ) {
VsqEvent item = (VsqEvent)itr.next();
if ( item.ID.type == VsqIDType.Singer ) {
item.ID.IconHandle.IDS = value;
break;
}
}
}
/// <summary>
/// EOSイベントが記録されているクロックを取得します。
/// </summary>
/// <returns></returns>
public int getIndexOfEOS() {
int result;
if ( m_events.getCount() > 0 ) {
int ilast = m_events.getCount() - 1;
result = m_events.getElement( ilast ).Clock;
} else {
result = -1;
}
return result;
}
/// <summary>
/// このインスタンスから、IDとHandleのリストを構築します
/// </summary>
/// <param name="id"></param>
/// <param name="handle"></param>
void BuildIDHandleList( out List<VsqID> id, out List<VsqHandle> handle ) {
id = new List<VsqID>();
handle = new List<VsqHandle>();
int current_id = -1;
int current_handle = -1;
List<VsqEvent> events = new List<VsqEvent>();
for ( Iterator itr = m_events.iterator(); itr.hasNext(); ) {
events.Add( (VsqEvent)itr.next() );
}
events.Sort();
for( int i = 0; i < events.Count; i++ ){
VsqEvent item = events[i];
VsqID id_item = (VsqID)item.ID.Clone();
current_id++;
item.ID.value = current_id;
id_item.value = current_id;
// IconHandle
if ( item.ID.IconHandle != null ) {
current_handle++;
VsqHandle handle_item = item.ID.IconHandle.castToVsqHandle();
handle_item.Index = current_handle;
handle.Add( handle_item );
id_item.IconHandle_index = current_handle;
}
// LyricHandle
if ( item.ID.LyricHandle != null ) {
current_handle++;
VsqHandle handle_item = item.ID.LyricHandle.castToVsqHandle();
handle_item.Index = current_handle;
handle.Add( handle_item );
id_item.LyricHandle_index = current_handle;
}
// VibratoHandle
if ( item.ID.VibratoHandle != null ) {
current_handle++;
VsqHandle handle_item = item.ID.VibratoHandle.castToVsqHandle();
handle_item.Index = current_handle;
handle.Add( handle_item );
id_item.VibratoHandle_index = current_handle;
}
id.Add( id_item );
}
}
/// <summary>
/// このインスタンスの内容を指定されたファイルに出力します。
/// </summary>
/// <param name="sw"></param>
/// <param name="encode"></param>
public void print( TextMemoryStream sw, bool encode, int eos, int start ) {
if ( Common != null ) {
Common.write( sw );
}
if ( master != null ) {
master.write( sw );
}
if ( mixer != null ) {
mixer.write( sw );
}
List<VsqID> id;
List<VsqHandle> handle;
BuildIDHandleList( out id, out handle );
writeEventList( sw, eos );
int i;
for ( i = 0; i < id.Count; i++ ) {
id[i].write( sw );
}
for ( i = 0; i < handle.Count; i++ ) {
handle[i].write( sw, encode );
}
if ( PIT.getCount() > 0 ) {
PIT.print( sw, start, "[PitchBendBPList]" );
}
if ( PBS.getCount() > 0 ) {
PBS.print( sw, start, "[PitchBendSensBPList]" );
}
if ( DYN.getCount() > 0 ) {
DYN.print( sw, start, "[DynamicsBPList]" );
}
if ( BRE.getCount() > 0 ) {
BRE.print( sw, start, "[EpRResidualBPList]" );
}
if ( BRI.getCount() > 0 ) {
BRI.print( sw, start, "[EpRESlopeBPList]" );
}
if ( CLE.getCount() > 0 ) {
CLE.print( sw, start, "[EpRESlopeDepthBPList]" );
}
if ( reso1FreqBPList.getCount() > 0 ) {
reso1FreqBPList.print( sw, start, "[Reso1FreqBPList]" );
}
if ( reso2FreqBPList.getCount() > 0 ) {
reso2FreqBPList.print( sw, start, "[Reso2FreqBPList]" );
}
if ( reso3FreqBPList.getCount() > 0 ) {
reso3FreqBPList.print( sw, start, "[Reso3FreqBPList]" );
}
if ( reso4FreqBPList.getCount() > 0 ) {
reso4FreqBPList.print( sw, start, "[Reso4FreqBPList]" );
}
if ( reso1BWBPList.getCount() > 0 ) {
reso1BWBPList.print( sw, start, "[Reso1BWBPList]" );
}
if ( reso2BWBPList.getCount() > 0 ) {
reso2BWBPList.print( sw, start, "[Reso2BWBPList]" );
}
if ( reso3BWBPList.getCount() > 0 ) {
reso3BWBPList.print( sw, start, "[Reso3BWBPList]" );
}
if ( reso4BWBPList.getCount() > 0 ) {
reso4BWBPList.print( sw, start, "[Reso4BWBPList]" );
}
if ( reso1AmpBPList.getCount() > 0 ) {
reso1AmpBPList.print( sw, start, "[Reso1AmpBPList]" );
}
if ( reso2AmpBPList.getCount() > 0 ) {
reso2AmpBPList.print( sw, start, "[Reso2AmpBPList]" );
}
if ( reso3AmpBPList.getCount() > 0 ) {
reso3AmpBPList.print( sw, start, "[Reso3AmpBPList]" );
}
if ( reso4AmpBPList.getCount() > 0 ) {
reso4AmpBPList.print( sw, start, "[Reso4AmpBPList]" );
}
if ( GEN.getCount() > 0 ) {
GEN.print( sw, start, "[GenderFactorBPList]" );
}
if ( POR.getCount() > 0 ) {
POR.print( sw, start, "[PortamentoTimingBPList]" );
}
if ( OPE.getCount() > 0 ) {
OPE.print( sw, start, "[OpeningBPList]" );
}
}
private void writeEventList( TextMemoryStream sw, int eos ) {
sw.writeLine( "[EventList]" );
List<VsqEvent> temp = new List<VsqEvent>();
for ( Iterator itr = m_events.iterator(); itr.hasNext(); ) {
temp.Add( (VsqEvent)itr.next() );
}
temp.Sort();
int i = 0;
while ( i < temp.Count ) {
VsqEvent item = temp[i];
if ( !item.ID.Equals( VsqID.EOS ) ) {
string ids = "ID#" + i.ToString( "0000" );
int clock = temp[i].Clock;
while ( i + 1 < temp.Count && clock == temp[i + 1].Clock ) {
i++;
ids += ",ID#" + i.ToString( "0000" );
}
sw.writeLine( clock + "=" + ids );
}
i++;
}
sw.writeLine( eos + "=EOS" );
}
/// <summary>
/// 何も無いVsqMetaTextを構築する。これは、Master Track用のMetaTextとしてのみ使用されるべき
/// </summary>
public VsqMetaText() {
}
/// <summary>
/// 最初のトラック以外の一般のメタテキストを構築。(Masterが作られない)
/// </summary>
public VsqMetaText( string name, string singer )
: this( name, 0, singer, false ) {
}
/// <summary>
/// 最初のトラックのメタテキストを構築。(Masterが作られる)
/// </summary>
/// <param name="pre_measure"></param>
public VsqMetaText( string name, string singer, int pre_measure )
: this( name, pre_measure, singer, true ) {
}
private VsqMetaText( string name, int pre_measure, string singer, bool is_first_track ) {
Common = new VsqCommon( name, Color.FromArgb( 179, 181, 123 ), 1, 1 );
PIT = new VsqBPList( 0, -8192, 8192 );
PIT.add( 0, PIT.getDefault() );
PBS = new VsqBPList( 2, 0, 24 );
PBS.add( 0, PBS.getDefault() );
DYN = new VsqBPList( 64, 0, 127 );
DYN.add( 0, DYN.getDefault() );
BRE = new VsqBPList( 0, 0, 127 );
BRE.add( 0, BRE.getDefault() );
BRI = new VsqBPList( 64, 0, 127 );
BRI.add( 0, BRI.getDefault() );
CLE = new VsqBPList( 0, 0, 127 );
CLE.add( 0, CLE.getDefault() );
reso1FreqBPList = new VsqBPList( 255, 0, 255 );
reso1FreqBPList.add( 0, reso1FreqBPList.getDefault() );
reso2FreqBPList = new VsqBPList( 255, 0, 255 );
reso2FreqBPList.add( 0, reso2FreqBPList.getDefault() );
reso3FreqBPList = new VsqBPList( 255, 0, 255 );
reso3FreqBPList.add( 0, reso3FreqBPList.getDefault() );
reso4FreqBPList = new VsqBPList( 255, 0, 255 );
reso4FreqBPList.add( 0, reso4FreqBPList.getDefault() );
reso1BWBPList = new VsqBPList( 255, 0, 255 );
reso1BWBPList.add( 0, reso1BWBPList.getDefault() );
reso2BWBPList = new VsqBPList( 255, 0, 255 );
reso2BWBPList.add( 0, reso2BWBPList.getDefault() );
reso3BWBPList = new VsqBPList( 255, 0, 255 );
reso3BWBPList.add( 0, reso3BWBPList.getDefault() );
reso4BWBPList = new VsqBPList( 255, 0, 255 );
reso4BWBPList.add( 0, reso4BWBPList.getDefault() );
reso1AmpBPList = new VsqBPList( 255, 0, 255 );
reso1AmpBPList.add( 0, reso1AmpBPList.getDefault() );
reso2AmpBPList = new VsqBPList( 255, 0, 255 );
reso2AmpBPList.add( 0, reso2AmpBPList.getDefault() );
reso3AmpBPList = new VsqBPList( 255, 0, 255 );
reso3AmpBPList.add( 0, reso3AmpBPList.getDefault() );
reso4AmpBPList = new VsqBPList( 255, 0, 255 );
reso4AmpBPList.add( 0, reso4AmpBPList.getDefault() );
GEN = new VsqBPList( 64, 0, 127 );
GEN.add( 0, GEN.getDefault() );
POR = new VsqBPList( 64, 0, 127 );
POR.add( 0, POR.getDefault() );
OPE = new VsqBPList( 127, 0, 127 );
OPE.add( 0, OPE.getDefault() );
if ( is_first_track ) {
master = new VsqMaster( pre_measure );
} else {
master = null;
}
m_events = new VsqEventList();
VsqID id = new VsqID( 0 );
id.type = VsqIDType.Singer;
id.IconHandle = new IconHandle();
id.IconHandle.IconID = "$07010000";
id.IconHandle.IDS = singer;
id.IconHandle.Original = 0;
id.IconHandle.Caption = "";
id.IconHandle.Length = 1;
id.IconHandle.Language = 0;
id.IconHandle.Program = 0;
m_events.add( new VsqEvent( 0, id ) );
}
public VsqMetaText( TextMemoryStream sr ) {
List<KeyValuePair<int, int>> t_event_list = new List<KeyValuePair<int, int>>();
Dictionary<int, VsqID> __id = new Dictionary<int, VsqID>();
Dictionary<int, VsqHandle> __handle = new Dictionary<int, VsqHandle>();
PIT = new VsqBPList( 0, -8192, 8192 );
PBS = new VsqBPList( 2, 0, 24 );
DYN = new VsqBPList( 64, 0, 127 );
BRE = new VsqBPList( 0 , 0, 127);
BRI = new VsqBPList( 64, 0, 127 );
CLE = new VsqBPList( 0, 0, 127 );
reso1FreqBPList = new VsqBPList( 255, 0, 255 );
reso2FreqBPList = new VsqBPList( 255, 0, 255 );
reso3FreqBPList = new VsqBPList( 255, 0, 255 );
reso4FreqBPList = new VsqBPList( 255, 0, 255 );
reso1BWBPList = new VsqBPList( 255, 0, 255 );
reso2BWBPList = new VsqBPList( 255, 0, 255 );
reso3BWBPList = new VsqBPList( 255, 0, 255 );
reso4BWBPList = new VsqBPList( 255, 0, 255 );
reso1AmpBPList = new VsqBPList( 255, 0, 255 );
reso2AmpBPList = new VsqBPList( 255, 0, 255 );
reso3AmpBPList = new VsqBPList( 255, 0, 255 );
reso4AmpBPList = new VsqBPList( 255, 0, 255 );
GEN = new VsqBPList( 64, 0, 127 );
POR = new VsqBPList( 64, 0, 127 );
OPE = new VsqBPList( 127, 0, 127 );
string last_line = sr.readLine();
while ( true ) {
#region "TextMemoryStreamから順次読込み"
if ( last_line.Length == 0 ) {
break;
}
switch ( last_line ) {
case "[Common]":
Common = new VsqCommon( sr, ref last_line );
break;
case "[Master]":
master = new VsqMaster( sr, ref last_line );
break;
case "[Mixer]":
mixer = new VsqMixer( sr, ref last_line );
break;
case "[EventList]":
last_line = sr.readLine();
while ( !last_line.StartsWith( "[" ) ) {
string[] spl2 = last_line.Split( new char[] { '=' } );
int clock = int.Parse( spl2[0] );
int id_number = -1;
if ( spl2[1] != "EOS" ) {
string[] ids = spl2[1].Split( ",".ToCharArray() );
for ( int i = 0; i < ids.Length; i++ ) {
string[] spl3 = ids[i].Split( new char[] { '#' } );
id_number = int.Parse( spl3[1] );
t_event_list.Add( new KeyValuePair<int,int>( clock, id_number ) );
}
} else {
t_event_list.Add( new KeyValuePair<int,int>( clock, -1) );
}
if ( sr.peek() < 0 ) {
break;
} else {
last_line = sr.readLine();
}
}
break;
case "[PitchBendBPList]":
last_line = PIT.appendFromText( sr );
break;
case "[PitchBendSensBPList]":
last_line = PBS.appendFromText( sr );
break;
case "[DynamicsBPList]":
last_line = DYN.appendFromText( sr );
break;
case "[EpRResidualBPList]":
last_line = BRE.appendFromText( sr );
break;
case "[EpRESlopeBPList]":
last_line = BRI.appendFromText( sr );
break;
case "[EpRESlopeDepthBPList]":
last_line = CLE.appendFromText( sr );
break;
case "[Reso1FreqBPList]":
last_line = reso1FreqBPList.appendFromText( sr );
break;
case "[Reso2FreqBPList]":
last_line = reso2FreqBPList.appendFromText( sr );
break;
case "[Reso3FreqBPList]":
last_line = reso3FreqBPList.appendFromText( sr );
break;
case "[Reso4FreqBPList]":
last_line = reso4FreqBPList.appendFromText( sr );
break;
case "[Reso1BWBPList]":
last_line = reso1BWBPList.appendFromText( sr );
break;
case "[Reso2BWBPList]":
last_line = reso2BWBPList.appendFromText( sr );
break;
case "[Reso3BWBPList]":
last_line = reso3BWBPList.appendFromText( sr );
break;
case "[Reso4BWBPList]":
last_line = reso4BWBPList.appendFromText( sr );
break;
case "[Reso1AmpBPList]":
last_line = reso1AmpBPList.appendFromText( sr );
break;
case "[Reso2AmpBPList]":
last_line = reso2AmpBPList.appendFromText( sr );
break;
case "[Reso3AmpBPList]":
last_line = reso3AmpBPList.appendFromText( sr );
break;
case "[Reso4AmpBPList]":
last_line = reso4AmpBPList.appendFromText( sr );
break;
case "[GenderFactorBPList]":
last_line = GEN.appendFromText( sr );
break;
case "[PortamentoTimingBPList]":
last_line = POR.appendFromText( sr );
break;
case "[OpeningBPList]":
last_line = OPE.appendFromText( sr );
break;
default:
string buffer = last_line;
buffer = buffer.Replace( "[", "" );
buffer = buffer.Replace( "]", "" );
string[] spl = buffer.Split( new char[] { '#' } );
int index = int.Parse( spl[1] );
if ( last_line.StartsWith( "[ID#" ) ) {
__id.Add( index, new VsqID( sr, index, ref last_line ) );
} else if ( last_line.StartsWith( "[h#" ) ) {
__handle.Add( index, new VsqHandle( sr, index, ref last_line ) );
}
break;
#endregion
}
if ( sr.peek() < 0 ) {
break;
}
}
// まずhandleをidに埋め込み
for ( int i = 0; i < __id.Count; i++ ) {
if ( __handle.ContainsKey( __id[i].IconHandle_index ) ) {
__id[i].IconHandle = __handle[__id[i].IconHandle_index].castToIconHandle();
}
if ( __handle.ContainsKey( __id[i].LyricHandle_index ) ) {
__id[i].LyricHandle = __handle[__id[i].LyricHandle_index].castToLyricHandle();
}
if ( __handle.ContainsKey( __id[i].VibratoHandle_index ) ) {
__id[i].VibratoHandle = __handle[__id[i].VibratoHandle_index].castToVibratoHandle();
}
}
// idをeventListに埋め込み
m_events = new VsqEventList();
for ( int i = 0; i < t_event_list.Count; i++ ) {
int clock = t_event_list[i].Key;
int id_number = t_event_list[i].Value;
if ( __id.ContainsKey( id_number ) ) {
m_events.add( new VsqEvent( clock, (VsqID)__id[id_number].Clone() ) );
}
}
}
public static bool test( string fpath ) {
VsqMetaText metaText;
using ( TextMemoryStream sr = new TextMemoryStream( fpath, Encoding.Unicode ) ) {
metaText = new VsqMetaText( sr );
}
string result = "test.txt";
StreamReader honmono = new StreamReader( fpath );
TextMemoryStream copy = new TextMemoryStream( FileAccess.ReadWrite );
metaText.print( copy, true, 1000, 100 );
copy.rewind();
while ( honmono.Peek() >= 0 && copy.peek() >= 0 ) {
string hon = honmono.ReadLine();
string cop = copy.readLine();
if ( hon != cop ) {
Console.WriteLine( "honmono,copy=" + hon + "," + cop );
honmono.Close();
copy.close();
return false;
}
}
honmono.Close();
copy.close();
return true;
}
}
public enum VsqIDType {
Singer,
Anote,
Unknown
}
public enum VsqHandleType {
Lyric,
Vibrato,
Singer
}
}

View File

@ -0,0 +1,236 @@
/*
* VsqNote.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;
using System.Text;
namespace Boare.Lib.Vsq {
/// <summary>
/// 音階を表現するためのクラス
/// </summary>
[Serializable]
public class VsqNote {
/// <summary>
/// このインスタンスが表す音階のノート値
/// </summary>
public int Value;
private static readonly bool[] _KEY_TYPE = new bool[128] {
true,
false,
true,
false,
true,
true,
false,
true,
false,
true,
false,
true,
true,
false,
true,
false,
true,
true,
false,
true,
false,
true,
false,
true,
true,
false,
true,
false,
true,
true,
false,
true,
false,
true,
false,
true,
true,
false,
true,
false,
true,
true,
false,
true,
false,
true,
false,
true,
true,
false,
true,
false,
true,
true,
false,
true,
false,
true,
false,
true,
true,
false,
true,
false,
true,
true,
false,
true,
false,
true,
false,
true,
true,
false,
true,
false,
true,
true,
false,
true,
false,
true,
false,
true,
true,
false,
true,
false,
true,
true,
false,
true,
false,
true,
false,
true,
true,
false,
true,
false,
true,
true,
false,
true,
false,
true,
false,
true,
true,
false,
true,
false,
true,
true,
false,
true,
false,
true,
false,
true,
true,
false,
true,
false,
true,
true,
false,
true,
};
/// <summary>
/// 音階のノート値からのコンストラクタ。
/// </summary>
/// <param name="note">この音階を初期化するためのノート値</param>
public VsqNote( int note ) {
Value = note;
}
/// <summary>
/// このインスタンスが表す音階が、ピアノの白鍵かどうかを返します
/// </summary>
public bool isWhiteKey() {
return isNoteWhiteKey( Value );
}
/// <summary>
/// 指定した音階が、ピアノの白鍵かどうかを返します
/// </summary>
/// <param name="note"></param>
/// <returns></returns>
public static bool isNoteWhiteKey( int note ) {
if ( 0 <= note && note <= 127 ) {
return _KEY_TYPE[note];
} else {
int odd = note % 12;
switch ( odd ) {
case 1:
case 3:
case 6:
case 8:
case 10:
return false;
default:
return true;
}
}
}
public static string getNoteString( int note ) {
int odd = note % 12;
int order = (note - odd) / 12 - 2;
switch ( odd ) {
case 0:
return "C" + order;
case 1:
return "C#" + order;
case 2:
return "D" + order;
case 3:
return "Eb" + order;
case 4:
return "E" + order;
case 5:
return "F" + order;
case 6:
return "F#" + order;
case 7:
return "G" + order;
case 8:
return "G#" + order;
case 9:
return "A" + order;
case 10:
return "Bb" + order;
case 11:
return "B" + order;
default:
return "";
}
}
override public string ToString() {
return getNoteString( Value );
}
}
}

View File

@ -0,0 +1,116 @@
/*
* VsqNrpn.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 VsqNrpn : IComparable<VsqNrpn> {
public int Clock;
public ushort Nrpn;
public byte DataMsb;
public byte DataLsb;
public bool DataLsbSpecified = false;
private List<VsqNrpn> m_list;
public VsqNrpn( int clock, ushort nrpn, byte data_msb ) {
Clock = clock;
Nrpn = nrpn;
DataMsb = data_msb;
DataLsbSpecified = false;
m_list = new List<VsqNrpn>();
}
public VsqNrpn( int clock, ushort nrpn, byte data_msb, byte data_lsb ) {
Clock = clock;
Nrpn = nrpn;
DataMsb = data_msb;
DataLsb = data_lsb;
DataLsbSpecified = true;
m_list = new List<VsqNrpn>();
}
private VsqNrpn() {
}
public VsqNrpn[] expand() {
List<VsqNrpn> ret = new List<VsqNrpn>();
if ( DataLsbSpecified ) {
ret.Add( new VsqNrpn( Clock, Nrpn, DataMsb, DataLsb ) );
} else {
ret.Add( new VsqNrpn( Clock, Nrpn, DataMsb ) );
}
for ( int i = 0; i < m_list.Count; i++ ) {
ret.AddRange( m_list[i].expand() );
}
return ret.ToArray();
}
public static VsqNrpn[] merge( VsqNrpn[] src1, VsqNrpn[] src2 ) {
List<VsqNrpn> ret = new List<VsqNrpn>();
for ( int i = 0; i < src1.Length; i++ ) {
ret.Add( src1[i] );
}
for ( int i = 0; i < src2.Length; i++ ) {
ret.Add( src2[i] );
}
ret.Sort();
return ret.ToArray();
}
public static NrpnData[] convert( VsqNrpn[] source ) {
ushort nrpn = (ushort)source[0].Nrpn;
byte msb = (byte)(nrpn >> 8);
byte lsb = (byte)(nrpn - (nrpn << 8));
List<NrpnData> ret = new List<NrpnData>();
ret.Add( new NrpnData( source[0].Clock, 0x63, msb ) );
ret.Add( new NrpnData( source[0].Clock, 0x62, lsb ) );
ret.Add( new NrpnData( source[0].Clock, 0x06, source[0].DataMsb ) );
if ( source[0].DataLsbSpecified ) {
ret.Add( new NrpnData( source[0].Clock, 0x26, source[0].DataLsb ) );
}
byte last_msb = msb;
for ( int i = 1; i < source.Length; i++ ) {
ushort tnrpn = (ushort)source[i].Nrpn;
msb = (byte)(tnrpn >> 8);
lsb = (byte)(tnrpn - (tnrpn << 8));
//if ( msb != last_msb ) {
ret.Add( new NrpnData( source[i].Clock, 0x63, msb ) );
//} else if ( msb == 0x63 ) {
// ret.Add( new NrpnData( source[i].Clock, 0x63, msb ) );
//}
last_msb = msb;
ret.Add( new NrpnData( source[i].Clock, 0x62, lsb ) );
ret.Add( new NrpnData( source[i].Clock, 0x06, source[i].DataMsb ) );
if ( source[i].DataLsbSpecified ) {
ret.Add( new NrpnData( source[i].Clock, 0x26, source[i].DataLsb ) );
}
}
return ret.ToArray();
}
public int CompareTo( VsqNrpn item ) {
return Clock - item.Clock;
}
public void append( NRPN nrpn, byte data_msb ) {
m_list.Add( new VsqNrpn( Clock, (ushort)nrpn, data_msb ) );
}
public void append( NRPN nrpn, byte data_msb, byte data_lsb ) {
m_list.Add( new VsqNrpn( Clock, (ushort)nrpn, data_msb, data_lsb ) );
}
}
}

View File

@ -0,0 +1,153 @@
/*
* VsqPhoneticSymbol.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;
namespace Boare.Lib.Vsq {
public class VsqPhoneticSymbol {
private static string[] _SYMBOL_VOWEL_JP = new string[]{
@"a",
@"i",
@"M",
@"e",
@"o",
};
private static string[] _SYMBOL_CONSONANT_JP = new string[]{
@"k",
@"k'",
@"g",
@"g'",
@"N",
@"N'",
@"s",
@"S",
@"z",
@"Z",
@"dz",
@"dZ",
@"t",
@"t'",
@"ts",
@"tS",
@"d",
@"d'",
@"n",
@"J",
@"h",
@"h\",
@"C",
@"p\",
@"p\'",
@"b",
@"b'",
@"p",
@"p'",
@"m",
@"m'",
@"j",
@"4",
@"4'",
@"w",
@"N\",
};
private static string[] _SYMBOL_EN = new string[]{
@"@",
@"V",
@"e",
@"e",
@"I",
@"i:",
@"{",
@"O:",
@"Q",
@"U",
@"u:",
@"@r",
@"eI",
@"aI",
@"OI",
@"@U",
@"aU",
@"I@",
@"e@",
@"U@",
@"O@",
@"Q@",
@"w",
@"j",
@"b",
@"d",
@"g",
@"bh",
@"dh",
@"gh",
@"dZ",
@"v",
@"D",
@"z",
@"Z",
@"m",
@"n",
@"N",
@"r",
@"l",
@"l0",
@"p",
@"t",
@"k",
@"ph",
@"th",
@"kh",
@"tS",
@"f",
@"T",
@"s",
@"S",
@"h",
};
public static bool isConsonant( string symbol ) {
for ( int i = 0; i < _SYMBOL_CONSONANT_JP.Length; i++ ){
string s = _SYMBOL_CONSONANT_JP[i];
if ( s == symbol ) {
return true;
}
}
return false;
}
public static bool isValidSymbol( string symbol ) {
for ( int i = 0; i < _SYMBOL_VOWEL_JP.Length; i++ ){
string s = _SYMBOL_VOWEL_JP[i];
if ( s == symbol ) {
return true;
}
}
for ( int i = 0; i < _SYMBOL_CONSONANT_JP.Length; i++ ){
string s = _SYMBOL_CONSONANT_JP[i];
if ( s == symbol ) {
return true;
}
}
for ( int i = 0; i < _SYMBOL_EN.Length; i++ ){
string s = _SYMBOL_EN[i];
if ( s == symbol ) {
return true;
}
}
return false;
}
}
}

View File

@ -0,0 +1,413 @@
/*
* VsqTrack.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;
using System.IO;
namespace Boare.Lib.Vsq {
/// <summary>
/// Stores the data of a vsq track.
/// </summary>
[Serializable]
public partial class VsqTrack : ICloneable {
public object Tag;
/// <summary>
/// トラックの名前。
/// </summary>
public string Name;
private VsqMetaText m_meta_text;
private List<Boare.Lib.Vsq.MidiEvent> m_midi_event;
private int m_edited_start = int.MaxValue;
private int m_edited_end = int.MinValue;
public string Renderer = "VOCALOID2";
private class SingerEventIterator : Iterator {
VsqEventList m_list;
int m_pos;
public SingerEventIterator( VsqEventList list ) {
m_list = list;
m_pos = -1;
}
public bool hasNext() {
for ( int i = m_pos + 1; i < m_list.getCount(); i++ ) {
if ( m_list.getElement( i ).ID.type == VsqIDType.Singer ) {
return true;
}
}
return false;
}
public object next() {
for ( int i = m_pos + 1; i < m_list.getCount(); i++ ) {
VsqEvent item = m_list.getElement( i );
if ( item.ID.type == VsqIDType.Singer ) {
m_pos = i;
return item;
}
}
return null;
}
public void remove() {
if ( 0 <= m_pos && m_pos < m_list.getCount() ) {
m_list.removeAt( m_pos );
}
}
}
private class NoteEventIterator : Iterator {
VsqEventList m_list;
int m_pos;
public NoteEventIterator( VsqEventList list ) {
m_list = list;
m_pos = -1;
}
public bool hasNext() {
for ( int i = m_pos + 1; i < m_list.getCount(); i++ ) {
if ( m_list.getElement( i ).ID.type == VsqIDType.Anote ) {
return true;
}
}
return false;
}
public object next() {
for ( int i = m_pos + 1; i < m_list.getCount(); i++ ) {
VsqEvent item = m_list.getElement( i );
if ( item.ID.type == VsqIDType.Anote ) {
m_pos = i;
return item;
}
}
return null;
}
public void remove() {
if ( 0 <= m_pos && m_pos < m_list.getCount() ) {
m_list.removeAt( m_pos );
}
}
}
private class EventIterator : Iterator{
private VsqEventList m_list;
private int m_pos;
public EventIterator( VsqEventList list ) {
m_list = list;
m_pos = -1;
}
public Boolean hasNext() {
if ( 0 <= m_pos + 1 && m_pos + 1 < m_list.getCount() ) {
return true;
}
return false;
}
public Object next() {
m_pos++;
return m_list.getElement( m_pos );
}
public void remove() {
if ( 0 <= m_pos && m_pos < m_list.getCount() ) {
m_list.removeAt( m_pos );
}
}
}
/// <summary>
/// 歌手変更イベントを曲の先頭から順に返すIteratorを取得します
/// </summary>
/// <returns></returns>
public Iterator getSingerEventIterator() {
return new SingerEventIterator( m_meta_text.getEventList() );
}
/// <summary>
/// 音符イベントを曲の先頭から順に返すIteratorを取得します
/// </summary>
/// <returns></returns>
public Iterator getNoteEventIterator() {
return new NoteEventIterator( m_meta_text.getEventList() );
}
/// <summary>
/// メタテキストを,メモリー上のストリームに出力します
/// </summary>
/// <param name="sw"></param>
/// <param name="encode"></param>
/// <param name="eos"></param>
/// <param name="start"></param>
public void printMetaText( TextMemoryStream sw, int eos, int start ) {
m_meta_text.print( sw, false, eos, start );
}
/// <summary>
/// メタテキストを,指定されたファイルに出力します
/// </summary>
/// <param name="file"></param>
public void printMetaText( string file ) {
TextMemoryStream tms = new TextMemoryStream( FileAccess.ReadWrite );
int count = m_meta_text.getEventList().getCount();
int clLast = m_meta_text.getEventList().getElement( count - 1 ).Clock + 480;
m_meta_text.print( tms, true, clLast, 0 );
using ( StreamWriter sw = new StreamWriter( file ) ) {
tms.rewind();
while ( tms.peek() >= 0 ) {
string line = tms.readLine();
sw.WriteLine( line );
}
}
}
/// <summary>
/// Masterを取得します
/// </summary>
public VsqMaster getMaster() {
return m_meta_text.master;
}
internal void setMaster( VsqMaster value ) {
m_meta_text.master = value;
}
/// <summary>
/// Mixerを取得します
/// </summary>
public VsqMixer getMixer() {
return m_meta_text.mixer;
}
internal void setMixer( VsqMixer value ) {
m_meta_text.mixer = value;
}
/// <summary>
/// このトラックが保持している指定されたカーブのBPListを取得します
/// </summary>
/// <param name="curve"></param>
/// <returns></returns>
public VsqBPList getCurve( string curve ) {
return m_meta_text.getElement( curve );
}
public void setCurve( string curve, VsqBPList value ) {
m_meta_text.setElement( curve, value );
}
public int getEventCount() {
return m_meta_text.getEventList().getCount();
}
public VsqEvent getEvent( int index ) {
return m_meta_text.getEventList().getElement( index );
}
public void setEvent( int index, VsqEvent item ) {
m_meta_text.getEventList().setElement( index, item );
}
public void addEvent( VsqEvent item ) {
m_meta_text.getEventList().add( item );
}
public Iterator getEventIterator() {
return new EventIterator( m_meta_text.getEventList() );
}
public void removeEvent( int index ) {
m_meta_text.getEventList().removeAt( index );
}
/// <summary>
/// このトラックの,最後に編集が加えられた範囲の,開始位置(クロック)を取得します.
/// このインスタンスを保持しているVsqFileインスタンスのExecuteメソッドによって自動的に更新されます
/// </summary>
public int getEditedStart() {
return m_edited_start;
}
internal void setEditedStart( int value ) {
if ( value < m_edited_start ) {
m_edited_start = value;
}
}
/// <summary>
/// このトラックの,最後に編集が加えられた範囲の,終了位置(クロック)を取得します.
/// このインスタンスを保持しているVsqFileインスタンスのExecuteメソッドによって自動的に更新されます
/// </summary>
public int getEditedEnd() {
return m_edited_end;
}
internal void setEditedEnd( int value ) {
if ( m_edited_end < value ) {
m_edited_end = value;
}
}
/// <summary>
/// このトラックの編集範囲EditedStart, EditedEndをリセットします
/// </summary>
public void resetEditedArea() {
m_edited_start = int.MaxValue;
m_edited_end = int.MinValue;
}
/// <summary>
/// このインスタンスのコピーを作成します
/// </summary>
/// <returns></returns>
public object Clone() {
VsqTrack res = new VsqTrack();
res.Name = Name;
if ( m_meta_text != null ) {
res.m_meta_text = (VsqMetaText)m_meta_text.Clone();
}
if ( m_midi_event != null ) {
res.m_midi_event = new List<MidiEvent>( m_midi_event );
}
res.m_edited_start = m_edited_start;
res.m_edited_end = m_edited_end;
res.Renderer = Renderer;
return res;
}
private VsqTrack() {
}
/// <summary>
/// Master Trackを構築
/// </summary>
/// <param name="tempo"></param>
/// <param name="numerator"></param>
/// <param name="denominator"></param>
public VsqTrack( int tempo, int numerator, int denominator ) {
this.Name = "Master Track";
this.m_meta_text = null;
m_midi_event = new List<MidiEvent>();
// テンポを設定
MidiEvent mi_tempo = new MidiEvent();
mi_tempo.Clock = 0;
mi_tempo.FirstByte = 0xff;
byte b1 = (byte)(tempo & 0xff);
tempo = tempo >> 8;
byte b2 = (byte)(tempo & 0xff);
tempo = tempo >> 8;
byte b3 = (byte)(tempo & 0xff);
mi_tempo.Data = new byte[5] { 0x51, 0x03, b3, b2, b1 };
m_midi_event.Add( mi_tempo );
// 拍子を設定
MidiEvent mi_timesig = MidiEvent.generateTimeSigEvent( 0, numerator, denominator );
m_midi_event.Add( mi_timesig );
}
/// <summary>
/// Master Trackでないトラックを構築。
/// </summary>
/// <param name="name"></param>
/// <param name="singer"></param>
public VsqTrack( string name, string singer ) {
Name = name;
m_meta_text = new VsqMetaText( name, singer );
m_midi_event = new List<MidiEvent>();
}
/// <summary>
/// 歌詞の文字数を調べます
/// </summary>
/// <returns></returns>
public int getLyricLength() {
int counter = 0;
for ( int i = 0; i < m_meta_text.getEventList().getCount(); i++ ) {
if ( m_meta_text.getEventList().getElement( i ).ID.type == VsqIDType.Anote ) {
counter++;
}
}
return counter;
}
public VsqTrack( List<Boare.Lib.Vsq.MidiEvent> midi_events ) {
m_midi_event = new List<MidiEvent>( midi_events );
Name = "";
#if DEBUG
bocoree.debug.push_log( "VsqTrack..ctor" );
#endif
using ( TextMemoryStream sw = new TextMemoryStream() ) {
for ( int i = 0; i < m_midi_event.Count; i++ ) {
if ( m_midi_event[i].FirstByte == 0xff && m_midi_event[i].Data.Length > 0 ) {
// meta textを抽出
byte type = m_midi_event[i].Data[0];
if ( type == 0x01 || type == 0x03 ) {
char[] ch = new char[m_midi_event[i].Data.Length - 1];
for ( int j = 1; j < midi_events[i].Data.Length; j++ ) {
ch[j - 1] = (char)midi_events[i].Data[j];
}
string line = new string( ch );
if ( type == 0x01 ) {
int second_colon = line.IndexOf( ':', 3 );
line = line.Substring( second_colon + 1 );
line = line.Replace( "\\n", Environment.NewLine );
line = line.Replace( "\n", Environment.NewLine );
sw.write( line );
} else {
Name = line;
}
}
} else {
continue;
}
}
sw.rewind();
m_meta_text = new VsqMetaText( sw );
}
}
public List<MidiEvent> getTempoList() {
List<MidiEvent> list = new List<MidiEvent>();
for ( int i = 0; i < m_midi_event.Count; i++ ) {
if ( m_midi_event[i].FirstByte == 0xff && m_midi_event[i].Data.Length >= 4 && m_midi_event[i].Data[0] == 0x51 ) {
list.Add( m_midi_event[i] );
}
}
return list;
}
/// <summary>
/// MidiEventの中から拍子情報を抽出します
/// </summary>
/// <returns></returns>
public List<MidiEvent> getTimeSigList() {
List<MidiEvent> list = new List<MidiEvent>();
for ( int i = 0; i < m_midi_event.Count; i++ ) {
if ( m_midi_event[i].FirstByte == 0xff && m_midi_event[i].Data.Length >= 5 && m_midi_event[i].Data[0] == 0x58 ) {
list.Add( m_midi_event[i] );
}
}
return list;
}
}
}

View File

@ -0,0 +1,390 @@
/*
* 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;
}
}
}

View File

@ -0,0 +1,173 @@
#ifndef __comhdr_h__
#define __comhdr_h__
#include <string>
#include <list>
#include <vector>
#include <sstream>
#include <fstream>
#include <map>
using namespace std;
#if __cplusplus
template<typename O, typename T> class Property{
public:
Property( O *owner_, T (O::*get_)( void ), void (O::*set_)( T ) ) :
owner( owner_ ),
getMethod( get_ ),
setMethod( set_ ){
}
operator T(){
return (owner->*getMethod)();
}
void operator=( const T value ){
(owner->*setMethod)( value );
}
private:
O *owner;
T (O::*getMethod)( void );
void (O::*setMethod)( T );
};
template<typename O, typename T> class ReadOnlyProperty{
public:
ReadOnlyProperty( O *owner_, T (O::*get_)( void ) ) :
owner( owner_ ),
getMethod( get_ ){
}
operator T(){
return (owner->*getMethod)();
}
private:
O *owner;
T (O::*getMethod)( void );
};
template<typename O, typename T> class WriteOnlyProperty{
public:
WriteOnlyProperty( O *owner_, void (O::*set_)( T ) ) :
owner( owner_ ),
setMethod( set_ ){
}
void operator=( const T value ){
(owner->*setMethod)( value );
}
private:
O *owner;
void (O::*setMethod)( T );
};
#define null NULL
typedef unsigned char byte;
string util_string_from_array( vector<wchar_t> str ){
string ret;
for( int i = 0; i < str.size(); i++ ){
ret += str[i];
}
return ret;
}
string util_string_from_array( vector<wchar_t> str, int start, int length ){
string ret;
for( int i = start; i < str.size() && i - start < length ; i++ ){
ret += str[i];
}
return ret;
}
vector<wchar_t> util_string_to_array( string str ){
std::vector<wchar_t> ret( str.size() );
for( int i = 0; i < str.size(); i++ ){
ret[i] = str[i];
}
return ret;
}
vector<string> util_split( string str, string delim ){
vector<string> result;
int cutAt;
while( (cutAt = str.find_first_of( delim )) != str.npos ){
if( cutAt > 0 ){
result.push_back( str.substr( 0, cutAt ) );
}
str = str.substr( cutAt + 1 );
}
if( str.length() > 0 ){
result.push_back( str );
}
return result;
}
int util_parse_int( string str ){
istringstream s( str );
int ret = 0;
s >> ret;
return ret;
}
#endif
namespace Boare{ namespace System{ namespace IO{
class StreamReader{
public:
//StreamReader( Stream stream );
StreamReader( string path ){
m_ifs.open( path.c_str() );
}
//StreamReader( Stream stream, bool detectEncodingFromByteOrderMarks );
//StreamReader( Stream stream, Encoding encoding );
//StreamReader( string path, bool detectEncodingFromByteOrderMarks );
//StreamReader( string path, Encoding encoding );
//StreamReader( Stream stream, Encoding encoding, bool detectEncodingFromByteOrderMarks );
//StreamReader( string path, Encoding encoding, bool detectEncodingFromByteOrderMarks );
//StreamReader( Stream stream, Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize );
//StreamReader( string path, Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize );
void Close(){
m_ifs.close();
}
string ReadLine(){
string ret;
if( get_line( &m_ifs, &ret ) ){
return ret;
}else{
return NULL;
}
}
int Peek(){
return m_ifs.peek();
}
private:
ifstream m_ifs;
static bool get_line( ifstream *ifs, string *str ){
char ch;
if( ifs->eof() ){
return false;
}
while( ifs->get( ch ) ){
if( ch == 0x0d ){
if( ifs->get( ch ) ){
if( ch != 0x0a ){
ifs->seekg( -1, ios::cur );
}
}
break;
}else if( ch == 0x0a ){
break;
}
str->append( 1, ch );
}
return true;
}
};
} } }
#endif // __comhdr_h__

View File

@ -0,0 +1,46 @@
#ifndef __common_h__
#define __common_h__
#include <vector>
#include <string>
#include <fstream>
#include <sstream>
using namespace std;
namespace Boare{ namespace Lib{ namespace Vsq{
typedef struct Color_t{
int R;
int G;
int B;
} Color;
vector<string> split( string src, string delim );
int int_parse( string str );
typedef class StreamReader_t{
public:
//StreamReader( Stream stream );
StreamReader_t( string path );
//StreamReader( Stream stream, bool detectEncodingFromByteOrderMarks );
//StreamReader( Stream stream, Encoding encoding );
//StreamReader( string path, bool detectEncodingFromByteOrderMarks );
//StreamReader( string path, Encoding encoding );
//StreamReader( Stream stream, Encoding encoding, bool detectEncodingFromByteOrderMarks );
//StreamReader( string path, Encoding encoding, bool detectEncodingFromByteOrderMarks );
//StreamReader( Stream stream, Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize );
//StreamReader( string path, Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize );
void Close();
string ReadLine();
int Peek();
private:
ifstream m_ifs;
static bool get_line( ifstream *ifs, string *str );
} StreamReader;
} } }
#endif

View File

@ -0,0 +1,21 @@
CP=cp
RM=rm
all: Boare.Lib.Vsq.dll libvsq.exe
Boare.Lib.Vsq.dll: *.cs bocoree.dll
gmcs -recurse:*.cs -target:library -define:MONO -out:Boare.Lib.Vsq.dll -r:bocoree.dll,System,System.Windows.Forms,System.Drawing
bocoree.dll: ../bocoree/bocoree.dll
cp ../bocoree/bocoree.dll bocoree.dll
../bocoree/bocoree.dll:
cd ../bocoree/ && $(MAKE)
libvsq.exe: common.cpp TextMemoryStream.cpp VsqCommon.cpp main.cpp
g++ common.cpp TextMemoryStream.cpp VsqCommon.cpp main.cpp -o libvsq.exe
clean:
$(RM) Boare.Lib.Vsq.dll
$(RM) bocoree.dll
cd ../bocoree/ && $(MAKE) RM=$(RM) clean

View File

@ -0,0 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 10.00
# Visual C++ Express 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Boare.Lib.Vsq", "Boare.Lib.Vsq.vcproj", "{19B6B5B7-6ADD-42D9-9F1E-426417DF4827}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{19B6B5B7-6ADD-42D9-9F1E-426417DF4827}.Debug|Win32.ActiveCfg = Debug|Win32
{19B6B5B7-6ADD-42D9-9F1E-426417DF4827}.Debug|Win32.Build.0 = Debug|Win32
{19B6B5B7-6ADD-42D9-9F1E-426417DF4827}.Release|Win32.ActiveCfg = Release|Win32
{19B6B5B7-6ADD-42D9-9F1E-426417DF4827}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,187 @@
<?xml version="1.0" encoding="shift_jis"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="libvsq"
ProjectGUID="{19B6B5B7-6ADD-42D9-9F1E-426417DF4827}"
RootNamespace="BoareLibVsq"
Keyword="Win32Proj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="4"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="0"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="4"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="ソース ファイル"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\cp932.cpp"
>
</File>
<File
RelativePath=".\libvsq.cpp"
>
</File>
<File
RelativePath=".\main.cpp"
>
</File>
</Filter>
<Filter
Name="ヘッダー ファイル"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\cp932.h"
>
</File>
<File
RelativePath=".\libvsq.h"
>
</File>
</Filter>
<Filter
Name="リソース ファイル"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,13 @@
#ifndef __cp932_h__
#define __cp932_h__
#include <map>
#include <vector>
#include <sstream>
using namespace std;
wstring cp932_convert( vector<char> dat );
vector<char> cp932_convert( wstring str );
#endif // __cp932_h__

View File

@ -0,0 +1,2 @@
#include "libvsq.h"

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,17 @@
#include "libvsq.h"
#include <iostream>
using namespace std;
using namespace vsq;
int main(){
TextMemoryStream tms;
tms.WriteLine( "foo" );
tms.WriteLine( "bar" );
tms.Rewind();
while( tms.Peek() >= 0 ){
cout << tms.ReadLine() << endl;
}
tms.Close();
return 0;
}

View File

@ -0,0 +1,239 @@
namespace Background {
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using Plugin;
public class Background : IPlugin {
public void ApplyLanguage( string language_code ) {
}
/// <summary>
/// プラグインの名称
/// </summary>
public string Name {
get {
return "Background";
}
}
/// <summary>
/// プラグインのタイプを表す。
/// </summary>
public ulong Type {
get {
return Constants.LS_ENABLES_ENTRY_SETTING + Constants.LS_NO_EVENT_HANDLER;
}
}
/// <summary>
/// プラグインの簡潔な説明文。
/// </summary>
public string Abstract {
get {
return "画像を配置するプラグインです。様々な特効が使えます。";
}
}
/// <summary>
/// イベントハンドラ。このプラグインの設定メニューが押された時呼び出されます。
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public DialogResult BaseSetting() {
return DialogResult.Cancel;
}
public DialogResult EntrySetting( ref string config ) {
EntryConfig cfg = new EntryConfig( config );
DialogResult result;
using ( entry_config dlg = new entry_config( cfg ) ) {
result = dlg.ShowDialog();
if ( result == DialogResult.OK ) {
cfg = dlg.Config;
config = cfg.ToString();
}
}
return result;
}
/// <summary>
/// 設定値を格納した文字列を指定します。
/// </summary>
/// <returns></returns>
public string Config {
get {
return "";
}
set {
}
}
private Bitmap m_bmp;
private string m_last_file = "";
/// <summary>
/// フレームに加工を施す関数
/// </summary>
/// <param name="bmp"></param>
/// <param name="time"></param>
public void Apply( ref Bitmap bmp, float time, float e_begin, float e_end, ref string e_body ) {
EntryConfig cfg = new EntryConfig( e_body );
if ( m_last_file != "" ) {
if ( m_last_file != cfg.File ) {
Image img = ImageFromFile( cfg.File );
if ( img != null ) {
m_bmp = new Bitmap( img.Width, img.Height, PixelFormat.Format32bppArgb );
using ( Graphics gx = Graphics.FromImage( m_bmp ) ) {
gx.DrawImage( img, 0, 0, img.Width, img.Height );
}
}
m_last_file = cfg.File;
}
} else {
Image img = ImageFromFile( cfg.File );
if ( img != null ) {
m_bmp = new Bitmap( img.Width, img.Height, PixelFormat.Format32bppArgb );
using ( Graphics gx = Graphics.FromImage( m_bmp ) ) {
gx.DrawImage( img, 0, 0, img.Width, img.Height );
}
}
}
float alpha = 1f;
if ( cfg.FadeIn ) {
float diff = time - e_begin;
if ( 0f <= diff && diff <= cfg.FadeInRatio ) {
alpha = 1.0f / cfg.FadeInRatio * diff;
}
}
if ( cfg.FadeOut ) {
float diff = e_end - time;
if ( 0f <= diff && diff <= cfg.FadeOutRatio ) {
alpha = 1.0f / cfg.FadeOutRatio * diff;
}
}
if ( m_bmp != null ) {
using ( Graphics g = Graphics.FromImage( bmp ) ) {
//g.DrawImage( m_bmp, cfg.X, cfg.Y, m_bmp.Width * cfg.Scale, m_bmp.Height * cfg.Scale );
ColorMatrix cm = new ColorMatrix();
cm.Matrix00 = 1;
cm.Matrix11 = 1;
cm.Matrix22 = 1;
cm.Matrix33 = alpha;
cm.Matrix44 = 1;
ImageAttributes ia = new ImageAttributes();
ia.SetColorMatrix( cm );
int width = (int)(m_bmp.Width * cfg.Scale);
int height = (int)(m_bmp.Height * cfg.Scale);
int iwidth = m_bmp.Width;
int iheight = m_bmp.Height;
g.DrawImage( m_bmp, new Rectangle( cfg.X, cfg.Y, width, height ),
0, 0, iwidth, iheight, GraphicsUnit.Pixel, ia );
}
}
}
/// <summary>
/// 指定したパスのファイルからイメージを読み込みます
/// </summary>
/// <param name="fpath"></param>
/// <returns></returns>
public static Image ImageFromFile( string fpath ) {
Image result = null;
if ( File.Exists( fpath ) ) {
using ( FileStream fs = new FileStream( fpath, FileMode.Open, FileAccess.Read ) ) {
result = Image.FromStream( fs );
}
}
return result;
}
public void Render( Graphics g, Size size, float time, string mouth, string reserved ) {
}
}
public struct EntryConfig {
public string File;
public bool FadeIn;
public bool FadeOut;
public int X;
public int Y;
public float Scale;
public float FadeInRatio;
public float FadeOutRatio;
public EntryConfig( string config ) {
string[] spl = config.Split( new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries );
File = "";
FadeIn = false;
FadeOut = false;
X = 0;
Y = 0;
Scale = 1f;
FadeInRatio = 2f;
FadeOutRatio = 2f;
foreach ( string entry in spl ) {
string[] spl2 = entry.Split( new char[] { '=' } );
switch ( spl2[0] ) {
case "File":
File = spl2[1];
break;
case "FadeIn":
if ( spl2[1] == TRUE ) {
FadeIn = true;
} else {
FadeIn = false;
}
break;
case "FadeOut":
if ( spl2[1] == TRUE ) {
FadeOut = true;
} else {
FadeOut = false;
}
break;
case "X":
X = int.Parse( spl2[1] );
break;
case "Y":
Y = int.Parse( spl2[1] );
break;
case "Scale":
Scale = float.Parse( spl2[1] );
break;
case "FadeInRatio":
FadeInRatio = float.Parse( spl2[1] );
break;
case "FadeOutRatio":
FadeOutRatio = float.Parse( spl2[1] );
break;
}
}
}
private const string TRUE = "true";
private const string FALSE = "false";
new public string ToString() {
string fadein, fadeout;
if ( FadeIn ) {
fadein = TRUE;
} else {
fadein = FALSE;
}
if ( FadeOut ) {
fadeout = TRUE;
} else {
fadeout = FALSE;
}
return "File=" + File + "\nFadeIn=" + fadein + "\nFadeOut=" + fadeout + "\nX=" + X + "\nY=" + Y + "\nScale=" + Scale + "\nFadeInRatio=" + FadeInRatio + "\nFadeOutRatio=" + FadeOutRatio;
}
}
}

View File

@ -0,0 +1,77 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.21022</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{F3B0AB64-CEEE-4003-9DA1-BCD4109ECBA9}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Background</RootNamespace>
<AssemblyName>Background</AssemblyName>
<FileUpgradeFlags>
</FileUpgradeFlags>
<OldToolsVersion>2.0</OldToolsVersion>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Background.cs" />
<Compile Include="entry_config.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="entry_config.Designer.cs">
<DependentUpon>entry_config.cs</DependentUpon>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="entry_config.resx">
<SubType>Designer</SubType>
<DependentUpon>entry_config.cs</DependentUpon>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\IPlugin\IPlugin.csproj">
<Project>{FB0C1FBD-3CB7-46BF-8E39-57BE2C8D1F00}</Project>
<Name>IPlugin</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
<PropertyGroup>
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
</Project>

Some files were not shown because too many files have changed in this diff Show More