static void Diff(SubSequence <double> x, double[] result) { for (var i = x.Length - 2; i > -1; i--) { result[i] = x[i + 1] - x[i]; } }
static void Histc(SubSequence <double> x, SubSequence <double> edges, int[] index) { var count = 1; var i = 0; for (; i < edges.Length; i++) { index[i] = 1; if (edges[i] >= x[0]) { break; } } for (; i < edges.Length; i++) { if (edges[i] < x[count]) { index[i] = count; } else { index[i--] = count++; } if (count == x.Length) { break; } } for (count--, i++; i < edges.Length; i++) { index[i] = count; } }
public static void FFTShift(SubSequence <double> x, double[] result) { var halfPoint = x.Length / 2; for (var i = 0; i < halfPoint; i++) { result[i] = x[i + halfPoint]; result[i + halfPoint] = x[i]; } }
public static void Interp1Q(double x, double shift, SubSequence <double> y, SubSequence <double> xi, double[] yi) { var deltaY = new double[y.Length]; Diff(y, deltaY); deltaY[y.Length - 1] = 0.0; for (var i = 0; i < xi.Length; i++) { var xiBase = (int)((xi[i] - x) / shift); var xiFraction = (xi[i] - x) / shift - xiBase; yi[i] = y[xiBase] + deltaY[xiBase] * xiFraction; } }
public static void Interp1(SubSequence <double> x, double[] y, SubSequence <double> xi, double[] yi) { var h = new double[x.Length - 1]; for (var i = 0; i < h.Length; i++) { h[i] = x[i + 1] - x[i]; } var k = new int[xi.Length]; Histc(x, xi, k); for (var i = 0; i < xi.Length; i++) { var s = (xi[i] - x[k[i] - 1]) / h[k[i] - 1]; yi[i] = y[k[i] - 1] + s * (y[k[i]] - y[k[i] - 1]); } }
public SubSequence(SubSequence <T> array) : this(array, 0, array.Length) { }
public SubSequence(SubSequence <T> array, int offset) : this(array, offset, Math.Max(array.Length - offset, 0)) { }
public SubSequence(SubSequence <T> a, int offset, int length) { Array = a.Array; Offset = a.Offset + offset; Length = length; }
public static SubSequence <T> SubSequence <T>(this SubSequence <T> array, int offset) { return(new SubSequence <T>(array, offset)); }
//----------------------------------------------------------------------------- // 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]); } }
//----------------------------------------------------------------------------- // 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); } }