예제 #1
0
        /// <summary>
        /// Return a list of freq/gain, at the ERB centers
        /// Assuming you smoothed the data...
        /// </summary>
        /// <param name="data">data from ERB.smooth</param>
        /// <param name="sr">sample rate</param>
        /// <param name="scaleFactor">1.0 for ~38 bands.  0.5 for twice as many...</param>
        /// <returns></returns>
        public static FilterProfile profile(double[] data, uint sr, double scaleFactor)
        {
            FilterProfile pts = new FilterProfile();
            int           dl  = data.Length;

            for (double j = 1; j < ERB.ERBVal(sr / 2) + 1; j += scaleFactor)
            {
                double f = ERB.invERBVal(j);
                double n = f * 2 * dl / sr;
                if (n < dl)
                {
                    double g = data[(int)n];
                    pts.Add(new FreqGain(f, g));
                }
            }
            return(pts);
        }
예제 #2
0
        public static double WindowLength(int bin, int bins, double sampleRate, SmoothingType type, double resolution, out int bin0, out int bin1)
        {
            double len = 0;

            bin0 = bin;
            bin1 = bin;

            // Frequency (Hz) of the center of the given bin:
            // Bins range from 0 through sampleRate-1,
            // so the width of each bin is (sampleRate/bins) Hz,
            // and the center of bin <N> is (<N> * (sampleRate/bins)) + half a bin
            double binw = sampleRate / bins;
            double freq = (0.5 + bin) * binw;

            // The window goes from f0=(freq/X) to f1=(freq*X)
            // where the width of the window is (resolution)*(octaves or ERB bands)
            double bw = 0;

            if (type == SmoothingType.OCTAVE)
            {
                // Fraction X of an octave is f(x) = 2^x
                bw = freq * Math.Pow(2, resolution);
            }
            else if (type == SmoothingType.ERB)
            {
                bw = ERB.ERBWidth(freq) * resolution;
            }

            // f.x - f/x = bw
            // f.x.x - bw.x - f = 0
            // f.x.(x-(bw/f)) = f
            // x.(x-(bw/f)) = 1
            // x.x - bw.x - 1/

            if (type == SmoothingType.OCTAVE)
            {
                // One octave is frequency*2.  Two is freq*4.
                // Fraction X of an octave is f(x) = 2^x
//                double f1 = freq * (1 - Math.Pow(2, r2));
//                double f2 = freq * (1 - Math.Pow(2, r2));
            }

            return(len * resolution);
        }
예제 #3
0
        public static double bin2f(double bin, uint sr)
        {
            double scale = (_bins / ERB.ERBVal(sr / 2));

            return(ERB.invERBVal(bin / scale));
        }
예제 #4
0
        public static double f2bin(double f, uint sr)
        {
            double scale = (_bins / ERB.ERBVal(sr / 2));

            return(ERB.ERBVal(f) * scale);
        }
예제 #5
0
        private static double[] magbands(ISoundObj impulse, double bins)
        {
            uint nSR  = impulse.SampleRate;
            uint nSR2 = nSR / 2;

            int nn = (int)bins + 1;

            double[] muff = new double[nn];

            ushort nChannels = impulse.NumChannels;

            for (ushort c = 0; c < nChannels; c++)
            {
                // Read channel into a buffer
                SingleChannel channel = impulse.Channel(c);
                SoundBuffer   buff    = new SoundBuffer(channel);
                buff.ReadAll();

                // And then double in length to prevent wraparound
                buff.PadTo(buff.Count * 2);
                // Pad to next higher power of two
                buff.PadToPowerOfTwo();
                // Read out into array of complex
                Complex[][] data  = buff.ToComplexArray();
                Complex[]   cdata = data[0];

                // Then we're done with the buffer for this channel
                buff = null;
                GC.Collect();

                // FFT in place
                Fourier.FFT(cdata.Length, cdata);

                int n = cdata.Length / 2;

                // Drop the FFT magnitudes into the 'muff' array
                // according to an ERB-based scale (near-logarithmic).
                // Then smoothing is easy.
                double binw    = (nSR2 / (double)n);
                int    prevbin = 0;
                int    nbin    = 0;
                double v       = 0;
                for (int j = 0; j < n; j++)
                {
                    double f   = (double)j * binw;             // equiv freq, Hz
                    int    bin = (int)ERB.f2bin(f, nSR, bins); // the bin we drop this sample in
                    v += cdata[j].Magnitude;
                    nbin++;

                    if ((bin > prevbin) || (j == n - 1))
                    {
                        muff[prevbin] += (v / nbin);
                        v              = 0;
                        nbin           = 0;
                        prevbin        = bin;
                    }
                }
            }

            // Now muff is sum(all channels) of average-magnitude-per-bin.
            // Divide it all by the number of channels, so our gains are averaged...
            for (int j = 0; j < muff.Length; j++)
            {
                muff[j] = muff[j] / nChannels;
            }

            return(muff);
        }