Server/Spectrum/LineSpectrum.cs
author StephaneLenclud
Fri, 06 Jan 2017 18:27:19 +0100
changeset 276 7cd495550d5f
parent 275 a4a341accc89
permissions -rw-r--r--
Published v1.4.3
Major hack into our spectrum math to make it prettier.
     1 using System;
     2 using System.ComponentModel;
     3 using System.Drawing;
     4 using System.Drawing.Drawing2D;
     5 using System.Drawing.Text;
     6 using CSCore.DSP;
     7 
     8 namespace Visualization
     9 {
    10     public class LineSpectrum : SpectrumBase
    11     {
    12         private int _barCount;
    13         private double _barSpacing;
    14         private double _barWidth;
    15         private Size _currentSize;
    16         
    17         
    18         public LineSpectrum(FftSize fftSize)
    19         {
    20             FftSize = fftSize;            
    21         }
    22 
    23         [Browsable(false)]
    24         public double BarWidth
    25         {
    26             get { return _barWidth; }
    27         }
    28 
    29         public double BarSpacing
    30         {
    31             get { return _barSpacing; }
    32             set
    33             {
    34                 if (value < 0)
    35                     throw new ArgumentOutOfRangeException("value");
    36                 _barSpacing = value;
    37                 UpdateFrequencyMapping();
    38 
    39                 RaisePropertyChanged("BarSpacing");
    40                 RaisePropertyChanged("BarWidth");
    41             }
    42         }
    43 
    44         public int BarCount
    45         {
    46             get { return _barCount; }
    47             set
    48             {
    49                 if (value <= 0)
    50                     throw new ArgumentOutOfRangeException("value");
    51                 _barCount = value;
    52                 SpectrumResolution = value;
    53                 UpdateFrequencyMapping();
    54 
    55                 RaisePropertyChanged("BarCount");
    56                 RaisePropertyChanged("BarWidth");
    57             }
    58         }
    59 
    60         [BrowsableAttribute(false)]
    61         public Size CurrentSize
    62         {
    63             get { return _currentSize; }
    64             protected set
    65             {
    66                 _currentSize = value;
    67                 RaisePropertyChanged("CurrentSize");
    68             }
    69         }
    70 
    71         /// <summary>
    72         /// Update our math.
    73         /// </summary>
    74         /// <returns></returns>
    75         public bool Update()
    76         {
    77             return SpectrumProvider.GetFftData(iFftBuffer, this);
    78         }
    79 
    80         private bool CreateSpectrumLine(Image aImage, Brush brush, Color background, bool highQuality)
    81         {
    82             //get the fft result from the spectrum provider            
    83             using (var pen = new Pen(brush, (float)_barWidth))
    84             {
    85                 using (Graphics graphics = Graphics.FromImage(aImage))
    86                 {
    87                     PrepareGraphics(graphics, highQuality);
    88                     graphics.Clear(background);
    89 
    90                     CreateSpectrumLineInternal(graphics, pen, iFftBuffer, aImage.Size);
    91                 }
    92             }
    93 
    94             return true;         
    95         }
    96 
    97         /// <summary>
    98         /// 
    99         /// </summary>
   100         /// <param name="size"></param>
   101         /// <param name="color1"></param>
   102         /// <param name="color2"></param>
   103         /// <param name="background"></param>
   104         /// <param name="highQuality"></param>
   105         /// <returns></returns>
   106         public bool Render(Image aImage, Color color1, Color color2, Color background, bool highQuality)
   107         {
   108             if (!UpdateFrequencyMappingIfNessesary(aImage.Size))
   109             {
   110                 return false;
   111             }
   112 
   113             using (Brush brush = new LinearGradientBrush(new RectangleF(0, 0, (float)_barWidth, aImage.Size.Height), color2, color1, LinearGradientMode.Vertical))
   114             {
   115                 return CreateSpectrumLine(aImage, brush, background, highQuality);
   116             }
   117         }
   118 
   119         /// <summary>
   120         /// 
   121         /// </summary>
   122         /// <param name="graphics"></param>
   123         /// <param name="pen"></param>
   124         /// <param name="fftBuffer"></param>
   125         /// <param name="size"></param>
   126         private void CreateSpectrumLineInternal(Graphics graphics, Pen pen, float[] fftBuffer, Size size)
   127         {
   128             int height = size.Height;
   129             //prepare the fft result for rendering 
   130             SpectrumPointData[] spectrumPoints = CalculateSpectrumPoints(height, fftBuffer);
   131 
   132             //connect the calculated points with lines
   133             for (int i = 0; i < spectrumPoints.Length; i++)
   134             {
   135                 SpectrumPointData p = spectrumPoints[i];
   136                 int barIndex = p.SpectrumPointIndex;
   137                 double xCoord = BarSpacing * (barIndex + 1) + (_barWidth * barIndex) + _barWidth / 2;
   138 
   139                 var p1 = new PointF((float)xCoord, height);
   140                 var p2 = new PointF((float)xCoord, height - (float)p.Value);
   141 
   142                 graphics.DrawLine(pen, p1, p2);
   143             }
   144         }
   145 
   146         protected override void UpdateFrequencyMapping()
   147         {
   148             _barWidth = Math.Max(((_currentSize.Width - (BarSpacing * (BarCount + 1))) / BarCount), 0.00001);
   149             base.UpdateFrequencyMapping();
   150         }
   151 
   152         private bool UpdateFrequencyMappingIfNessesary(Size newSize)
   153         {
   154             if (newSize != CurrentSize)
   155             {
   156                 CurrentSize = newSize;
   157                 UpdateFrequencyMapping();
   158             }
   159 
   160             return newSize.Width > 0 && newSize.Height > 0;
   161         }
   162 
   163         private void PrepareGraphics(Graphics graphics, bool highQuality)
   164         {
   165             if (highQuality)
   166             {
   167                 graphics.SmoothingMode = SmoothingMode.AntiAlias;
   168                 graphics.CompositingQuality = CompositingQuality.AssumeLinear;
   169                 graphics.PixelOffsetMode = PixelOffsetMode.Default;
   170                 graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
   171             }
   172             else
   173             {
   174                 graphics.SmoothingMode = SmoothingMode.HighSpeed;
   175                 graphics.CompositingQuality = CompositingQuality.HighSpeed;
   176                 graphics.PixelOffsetMode = PixelOffsetMode.None;
   177                 graphics.TextRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit;
   178             }
   179         }
   180     }
   181 }