public override WWUtil.LargeArray <double> FilterDo(WWUtil.LargeArray <double> inPcmLA) { var inPcm = inPcmLA.ToArray(); double[] outPcm = null; if (mProcessed == 0) { outPcm = new double[inPcm.Length - INSPECT_BITS + 1]; } else { outPcm = new double[inPcm.Length]; } int writePos = 0; for (int readPos = 0; readPos < inPcm.Length; ++readPos) { double y = 0; if (!Process(inPcm[readPos], out y)) { // まだ出力から値が出てこない。 } else { outPcm[writePos++] = y; } } return(new WWUtil.LargeArray <double>(outPcm)); }
/* * Transfer function H(z): * (r・e^{jθ} - z^{-1})(r・e^{-jθ} - z^{-1}) * H(z) = ------------------------------------------------ * (1 - r・e^{jθ}・z^{-1})(1 - r・e^{-jθ}・z^{-1}) * * r^2 - 2r・cos(θ)z^{-1} + z^{-2} * = ------------------------------- * 1 - 2r・cos(θ)z^{-1} + r^2・z^{-2} * * Difference equation: * Input: x[n] * Output: y[n] * * y[n] = r^2 * x[n] - 2rcosθ * x[n-1] + x[n-2] + 2rcosθ * y[n-1] - r^2 * y[n-2] */ public override WWUtil.LargeArray <double> FilterDo(WWUtil.LargeArray <double> inPcmLA) { var inPcm = inPcmLA.ToArray(); var outPcm = new double[inPcm.Length]; double θ = T * Math.PI / 180.0; for (int i = 0; i < inPcm.Length; ++i) { double x = inPcm[i]; // direct form implementation of the difference equation double y = R * R * x - 2 * R * Math.Cos(θ) * mLastX[0] + mLastX[1]; y += 2 * R * Math.Cos(θ) * mLastY[0] - R * R * mLastY[1]; outPcm[i] = y; mLastX[1] = mLastX[0]; mLastX[0] = x; mLastY[1] = mLastY[0]; mLastY[0] = y; } return(new WWUtil.LargeArray <double>(outPcm)); }
public override WWUtil.LargeArray <double> FilterDo(WWUtil.LargeArray <double> inPcmLA) { var inPcm = inPcmLA.ToArray(); var result = new double[inPcm.Length - (mFilterCoeffs.Length - mSampleDelay.Count - 1)]; int pos = 0; foreach (double v in inPcm) { mSampleDelay.Enqueue(v); if (mFilterCoeffs.Length <= mSampleDelay.Count) { double sum = 0.0; int offs = 0; foreach (double d in mSampleDelay) { sum += mFilterCoeffs[offs] * d; ++offs; } result[pos] = sum; ++pos; mSampleDelay.Dequeue(); } } return(new WWUtil.LargeArray <double>(result)); }
public override WWUtil.LargeArray <double> FilterDo(WWUtil.LargeArray <double> inPcmLA) { var inPcm = inPcmLA.ToArray(); var outPcm = new double[inPcm.Length]; for (int i = 0; i < outPcm.Length; ++i) { double sampleD = inPcm[i]; int sampleI24; if (1.0 <= sampleD) { sampleI24 = 8388607; } else if (sampleD < -1.0) { sampleI24 = -8388608; } else { sampleI24 = (int)(8388608 * sampleD); } sampleI24 = mNoiseShaper.Filter24(sampleI24); outPcm[i] = (double)sampleI24 * (1.0 / 8388608); } return(new WWUtil.LargeArray <double>(outPcm)); }
public override WWUtil.LargeArray <double> FilterDo(WWUtil.LargeArray <double> inPcmLA) { var inPcm = inPcmLA.ToArray(); double[] outPcm; int i = 0; if (mFirst) { outPcm = new double[(inPcm.Length - 1) * Factor]; mLastOriginalSampleValue = inPcm[0]; mFirst = false; i = 1; } else { outPcm = new double[inPcm.Length * Factor]; // i==0 } int pos = 0; for (; i < inPcm.Length; ++i) { for (int r = 0; r < Factor; ++r) { double ratio = (r + 1.0) / Factor; outPcm[pos] = inPcm[i] * ratio + mLastOriginalSampleValue * (1.0 - ratio); ++pos; } mLastOriginalSampleValue = inPcm[i]; } return(new WWUtil.LargeArray <double>(outPcm)); }
public override WWUtil.LargeArray <double> FilterDo(WWUtil.LargeArray <double> inPcmLA) { var inPcm = inPcmLA.ToArray(); var outPcm = new double[inPcm.Length]; for (int i = 0; i < outPcm.Length; ++i) { double sampleD = 0.0; for (int order = 0; order < 5; ++order) { sampleD += mC[order] * mS[order]; } if (1 == TargetBitsPerSample) { if (0.0 <= sampleD) { outPcm[i] = 8388607.0 / 8388608.0; } else { outPcm[i] = -1.0; } } else { int sampleI = 0; if (1.0f <= sampleD) { sampleI = Int32.MaxValue; } else if (sampleD < -1.0f) { sampleI = Int32.MinValue; } else { sampleI = (int)(sampleD * -1.0 * Int32.MinValue); } sampleI = (int)((sampleI) & mMask); outPcm[i] = sampleI * (-1.0 / Int32.MinValue); } mS[4] += mS[3]; mS[3] += mS[2] - mF[1] * mS[4]; mS[2] += mS[1]; mS[1] += mS[0] - mF[0] * mS[2]; mS[0] += (inPcm[i] - outPcm[i]); } return(new WWUtil.LargeArray <double>(outPcm)); }
public override WWUtil.LargeArray <double> FilterDo(WWUtil.LargeArray <double> inPcmLA) { var inPcm = inPcmLA.ToArray(); var outPcm = new double[inPcm.Length]; for (int i = 0; i < outPcm.Length; ++i) { outPcm[i] = inPcm[i] * Amplitude; } return(new WWUtil.LargeArray <double>(outPcm)); }
public override WWUtil.LargeArray <double> FilterDo(WWUtil.LargeArray <double> inPcmLA) { var inPcm = inPcmLA.ToArray(); var outPcm = new double[inPcm.Length]; for (int i = 0; i < outPcm.Length; ++i) { outPcm[i] = inPcm[i] + mGNG.NextFloat() * NoiseLevelScale(); } return(new WWUtil.LargeArray <double>(outPcm)); }
public override WWUtil.LargeArray <double> FilterDo(WWUtil.LargeArray <double> inPcmLA) { if (inPcmLA.LongLength == 0) { return(new WWUtil.LargeArray <double>(0)); } var inPcm = inPcmLA.ToArray(); var pcmF = mFFT.ForwardFft(inPcm); double scaleLsb = Math.Pow(10, LsbScalingDb / 20.0); double maxMagnitude = FFT_LENGTH / 2; for (int i = 0; i < pcmF.Length; ++i) { /* -144 dBより小さい: そのまま * -144 dB: scaleLsb倍 * -72 dB: scaleLsb/2倍 * 0 dB: 1倍 * になるようなスケーリングをする。 * 出力データは音量が増えるので、後段にノーマライズ処理を追加すると良い。 */ // magnitudeは0.0~1.0の範囲の値。 double magnitude = pcmF[i].Magnitude() / maxMagnitude; double db = float.MinValue; if (float.Epsilon < magnitude) { db = 20.0 * Math.Log10(magnitude); } double scale = 1.0; if (db < LSB_DECIBEL) { scale = 1.0; } else if (0 <= db) { scale = 1.0; } else { scale = 1.0 + db * (scaleLsb - 1) / LSB_DECIBEL; } pcmF[i] = WWComplex.Mul(pcmF[i], scale); } return(new WWUtil.LargeArray <double>(mFFT.InverseFft(pcmF))); }
public override WWUtil.LargeArray <double> FilterDo(WWUtil.LargeArray <double> inPcmLA) { System.Diagnostics.Debug.Assert(inPcmLA.LongLength == NumOfSamplesNeeded()); var inPcm = inPcmLA.ToArray(); var outPcm = new double[inPcm.Length * Factor]; for (int i = 0; i < inPcm.Length; ++i) { outPcm[i * Factor] = inPcm[i]; } return(new WWUtil.LargeArray <double>(outPcm)); }
public override WWUtil.LargeArray <double> FilterDo(WWUtil.LargeArray <double> inPcmLA) { var inPcm = inPcmLA.ToArray(); var outPcm = new double[inPcm.Length]; var dict = new Dictionary <int, int>(); for (int i = 0; i < outPcm.Length; ++i) { double sampleD = inPcm[i]; int sampleI24; if (1.0 <= sampleD) { sampleI24 = 8388607; } else if (sampleD < -1.0) { sampleI24 = -8388608; } else { sampleI24 = (int)(8388608 * sampleD); } sampleI24 = mNoiseShaper1bit.Filter24(sampleI24); if (dict.ContainsKey(sampleI24)) { ++dict[sampleI24]; } else { dict.Add(sampleI24, 1); } outPcm[i] = (double)sampleI24 * (1.0 / 8388608); } foreach (var n in dict) { Console.WriteLine("{0} {1}", n.Key, n.Value); } return(new WWUtil.LargeArray <double>(outPcm)); }
public override WWUtil.LargeArray <double> FilterDo(WWUtil.LargeArray <double> inPcmLA) { var inPcm = inPcmLA.ToArray(); var outPcm = new double[inPcm.Length]; // 32bit integerにサンプル値を左寄せで詰める。 // maskで下位ビットを0にすることで量子化ビット数を減らす。 uint mask = 0xffffff00U << (24 - TargetBitsPerSample); for (long i = 0; i < outPcm.Length; ++i) { double sampleD = inPcm[i]; int sampleI24; if (1.0 <= sampleD) { sampleI24 = 8388607; } else if (sampleD < -1.0) { sampleI24 = -8388608; } else { sampleI24 = (int)(8388608 * sampleD); } int sampleI32 = sampleI24 << 8; if (TargetBitsPerSample == 1) { sampleI32 = (0 <= sampleI32) ? Int32.MaxValue : Int32.MinValue; } else { sampleI32 = (int)(((int)sampleI32) & mask); } sampleI24 = sampleI32 >> 8; outPcm[i] = (double)sampleI24 * (1.0 / 8388608); } return(new WWUtil.LargeArray <double>(outPcm)); }
public override WWUtil.LargeArray <double> FilterDo(WWUtil.LargeArray <double> inPcmLA) { var inPcm = inPcmLA.ToArray(); int i = 0; double[] outPcm; if (mDelay.Count == 0) { outPcm = new double[(inPcm.Length - 3) * Factor]; mDelay.Add(0); for (i = 0; i < 3; ++i) { mDelay.Add(inPcm[i]); } // i==3 } else { outPcm = new double[inPcm.Length * Factor]; // i==0 } int pos = 0; for (; i < inPcm.Length; ++i) { // p0 and p1: 2つの隣接する入力サンプル値 // m0 and m1: p0地点、p1地点の傾き double p0 = mDelay[1]; double p1 = mDelay[2]; double m0 = mDelay[2] - mDelay[0]; double m1 = mDelay[3] - mDelay[1]; for (int r = 0; r < Factor; ++r) { // tは補間時刻。0 < t ≦ 1まで変化する double t = (r + 1.0) / Factor; outPcm[pos] = H00(t) * p0 + H10(t) * m0 + H01(t) * p1 + H11(t) * m1; ++pos; } mDelay.RemoveAt(0); mDelay.Add(inPcm[i]); } return(new WWUtil.LargeArray <double>(outPcm)); }
public override WWUtil.LargeArray <double> FilterDo(WWUtil.LargeArray <double> inPcmLA) { var inPcm = inPcmLA.ToArray(); System.Diagnostics.Debug.Assert(inPcm.Length == mResamplePosArray.Length); System.Diagnostics.Debug.Assert(inPcm.Length == mFractionArray.Length); double [] outPcm = new double[inPcm.Length]; long processed = 0; Parallel.For(0, inPcm.Length, toPos => { int fromPos = mResamplePosArray[toPos]; double fraction = mFractionArray[toPos]; double sinFraction = Math.Sin(-Math.PI * mFractionArray[toPos]); double v = 0.0; for (int convOffs = -ConvolutionLengthMinus1 / 2; convOffs <= ConvolutionLengthMinus1 / 2; ++convOffs) { long pos = convOffs + fromPos; if (0 <= pos && pos < inPcm.LongLength) { double x = Math.PI * (convOffs - fraction); double sinX = sinFraction; if (0 != (convOffs & 1)) { sinX *= -1.0; } double sinc = SincD(sinX, x); v += inPcm[pos] * sinc; } } outPcm[toPos] = v; // report progress. Interlocked.Increment(ref processed); if (0xffff == (processed & 0xffff)) { ProgressReport((double)processed / inPcm.Length); } }); return(new WWUtil.LargeArray <double>(outPcm)); }
public override WWUtil.LargeArray<double> FilterDo(WWUtil.LargeArray<double> inPcmLA) { System.Diagnostics.Debug.Assert(inPcmLA.LongLength == NumOfSamplesNeeded()); var inPcm = inPcmLA.ToArray(); int inputSamples = (int)((UpsampledWindowLen + 1) / Factor + PROCESS_SLICE); if (mFirst) { var silence = new double[(UpsampledWindowLen + 1) / Factor / 2]; mInputDelay.AddRange(silence); } mInputDelay.AddRange(inPcm); if (inputSamples < mInputDelay.Count) { int count = mInputDelay.Count - inputSamples; mInputDelay.RemoveRange(0, count); } var fromPcm = mInputDelay.ToArray(); var toPcm = new double[PROCESS_SLICE * Factor]; #if false for (int i=0; i<PROCESS_SLICE; ++i) { #else Parallel.For(0, PROCESS_SLICE, i => { #endif for (int f = 0; f < Factor; ++f) { double sampleValue = 0; for (long offs = 0; offs + Factor - f < mCoeffs.LongLength; offs += Factor) { double input = mInputDelay[(int)(offs / Factor + i)]; if (input != 0.0) { sampleValue += mCoeffs.At(offs + Factor - f) * input; } } toPcm[i * Factor + f] = sampleValue; } #if false } #else }); #endif mFirst = false; return new WWUtil.LargeArray<double>(toPcm); } }
public override WWUtil.LargeArray <double> FilterDo(WWUtil.LargeArray <double> inPcmLA) { var inPcm = inPcmLA.ToArray(); var outPcm = new double[inPcm.LongLength * Factor]; long pos = 0; for (long i = 0; i < inPcm.LongLength; ++i) { for (int r = 0; r < Factor; ++r) { outPcm[pos] = inPcm[i]; ++pos; } } return(new WWUtil.LargeArray <double>(outPcm)); }
public override WWUtil.LargeArray <double> FilterDo(WWUtil.LargeArray <double> inPcmLA) { var inPcm = inPcmLA.ToArray(); System.Diagnostics.Debug.Assert(inPcm.Length == NumOfSamplesNeeded()); var outPcm = new double[inPcm.Length / Factor]; long writePos = 0; for (long i = PickSampleIndex; i < inPcm.Length; i += Factor) { outPcm[writePos] = inPcm[i]; ++writePos; } return(new WWUtil.LargeArray <double>(outPcm)); }
public override WWUtil.LargeArray <double> FilterDo(WWUtil.LargeArray <double> inPcmLA) { var inPcm = inPcmLA.ToArray(); var pcmF = mFFTfwd.Process(inPcm); if (pcmF.Length == 0) { return(new WWUtil.LargeArray <double>(0)); } int idx20Hz = (int)(20.0 * mFftLength / mPcmFormat.SampleRate); int idx40Hz = (int)(40.0 * mFftLength / mPcmFormat.SampleRate); for (int i = 0; i < idx40Hz - idx20Hz; ++i) { // 正の周波数 { var v = pcmF[i + idx40Hz]; v = WWComplex.Mul(v, Gain); pcmF[i + idx20Hz] = WWComplex.Add(pcmF[i + idx20Hz], v); } // 負の周波数 { var v = pcmF[mFftLength - (i + idx40Hz)]; v = WWComplex.Mul(v, Gain); pcmF[mFftLength - (i + idx20Hz)] = WWComplex.Add(pcmF[mFftLength - (i + idx20Hz)], v); } } var r = new WWUtil.LargeArray <double>(mFFTinv.Process(pcmF)); // 進捗表示。 mProcessedSamples += inPcm.Length; ProgressReport((double)mProcessedSamples / mTotalSamples); return(r); }
public override WWUtil.LargeArray <double> FilterDo(WWUtil.LargeArray <double> inPcmLA) { System.Diagnostics.Debug.Assert(inPcmLA.LongLength == NumOfSamplesNeeded()); var inPcm = inPcmLA.ToArray(); int inputSamples = (WindowLength + 1) + PROCESS_SLICE * Factor; if (mFirst) { var silence = new double[(WindowLength + 1) / 2]; mInputDelay.AddRange(silence); } mInputDelay.AddRange(inPcm); if (inputSamples < mInputDelay.Count) { int count = mInputDelay.Count - inputSamples; mInputDelay.RemoveRange(0, count); } var fromPcm = mInputDelay.ToArray(); var toPcm = new double[PROCESS_SLICE]; Parallel.For(0, PROCESS_SLICE, i => { double sampleValue = 0; for (int offs = 0; offs < mCoeffs.Length; ++offs) { double input = mInputDelay[offs + i * Factor]; if (input != 0.0) { sampleValue += mCoeffs[offs] * input; } } toPcm[i] = sampleValue; }); mFirst = false; return(new WWUtil.LargeArray <double>(toPcm)); }
/* * Transfer function H(z): * -a + z^{-1} * H(z) = ------------------ * 1 - a * z^{-1} * * for a : real value * * Difference equation: * Input: x[n] * Output: y[n] * * y[n] = -a * x[n] + x[n-1] + a * y[n-1] */ public override WWUtil.LargeArray <double> FilterDo(WWUtil.LargeArray <double> inPcmLA) { var inPcm = inPcmLA.ToArray(); var outPcm = new double[inPcm.Length]; for (int i = 0; i < inPcm.Length; ++i) { double x = inPcm[i]; // direct form implementation of the difference equation double y = -A * x + mLastX; y += A * mLastY; outPcm[i] = y; mLastX = x; mLastY = y; //Console.WriteLine("A={0:g} n={1:g} y={2:g}", A, i, y); } return(new WWUtil.LargeArray <double>(outPcm)); }
/// <summary> /// Understanding digital signal processing 3rd ed. pp.558 - 562 /// int型のデータをQ次、ディレイDのCICで処理するとき、 /// 中間データは32(intのビット数) + Q * log_2(D)ビットのデータ型である必要がある。 /// </summary> public override WWUtil.LargeArray <double> FilterDo(WWUtil.LargeArray <double> inPcmLA) { System.Diagnostics.Debug.Assert(inPcmLA.LongLength == NumOfSamplesNeeded()); var inPcm = inPcmLA.ToArray(); int gain = (int)Math.Pow(Delay, Order); var result = new double[inPcm.Length]; for (int i = 0; i < inPcm.Length; ++i) { double vD = inPcm[i]; long v = PCMDoubleToInt(vD); for (int j = 0; j < Order; ++j) { v += mIntegratorZ[j]; mIntegratorZ[j] = v; } for (int j = 0; j < Order; ++j) { mCombQueue[j].Enqueue(v); if (Delay < mCombQueue[j].Count) { v -= mCombQueue[j].Dequeue(); } } v /= gain; result[i] = PCMIntToDouble((int)v); } return(new WWUtil.LargeArray <double>(result)); }
public override WWUtil.LargeArray <double> FilterDo(WWUtil.LargeArray <double> inPcmLA) { System.Diagnostics.Debug.Assert(inPcmLA.LongLength == NumOfSamplesNeeded()); var inPcm = inPcmLA.ToArray(); // inPcmTをFFTしてinPcmFを得る。 // inPcmFを0で水増ししたデータoutPcmFを作って逆FFTしoutPcmを得る。 var inPcmF = mFFT.ForwardFft(inPcm); var outPcmF = new WWComplex[UpsampleFftLength]; for (int i = 0; i < outPcmF.Length; ++i) { if (i <= FftLength / 2) { outPcmF[i] = inPcmF[i]; } else if (UpsampleFftLength - FftLength / 2 <= i) { int pos = i + FftLength - UpsampleFftLength; outPcmF[i] = inPcmF[pos]; } else { outPcmF[i] = WWComplex.Zero(); } } inPcmF = null; var outPcm = mFFT.InverseFft(outPcmF); outPcmF = null; return(new WWUtil.LargeArray <double>(outPcm)); }
public override WWUtil.LargeArray <double> FilterDo(WWUtil.LargeArray <double> inPcmLA) { System.Diagnostics.Debug.Assert(inPcmLA.LongLength <= NumOfSamplesNeeded()); var inPcm = inPcmLA.ToArray(); var fft = new WWRadix2Fft(FFT_LEN); // Overlap and add continuous FFT var inTime = new WWComplex[FFT_LEN]; for (int i = 0; i < inPcm.Length; ++i) { inTime[i] = new WWComplex(inPcm[i], 0); } // FFTでinTimeをinFreqに変換 var inFreq = fft.ForwardFft(inTime); inTime = null; // FFT後、フィルターHの周波数ドメインデータを掛ける var mulFreq = WWComplex.Mul(inFreq, mFilterFreq); inFreq = null; // inFreqをIFFTしてoutTimeに変換 var outTime = fft.InverseFft(mulFreq); mulFreq = null; double [] outReal; if (mFirstFilterDo) { // 最初のFilterDo()のとき、フィルタの遅延サンプル数だけ先頭サンプルを削除する。 outReal = new double[NumOfSamplesNeeded() - FILTER_DELAY]; for (int i = 0; i < outReal.Length; ++i) { outReal[i] = outTime[i + FILTER_DELAY].real; } mFirstFilterDo = false; } else { outReal = new double[NumOfSamplesNeeded()]; for (int i = 0; i < outReal.Length; ++i) { outReal[i] = outTime[i].real; } } // 前回のIFFT結果の最後のFILTER_LENGTH-1サンプルを先頭に加算する if (null != mIfftAddBuffer) { for (int i = 0; i < mIfftAddBuffer.Length; ++i) { outReal[i] += mIfftAddBuffer[i]; } } // 今回のIFFT結果の最後のFILTER_LENGTH-1サンプルをmIfftAddBufferとして保存する mIfftAddBuffer = new double[FILTER_LENP1]; for (int i = 0; i < mIfftAddBuffer.Length; ++i) { mIfftAddBuffer[i] = outTime[outTime.Length - mIfftAddBuffer.Length + i].real; } outTime = null; return(new WWUtil.LargeArray <double>(outReal)); }
public override WWUtil.LargeArray <double> FilterDo(WWUtil.LargeArray <double> inPcmLA) { var inPcm = inPcmLA.ToArray(); double scaleLsb = Math.Pow(10, LsbScalingDb / 20.0); double maxScaling = 0.0; for (int b = 0; b < 15; ++b) { double scale = 1.0 * b / 14.0 + scaleLsb * (14 - b) / 14.0; maxScaling += scale * (1 << b); } var outPcm = new double[inPcm.Length]; for (int i = 0; i < outPcm.Length; ++i) { double d = inPcm[i] * (Int16.MaxValue + 1); bool plus = true; int v; if (Int16.MaxValue < d) { v = Int16.MaxValue; } else if (d < Int16.MinValue + 1) { v = Int16.MinValue + 1; } else { v = (int)d; } if (v < 0) { v = -v; plus = false; } double result = 0.0; for (int b = 0; b < 15; ++b) { if ((v & (1 << b)) != 0) { double scale = 1.0 * b / 14.0 + scaleLsb * (14 - b) / 14.0; result += (1 << b) * scale; } } if (!plus) { result = -result; } result /= maxScaling; outPcm[i] = result; } return(new WWUtil.LargeArray <double>(outPcm)); }