/// <summary> /// returns the fft spectrum of a cross-correlation function. /// </summary> /// <param name="v1"></param> /// <param name="v2"></param> /// <returns></returns> public static double[] CrossCorr(double[] v1, double[] v2) { int n = v1.Length; // assume both vectors of same length double[] r; alglib.corrr1d(v1, n, v2, n, out r); // alglib.complex[] f; // alglib.fftr1d(newOp, out f); // System.LoggedConsole.WriteLine("{0}", alglib.ap.format(f, 3)); // for (int i = 0; i < op.Length; i++) LoggedConsole.WriteLine("{0} {1:f2}", i, op[i]); // rearrange corr output and NormaliseMatrixValues int xcorrLength = 2 * n; double[] xCorr = new double[xcorrLength]; // for (int i = 0; i < n - 1; i++) newOp[i] = r[i + n]; //rearrange corr output // for (int i = n - 1; i < opLength-1; i++) newOp[i] = r[i - n + 1]; for (int i = 0; i < n - 1; i++) { xCorr[i] = r[i + n] / (i + 1); // rearrange and NormaliseMatrixValues } for (int i = n - 1; i < xcorrLength - 1; i++) { xCorr[i] = r[i - n + 1] / (xcorrLength - i - 1); } // add extra value at end so have length = power of 2 for FFT // xCorr[xCorr.Length - 1] = xCorr[xCorr.Length - 2]; // LoggedConsole.WriteLine("xCorr length = " + xCorr.Length); // for (int i = 0; i < xCorr.Length; i++) LoggedConsole.WriteLine("{0} {1:f2}", i, xCorr[i]); // DataTools.writeBarGraph(xCorr); xCorr = DataTools.DiffFromMean(xCorr); FFT.WindowFunc wf = FFT.Hamming; var fft = new FFT(xCorr.Length, wf); var spectrum = fft.Invoke(xCorr); return(spectrum); }// CrossCorrelation()
public static Image <Rgb24> DrawWaveAndFft(double[] signal, int sr, TimeSpan startTime, double[] fftSpectrum, int maxHz, double[] scores) { int imageHeight = 300; double max = -2.0; foreach (double value in signal) { double absValue = Math.Abs(value); if (absValue > max) { max = absValue; } } double scalingFactor = 0.5 / max; // now process neighbourhood of each max int nyquist = sr / 2; int windowWidth = signal.Length; int binCount = windowWidth / 2; double hzPerBin = nyquist / (double)binCount; if (fftSpectrum == null) { FFT.WindowFunc wf = FFT.Hamming; var fft = new FFT(windowWidth, wf); fftSpectrum = fft.Invoke(signal); } int requiredBinCount = (int)(maxHz / hzPerBin); var subBandSpectrum = DataTools.Subarray(fftSpectrum, 1, requiredBinCount); // ignore DC in bin zero. var endTime = startTime + TimeSpan.FromSeconds(windowWidth / (double)sr); string title1 = $"Bandpass filtered: tStart={startTime.ToString()}, tEnd={endTime.ToString()}"; var image4A = DrawWaveform(title1, signal, signal.Length, imageHeight, scalingFactor); string title2 = $"FFT 1->{maxHz}Hz., hz/bin={hzPerBin:f1}, score={scores[0]:f3}={scores[1]:f3}+{scores[2]:f3}"; var image4B = DrawGraph(title2, subBandSpectrum, signal.Length, imageHeight, 1); var imageList = new List <Image <Rgb24> > { image4A, image4B }; Pen pen1 = new Pen(Color.Wheat, 1f); var stringFont = Drawing.Arial9; var bmp2 = new Image <Rgb24>(signal.Length, 25); bmp2.Mutate(g2 => { g2.DrawLine(pen1, 0, 0, signal.Length, 0); g2.DrawLine(pen1, 0, bmp2.Height - 1, signal.Length, bmp2.Height - 1); int barWidth = signal.Length / subBandSpectrum.Length; for (int i = 1; i < subBandSpectrum.Length - 1; i++) { if (subBandSpectrum[i] > subBandSpectrum[i - 1] && subBandSpectrum[i] > subBandSpectrum[i + 1]) { string label = $"{i + 1},"; g2.DrawText(label, stringFont, Color.Wheat, new PointF((i * barWidth) - 3, 3)); } } }); imageList.Add(bmp2); var image = ImageTools.CombineImagesVertically(imageList); return(image); }