various feature additions, improvements, and bug fixes to synthesized audio plugins and editors
This commit is contained in:
parent
51414cc4a7
commit
f884365c95
@ -129,24 +129,26 @@
|
||||
</Items>
|
||||
</Command>
|
||||
|
||||
<!-- Length : controls the quantize of length when drawing a new note -->
|
||||
<Command ID="PianoRollEditor_ContextMenu_Length_4" Title="1/4 [480]" />
|
||||
<Command ID="PianoRollEditor_ContextMenu_Length_8" Title="1/8 [240]" />
|
||||
<Command ID="PianoRollEditor_ContextMenu_Length_16" Title="1/16 [120]" />
|
||||
<Command ID="PianoRollEditor_ContextMenu_Length_32" Title="1/32 [60]" />
|
||||
<Command ID="PianoRollEditor_ContextMenu_Length_64" Title="1/64 [30]" />
|
||||
<Command ID="PianoRollEditor_ContextMenu_Length_Off" Title="Off" />
|
||||
<Command ID="PianoRollEditor_ContextMenu_Length_Triplet" Title="Triplet" />
|
||||
<Command ID="PianoRollEditor_ContextMenu_Length" Title="_Length">
|
||||
<!-- NoteLength : controls the quantize of length when drawing a new note -->
|
||||
<Command ID="PianoRollEditor_ContextMenu_NoteLength_4" Title="1/4 [480]" />
|
||||
<Command ID="PianoRollEditor_ContextMenu_NoteLength_8" Title="1/8 [240]" />
|
||||
<Command ID="PianoRollEditor_ContextMenu_NoteLength_16" Title="1/16 [120]" />
|
||||
<Command ID="PianoRollEditor_ContextMenu_NoteLength_32" Title="1/32 [60]" />
|
||||
<Command ID="PianoRollEditor_ContextMenu_NoteLength_64" Title="1/64 [30]" />
|
||||
<Command ID="PianoRollEditor_ContextMenu_NoteLength_Off" Title="Off" />
|
||||
<Command ID="PianoRollEditor_ContextMenu_NoteLength_Default" Title="Default" />
|
||||
<Command ID="PianoRollEditor_ContextMenu_NoteLength_Triplet" Title="Triplet" />
|
||||
<Command ID="PianoRollEditor_ContextMenu_NoteLength" Title="Note _Length">
|
||||
<Items>
|
||||
<CommandReference CommandID="PianoRollEditor_ContextMenu_Length_4" />
|
||||
<CommandReference CommandID="PianoRollEditor_ContextMenu_Length_8" />
|
||||
<CommandReference CommandID="PianoRollEditor_ContextMenu_Length_16" />
|
||||
<CommandReference CommandID="PianoRollEditor_ContextMenu_Length_32" /> <!-- default -->
|
||||
<CommandReference CommandID="PianoRollEditor_ContextMenu_Length_64" />
|
||||
<CommandReference CommandID="PianoRollEditor_ContextMenu_Length_Off" />
|
||||
<CommandReference CommandID="PianoRollEditor_ContextMenu_NoteLength_4" />
|
||||
<CommandReference CommandID="PianoRollEditor_ContextMenu_NoteLength_8" />
|
||||
<CommandReference CommandID="PianoRollEditor_ContextMenu_NoteLength_16" />
|
||||
<CommandReference CommandID="PianoRollEditor_ContextMenu_NoteLength_32" /> <!-- default -->
|
||||
<CommandReference CommandID="PianoRollEditor_ContextMenu_NoteLength_64" />
|
||||
<CommandReference CommandID="PianoRollEditor_ContextMenu_NoteLength_Off" />
|
||||
<CommandReference CommandID="PianoRollEditor_ContextMenu_NoteLength_Default" />
|
||||
<Separator />
|
||||
<CommandReference CommandID="PianoRollEditor_ContextMenu_Length_Triplet" />
|
||||
<CommandReference CommandID="PianoRollEditor_ContextMenu_NoteLength_Triplet" />
|
||||
</Items>
|
||||
</Command>
|
||||
|
||||
@ -215,9 +217,9 @@
|
||||
<CommandReference CommandID="PianoRollEditor_ContextMenu_Scale" />
|
||||
<CommandReference CommandID="PianoRollEditor_ContextMenu_Chord" />
|
||||
<Separator />
|
||||
<CommandReference CommandID="PianoRollEditor_ContextMenu_NoteFixedLength" />
|
||||
<CommandReference CommandID="PianoRollEditor_ContextMenu_Quantize" />
|
||||
<CommandReference CommandID="PianoRollEditor_ContextMenu_Length" />
|
||||
<CommandReference CommandID="PianoRollEditor_ContextMenu_NoteLength" />
|
||||
<CommandReference CommandID="PianoRollEditor_ContextMenu_NoteFixedLength" />
|
||||
<CommandReference CommandID="PianoRollEditor_ContextMenu_ShowGridLines" />
|
||||
<Separator />
|
||||
<CommandReference CommandID="EditUndo" />
|
||||
|
||||
@ -3,24 +3,29 @@
|
||||
<Associations>
|
||||
<Association>
|
||||
<Filters>
|
||||
<Filter Title="VOCALOID2 voice sequence (MIDI)">
|
||||
<Filter Title="VOCALOID5 project (JSON/ZIP)">
|
||||
<FileNameFilters>
|
||||
<FileNameFilter>*.vsq</FileNameFilter>
|
||||
<FileNameFilter>*.vpr</FileNameFilter>
|
||||
</FileNameFilters>
|
||||
<MagicByteSequences>
|
||||
<MagicByteSequence>
|
||||
<MagicByte Type="String">PK</MagicByte>
|
||||
</MagicByteSequence>
|
||||
</MagicByteSequences>
|
||||
</Filter>
|
||||
</Filters>
|
||||
<ObjectModels>
|
||||
<ObjectModel TypeName="UniversalEditor.ObjectModels.Multimedia.Audio.Synthesized.SynthesizedAudioObjectModel" />
|
||||
</ObjectModels>
|
||||
<DataFormats>
|
||||
<DataFormat TypeName="UniversalEditor.Plugins.Vocaloid.DataFormats.Multimedia.Audio.Synthesized.Vocaloid.VSQDataFormat" />
|
||||
<DataFormat TypeName="UniversalEditor.Plugins.Vocaloid.DataFormats.Multimedia.Audio.Synthesized.Vocaloid.VPR.VPRProjectZIPDataFormat" />
|
||||
</DataFormats>
|
||||
</Association>
|
||||
<Association>
|
||||
<Filters>
|
||||
<Filter Title="VOCALOID3 voice sequence (XML)">
|
||||
<Filter Title="VOCALOID5 voice sequence (JSON)">
|
||||
<FileNameFilters>
|
||||
<FileNameFilter>*.vsqx</FileNameFilter>
|
||||
<FileNameFilter>sequence.json</FileNameFilter>
|
||||
</FileNameFilters>
|
||||
</Filter>
|
||||
</Filters>
|
||||
@ -28,7 +33,7 @@
|
||||
<ObjectModel TypeName="UniversalEditor.ObjectModels.Multimedia.Audio.Synthesized.SynthesizedAudioObjectModel" />
|
||||
</ObjectModels>
|
||||
<DataFormats>
|
||||
<DataFormat TypeName="UniversalEditor.Plugins.Vocaloid.DataFormats.Multimedia.Audio.Synthesized.Vocaloid.VSQXDataFormat" />
|
||||
<DataFormat TypeName="UniversalEditor.Plugins.Vocaloid.DataFormats.Multimedia.Audio.Synthesized.Vocaloid.VPR.VPRSequenceJSONDataFormat" />
|
||||
</DataFormats>
|
||||
</Association>
|
||||
</Associations>
|
||||
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<UniversalEditor Version="4.0">
|
||||
<Associations>
|
||||
<Association>
|
||||
<Filters>
|
||||
<Filter Title="VOCALOID2 voice sequence (MIDI)">
|
||||
<FileNameFilters>
|
||||
<FileNameFilter>*.vsq</FileNameFilter>
|
||||
</FileNameFilters>
|
||||
</Filter>
|
||||
</Filters>
|
||||
<ObjectModels>
|
||||
<ObjectModel TypeName="UniversalEditor.ObjectModels.Multimedia.Audio.Synthesized.SynthesizedAudioObjectModel" />
|
||||
</ObjectModels>
|
||||
<DataFormats>
|
||||
<DataFormat TypeName="UniversalEditor.Plugins.Vocaloid.DataFormats.Multimedia.Audio.Synthesized.Vocaloid.VSQDataFormat" />
|
||||
</DataFormats>
|
||||
</Association>
|
||||
</Associations>
|
||||
</UniversalEditor>
|
||||
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<UniversalEditor Version="4.0">
|
||||
<Associations>
|
||||
<Association>
|
||||
<Filters>
|
||||
<Filter Title="VOCALOID3 voice sequence (XML)">
|
||||
<FileNameFilters>
|
||||
<FileNameFilter>*.vsqx</FileNameFilter>
|
||||
</FileNameFilters>
|
||||
</Filter>
|
||||
</Filters>
|
||||
<ObjectModels>
|
||||
<ObjectModel TypeName="UniversalEditor.ObjectModels.Multimedia.Audio.Synthesized.SynthesizedAudioObjectModel" />
|
||||
</ObjectModels>
|
||||
<DataFormats>
|
||||
<DataFormat TypeName="UniversalEditor.Plugins.Vocaloid.DataFormats.Multimedia.Audio.Synthesized.Vocaloid.VSQXDataFormat" />
|
||||
</DataFormats>
|
||||
</Association>
|
||||
</Associations>
|
||||
</UniversalEditor>
|
||||
@ -728,8 +728,10 @@
|
||||
<Content Include="Editors\Database\DatabaseEditor.glade" />
|
||||
<Content Include="Editors\Multimedia\Synthesized\Dialogs\NotePropertiesDialog.glade" />
|
||||
<Content Include="Extensions\AudioWorkstation\Extensions\Vocaloid\Associations\Voicebank\Vocaloid.uexml" />
|
||||
<Content Include="Extensions\AudioWorkstation\Extensions\Vocaloid\Associations\SynthesizedAudio\Vocaloid.uexml" />
|
||||
<Content Include="Extensions\AudioWorkstation\Extensions\Vocaloid\Associations\SynthesizedAudio\VSQ.uexml" />
|
||||
<Content Include="Extensions\AudioWorkstation\Extensions\Vocaloid\Associations\VoicebankIndex\Vocaloid.uexml" />
|
||||
<Content Include="Extensions\AudioWorkstation\Extensions\Vocaloid\Associations\SynthesizedAudio\VSQX.uexml" />
|
||||
<Content Include="Extensions\AudioWorkstation\Extensions\Vocaloid\Associations\SynthesizedAudio\VPR.uexml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Configuration\Application.upl" />
|
||||
|
||||
@ -26,7 +26,7 @@ using UniversalEditor.UserInterface;
|
||||
|
||||
using UniversalEditor.ObjectModels.Multimedia.Audio.Synthesized;
|
||||
|
||||
using UniversalEditor.Editors.Multimedia.Audio.Synthesized.PianoRoll.Controls;
|
||||
using UniversalEditor.Editors.Multimedia.Audio.Synthesized.PianoRoll.Views;
|
||||
|
||||
namespace UniversalEditor.Editors.Multimedia.Audio.Synthesized.PianoRoll
|
||||
{
|
||||
|
||||
@ -32,7 +32,16 @@ namespace UniversalEditor.Editors.Multimedia.Audio.Synthesized.PianoRoll
|
||||
{
|
||||
public override void UpdateSelections()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
Selections.Clear();
|
||||
if (PianoRoll.SelectedCommands.Count > 0)
|
||||
{
|
||||
PianoRollEditorSelection sel = new PianoRollEditorSelection(this, PianoRoll);
|
||||
for (int i = 0; i < PianoRoll.SelectedCommands.Count; i++)
|
||||
{
|
||||
sel.Commands.Add(PianoRoll.SelectedCommands[i]);
|
||||
}
|
||||
Selections.Add(sel);
|
||||
}
|
||||
}
|
||||
|
||||
protected override EditorSelection CreateSelectionInternal(object content)
|
||||
@ -40,6 +49,11 @@ namespace UniversalEditor.Editors.Multimedia.Audio.Synthesized.PianoRoll
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected override void OnDocumentEdited(EventArgs e)
|
||||
{
|
||||
base.OnDocumentEdited(e);
|
||||
PianoRoll.Refresh();
|
||||
}
|
||||
protected override void OnObjectModelChanged(EventArgs e)
|
||||
{
|
||||
base.OnObjectModelChanged(e);
|
||||
|
||||
@ -0,0 +1,29 @@
|
||||
//
|
||||
// QuantizationMode.cs
|
||||
//
|
||||
// Author:
|
||||
// Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// Copyright (c) 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
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program 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. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// 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;
|
||||
namespace UniversalEditor.Editors.Multimedia.Audio.Synthesized.PianoRoll
|
||||
{
|
||||
public enum QuantizationMode
|
||||
{
|
||||
Length,
|
||||
Position
|
||||
}
|
||||
}
|
||||
@ -21,6 +21,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using MBS.Framework.Drawing;
|
||||
using MBS.Framework.UserInterface;
|
||||
@ -34,7 +35,7 @@ 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
|
||||
namespace UniversalEditor.Editors.Multimedia.Audio.Synthesized.PianoRoll.Views
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a UWT-based <see cref="View" /> for manipulating <see cref="SynthesizedAudioCommand" />s in a piano roll style.
|
||||
@ -60,6 +61,23 @@ namespace UniversalEditor.Editors.Multimedia.Audio.Synthesized.PianoRoll.Control
|
||||
Application.AttachCommandEventHandler("PianoRollEditor_ContextMenu_Draw", ContextMenuPencil_Click);
|
||||
Application.AttachCommandEventHandler("PianoRollEditor_ContextMenu_Erase", ContextMenuErase_Click);
|
||||
|
||||
Application.AttachCommandEventHandler("PianoRollEditor_ContextMenu_Quantize_4", ContextMenu_Quantize_Click);
|
||||
Application.AttachCommandEventHandler("PianoRollEditor_ContextMenu_Quantize_8", ContextMenu_Quantize_Click);
|
||||
Application.AttachCommandEventHandler("PianoRollEditor_ContextMenu_Quantize_16", ContextMenu_Quantize_Click);
|
||||
Application.AttachCommandEventHandler("PianoRollEditor_ContextMenu_Quantize_32", ContextMenu_Quantize_Click);
|
||||
Application.AttachCommandEventHandler("PianoRollEditor_ContextMenu_Quantize_64", ContextMenu_Quantize_Click);
|
||||
Application.AttachCommandEventHandler("PianoRollEditor_ContextMenu_Quantize_Off", ContextMenu_Quantize_Click);
|
||||
Application.AttachCommandEventHandler("PianoRollEditor_ContextMenu_Quantize_Triplet", ContextMenu_Quantize_Click);
|
||||
|
||||
Application.AttachCommandEventHandler("PianoRollEditor_ContextMenu_NoteLength_4", ContextMenu_NoteLength_Click);
|
||||
Application.AttachCommandEventHandler("PianoRollEditor_ContextMenu_NoteLength_8", ContextMenu_NoteLength_Click);
|
||||
Application.AttachCommandEventHandler("PianoRollEditor_ContextMenu_NoteLength_16", ContextMenu_NoteLength_Click);
|
||||
Application.AttachCommandEventHandler("PianoRollEditor_ContextMenu_NoteLength_32", ContextMenu_NoteLength_Click);
|
||||
Application.AttachCommandEventHandler("PianoRollEditor_ContextMenu_NoteLength_64", ContextMenu_NoteLength_Click);
|
||||
Application.AttachCommandEventHandler("PianoRollEditor_ContextMenu_NoteLength_Off", ContextMenu_NoteLength_Click);
|
||||
Application.AttachCommandEventHandler("PianoRollEditor_ContextMenu_NoteLength_Default", ContextMenu_NoteLength_Click);
|
||||
Application.AttachCommandEventHandler("PianoRollEditor_ContextMenu_NoteLength_Triplet", ContextMenu_NoteLength_Click);
|
||||
|
||||
Application.AttachCommandEventHandler("PianoRollEditor_ContextMenu_NoteFixedLength_1", ContextMenu_NoteFixedLength_Click);
|
||||
Application.AttachCommandEventHandler("PianoRollEditor_ContextMenu_NoteFixedLength_2", ContextMenu_NoteFixedLength_Click);
|
||||
Application.AttachCommandEventHandler("PianoRollEditor_ContextMenu_NoteFixedLength_4", ContextMenu_NoteFixedLength_Click);
|
||||
@ -152,17 +170,6 @@ namespace UniversalEditor.Editors.Multimedia.Audio.Synthesized.PianoRoll.Control
|
||||
/// <value>The length of a newly-created note.</value>
|
||||
public int FixedNoteLength { get; set; } = -1;
|
||||
|
||||
private int _PositionQuantization = -1;
|
||||
public int PositionQuantization
|
||||
{
|
||||
get { return _PositionQuantization; }
|
||||
set
|
||||
{
|
||||
_PositionQuantization = value;
|
||||
Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
private void ContextMenu_NoteFixedLength_Click(object sender, EventArgs e)
|
||||
{
|
||||
Command cmd = (sender as Command);
|
||||
@ -190,6 +197,65 @@ namespace UniversalEditor.Editors.Multimedia.Audio.Synthesized.PianoRoll.Control
|
||||
}
|
||||
}
|
||||
}
|
||||
private void ContextMenu_Quantize_Click(object sender, EventArgs e)
|
||||
{
|
||||
Command cmd = (sender as Command);
|
||||
string sValue = cmd.ID.Substring("PianoRollEditor_ContextMenu_Quantize_".Length);
|
||||
int iValue = 4; //-1;
|
||||
|
||||
switch (sValue)
|
||||
{
|
||||
case "Off":
|
||||
{
|
||||
break;
|
||||
}
|
||||
case "Triplet":
|
||||
{
|
||||
break;
|
||||
}
|
||||
case "Dot":
|
||||
{
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
iValue = Int32.Parse(sValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PositionQuantization = (int)((double)1920 / iValue);
|
||||
}
|
||||
private void ContextMenu_NoteLength_Click(object sender, EventArgs e)
|
||||
{
|
||||
Command cmd = (sender as Command);
|
||||
string sValue = cmd.ID.Substring("PianoRollEditor_ContextMenu_NoteLength_".Length);
|
||||
int iValue = 4; //-1;
|
||||
|
||||
switch (sValue)
|
||||
{
|
||||
case "Off":
|
||||
{
|
||||
break;
|
||||
}
|
||||
case "Triplet":
|
||||
{
|
||||
break;
|
||||
}
|
||||
case "Default":
|
||||
{
|
||||
iValue = -1;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
iValue = Int32.Parse(sValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
LengthQuantization = (int)((double)1920 / iValue);
|
||||
}
|
||||
|
||||
// TODO: make this more user-friendly
|
||||
private static Dictionary<string, int[]> Scales = new Dictionary<string, int[]>();
|
||||
@ -317,7 +383,6 @@ namespace UniversalEditor.Editors.Multimedia.Audio.Synthesized.PianoRoll.Control
|
||||
set { _SelectedTrack = value; Refresh(); }
|
||||
}
|
||||
|
||||
public int GridSize { get; set; } = 4;
|
||||
public Dimension2D NoteSize { get; set; } = new Dimension2D(12, 16);
|
||||
|
||||
private Pen pGrid = new Pen(Colors.LightGray);
|
||||
@ -327,20 +392,54 @@ namespace UniversalEditor.Editors.Multimedia.Audio.Synthesized.PianoRoll.Control
|
||||
private SolidBrush bSelectionFillDrawing = new SolidBrush(Color.FromRGBADouble(Colors.DarkGray.R, Colors.DarkGray.G, Colors.DarkGray.B, 0.5));
|
||||
|
||||
private bool mvarShowKeyboard = true;
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the virtual keyboard should be shown on this <see cref="PianoRollView" />.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if the virtual keyboard should be shown; otherwise, <c>false</c>.</value>
|
||||
public bool ShowKeyboard { get { return mvarShowKeyboard; } set { mvarShowKeyboard = value; Invalidate(); } }
|
||||
|
||||
private int mvarKeyboardWidth = 64;
|
||||
public int KeyboardWidth { get { return mvarKeyboardWidth; } set { mvarKeyboardWidth = value; Invalidate(); } }
|
||||
|
||||
private int mvarQuarterNoteWidth = 48;
|
||||
private int mvarNoteHeight = 22;
|
||||
private int _LengthQuantization = -1;
|
||||
/// <summary>
|
||||
/// Gets or sets the quantization for note length (i.e., the width of a quarter note on the grid). All quantization operations are relative to this value.
|
||||
/// </summary>
|
||||
/// <value>The quantization for note length (i.e., the width of a quarter note on the grid).</value>
|
||||
public int LengthQuantization { get { return _LengthQuantization; } set { _LengthQuantization = value; Invalidate(); } }
|
||||
/// <summary>
|
||||
/// Gets or sets the quantization for note positioning.
|
||||
/// </summary>
|
||||
/// <value>The quantization for note positioning.</value>
|
||||
public int PositionQuantization { get; set; } = 60;
|
||||
|
||||
private int GetLengthQuantization()
|
||||
{
|
||||
if (LengthQuantization == -1)
|
||||
return PositionQuantization;
|
||||
return LengthQuantization;
|
||||
}
|
||||
|
||||
private int _GridWidth = 120;
|
||||
public int GridWidth { get { return _GridWidth; }set { _GridWidth = value; Invalidate(); } }
|
||||
|
||||
private int _NoteHeight = 22;
|
||||
/// <summary>
|
||||
/// Gets or sets the height of a note on the grid.
|
||||
/// </summary>
|
||||
/// <value>The height of a note on the grid.</value>
|
||||
public int NoteHeight { get { return _NoteHeight; } set { _NoteHeight = value; Invalidate(); } }
|
||||
|
||||
private bool _HighlightOverlappingNotes = true;
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether overlapping notes on this <see cref="PianoRollView" /> grid are highlighted.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if overlapping notes should be highlighted; otherwise, <c>false</c>.</value>
|
||||
public bool HighlightOverlappingNotes { get { return _HighlightOverlappingNotes; } set { _HighlightOverlappingNotes = value; Invalidate(); } }
|
||||
|
||||
private double mvarZoomFactor = 1.0;
|
||||
public double ZoomFactor { get { return mvarZoomFactor; } set { mvarZoomFactor = value; Invalidate(); } }
|
||||
|
||||
private Dimension2D mvarQuantizationSize = new Dimension2D(16, 16);
|
||||
public Dimension2D QuantizationSize { get { return mvarQuantizationSize; } set { mvarQuantizationSize = value; Invalidate(); } }
|
||||
|
||||
private bool m_selecting = false;
|
||||
private double cx = 0, cy = 0;
|
||||
private double dx = 0, dy = 0;
|
||||
@ -356,6 +455,7 @@ namespace UniversalEditor.Editors.Multimedia.Audio.Synthesized.PianoRoll.Control
|
||||
protected override void OnMouseDown(MouseEventArgs e)
|
||||
{
|
||||
base.OnMouseDown(e);
|
||||
Focus();
|
||||
|
||||
if (SelectedTrack == null) return;
|
||||
|
||||
@ -411,10 +511,10 @@ namespace UniversalEditor.Editors.Multimedia.Audio.Synthesized.PianoRoll.Control
|
||||
dy = e.Y;
|
||||
m_selecting = true;
|
||||
|
||||
drag_OriginalLocation = Quantize(new Vector2D(cx, cy));
|
||||
drag_OriginalLocation = Quantize(new Vector2D(cx, cy), QuantizationMode.Position);
|
||||
if (cmd is SynthesizedAudioCommandNote)
|
||||
{
|
||||
note_OriginalLocation = Quantize(GetNoteRect(cmd as SynthesizedAudioCommandNote).Location);
|
||||
note_OriginalLocation = Quantize(GetNoteRect(cmd as SynthesizedAudioCommandNote).Location, QuantizationMode.Position);
|
||||
}
|
||||
drag_CurrentLocation = drag_OriginalLocation;
|
||||
}
|
||||
@ -447,7 +547,7 @@ namespace UniversalEditor.Editors.Multimedia.Audio.Synthesized.PianoRoll.Control
|
||||
|
||||
if (draggingCommand == null && (SelectionMode == PianoRollSelectionMode.Select || SelectionMode == PianoRollSelectionMode.Insert))
|
||||
{
|
||||
drag_CurrentLocation = Quantize(new Vector2D(dx, drag_OriginalLocation.Y));
|
||||
drag_CurrentLocation = Quantize(new Vector2D(dx, drag_OriginalLocation.Y), QuantizationMode.Length);
|
||||
if (SelectionMode == PianoRollSelectionMode.Select)
|
||||
{
|
||||
Rectangle rectSelection = new Rectangle(cx, cy, dx - cx, dy - cy);
|
||||
@ -462,7 +562,7 @@ namespace UniversalEditor.Editors.Multimedia.Audio.Synthesized.PianoRoll.Control
|
||||
}
|
||||
else
|
||||
{
|
||||
drag_CurrentLocation = Quantize(new Vector2D(dx, dy));
|
||||
drag_CurrentLocation = Quantize(new Vector2D(dx, dy), QuantizationMode.Length);
|
||||
}
|
||||
Refresh();
|
||||
}
|
||||
@ -497,11 +597,21 @@ namespace UniversalEditor.Editors.Multimedia.Audio.Synthesized.PianoRoll.Control
|
||||
double y = drag_CurrentLocation.Y - drag_OriginalLocation.Y;
|
||||
|
||||
Rectangle origNoteRect = GetNoteRect(note);
|
||||
Vector2D v = Quantize(origNoteRect.Location);
|
||||
Vector2D v = Quantize(origNoteRect.Location, QuantizationMode.Position);
|
||||
v.X += x;
|
||||
v.Y += y;
|
||||
|
||||
ApplyNoteRect(ref note, v);
|
||||
if ((e.ModifierKeys & KeyboardModifierKey.Control) == KeyboardModifierKey.Control)
|
||||
{
|
||||
// copy the note to the current location
|
||||
SynthesizedAudioCommandNote note2 = note.Clone() as SynthesizedAudioCommandNote;
|
||||
ApplyNoteRect(ref note2, v);
|
||||
SelectedTrack.Commands.Add(note2);
|
||||
}
|
||||
else
|
||||
{
|
||||
ApplyNoteRect(ref note, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -526,8 +636,8 @@ namespace UniversalEditor.Editors.Multimedia.Audio.Synthesized.PianoRoll.Control
|
||||
|
||||
SynthesizedAudioCommandNote note = new SynthesizedAudioCommandNote();
|
||||
|
||||
note.Position = (int)drag_OriginalLocation.X;
|
||||
note.Length = (drag_CurrentLocation.X - drag_OriginalLocation.X);
|
||||
note.Position = LocationToNotePosition((int)drag_OriginalLocation.X, QuantizationMode.Position) * 4;
|
||||
note.Length = LocationToNotePosition((int)(drag_CurrentLocation.X - drag_OriginalLocation.X), QuantizationMode.Length) * 4;
|
||||
note.Frequency = ValueToFrequency((int)drag_OriginalLocation.Y);
|
||||
|
||||
Editor.BeginEdit();
|
||||
@ -547,9 +657,18 @@ namespace UniversalEditor.Editors.Multimedia.Audio.Synthesized.PianoRoll.Control
|
||||
}
|
||||
}
|
||||
|
||||
private int LocationToNotePosition(int x, QuantizationMode mode)
|
||||
{
|
||||
return (int)Unquantize(new MBS.Framework.Drawing.Vector2D(x, 0), mode).X;
|
||||
}
|
||||
private int NotePositionToLocation(double x)
|
||||
{
|
||||
return (int)(x / 4);
|
||||
}
|
||||
|
||||
private void ApplyNoteRect(ref SynthesizedAudioCommandNote note, Vector2D quantized)
|
||||
{
|
||||
note.Position = (int)quantized.X;
|
||||
note.Position = LocationToNotePosition((int)quantized.X, QuantizationMode.Position) * 4;
|
||||
note.Frequency = ValueToFrequency((int)quantized.Y);
|
||||
}
|
||||
|
||||
@ -625,19 +744,31 @@ namespace UniversalEditor.Editors.Multimedia.Audio.Synthesized.PianoRoll.Control
|
||||
"A#", "A", "G#", "G", "F#", "F", "E", "D#", "D", "C#", "C", "B"
|
||||
};
|
||||
|
||||
private Vector2D Quantize(Vector2D pt)
|
||||
private Vector2D Quantize(Vector2D pt, QuantizationMode mode)
|
||||
{
|
||||
if (mvarShowKeyboard)
|
||||
pt.X -= mvarKeyboardWidth;
|
||||
|
||||
int qX = (int)((double)(pt.X / mvarQuarterNoteWidth));
|
||||
int qY = (int)((double)((pt.Y / mvarNoteHeight)));
|
||||
int quant;
|
||||
if (mode == QuantizationMode.Length)
|
||||
quant = GetLengthQuantization();
|
||||
else
|
||||
quant = PositionQuantization;
|
||||
|
||||
int qX = (int)((double)(pt.X / (quant * ZoomFactor)));
|
||||
int qY = (int)((double)((pt.Y / NoteHeight)));
|
||||
return new Vector2D(qX, qY);
|
||||
}
|
||||
private Vector2D Unquantize(Vector2D pt)
|
||||
private Vector2D Unquantize(Vector2D pt, QuantizationMode mode)
|
||||
{
|
||||
int uqX = (int)(pt.X * mvarQuarterNoteWidth);
|
||||
int uqY = (int)(pt.Y * mvarNoteHeight);
|
||||
int quant;
|
||||
if (mode == QuantizationMode.Length)
|
||||
quant = GetLengthQuantization();
|
||||
else
|
||||
quant = PositionQuantization;
|
||||
|
||||
int uqX = (int)(pt.X * (quant * ZoomFactor));
|
||||
int uqY = (int)(pt.Y * NoteHeight);
|
||||
return new Vector2D(uqX, uqY);
|
||||
}
|
||||
|
||||
@ -668,26 +799,46 @@ namespace UniversalEditor.Editors.Multimedia.Audio.Synthesized.PianoRoll.Control
|
||||
private Rectangle GetNoteRect(SynthesizedAudioCommandNote note)
|
||||
{
|
||||
Rectangle gridRect = GetGridRect();
|
||||
Vector2D pt1 = Unquantize(new Vector2D((int)(note.Position), FrequencyToValue(note.Frequency)));
|
||||
Vector2D pt2 = Unquantize(new Vector2D((int)note.Length, FrequencyToValue(note.Frequency)));
|
||||
return new Rectangle(gridRect.X + pt1.X + 1, gridRect.Y + pt1.Y + 1, pt2.X - 1, mvarNoteHeight - 1);
|
||||
|
||||
int x = (int)NotePositionToLocation(note.Position);
|
||||
int y = FrequencyToValue(note.Frequency);
|
||||
int width = (int)NotePositionToLocation((int)note.Length);
|
||||
int height = NoteHeight;
|
||||
|
||||
return new Rectangle(gridRect.X + x + 1, gridRect.Y + y + 1, width - 1, height - 1);
|
||||
}
|
||||
|
||||
private double ValueToFrequency(int value)
|
||||
{
|
||||
return value;
|
||||
return (81 - value);
|
||||
}
|
||||
private int FrequencyToValue(double frequency)
|
||||
{
|
||||
return (int)frequency;
|
||||
return (int)((81 - frequency) * NoteHeight);
|
||||
}
|
||||
|
||||
private bool _scrollBoundsChanged = true;
|
||||
private void RecalcScrollBounds()
|
||||
{
|
||||
for (int i = 0; i < SelectedTrack.Commands.Count; i++)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected override void OnPaint(PaintEventArgs e)
|
||||
{
|
||||
base.OnPaint(e);
|
||||
|
||||
int gridWidth = (int)(mvarQuarterNoteWidth * mvarZoomFactor);
|
||||
int gridHeight = (int)(mvarNoteHeight * mvarZoomFactor);
|
||||
int gridWidth = (int)(GridWidth * mvarZoomFactor);
|
||||
int gridHeight = (int)(NoteHeight * mvarZoomFactor);
|
||||
|
||||
if (_scrollBoundsChanged)
|
||||
{
|
||||
RecalcScrollBounds();
|
||||
_scrollBoundsChanged = false;
|
||||
}
|
||||
|
||||
Rectangle gridRect = GetGridRect();
|
||||
if (mvarShowKeyboard)
|
||||
@ -738,7 +889,7 @@ namespace UniversalEditor.Editors.Multimedia.Audio.Synthesized.PianoRoll.Control
|
||||
}
|
||||
for (int i = 0; i < Size.Width; i += (ShowGridLines ? (gridWidth / 2) : gridWidth))
|
||||
{
|
||||
if ((i % (mvarQuarterNoteWidth * 4)) == 0)
|
||||
if ((i % GetLengthQuantization()) == 0)
|
||||
{
|
||||
gridPen.Color = Colors.Gray.Alpha(0.50);
|
||||
}
|
||||
@ -758,24 +909,10 @@ namespace UniversalEditor.Editors.Multimedia.Audio.Synthesized.PianoRoll.Control
|
||||
SynthesizedAudioCommandNote note = (cmd as SynthesizedAudioCommandNote);
|
||||
|
||||
Rectangle rect = GetNoteRect(note);
|
||||
|
||||
if (mvarSelectedCommands.Contains(cmd))
|
||||
{
|
||||
e.Graphics.FillRectangle(new SolidBrush(SystemColors.HighlightBackground), rect);
|
||||
}
|
||||
else
|
||||
{
|
||||
e.Graphics.FillRectangle(new SolidBrush(SystemColors.WindowBackground), rect);
|
||||
e.Graphics.FillRectangle(new SolidBrush(Colors.Green.Alpha(0.3)), rect);
|
||||
}
|
||||
e.Graphics.DrawRectangle(new Pen(Colors.Green.Alpha(0.5)), rect);
|
||||
|
||||
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));
|
||||
}
|
||||
bool overlaps = false;
|
||||
if (HighlightOverlappingNotes) overlaps = NoteOverlaps(note);
|
||||
if (!DrawNote(e.Graphics, rect, note.Lyric, note.Phoneme, mvarSelectedCommands.Contains(cmd), _EditingNote == note, overlaps))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -786,7 +923,7 @@ namespace UniversalEditor.Editors.Multimedia.Audio.Synthesized.PianoRoll.Control
|
||||
{
|
||||
Rectangle origNoteRect = GetNoteRect(draggingCommand as SynthesizedAudioCommandNote);
|
||||
Rectangle newNoteRect = GetNoteRect(draggingCommand as SynthesizedAudioCommandNote);
|
||||
newNoteRect.Location = Unquantize(new Vector2D(note_OriginalLocation.X + (drag_CurrentLocation.X - drag_OriginalLocation.X), note_OriginalLocation.Y + (drag_CurrentLocation.Y - drag_OriginalLocation.Y)));
|
||||
newNoteRect.Location = Unquantize(new Vector2D(note_OriginalLocation.X + (drag_CurrentLocation.X - drag_OriginalLocation.X), note_OriginalLocation.Y + (drag_CurrentLocation.Y - drag_OriginalLocation.Y)), QuantizationMode.Position);
|
||||
|
||||
Vector2D diff = new Vector2D(newNoteRect.X - origNoteRect.X, newNoteRect.Y - origNoteRect.Y);
|
||||
foreach (SynthesizedAudioCommand cmd in mvarSelectedCommands)
|
||||
@ -812,7 +949,7 @@ namespace UniversalEditor.Editors.Multimedia.Audio.Synthesized.PianoRoll.Control
|
||||
}
|
||||
else if (SelectionMode == PianoRollSelectionMode.Insert)
|
||||
{
|
||||
Rectangle dragrect = new Rectangle(drag_OriginalLocation.X * mvarQuarterNoteWidth, drag_OriginalLocation.Y * mvarNoteHeight, (drag_CurrentLocation.X * mvarQuarterNoteWidth) - (drag_OriginalLocation.X * mvarQuarterNoteWidth), mvarNoteHeight);
|
||||
Rectangle dragrect = new Rectangle(drag_OriginalLocation.X * PositionQuantization, drag_OriginalLocation.Y * NoteHeight, (drag_CurrentLocation.X * GetLengthQuantization()) - (drag_OriginalLocation.X * GetLengthQuantization()), NoteHeight);
|
||||
if (mvarShowKeyboard)
|
||||
{
|
||||
dragrect.X += mvarKeyboardWidth;
|
||||
@ -837,11 +974,58 @@ namespace UniversalEditor.Editors.Multimedia.Audio.Synthesized.PianoRoll.Control
|
||||
}
|
||||
*/
|
||||
}
|
||||
private bool NoteOverlaps(SynthesizedAudioCommandNote note)
|
||||
{
|
||||
Rectangle rect = GetNoteRect(note);
|
||||
|
||||
for (int i = 0; i < SelectedTrack.Commands.Count; i++)
|
||||
{
|
||||
SynthesizedAudioCommandNote note2 = SelectedTrack.Commands[i] as SynthesizedAudioCommandNote;
|
||||
if (note2 == null) continue;
|
||||
if (note2 == note) continue;
|
||||
|
||||
Rectangle rect2 = GetNoteRect(note2);
|
||||
if ((rect.X >= rect2.X && rect.X <= rect2.Right) || (rect2.X >= rect.X & rect2.X <= rect.Right))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool DrawNote(Graphics graphics, Rectangle rect, string lyric, string phoneme, bool selected, bool editing, bool overlaps)
|
||||
{
|
||||
if (rect.X > Size.Width)
|
||||
return false; // no need to continue since we've reached the end of the visible area
|
||||
|
||||
Color noteColor = SystemColors.HighlightBackground.Darken(0.1);
|
||||
if (overlaps)
|
||||
{
|
||||
noteColor = Colors.DarkGray;
|
||||
}
|
||||
|
||||
if (selected)
|
||||
{
|
||||
graphics.FillRectangle(new SolidBrush(SystemColors.HighlightBackground), rect);
|
||||
}
|
||||
else
|
||||
{
|
||||
graphics.FillRectangle(new SolidBrush(SystemColors.WindowBackground), rect);
|
||||
graphics.FillRectangle(new SolidBrush(noteColor.Alpha(0.3)), rect);
|
||||
}
|
||||
graphics.DrawRectangle(new Pen(noteColor.Alpha(0.5)), rect);
|
||||
|
||||
Rectangle textRect = new Rectangle(rect.X + 2, rect.Y + 10, rect.Width - 4, rect.Height - 2);
|
||||
|
||||
if (!(txt.Visible && editing))
|
||||
{
|
||||
graphics.DrawText(String.Format("{0} [ {1} ]", lyric, phoneme), Font, textRect, new SolidBrush(selected ? SystemColors.HighlightForeground : SystemColors.WindowForeground));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void DrawKeyboard(Graphics g)
|
||||
{
|
||||
int gridWidth = (int)(mvarQuarterNoteWidth * mvarZoomFactor);
|
||||
int gridHeight = (int)(mvarNoteHeight * mvarZoomFactor);
|
||||
int gridWidth = (int)(GetLengthQuantization() * mvarZoomFactor);
|
||||
int gridHeight = (int)(NoteHeight * mvarZoomFactor);
|
||||
|
||||
Rectangle keyboardRect = GetKeyboardRect();
|
||||
for (int i = 0; i < keyboardRect.Height; i += gridHeight)
|
||||
@ -864,11 +1048,11 @@ namespace UniversalEditor.Editors.Multimedia.Audio.Synthesized.PianoRoll.Control
|
||||
|
||||
private int QuantizeHeight(int cy)
|
||||
{
|
||||
return (int)((double)cy / mvarNoteHeight);
|
||||
return (int)((double)cy / NoteHeight);
|
||||
}
|
||||
private int QuantizeWidth(int cy)
|
||||
{
|
||||
return (int)((double)cy / mvarQuarterNoteWidth);
|
||||
return (int)((double)cy / GetLengthQuantization());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,49 @@
|
||||
//
|
||||
// PianoRollEditorSelection.cs
|
||||
//
|
||||
// Author:
|
||||
// Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// Copyright (c) 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
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program 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. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// 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 UniversalEditor.Editors.Multimedia.Audio.Synthesized.PianoRoll;
|
||||
using UniversalEditor.ObjectModels.Multimedia.Audio.Synthesized;
|
||||
using UniversalEditor.UserInterface;
|
||||
|
||||
namespace UniversalEditor.Editors.Multimedia.Audio.Synthesized
|
||||
{
|
||||
public class PianoRollEditorSelection : EditorSelection
|
||||
{
|
||||
private PianoRoll.Views.PianoRollView _parent = null;
|
||||
internal PianoRollEditorSelection(Editor editor, PianoRoll.Views.PianoRollView parent) : base(editor)
|
||||
{
|
||||
_parent = parent;
|
||||
}
|
||||
|
||||
public SynthesizedAudioCommand.SynthesizedAudioCommandCollection Commands { get; private set; } = new SynthesizedAudioCommand.SynthesizedAudioCommandCollection();
|
||||
public override object Content { get => Commands; set => Commands = (SynthesizedAudioCommand.SynthesizedAudioCommandCollection)value; }
|
||||
|
||||
protected override void DeleteInternal()
|
||||
{
|
||||
_parent.Editor.BeginEdit();
|
||||
for (int i = 0; i < Commands.Count; i++)
|
||||
{
|
||||
_parent.SelectedTrack.Commands.Remove(Commands[i]);
|
||||
}
|
||||
_parent.Editor.EndEdit();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -48,6 +48,8 @@
|
||||
<Compile Include="Editors\Multimedia\Palette\PaletteEntrySelection.cs" />
|
||||
<Compile Include="Editors\Multimedia\Audio\Voicebank\VoicebankEditor.cs" />
|
||||
<Compile Include="Editors\Multimedia\PictureCollection\PictureCollectionEditor.cs" />
|
||||
<Compile Include="Editors\Multimedia\Audio\Synthesized\PianoRoll\QuantizationMode.cs" />
|
||||
<Compile Include="Editors\Multimedia\Audio\Synthesized\PianoRollEditorSelection.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Editors\" />
|
||||
|
||||
@ -72,27 +72,27 @@ namespace UniversalEditor.DataFormats.Multimedia.Audio.Synthesized.UTAU
|
||||
InitializePhonemeDictionary();
|
||||
}
|
||||
|
||||
private static DataFormatReference _dfr = null;
|
||||
protected override DataFormatReference MakeReferenceInternal()
|
||||
{
|
||||
DataFormatReference dfr = base.MakeReferenceInternal();
|
||||
dfr.Clear();
|
||||
|
||||
dfr.Capabilities.Add(typeof(PropertyListObjectModel), DataFormatCapabilities.Bootstrap);
|
||||
dfr.Capabilities.Add(typeof(SynthesizedAudioObjectModel), DataFormatCapabilities.All);
|
||||
return dfr;
|
||||
if (_dfr == null)
|
||||
{
|
||||
_dfr = base.MakeReferenceInternal();
|
||||
_dfr.Capabilities.Add(typeof(SynthesizedAudioObjectModel), DataFormatCapabilities.All);
|
||||
}
|
||||
return _dfr;
|
||||
}
|
||||
protected override void BeforeLoadInternal(Stack<ObjectModel> objectModels)
|
||||
{
|
||||
base.BeforeLoadInternal(objectModels);
|
||||
|
||||
// base.Accessor.DefaultEncoding = IO.Encoding.GetRuntimeEncoding(System.Text.Encoding.GetEncoding("shift-jis"));
|
||||
throw new NotImplementedException();
|
||||
base.Accessor.DefaultEncoding = IO.Encoding.ShiftJIS;
|
||||
|
||||
objectModels.Push(new PropertyListObjectModel());
|
||||
}
|
||||
protected override void AfterLoadInternal(Stack<ObjectModel> objectModels)
|
||||
{
|
||||
base.AfterLoadInternal(objectModels);
|
||||
|
||||
PropertyListObjectModel plom = objectModels.Pop() as PropertyListObjectModel;
|
||||
SynthesizedAudioObjectModel sa = objectModels.Pop() as SynthesizedAudioObjectModel;
|
||||
|
||||
@ -105,6 +105,8 @@ namespace UniversalEditor.DataFormats.Multimedia.Audio.Synthesized.UTAU
|
||||
{
|
||||
SynthesizedAudioTrack track = new SynthesizedAudioTrack();
|
||||
Group grp = plom.Items[groupStart] as Group;
|
||||
|
||||
int position = 0;
|
||||
while (grp.Name != "#TRACKEND")
|
||||
{
|
||||
SynthesizedAudioCommandNote note = null;
|
||||
@ -116,6 +118,7 @@ namespace UniversalEditor.DataFormats.Multimedia.Audio.Synthesized.UTAU
|
||||
{
|
||||
note = new SynthesizedAudioCommandNote();
|
||||
}
|
||||
note.Position = position;
|
||||
note.Length = int.Parse(grp.Items.OfType<Property>("Length").Value.ToString());
|
||||
note.Lyric = grp.Items.OfType<Property>("Lyric").Value.ToString();
|
||||
note.Phoneme = LyricToPhoneme(note.Lyric);
|
||||
@ -126,25 +129,82 @@ namespace UniversalEditor.DataFormats.Multimedia.Audio.Synthesized.UTAU
|
||||
note.Intensity = grp.GetPropertyValue<int>("Intensity");
|
||||
note.Modulation = grp.GetPropertyValue<int>("Moduration");
|
||||
note.PBType = grp.GetPropertyValue<int>("PBType");
|
||||
note.Pitches = grp.GetPropertyValue<string>("Pitches").Split<double>(new char[] { ',' });
|
||||
note.Envelope = grp.GetPropertyValue<string>("Envelope").Split(new char[] { ',' });
|
||||
note.VBR = grp.GetPropertyValue<string>("VBR").Split<double>(new char[] { ',' });
|
||||
note.Pitches = grp.GetPropertyValue<string>("Pitches", String.Empty).Split<double>(new char[] { ',' });
|
||||
note.Envelope = grp.GetPropertyValue<string>("Envelope", String.Empty).Split(new char[] { ',' });
|
||||
note.VBR = grp.GetPropertyValue<string>("VBR", String.Empty).Split<double>(new char[] { ',' });
|
||||
|
||||
track.Commands.Add(note);
|
||||
groupStart++;
|
||||
grp = plom.Items[groupStart] as Group;
|
||||
|
||||
position += (int)note.Length;
|
||||
}
|
||||
sa.Tracks.Add(track);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void BeforeSaveInternal(Stack<ObjectModel> objectModels)
|
||||
{
|
||||
base.BeforeSaveInternal(objectModels);
|
||||
|
||||
SynthesizedAudioObjectModel sa = objectModels.Pop() as SynthesizedAudioObjectModel;
|
||||
PropertyListObjectModel plom = new PropertyListObjectModel();
|
||||
|
||||
plom.Items.Add(new Group("#SETTING", new PropertyListItem[]
|
||||
{
|
||||
new Property("Tempo", sa.Tempo),
|
||||
new Property("Tracks", sa.Tracks.Count.ToString()),
|
||||
new Property("ProjectName", sa.Name),
|
||||
new Property("VoiceDir", "%VOICE%"),
|
||||
new Property("OutFile", System.IO.Path.ChangeExtension(System.IO.Path.GetFileName(Accessor.GetFileName()), ".wav")),
|
||||
new Property("CacheDir", ".cache"),
|
||||
new Property("Tool1", "wavtool.exe"),
|
||||
new Property("Tool2", "resampler.exe"),
|
||||
new Property("Mode2", true),
|
||||
new Property("Flags", "g8BRE10H10")
|
||||
}));
|
||||
|
||||
for (int i = 0; i < sa.Tracks.Count; i++)
|
||||
{
|
||||
for (int k = 0; k < sa.Tracks[i].Commands.Count; k++)
|
||||
{
|
||||
if (sa.Tracks[i].Commands[k] is SynthesizedAudioCommandNote)
|
||||
{
|
||||
SynthesizedAudioCommandNote note = sa.Tracks[i].Commands[k] as SynthesizedAudioCommandNote;
|
||||
|
||||
Group gNote = new Group(String.Format("#{0}", i.ToString().PadLeft(4, '0')), new PropertyListItem[]
|
||||
{
|
||||
new Property("Length", note.Length),
|
||||
new Property("Lyric", note.Lyric),
|
||||
new Property("NoteNum", note.Frequency),
|
||||
new Property("PreUtterance", note.PreUtterance),
|
||||
new Property("VoiceOverlap", note.VoiceOverlap),
|
||||
new Property("Intensity", note.Intensity),
|
||||
new Property("Moduration", note.Modulation),
|
||||
new Property("Envelope", String.Join(",", note.Envelope))
|
||||
});
|
||||
plom.Items.Add(gNote);
|
||||
}
|
||||
}
|
||||
plom.Items.Add(new Group("#TRACKEND"));
|
||||
}
|
||||
|
||||
objectModels.Push(plom);
|
||||
}
|
||||
|
||||
private string LyricToPhoneme(string lyric)
|
||||
{
|
||||
// Use PhonemeDictionary.xml lookup table to find the phoneme that corresponds to the
|
||||
// lyric
|
||||
Phoneme p = mvarPhonemeDictionary.PhonemeLists[0].GetPhonemeFromMapping(lyric);
|
||||
if (p == null) return null;
|
||||
return p.Value;
|
||||
if (mvarPhonemeDictionary.PhonemeLists.Count > 0)
|
||||
{
|
||||
for (int i = 0; i < mvarPhonemeDictionary.PhonemeLists.Count; i++)
|
||||
{
|
||||
Phoneme p = mvarPhonemeDictionary.PhonemeLists[i].GetPhonemeFromMapping(lyric);
|
||||
if (p != null) return p.Value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,6 +66,7 @@ namespace UniversalEditor.ObjectModels.Multimedia.Audio.Synthesized
|
||||
PortamentoRising = this.PortamentoRising,
|
||||
PreUtterance = this.PreUtterance,
|
||||
Protected = this.Protected,
|
||||
Position = this.Position,
|
||||
Frequency = this.Frequency,
|
||||
VBR = this.VBR.Clone() as double[],
|
||||
VoiceOverlap = this.VoiceOverlap
|
||||
|
||||
@ -0,0 +1,96 @@
|
||||
//
|
||||
// VPRProjectZIPDataFormat.cs
|
||||
//
|
||||
// Author:
|
||||
// Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// Copyright (c) 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
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program 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. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// 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.Collections.Generic;
|
||||
using UniversalEditor.Accessors;
|
||||
using UniversalEditor.DataFormats.FileSystem.ZIP;
|
||||
using UniversalEditor.ObjectModels.FileSystem;
|
||||
using UniversalEditor.ObjectModels.Multimedia.Audio.Synthesized;
|
||||
|
||||
namespace UniversalEditor.Plugins.Vocaloid.DataFormats.Multimedia.Audio.Synthesized.Vocaloid.VPR
|
||||
{
|
||||
public class VPRProjectZIPDataFormat : ZIPDataFormat
|
||||
{
|
||||
private static DataFormatReference _dfr = null;
|
||||
protected override DataFormatReference MakeReferenceInternal()
|
||||
{
|
||||
if (_dfr == null)
|
||||
{
|
||||
_dfr = base.MakeReferenceInternal();
|
||||
_dfr.Capabilities.Add(typeof(SynthesizedAudioObjectModel), DataFormatCapabilities.All);
|
||||
}
|
||||
return _dfr;
|
||||
}
|
||||
|
||||
protected override void BeforeLoadInternal(Stack<ObjectModel> objectModels)
|
||||
{
|
||||
base.BeforeLoadInternal(objectModels);
|
||||
objectModels.Push(new FileSystemObjectModel());
|
||||
}
|
||||
protected override void AfterLoadInternal(Stack<ObjectModel> objectModels)
|
||||
{
|
||||
base.AfterLoadInternal(objectModels);
|
||||
|
||||
FileSystemObjectModel fsom = (objectModels.Pop() as FileSystemObjectModel);
|
||||
ObjectModel whatever = objectModels.Pop();
|
||||
|
||||
if (whatever is SynthesizedAudioObjectModel)
|
||||
{
|
||||
// have the VPRSequenceJSONDataFormat load the sequence.json into the synthesized audio object model
|
||||
SynthesizedAudioObjectModel vsq = (whatever as SynthesizedAudioObjectModel);
|
||||
VPRSequenceJSONDataFormat vpr = new VPRSequenceJSONDataFormat();
|
||||
|
||||
File sequence_json = fsom.FindFile("Project\\sequence.json");
|
||||
if (sequence_json == null) throw new InvalidDataFormatException("archive does not contain a file called 'Project\\sequence.json'");
|
||||
|
||||
MemoryAccessor ma = new MemoryAccessor(sequence_json.GetData());
|
||||
Document.Load(vsq, vpr, ma);
|
||||
}
|
||||
else
|
||||
{
|
||||
// huh?
|
||||
}
|
||||
}
|
||||
protected override void BeforeSaveInternal(Stack<ObjectModel> objectModels)
|
||||
{
|
||||
base.BeforeSaveInternal(objectModels);
|
||||
|
||||
ObjectModel whatever = objectModels.Pop();
|
||||
FileSystemObjectModel fsom = new FileSystemObjectModel();
|
||||
|
||||
if (whatever is SynthesizedAudioObjectModel)
|
||||
{
|
||||
// have the VPRSequenceJSONDataFormat save the sequence.json and just add it as the only file in the ZIP
|
||||
SynthesizedAudioObjectModel vsq = (whatever as SynthesizedAudioObjectModel);
|
||||
VPRSequenceJSONDataFormat vpr = new VPRSequenceJSONDataFormat();
|
||||
MemoryAccessor ma = new MemoryAccessor();
|
||||
Document.Save(vsq, vpr, ma);
|
||||
|
||||
fsom.Files.Add("Project\\sequence.json", ma.ToArray());
|
||||
}
|
||||
else
|
||||
{
|
||||
// huh?
|
||||
}
|
||||
objectModels.Push(fsom);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,173 @@
|
||||
//
|
||||
// VPRSequenceJSONDataFormat.cs
|
||||
//
|
||||
// Author:
|
||||
// Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// Copyright (c) 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
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program 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. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// 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 UniversalEditor.DataFormats.PropertyList.JavaScriptObjectNotation;
|
||||
using UniversalEditor.ObjectModels.Multimedia.Audio.Synthesized;
|
||||
using UniversalEditor.ObjectModels.PropertyList;
|
||||
|
||||
namespace UniversalEditor.Plugins.Vocaloid.DataFormats.Multimedia.Audio.Synthesized.Vocaloid
|
||||
{
|
||||
public class VPRSequenceJSONDataFormat : JSONDataFormat
|
||||
{
|
||||
private static DataFormatReference _dfr = null;
|
||||
protected override DataFormatReference MakeReferenceInternal()
|
||||
{
|
||||
if (_dfr == null)
|
||||
{
|
||||
_dfr = base.MakeReferenceInternal();
|
||||
_dfr.Capabilities.Add(typeof(SynthesizedAudioObjectModel), DataFormatCapabilities.All);
|
||||
}
|
||||
return _dfr;
|
||||
}
|
||||
|
||||
[CustomOptionText("Vendor", "Yamaha Corporation")]
|
||||
public string Vendor { get; set; } = "Yamaha Corporation";
|
||||
|
||||
protected override void BeforeLoadInternal(Stack<ObjectModel> objectModels)
|
||||
{
|
||||
base.BeforeLoadInternal(objectModels);
|
||||
objectModels.Push(new PropertyListObjectModel());
|
||||
}
|
||||
protected override void AfterLoadInternal(Stack<ObjectModel> objectModels)
|
||||
{
|
||||
base.AfterLoadInternal(objectModels);
|
||||
|
||||
PropertyListObjectModel plom = (objectModels.Pop() as PropertyListObjectModel);
|
||||
SynthesizedAudioObjectModel vsq = (objectModels.Pop() as SynthesizedAudioObjectModel);
|
||||
|
||||
Group g = (plom.Items[0] as Group);
|
||||
Group gVersion = g.Items.OfType<Group>("version");
|
||||
|
||||
Property pTracks = g.Items.OfType<Property>("tracks");
|
||||
Group[] gTracks = pTracks.Value as Group[];
|
||||
if (gTracks == null) throw new InvalidDataFormatException("tracks is not a Group[]");
|
||||
|
||||
for (int i = 0; i < gTracks.Length; i++)
|
||||
{
|
||||
SynthesizedAudioTrack track = new SynthesizedAudioTrack();
|
||||
|
||||
Property pParts = gTracks[i].Items.OfType<Property>("parts");
|
||||
Group[] gParts = pParts.Value as Group[];
|
||||
if (gParts == null) throw new InvalidDataFormatException("parts is not a Group[]");
|
||||
|
||||
for (int j = 0; j < gParts.Length; j++)
|
||||
{
|
||||
Property pNotes = gParts[j].Items.OfType<Property>("notes");
|
||||
Group[] gNotes = pNotes.Value as Group[];
|
||||
if (gNotes == null) throw new InvalidDataFormatException("notes is not a Group[]");
|
||||
|
||||
for (int k = 0; k < gNotes.Length; k++)
|
||||
{
|
||||
SynthesizedAudioCommandNote note = new SynthesizedAudioCommandNote();
|
||||
|
||||
Property pLyric = gNotes[k].Items.OfType<Property>("lyric");
|
||||
Property pPhoneme = gNotes[k].Items.OfType<Property>("phoneme");
|
||||
Property pIsProtected = gNotes[k].Items.OfType<Property>("isProtected");
|
||||
Property pPos = gNotes[k].Items.OfType<Property>("pos");
|
||||
Property pDuration = gNotes[k].Items.OfType<Property>("duration");
|
||||
Property pNumber = gNotes[k].Items.OfType<Property>("number");
|
||||
Property pVelocity = gNotes[k].Items.OfType<Property>("velocity");
|
||||
|
||||
Group gExp = gNotes[k].Items.OfType<Group>("exp");
|
||||
Property pExpOpening = gExp.Items.OfType<Property>("opening");
|
||||
|
||||
Group dvqm = gNotes[k].Items.OfType<Group>("dvqm");
|
||||
Group dvqmRelease = dvqm.Items.OfType<Group>("release");
|
||||
Property dvqmReleaseCompID = dvqmRelease.Items.OfType<Property>("compID");
|
||||
|
||||
Group gVibrato = gNotes[k].Items.OfType<Group>("vibrato");
|
||||
Property pVibratoType = gVibrato.Items.OfType<Property>("type");
|
||||
Property pVibratoDuration = gVibrato.Items.OfType<Property>("duration");
|
||||
|
||||
track.Commands.Add(note);
|
||||
}
|
||||
}
|
||||
|
||||
vsq.Tracks.Add(track);
|
||||
}
|
||||
}
|
||||
protected override void BeforeSaveInternal(Stack<ObjectModel> objectModels)
|
||||
{
|
||||
base.BeforeSaveInternal(objectModels);
|
||||
|
||||
SynthesizedAudioObjectModel vsq = (objectModels.Pop() as SynthesizedAudioObjectModel);
|
||||
|
||||
PropertyListObjectModel plom = new PropertyListObjectModel();
|
||||
plom.Items.AddRange(new PropertyListItem[]
|
||||
{
|
||||
new Group("version", new PropertyListItem[]
|
||||
{
|
||||
new Property("major", 5),
|
||||
new Property("minor", 0),
|
||||
new Property("revision", 0)
|
||||
}),
|
||||
new Property("vender", Vendor),
|
||||
new Property("title", vsq.Information.SongTitle),
|
||||
new Group("masterTrack", new PropertyListItem[]
|
||||
{
|
||||
new Property("samplingRate", 44100),
|
||||
new Group("loop", new PropertyListItem[]
|
||||
{
|
||||
new Property("isEnabled", false),
|
||||
new Property("begin", 0),
|
||||
new Property("end", 0)
|
||||
})
|
||||
}),
|
||||
new Property("voices", new Group[]
|
||||
{
|
||||
new Group("", new PropertyListItem[]
|
||||
{
|
||||
new Property("compID", "BCNFCY43LB2LZCD4"),
|
||||
new Property("name", "MIKU_V4X_Original_EVEC")
|
||||
})
|
||||
}),
|
||||
new Property("tracks", new Group[]
|
||||
{
|
||||
new Group("", new PropertyListItem[]
|
||||
{
|
||||
new Property("type", 0),
|
||||
new Property("name", "MIKU_V4X_ORIGINAL_EVEC"),
|
||||
new Property("color", 0),
|
||||
new Property("busNo", 0),
|
||||
new Property("isFolded", false),
|
||||
new Property("height", 0.0),
|
||||
new Group("volume", new PropertyListItem[]
|
||||
{
|
||||
new Property("isFolded", true),
|
||||
new Property("height", 0.0),
|
||||
new Property("events", new Group[]
|
||||
{
|
||||
new Group("", new PropertyListItem[]
|
||||
{
|
||||
new Property("pos" , 0.0),
|
||||
new Property("value", 0.0)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
});
|
||||
objectModels.Push(plom);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -45,7 +45,7 @@ namespace UniversalEditor.Plugins.Vocaloid.DataFormats.Multimedia.Audio.Synthesi
|
||||
protected override void AfterLoadInternal(Stack<ObjectModel> objectModels)
|
||||
{
|
||||
SynthesizedAudioObjectModel audio = objectModels.Pop() as SynthesizedAudioObjectModel;
|
||||
for (int i = 1; i < audio.Tracks.Count; i++)
|
||||
for (int i = 0; i < audio.Tracks.Count; i++)
|
||||
{
|
||||
SynthesizedAudioTrack track = audio.Tracks[i];
|
||||
string text = string.Empty;
|
||||
@ -108,7 +108,7 @@ namespace UniversalEditor.Plugins.Vocaloid.DataFormats.Multimedia.Audio.Synthesi
|
||||
note.Phoneme = phonemeInfos[1];
|
||||
note.Length = length;
|
||||
note.Frequency = 128 - noteNumber;
|
||||
track.Commands.Add(note);
|
||||
note.Position = thisNotePosition;
|
||||
if (grp.Items.IndexOf(prop) < grp.Items.Count - 1)
|
||||
{
|
||||
int nextNotePosition = int.Parse(grp.Items[grp.Items.IndexOf(prop) + 1].Name);
|
||||
@ -120,6 +120,7 @@ namespace UniversalEditor.Plugins.Vocaloid.DataFormats.Multimedia.Audio.Synthesi
|
||||
track.Commands.Add(rest);
|
||||
}
|
||||
}
|
||||
track.Commands.Add(note);
|
||||
break;
|
||||
}
|
||||
case "Singer":
|
||||
|
||||
@ -37,6 +37,8 @@
|
||||
<Compile Include="DataFormats\Multimedia\Audio\Voicebank\Vocaloid\VocaloidVoicebankDataFormat.cs" />
|
||||
<Compile Include="DataFormats\Multimedia\Audio\VoicebankIndex\Vocaloid\DDIDataFormat.cs" />
|
||||
<Compile Include="DataFormats\Multimedia\Audio\VoicebankIndex\Vocaloid\DDIParameter.cs" />
|
||||
<Compile Include="DataFormats\Multimedia\Audio\Synthesized\Vocaloid\VPR\VPRSequenceJSONDataFormat.cs" />
|
||||
<Compile Include="DataFormats\Multimedia\Audio\Synthesized\Vocaloid\VPR\VPRProjectZIPDataFormat.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="DataFormats\" />
|
||||
@ -47,6 +49,7 @@
|
||||
<Folder Include="DataFormats\Multimedia\Audio\Voicebank\" />
|
||||
<Folder Include="DataFormats\Multimedia\Audio\Voicebank\Vocaloid\" />
|
||||
<Folder Include="DataFormats\Multimedia\Audio\VoicebankIndex\" />
|
||||
<Folder Include="DataFormats\Multimedia\Audio\Synthesized\Vocaloid\VPR\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Libraries\UniversalEditor.Core\UniversalEditor.Core.csproj">
|
||||
@ -61,6 +64,10 @@
|
||||
<Project>{BE4D0BA3-0888-42A5-9C09-FC308A4509D2}</Project>
|
||||
<Name>UniversalEditor.Plugins.Multimedia</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\UniversalEditor.Plugins.FileSystem\UniversalEditor.Plugins.FileSystem.csproj">
|
||||
<Project>{76FD1306-9CA4-428F-993B-B7E4EEEACBF3}</Project>
|
||||
<Name>UniversalEditor.Plugins.FileSystem</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
Loading…
x
Reference in New Issue
Block a user