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