예제 #1
0
        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);
        }
예제 #2
0
        public Bitmap CreateSpectrogramLine(Size size, Color foregroundColor, Color backgroundColor, bool highQuality)
        {
            if (!UpdateFrequencyMappingIfNessesary(size))
            {
                return(null);
            }

            var fftBuffer = new float[(int)FftSize];

            if (SpectrumProvider.GetFftData(fftBuffer, this))
            {
                using (var foregroundPen = new Pen(foregroundColor))
                    using (var backgroundPen = new Pen(backgroundColor))
                    {
                        var bitmap = _previousBitmap == null ? new Bitmap(size.Width, (int)FftSize) : new Bitmap(_previousBitmap, size.Width, (int)FftSize);

                        using (Graphics graphics = Graphics.FromImage(bitmap))
                        {
                            PrepareGraphics(graphics, highQuality);

                            if (_previousBitmap == null)
                            {
                                graphics.Clear(backgroundColor);
                            }

                            DrawSpectrogramLine(graphics, foregroundPen, backgroundPen, fftBuffer, size);
                        }

                        _previousBitmap = bitmap;
                        return(new Bitmap(bitmap, size));
                    }
            }
            return(null);
        }
예제 #3
0
        public void InitialiseAudioProgram()
        {
            _soundIn = new WasapiLoopbackCapture();
            _soundIn.Initialize();

            var           soundInSource = new SoundInSource(_soundIn);
            ISampleSource source        = soundInSource.ToSampleSource();

            var spectrumProvider = new SpectrumProvider(2, 48000, FftSize.Fft4096);

            _spectrum = new LineSpectrum(spectrumProvider, _barCount);
            var notificationSource = new SingleBlockNotificationStream(source);

            notificationSource.SingleBlockRead += (s, a) => spectrumProvider.Add(a.Left, a.Right);

            _source = notificationSource.ToWaveSource(16);

            // Read from the source otherwise SingleBlockRead is never called
            byte[] buffer = new byte[_source.WaveFormat.BytesPerSecond / 2];
            soundInSource.DataAvailable += (src, evt) =>
            {
                int read;
                while ((read = _source.Read(buffer, 0, buffer.Length)) > 0)
                {
                    ;
                }
            };

            _soundIn.Start();

            for (int i = 0; i < MatrixCount; i++)
            {
                _Programs[i] = i == 0 ? AudioSequence().GetEnumerator() : null;
            }
        }
예제 #4
0
        public void Load(Uri uri)
        {
            Dispose();
            _uri        = uri;
            _waveSource = CSCore.Codecs.CodecFactory.Instance.GetCodec(_uri)
                          .ToSampleSource()
                          .ToMono()
                          .ToWaveSource();

            spectrumProvider = new BasicSpectrumProvider(_waveSource.WaveFormat.Channels,
                                                         _waveSource.WaveFormat.SampleRate,
                                                         CSCore.DSP.FftSize.Fft4096);

            //the SingleBlockNotificationStream is used to intercept the played samples
            var notificationSource = new SingleBlockNotificationStream(_waveSource.ToSampleSource());

            //pass the intercepted samples as input data to the spectrumprovider (which will calculate a fft based on them)
            notificationSource.SingleBlockRead += (s, a) => SpectrumProvider.Add(a.Left, a.Right);
            _waveSource = notificationSource.ToWaveSource(16);
            // Load the sample source
            var ws = CSCore.Codecs.CodecFactory.Instance.GetCodec(_uri);

            _sampleSource = ws.ToSampleSource();
            RaiseSourceEvent(SourceEventType.Loaded);
            hasMedia = true;
            LoadSoundOut();
        }
예제 #5
0
        private void TimerTick(object state)
        {
            // This is a loop for the life of the source that reports things like
            // position back to a subscriber.
            if (_waveSource != null)
            {
                if (Position != cachedPosition)
                {
                    // position has changed
                    cachedPosition = Position;
                    RaiseSourcePropertyChangedEvent(ESourceProperty.Position, cachedPosition);
                }

                if (_soundOut != null)
                {
                    if (PlaybackState != cachedPlaybackState)
                    {
                        cachedPlaybackState = PlaybackState;
                        RaiseSourcePropertyChangedEvent(ESourceProperty.PlaybackState, cachedPlaybackState);
                    }
                }

                if (SpectrumProvider != null && cachedPlaybackState == PlaybackState.Playing)
                {
                    fftData = new float[(int)fftSize];
                    SpectrumProvider.GetFftData(fftData);
                    RaiseSourcePropertyChangedEvent(ESourceProperty.FftData, FftData);
                }
            }
        }
예제 #6
0
        /// <summary>
        /// Initializes a new RLSpectrum instance
        /// </summary>
        /// <param name="game"></param>
        /// <param name="provider"></param>
        /// <param name="fftSize"></param>
        public RLSpectrum(MainGame game, SpectrumProvider provider, FftSize fftSize) : base(fftSize)
        {
            this.game = game;

            SpectrumProvider = provider;
            UseAverage       = true;
            Resolution       = MatrixResolution + LowCut + HighCut;
            IsXLogScale      = true;
            ScalingStrategy  = ScalingStrategy.Decibel;

            effect = new BasicEffect(game.GraphicsDevice)
            {
                DiffuseColor = RetroPurple.ToVector3()
            };

            random = new Random();

            matrix = new RLMatrix(game, MatrixNumEntries, MatrixResolution);

            linePlot = new RLLinePlot(MatrixResolution, LineCache, RetroPurple);

            carTexture     = game.Content.Load <Texture2D>("Images/Octane");
            messageTexture = game.Content.Load <Texture2D>("Images/Message");
            spriteFont     = game.Content.Load <SpriteFont>("Fonts/Lazer84");

            car = new RLCar(carTexture, RetroBlue, random);

            countdown        = new RLCountdown(spriteFont, RetroRed);
            countdown.Alarm += CountdownAlarm;

            constrainedPoints = new SpectrumPointData[MatrixResolution];

            globalHook          = Hook.GlobalEvents();
            globalHook.KeyDown += KeyDown;
        }
예제 #7
0
        public float[] livelyGetSystemAudioSpectrum()
        {
            var fftBuffer = new float[(int)FftSize];

            if (SpectrumProvider.GetFftData(fftBuffer, this))
            {
                //return fftBuffer;
            }
            else
            {
                System.Diagnostics.Debug.WriteLine("livelygetspectrum error");
                return(null);
            }

            int height = CurrentSize.Height;

            SpectrumPointData[] dats = CalculateSpectrumPoints(2, fftBuffer);
            float[]             res  = new float[dats.Length];
            for (int i = 0; i < dats.Length; i++)
            {
                res[i] = (float)dats[i].Value;
            }

            return(res);
        }
예제 #8
0
        public void Draw()
        {
            var fftBuffer = new float[FftSize];

            if (!SpectrumProvider.GetFftData(fftBuffer, this))
            {
                return;
            }

            var spectrumPoints = CalculateSpectrumPoints(MatrixPanel.Height, fftBuffer);

            for (var x = 0; x < spectrumPoints.Count; x++)
            {
                var height = (int)Math.Round(spectrumPoints[x].Value * Amplifier);

                using (var brush = new LinearGradientBrush(new Rectangle(x, 0, 1, MatrixPanel.Height), ColorHelper.HsvToColor((byte)(Hue + 32)), ColorHelper.HsvToColor(Hue), LinearGradientMode.Vertical))
                {
                    Frame.Graphics.FillRectangle(brush, x, MatrixPanel.Height - height, 1, height);
                }



                //                using (var brush = new LinearGradientBrush(new Rectangle(x, 0, 1, MatrixPanel.Height), Color.Red, Color.Green, LinearGradientMode.Vertical))
                //                {
                //                    Frame.Graphics.FillRectangle(brush, x, MatrixPanel.Height - height, 1, height);
                //                }
            }

            Hue++;
        }
예제 #9
0
 public bool GetFftData(float[] fftDataBuffer)
 {
     if (SpectrumProvider == null)
     {
         return(false);
     }
     return(SpectrumProvider.GetFftData(fftDataBuffer));
 }
예제 #10
0
        public double[] CreateSpectrumData()
        {
            var fftBuffer = new float[(int)FftSize];

            if (SpectrumProvider.GetFftData(fftBuffer, this))
            {
                return(GetSpectrumPointData(fftBuffer, 100).Select(x => x.Value).ToArray());
            }
            return(new double[50]);
        }
예제 #11
0
        public void CreateSpectrumLine(int type)
        {
            var fftBuffer = new float[(int)FftSize];

            //get the fft result from the spectrum provider
            if (!SpectrumProvider.GetFftData(fftBuffer, this))
            {
                return;
            }
            CreateSpectrumLineInternal(fftBuffer, type);
        }
예제 #12
0
        public List <double> GetLineValues(double height)
        {
            var fftBuffer = new float[(int)FftSize];

            // get the fft result from the spectrum provider
            if (!SpectrumProvider.GetFftData(fftBuffer, this))
            {
                return(null);
            }

            var spectrumPoints = CalculateSpectrumPoints(height, fftBuffer);

            return(spectrumPoints?.Select(s => s.Value).ToList());
        }
예제 #13
0
        public double?GetValue()
        {
            var fftBuffer = new float[(int)FftSize];

            // get the fft result from the spectrum provider
            if (SpectrumProvider == null || !SpectrumProvider.GetFftData(fftBuffer, this))
            {
                return(null);
            }

            var spectrumPoints = CalculateSpectrumPoints(1, fftBuffer);

            return(spectrumPoints[0].Value);
        }
예제 #14
0
 private unsafe void ProcessFrameOutput(AudioFrame frame)
 {
     using (var buffer = frame.LockBuffer(AudioBufferAccessMode.Read))
         using (var reference = buffer.CreateReference())
         {
             // Get hold of the buffer pointer.
             ((IMemoryBufferByteAccess)reference).GetBuffer(out var dataInBytes, out var capacityInBytes);
             var dataInFloat = (float *)dataInBytes;
             for (var n = 0; n < _audioGraph.SamplesPerQuantum; n += 2)
             {
                 SpectrumProvider.Add(dataInFloat[n], dataInFloat[n + 1]);
             }
         }
 }
예제 #15
0
        void SetupSampleSource(ISampleSource sampleSource)
        {
            FftSize fftSize = FftSize.Fft4096;

            SpectrumProvider spectrumProvider = new SpectrumProvider(sampleSource.WaveFormat.Channels,
                sampleSource.WaveFormat.SampleRate, fftSize);

            //spectrum = new BlobSpectrum(this, spectrumProvider, FftSize.Fft4096);
            spectrum = new RLSpectrum(this, spectrumProvider, FftSize.Fft4096);

            SingleBlockNotificationStream notificationSource = new SingleBlockNotificationStream(sampleSource);
            notificationSource.SingleBlockRead += (s, a) => spectrumProvider.Add(a.Left, a.Right);

            source = notificationSource.ToWaveSource(16);
        }
예제 #16
0
        public bool CreateVoicePrint3D(Graphics graphics, RectangleF clipRectangle, float xPos, Color background,
                                       float lineThickness = 1f)
        {
            if (!_isInitialized)
            {
                UpdateFrequencyMapping();
                _isInitialized = true;
            }

            var fftBuffer = new float[(int)FftSize];

            //get the fft result from the spectrumprovider
            if (SpectrumProvider.GetFftData(fftBuffer, this))
            {
                //prepare the fft result for rendering
                var spectrumPoints = CalculateSpectrumPoints(1.0, fftBuffer);
                using (var pen = new Pen(background, lineThickness))
                {
                    var currentYOffset = clipRectangle.Y + clipRectangle.Height;

                    //render the fft result
                    for (var i = 0; i < spectrumPoints.Length; i++)
                    {
                        var p = spectrumPoints[i];

                        var xCoord      = clipRectangle.X + xPos;
                        var pointHeight = clipRectangle.Height / spectrumPoints.Length;

                        //get the color based on the fft band value
                        pen.Color = _colorCalculator.GetColor((float)p.Value);

                        var p1 = new PointF(xCoord, currentYOffset);
                        var p2 = new PointF(xCoord, currentYOffset - pointHeight);

                        graphics.DrawLine(pen, p1, p2);

                        currentYOffset -= pointHeight;
                    }
                }

                return(true);
            }

            return(false);
        }
        public double[] GetPointData(double multiplier)
        {
            float[] fftBuffer = new float[(int)FftSize];

            SpectrumProvider.GetFftData(fftBuffer, this);

            SpectrumPointData[] spectrumPoints = CalculateSpectrumPoints(multiplier, fftBuffer);

            double[] values = new double[spectrumPoints.Length];

            for (int i = 0; i < spectrumPoints.Length; i++)
            {
                SpectrumPointData p = spectrumPoints[i];
                values[i] = p.Value;
            }

            return(values);
        }
예제 #18
0
        /// <summary>
        /// Calculate the colors
        /// </summary>
        protected override bool GetColors(Graphics graphics, float lineThickness)
        {
            if (!m_IsInitialized)
            {
                UpdateFrequencyMapping();
                m_IsInitialized = true;
            }

            var fftBuffer = new float[(int)Analyzer.FFTSize];

            //get the fft result from the spectrumprovider
            if (SpectrumProvider.GetFftData(fftBuffer, this))
            {
                //prepare the fft result for rendering
                SpectrumPointData[] spectrumPoints = CalculateSpectrumPoints(1.0, fftBuffer);
                using (var pen = new System.Drawing.Pen(ColorPalette.PanelBG_Drawing, lineThickness))
                {
                    float currentYOffset = m_Bitmap.Size.Height;

                    //render the fft result
                    for (int i = 0; i < spectrumPoints.Length; i++)
                    {
                        SpectrumPointData p = spectrumPoints[i];

                        float xCoord      = m_Position;
                        float pointHeight = (float)m_Bitmap.Size.Height / (float)spectrumPoints.Length;

                        //get the color based on the fft band value
                        double value = p.Value * m_Multiplier;

                        pen.Color = Utils.Lerp(ColorPalette.PanelBG, ColorPalette.Accent, value);

                        var p1 = new PointF(xCoord, currentYOffset);
                        var p2 = new PointF(xCoord, currentYOffset - pointHeight);

                        graphics.DrawLine(pen, p1, p2);

                        currentYOffset -= pointHeight;
                    }
                }
                return(true);
            }
            return(false);
        }
예제 #19
0
        public float[] GetSpectrumData(double maxValue)
        {
            // Get spectrum data internal
            var fftBuffer = new float[(int)FftSize];

            UpdateFrequencyMapping();

            if (SpectrumProvider.GetFftData(fftBuffer, this))
            {
                SpectrumPointData[] spectrumPoints = CalculateSpectrumPoints(maxValue, fftBuffer);

                // Convert to float[]
                List <float> spectrumData = new List <float>();
                spectrumPoints.ToList().ForEach(point => spectrumData.Add((float)point.Value));
                return(spectrumData.ToArray());
            }

            return(null);
        }
예제 #20
0
        public void CreateSpectrum()
        {
            var fftBuffer = new float[(int)FftSize];

            SpectrumProvider.GetFftData(fftBuffer, this);
            SpectrumPointData[] spectrumPoints = CalculateSpectrumPoints(255, fftBuffer);
            if (spectrumPoints[0].Value > 0)
            {
                Mode.Colors[0].SetR(CalculateScale(spectrumPoints[0].Value));
            }
            if (spectrumPoints[1].Value > 0)
            {
                Mode.Colors[0].SetG(CalculateScale(spectrumPoints[1].Value));
            }
            if (spectrumPoints[2].Value > 0)
            {
                Mode.Colors[0].SetB(CalculateScale(spectrumPoints[2].Value));
            }
        }
예제 #21
0
        public float[] livelyGetSystemAudioSpectrum()
        {
            System.Globalization.CultureInfo customCulture = (System.Globalization.CultureInfo)System.Threading.Thread.CurrentThread.CurrentCulture.Clone();
            customCulture.NumberFormat.NumberDecimalSeparator = ".";

            System.Threading.Thread.CurrentThread.CurrentCulture = customCulture;

            var fftBuffer = new float[(int)FftSize];

            if (SpectrumProvider.GetFftData(fftBuffer, this))
            {
                //return fftBuffer;
            }
            else
            {
                //System.Diagnostics.Debug.WriteLine("livelygetspectrum error");
                //return fftBuffer;
                //return null;
            }

            //return fftBuffer;

            for (int i = 0; i < fftBuffer.Length; i++)
            {
                //fftBuffer[i] /= 100;
                //Debug.Write(fftBuffer[i] + " ");
            }

            int height = CurrentSize.Height;

            SpectrumPointData[] dats = CalculateSpectrumPoints(2, fftBuffer);
            float[]             res  = new float[dats.Length];
            for (int i = 0; i < dats.Length; i++)
            {
                res[i] = (float)dats[i].Value;
                //System.Diagnostics.Debug.WriteLine(res[i]);
                //res[i] = (float)dats[i].Value - 1;
            }

            return(res);
        }
예제 #22
0
        public void LoadFile(string filePath, int resoulution = 9, FftSize fftSize = FftSize.Fft256)
        {
            var source = CodecFactory.Instance.GetCodec(filePath).ToSampleSource();

            NotificationStream = new SingleBlockNotificationStream(source);
            NotificationStream.SingleBlockRead += (s, a) =>
            {
                SpectrumProvider.Add(a.Left, a.Right);
            };

            SpectrumProvider = new BasicSpectrumProvider(source.WaveFormat.Channels, source.WaveFormat.SampleRate, fftSize);
            Spectrum         = new SpectrumBase()
            {
                SpectrumProvider   = SpectrumProvider,
                SpectrumResolution = resoulution,
                MaximumFrequency   = 20000,
                MinimumFrequency   = 20,
                ScalingStrategy    = ScalingStrategy.Linear,
                UseAverage         = true,
            };
        }
예제 #23
0
        public bool CreateVoicePrint3D(Graphics graphics, RectangleF clipRectangle, float xPos, Color background,
                                       float lineThickness = 1f)
        {
            if (!_isInitialized)
            {
                UpdateFrequencyMapping();
                _isInitialized = true;
            }

            var fftBuffer = new float[(int)FftSize];

            if (SpectrumProvider.GetFftData(fftBuffer, this))
            {
                SpectrumPointData[] spectrumPoints = CalculateSpectrumPoints(1.0, fftBuffer);
                using (var pen = new Pen(background, lineThickness))
                {
                    float currentYOffset = clipRectangle.Y + clipRectangle.Height;

                    for (int i = 0; i < spectrumPoints.Length; i++)
                    {
                        SpectrumPointData p = spectrumPoints[i];

                        float xCoord      = clipRectangle.X + xPos;
                        float pointHeight = clipRectangle.Height / spectrumPoints.Length;

                        pen.Color = _colorCalculator.GetColor((float)p.Value);
                        //pen.Color = Color.FromArgb(255, pen.Color.R, pen.Color.G, pen.Color.B);

                        var p1 = new PointF(xCoord, currentYOffset);
                        var p2 = new PointF(xCoord, currentYOffset - pointHeight);

                        graphics.DrawLine(pen, p1, p2);

                        currentYOffset -= pointHeight;
                    }
                }
                return(true);
            }
            return(false);
        }
예제 #24
0
        public List <TimeSpectrumData> GenerateSpectrumDataNewWay(int stepDurationMs = 10, int smoothnessWindow = 3)
        {
            var streamLength = NotificationStream.Length;
            var samples = new float[32 * 1024];
            int samplesRead = -1, totalSamplesRead = 0;

            var result = new List <TimeSpectrumData>();

            NotificationStream.Position = 0;
            while (NotificationStream.Position < streamLength)
            {
                var lastTimeRead = NotificationStream.GetMilliseconds(NotificationStream.Position);

                while (NotificationStream.GetMilliseconds(NotificationStream.Position) - lastTimeRead < stepDurationMs & samplesRead != 0)
                {
                    samplesRead = NotificationStream.Read(samples, 0, samples.Length);
                }

                for (int i = 0; i < samplesRead; i += NotificationStream.WaveFormat.Channels)
                {
                    SpectrumProvider.Add(samples[i], NotificationStream.WaveFormat.Channels > 1 ? samples[i + 1] : 0);

                    if (NotificationStream.GetMilliseconds(totalSamplesRead + i) - lastTimeRead >= stepDurationMs)
                    {
                        result.Add(GetTimeSpectrumData());
                        lastTimeRead = NotificationStream.GetMilliseconds(totalSamplesRead + i);
                    }
                }

                totalSamplesRead += samplesRead;
                if (samplesRead == 0)
                {
                    break;
                }
            }

            SmoothDataAcrossTime(result, smoothnessWindow);
            return(result);
        }
예제 #25
0
        private void TimerTick(object state)
        {
            if (_waveSource != null)
            {
                if (recordingState == RecordingState.Recording)
                {
                    if (Position - TimeSpan.FromMilliseconds(50) > cachedPosition)
                    //if (Position != cachedPosition)
                    {
                        // position has changed
                        cachedPosition = Position;
                        RaiseSourcePropertyChangedEvent(SourceProperty.Position, cachedPosition);
                    }
                }

                if (SpectrumProvider != null && recordingState == RecordingState.Recording)
                {
                    fftData = new float[(int)fftSize];
                    SpectrumProvider.GetFftData(fftData);
                    RaiseSourcePropertyChangedEvent(SourceProperty.FftData, FftData);
                }
            }
        }
예제 #26
0
        public float[] GetSpectrumData(double maxValue, int bandIndex)
        {
            // Get spectrum data internal
            if (fftBuffer == null)
            {
                fftBuffer = new float[(int)FftSize];
            }

            UpdateFrequencyMapping(bandIndex);

            SpectrumProvider.GetFftData(fftBuffer, this);

            SpectrumPointData[] spectrumPoints = CalculateSpectrumPoints(maxValue, fftBuffer, bandIndex);

            // Convert to float[]
            List <float> spectrumData = new List <float>();

            spectrumPoints.ToList().
            ForEach
            (
                point =>
            {
                float val = (float)point.Value;
                if (_BandFrecuencies.TryGetValue(bandIndex, out var filterList))
                {
                    foreach (var filter in filterList)
                    {
                        val = filter.Process(val);
                    }
                }

                spectrumData.Add(val);
            }
            );
            return(spectrumData.ToArray());
        }
예제 #27
0
 /// <summary>
 /// Update our math.
 /// </summary>
 /// <returns></returns>
 public bool Update()
 {
     return(SpectrumProvider.GetFftData(iFftBuffer, this));
 }
예제 #28
0
        public bool CreateVoicePrint3D(Graphics graphics, RectangleF clipRectangle, float xPos, Color background, DrawPurpose dp,
                                       float lineThickness = 1f)
        {
            if (!_isInitialized)
            {
                UpdateFrequencyMapping();
                _isInitialized = true;
            }

            var fftBuffer = new float[(int)FftSize];

            //get the fft result from the spectrumprovider
            if (SpectrumProvider.GetFftData(fftBuffer, this))
            {
                SpectrumPointData[] spectrumPoints;
                //prepare the fft result for rendering
                switch (dp)
                {
                case DrawPurpose.ForAnalog:
                    spectrumPoints = CalculateSpectrumPoints(0.99, fftBuffer);
                    break;

                case DrawPurpose.ForDigitalBass:
                    spectrumPoints = CalculateSpectrumPoints(0.99, fftBuffer, bassFactor, BassFactorSqrt);
                    break;

                case DrawPurpose.ForDigitalMedio:
                    spectrumPoints = CalculateSpectrumPoints(0.99, fftBuffer, medioFactor, MedioFactorSqrt);
                    break;

                case DrawPurpose.ForDigitalTreble:
                    spectrumPoints = CalculateSpectrumPoints(0.99, fftBuffer, trebleFactor, trebleFactorSqrt);
                    break;

                case DrawPurpose.ForGeneric:
                    spectrumPoints = CalculateSpectrumPoints(0.99, fftBuffer);
                    break;

                default:
                    spectrumPoints = CalculateSpectrumPoints(0.99, fftBuffer);
                    break;
                }


                using (var pen = new Pen(background, lineThickness))
                {
                    float currentYOffset = clipRectangle.Y + clipRectangle.Height;

                    //render the fft result
                    for (int i = 0; i < spectrumPoints.Length; i++)
                    {
                        SpectrumPointData p = spectrumPoints[i];

                        float xCoord      = clipRectangle.X + xPos;
                        float pointHeight = clipRectangle.Height / spectrumPoints.Length;

                        //get the color based on the fft band value
                        pen.Color = _colorCalculator.GetColor((float)p.Value);

                        switch (dp)
                        {
                        case DrawPurpose.ForAnalog:
                            FirmataModule.SoundSpectrumColor = pen.Color;
                            break;

                        case DrawPurpose.ForDigitalBass:
                            FirmataModule.DigitalSpectrumPattern[0] = pen.Color;
                            break;

                        case DrawPurpose.ForDigitalMedio:
                            FirmataModule.DigitalSpectrumPattern[1] = pen.Color;
                            break;

                        case DrawPurpose.ForDigitalTreble:
                            FirmataModule.DigitalSpectrumPattern[2] = pen.Color;
                            break;

                        case DrawPurpose.ForGeneric:
                            break;

                        default:
                            break;
                        }


                        var p1 = new PointF(xCoord, currentYOffset);
                        var p2 = new PointF(xCoord, currentYOffset - pointHeight);

                        graphics.DrawLine(pen, p1, p2);

                        currentYOffset -= pointHeight;
                    }
                }
                return(true);
            }
            return(false);
        }
예제 #29
0
    // { 0, 500, 500, 2000, 2000, 4000, 4000, 8000, 8000, 16000, 16000, 22000 };
    public static void analyse(DecoderInterface decoder)
    {
        loadingProgress = 0;
        abortAnalysis = false;
        // For finding the volume levels
        List<int> volumeLevelList = new List<int> ();
        float rollingAverage = 0.01f;
        float alpha = 0.15f;
        int activePart = -1;
        int sampleCounter = 0;
        float totalMax = -1;

        // Get spectral flux
        SpectrumProvider spectrumProvider = new SpectrumProvider (decoder, BUFFER_SIZE, HOP_SIZE, true);
        float[] spectrum = spectrumProvider.nextSpectrum ();
        float[] lastSpectrum = new float[spectrum.Length];
        List<List<float>> spectralFlux = new List<List<float>> ();
        for (int i = 0; i < bands.Length / 2; i++)
            spectralFlux.Add (new List<float> ());

        int bufferCounter = 0;

        do {

            if(abortAnalysis) return;

            #region SPECTRAL ANALYSIS
            for (int i = 0; i < bands.Length; i+=2) {
                int startFreq = spectrumProvider.getFFT ().freqToIndex (bands [i]);
                int endFreq = spectrumProvider.getFFT ().freqToIndex (bands [i + 1]);
                float flux = 0;
                for (int j = startFreq; j <= endFreq; j++) {
                    float value = (spectrum [j] - lastSpectrum [j]);
                    value = (value + Mathf.Abs (value)) / 2;
                    flux += value;
                }
                (spectralFlux [i / 2]).Add (flux);
            }

            System.Array.Copy (spectrum, 0, lastSpectrum, 0, spectrum.Length);
            #endregion

            #region GET MAX SAMPLE
            foreach (float sample in spectrumProvider.getCurrentSamples()) {
                if (sample > totalMax)
                    totalMax = sample;
            }
            #endregion

            bufferCounter++;
            loadingProgress = 0.75f*(((bufferCounter*BUFFER_SIZE)/(float)AudioManager.frequency)/AudioManager.audioLength);

        } while( (spectrum = spectrumProvider.nextSpectrum() ) != null );

        #region VOLUME CLASSIFICATION
        DecoderInterface dec = spectrumProvider.getDecoder ();
        dec.reset ();

        float [] samples = new float[spectrumProvider.getWinSize ()];
        float factor = 1f / totalMax;
        List<float> decibelLevels = new List<float>();
        float avgDecibels = 0;

        float oldProgress = loadingProgress;

        while (dec.readSamples(ref samples) !=0) {

            if(abortAnalysis) return;

            float max = -1;

            /* Normalize the volume using the previously calculated factor */
            for (int i =0; i < samples.Length; i++) {
                samples [i] = Mathf.Abs (samples[i] * factor);
                if (samples [i] > max)
                    max = samples [i];
            }

            float db = Mathf.Abs(20*Mathf.Log10(max));
            if(max != 0) decibelLevels.Add(db);
            avgDecibels += db;

            rollingAverage = (alpha * max) + ((1 - alpha) * rollingAverage);

            // Have we found a part which classifies as extremely loud?
            if (rollingAverage > 0.82f) { //0.8

                // Are we already in that part?
                if (activePart != 5) {
                    activePart = 5; // Set flag that we are now in that part
                    volumeLevelList.Add (sampleCounter * spectrumProvider.getCurrentSamples ().Length);
                    volumeLevelList.Add (activePart);
                }

                // Have we found a part which classifies as damn loud?
            } else if (rollingAverage > 0.7f) { //0.6

                // Are we already in that part?
                if (activePart != 4) {
                    activePart = 4; // Set flag that we are now in that part
                    volumeLevelList.Add (sampleCounter * spectrumProvider.getCurrentSamples ().Length);
                    volumeLevelList.Add (activePart);
                }

                // Have we found a part which classifies as pretty loud?
            } else if (rollingAverage > 0.4f) { //0.2

                // Are we already in that part?
                if (activePart != 3) {
                    activePart = 3; // Set flag that we are now in that part
                    volumeLevelList.Add (sampleCounter * spectrumProvider.getCurrentSamples ().Length);
                    volumeLevelList.Add (activePart);
                }

                // Have we found a part which classifies as pretty normal?
            } else if (rollingAverage > 0.1f) { //0.0716

                // Are we already in that part?
                if (activePart != 2) {
                    activePart = 2; // Set flag that we are now in that part
                    volumeLevelList.Add (sampleCounter * spectrumProvider.getCurrentSamples ().Length);
                    volumeLevelList.Add (activePart);
                }

                // Have we found a part which classifies as pretty quiet?
            } else if (rollingAverage > 0.0016f) { //0.0016

                // Are we already in that part?
                if (activePart != 1) {
                    activePart = 1; // Set flag that we are now in that part
                    volumeLevelList.Add (sampleCounter * spectrumProvider.getCurrentSamples ().Length);
                    volumeLevelList.Add (activePart);
                }

                // Have we found a part which classifies as very quiet?
                // Below 40db (== below 0.06f amplitude)
            } else {

                // Are we already in that part?
                if (activePart != 0) {
                    activePart = 0; // Set flag that we are now in that part
                    volumeLevelList.Add (sampleCounter * spectrumProvider.getCurrentSamples ().Length);
                    volumeLevelList.Add (activePart);
                }
            }
            sampleCounter++;
            loadingProgress = oldProgress + 0.25f*(((sampleCounter*BUFFER_SIZE)/(float)AudioManager.frequency)/AudioManager.audioLength);
        }
        #endregion

        if(abortAnalysis) return;

        // Store volumelevels
        volumeLevels = volumeLevelList.ToArray ();
        volumeLevelList.Clear();
        volumeLevelList = null;

        #region SPECTRAL FLUX ANALYSIS
        // Convert spectral flux arraylist to array
        float[][] spectralFluxArray = new float[spectralFlux.Count][];
        for (int i = 0; i < spectralFluxArray.Length; i++) {
            spectralFluxArray [i] = spectralFlux [i].ToArray ();
        }
        spectralFlux.Clear ();
        spectralFlux = null;

        if(abortAnalysis) return;

        // Get thresholds
        float[][] thresholds = new float[bands.Length / 2][];
        float[][] prunnedSpectralFlux = new float[bands.Length / 2][];
        for (int i = 0; i < bands.Length / 2; i++) {
            float[] threshold = new ThresholdFunction (HISTORY_SIZE, multipliers [i]).calculate (spectralFluxArray [i]);
            thresholds [i] = threshold;

            float[] tempPSF = new float[spectralFluxArray [i].Length];
            for (int j = 0; j < spectralFluxArray[i].Length; j++) {
                if (threshold [j] <= spectralFluxArray [i] [j])
                    tempPSF [j] = spectralFluxArray [i] [j] - threshold [j];
                else
                    tempPSF [j] = 0;
            }
            prunnedSpectralFlux [i] = tempPSF;
        }
        thresholds = null;

        if(abortAnalysis) return;

        // Get Peaks
        List<int[]> peaksList = new List<int[]> ();
        float[] peakAvgs = new float[prunnedSpectralFlux.Length];
        float[] minPeaks = new float[prunnedSpectralFlux.Length];
        for (int i = 0; i < prunnedSpectralFlux.Length; i++) {

            List<int> tempPeaks = new List<int> ();
            minPeaks [i] = float.MaxValue;

            for (int j = 0; j < prunnedSpectralFlux[i].Length -1; j++) {
                if (prunnedSpectralFlux [i] [j] > prunnedSpectralFlux [i] [j + 1]) {
                    tempPeaks.Add (j);
                    peakAvgs [i] += prunnedSpectralFlux [i] [j];
                    if (prunnedSpectralFlux [i] [j] != 0 && prunnedSpectralFlux [i] [j] < minPeaks [i])
                        minPeaks [i] = prunnedSpectralFlux [i] [j];
                }
            }
            peaksList.Add (tempPeaks.ToArray ());
            peakAvgs [i] /= tempPeaks.Count;
        }

        if(abortAnalysis) return;

        // Save current peaks & reset list
        peaks = peaksList.ToArray ();
        peaksList.Clear ();

        // Lowpass filter the peaks
        for (int i = 0; i < peaks.Length; i++) {
            List<int> tempPeaks = new List<int> ();
            for (int j = 0; j < peaks[i].Length; j++) {
                if (prunnedSpectralFlux [i] [peaks [i] [j]] > minPeaks [i] + 0.7f * (peakAvgs [i] - minPeaks [i])) {
                    tempPeaks.Add (peaks [i] [j]);
                    tempPeaks.Add (Mathf.RoundToInt(prunnedSpectralFlux[i][peaks[i][j]]));
                }
            }
            peaksList.Add (tempPeaks.ToArray ());
        }
        peaks = peaksList.ToArray ();
        #endregion

        if(abortAnalysis) return;

        #region NORMALIZE PEAK INTENSITIES
        for(int i = 0; i < peaks.Length; i++) {
            float max = -1;
            for(int j = 1;j < peaks[i].Length; j+=2) {
                if(peaks[i][j] > max) max = peaks[i][j];
            }
            for(int j = 1;j < peaks[i].Length; j+=2) {
                peaks[i][j] = Mathf.RoundToInt(100f*(peaks[i][j]/max));
            }
        }
        #endregion

        if(abortAnalysis) return;

        #region VARIATION FACTOR
        float[] dbLvls = decibelLevels.ToArray();
        decibelLevels.Clear();
        decibelLevels = null;

        avgDecibels /= (float)dbLvls.Length;

        float stDev = 0;
        for (int i = 0; i < dbLvls.Length; i++) {
            stDev += (dbLvls[i] - avgDecibels) * (dbLvls[i] - avgDecibels);
        }

        stDev = Mathf.Sqrt (stDev / (float)dbLvls.Length);

        if(stDev > 25f) stDev = 25f;
        else if (stDev < 5f) stDev = 5f;

        stDev /= 25f;
        variationFactor = stDev;
        #endregion

        isAnalyzing = false;
    }