示例#1
0
        /// <summary>
        /// Inverse STFT
        /// </summary>
        /// <param name="stft"></param>
        /// <returns></returns>
        public float[] Inverse(List <Tuple <float[], float[]> > stft)
        {
            var spectraCount = stft.Count;
            var samples      = new float[spectraCount * _hopSize + _windowSize];

            var re = new float[_windowSize];
            var im = new float[_windowSize];

            var pos = 0;

            for (var i = 0; i < spectraCount; i++)
            {
                stft[i].Item1.FastCopyTo(re, _windowSize);
                stft[i].Item2.FastCopyTo(im, _windowSize);

                _fft.Inverse(re, im);

                // windowing and reconstruction

                for (var j = 0; j < re.Length; j++)
                {
                    samples[pos + j] += re[j] * _windowSamples[j] * _norm;
                }

                pos += _hopSize;
            }

            return(samples);
        }
示例#2
0
        /// <summary>
        /// Compute complex analytic signal, single precision
        /// </summary>
        /// <param name="samples">Array of samples</param>
        /// <param name="norm">Normalize by fft size</param>
        /// <returns>Complex analytic signal</returns>
        public Tuple <float[], float[]> AnalyticSignal(float[] samples, bool norm = true)
        {
            var sre = new DiscreteSignal(1, samples, allocateNew: true);
            var sim = new DiscreteSignal(1, samples.Length);

            var re = sre.Samples;
            var im = sim.Samples;

            _fft32.Direct(re, im);

            for (var i = 1; i < re.Length / 2; i++)
            {
                re[i] *= 2;
                im[i] *= 2;
            }

            for (var i = re.Length / 2 + 1; i < re.Length; i++)
            {
                re[i] = 0.0f;
                im[i] = 0.0f;
            }

            _fft32.Inverse(re, im);

            if (norm)
            {
                sre.Attenuate(re.Length);
                sim.Attenuate(im.Length);
            }

            return(new Tuple <float[], float[]>(re, im));
        }
示例#3
0
        /// <summary>
        /// Does Fast Hilbert Transform.
        /// </summary>
        /// <param name="input">Input data</param>
        /// <param name="output">Output data</param>
        public void Direct(float[] input, float[] output)
        {
            // just here, for code brevity, use alias _im for output (i.e. it's not internal _im)
            var _im = output;

            Array.Clear(_re, 0, _re.Length);
            Array.Clear(_im, 0, _im.Length);

            input.FastCopyTo(_re, input.Length);

            _fft.Direct(_re, _im);

            for (var i = 1; i < _re.Length / 2; i++)
            {
                _re[i] *= 2;
                _im[i] *= 2;
            }

            for (var i = _re.Length / 2 + 1; i < _re.Length; i++)
            {
                _re[i] = 0.0f;
                _im[i] = 0.0f;
            }

            _fft.Inverse(_re, _im);
        }
示例#4
0
        /// <summary>
        /// Method for computing real cepstrum from array of samples
        /// </summary>
        /// <param name="samples"></param>
        /// <param name="cepstrum"></param>
        /// <param name="power"></param>
        /// <returns></returns>
        public void Direct(float[] samples, float[] cepstrum, bool power = false)
        {
            samples.FastCopyTo(_realSpectrum, _realSpectrum.Length);
            Array.Clear(_imagSpectrum, 0, _imagSpectrum.Length);

            // complex fft

            _fft.Direct(_realSpectrum, _imagSpectrum);

            // logarithm of power spectrum

            for (var i = 0; i < _realSpectrum.Length; i++)
            {
                var ps = _realSpectrum[i] * _realSpectrum[i] + _imagSpectrum[i] * _imagSpectrum[i];

                _realSpectrum[i] = (float)Math.Log10(ps + float.Epsilon);
                _imagSpectrum[i] = 0.0f;
            }

            // complex ifft

            _fft.Inverse(_realSpectrum, _imagSpectrum);

            // take truncated part

            if (power)
            {
                for (var i = 0; i < Size; i++)
                {
                    cepstrum[i] = (_realSpectrum[i] * _realSpectrum[i] +
                                   _imagSpectrum[i] * _imagSpectrum[i]) / _realSpectrum.Length;
                }
            }
            else
            {
                _realSpectrum.FastCopyTo(cepstrum, Size);
            }
        }
示例#5
0
        /// <summary>
        /// Method for computing real cepstrum from array of samples
        /// </summary>
        /// <param name="samples"></param>
        /// <param name="cepstrum"></param>
        /// <param name="power"></param>
        /// <returns></returns>
        public void Direct(float[] samples, float[] cepstrum, bool power = false)
        {
            // complex fft

            _fft.PowerSpectrum(samples, _realSpectrum, false);


            // logarithm of power spectrum

            for (var i = 0; i < _realSpectrum.Length; i++)
            {
                _realSpectrum[i] = (float)Math.Log10(_realSpectrum[i] + float.Epsilon);
                _imagSpectrum[i] = 0.0f;
            }


            // complex ifft

            _fft.Inverse(_realSpectrum, _imagSpectrum);


            // take truncated part

            if (power)
            {
                for (var i = 0; i < _cepstrumSize; i++)
                {
                    cepstrum[i] = (_realSpectrum[i] * _realSpectrum[i] +
                                   _imagSpectrum[i] * _imagSpectrum[i]) / _realSpectrum.Length;
                }
            }
            else
            {
                _realSpectrum.FastCopyTo(cepstrum, _cepstrumSize);
            }
        }
示例#6
0
        /// <summary>
        /// Inverse STFT
        /// </summary>
        /// <param name="stft"></param>
        /// <returns></returns>
        public float[] Inverse(List <Tuple <float[], float[]> > stft)
        {
            var spectraCount = stft.Count;
            var output       = new float[spectraCount * _hopSize + _windowSize];
            var windowSum    = new float[output.Length];

            var re = new float[_windowSize];
            var im = new float[_windowSize];

            var pos = 0;

            for (var i = 0; i < spectraCount; i++)
            {
                stft[i].Item1.FastCopyTo(re, _windowSize);
                stft[i].Item2.FastCopyTo(im, _windowSize);

                _fft.Inverse(re, im);

                // windowing and reconstruction

                for (var j = 0; j < re.Length; j++)
                {
                    output[pos + j]    += re[j] * _windowSamples[j];
                    windowSum[pos + j] += _windowSquared[j];
                }

                pos += _hopSize;
            }

            for (var j = 0; j < output.Length; j++)
            {
                if (windowSum[j] < 1e-10)
                {
                    continue;
                }
                output[j] /= (windowSum[j] * _fftSize);
            }

            return(output);
        }
示例#7
0
        /// <summary>
        /// Inverse DCT-II via FFT
        /// </summary>
        /// <param name="input"></param>
        /// <param name="output"></param>
        public void Inverse(float[] input, float[] output)
        {
            // multiply by exp(j * pi * n / 2N):

            int N = _fft.Size;

            for (int i = 0; i < N; i++)
            {
                _temp[i]  = (float)(input[i] * Math.Cos(0.5 * Math.PI * i / N));
                output[i] = (float)(input[i] * Math.Sin(0.5 * Math.PI * i / N));
            }
            _temp[0]  *= 0.5f;
            output[0] *= 0.5f;

            _fft.Inverse(_temp, output);

            for (int m = 0; m < _temp.Length / 2; m++)
            {
                output[2 * m]     = 2 * _temp[m];
                output[2 * m + 1] = 2 * _temp[N - 1 - m];
            }
        }
示例#8
0
        /// <summary>
        /// Evaluates complex cepstrum as:
        /// <code>
        ///    Real{IFFT(log(abs(FFT(x)) + unwrapped_phase))}
        /// </code>
        /// </summary>
        /// <param name="input">Input data</param>
        /// <param name="cepstrum">Complex cepstrum</param>
        /// <param name="normalize">Normalize cepstrum by FFT size</param>
        /// <returns>Circular delay (number of samples) added to <paramref name="input"/></returns>
        public double ComplexCepstrum(float[] input, float[] cepstrum, bool normalize = true)
        {
            Array.Clear(_re, 0, _re.Length);
            Array.Clear(_im, 0, _im.Length);

            input.FastCopyTo(_re, input.Length);

            // complex fft

            _fft.Direct(_re, _im);

            // complex logarithm of magnitude spectrum

            // the most difficult part is phase unwrapping which is slightly different from MathUtils.Unwrap

            var offset = 0.0;

            _unwrapped[0] = 0.0;

            var prevPhase = Math.Atan2(_im[0], _re[0]);

            for (var n = 1; n < _unwrapped.Length; n++)
            {
                var phase = Math.Atan2(_im[n], _re[n]);

                var delta = phase - prevPhase;

                if (delta > Math.PI)
                {
                    offset -= 2 * Math.PI;
                }
                else if (delta < -Math.PI)
                {
                    offset += 2 * Math.PI;
                }

                _unwrapped[n] = phase + offset;
                prevPhase     = phase;
            }

            var mid   = _re.Length / 2;
            var delay = Math.Round(_unwrapped[mid] / Math.PI);

            for (var i = 0; i < _re.Length; i++)
            {
                _unwrapped[i] -= Math.PI * delay * i / mid;

                var mag = Math.Sqrt(_re[i] * _re[i] + _im[i] * _im[i]);

                _re[i] = (float)Math.Log(mag + float.Epsilon, _logBase);
                _im[i] = (float)_unwrapped[i];
            }

            // complex ifft

            _fft.Inverse(_re, _im);

            // take truncated part

            _re.FastCopyTo(cepstrum, Size);

            if (normalize)
            {
                for (var i = 0; i < cepstrum.Length; i++)
                {
                    cepstrum[i] /= _fft.Size;
                }
            }

            return(delay);
        }