Пример #1
0
        /// <summary>
        /// Used for debugging purposes.
        /// </summary>
        public static void Print(TextWriter writer, TriangleFilter f)
        {
            for (int i = 0; i < f.leftEdge; ++i)
            {
                if (i != 0)
                {
                    writer.Write(", ");
                }
                writer.Write("0");
            }

            for (int i = 0; i < f.size; ++i)
            {
                writer.Write(", " + f.FilterData[i].ToString("0.000", CultureInfo.InvariantCulture));
            }
        }
Пример #2
0
        /// <summary>
        /// Creates a new MelFilterBank.
        /// </summary>
        /// <param name="minFreq">The minimum frequency in hz to be considered, i.e.
        /// the left edge of the first TriangleFilter.</param>
        /// <param name="maxFreq">The maximum frequency in hz to be considered, i.e.
        /// the right edge of the last TriangleFilter.</param>
        /// <param name="numMelBands">The number of Mel bands to be calculated, i.e.
        /// the number of TriangleFilters to be applied.</param>
        /// <param name="numBins">The number of bins that are present in the fft_buffer
        /// that will be passed to the MelFilterBank.Apply method. This is also
        /// required to properly configure the TriangleFilter instances which
        /// operate on array indices only. (half the window size)</param>
        /// <param name="sampleRate">The original sample rate the FFT buffer which will
        /// be passed to MelFilterBank.Apply is based on.</param>
        /// <param name="doNormalizeFilterArea">If set to "true", the area of the
        /// created TriangleFilter will be normalized, e.g. the height of the
        /// filter's triangle shape will be configured in a way, that the area
        /// of the triangle shape equals one.</param>
        public MelFilterBank(double minFreq, double maxFreq, int numMelBands, int numBins, int sampleRate, bool doNormalizeFilterArea)
        {
            this.minFreq               = minFreq;
            this.maxFreq               = maxFreq;
            this.numMelBands           = numMelBands;
            this.numBins               = numBins;
            this.sampleRate            = sampleRate;
            this.doNormalizeFilterArea = doNormalizeFilterArea;

            // Let's do some argument checking
            if ((minFreq >= maxFreq) || (maxFreq == 0))
            {
                throw new ArgumentException(String.Format("Invalid min/max frequencies for MelFilterBank: min = '{0}' max = '{1}'", minFreq, maxFreq));
            }

            if (numMelBands == 0)
            {
                throw new ArgumentException(String.Format("Invalid number of mel bands for MelFilterBank: n = {0}", numMelBands));
            }

            if (sampleRate == 0)
            {
                throw new ArgumentException(String.Format("Invalid sample rate for MelFilterBank: s = {0}", sampleRate));
            }

            if (numBins == 0)
            {
                throw new ArgumentException(String.Format("Invalid number of bins for MelFilterBank: s = '{0}'", numBins));
            }

            // 2 * numBins should be the same as window length
            double deltaFreq = (double)sampleRate / (2 * numBins);

            double melMin = MelUtils.LinToMelFreq(minFreq);
            double melMax = MelUtils.LinToMelFreq(maxFreq);

            // We divide by #band + 1 as min / max should present the beginning / end
            // of beginng up / ending low slope, i.e. it's not the centers of each
            // band that represent min/max frequency in mel bands.
            double deltaFreqMel = (melMax - melMin) / (numMelBands + 1);

            // Fill up equidistant spacing in mel-space
            double melLeft = melMin;

            for (int i = 0; i < numMelBands; i++)
            {
                double melCenter = melLeft + deltaFreqMel;
                double melRight  = melCenter + deltaFreqMel;

                double leftHz  = MelUtils.MelToLinFreq(melLeft);
                double rightHz = MelUtils.MelToLinFreq(melRight);

                // align to closest num_bins (round)
                int leftBin  = (int)((leftHz / deltaFreq) + 0.5);
                int rightBin = (int)((rightHz / deltaFreq) + 0.5);

                // calculate normalized height
                double height = 1.0;

                if (doNormalizeFilterArea)
                {
                    height = 2.0 / (rightBin - leftBin);
                }

                // Create the actual filter
                var filter = new TriangleFilter(leftBin, rightBin, height);
                filters.Add(filter);

                // next left edge is current center
                melLeft = melCenter;
            }
        }