From e34df72fc9894879c4e5f5f16b5cc83f938a045f Mon Sep 17 00:00:00 2001 From: Michael Becker Date: Sun, 24 May 2020 10:21:29 -0400 Subject: [PATCH] preliminary implementation of a linear Waveform audio editor similar to Audacity --- .../Controls/WaveformAudioEditorTrack.glade | 41 +++ ...WaveformAudioEditorTrackControlPanel.glade | 310 ++++++++++++++++++ ...lEditor.Content.PlatformIndependent.csproj | 2 + .../Controls/WaveformAudioEditorTrack.cs | 49 +++ .../WaveformAudioEditorTrackControlPanel.cs | 66 ++++ .../WaveformAudioEditorTrackWaveform.cs | 138 ++++++++ .../Audio/Waveform/WaveformAudioEditor.cs | 74 +++++ ...or.Plugins.Multimedia.UserInterface.csproj | 6 + 8 files changed, 686 insertions(+) create mode 100644 Content/UniversalEditor.Content.PlatformIndependent/Editors/Multimedia/Audio/Waveform/Controls/WaveformAudioEditorTrack.glade create mode 100644 Content/UniversalEditor.Content.PlatformIndependent/Editors/Multimedia/Audio/Waveform/Controls/WaveformAudioEditorTrackControlPanel.glade create mode 100644 Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/Audio/Waveform/Controls/WaveformAudioEditorTrack.cs create mode 100644 Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/Audio/Waveform/Controls/WaveformAudioEditorTrackControlPanel.cs create mode 100644 Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/Audio/Waveform/Controls/WaveformAudioEditorTrackWaveform.cs create mode 100644 Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/Audio/Waveform/WaveformAudioEditor.cs diff --git a/Content/UniversalEditor.Content.PlatformIndependent/Editors/Multimedia/Audio/Waveform/Controls/WaveformAudioEditorTrack.glade b/Content/UniversalEditor.Content.PlatformIndependent/Editors/Multimedia/Audio/Waveform/Controls/WaveformAudioEditorTrack.glade new file mode 100644 index 00000000..875c6817 --- /dev/null +++ b/Content/UniversalEditor.Content.PlatformIndependent/Editors/Multimedia/Audio/Waveform/Controls/WaveformAudioEditorTrack.glade @@ -0,0 +1,41 @@ + + + + + + False + + + + + + True + False + + + UniversalEditor.Plugins.Multimedia.UserInterface.Editors.Multimedia.Audio.Waveform.Controls.WaveformAudioEditorTrackControlPanel + True + False + + + False + True + 0 + + + + + UniversalEditor.Plugins.Multimedia.UserInterface.Editors.Multimedia.Audio.Waveform.Controls.WaveformAudioEditorTrackWaveform + True + False + + + True + True + 1 + + + + + + diff --git a/Content/UniversalEditor.Content.PlatformIndependent/Editors/Multimedia/Audio/Waveform/Controls/WaveformAudioEditorTrackControlPanel.glade b/Content/UniversalEditor.Content.PlatformIndependent/Editors/Multimedia/Audio/Waveform/Controls/WaveformAudioEditorTrackControlPanel.glade new file mode 100644 index 00000000..1440f4a4 --- /dev/null +++ b/Content/UniversalEditor.Content.PlatformIndependent/Editors/Multimedia/Audio/Waveform/Controls/WaveformAudioEditorTrackControlPanel.glade @@ -0,0 +1,310 @@ + + + + + + 100 + 75 + 1 + 10 + 10 + + + 100 + 50 + 1 + 10 + + + True + False + gtk-missing-image + + + True + False + gtk-go-up + + + False + + + + + + True + False + 8 + 8 + 8 + 8 + vertical + + + True + False + + + True + True + True + image1 + none + True + + + False + True + 0 + + + + + True + True + + + True + True + 1 + + + + + True + True + False + True + none + + + + + + False + True + 2 + + + + + False + True + 0 + + + + + True + False + + + Mute + True + True + True + + + True + True + 0 + + + + + Solo + True + True + True + + + True + True + 1 + + + + + False + True + 1 + + + + + True + False + + + True + False + 8 + 8 + 8 + 8 + + + + + 2 + 0 + + + + + True + False + 8 + 8 + 8 + 8 + - + + + 0 + 0 + + + + + True + False + 8 + 8 + 8 + 8 + R + + + 2 + 1 + + + + + True + False + 8 + 8 + 8 + 8 + L + + + 0 + 1 + + + + + True + True + True + adjustment1 + off + off + 1 + False + + + 1 + 0 + + + + + True + True + True + adjustment2 + off + off + False + + + 1 + 1 + + + + + False + True + 2 + + + + + True + False + 8 + 8 + 8 + 8 + Mono, 22050 Hz + 0 + + + False + True + 3 + + + + + True + False + 8 + 8 + 8 + 8 + 32-bit float + 0 + + + False + True + 4 + + + + + True + False + + + True + True + True + image2 + none + + + False + True + 0 + + + + + Select + True + True + True + + + False + True + 1 + + + + + False + True + 5 + + + + + + diff --git a/Content/UniversalEditor.Content.PlatformIndependent/UniversalEditor.Content.PlatformIndependent.csproj b/Content/UniversalEditor.Content.PlatformIndependent/UniversalEditor.Content.PlatformIndependent.csproj index 06723614..732f670d 100644 --- a/Content/UniversalEditor.Content.PlatformIndependent/UniversalEditor.Content.PlatformIndependent.csproj +++ b/Content/UniversalEditor.Content.PlatformIndependent/UniversalEditor.Content.PlatformIndependent.csproj @@ -737,6 +737,8 @@ + + diff --git a/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/Audio/Waveform/Controls/WaveformAudioEditorTrack.cs b/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/Audio/Waveform/Controls/WaveformAudioEditorTrack.cs new file mode 100644 index 00000000..92d8c8a8 --- /dev/null +++ b/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/Audio/Waveform/Controls/WaveformAudioEditorTrack.cs @@ -0,0 +1,49 @@ +// +// WaveformAudioEditorTrack.cs +// +// Author: +// Michael Becker +// +// 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 . + +using System; +using MBS.Framework.UserInterface; +using UniversalEditor.ObjectModels.Multimedia.Audio.Waveform; + +namespace UniversalEditor.Plugins.Multimedia.UserInterface.Editors.Multimedia.Audio.Waveform.Controls +{ + [ContainerLayout("~/Editors/Multimedia/Audio/Waveform/Controls/WaveformAudioEditorTrack.glade")] + public class WaveformAudioEditorTrack : Container + { + private WaveformAudioEditorTrackControlPanel ctTrackControlPanel; + private WaveformAudioEditorTrackWaveform ctTrackWaveform; + + public WaveformAudioObjectModel ObjectModel { get; set; } + + public WaveformAudioEditorTrack() + { + } + public WaveformAudioEditorTrack(WaveformAudioObjectModel wave) + { + ObjectModel = wave; + } + + protected override void OnCreated(EventArgs e) + { + base.OnCreated(e); + } + } +} diff --git a/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/Audio/Waveform/Controls/WaveformAudioEditorTrackControlPanel.cs b/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/Audio/Waveform/Controls/WaveformAudioEditorTrackControlPanel.cs new file mode 100644 index 00000000..b4fa8c13 --- /dev/null +++ b/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/Audio/Waveform/Controls/WaveformAudioEditorTrackControlPanel.cs @@ -0,0 +1,66 @@ +// +// WaveformAudioEditorTrackControlPanel.cs +// +// Author: +// Michael Becker +// +// 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 . + +using System; +using MBS.Framework.UserInterface; +using MBS.Framework.UserInterface.Controls; + +namespace UniversalEditor.Plugins.Multimedia.UserInterface.Editors.Multimedia.Audio.Waveform.Controls +{ + [ContainerLayout("~/Editors/Multimedia/Audio/Waveform/Controls/WaveformAudioEditorTrackControlPanel.glade")] + public class WaveformAudioEditorTrackControlPanel : Container + { + private Button cmdDelete; + private TextBox txtTrackName; + private Button cmdMenu; + private Container ctButtons; + private Button cmdMute; + private Button cmdSolo; + private Container ctSliders; + private Label lblBitrate; + private Label lblFormat; + private Button cmdExpandCollapse; + private Button cmdSelect; + + protected override void OnCreated(EventArgs e) + { + base.OnCreated(e); + } + + private void cmdExpandCollapse_Click(object sender, EventArgs e) + { + if (ctButtons.Visible) + { + ctButtons.Visible = false; + ctSliders.Visible = false; + lblBitrate.Visible = false; + lblFormat.Visible = false; + } + else + { + ctButtons.Visible = true; + ctSliders.Visible = true; + lblBitrate.Visible = true; + lblFormat.Visible = true; + } + } + } +} diff --git a/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/Audio/Waveform/Controls/WaveformAudioEditorTrackWaveform.cs b/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/Audio/Waveform/Controls/WaveformAudioEditorTrackWaveform.cs new file mode 100644 index 00000000..1c58e96c --- /dev/null +++ b/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/Audio/Waveform/Controls/WaveformAudioEditorTrackWaveform.cs @@ -0,0 +1,138 @@ +// +// WaveformAudioEditorTrackWaveform.cs +// +// Author: +// Michael Becker +// +// 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 . + +using System; +using MBS.Framework.Drawing; +using MBS.Framework.UserInterface; +using MBS.Framework.UserInterface.Drawing; +using MBS.Framework.UserInterface.Input.Mouse; +using UniversalEditor.ObjectModels.Multimedia.Audio.Waveform; + +namespace UniversalEditor.Plugins.Multimedia.UserInterface.Editors.Multimedia.Audio.Waveform.Controls +{ + public class WaveformAudioEditorTrackWaveform : CustomControl + { + protected override void OnCreated(EventArgs e) + { + base.OnCreated(e); + + ScrollBounds = new MBS.Framework.Drawing.Dimension2D(4096, 0); + Cursor = Cursors.Text; + } + + private static bool preventScroll = false; + + private int _SelectionStart = 0; + public int SelectionStart { get { return _SelectionStart; } set { _SelectionStart = value; Refresh(); } } + private int _SelectionLength = 0; + public int SelectionLength { get { return _SelectionLength; } set { _SelectionLength = value; Refresh(); } } + + public double ScaleFactorY { get; set; } = 0.5;// 1.0; + + private int origStart = 0; + protected override void OnMouseDown(MouseEventArgs e) + { + base.OnMouseDown(e); + + origStart = (int)e.X; + _SelectionStart = (int)e.X; + _SelectionLength = 0; + Refresh(); + } + protected override void OnMouseMove(MouseEventArgs e) + { + base.OnMouseMove(e); + + if (e.Buttons == MouseButtons.Primary) + { + if ((int)(e.X - origStart) < 0) + { + _SelectionStart = origStart + (int)(e.X - origStart); + _SelectionLength = (int)(origStart - e.X); + } + else + { + _SelectionStart = origStart; + _SelectionLength = (int)(e.X - _SelectionStart); + } + Refresh(); + } + } + + private const int WAVEFORM_MIDPOINT = 128; + + protected override void OnPaint(PaintEventArgs e) + { + base.OnPaint(e); + + WaveformAudioEditorTrack track = (Parent as WaveformAudioEditorTrack); + WaveformAudioObjectModel wave = track.ObjectModel; + + ScrollBounds = new MBS.Framework.Drawing.Dimension2D(wave.RawSamples.Length, 0); + + Vector2D lastPoint = new Vector2D(0, WAVEFORM_MIDPOINT); + Pen pen = new Pen(SystemColors.HighlightBackground); + Pen pen2 = new Pen(SystemColors.HighlightForeground); + + if (SelectionLength > 0) + { + e.Graphics.FillRectangle(new SolidBrush(SystemColors.HighlightBackground), new Rectangle(SelectionStart, 0, SelectionLength, Size.Height)); + } + + e.Graphics.DrawLine(new Pen(Colors.Black), 0, WAVEFORM_MIDPOINT * ScaleFactorY, HorizontalAdjustment.Value + Size.Width, WAVEFORM_MIDPOINT * ScaleFactorY); + e.Graphics.DrawLine(new Pen(Colors.White), SelectionStart, 0, SelectionStart, Size.Height); + + for (int i = 0; i < wave.RawSamples.Length; i++) + { + double x = i; + double y = (ScaleFactorY * wave.RawSamples[i]); + + if (x >= SelectionStart && x <= (SelectionStart + SelectionLength)) + { + e.Graphics.DrawLine(pen2, lastPoint.X, lastPoint.Y, x, y); + } + else + { + e.Graphics.DrawLine(pen, lastPoint.X, lastPoint.Y, x, y); + } + lastPoint = new Vector2D(x, y); + } + } + + protected override void OnScrolled(ScrolledEventArgs e) + { + if (preventScroll) return; + + preventScroll = true; + WaveformAudioEditor ed = (Parent.Parent as WaveformAudioEditor); + for (int i = 0; i < ed.Controls.Count; i++) + { + if (ed.Controls[i] is WaveformAudioEditorTrack) + { + WaveformAudioEditorTrackWaveform wvff = ((WaveformAudioEditorTrack)ed.Controls[i]).Controls[1] as WaveformAudioEditorTrackWaveform; + wvff.HorizontalAdjustment.Value = HorizontalAdjustment.Value; + } + } + preventScroll = false; + base.OnScrolled(e); + } + } +} diff --git a/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/Audio/Waveform/WaveformAudioEditor.cs b/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/Audio/Waveform/WaveformAudioEditor.cs new file mode 100644 index 00000000..89f5df8f --- /dev/null +++ b/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/Audio/Waveform/WaveformAudioEditor.cs @@ -0,0 +1,74 @@ +// +// WaveformAudioEditor.cs +// +// Author: +// Michael Becker +// +// 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 . + +using System; +using MBS.Framework.UserInterface; +using MBS.Framework.UserInterface.Layouts; +using UniversalEditor.ObjectModels.Multimedia.Audio.Waveform; +using UniversalEditor.Plugins.Multimedia.UserInterface.Editors.Multimedia.Audio.Waveform.Controls; +using UniversalEditor.UserInterface; + +namespace UniversalEditor.Plugins.Multimedia.UserInterface.Editors.Multimedia.Audio.Waveform +{ + public class WaveformAudioEditor : Editor + { + private static EditorReference _er = null; + public override EditorReference MakeReference() + { + if (_er == null) + { + _er = base.MakeReference(); + _er.SupportedObjectModels.Add(typeof(WaveformAudioObjectModel)); + } + return _er; + } + + public WaveformAudioEditor() + { + Layout = new BoxLayout(Orientation.Vertical); + } + + protected override void OnObjectModelChanged(EventArgs e) + { + base.OnObjectModelChanged(e); + + this.Controls.Clear(); + + WaveformAudioObjectModel wave = (ObjectModel as WaveformAudioObjectModel); + if (wave == null) return; + + BoxLayout.Constraints cc = new BoxLayout.Constraints(false, false); + cc.VerticalExpand = false; + cc.HorizontalExpand = true; + this.Controls.Add(new WaveformAudioEditorTrack(wave), cc); + } + + public override void UpdateSelections() + { + throw new System.NotImplementedException(); + } + + protected override EditorSelection CreateSelectionInternal(object content) + { + throw new System.NotImplementedException(); + } + } +} diff --git a/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface.csproj b/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface.csproj index 0f7ce72e..dfbe530e 100644 --- a/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface.csproj +++ b/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface.csproj @@ -50,6 +50,10 @@ + + + + @@ -68,6 +72,8 @@ + +