public WWRadix2Fft(int numPoints) { if (!WWUtil.IsPowerOfTwo(numPoints) || numPoints < 2) { throw new ArgumentException("numPoints must be power of two integer and larger than 2"); } mNumPoints = numPoints; mWn = new WWComplex[mNumPoints]; for (int i = 0; i < mNumPoints; ++i) { double angle = -2.0 * Math.PI * i / mNumPoints; mWn[i] = new WWComplex(Math.Cos(angle), Math.Sin(angle)); } // mNumStage == log_2(mNumPoints) int t = mNumPoints; for (int i = 0; 0 < t; ++i) { t >>= 1; mNumStage = i; } mBitReversalTable = new uint[mNumPoints]; for (uint i = 0; i < mNumPoints; ++i) { mBitReversalTable[i] = BitReversal(mNumStage, i); } }
public override PcmFormat Setup(PcmFormat inputFormat) { mPcmFormat = new PcmFormat(inputFormat); mFftLength = WWUtil.NextPowerOf2(mPcmFormat.SampleRate); mOverlappedFft = new OverlappedFft(mFftLength); return(inputFormat); }
public WWComplex[] ConvolutionContinuousFft(WWComplex[] h, WWComplex[] x) { int fftSize = WWUtil.NextPowerOf2(h.Length * 4); int fragmentSize = fftSize - h.Length + 1; if (x.Length <= fragmentSize) { // 1回のFFTで計算する。 return(ConvolutionFft(h, x)); } var fft = new WWRadix2Fft(fftSize); var r = new WWComplex[h.Length + x.Length - 1]; var h2 = new WWComplex[fftSize]; Array.Copy(h, 0, h2, 0, h.Length); var Hf = fft.ForwardFft(h2); // x(n)をfragmentSize要素ごとのデータ列に分解し、 // それぞれ長さfftSizeになるように末尾に0を追加してx0(n)、x1(n)を得る。 //Parallel.For(0, x.Length / fragmentSize, i => { for (int i = 0; i < (x.Length + fragmentSize - 1) / fragmentSize; ++i) { var xf = new WWComplex[fftSize]; int count = fragmentSize; if (x.Length < (i + 1) * fragmentSize) { count = x.Length - i * fragmentSize; } Array.Copy(x, i * fragmentSize, xf, 0, count); var Xf = fft.ForwardFft(xf); var Yf = WWComplex.Mul(Hf, Xf); var yf = fft.InverseFft(Yf); for (int j = 0; j < fftSize; ++j) { if (r.Length <= i * fragmentSize + j) { break; } r[i * fragmentSize + j].Add(yf[j]); } } ; return(r); }
public override double[] FilterDo(double[] inPcm) { // この計算で求めるのは、mChannelId==0のとき左耳, mChannelId==1のとき右耳の音。mChannelIdは耳のチャンネル番号。 // 入力データとしてmPcmAllChannelsが使用できる。mPcmAllChannels[0]==左スピーカーの音、mPcmAllChannels[1]==右スピーカーの音。 int fftLength = ((int)mNumSamples < mCoeffs[0].Length) ? mCoeffs[0].Length : (int)mNumSamples; fftLength = WWUtil.NextPowerOf2(fftLength); // 左スピーカーの音=mPcmAllChannels[0] // 左スピーカーと耳chの相互作用のCoeff==mCoeffs[ch] var leftSpeaker = FFTFir(mPcmAllChannels[0], mCoeffs[mChannelId + 0], fftLength); // 右スピーカーの音=mPcmAllChannels[1] // 右スピーカーと耳chの相互作用のCoeff==mCoeffs[ch+2] var rightSpeaker = FFTFir(mPcmAllChannels[1], mCoeffs[mChannelId + 2], fftLength); var mixed = Add(leftSpeaker, rightSpeaker); return(mixed); }
public WWComplex[] ConvolutionFft(WWComplex[] h, WWComplex[] x) { var r = new WWComplex[h.Length + x.Length - 1]; int fftSize = WWUtil.NextPowerOf2(r.Length); var h2 = new WWComplex[fftSize]; Array.Copy(h, 0, h2, 0, h.Length); var x2 = new WWComplex[fftSize]; Array.Copy(x, 0, x2, 0, x.Length); var fft = new WWRadix2Fft(fftSize); var H = fft.ForwardFft(h2); var X = fft.ForwardFft(x2); var Y = WWComplex.Mul(H, X); var y = fft.InverseFft(Y); Array.Copy(y, 0, r, 0, r.Length); return(r); }
public override string ToSaveText() { return(string.Format(CultureInfo.InvariantCulture, "{0}", WWUtil.EscapeString(FilterFilePath))); }
public override string ToSaveText() { return(string.Format(CultureInfo.InvariantCulture, "{0} {1}", TagType, WWUtil.EscapeString(Text))); }