// Beat detection, algorithm put together by Ben Fisher after reading some things
        // numbers here are arbitrary, based on what seemed to work ok. I'm sure it could be better.
        public static double GuessBpm(WaveAudio input)
        {
            const double minBpm = 60, maxBpm = 150;

            WaveAudio w = Effects.Derivative(input); // take the derivative of samples.

            // divide samples into chunks of size 1024.
            int    nBufsize       = 1024;
            double chunkframerate = input.getSampleRate() / nBufsize; // the chunks go by at this rate.

            // do first FFT
            double[][] frequencyData = SpectrumContentOverTime(w, 4, nBufsize);

            // create a new signal in time, consisting of the energy at lowest 1/4 freqs of the chunks.
            int slength = (int)Fourier.findNearestPowerOfTwo((uint)frequencyData.Length);

            double[] lowerdata = new double[slength];
            for (int i = 0; i < slength; i++)
            {
                lowerdata[i] = frequencyData[i][0]; // the bottom 1/4 freqs (index 0-255,0Hz to 5512.5Hz  or something ?)
            }
            // now take a second FFT on this new signal. Frequency should be range 0.6 to 2.5 Hz (40 to 150 Bpm).
            double[] reout, imgout;
            RawSamplesToFrequency(lowerdata, out reout, out imgout);

            // only keep track of output inside the range we are interested in
            int minFreqindex = (int)(reout.Length * ((minBpm / 60) / chunkframerate));
            int maxFreqindex = (int)(reout.Length * ((maxBpm / 60) / chunkframerate));

            // find the best candidate
            double highestEnergy = -1; int highestEnergyIndex = -1;

            for (int b = minFreqindex; b < maxFreqindex; b++)
            {
                double magnitude = Math.Sqrt(reout[b] * reout[b] + imgout[b] + imgout[b]);
                if (magnitude > highestEnergy)
                {
                    highestEnergyIndex = b; highestEnergy = magnitude;
                }
            }
            double freqHertz = chunkframerate * (highestEnergyIndex / (double)reout.Length);
            double freqInBpm = freqHertz * 60;

            return(freqInBpm);
        }
Exemple #2
0
            public WaveAudio doModify(WaveAudio src, int bufsize)
            {
                WaveAudio wout = new WaveAudio(src.getSampleRate(), 1);

                wout.LengthInSamples = src.LengthInSamples;

                //reuse the buffers.
                double[] ffreqmaghalfout = new double[bufsize / 2], ffreqanghalfout = new double[bufsize / 2];
                double[] ffreqmaghalfin  = new double[bufsize / 2], ffreqanghalfin = new double[bufsize / 2];
                double[] fbuffertime     = new double[bufsize];
                for (int partnum = 0; partnum < src.LengthInSamples / bufsize; partnum++)
                {
                    //copy into buffer.
                    Array.Copy(src.data[0], partnum * bufsize, fbuffertime, 0, bufsize);
                    double[] ffreqreal, ffreqimag;
                    Fourier.RawSamplesToFrequency(fbuffertime, out ffreqreal, out ffreqimag);
                    //we only care about the first half of these results.
                    for (int i = 0; i < bufsize / 2; i++)
                    {
                        ffreqmaghalfin[i] = Math.Sqrt(ffreqreal[i] * ffreqreal[i] + ffreqimag[i] * ffreqimag[i]);
                        ffreqanghalfin[i] = Math.Atan2(ffreqimag[i], ffreqreal[i]);
                    }
                    this.modifyAngular(ffreqmaghalfin, ffreqanghalfin, ffreqmaghalfout, ffreqanghalfout);
                    if (partnum == 0)
                    {
                        this.drawPlots(ffreqmaghalfin, ffreqanghalfin, ffreqmaghalfout, ffreqanghalfout);
                    }
                    for (int i = 0; i < ffreqreal.Length / 2; i++)
                    {
                        ffreqreal[i] = ffreqmaghalfout[i] * Math.Sin(ffreqanghalfout[i]);
                        ffreqimag[i] = ffreqmaghalfout[i] * Math.Cos(ffreqanghalfout[i]);
                    }
                    for (int i = ffreqreal.Length / 2; i < ffreqreal.Length; i++)
                    {
                        ffreqreal[i] = ffreqimag[i] = 0;
                    }
                    double[] fbufout;
                    Fourier.RawFrequencyToSamples(out fbufout, ffreqreal, ffreqimag);
                    Array.Copy(fbufout, 0, wout.data[0], partnum * bufsize, bufsize);
                }
                return(wout);
            }
Exemple #3
0
            public WaveAudio doModify(WaveAudio src, int bufsize)
            {
                WaveAudio wout = new WaveAudio(src.getSampleRate(), 1);

                wout.LengthInSamples = src.LengthInSamples;

                //reuse the buffers.
                double[] ffreqmaghalfout = new double[bufsize / 2], ffreqanghalfout = new double[bufsize / 2];
                double[] ffreqmaghalfin  = new double[bufsize / 2], ffreqanghalfin = new double[bufsize / 2];
                double[] fbuffertime     = new double[bufsize];

                for (int index = 0; index < src.LengthInSamples - bufsize; index += bufsize / overlap)
                {
                    //copy into buffer.
                    Array.Copy(src.data[0], index, fbuffertime, 0, bufsize);
                    double[] ffreqreal, ffreqimag;
                    Fourier.RawSamplesToFrequency(fbuffertime, out ffreqreal, out ffreqimag);
                    //we only care about the first half of these results.
                    for (int i = 0; i < bufsize / 2; i++)
                    {
                        ffreqmaghalfin[i] = Math.Sqrt(ffreqreal[i] * ffreqreal[i] + ffreqimag[i] * ffreqimag[i]);
                        ffreqanghalfin[i] = Math.Atan2(ffreqimag[i], ffreqreal[i]);
                    }
                    this.modifyAngular(ffreqmaghalfin, ffreqanghalfin, ffreqmaghalfout, ffreqanghalfout);
                    for (int i = 0; i < ffreqreal.Length / 2; i++)
                    {
                        ffreqreal[i] = ffreqmaghalfout[i] * Math.Sin(ffreqanghalfout[i]);
                        ffreqimag[i] = ffreqmaghalfout[i] * Math.Cos(ffreqanghalfout[i]);
                    }
                    for (int i = ffreqreal.Length / 2; i < ffreqreal.Length; i++)
                    {
                        ffreqreal[i] = ffreqimag[i] = 0;
                    }
                    double[] fbufout;
                    Fourier.RawFrequencyToSamples(out fbufout, ffreqreal, ffreqimag);
                    WaveAudio ww = new WaveAudio(44100, 1);
                    ww.data[0] = fbufout;
                    //Array.Copy(fbufout, 0, wout.data[0], partnum*bufsize, bufsize);
                    ConstructionUtil.placeAudioRamp(wout, ww, index, (bufsize / overlapRamp));
                }
                return(wout);
            }