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; } } } }