/// <summary> /// Создает сонограмму заданной глубины с заданным шагом, смещением и размером. /// Размер считается в "полноценных" спектрах, то есть не дополненных нулями. /// Если спектрограмму такого размера создать невозможно, возращается null. /// Размер выходного массива: { x = Length / Step; y = Depth / 2; } /// </summary> public float[][] CreateSono(int Depth, int Step, int Offset, int Length, WindowFunction WndFunc) { if (Length + Offset + Depth > Data.Length) { Length = Data.Length - Offset - Depth; } floatMax = 0; FFT.Initialize(); int steps = Length / Step; float[][] ret = new float[steps][]; //List<float[]> ret = new List<float[]>(); float dState = steps * 0.01f, nState = 0; float[] data = new float[Depth]; float nDepth = 1.0f / Depth; float[] nWnd = new float[Depth]; for (int i = 0; i < Depth; i++) nWnd[i] = WndFunc.Act(i * nDepth); Complex[] fftCpx = new Complex[Depth]; for (int i = 0; i < steps; i++) { for (int j = 0, j0 = i * Step; j < Depth; j++) { data[j] = nWnd[j] * Data[Offset + j0++]; } float[] fftFloat = new float[Depth / 2]; Complex[] result = FFT.GenFFT(data, 0, Depth); if (result == null) break; for (int j = 0; j < fftFloat.Length; j++) { float abs = result[j].Amplitude; if (floatMax < abs) floatMax = abs; fftFloat[j] = abs; } if (nState < i) { nState += dState; if (OnSonoProgress != null) OnSonoProgress(i, steps); } ret[i] = fftFloat; //ret.Add(fftFloat); } return ret.ToArray(); }
/// <summary> /// Создает сонограмму заданной глубины с заданным шагом, смещением и размером. /// Размер считается в "полноценных" спектрах, то есть не дополненных нулями. /// Если спектрограмму такого размера создать невозможно, возращается null. /// Размер выходного массива: { x = Length / Step; y = Depth / 2; } /// </summary> public float[][] CreateSonoParallel(int Depth, int Step, int Offset, int Length, WindowFunction WndFunc) { if (Length + Offset + Depth > Data.Length) { Length = Data.Length - Offset - Depth; } FFT.Initialize(); int steps = Length / Step; float[][] ret = new float[steps][]; int dState = steps / 100; if (dState < 1) dState = 1; float nDepth = 1.0f / Depth; float[] nWnd = new float[Depth]; for (int i = 0; i < Depth; i++) nWnd[i] = WndFunc.Act(i * nDepth); int k = 0; Parallel.For(0, steps, (i, n) => { float[] data = new float[Depth]; for (int j = 0, j0 = i * Step; j < Depth; j++) data[j] = nWnd[j] * Data[Offset + j0++]; Complex[] result = FFT.GenFFT(data, 0, Depth); if (result == null) return; float[] fftFloat = new float[Depth / 2]; for (int j = 0; j < fftFloat.Length; j++) fftFloat[j] = result[j].Amplitude; if (i % dState == 0) if (OnSonoProgress != null) OnSonoProgress(k++, steps); ret[i] = fftFloat; }); return ret; }
/// <summary> /// Создает сонограмму заданной глубины с заданным шагом. /// Размер выходного массива: { x = Data.Length / Step; y = Depth / 2; } /// Обнуляет floatMax. /// </summary> public float[][] CreateSono(int Depth, int Step, WindowFunction WndFunc) { return CreateSono(Depth, Step, 0, Data.Length - Depth, WndFunc); }