Esempio n. 1
0
        //-----------------------------------------------------------------------------
        // SetParametersForGetWindowedWaveform()
        //-----------------------------------------------------------------------------
        void SetParametersForGetWindowedWaveform(int halfWindowLength, int xLength, double currentPosition, int fs, double currentF0, int[] baseIndex, int[] safeIndex, double[] window)
        {
            for (var i = -halfWindowLength; i <= halfWindowLength; i++)
            {
                baseIndex[i + halfWindowLength] = i;
            }
            var origin = MatlabFunctions.MatlabRound(currentPosition * fs + 0.001);

            for (int i = 0, limit = halfWindowLength * 2; i <= limit; i++)
            {
                safeIndex[i] = Math.Min(xLength - 1, Math.Max(0, origin + baseIndex[i]));
            }

            var average = 0.0;

            for (int i = 0, limit = halfWindowLength * 2; i <= limit; i++)
            {
                var position = baseIndex[i] / 1.5 / fs;
                window[i] = 0.5 * Math.Cos(Math.PI * position * currentF0) + 0.5;
                average  += window[i] * window[i];
            }
            average = Math.Sqrt(average);
            for (int i = 0, limit = halfWindowLength * 2; i <= limit; i++)
            {
                window[i] /= average;
            }
        }
Esempio n. 2
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]);
            }
        }
Esempio n. 3
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;
            }
        }
Esempio n. 4
0
        public static void LinearSmoothing(double[] input, double width, int fs, int fftSize, double[] output)
        {
            var boundary = (int)(width * fftSize / fs) + 1;

            // These parameters are set by the other function.
            var mirroringSpectrum = new double[fftSize / 2 + boundary * 2 + 1];
            var mirroringSegment  = new double[fftSize / 2 + boundary * 2 + 1];
            var frequencyAxis     = new double[fftSize / 2 + 1];

            SetParametersForLinearSmoothing(boundary, fftSize, fs, width, input, mirroringSpectrum, mirroringSegment, frequencyAxis);

            var lowLevels                 = new double[fftSize / 2 + 1];
            var highLevels                = new double[fftSize / 2 + 1];
            var originOfMirroringAxis     = -(boundary - 0.5) * fs / fftSize;
            var discreteFrequencyInterval = (double)fs / fftSize;

            MatlabFunctions.Interp1Q(originOfMirroringAxis, discreteFrequencyInterval, mirroringSegment.SubSequence(0, fftSize / 2 + boundary * 2 + 1), frequencyAxis.SubSequence(0, fftSize / 2 + 1), lowLevels);

            for (int i = 0, limit = fftSize / 2; i <= limit; i++)
            {
                frequencyAxis[i] += width;
            }

            MatlabFunctions.Interp1Q(originOfMirroringAxis, discreteFrequencyInterval, mirroringSegment.SubSequence(0, fftSize / 2 + boundary * 2 + 1), frequencyAxis.SubSequence(0, fftSize / 2 + 1), highLevels);

            for (int i = 0, limit = fftSize / 2; i <= limit; i++)
            {
                output[i] = (highLevels[i] - lowLevels[i]) / width;
            }
        }
Esempio n. 5
0
        void GetTimeBase(double[] f0, int f0Length, int startSample, int numberOfSamples)
        {
            var coarseTimeAxis = new double[f0Length + Handoff];
            var coarseF0       = new double[f0Length + Handoff];
            var coarseVUV      = new double[f0Length + Handoff];

            GetTemporalParametersForTimeBase(f0, f0Length, coarseTimeAxis, coarseF0, coarseVUV);

            var interpolatedF0 = new double[numberOfSamples];
            var timeAxis       = Enumerable.Range(0, numberOfSamples).Select((i) => (i + startSample) / (double)SampleRate).ToArray();

            var pointer = Buffer.HeadIndex;

            MatlabFunctions.Interp1(coarseTimeAxis, coarseF0, timeAxis, interpolatedF0);
            MatlabFunctions.Interp1(coarseTimeAxis, coarseVUV, timeAxis, Buffer.InterpolatedVUV[pointer]);
            var interpolatedVUV = Buffer.InterpolatedVUV[pointer];

            for (var i = 0; i < numberOfSamples; i++)
            {
                interpolatedVUV[i] = interpolatedVUV[i] > 0.5 ? 1.0 : 0.0;
                interpolatedF0[i]  = interpolatedVUV[i] == 0.0 ? DefaultF0 : interpolatedF0[i];
            }

            GetPulseLocationsForTimeBase(interpolatedF0, timeAxis, numberOfSamples, coarseTimeAxis[0]);

            HandoffF0 = interpolatedF0[numberOfSamples - 1];
        }
Esempio n. 6
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);
        }
Esempio n. 7
0
        void GetPulseLocationsForTimeBase(double[] interpolatedF0, double[] timeAxis, int numberOfSamples, double origin)
        {
            var totalPhase = new double[numberOfSamples + Handoff];

            totalPhase[0] = Handoff == 1 ? HandoffPhase : PI2 * interpolatedF0[0] / SampleRate;

            totalPhase[1] = totalPhase[0] + PI2 * interpolatedF0[0] / SampleRate;
            for (int i = 1 + Handoff, limit = numberOfSamples + Handoff; i < limit; i++)
            {
                totalPhase[i] = totalPhase[i - 1] + PI2 * interpolatedF0[i - Handoff] / SampleRate;
            }
            HandoffPhase = totalPhase[numberOfSamples - 1 + Handoff];

            var wrapPhase    = totalPhase.Select((t) => t % PI2).ToArray();
            var wrapPhaseABS = wrapPhase.Zip(wrapPhase.Skip(1), (w, nw) => Math.Abs(nw - w)).Append(0.0).ToArray();

            var pointer        = Buffer.HeadIndex;
            var numberOfPulses = 0;

            for (int i = 0, limit = numberOfSamples - 1 + Handoff; i < limit; i++)
            {
                if (wrapPhaseABS[i] > Math.PI)
                {
                    Buffer.PulseLocations[pointer][numberOfPulses]     = timeAxis[i] - (double)Handoff / SampleRate;
                    Buffer.PulseLocationIndex[pointer][numberOfPulses] = MatlabFunctions.MatlabRound(Buffer.PulseLocations[pointer][numberOfPulses] * SampleRate);
                    numberOfPulses++;
                }
            }
            Buffer.NumberOfPulses[pointer] = numberOfPulses;

            if (numberOfPulses != 0)
            {
                LastLocation = Buffer.PulseLocationIndex[pointer][numberOfPulses - 1];
            }
        }
Esempio n. 8
0
        //-----------------------------------------------------------------------------
        // GetPeriodicResponse() calculates an aperiodic response.
        //-----------------------------------------------------------------------------
        void GetPeriodicResponse(int fftSize, double[] spectrum, double[] aperiodicRatio, double currentVUV, InverseRealFFT inverseRealFFT, MinimumPhaseAnalysis minimumPhase, double[] dcRemover, double fractionalTimeShift, int fs, double[] periodicResponse)
        {
            if (currentVUV <= 0.5 || aperiodicRatio[0] > 0.999)
            {
                Array.Clear(periodicResponse, 0, fftSize);
                return;
            }

            var logSpectrum = minimumPhase.LogSpectrum;

            for (int i = 0, limit = minimumPhase.FFTSize / 2; i <= limit; i++)
            {
                logSpectrum[i] = Math.Log(spectrum[i] * (1.0 - aperiodicRatio[i]) + SafeGuardMinimum) / 2.0;
            }
            Common.GetMinimumPhaseSpectrum(minimumPhase);
            Array.Copy(minimumPhase.MinimumPhaseSpectrum, 0, inverseRealFFT.Spectrum, 0, fftSize / 2 + 1);

            double coefficient = PI2 * fractionalTimeShift * fs / fftSize;

            GetSpectrumWithFractionalTimeShift(fftSize, coefficient, inverseRealFFT);

            FFT.Execute(inverseRealFFT.InverseFFT);
            MatlabFunctions.FFTShift(inverseRealFFT.Waveform.SubSequence(0, fftSize), periodicResponse);
            RemoveDCComponent(periodicResponse, fftSize, dcRemover, periodicResponse);
        }
Esempio n. 9
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;
            }
        }
Esempio n. 10
0
        //-----------------------------------------------------------------------------
        // SetParametersForGetWindowedWaveform()
        //-----------------------------------------------------------------------------
        void SetParametersForGetWindowedWaveform(int halfWindowLength, int xLength, double currentPosition, int fs, double currentF0, WindowType windowType, double windowLengthRatio, int[] baseIndex, int[] safeIndex, double[] window)
        {
            for (var i = -halfWindowLength; i <= halfWindowLength; i++)
            {
                baseIndex[i + halfWindowLength] = i;
            }
            var origin = MatlabFunctions.MatlabRound(currentPosition * fs + 0.001);

            for (int i = 0, limit = halfWindowLength * 2; i <= limit; i++)
            {
                safeIndex[i] = Math.Min(xLength - 1, Math.Max(0, origin + baseIndex[i]));
            }

            switch (windowType)
            {
            case WindowType.Hanning:
                for (int i = 0, limit = halfWindowLength * 2; i <= limit; i++)
                {
                    var position = (2.0 * baseIndex[i] / windowLengthRatio) / fs;
                    window[i] = 0.5 * Math.Cos(Math.PI * position * currentF0) + 0.5;
                }
                break;

            case WindowType.Blackman:
                for (int i = 0, limit = halfWindowLength * 2; i <= limit; i++)
                {
                    var position = (2.0 * baseIndex[i] / windowLengthRatio) / fs;
                    window[i] = 0.42 + 0.5 * Math.Cos(Math.PI * position * currentF0) + 0.08 * Math.Cos(Math.PI * position * currentF0 * 2);
                }
                break;
            }
        }
Esempio n. 11
0
 void GetAperiodicity(double[] coarseFrequencyAxis, double[] coarseAperiodicity, int numberOfAperiodicities, double[] frequencyAxis, int fftSize, double[] aperiodicity)
 {
     MatlabFunctions.Interp1(coarseFrequencyAxis.SubSequence(0, numberOfAperiodicities + 2), coarseAperiodicity, frequencyAxis.SubSequence(0, fftSize / 2 + 1), aperiodicity);
     for (int i = 0, limit = fftSize / 2; i <= limit; i++)
     {
         aperiodicity[i] = Math.Pow(10.0, aperiodicity[i] / 20.0);
     }
 }
Esempio n. 12
0
        public static void DCCorrection(double[] input, double f0, int fs, int fftSize, double[] output)
        {
            var upperLimit          = 2 + (int)(f0 * fftSize / fs);
            var lowFrequencyReplica = new double[upperLimit];
            var lowFrequencyAxis    = Enumerable.Range(0, upperLimit).Select((i) => (double)i * fs / fftSize).ToArray();

            var upperLimitReplica = upperLimit - 1;

            MatlabFunctions.Interp1Q(f0 - lowFrequencyAxis[0], -(double)fs / fftSize, input.SubSequence(0, upperLimit + 1), lowFrequencyAxis.SubSequence(0, upperLimitReplica), lowFrequencyReplica);

            for (var i = 0; i < upperLimitReplica; i++)
            {
                output[i] = input[i] + lowFrequencyReplica[i];
            }
        }
Esempio n. 13
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);
        }
Esempio n. 14
0
        //-----------------------------------------------------------------------------
        // GetPeriodicResponse() calculates an aperiodic response.
        //-----------------------------------------------------------------------------
        void GetPeriodicResponse(int fftSize, double[] spectrum, double[] aperiodicRatio, double currentVUV, double[] periodicResponse)
        {
            if (currentVUV <= 0.5 || aperiodicRatio[0] > 0.999)
            {
                periodicResponse.Fill(0.0, 0, fftSize);
                return;
            }

            var logSpectrum = MinimumPhase.LogSpectrum;

            for (int i = 0, limit = MinimumPhase.FFTSize / 2; i <= limit; i++)
            {
                logSpectrum[i] = Math.Log(spectrum[i] * (1.0 - aperiodicRatio[i]) + SafeGuardMinimum) / 2.0;
            }
            Common.GetMinimumPhaseSpectrum(MinimumPhase);
            Array.Copy(MinimumPhase.MinimumPhaseSpectrum, 0, InverseRealFFT.Spectrum, 0, fftSize / 2 + 1);

            FFT.Execute(InverseRealFFT.InverseFFT);
            MatlabFunctions.FFTShift(InverseRealFFT.Waveform.SubSequence(0, fftSize), periodicResponse);
            RemoveDCComponent(periodicResponse, fftSize, DCRemover, periodicResponse);
        }
Esempio n. 15
0
        int GetTimeBase(double[] f0, int f0Length, int fs, double framePeriod, int yLength, double lowestF0, double[] pulseLocations, int[] pulseLocationsIndex, double[] pulseLocationsTimeShift, double[] interpolatedVUV)
        {
            var timeAxis       = new double[yLength];
            var coarseTimeAxis = new double[f0Length + 1];
            var coarseF0       = new double[f0Length + 1];
            var coarseVUV      = new double[f0Length + 1];

            GetTemporalParametersForTimeBase(f0, f0Length, fs, yLength, framePeriod, lowestF0, timeAxis, coarseTimeAxis, coarseF0, coarseVUV);

            var interpolatedF0 = new double[yLength];

            MatlabFunctions.Interp1(coarseTimeAxis, coarseF0, timeAxis, interpolatedF0);
            MatlabFunctions.Interp1(coarseTimeAxis, coarseVUV, timeAxis, interpolatedVUV);
            for (var i = 0; i < yLength; i++)
            {
                interpolatedVUV[i] = interpolatedVUV[i] > 0.5 ? 1.0 : 0.0;
                interpolatedF0[i]  = interpolatedVUV[i] == 0.0 ? DefaultF0 : interpolatedF0[i];
            }

            return(GetPulseLocationsForTimeBase(interpolatedF0, timeAxis, yLength, fs, pulseLocations, pulseLocationsIndex, pulseLocationsTimeShift));
        }
Esempio n. 16
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]);
        }
Esempio n. 17
0
        //-----------------------------------------------------------------------------
        // GetWindowedWaveform() windows the waveform by F0-adaptive window
        // In the variable window_type, 1: hanning, 2: blackman
        //-----------------------------------------------------------------------------
        void GetWindowedWaveform(double[] x, int fs, double currentF0, double currentPosition, WindowType windowType, double windowLengthRatio, double[] waveform)
        {
            var halfWindowLength = MatlabFunctions.MatlabRound(windowLengthRatio * fs / currentF0 / 2.0);

            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, windowType, windowLengthRatio, baseIndex, safeIndex, window);

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

            var tmpWeight1           = waveform.Sum();
            var tmpWeight2           = window.Sum();
            var weightingCoefficient = tmpWeight1 / tmpWeight2;

            for (int i = 0, limit = halfWindowLength * 2; i <= limit; i++)
            {
                waveform[i] -= window[i] * weightingCoefficient;
            }
        }