예제 #1
0
        /// <summary>
        /// Method returns FIR bandpass (close to trapezoidal) filterbank based on given frequencies.
        /// </summary>
        /// <param name="fftSize">Assumed size of FFT</param>
        /// <param name="samplingRate">Assumed sampling rate of a signal</param>
        /// <param name="frequencies">Array of frequency tuples (left, center, right) for each filter</param>
        /// <param name="vtln">VTLN frequency warper</param>
        /// <param name="mapper">Frequency scale mapper (e.g. herz-to-mel)</param>
        /// <returns>Array of rectangular filters</returns>
        public static float[][] Trapezoidal(int fftSize,
                                            int samplingRate,
                                            Tuple <double, double, double>[] frequencies,
                                            VtlnWarper vtln = null,
                                            Func <double, double> mapper = null)
        {
            var filterBank = Rectangular(fftSize, samplingRate, frequencies, vtln, mapper);

            for (var i = 0; i < filterBank.Length; i++)
            {
                var filterTf = new TransferFunction(DesignFilter.Fir(fftSize / 4 + 1, filterBank[i]));

                filterBank[i] = filterTf.FrequencyResponse(fftSize).Magnitude.ToFloats();

                // normalize gain to 1.0

                var maxAmp = 0.0f;
                for (var j = 0; j < filterBank[i].Length; j++)
                {
                    if (filterBank[i][j] > maxAmp)
                    {
                        maxAmp = filterBank[i][j];
                    }
                }
                for (var j = 0; j < filterBank[i].Length; j++)
                {
                    filterBank[i][j] /= maxAmp;
                }
            }

            return(filterBank);
        }
예제 #2
0
        /// <summary>
        /// Method returns universal triangular filterbank weights based on given frequencies.
        /// </summary>
        /// <param name="fftSize">Assumed size of FFT</param>
        /// <param name="samplingRate">Assumed sampling rate of a signal</param>
        /// <param name="frequencies">Array of frequency tuples (left, center, right) for each filter</param>
        /// <param name="vtln">VTLN frequency warper</param>
        /// <param name="mapper">Frequency scale mapper (e.g. herz-to-mel) used here only for proper weighting</param>
        /// <returns>Array of triangular filters</returns>
        public static float[][] Triangular(int fftSize,
                                           int samplingRate,
                                           Tuple <double, double, double>[] frequencies,
                                           VtlnWarper vtln = null,
                                           Func <double, double> mapper = null)
        {
            if (mapper == null)
            {
                mapper = x => x;
            }
            Func <double, double> warp = vtln == null ? mapper : x => mapper(vtln.Warp(x));

            var herzResolution = (double)samplingRate / fftSize;

            var herzFrequencies = Enumerable.Range(0, fftSize / 2 + 1)
                                  .Select(f => f * herzResolution)
                                  .ToArray();

            var filterCount = frequencies.Length;
            var filterBank  = new float[filterCount][];

            for (var i = 0; i < filterCount; i++)
            {
                filterBank[i] = new float[fftSize / 2 + 1];

                var left   = warp(frequencies[i].Item1);
                var center = warp(frequencies[i].Item2);
                var right  = warp(frequencies[i].Item3);

                var j = 0;
                for (; mapper(herzFrequencies[j]) <= left; j++)
                {
                    ;
                }
                for (; mapper(herzFrequencies[j]) <= center; j++)
                {
                    filterBank[i][j] = (float)((mapper(herzFrequencies[j]) - left) / (center - left));
                }
                for (; j < herzFrequencies.Length && mapper(herzFrequencies[j]) < right; j++)
                {
                    filterBank[i][j] = (float)((right - mapper(herzFrequencies[j])) / (right - center));
                }
            }

            return(filterBank);
        }
예제 #3
0
        /// <summary>
        /// Method creates overlapping triangular mel filters (as suggested by Malcolm Slaney).
        /// </summary>
        /// <param name="erbFilterCount">Number of mel filters</param>
        /// <param name="fftSize">Assumed size of FFT</param>
        /// <param name="samplingRate">Assumed sampling rate</param>
        /// <param name="lowFreq">Lower bound of the frequency range</param>
        /// <param name="highFreq">Upper bound of the frequency range</param>
        /// <param name="normalizeGain">True if gain should be normalized; false if all filters should have same height 1.0</param>
        /// <param name="vtln">VTLN frequency warper</param>
        /// <returns>Array of mel filters</returns>
        public static float[][] MelBankSlaney(
            int filterCount, int fftSize, int samplingRate, double lowFreq = 0, double highFreq = 0, bool normalizeGain = true, VtlnWarper vtln = null)
        {
            if (lowFreq < 0)
            {
                lowFreq = 0;
            }
            if (highFreq <= lowFreq)
            {
                highFreq = samplingRate / 2.0;
            }

            var frequencies = UniformBands(Scale.HerzToMelSlaney, Scale.MelToHerzSlaney, filterCount, samplingRate, lowFreq, highFreq, true);

            var filterBank = Triangular(fftSize, samplingRate, frequencies, vtln);

            if (normalizeGain)
            {
                Normalize(filterCount, frequencies, filterBank);
            }

            return(filterBank);
        }