Пример #1
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;
            }
        }
Пример #2
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;
            }
        }
Пример #3
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];
            }
        }
Пример #4
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;
            }
        }
Пример #5
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;
            }
        }
Пример #6
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]);
            }
        }
Пример #7
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);
        }
Пример #8
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]);
        }
Пример #9
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;
            }
        }