Esempio n. 1
0
        ////////////////////////////////////////////////////////////////////////////////
        //
        //  Function:       createDeemphasisFilter
        //
        //  Arguments:      length:         Filter kernel length.
        //                  sampleRate:     System sample rate in Hertz. Must
        //									be greater than 0.
        //                  doAnalysis:     If set to true, this function will
        //                                  calculate and print the filter response.
        //                  correctPhase:   If set to true, this function corrects the
        //                                  phase distortion produced by the pre-
        //                                  emphasis filter.
        //
        //  Returns:        Returns a pointer to a struct containing pointer to the
        //					filter kernel plus other information
        //
        //  Description:    This function creates a filter kernel that implements
        //                  the de-emphasis filter needed to compensate for the pre-
        //                  emphasis filtering that is present on some CD recordings.
        //                  The filter will correct the frequency response of the input
        //                  to produce an output that should have a spectrum identical
        //                  to the original recording before an emphasis filter was
        //                  applied. If the correctPhase switch is set to true, then
        //                  the phase is also corrected; if not, a linear phase filter
        //                  is created.
        //
        ////////////////////////////////////////////////////////////////////////////////

        public static Deemphasis createDeemphasisFilter(int length, double sampleRate,
                                                        bool correctPhase, bool doAnalysis)
        {
            // Make sure the length of the filter is at least 8 samples
            if (length < 8)
            {
                throw new ArgumentOutOfRangeException("length", "" + length);
            }

            // Make sure the length of the filter is power of 2
            if (!Utility.isPowerOf2(length))
            {
                throw new ArgumentOutOfRangeException("length", "" + length);
            }

            // Make sure the sample rate is greater than 0
            if (sampleRate <= 0)
            {
                throw new ArgumentOutOfRangeException("sampleRate", "" + sampleRate);
            }

            // Calculate the bin size
            double binSize = sampleRate / (double)length;

            // Make sure the binsize is > 0 and <= 1/4 of the sample rate. This
            // guarantees at least 3 data points when calculating the filter
            // response, i.e. at DC, nyquist/2, and nyquist.
            if ((binSize <= 0) || (binSize > sampleRate / 4))
            {
                throw new ArgumentOutOfRangeException("binSize", "" + binSize);
            }

            // Allocate memory for the deemphasis filter struct
            Deemphasis deemphasis = new Deemphasis(length, sampleRate, binSize,
                                                   correctPhase, doAnalysis);

            // Calculate the ideal frequency response of the de-emphasis filter
            deemphasis.idealFilterResponse =
                IdealResponse.calculateIdealResponse(length, sampleRate);

            // Create the de-emphasis filter kernel, using the ideal filter response
            deemphasis.filterKernel =
                createFilterKernel(deemphasis.idealFilterResponse,
                                   deemphasis.correctPhase);

            // If we are doing analysis, then calculate the response and deviation
            // of this filter kernel, and print out the results
            if (deemphasis.doAnalysis)
            {
                // Calculate the actual filter response
                //deemphasis.actualFilterResponse =
                //    IdealResponse.calculateIdealResponse(deemphasis.filterKernel,
                //                            sampleRate, binSize);

                // Calculate and print out deviations for
                // amplitude (dB), phase Delay (s), group delay (s)
                //deemphasis.deviation = Deviation.calculateDeviation(deemphasis);
            }

            // Return a pointer to the newly created deemphasis struct
            return(deemphasis);
        }
Esempio n. 2
0
        ////////////////////////////////////////////////////////////////////////////////
        //
        //  Function:       calculateDeviation
        //
        //  Arguments:      deemphasisFilter:     A pointer to a calculated deemphasis
        //                                        filter.
        //
        //  Returns:        A pointer to a deviation struct.
        //
        //  Description:    This function calculates the deviation between the ideal
        //                  deemphasis filter response and the actual deemphasis filter
        //                  response embodied in the calculated filter kernel. In
        //                  particular, the deviation of the amplitude response (in dB),
        //                  phase delay (in seconds), and group delay (in seconds) is
        //                  calculated.
        //
        ////////////////////////////////////////////////////////////////////////////////

        public static Deviation calculateDeviation(Deemphasis deemphasisFilter)
        {
            int length;

            // Make sure we have valid pointers
            if (deemphasisFilter == null)
            {
                throw new ArgumentNullException("deemphasisFilter");
            }
            if (deemphasisFilter.idealFilterResponse == null)
            {
                throw new ArgumentNullException("deemphasisFilter.idealFilterResponse");
            }
            if (deemphasisFilter.actualFilterResponse == null)
            {
                throw new ArgumentNullException("deemphasisFilter.actualFilterResponse");
            }
            if (deemphasisFilter.idealFilterResponse.frequency == null)
            {
                throw new ArgumentNullException("deemphasisFilter.idealFilterResponse.frequency");
            }
            if (deemphasisFilter.idealFilterResponse.amplitudeDB == null)
            {
                throw new ArgumentNullException("deemphasisFilter.idealFilterResponse.amplitudeDB");
            }
            if (deemphasisFilter.idealFilterResponse.phaseDelay == null)
            {
                throw new ArgumentNullException("deemphasisFilter.idealFilterResponse.phaseDelay");
            }
            if (deemphasisFilter.idealFilterResponse.groupDelay == null)
            {
                throw new ArgumentNullException("deemphasisFilter.idealFilterResponse.groupDelay");
            }
            if (deemphasisFilter.actualFilterResponse.frequency == null)
            {
                throw new ArgumentNullException("deemphasisFilter.actualFilterResponse.frequency");
            }
            if (deemphasisFilter.actualFilterResponse.amplitudeDB == null)
            {
                throw new ArgumentNullException("deemphasisFilter.actualFilterResponse.amplitudeDB");
            }
            if (deemphasisFilter.actualFilterResponse.phaseDelay == null)
            {
                throw new ArgumentNullException("deemphasisFilter.actualFilterResponse.phaseDelay");
            }
            if (deemphasisFilter.actualFilterResponse.groupDelay == null)
            {
                throw new ArgumentNullException("deemphasisFilter.actualFilterResponse.groupDelay");
            }

            // Allocate memory for the deviation struct
            Deviation deviation = new Deviation();

            // Calculate the length of the deviation vectors
            length = deemphasisFilter.actualFilterResponse.frequency.Length;

            // Copy the frequency vector from the actual filter response
            deviation.frequency = (double[])deemphasisFilter.actualFilterResponse.frequency.Clone();

            // Create the deviation vectors
            deviation.amplitudeDB = new double[length];
            deviation.phaseDelay  = new double[length];
            deviation.groupDelay  = new double[length];

            // Calculate the position of the DC component in the ideal filter
            // response vectors
            int DCIndex =
                (deemphasisFilter.idealFilterResponse.amplitudeDB.Length / 2) - 1;

            // Calculate the amplitude deviation
            for (int i = 0, j = DCIndex; i < length; i++, j++)
            {
                deviation.amplitudeDB[i] =
                    deemphasisFilter.actualFilterResponse.amplitudeDB[i] -
                    deemphasisFilter.idealFilterResponse.amplitudeDB[j];
            }

            // Record the minimum and maximum amplitude deviations
            deviation.amplitudeDeviationMin = deviation.amplitudeDB.Min();
            deviation.amplitudeDeviationMax = deviation.amplitudeDB.Max();

            // Calculate the phase delay deviation
            // First calculate the offset at f = 0
            double offset =
                deemphasisFilter.actualFilterResponse.phaseDelay[0] -
                deemphasisFilter.idealFilterResponse.phaseDelay[DCIndex];

            // Then calculate the deviation for each element
            for (int i = 0, j = DCIndex; i < length; i++, j++)
            {
                deviation.phaseDelay[i] =
                    deemphasisFilter.actualFilterResponse.phaseDelay[i] -
                    deemphasisFilter.idealFilterResponse.phaseDelay[j] -
                    offset;
            }

            // Record the minimum and maximum phase delay deviations
            deviation.phaseDelayDeviationMin = deviation.phaseDelay.Min();
            deviation.phaseDelayDeviationMax = deviation.phaseDelay.Max();

            // Calculate the group delay deviation
            // First calculate the offset at f = 0
            offset =
                deemphasisFilter.actualFilterResponse.groupDelay[0] -
                deemphasisFilter.idealFilterResponse.groupDelay[DCIndex];

            // Then calculate the deviation for each element
            for (int i = 0, j = DCIndex; i < length; i++, j++)
            {
                deviation.groupDelay[i] =
                    deemphasisFilter.actualFilterResponse.groupDelay[i] -
                    deemphasisFilter.idealFilterResponse.groupDelay[j] -
                    offset;
            }

            // Record the minimum and maximum group delay deviations
            deviation.groupDelayDeviationMin = deviation.groupDelay.Min();
            deviation.groupDelayDeviationMax = deviation.groupDelay.Max();

            // Return a pointer to the newly calculated deviation structure
            return(deviation);
        }