HUGE improvements to synthesized audio editor and minor bug fixes in VSQX format; we can now inline edit lyrics in editor and all sorts of cool stuff

This commit is contained in:
Michael Becker 2020-05-12 08:44:59 -04:00
parent 8dc5e95f86
commit 6c5dea0ec9
No known key found for this signature in database
GPG Key ID: 506F54899E2BFED7
6 changed files with 654 additions and 268 deletions

View File

@ -0,0 +1,198 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkDialog">
<property name="can_focus">False</property>
<property name="type_hint">dialog</property>
<child>
<placeholder/>
</child>
<child internal-child="vbox">
<object class="GtkBox">
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<child internal-child="action_area">
<object class="GtkButtonBox">
<property name="can_focus">False</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton" id="cmdOK">
<property name="label">gtk-ok</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
<style>
<class name="suggested-action"/>
</style>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="cmdCancel">
<property name="label">gtk-cancel</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">16</property>
<property name="margin_right">16</property>
<property name="margin_top">16</property>
<property name="margin_bottom">16</property>
<property name="row_spacing">8</property>
<property name="column_spacing">16</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Note _value</property>
<property name="use_underline">True</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">_Lyric</property>
<property name="use_underline">True</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="txtNoteValue">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hexpand">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
<property name="width">3</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="txtLyric">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hexpand">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
<property name="width">3</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">_Phoneme</property>
<property name="use_underline">True</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">2</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="txtPhoneme">
<property name="visible">True</property>
<property name="can_focus">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">2</property>
<property name="width">3</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Note o_ff</property>
<property name="use_underline">True</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">2</property>
<property name="top_attach">3</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Note o_n</property>
<property name="use_underline">True</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">3</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="txtNoteOff">
<property name="visible">True</property>
<property name="can_focus">True</property>
</object>
<packing>
<property name="left_attach">3</property>
<property name="top_attach">3</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="txtNoteOn">
<property name="visible">True</property>
<property name="can_focus">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">3</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</interface>

View File

@ -729,6 +729,7 @@
<Content Include="Editors\Binary\Dialogs\FieldDefinitionPropertiesDialog.glade" />
<Content Include="Editors\Binary\BinaryEditor.glade" />
<Content Include="Editors\Database\DatabaseEditor.glade" />
<Content Include="Editors\Multimedia\Synthesized\Dialogs\NotePropertiesDialog.glade" />
</ItemGroup>
<ItemGroup>
<Content Include="Configuration\Application.upl" />

View File

@ -19,37 +19,55 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
using System;
using MBS.Framework.UserInterface;
using MBS.Framework.UserInterface.Controls;
using MBS.Framework.UserInterface.Layouts;
using UniversalEditor.ObjectModels.Multimedia.Audio.Synthesized;
namespace UniversalEditor.Editors.Multimedia.Audio.Synthesized.PianoRoll.Dialogs
{
/// <summary>
/// Provides a UWT <see cref="CustomDialog" /> that modifies the properties of a <see cref="ObjectModels.Multimedia.Audio.Synthesized.SynthesizedAudioCommandNote" />.
/// Provides a UWT <see cref="ContainerLayoutAttribute" />-based <see cref="CustomDialog" /> that modifies the properties of a
/// <see cref="ObjectModels.Multimedia.Audio.Synthesized.SynthesizedAudioCommandNote" />.
/// </summary>
[ContainerLayout("~/Editors/Multimedia/Synthesized/Dialogs/NotePropertiesDialog.glade")]
public class NotePropertiesDialog : CustomDialog
{
private Label lblNoteValue = null;
private TextBox txtNoteValue = null;
private TextBox txtNoteValue;
private TextBox txtLyric;
private TextBox txtPhoneme;
private NumericTextBox txtNoteOn;
private NumericTextBox txtNoteOff;
public NotePropertiesDialog()
private Button cmdOK;
public string Lyric { get; set; } = null;
public string Phoneme { get; set; } = null;
public double NoteOn { get; set; } = 0.0;
public double NoteOff { get; set; } = 0.0;
protected override void OnCreated(EventArgs e)
{
Layout = new BoxLayout(Orientation.Vertical);
base.OnCreated(e);
DefaultButton = cmdOK;
Container p = new Container();
p.Layout = new GridLayout();
txtLyric.Text = Lyric;
txtPhoneme.Text = Phoneme;
txtNoteOn.Value = NoteOn;
txtNoteOff.Value = NoteOff;
}
lblNoteValue = new Label();
lblNoteValue.Text = "Note _value:";
p.Controls.Add(lblNoteValue, new GridLayout.Constraints(0, 0));
txtNoteValue = new TextBox();
p.Controls.Add(txtNoteValue, new GridLayout.Constraints(0, 1));
[EventHandler(nameof(cmdOK), "Click")]
private void cmdOK_Click(object sender, EventArgs e)
{
Lyric = txtLyric.Text;
Phoneme = txtPhoneme.Text;
NoteOn = txtNoteOn.Value;
NoteOff = txtNoteOff.Value;
this.Controls.Add(p, new BoxLayout.Constraints(true, true));
this.Buttons.Add(new Button(StockType.OK, DialogResult.OK));
this.Buttons.Add(new Button(StockType.Cancel, DialogResult.Cancel));
DialogResult = DialogResult.OK;
Close();
}
}
}

View File

@ -1,10 +1,10 @@
//
// PianoRollControl.cs
// PianoRollView.cs - provides a UWT-based View for manipulating SynthesizedAudioCommands in a piano roll style
//
// Author:
// Mike Becker <alcexhim@gmail.com>
// Michael Becker <alcexhim@gmail.com>
//
// Copyright (c) 2019 Mike Becker
// Copyright (c) 2019-2020 Mike Becker's Software
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@ -18,23 +18,42 @@
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
using System;
using System.Collections.Generic;
using MBS.Framework.Drawing;
using MBS.Framework.UserInterface;
using MBS.Framework.UserInterface.Controls;
using MBS.Framework.UserInterface.Drawing;
using MBS.Framework.UserInterface.Input.Keyboard;
using MBS.Framework.UserInterface.Input.Mouse;
using MBS.Framework.UserInterface.Layouts;
using UniversalEditor.Editors.Multimedia.Audio.Synthesized.PianoRoll.Dialogs;
using UniversalEditor.ObjectModels.Multimedia.Audio.Synthesized;
using UniversalEditor.UserInterface;
namespace UniversalEditor.Editors.Multimedia.Audio.Synthesized.PianoRoll.Controls
{
/// <summary>
/// Provides a UWT-based <see cref="View" /> for manipulating <see cref="SynthesizedAudioCommand" />s in a piano roll style.
/// </summary>
public class PianoRollView : View
{
private TextBox txt = null;
private SynthesizedAudioCommandNote _EditingNote = null;
public PianoRollView(Editor parentEditor) : base(parentEditor)
{
Layout = new AbsoluteLayout();
txt = new TextBox();
txt.BorderStyle = ControlBorderStyle.None;
txt.WidthChars = 0;
txt.KeyDown += txt_KeyDown;
Controls.Add(txt, new AbsoluteLayout.Constraints(0, 0, 128, 18));
this.ContextMenuCommandID = "PianoRollEditor_ContextMenu";
Application.AttachCommandEventHandler("PianoRollEditor_ContextMenu_Arrow", ContextMenuArrow_Click);
@ -78,6 +97,55 @@ namespace UniversalEditor.Editors.Multimedia.Audio.Synthesized.PianoRoll.Control
Application.AttachCommandEventHandler("PianoRollEditor_ContextMenu_Properties", ContextMenuProperties_Click);
}
private void txt_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == KeyboardKey.Enter)
{
if (_EditingNote != null)
{
if (_EditingNote.Lyric != txt.Text)
{
(Parent as Editor).BeginEdit();
_EditingNote.Lyric = txt.Text;
(Parent as Editor).EndEdit();
}
}
txt.Visible = false;
}
else if (e.Key == KeyboardKey.Tab)
{
if (_EditingNote != null)
{
if (_EditingNote.Lyric != txt.Text)
{
(Parent as Editor).BeginEdit();
_EditingNote.Lyric = txt.Text;
(Parent as Editor).EndEdit();
}
if ((e.ModifierKeys & KeyboardModifierKey.Shift) == KeyboardModifierKey.Shift)
{
LyricEditNote(SelectedTrack.Commands.PreviousOfType<SynthesizedAudioCommandNote>(_EditingNote));
}
else
{
LyricEditNote(SelectedTrack.Commands.NextOfType<SynthesizedAudioCommandNote>(_EditingNote));
}
}
e.Cancel = true;
}
else if (e.Key == KeyboardKey.Escape)
{
txt.Visible = false;
}
}
protected override void OnRealize(EventArgs e)
{
base.OnRealize(e);
// hack
txt.Visible = false;
}
/// <summary>
/// When greater than -1, specifies the note length at which all newly-created notes are set and prevents dragging to specify note length.
/// </summary>
@ -265,7 +333,7 @@ namespace UniversalEditor.Editors.Multimedia.Audio.Synthesized.PianoRoll.Control
public int KeyboardWidth { get { return mvarKeyboardWidth; } set { mvarKeyboardWidth = value; Invalidate(); } }
private int mvarQuarterNoteWidth = 48;
private int mvarNoteHeight = 14;
private int mvarNoteHeight = 22;
private double mvarZoomFactor = 1.0;
public double ZoomFactor { get { return mvarZoomFactor; } set { mvarZoomFactor = value; Invalidate(); } }
@ -350,6 +418,8 @@ namespace UniversalEditor.Editors.Multimedia.Audio.Synthesized.PianoRoll.Control
}
drag_CurrentLocation = drag_OriginalLocation;
}
txt.Visible = false;
Refresh();
}
protected override void OnMouseMove(MouseEventArgs e)
@ -414,22 +484,30 @@ namespace UniversalEditor.Editors.Multimedia.Audio.Synthesized.PianoRoll.Control
if (draggingCommand != null)
{
foreach (SynthesizedAudioCommand cmd1 in mvarSelectedCommands)
if (!(drag_CurrentLocation.X - drag_OriginalLocation.X == 0 && drag_CurrentLocation.Y - drag_OriginalLocation.Y == 0))
{
SynthesizedAudioCommandNote note = (cmd1 as SynthesizedAudioCommandNote);
if (note != null)
(Parent as Editor).BeginEdit();
foreach (SynthesizedAudioCommand cmd1 in mvarSelectedCommands)
{
double x = drag_CurrentLocation.X - drag_OriginalLocation.X;
double y = drag_CurrentLocation.Y - drag_OriginalLocation.Y;
SynthesizedAudioCommandNote note = (cmd1 as SynthesizedAudioCommandNote);
if (note != null)
{
double x = drag_CurrentLocation.X - drag_OriginalLocation.X;
double y = drag_CurrentLocation.Y - drag_OriginalLocation.Y;
Rectangle origNoteRect = GetNoteRect(note);
Vector2D v = Quantize(origNoteRect.Location);
v.X += x;
v.Y += y;
Rectangle origNoteRect = GetNoteRect(note);
Vector2D v = Quantize(origNoteRect.Location);
v.X += x;
v.Y += y;
ApplyNoteRect(ref note, v);
ApplyNoteRect(ref note, v);
}
}
(Parent as Editor).EndEdit();
}
/*
SynthesizedAudioCommandNote note = (draggingCommand as SynthesizedAudioCommandNote);
if (note != null)
@ -444,6 +522,8 @@ namespace UniversalEditor.Editors.Multimedia.Audio.Synthesized.PianoRoll.Control
{
if (drag_CurrentLocation.X - drag_OriginalLocation.X > 0)
{
(Parent as Editor).BeginEdit();
SynthesizedAudioCommandNote note = new SynthesizedAudioCommandNote();
note.Position = (int)drag_OriginalLocation.X;
@ -456,6 +536,8 @@ namespace UniversalEditor.Editors.Multimedia.Audio.Synthesized.PianoRoll.Control
mvarSelectedCommands.Clear();
mvarSelectedCommands.Add(note);
(Parent as Editor).EndEdit();
}
}
m_selecting = false;
@ -480,9 +562,9 @@ namespace UniversalEditor.Editors.Multimedia.Audio.Synthesized.PianoRoll.Control
if (cmd is SynthesizedAudioCommandNote)
{
SynthesizedAudioCommandNote note = (cmd as SynthesizedAudioCommandNote);
Rectangle rect = GetNoteRect(note);
LyricEditNote(note);
ShowNotePropertiesDialog(note);
// ShowNotePropertiesDialog(note);
/*
txtLyric.Location = rect.Location;
txtLyric.Size = rect.Size;
@ -497,6 +579,19 @@ namespace UniversalEditor.Editors.Multimedia.Audio.Synthesized.PianoRoll.Control
}
}
private void LyricEditNote(SynthesizedAudioCommandNote note)
{
_EditingNote = note;
Rectangle rect = GetNoteRect(note);
txt.Text = note.Lyric;
txt.Visible = true;
Layout.SetControlConstraints(txt, new AbsoluteLayout.Constraints((int)rect.X, (int)rect.Y, (int)rect.Width, (int)rect.Height));
txt.Focus();
Invalidate(rect);
}
public void ShowNotePropertiesDialog(SynthesizedAudioCommandNote note = null)
{
if (note == null && mvarSelectedCommands.Count > 0)
@ -508,9 +603,20 @@ namespace UniversalEditor.Editors.Multimedia.Audio.Synthesized.PianoRoll.Control
// FIXME: ParentWindow is null, probably because this isn't a "normal" parented control but rather it's inside a DockingWindow...
NotePropertiesDialog dlg = new NotePropertiesDialog();
dlg.Lyric = note.Lyric;
dlg.Phoneme = note.Phoneme;
dlg.NoteOn = (double)note.Position;
dlg.NoteOff = note.Position + note.Length;
if (dlg.ShowDialog(ParentWindow) == DialogResult.OK)
{
(Parent as Editor).BeginEdit();
note.Lyric = dlg.Lyric;
note.Phoneme = dlg.Phoneme;
note.Position = (int)dlg.NoteOn;
note.Length = dlg.NoteOff - dlg.NoteOn;
(Parent as Editor).EndEdit();
}
}
@ -664,8 +770,12 @@ namespace UniversalEditor.Editors.Multimedia.Audio.Synthesized.PianoRoll.Control
}
e.Graphics.DrawRectangle(new Pen(Colors.Green.Alpha(0.5)), rect);
Rectangle textRect = new Rectangle(rect.X + 2, rect.Y + 1, rect.Width - 4, rect.Height - 2);
e.Graphics.DrawText(note.Lyric, Font, textRect, new SolidBrush(Colors.Black));
Rectangle textRect = new Rectangle(rect.X + 2, rect.Y + 10, rect.Width - 4, rect.Height - 2);
if (!(txt.Visible && _EditingNote == cmd))
{
e.Graphics.DrawText(String.Format("{0} [ {1} ]", note.Lyric, note.Phoneme), Font, textRect, new SolidBrush(mvarSelectedCommands.Contains(cmd) ? SystemColors.HighlightForeground : SystemColors.WindowForeground));
}
}
}
}

View File

@ -102,230 +102,30 @@ namespace UniversalEditor.DataFormats.Multimedia.Audio.Synthesized.Vocaloid
if (tag2 != null)
{
text = tag2.FullName;
switch (tag2.FullName)
{
case "musicalPart":
{
for (int j = 0; j < tag2.Elements.Count; j++)
{
MarkupTagElement tag3 = tag2.Elements[j] as MarkupTagElement;
if (tag3 == null) continue;
SynthesizedAudioCommand cmd = SynthesizedAudioCommandFromTag(tag3);
if (cmd != null)
{
track.Commands.Add(cmd);
}
}
break;
}
}
if (text != null)
{
if (!(text == "stylePlugin"))
{
if (text == "note")
{
SynthesizedAudioCommandNote note = new SynthesizedAudioCommandNote();
MarkupTagElement tagPosTick = tag2.Elements["posTick"] as MarkupTagElement;
if (tagPosTick != null)
{
int posTick = 0;
if (int.TryParse(tagPosTick.Value, out posTick))
{
note.Position = posTick;
}
}
MarkupTagElement tagDurTick = tag2.Elements["durTick"] as MarkupTagElement;
if (tagDurTick != null)
{
int durTick = 0;
if (int.TryParse(tagDurTick.Value, out durTick))
{
note.Length = durTick;
}
}
MarkupTagElement tagNoteNum = tag2.Elements["noteNum"] as MarkupTagElement;
if (tagNoteNum != null)
{
int noteNum = 0;
if (int.TryParse(tagNoteNum.Value, out noteNum))
{
note.Frequency = noteNum;
}
}
MarkupTagElement tagVelocity = tag2.Elements["velocity"] as MarkupTagElement;
if (tagVelocity != null)
{
int velocity = 0;
if (int.TryParse(tagVelocity.Value, out velocity))
{
note.Intensity = velocity;
}
}
MarkupTagElement tagLyric = tag2.Elements["lyric"] as MarkupTagElement;
if (tagLyric != null)
{
MarkupStringElement tagLyricCDATA = tagLyric.Elements[0] as MarkupStringElement;
if (tagLyricCDATA != null)
{
note.Lyric = tagLyricCDATA.Value;
}
}
MarkupTagElement tagPhoneme = tag2.Elements["phnms"] as MarkupTagElement;
if (tagPhoneme != null)
{
MarkupStringElement tagPhonemeCDATA = tagPhoneme.Elements[0] as MarkupStringElement;
if (tagPhonemeCDATA != null)
{
note.Phoneme = tagPhonemeCDATA.Value;
}
}
MarkupTagElement tagNoteStyle = tag2.Elements["noteStyle"] as MarkupTagElement;
if (tagNoteStyle != null)
{
foreach (MarkupElement elAttr in tagNoteStyle.Elements)
{
MarkupTagElement tagAttr = elAttr as MarkupTagElement;
if (tagAttr != null)
{
if (tagAttr.Attributes["id"] != null)
{
if (tagAttr.Name == "attr")
{
text = tagAttr.Attributes["id"].Value;
switch (text)
{
case "accent":
{
string value = tagAttr.Value;
int realValue = 50;
int.TryParse(value, out realValue);
note.Accent = realValue;
break;
}
case "bendDep":
{
string value = tagAttr.Value;
int realValue = 8;
int.TryParse(value, out realValue);
note.PitchBendDepth = realValue;
break;
}
case "bendLen":
{
string value = tagAttr.Value;
int realValue = 0;
int.TryParse(value, out realValue);
note.PitchBendLength = realValue;
break;
}
case "decay":
{
string value = tagAttr.Value;
int realValue = 50;
int.TryParse(value, out realValue);
note.Decay = realValue;
break;
}
case "fallPort":
{
string value = tagAttr.Value;
bool realValue2 = false;
bool.TryParse(value, out realValue2);
note.PortamentoFalling = realValue2;
break;
}
case "opening":
{
string value = tagAttr.Value;
int realValue = 127;
int.TryParse(value, out realValue);
note.Opening = realValue;
break;
}
case "risePort":
{
string value = tagAttr.Value;
bool realValue2 = false;
bool.TryParse(value, out realValue2);
note.PortamentoRising = realValue2;
break;
}
case "vibLen":
{
string value = tagAttr.Value;
int realValue = 66;
int.TryParse(value, out realValue);
note.VibratoLength = realValue;
break;
}
case "vibType":
{
string value = tagAttr.Value;
SynthesizedAudioVibratoType realValue3 = SynthesizedAudioVibratoType.None;
try
{
realValue3 = (SynthesizedAudioVibratoType)Enum.Parse(typeof(SynthesizedAudioVibratoType), value);
}
catch
{
}
note.VibratoType = realValue3;
break;
}
}
}
else
{
if (tagAttr.FullName == "seqAttr")
{
if (tagAttr.Attributes["id"] != null)
{
text = tagAttr.Attributes["id"].Value;
if (text != null)
{
if (!(text == "vibDep"))
{
if (text == "vibRate")
{
MarkupTagElement tagPosNrm = tagAttr.FindElement(new string[]
{
"elem",
"posNrm"
}) as MarkupTagElement;
MarkupTagElement tagElv = tagAttr.FindElement(new string[]
{
"elem",
"elv"
}) as MarkupTagElement;
if (tagPosNrm != null)
{
int posNrm = 0;
int.TryParse(tagPosNrm.Value, out posNrm);
}
if (tagElv != null)
{
int elv = 0;
int.TryParse(tagElv.Value, out elv);
}
}
}
else
{
MarkupTagElement tagPosNrm = tagAttr.FindElement(new string[]
{
"elem",
"posNrm"
}) as MarkupTagElement;
MarkupTagElement tagElv = tagAttr.FindElement(new string[]
{
"elem",
"elv"
}) as MarkupTagElement;
if (tagPosNrm != null)
{
int posNrm = 0;
int.TryParse(tagPosNrm.Value, out posNrm);
}
if (tagElv != null)
{
int elv = 0;
int.TryParse(tagElv.Value, out elv);
}
}
}
}
}
}
}
}
}
}
track.Commands.Add(note);
}
}
else
{
@ -398,6 +198,232 @@ namespace UniversalEditor.DataFormats.Multimedia.Audio.Synthesized.Vocaloid
}
}
}
private SynthesizedAudioCommand SynthesizedAudioCommandFromTag(MarkupTagElement tag3)
{
switch (tag3.FullName)
{
case "note":
{
SynthesizedAudioCommandNote note = new SynthesizedAudioCommandNote();
MarkupTagElement tagPosTick = tag3.Elements["posTick"] as MarkupTagElement;
if (tagPosTick != null)
{
int posTick = 0;
if (int.TryParse(tagPosTick.Value, out posTick))
{
note.Position = posTick;
}
}
MarkupTagElement tagDurTick = tag3.Elements["durTick"] as MarkupTagElement;
if (tagDurTick != null)
{
int durTick = 0;
if (int.TryParse(tagDurTick.Value, out durTick))
{
note.Length = durTick;
}
}
MarkupTagElement tagNoteNum = tag3.Elements["noteNum"] as MarkupTagElement;
if (tagNoteNum != null)
{
int noteNum = 0;
if (int.TryParse(tagNoteNum.Value, out noteNum))
{
note.Frequency = noteNum;
}
}
MarkupTagElement tagVelocity = tag3.Elements["velocity"] as MarkupTagElement;
if (tagVelocity != null)
{
int velocity = 0;
if (int.TryParse(tagVelocity.Value, out velocity))
{
note.Intensity = velocity;
}
}
MarkupTagElement tagLyric = tag3.Elements["lyric"] as MarkupTagElement;
if (tagLyric != null)
{
MarkupStringElement tagLyricCDATA = tagLyric.Elements[0] as MarkupStringElement;
if (tagLyricCDATA != null)
{
note.Lyric = tagLyricCDATA.Value;
}
}
MarkupTagElement tagPhoneme = tag3.Elements["phnms"] as MarkupTagElement;
if (tagPhoneme != null)
{
MarkupStringElement tagPhonemeCDATA = tagPhoneme.Elements[0] as MarkupStringElement;
if (tagPhonemeCDATA != null)
{
note.Phoneme = tagPhonemeCDATA.Value;
}
}
MarkupTagElement tagNoteStyle = tag3.Elements["noteStyle"] as MarkupTagElement;
if (tagNoteStyle != null)
{
foreach (MarkupElement elAttr in tagNoteStyle.Elements)
{
MarkupTagElement tagAttr = elAttr as MarkupTagElement;
if (tagAttr != null)
{
if (tagAttr.Attributes["id"] != null)
{
if (tagAttr.Name == "attr")
{
switch (tagAttr.Attributes["id"].Value)
{
case "accent":
{
string value = tagAttr.Value;
int realValue = 50;
int.TryParse(value, out realValue);
note.Accent = realValue;
break;
}
case "bendDep":
{
string value = tagAttr.Value;
int realValue = 8;
int.TryParse(value, out realValue);
note.PitchBendDepth = realValue;
break;
}
case "bendLen":
{
string value = tagAttr.Value;
int realValue = 0;
int.TryParse(value, out realValue);
note.PitchBendLength = realValue;
break;
}
case "decay":
{
string value = tagAttr.Value;
int realValue = 50;
int.TryParse(value, out realValue);
note.Decay = realValue;
break;
}
case "fallPort":
{
string value = tagAttr.Value;
bool realValue2 = false;
bool.TryParse(value, out realValue2);
note.PortamentoFalling = realValue2;
break;
}
case "opening":
{
string value = tagAttr.Value;
int realValue = 127;
int.TryParse(value, out realValue);
note.Opening = realValue;
break;
}
case "risePort":
{
string value = tagAttr.Value;
bool realValue2 = false;
bool.TryParse(value, out realValue2);
note.PortamentoRising = realValue2;
break;
}
case "vibLen":
{
string value = tagAttr.Value;
int realValue = 66;
int.TryParse(value, out realValue);
note.VibratoLength = realValue;
break;
}
case "vibType":
{
string value = tagAttr.Value;
SynthesizedAudioVibratoType realValue3 = SynthesizedAudioVibratoType.None;
try
{
realValue3 = (SynthesizedAudioVibratoType)Enum.Parse(typeof(SynthesizedAudioVibratoType), value);
}
catch
{
}
note.VibratoType = realValue3;
break;
}
}
}
else
{
if (tagAttr.FullName == "seqAttr")
{
if (tagAttr.Attributes["id"] != null)
{
switch (tagAttr.Attributes["id"].Value)
{
case "vibRate":
{
MarkupTagElement tagPosNrm = tagAttr.FindElement(new string[]
{
"elem",
"posNrm"
}) as MarkupTagElement;
MarkupTagElement tagElv = tagAttr.FindElement(new string[]
{
"elem",
"elv"
}) as MarkupTagElement;
if (tagPosNrm != null)
{
int posNrm = 0;
int.TryParse(tagPosNrm.Value, out posNrm);
}
if (tagElv != null)
{
int elv = 0;
int.TryParse(tagElv.Value, out elv);
}
break;
}
case "vibDep":
{
MarkupTagElement tagPosNrm = tagAttr.FindElement(new string[]
{
"elem",
"posNrm"
}) as MarkupTagElement;
MarkupTagElement tagElv = tagAttr.FindElement(new string[]
{
"elem",
"elv"
}) as MarkupTagElement;
if (tagPosNrm != null)
{
int posNrm = 0;
int.TryParse(tagPosNrm.Value, out posNrm);
}
if (tagElv != null)
{
int elv = 0;
int.TryParse(tagElv.Value, out elv);
}
break;
}
}
}
}
}
}
}
}
}
return note;
}
}
return null;
}
protected override void BeforeSaveInternal(Stack<ObjectModel> objectModels)
{
SynthesizedAudioObjectModel au = objectModels.Pop() as SynthesizedAudioObjectModel;
@ -407,6 +433,7 @@ namespace UniversalEditor.DataFormats.Multimedia.Audio.Synthesized.Vocaloid
xml.Value = "version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"";
mom.Elements.Add(xml);
MarkupTagElement tagVSQ3 = new MarkupTagElement();
tagVSQ3.Name = "vsq3";
tagVSQ3.Attributes.Add("xmlns", "http://www.yamaha.co.jp/vocaloid/schema/vsq3/");
tagVSQ3.Attributes.Add("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
tagVSQ3.Attributes.Add("xsi:schemaLocation", "http://www.yamaha.co.jp/vocaloid/schema/vsq3/vsq3.xsd");
@ -725,20 +752,26 @@ namespace UniversalEditor.DataFormats.Multimedia.Audio.Synthesized.Vocaloid
MarkupElement arg_EB7_0 = tagVelocity;
arg_EB7_0.Value = note.Frequency.ToString();
tagNote.Elements.Add(tagVelocity);
MarkupTagElement tagLyric = new MarkupTagElement();
tagLyric.FullName = "lyric";
MarkupStringElement tagLyricCDATA = new MarkupStringElement();
tagLyricCDATA.Name = "CDATA";
tagLyricCDATA.Value = note.Lyric.ToString();
tagLyric.Elements.Add(tagLyricCDATA);
tagNote.Elements.Add(tagLyric);
MarkupTagElement tagPhoneme = new MarkupTagElement();
tagPhoneme.FullName = "phnms";
MarkupStringElement tagPhonemeCDATA = new MarkupStringElement();
tagPhonemeCDATA.Name = "CDATA";
tagPhonemeCDATA.Value = note.Phoneme.ToString();
tagPhoneme.Elements.Add(tagPhonemeCDATA);
tagNote.Elements.Add(tagPhoneme);
if (note.Lyric != null)
{
MarkupTagElement tagLyric = new MarkupTagElement();
tagLyric.FullName = "lyric";
MarkupStringElement tagLyricCDATA = new MarkupStringElement();
tagLyricCDATA.Name = "CDATA";
tagLyricCDATA.Value = note.Lyric.ToString();
tagLyric.Elements.Add(tagLyricCDATA);
tagNote.Elements.Add(tagLyric);
}
if (note.Phoneme != null)
{
MarkupTagElement tagPhoneme = new MarkupTagElement();
tagPhoneme.FullName = "phnms";
MarkupStringElement tagPhonemeCDATA = new MarkupStringElement();
tagPhonemeCDATA.Name = "CDATA";
tagPhonemeCDATA.Value = note.Phoneme.ToString();
tagPhoneme.Elements.Add(tagPhonemeCDATA);
tagNote.Elements.Add(tagPhoneme);
}
MarkupTagElement tagNoteStyle = new MarkupTagElement();
tagNoteStyle.FullName = "noteStyle";
MarkupTagElement tagNoteStyleAccent = new MarkupTagElement();

View File

@ -76,6 +76,32 @@ namespace UniversalEditor.ObjectModels.Multimedia.Audio.Synthesized
OnItemsChanged(EventArgs.Empty);
}
public T PreviousOfType<T>(T item) where T : SynthesizedAudioCommand
{
int index = IndexOf(item);
if (index < 0) index = Count - 1;
if (index > Count - 1) index = Count - 1;
for (int i = index - 1; i >= 0; i--)
{
if (this[i] is T)
return (T)this[i];
}
return (T)this[Count - 1];
}
public T NextOfType<T>(T item) where T : SynthesizedAudioCommand
{
int index = IndexOf(item);
if (index < 0) index = 0;
if (index > Count - 1) index = 0;
for (int i = index + 1; i < Count; i++)
{
if (this[i] is T)
return (T)this[i];
}
return (T)this[0];
}
}
public virtual object Clone()