166 lines
5.3 KiB
C#
166 lines
5.3 KiB
C#
|
using System;
|
|||
|
using System.ComponentModel;
|
|||
|
using System.Drawing;
|
|||
|
using System.Drawing.Drawing2D;
|
|||
|
using System.Drawing.Text;
|
|||
|
using CSCore.DSP;
|
|||
|
|
|||
|
namespace WinformsVisualization.Visualization
|
|||
|
{
|
|||
|
public class LineSpectrum : SpectrumBase
|
|||
|
{
|
|||
|
private int _barCount;
|
|||
|
private double _barSpacing;
|
|||
|
private double _barWidth;
|
|||
|
private Size _currentSize;
|
|||
|
|
|||
|
public LineSpectrum(FftSize fftSize)
|
|||
|
{
|
|||
|
FftSize = fftSize;
|
|||
|
}
|
|||
|
|
|||
|
[Browsable(false)]
|
|||
|
public double BarWidth
|
|||
|
{
|
|||
|
get { return _barWidth; }
|
|||
|
}
|
|||
|
|
|||
|
public double BarSpacing
|
|||
|
{
|
|||
|
get { return _barSpacing; }
|
|||
|
set
|
|||
|
{
|
|||
|
if (value < 0)
|
|||
|
throw new ArgumentOutOfRangeException("value");
|
|||
|
_barSpacing = value;
|
|||
|
UpdateFrequencyMapping();
|
|||
|
|
|||
|
RaisePropertyChanged("BarSpacing");
|
|||
|
RaisePropertyChanged("BarWidth");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public int BarCount
|
|||
|
{
|
|||
|
get { return _barCount; }
|
|||
|
set
|
|||
|
{
|
|||
|
if (value <= 0)
|
|||
|
throw new ArgumentOutOfRangeException("value");
|
|||
|
_barCount = value;
|
|||
|
SpectrumResolution = value;
|
|||
|
UpdateFrequencyMapping();
|
|||
|
|
|||
|
RaisePropertyChanged("BarCount");
|
|||
|
RaisePropertyChanged("BarWidth");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
[BrowsableAttribute(false)]
|
|||
|
public Size CurrentSize
|
|||
|
{
|
|||
|
get { return _currentSize; }
|
|||
|
protected set
|
|||
|
{
|
|||
|
_currentSize = value;
|
|||
|
RaisePropertyChanged("CurrentSize");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public Bitmap CreateSpectrumLine(Size size, Brush brush, Color background, bool highQuality)
|
|||
|
{
|
|||
|
if (!UpdateFrequencyMappingIfNessesary(size))
|
|||
|
return null;
|
|||
|
|
|||
|
var fftBuffer = new float[(int)FftSize];
|
|||
|
|
|||
|
//get the fft result from the spectrum provider
|
|||
|
if (SpectrumProvider.GetFftData(fftBuffer, this))
|
|||
|
{
|
|||
|
using (var pen = new Pen(brush, (float)_barWidth))
|
|||
|
{
|
|||
|
var bitmap = new Bitmap(size.Width, size.Height);
|
|||
|
|
|||
|
using (Graphics graphics = Graphics.FromImage(bitmap))
|
|||
|
{
|
|||
|
PrepareGraphics(graphics, highQuality);
|
|||
|
graphics.Clear(background);
|
|||
|
|
|||
|
CreateSpectrumLineInternal(graphics, pen, fftBuffer, size);
|
|||
|
}
|
|||
|
|
|||
|
return bitmap;
|
|||
|
}
|
|||
|
}
|
|||
|
return null;
|
|||
|
}
|
|||
|
|
|||
|
public Bitmap CreateSpectrumLine(Size size, Color color1, Color color2, Color background, bool highQuality)
|
|||
|
{
|
|||
|
if (!UpdateFrequencyMappingIfNessesary(size))
|
|||
|
return null;
|
|||
|
|
|||
|
using (
|
|||
|
Brush brush = new LinearGradientBrush(new RectangleF(0, 0, (float)_barWidth, size.Height), color2,
|
|||
|
color1, LinearGradientMode.Vertical))
|
|||
|
{
|
|||
|
return CreateSpectrumLine(size, brush, background, highQuality);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void CreateSpectrumLineInternal(Graphics graphics, Pen pen, float[] fftBuffer, Size size)
|
|||
|
{
|
|||
|
int height = size.Height;
|
|||
|
//prepare the fft result for rendering
|
|||
|
SpectrumPointData[] spectrumPoints = CalculateSpectrumPoints(height, fftBuffer);
|
|||
|
|
|||
|
//connect the calculated points with lines
|
|||
|
for (int i = 0; i < spectrumPoints.Length; i++)
|
|||
|
{
|
|||
|
SpectrumPointData p = spectrumPoints[i];
|
|||
|
int barIndex = p.SpectrumPointIndex;
|
|||
|
double xCoord = BarSpacing * (barIndex + 1) + (_barWidth * barIndex) + _barWidth / 2;
|
|||
|
|
|||
|
var p1 = new PointF((float)xCoord, height);
|
|||
|
var p2 = new PointF((float)xCoord, height - (float)p.Value - 1);
|
|||
|
|
|||
|
graphics.DrawLine(pen, p1, p2);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
protected override void UpdateFrequencyMapping()
|
|||
|
{
|
|||
|
_barWidth = Math.Max(((_currentSize.Width - (BarSpacing * (BarCount + 1))) / BarCount), 0.00001);
|
|||
|
base.UpdateFrequencyMapping();
|
|||
|
}
|
|||
|
|
|||
|
private bool UpdateFrequencyMappingIfNessesary(Size newSize)
|
|||
|
{
|
|||
|
if (newSize != CurrentSize)
|
|||
|
{
|
|||
|
CurrentSize = newSize;
|
|||
|
UpdateFrequencyMapping();
|
|||
|
}
|
|||
|
|
|||
|
return newSize.Width > 0 && newSize.Height > 0;
|
|||
|
}
|
|||
|
|
|||
|
private void PrepareGraphics(Graphics graphics, bool highQuality)
|
|||
|
{
|
|||
|
if (highQuality)
|
|||
|
{
|
|||
|
graphics.SmoothingMode = SmoothingMode.AntiAlias;
|
|||
|
graphics.CompositingQuality = CompositingQuality.AssumeLinear;
|
|||
|
graphics.PixelOffsetMode = PixelOffsetMode.Default;
|
|||
|
graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
graphics.SmoothingMode = SmoothingMode.HighSpeed;
|
|||
|
graphics.CompositingQuality = CompositingQuality.HighSpeed;
|
|||
|
graphics.PixelOffsetMode = PixelOffsetMode.None;
|
|||
|
graphics.TextRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|