Пример #1
0
        //-----------------------------------------------------------------------------
        // SmoothingWithRecovery() carries out the spectral smoothing and spectral
        // recovery on the Cepstrum domain.
        //-----------------------------------------------------------------------------
        void SmoothingWithRecovery(double f0, int fs, ForwardRealFFT forwardRealFFT, InverseRealFFT inverseRealFFT, double[] spectralEnvelope)
        {
            var smoothingLifter    = new double[FFTSize];
            var compensationLifter = new double[FFTSize];

            smoothingLifter[0]    = 1;
            compensationLifter[0] = (1.0 - 2.0 * Q1) + 2.0 * Q1;
            for (int i = 1, limit = forwardRealFFT.FFTSize / 2; i <= limit; i++)
            {
                var quefrency = (double)i / fs;
                smoothingLifter[i]    = Math.Sin(Math.PI * f0 * quefrency) / (Math.PI * f0 * quefrency);
                compensationLifter[i] = (1.0 - 2.0 * Q1) + 2.0 * Q1 * Math.Cos(2.0 * Math.PI * quefrency * f0);
            }

            for (int i = 0, limit = FFTSize / 2; i <= limit; i++)
            {
                forwardRealFFT.Waveform[i] = Math.Log(forwardRealFFT.Waveform[i]);
            }
            for (int i = 1, limit = FFTSize / 2; i < limit; i++)
            {
                forwardRealFFT.Waveform[FFTSize - i] = forwardRealFFT.Waveform[i];
            }
            FFT.Execute(forwardRealFFT.ForwardFFT);

            for (int i = 0, limit = FFTSize / 2; i <= limit; i++)
            {
                inverseRealFFT.Spectrum[i] = new Complex(forwardRealFFT.Spectrum[i].Real * smoothingLifter[i] * compensationLifter[i] / FFTSize, 0.0);
            }
            FFT.Execute(inverseRealFFT.InverseFFT);

            for (int i = 0, limit = FFTSize / 2; i <= limit; i++)
            {
                spectralEnvelope[i] = Math.Exp(inverseRealFFT.Waveform[i]);
            }
        }
Пример #2
0
        public void Synthesize(double[] f0, int f0Length, double[][] spectrogram, double[][] aperiodicity, int fftSize, double framePeriod, int fs, double[] y)
        {
            var minimumPhase   = MinimumPhaseAnalysis.Create(fftSize);
            var inverseRealFFT = InverseRealFFT.Create(fftSize);
            var forwardRealFFT = ForwardRealFFT.Create(fftSize);

            var pulseLocations          = new double[y.Length];
            var pulseLocationsIndex     = new int[y.Length];
            var pulseLocationsTimeShift = new double[y.Length];
            var interpolatedVUV         = new double[y.Length];
            var numberOfPulses          = GetTimeBase(f0, f0Length, fs, framePeriod / 1000.0, y.Length, fs / fftSize + 1.0, pulseLocations, pulseLocationsIndex, pulseLocationsTimeShift, interpolatedVUV);

            var dcRemover = GetDCRemover(fftSize);

            framePeriod /= 1000.0;

            var impulseResponse = new double[fftSize];

            for (var i = 0; i < numberOfPulses; i++)
            {
                var noiseSize = pulseLocationsIndex[Math.Min(numberOfPulses - 1, i + 1)] - pulseLocationsIndex[i];

                GetOneFrameSegment(interpolatedVUV[pulseLocationsIndex[i]], noiseSize, spectrogram, fftSize, aperiodicity, f0Length, framePeriod, pulseLocations[i], pulseLocationsTimeShift[i], fs, forwardRealFFT, inverseRealFFT, minimumPhase, dcRemover, impulseResponse);

                for (var j = 0; j < fftSize; j++)
                {
                    var index = j + pulseLocationsIndex[i] - fftSize / 2 + 1;
                    if (index < 0 || index > y.Length - 1)
                    {
                        continue;
                    }
                    y[index] += impulseResponse[j];
                }
            }
        }
Пример #3
0
        public void Estimate(double[] x, int fs, double[] temporalPositions, double[] f0, int f0Length, int fftSize, double[][] aperiodicity)
        {
            aperiodicity.ForEach((a) => a.Fill(1.0 - SafeGuardMinimum));

            var fftSizeD4C = (int)Math.Pow(2.0, 1.0 + (int)MathUtil.Log2(4.0 * fs / FloorF0D4C + 1.0));

            var forwardRealFFT = ForwardRealFFT.Create(fftSizeD4C);

            var numberOfAperiodicities = (int)(Math.Min(UpperLimit, fs / 2.0 - FrequencyInterval) / FrequencyInterval);

            // Since the window function is common in D4CGeneralBody(),
            // it is designed here to speed up.
            var windowLength = (int)(FrequencyInterval * fftSizeD4C / fs) * 2 + 1;
            var window       = new double[windowLength];

            Common.NuttallWindow(windowLength, window);

            // D4C Love Train (Aperiodicity of 0 Hz is given by the different algorithm)
            var aperiodicity0 = new double[f0Length];

            D4CLoveTrain(x, fs, f0, f0Length, temporalPositions, aperiodicity0);

            var coarseAperiodicity = new double[numberOfAperiodicities + 2];

            coarseAperiodicity[0] = -60.0;
            coarseAperiodicity[numberOfAperiodicities + 1] = -SafeGuardMinimum;
            var coarseFrequencyAxis = Enumerable.Range(0, numberOfAperiodicities + 2).Select((i) => i * FrequencyInterval).ToArray();

            coarseFrequencyAxis[numberOfAperiodicities + 1] = fs / 2.0;

            var frequencyAxis = Enumerable.Range(0, fftSize / 2 + 1).Select((i) => (double)i * fs / fftSize).ToArray();

            for (var i = 0; i < f0Length; i++)
            {
                if (f0[i] == 0.0 || aperiodicity0[i] <= Threshold)
                {
                    continue;
                }

                D4CGeneralBody(x, fs, Math.Max(FloorF0D4C, f0[i]), fftSizeD4C, temporalPositions[i], numberOfAperiodicities, window, forwardRealFFT, coarseAperiodicity.SubSequence(1));

                // Linear interpolation to convert the coarse aperiodicity into its
                // spectral representation.
                GetAperiodicity(coarseFrequencyAxis, coarseAperiodicity, numberOfAperiodicities, frequencyAxis, fftSize, aperiodicity[i]);
            }
        }
Пример #4
0
        void GetNoiseSpectrum(int noiseSize, int fftSize, ForwardRealFFT forwardRealFFT)
        {
            var waveform = forwardRealFFT.Waveform;

            for (var i = 0; i < noiseSize; i++)
            {
                waveform[i] = Rand.Next();
            }

            var average = noiseSize > 0 ? waveform.Take(noiseSize).Average() : 1.0;

            for (var i = 0; i < noiseSize; i++)
            {
                waveform[i] -= average;
            }
            Array.Clear(waveform, noiseSize, fftSize - noiseSize);
            FFT.Execute(forwardRealFFT.ForwardFFT);
        }
Пример #5
0
        //-----------------------------------------------------------------------------
        // GetPowerSpectrum() calculates the power_spectrum with DC correction.
        // DC stands for Direct Current. In this case, the component from 0 to F0 Hz
        // is corrected.
        //-----------------------------------------------------------------------------
        void GetPowerSpectrum(int fs, double f0, ForwardRealFFT forwardRealFFT)
        {
            var halfWindowLength = MatlabFunctions.MatlabRound(1.5 * fs / f0);

            // FFT
            Array.Clear(forwardRealFFT.Waveform, halfWindowLength * 2 + 1, FFTSize - halfWindowLength * 2 - 1);
            FFT.Execute(forwardRealFFT.ForwardFFT);

            var powerSpectrum = forwardRealFFT.Waveform;
            var spectrum      = forwardRealFFT.Spectrum;

            for (int i = 0, limit = FFTSize / 2; i <= limit; i++)
            {
                powerSpectrum[i] = spectrum[i].Real * spectrum[i].Real + spectrum[i].Imaginary * spectrum[i].Imaginary;
            }

            Common.DCCorrection(powerSpectrum, f0, fs, FFTSize, powerSpectrum);
        }
Пример #6
0
        public SynthesisRealTime(int sampleRate, double framePeriod, int fftSize, int bufferSize, int ringBufferCapacity)
        {
            SampleRate      = sampleRate;
            FramePeriod     = framePeriod * 0.001;
            AudioBufferSize = bufferSize;
            AudioBuffer     = new double[bufferSize * 2 + fftSize];
            Buffer          = new RingBuffer(ringBufferCapacity);
            FFTSize         = fftSize;

            ImpulseResponse = new double[fftSize];
            DCRemover       = GetDCRemover(fftSize / 2);

            RefreshSynthesizer();

            MinimumPhase   = MinimumPhaseAnalysis.Create(fftSize);
            InverseRealFFT = InverseRealFFT.Create(fftSize);
            ForwardRealFFT = ForwardRealFFT.Create(fftSize);
        }
Пример #7
0
        public void Estimate(double[] x, int fs, double[] temporalPositions, double[] f0, double[][] spectrogram)
        {
            var f0Floor          = GetF0FloorForCheapTrick(fs, FFTSize);
            var spectralEnvelope = new double[FFTSize];

            var forwardRealFFT = ForwardRealFFT.Create(FFTSize);
            var inverseRealFFT = InverseRealFFT.Create(FFTSize);

            for (var i = 0; i < f0.Length; i++)
            {
                var currentF0 = f0[i] <= f0Floor ? DefaultF0 : f0[i];
                CheapTrickGeneralBody(x, fs, currentF0, temporalPositions[i], forwardRealFFT, inverseRealFFT, spectralEnvelope);

                for (int j = 0, limit = FFTSize / 2; j <= limit; j++)
                {
                    spectrogram[i][j] = spectralEnvelope[j];
                }
            }
        }
Пример #8
0
        //-----------------------------------------------------------------------------
        // D4CLoveTrain() determines the aperiodicity with VUV detection.
        // If a frame was determined as the unvoiced section, aperiodicity is set to
        // very high value as the safeguard.
        // If it was voiced section, the aperiodicity of 0 Hz is set to -60 dB.
        //-----------------------------------------------------------------------------
        void D4CLoveTrain(double[] x, int fs, double[] f0, int f0Length, double[] temporalPositions, double[] aperiodicity0)
        {
            var lowestF0       = 40.0;
            var fftSize        = (int)Math.Pow(2.0, 1.0 + (int)MathUtil.Log2(3.0 * fs / lowestF0 + 1));
            var forwardRealFFT = ForwardRealFFT.Create(fftSize);

            // Cumulative powers at 100, 4000, 7900 Hz are used for VUV identification.
            var boundary0 = (int)Math.Ceiling(100.0 * fftSize / fs);
            var boundary1 = (int)Math.Ceiling(4000.0 * fftSize / fs);
            var boundary2 = (int)Math.Ceiling(7900.0 * fftSize / fs);

            for (var i = 0; i < f0Length; i++)
            {
                if (f0[i] == 0.0)
                {
                    aperiodicity0[i] = 0.0;
                    continue;
                }

                aperiodicity0[i] = D4CLoveTrainSub(x, fs, Math.Max(f0[i], lowestF0), temporalPositions[i], f0Length, fftSize, boundary0, boundary1, boundary2, forwardRealFFT);
            }
        }
Пример #9
0
        static void FastFFTFilt(double[] x, double[] h, int fftSize, ForwardRealFFT forwardRealFFT, InverseRealFFT inverseRealFFT, double[] y)
        {
            for (var i = 0; i < x.Length; i++)
            {
                forwardRealFFT.Waveform[i] = x[i] / fftSize;
            }
            if (x.Length < fftSize)
            {
                Array.Clear(forwardRealFFT.Waveform, x.Length, fftSize - x.Length);
            }
            FFT.Execute(forwardRealFFT.ForwardFFT);
            var xSpectrum = new Complex[fftSize];

            Array.Copy(forwardRealFFT.Spectrum, xSpectrum, fftSize / 2 + 1);

            for (var i = 0; i < h.Length; i++)
            {
                forwardRealFFT.Waveform[i] = h[i] / fftSize;
            }
            if (h.Length < fftSize)
            {
                Array.Clear(forwardRealFFT.Waveform, h.Length, fftSize - h.Length);
            }
            FFT.Execute(forwardRealFFT.ForwardFFT);

            for (var i = fftSize / 2 + 1; i > -1; i--)
            {
                inverseRealFFT.Spectrum[i] = new Complex(
                    xSpectrum[i].Real * forwardRealFFT.Spectrum[i].Real - xSpectrum[i].Imaginary * forwardRealFFT.Spectrum[i].Imaginary,
                    xSpectrum[i].Real * forwardRealFFT.Spectrum[i].Imaginary + xSpectrum[i].Imaginary * forwardRealFFT.Spectrum[i].Real
                    );
            }
            FFT.Execute(inverseRealFFT.InverseFFT);

            inverseRealFFT.Waveform.BlockCopy(0, y, 0, fftSize);
        }
Пример #10
0
        //-----------------------------------------------------------------------------
        // D4CGeneralBody() calculates a spectral envelope at a temporal
        // position. This function is only used in D4C().
        // Caution:
        //   forward_fft is allocated in advance to speed up the processing.
        //-----------------------------------------------------------------------------
        void D4CGeneralBody(double[] x, int fs, double currentF0, int fftSize, double currentPosition, int numberOfAperiodicities, double[] window, ForwardRealFFT forwardRealFFT, SubSequence <double> coarseAperiodicity)
        {
            var staticCentroid        = new double[fftSize / 2 + 1];
            var smoothedPowerSpectrum = new double[fftSize / 2 + 1];
            var staticGroupDelay      = new double[fftSize / 2 + 1];

            GetStaticCentroid(x, fs, currentF0, fftSize, currentPosition, forwardRealFFT, staticCentroid);
            GetSmoothedPowerSpectrum(x, fs, currentF0, fftSize, currentPosition, forwardRealFFT, smoothedPowerSpectrum);
            GetStaticGroupDelay(staticCentroid, smoothedPowerSpectrum, fs, currentF0, fftSize, staticGroupDelay);

            GetCoarseAperiodicity(staticGroupDelay, fs, fftSize, numberOfAperiodicities, window, forwardRealFFT, coarseAperiodicity);

            // Revision of the result based on the F0
            for (var i = 0; i < numberOfAperiodicities; i++)
            {
                coarseAperiodicity[i] = Math.Min(0.0, coarseAperiodicity[i] + (currentF0 - 100) / 50.0);
            }
        }
Пример #11
0
        //-----------------------------------------------------------------------------
        // GetSmoothedPowerSpectrum() calculates the smoothed power spectrum.
        // The parameters used for smoothing are optimized in davance.
        //-----------------------------------------------------------------------------
        void GetSmoothedPowerSpectrum(double[] x, int fs, double currentF0, int fftSize, double currentPosition, ForwardRealFFT forwardRealFFT, double[] smoothedPowerSpectrum)
        {
            Array.Clear(forwardRealFFT.Waveform, 0, fftSize);
            GetWindowedWaveform(x, fs, currentF0, currentPosition, WindowType.Hanning, 4.0, forwardRealFFT.Waveform);

            FFT.Execute(forwardRealFFT.ForwardFFT);
            var spectrum = forwardRealFFT.Spectrum;

            for (int i = 0, limit = fftSize / 2; i <= limit; i++)
            {
                smoothedPowerSpectrum[i] = spectrum[i].Real * spectrum[i].Real + spectrum[i].Imaginary * spectrum[i].Imaginary;
            }
            Common.DCCorrection(smoothedPowerSpectrum, currentF0, fs, fftSize, smoothedPowerSpectrum);
            Common.LinearSmoothing(smoothedPowerSpectrum, currentF0, fs, fftSize, smoothedPowerSpectrum);
        }
Пример #12
0
        //-----------------------------------------------------------------------------
        // CheapTrickGeneralBody() calculates a spectral envelope at a temporal
        // position. This function is only used in CheapTrick().
        // Caution:
        //   forward_fft is allocated in advance to speed up the processing.
        //-----------------------------------------------------------------------------
        void CheapTrickGeneralBody(double[] x, int fs, double currentF0, double currentPosition, ForwardRealFFT forwardRealFFT, InverseRealFFT inverseRealFFT, double[] spectralEnvelope)
        {
            // F0-adaptive windowing
            GetWindowedWaveform(x, fs, currentF0, currentPosition, forwardRealFFT);

            // Calculate power spectrum with DC correction
            // Note: The calculated power spectrum is stored in an array for waveform.
            // In this imprementation, power spectrum is transformed by FFT (NOT IFFT).
            // However, the same result is obtained.
            // This is tricky but important for simple implementation.
            GetPowerSpectrum(fs, currentF0, forwardRealFFT);

            // Smoothing of the power (linear axis)
            // forward_real_fft.waveform is the power spectrum.
            Common.LinearSmoothing(forwardRealFFT.Waveform, currentF0 * 2.0 / 3.0, fs, FFTSize, forwardRealFFT.Waveform);

            // Add infinitesimal noise
            // This is a safeguard to avoid including zero in the spectrum.
            AddInfinitesimalNoise(forwardRealFFT.Waveform, FFTSize, forwardRealFFT.Waveform);

            // Smoothing (log axis) and spectral recovery on the cepstrum domain.
            SmoothingWithRecovery(currentF0, fs, forwardRealFFT, inverseRealFFT, spectralEnvelope);
        }
Пример #13
0
        //-----------------------------------------------------------------------------
        // GetStaticCentroid() calculates the temporally static energy centroid.
        // Basic idea was proposed by H. Kawahara.
        //-----------------------------------------------------------------------------
        void GetStaticCentroid(double[] x, int fs, double currentF0, int fftSize, double currentPosition, ForwardRealFFT forwardRealFFT, double[] staticCentroid)
        {
            var centroid1 = new double[fftSize / 2 + 1];
            var centroid2 = new double[fftSize / 2 + 1];

            GetCentroid(x, fs, currentF0, fftSize, currentPosition - 0.25 / currentF0, forwardRealFFT, centroid1);
            GetCentroid(x, fs, currentF0, fftSize, currentPosition + 0.25 / currentF0, forwardRealFFT, centroid2);

            for (int i = 0, limit = fftSize / 2; i <= limit; i++)
            {
                staticCentroid[i] = centroid1[i] + centroid2[i];
            }

            Common.DCCorrection(staticCentroid, currentF0, fs, fftSize, staticCentroid);
        }
Пример #14
0
        //-----------------------------------------------------------------------------
        // GetWindowedWaveform() windows the waveform by F0-adaptive window
        //-----------------------------------------------------------------------------
        void GetWindowedWaveform(double[] x, int fs, double currentF0, double currentPosition, ForwardRealFFT forwardRealFFT)
        {
            var halfWindowLength = MatlabFunctions.MatlabRound(1.5 * fs / currentF0);

            var baseIndex = new int[halfWindowLength * 2 + 1];
            var safeIndex = new int[halfWindowLength * 2 + 1];
            var window    = new double[halfWindowLength * 2 + 1];

            SetParametersForGetWindowedWaveform(halfWindowLength, x.Length, currentPosition, fs, currentF0, baseIndex, safeIndex, window);

            // F0-adaptive windowing
            var waveForm = forwardRealFFT.Waveform;

            for (int i = 0, limit = halfWindowLength * 2; i <= limit; i++)
            {
                waveForm[i] = x[safeIndex[i]] * window[i] + Rand.Next() * SafeGuardMinimum;
            }

            var tmpWeight1           = waveForm.Take(halfWindowLength * 2 + 1).Sum();
            var tmpWeight2           = window.Sum();
            var weightingCoefficient = tmpWeight1 / tmpWeight2;

            for (int i = 0, limit = halfWindowLength * 2; i <= limit; i++)
            {
                waveForm[i] -= window[i] * weightingCoefficient;
            }
        }
Пример #15
0
        void GetCentroid(double[] x, int fs, double currentF0, int fftSize, double currentPosition, ForwardRealFFT forwardRealFFT, double[] centroid)
        {
            Array.Clear(forwardRealFFT.Waveform, 0, fftSize);
            GetWindowedWaveform(x, fs, currentF0, currentPosition, WindowType.Blackman, 4.0, forwardRealFFT.Waveform);

            var windowRange = MatlabFunctions.MatlabRound(2.0 * fs / currentF0) * 2;
            var power       = Math.Sqrt(forwardRealFFT.Waveform.Take(windowRange).Sum((w) => w * w));

            for (var i = 0; i <= windowRange; i++)
            {
                forwardRealFFT.Waveform[i] /= power;
            }

            FFT.Execute(forwardRealFFT.ForwardFFT);
            var tmpSpectrum = new Complex[fftSize / 2 + 1];

            Array.Copy(forwardRealFFT.Spectrum, tmpSpectrum, tmpSpectrum.Length);

            for (var i = 0; i < fftSize; i++)
            {
                forwardRealFFT.Waveform[i] *= i + 1.0;
            }
            FFT.Execute(forwardRealFFT.ForwardFFT);
            var spectrum = forwardRealFFT.Spectrum;

            for (int i = 0, limit = fftSize / 2; i <= limit; i++)
            {
                centroid[i] = spectrum[i].Real * tmpSpectrum[i].Real + spectrum[i].Imaginary * tmpSpectrum[i].Imaginary;
            }
        }
Пример #16
0
        //-----------------------------------------------------------------------------
        // GetAperiodicResponse() calculates an aperiodic response.
        //-----------------------------------------------------------------------------
        void GetAperiodicResponse(int noiseSize, int fftSize, double[] spectrum, double[] aperiodicRatio, double currentVUV, ForwardRealFFT forwardRealFFT, InverseRealFFT inverseRealFFT, MinimumPhaseAnalysis minimumPhase, double[] aperiodicResponse)
        {
            GetNoiseSpectrum(noiseSize, fftSize, forwardRealFFT);

            var logSpectrum = minimumPhase.LogSpectrum;

            if (currentVUV != 0.0)
            {
                for (int i = 0, limit = minimumPhase.FFTSize / 2; i <= limit; i++)
                {
                    logSpectrum[i] = Math.Log(spectrum[i] * aperiodicRatio[i]) / 2.0;
                }
            }
            else
            {
                for (int i = 0, limit = minimumPhase.FFTSize / 2; i <= limit; i++)
                {
                    logSpectrum[i] = Math.Log(spectrum[i]) / 2.0;
                }
            }
            Common.GetMinimumPhaseSpectrum(minimumPhase);

            var minimumPhaseSpectrum = minimumPhase.MinimumPhaseSpectrum;

            Array.Copy(minimumPhaseSpectrum, 0, inverseRealFFT.Spectrum, 0, fftSize / 2 + 1);
            for (int i = 0, limit = fftSize / 2; i <= limit; i++)
            {
                var real      = minimumPhaseSpectrum[i].Real * forwardRealFFT.Spectrum[i].Real - minimumPhaseSpectrum[i].Imaginary * forwardRealFFT.Spectrum[i].Imaginary;
                var imaginary = minimumPhaseSpectrum[i].Real * forwardRealFFT.Spectrum[i].Imaginary + minimumPhaseSpectrum[i].Imaginary * forwardRealFFT.Spectrum[i].Real;

                inverseRealFFT.Spectrum[i] = new Complex(real, imaginary);
            }
            FFT.Execute(inverseRealFFT.InverseFFT);
            MatlabFunctions.FFTShift(inverseRealFFT.Waveform.SubSequence(0, fftSize), aperiodicResponse);
        }
Пример #17
0
        double D4CLoveTrainSub(double[] x, int fs, double currentF0, double currentPosition, int f0Length, int fftSize, int boundary0, int boundary1, int boundary2, ForwardRealFFT forwardRealFFT)
        {
            var powerSpectrum = new double[fftSize];

            var windowLength = MatlabFunctions.MatlabRound(1.5 * fs / currentF0) * 2 + 1;

            GetWindowedWaveform(x, fs, currentF0, currentPosition, WindowType.Blackman, 3.0, forwardRealFFT.Waveform);

            Array.Clear(forwardRealFFT.Waveform, windowLength, fftSize - windowLength);
            FFT.Execute(forwardRealFFT.ForwardFFT);

            var spectrum = forwardRealFFT.Spectrum;

            for (int i = boundary0 + 1, limit = fftSize / 2 + 1; i < limit; i++)
            {
                powerSpectrum[i] = spectrum[i].Real * spectrum[i].Real + spectrum[i].Imaginary * spectrum[i].Imaginary;
            }
            for (var i = boundary0; i <= boundary2; i++)
            {
                powerSpectrum[i] += powerSpectrum[i - 1];
            }

            return(powerSpectrum[boundary1] / powerSpectrum[boundary2]);
        }
Пример #18
0
        //-----------------------------------------------------------------------------
        // GetOneFrameSegment() calculates a periodic and aperiodic response at a time.
        //-----------------------------------------------------------------------------
        void GetOneFrameSegment(double currentVUV, int noiseSize, double[][] spectrogram, int fftSize, double[][] aperiodicity, int f0Length, double framePeriod, double currentTime, double fractionalTimeShift, int fs, ForwardRealFFT forwardRealFFT, InverseRealFFT inverseRealFFT, MinimumPhaseAnalysis minimumPhase, double[] dcRemover, double[] response)
        {
            var aperiodicResponse = new double[fftSize];
            var periodicResponse  = new double[fftSize];

            var spectralEnvelope = new double[fftSize];
            var aperiodicRatio   = new double[fftSize];

            GetSpectralEnvelope(currentTime, framePeriod, f0Length, spectrogram, fftSize, spectralEnvelope);
            GetAperiodicRatio(currentTime, framePeriod, f0Length, aperiodicity, fftSize, aperiodicRatio);

            // Synthesis of the periodic response
            GetPeriodicResponse(fftSize, spectralEnvelope, aperiodicRatio, currentVUV, inverseRealFFT, minimumPhase, dcRemover, fractionalTimeShift, fs, periodicResponse);

            // Synthesis of the aperiodic response
            GetAperiodicResponse(noiseSize, fftSize, spectralEnvelope, aperiodicRatio, currentVUV, forwardRealFFT, inverseRealFFT, minimumPhase, aperiodicResponse);

            var sqrtNoiseSize = Math.Sqrt(noiseSize);

            for (var i = 0; i < fftSize; i++)
            {
                response[i] = (periodicResponse[i] * sqrtNoiseSize + aperiodicResponse[i]) / fftSize;
            }
        }
Пример #19
0
        //-----------------------------------------------------------------------------
        // GetCoarseAperiodicity() calculates the aperiodicity in multiples of 3 kHz.
        // The upper limit is given based on the sampling frequency.
        //-----------------------------------------------------------------------------
        private void GetCoarseAperiodicity(double[] staticGroupDelay, int fs, int fftSize, int numberOfAperiodicities, double[] window, ForwardRealFFT forwardRealFFT, SubSequence <double> coarseAperiodicity)
        {
            var boundary         = MatlabFunctions.MatlabRound(fftSize * 8.0 / window.Length);
            var halfWindowLength = window.Length / 2;

            Array.Clear(forwardRealFFT.Waveform, 0, fftSize);

            var powerSpectrum = new double[fftSize / 2 + 1];

            for (var i = 0; i < numberOfAperiodicities; i++)
            {
                var center = (int)(FrequencyInterval * (i + 1) * fftSize / fs);
                for (int j = 0, limit = halfWindowLength * 2; j <= limit; j++)
                {
                    forwardRealFFT.Waveform[j] = staticGroupDelay[center - halfWindowLength + j] * window[j];
                }
                FFT.Execute(forwardRealFFT.ForwardFFT);

                var spectrum = forwardRealFFT.Spectrum;
                for (int j = 0, limit = fftSize / 2; j <= limit; j++)
                {
                    powerSpectrum[j] = spectrum[j].Real * spectrum[j].Real + spectrum[j].Imaginary * spectrum[j].Imaginary;
                }

                Array.Sort(powerSpectrum);
                for (int j = 1, limit = fftSize / 2; j <= limit; j++)
                {
                    powerSpectrum[j] += powerSpectrum[j - 1];
                }

                coarseAperiodicity[i] = 10.0 * Math.Log10(powerSpectrum[fftSize / 2 - boundary - 1] / powerSpectrum[fftSize / 2]);
            }
        }