JD2022-TU1/main/tools/framework/JD.Application.TeaBox/View/Tracks/WaveTrack.cs

121 lines
3.6 KiB
C#

using System;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using JD.Application.View.Timeline;
using JD.Application.View.Utilities;
using JD.Audio.Annotations;
using JD.Audio.Sound;
using JD.Kernel.StaticHelpers;
using TeaBox;
using Point = System.Drawing.Point;
using Size = System.Drawing.Size;
namespace JD.Application.View.Tracks
{
/// <summary>
/// Paints the wave as a track in the Sequence
/// </summary>
public class WaveTrack : AnnotationTrack
{
private readonly PaintCache _cache = new PaintCache();
private readonly Wave _wave;
private readonly IChannel _channel;
public WaveTrack(Wave wave, IChannel channel)
: base(wave.Annotations)
{
Throw.IfNull(wave, "wave");
Throw.IfNull(channel, "channel");
_wave = wave;
_wave.AsyncLoaded += _wave_AsyncLoaded;
_channel = channel;
_cache.Refreshed += (s, e) => Invalidate();
}
void _wave_AsyncLoaded(object sender, EventArgs e)
{
_cache.Invalidate();
Invalidate();
}
protected override void Dispose(bool disposing)
{
_wave.AsyncLoaded -=_wave_AsyncLoaded;
base.Dispose(disposing);
}
protected override void OnPaintSelf(PaintEventArgs e)
{
base.OnPaintSelf(e);
int start = Timeline.TimeToPixel(Timeline.VisibleTimeRange.Min);
int end = Timeline.TimeToPixel(Timeline.VisibleTimeRange.Max);
var image = _cache.GetImage(new PaintRequest
{
Channel = _channel,
Wave = _wave,
Start = Timeline.VisibleStartBeat(),
End = Timeline.VisibleEndBeat(),
Size = new Size(end - start, Bounds.Height - 1),
});
if (image != null)
{
e.Graphics.DrawImage(image, new Point(Bounds.Left + start, Bounds.Top));
}
}
public override string ToString()
{
return Path.GetFileName(_wave.FileName) ?? "No wave found";
}
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
if (e.Button == MouseButtons.Left)
{
Timeline.TimeCursor.Time = Timeline.PixelToTime(e.X);
}
}
#region Nested
private struct PaintRequest
{
public IChannel Channel;
public Wave Wave;
public BeatUnit Start;
public BeatUnit End;
public Size Size;
}
private class PaintCache : AsyncPaintCache<PaintRequest>
{
protected override Image DoPaint(PaintRequest request)
{
if (request.Size.Width == 0 || request.Size.Height == 0)
{
return new Bitmap(1, 1);
}
var curve = new GraphicalWaveCurve();
float beatsLength = request.End.Value - request.Start.Value;
float pixelsPerBeat = request.Size.Width / beatsLength;
curve.AddBeats(request.Channel, request.Wave.UnitConverter, request.Start, request.End, pixelsPerBeat);
var bitmap = new Bitmap(request.Size.Width, request.Size.Height);
using (var graphics = Graphics.FromImage(bitmap))
{
curve.Paint(graphics, request.Start, request.Size.Height, pixelsPerBeat, LowQuality);
}
return bitmap;
}
}
#endregion
}
}