Ejemplo n.º 1
0
        /// <summary>
        /// Method for computing inverse cepstrum
        /// </summary>
        /// <param name="cepstrum"></param>
        /// <param name="samples"></param>
        /// <param name="power"></param>
        /// <returns></returns>
        public void Inverse(float[] cepstrum, float[] samples, bool power = false)
        {
            Guard.AgainstInequality(cepstrum.Length, _realSpectrum.Length, "Cepstrum length", "Size of FFT");

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

            if (power)
            {
                for (var i = 0; i < _realSpectrum.Length; i++)
                {
                    _realSpectrum[i] = (float)Math.Sqrt(_realSpectrum[i]) * _realSpectrum.Length;
                }
            }

            // FFT

            _fft.Direct(_realSpectrum, _imagSpectrum);

            // Pow ("inverse" logarithm)

            for (var i = 0; i < _realSpectrum.Length; i++)
            {
                samples[i]       = (float)Math.Sqrt(Math.Pow(_realSpectrum[i], 10));
                _imagSpectrum[i] = 0.0f;
            }

            // IFFT

            _fft.Inverse(samples, _imagSpectrum);
        }
Ejemplo n.º 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));
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Direct Fast Mellin Transform
        /// </summary>
        /// <param name="input"></param>
        /// <param name="outputRe"></param>
        /// <param name="outputIm"></param>
        /// <param name="normalize"></param>
        public void Direct(float[] input, float[] outputRe, float[] outputIm, bool normalize = true)
        {
            MathUtils.InterpolateLinear(_linScale, input, _expScale, outputRe);

            for (var i = 0; i < outputRe.Length; i++)
            {
                outputRe[i] *= (float)Math.Pow(_expScale[i], 0.5);
                outputIm[i]  = 0;
            }

            _fft.Direct(outputRe, outputIm);

            if (!normalize)
            {
                return;
            }

            var norm = (float)(1 / Math.Sqrt(outputRe.Length));

            for (var i = 0; i < outputRe.Length; i++)
            {
                outputRe[i] *= norm;
                outputIm[i] *= norm;
            }
        }
Ejemplo n.º 4
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);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Does Fast Hartley Transform in-place.
        /// </summary>
        /// <param name="re">Input/output data</param>
        public void Direct(float[] re)
        {
            Array.Clear(_im, 0, _im.Length);

            _fft.Direct(re, _im);

            for (var i = 0; i < re.Length; i++)
            {
                re[i] -= _im[i];
            }
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Direct DCT-II via FFT
        /// </summary>
        /// <param name="input"></param>
        /// <param name="output"></param>
        public void Direct(float[] input, float[] output)
        {
            Array.Clear(output, 0, output.Length);

            for (int m = 0; m < _temp.Length / 2; m++)
            {
                _temp[m] = input[2 * m];
                _temp[_temp.Length - 1 - m] = input[2 * m + 1];
            }

            _fft.Direct(_temp, output);

            // mutiply by exp(-j * pi * n / 2N):

            int N = _fft.Size;

            for (int i = 0; i < N; i++)
            {
                output[i] = 2 * (float)(_temp[i] * Math.Cos(0.5 * Math.PI * i / N) - output[i] * Math.Sin(-0.5 * Math.PI * i / N));
            }
        }
Ejemplo n.º 7
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);
            }
        }
Ejemplo n.º 8
0
        public void Direct(float[] input, float[] output)
        {
            Array.Clear(output, 0, output.Length);

            var N = Size;

            // mutiply by exp(-j * pi * n / N):

            for (var m = 0; m < _temp.Length; m++)
            {
                var re  = input[2 * m];
                var im  = input[N - 1 - 2 * m];
                var cos = Math.Cos(Math.PI * m / N);
                var sin = Math.Sin(-Math.PI * m / N);

                _temp[m]  = 2 * (float)(re * cos - im * sin);
                output[m] = 2 * (float)(re * sin + im * cos);
            }
            ;

            _fft.Direct(_temp, output);

            // mutiply by exp(-j * pi * (2n + 0.5) / 2N):

            for (var m = 0; m < _temp.Length; m++)
            {
                var re  = _temp[m];
                var im  = output[m];
                var cos = Math.Cos(0.5 * Math.PI * (2 * m + 0.5) / N);
                var sin = Math.Sin(-0.5 * Math.PI * (2 * m + 0.5) / N);

                _tempRe[m] = (float)(re * cos - im * sin);
                _tempIm[m] = (float)(re * sin + im * cos);
            }
            ;

            for (int m = 0, k = 0; m < N; m += 2, k++)
            {
                output[m] = _tempRe[k];
            }
            for (int m = 1, k = (N - 2) / 2; m < N; m += 2, k--)
            {
                output[m] = -_tempIm[k];
            }
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Method for computing direct STFT of a signal block.
        /// STFT (spectrogram) is essentially the list of spectra in time.
        /// </summary>
        /// <param name="samples">The samples of signal</param>
        /// <returns>STFT of the signal</returns>
        public List <Tuple <float[], float[]> > Direct(float[] samples)
        {
            var stft = new List <Tuple <float[], float[]> >();

            for (var pos = 0; pos + _windowSize < samples.Length; pos += _hopSize)
            {
                var re = new float[_fftSize];
                var im = new float[_fftSize];
                samples.FastCopyTo(re, _windowSize, pos);

                if (_window != WindowTypes.Rectangular)
                {
                    re.ApplyWindow(_windowSamples);
                }

                _fft.Direct(re, im);

                stft.Add(new Tuple <float[], float[]>(re, im));
            }

            return(stft);
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Method for computing inverse cepstrum
        /// </summary>
        /// <param name="cepstrum"></param>
        /// <param name="samples"></param>
        /// <param name="power"></param>
        /// <returns></returns>
        public void Inverse(float[] cepstrum, float[] samples, bool power = false)
        {
            if (cepstrum.Length != _realSpectrum.Length)
            {
                throw new ArgumentException("");
            }

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

            if (power)
            {
                for (var i = 0; i < _realSpectrum.Length; i++)
                {
                    _realSpectrum[i] = (float)Math.Sqrt(_realSpectrum[i]) * _realSpectrum.Length;
                }
            }

            // FFT

            _fft.Direct(_realSpectrum, _imagSpectrum);

            // Pow ("inverse" logarithm)

            for (var i = 0; i < _realSpectrum.Length; i++)
            {
                samples[i]       = (float)Math.Sqrt(Math.Pow(_realSpectrum[i], 10));
                _imagSpectrum[i] = 0.0f;
            }

            // IFFT

            _fft.Inverse(samples, _imagSpectrum);
        }
Ejemplo n.º 11
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);
        }