Server/Spectrum/LineSpectrum.cs
author StephaneLenclud
Mon, 02 Jan 2017 18:43:45 +0100
changeset 273 e5f85a895a62
child 274 920fea7a6427
permissions -rw-r--r--
Draft audio spectrum visualizer.
     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         public LineSpectrum(FftSize fftSize)
    18         {
    19             FftSize = fftSize;
    20         }
    21 
    22         [Browsable(false)]
    23         public double BarWidth
    24         {
    25             get { return _barWidth; }
    26         }
    27 
    28         public double BarSpacing
    29         {
    30             get { return _barSpacing; }
    31             set
    32             {
    33                 if (value < 0)
    34                     throw new ArgumentOutOfRangeException("value");
    35                 _barSpacing = value;
    36                 UpdateFrequencyMapping();
    37 
    38                 RaisePropertyChanged("BarSpacing");
    39                 RaisePropertyChanged("BarWidth");
    40             }
    41         }
    42 
    43         public int BarCount
    44         {
    45             get { return _barCount; }
    46             set
    47             {
    48                 if (value <= 0)
    49                     throw new ArgumentOutOfRangeException("value");
    50                 _barCount = value;
    51                 SpectrumResolution = value;
    52                 UpdateFrequencyMapping();
    53 
    54                 RaisePropertyChanged("BarCount");
    55                 RaisePropertyChanged("BarWidth");
    56             }
    57         }
    58 
    59         [BrowsableAttribute(false)]
    60         public Size CurrentSize
    61         {
    62             get { return _currentSize; }
    63             protected set
    64             {
    65                 _currentSize = value;
    66                 RaisePropertyChanged("CurrentSize");
    67             }
    68         }
    69 
    70         public Bitmap CreateSpectrumLine(Size size, Brush brush, Color background, bool highQuality)
    71         {
    72             if (!UpdateFrequencyMappingIfNessesary(size))
    73                 return null;
    74 
    75             var fftBuffer = new float[(int)FftSize];
    76 
    77             //get the fft result from the spectrum provider
    78             if (SpectrumProvider.GetFftData(fftBuffer, this))
    79             {
    80                 using (var pen = new Pen(brush, (float)_barWidth))
    81                 {
    82                     var bitmap = new Bitmap(size.Width, size.Height);
    83 
    84                     using (Graphics graphics = Graphics.FromImage(bitmap))
    85                     {
    86                         PrepareGraphics(graphics, highQuality);
    87                         graphics.Clear(background);
    88 
    89                         CreateSpectrumLineInternal(graphics, pen, fftBuffer, size);
    90                     }
    91 
    92                     return bitmap;
    93                 }
    94             }
    95             return null;
    96         }
    97 
    98         public Bitmap CreateSpectrumLine(Size size, Color color1, Color color2, Color background, bool highQuality)
    99         {
   100             if (!UpdateFrequencyMappingIfNessesary(size))
   101                 return null;
   102 
   103             using (
   104                 Brush brush = new LinearGradientBrush(new RectangleF(0, 0, (float)_barWidth, size.Height), color2,
   105                     color1, LinearGradientMode.Vertical))
   106             {
   107                 return CreateSpectrumLine(size, brush, background, highQuality);
   108             }
   109         }
   110 
   111         private void CreateSpectrumLineInternal(Graphics graphics, Pen pen, float[] fftBuffer, Size size)
   112         {
   113             int height = size.Height;
   114             //prepare the fft result for rendering 
   115             SpectrumPointData[] spectrumPoints = CalculateSpectrumPoints(height, fftBuffer);
   116 
   117             //connect the calculated points with lines
   118             for (int i = 0; i < spectrumPoints.Length; i++)
   119             {
   120                 SpectrumPointData p = spectrumPoints[i];
   121                 int barIndex = p.SpectrumPointIndex;
   122                 double xCoord = BarSpacing * (barIndex + 1) + (_barWidth * barIndex) + _barWidth / 2;
   123 
   124                 var p1 = new PointF((float)xCoord, height);
   125                 var p2 = new PointF((float)xCoord, height - (float)p.Value - 1);
   126 
   127                 graphics.DrawLine(pen, p1, p2);
   128             }
   129         }
   130 
   131         protected override void UpdateFrequencyMapping()
   132         {
   133             _barWidth = Math.Max(((_currentSize.Width - (BarSpacing * (BarCount + 1))) / BarCount), 0.00001);
   134             base.UpdateFrequencyMapping();
   135         }
   136 
   137         private bool UpdateFrequencyMappingIfNessesary(Size newSize)
   138         {
   139             if (newSize != CurrentSize)
   140             {
   141                 CurrentSize = newSize;
   142                 UpdateFrequencyMapping();
   143             }
   144 
   145             return newSize.Width > 0 && newSize.Height > 0;
   146         }
   147 
   148         private void PrepareGraphics(Graphics graphics, bool highQuality)
   149         {
   150             if (highQuality)
   151             {
   152                 graphics.SmoothingMode = SmoothingMode.AntiAlias;
   153                 graphics.CompositingQuality = CompositingQuality.AssumeLinear;
   154                 graphics.PixelOffsetMode = PixelOffsetMode.Default;
   155                 graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
   156             }
   157             else
   158             {
   159                 graphics.SmoothingMode = SmoothingMode.HighSpeed;
   160                 graphics.CompositingQuality = CompositingQuality.HighSpeed;
   161                 graphics.PixelOffsetMode = PixelOffsetMode.None;
   162                 graphics.TextRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit;
   163             }
   164         }
   165     }
   166 }