/// <summary> /// 複素数がインターリーブされたデータを離散フーリエ変換します。 /// </summary> /// <param name="invert">逆離散フーリエ変換を行うかの真偽値。</param> /// <param name="data">複素数がインターリーブされた配列。</param> public void TransformComplex(bool invert, double[] data) { if (data == null) { throw new ArgumentNullException("data"); } if (data.Length != this.n) { throw new ArgumentOutOfRangeException("data"); } FastFourier.cdft(this.n, invert, data, this.ip, this.w); if (invert) { double f = 2.0 / this.n; for (int j = 0; j < this.n; j++) { data[j] *= f; } } }
public override void Draw(float[] data) { float dx = (float)this.size.Width / (float)(data.Length / 8); float y_offset = +20.0f; int fftSize = data.Length / 2; int height = this.size.Height / 2; if (this.buffer.Length != fftSize) { this.buffer = new PointF[fftSize / 4]; this.lchannel = new double[fftSize]; this.rchannel = new double[fftSize]; this.fft_buffer = new double[fftSize * 2]; this.fft = new FastFourier(fftSize); } this.graphics.Clear(this.backgroundColor); for (int i = 0, j = 0, k = 1; i < fftSize; i++, j += 2, k += 2) { this.lchannel[i] = data[j]; this.rchannel[i] = data[k]; } // L channel { Window.Hanning(lchannel); Channel.Interleave(lchannel, this.fft_buffer, fftSize); this.fft.TransformComplex(false, this.fft_buffer); for (int i = 0, j = 0, k = 1; i < fftSize / 4; i++, j += 2, k += 2) { double d = 20.0 * Math.Log10(Math.Sqrt(this.fft_buffer[j] * this.fft_buffer[j] + this.fft_buffer[k] * this.fft_buffer[k]) / fftSize) + y_offset; if (d <= -height) d = -height; else if (d > 0.0) d = 0.0; this.buffer[i] = new PointF(i * dx, -(float)d); } this.graphics.DrawLines(this.p, this.buffer); } // R channel { Window.Hanning(rchannel); Channel.Interleave(rchannel, this.fft_buffer, fftSize); this.fft.TransformComplex(false, this.fft_buffer); for (int i = 0, j = 0, k = 1; i < fftSize / 4; i++, j += 2, k += 2) { double d = 20.0 * Math.Log10(Math.Sqrt(this.fft_buffer[j] * this.fft_buffer[j] + this.fft_buffer[k] * this.fft_buffer[k]) / fftSize) + y_offset; if (d <= -height) d = -height; else if (d > 0.0) d = 0.0; this.buffer[i] = new PointF(i * dx, this.size.Height / 2 - (float)d); } this.graphics.DrawLines(this.p, this.buffer); } this.graphics.DrawLine(this.p, 0, height, this.size.Width, height); this.graphics.Flush(); }
public unsafe override void Draw(float[] data) { float dx = (float)this.size.Width / (float)(data.Length / 4); const float y_offset = +210.0f; const float y_amplifier = 100.0f; int fftSize = data.Length; if (fftSize != this.fft_buffer.Length) { this.fft = new FastFourier(fftSize); this.re = new double[fftSize]; this.fft_buffer = new double[fftSize * 2]; this.spectrum = new Bitmap(1, fftSize / 8); } data.CopyTo(re, 0); Window.Hanning(this.re); Channel.Interleave(this.re, this.fft_buffer, fftSize); this.fft.TransformComplex(false, this.fft_buffer); for (int i = 0, j = 0, k = 1; i < fftSize / 8; i++, j += 2, k += 2) { re[i] = y_amplifier * Math.Log10(Math.Sqrt(this.fft_buffer[j] * this.fft_buffer[j] + this.fft_buffer[k] * this.fft_buffer[k]) / (fftSize * 4)) + y_offset; if (re[i] < -255.0) re[i] = -255.0; else if (re[i] > 0.0) re[i] = 0.0; } var bdata = this.bitmap.LockBits(new Rectangle(0, 0, this.bitmap.Width, this.bitmap.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); { for (byte* i = (byte*)bdata.Scan0, j = i + 4, l = i + bdata.Width * bdata.Height * 4; j < l; i++, j++) *i = *j; } this.bitmap.UnlockBits(bdata); bdata = this.spectrum.LockBits(new Rectangle(0, 0, 1, fftSize / 8), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); { int j = 0; for (byte* i = (byte*)bdata.Scan0, l = i + bdata.Height * 4; i < l; j++) { byte b = (byte)(255.0 + re[j]); *i++ = b; *i++ = b; *i++ = b; *i++ = 255; } } this.spectrum.UnlockBits(bdata); this.graphics.DrawImage(this.spectrum, this.size.Width - 1, this.size.Height - 1, 1, -this.size.Height); this.graphics.Flush(); }