private void processBlock(DataBuffer dbout) { if (buffInFill == blockSize) { if (fft == null) { fft = new FFTProcessor(FFTProcessor.ProcessorMode.Bidirectional, blockSize, owner.sampleRate, fftWindow); } if (fftWindow != fft.windowType) { fft.windowType = fftWindow; } fft.runFFT(ref buffIn, true, ref re, ref im); Array.Copy(buffIn, blockSize / 2, buffIn, 0, buffInFill - blockSize / 2); buffInFill -= blockSize / 2; // Process FFT Data if (normalize || (mode == FFTOutMode.Phase) || (mode == FFTOutMode.Sig) || (mode == FFTOutMode.SigPhase)) { // Must calculate Energy if ((energy == null) || (energy.Length != re.Length)) { energy = new double[re.Length]; } for (int i = 0; i < re.Length; i++) { energy[i] = re[i] * re[i] + im[i] * im[i]; } emax = energy[0]; rmax = re[0]; imax = im[0]; for (int i = 1; i < re.Length; i++) { if (energy[i] > emax) { emax = energy[i]; } if (re[i] > rmax) { rmax = re[i]; } if (im[i] > imax) { imax = im[i]; } if (re[i] < -rmax) { rmax = -re[i]; } if (im[i] < -imax) { imax = -im[i]; } } } switch (mode) { case FFTOutMode.ReIm: if ((outArray == null) || (outArray.Length != 2 * re.Length)) { outArray = new double[2 * re.Length]; } if (normalize) { double sf = 1; if (emax > 0) { sf = 1.0 / Math.Sqrt(emax); } for (int i = 0; i < re.Length; i++) { outArray[2 * i] = re[i] * sf; outArray[2 * i + 1] = im[i] * sf; } } else { for (int i = 0; i < re.Length; i++) { outArray[2 * i] = re[i]; outArray[2 * i + 1] = im[i]; } } break; case FFTOutMode.Re: case FFTOutMode.Im: if ((outArray == null) || (outArray.Length != re.Length)) { outArray = new double[re.Length]; } if (normalize) { double sf = 1; if (mode == FFTOutMode.Re) { if (rmax > 0) { sf = 1 / rmax; } for (int i = 0; i < re.Length; i++) { outArray[i] = re[i] * sf; } } else { if (imax > 0) { sf = 1 / imax; } for (int i = 0; i < re.Length; i++) { outArray[i] = im[i] * sf; } } } else { if (mode == FFTOutMode.Re) { Array.Copy(re, outArray, re.Length); } else { Array.Copy(im, outArray, re.Length); } } break; case FFTOutMode.Phase: if ((outArray == null) || (outArray.Length != re.Length)) { outArray = new double[re.Length]; } for (int i = 0; i < re.Length; i++) { outArray[i] = Math.Atan2(im[i], re[i]); } break; case FFTOutMode.Sig: if ((outArray == null) || (outArray.Length != re.Length)) { outArray = new double[re.Length]; } if (normalize) { double sf = 1; if (emax > 0) { sf = 1.0 / Math.Sqrt(emax); } for (int i = 0; i < re.Length; i++) { outArray[i] = Math.Sqrt(energy[i]) * sf; } } else { for (int i = 0; i < re.Length; i++) { outArray[i] = Math.Sqrt(energy[i]); } } break; case FFTOutMode.SigPhase: if ((outArray == null) || (outArray.Length != 2 * re.Length)) { outArray = new double[2 * re.Length]; } if (normalize) { double sf = 1; if (emax > 0) { sf = 1.0 / Math.Sqrt(emax); } for (int i = 0; i < re.Length; i++) { outArray[2 * i] = Math.Sqrt(energy[i]) * sf; outArray[2 * i + 1] = Math.Atan2(im[i], re[i]); } } else { for (int i = 0; i < re.Length; i++) { outArray[2 * i] = Math.Sqrt(energy[i]); outArray[2 * i + 1] = Math.Atan2(im[i], re[i]); } } break; } if (dbout != null) { dbout.initialize(outArray.Length); dbout.set(outArray); } } }
public override void tick() { if (!_active) { return; } SignalBuffer dbin = getSignalInputBuffer(ioI); SignalBuffer[] dbout = new SignalBuffer[7]; dbout[0] = getSignalOutputBuffer(ioM3); dbout[1] = getSignalOutputBuffer(ioM2); dbout[2] = getSignalOutputBuffer(ioM1); dbout[3] = getSignalOutputBuffer(io0); dbout[4] = getSignalOutputBuffer(ioP1); dbout[5] = getSignalOutputBuffer(ioP2); dbout[6] = getSignalOutputBuffer(ioP3); if (dbin == null) { return; } if (oval == null) { oval = new double[7]; } if (buffIn == null) { buffIn = new double[blockSize]; re = new double[blockSize / 2]; im = new double[blockSize / 2]; buffInFill = 0; } Array.Copy(dbin.data, 0, buffIn, buffInFill, owner.blockSize); buffInFill += owner.blockSize; if (buffInFill == blockSize) { if (fft == null) { fft = new FFTProcessor(FFTProcessor.ProcessorMode.Bidirectional, blockSize, owner.sampleRate, fftWindow); } n = (int)Math.Floor((double)blockSize * f / (owner.sampleRate)); fft.windowType = fftWindow; fft.runFFT(ref buffIn, true, ref re, ref im); Array.Copy(buffIn, blockSize / 2, buffIn, 0, buffInFill - blockSize / 2); buffInFill -= blockSize / 2; // Process FFT for (int i = -3; i <= 3; i++) { int m = n + i; oval[i + 3] = 0; if ((m >= 0) && (m < blockSize / 2)) { oval[i + 3] = Math.Sqrt(re[m] * re[m] + im[m] * im[m]); } } } for (int i = -3; i <= 3; i++) { if (dbout[i + 3] != null) { dbout[i + 3].SetTo(oval[i + 3]); } } }
public override void tick() { if (!_active) { return; } SignalBuffer dbin = getSignalInputBuffer(ioI); DataBuffer dbout = getDataOutputBuffer(ioData); if (dbin == null) { return; } if (oval == null) { oval = new double[7]; } if ((buffIn == null) || (buffIn.Length != blockSize)) { buffIn = new double[blockSize]; re = new double[blockSize / 2]; im = new double[blockSize / 2]; energy = new double[blockSize / 2]; buffInFill = 0; fft = null; addto = null; } if ((fft != null) && (fft.windowType != fftWindow)) { fft = new FFTProcessor(FFTProcessor.ProcessorMode.Bidirectional, blockSize, owner.sampleRate, fftWindow); } Array.Copy(dbin.data, 0, buffIn, buffInFill, owner.blockSize); buffInFill += owner.blockSize; if (buffInFill == blockSize) { if (fft == null) { fft = new FFTProcessor(FFTProcessor.ProcessorMode.Bidirectional, blockSize, owner.sampleRate, fftWindow); } if ((addto == null) || (fA != fA0) || (fMax != fMax0) || (coeffs != coeffs0)) { fA0 = fA; fMax0 = fMax; coeffs0 = coeffs; double melA = 1125.0 * Math.Log(1 + fA / 700.0); double melMax = 1125.0 * Math.Log(1 + fMax / 700.0); double[] centermels = new double[coeffs + 2]; for (int i = 0; i < coeffs + 2; i++) { double melf = melA + (i - 1) * (melMax - melA) / (coeffs - 1); centermels[i] = 700.0 * (Math.Exp(melf / 1125.0) - 1); } melfilterbank = new melfilter[coeffs]; for (int i = 0; i < coeffs; i++) { melfilterbank[i] = new melfilter(fft, centermels[i], centermels[i + 1], centermels[i + 2]); } mels = new double[coeffs]; } // n = (int)Math.Floor((double)blockSize * fA / (owner.sampleRate)); fft.windowType = fftWindow; fft.runFFT(ref buffIn, true, ref re, ref im); Array.Copy(buffIn, blockSize / 2, buffIn, 0, buffInFill - blockSize / 2); buffInFill -= blockSize / 2; // Process FFT Data for (int i = 0; i < re.Length; i++) { energy[i] = re[i] * re[i] + im[i] * im[i]; } for (int i = 0; i < coeffs; i++) { mels[i] = melfilterbank[i].calc(ref energy); } if (normalize) { double max = Math.Abs(mels[0]); for (int i = 1; i < coeffs; i++) { double ax = Math.Abs(mels[i]); if (ax > max) { max = ax; } } if (max == 0) { max = 1; } for (int i = 0; i < coeffs; i++) { mels[i] = mels[i] / max; } } if (dbout != null) { dbout.initialize(coeffs); dbout.set(mels); } } }
public override void tick() { if (!_active) { return; } SignalBuffer dbin = getSignalInputBuffer(ioI); DataBuffer dbout = getDataOutputBuffer(ioData); if (dbin == null) { return; } if (oval == null) { oval = new double[7]; } if ((buffIn == null) || (buffIn.Length != blockSize)) { buffIn = new double[blockSize]; re = new double[blockSize / 2]; im = new double[blockSize / 2]; buffInFill = 0; fft = null; addto = null; } if ((fft != null) && (fft.windowType != fftWindow)) { fft = new FFTProcessor(FFTProcessor.ProcessorMode.Bidirectional, blockSize, owner.sampleRate, fftWindow); } Array.Copy(dbin.data, 0, buffIn, buffInFill, owner.blockSize); buffInFill += owner.blockSize; if (buffInFill == blockSize) { if (fft == null) { fft = new FFTProcessor(FFTProcessor.ProcessorMode.Bidirectional, blockSize, owner.sampleRate, fftWindow); } if ((addto == null) || (fA != fA0) || (fMax != fMax0)) { fA0 = fA; fMax0 = fMax; double fC = fA * Math.Pow(2, -9.0 / 12.0); addto = new int[blockSize / 2]; addtoCoeff = new double[blockSize / 2]; for (int i = 0; i < blockSize / 2; i++) { double f = fft.freq[i]; double weight = bandPass(f, fC, fMax); if (weight < 0.1) { addto[i] = -1; } else { int fn = (int)Math.Floor(Math.Log(f / fC, 2.0) * 12 + 0.5); addto[i] = fn % 12; addtoCoeff[i] = weight; } } } // n = (int)Math.Floor((double)blockSize * fA / (owner.sampleRate)); fft.windowType = fftWindow; fft.runFFT(ref buffIn, true, ref re, ref im); Array.Copy(buffIn, blockSize / 2, buffIn, 0, buffInFill - blockSize / 2); buffInFill -= blockSize / 2; // Process FFT Data //double[] on = new double[12]; for (int i = 0; i < 12; i++) { on[i] = 0; } double[] n = new double[12]; for (int i = 0; i < addto.Length; i++) { if (addto[i] >= 0) { on[addto[i]] += addtoCoeff[i] * (re[i] * re[i] + im[i] * im[i]); n[addto[i]] += addtoCoeff[i]; } } double emax = 0; double emin = 0; for (int i = 0; i < 12; i++) { on[i] = Math.Sqrt(on[i] / n[i]); if (i == 0) { emin = emax = on[i]; } else { if (on[i] < emin) { emin = on[i]; } if (on[i] > emax) { emax = on[i]; } } } if (normalize) { if (emax == emin) { emax = emin + 1; } for (int i = 0; i < 12; i++) { on[i] = (on[i] - emin) / (emax - emin); } } else { double[] onLog = new double[12]; for (int i = 0; i < 12; i++) { if (on[i] < 1e-5) { onLog[i] = -100; } else if (on[i] > 1e1) { onLog[i] = 20; } else { onLog[i] = 20 * Math.Log10(on[i]); } onLog[i] = (onLog[i] - (-100)) / (20 - (-100)); } } if (dbout != null) { dbout.initialize(12); dbout.set(on); } } }
public override void tick() { if (fft == null) { fft = new FFTProcessor(FFTProcessor.ProcessorMode.Bidirectional, blockSize, owner.sampleRate, FFTProcessor.WindowType.Hann); } SignalBuffer dbout = getSignalOutputBuffer(ioO); SignalBuffer dbin = getSignalInputBuffer(ioI); if (!_active) { return; } if ((dbout == null) && (dbin == null)) { return; } if (buffIn == null) { buffIn = new double[blockSize]; buffOut = new double[blockSize]; fftOut = new double[blockSize]; re = new double[blockSize / 2]; im = new double[blockSize / 2]; buffInFill = 0; buffOutFill = 0; buffOutRead = 0; } if (dbin != null) { Array.Copy(dbin.data, 0, buffIn, buffInFill, owner.blockSize); buffInFill += owner.blockSize; if (buffInFill == blockSize) { fft.runFFT(ref buffIn, true, ref re, ref im); Array.Copy(buffIn, blockSize / 2, buffIn, 0, buffInFill - blockSize / 2); buffInFill -= blockSize / 2; // Process FFT int n1, n2; double s, c; switch (filterMode) { case FFTFilterMode.LowPass: n1 = (int)Math.Floor(f1 / (double)owner.sampleRate * blockSize); if (n1 < 0) { n1 = 0; } for (int i = n1; i < blockSize / 2; i++) { re[i] = im[i] = 0; } break; case FFTFilterMode.HighPass: n1 = (int)Math.Ceiling(f1 / (double)owner.sampleRate * blockSize); if (n1 >= blockSize / 2) { n1 = blockSize / 2 - 1; } for (int i = 0; i < n1; i++) { re[i] = im[i] = 0; } break; case FFTFilterMode.BandPass: n1 = (int)Math.Floor(f1 / (double)owner.sampleRate * blockSize); n2 = (int)Math.Ceiling(f2 / (double)owner.sampleRate * blockSize); if (n1 < 0) { n1 = 0; } if (n2 >= blockSize / 2) { n2 = blockSize / 2 - 1; } for (int i = 0; i < n1; i++) { re[i] = im[i] = 0; } for (int i = n2 + 1; i < blockSize / 2; i++) { re[i] = im[i] = 0; } break; case FFTFilterMode.BandStop: n1 = (int)Math.Floor(f1 / (double)owner.sampleRate * blockSize); n2 = (int)Math.Ceiling(f2 / (double)owner.sampleRate * blockSize); if (n1 < 0) { n1 = 0; } if (n2 >= blockSize / 2) { n2 = blockSize / 2 - 1; } for (int i = n1 + 1; i < n2; i++) { re[i] = im[i] = 0; } break; case FFTFilterMode.AllPass: s = Math.Sin(phi); c = Math.Cos(phi); for (int i = 1; i < blockSize / 2; i++) { double _re = re[i] * c - im[i] * s; double _im = re[i] * s + im[i] * c; re[i] = _re; im[i] = _im; } break; case FFTFilterMode.FrequencyShifter: n1 = (int)Math.Floor(f1 / (double)owner.sampleRate * blockSize + 0.5); if (n1 > 0) { // positive shift double df = (double)owner.sampleRate / (double)blockSize; // Bin Spacing Array.Copy(re, 1, re, 1 + n1, blockSize / 2 - 1 - n1); Array.Copy(im, 1, im, 1 + n1, blockSize / 2 - 1 - n1); Array.Clear(re, 1, n1); Array.Clear(im, 1, n1); for (int i = 1 + n1; i < blockSize / 2; i++) { double T = 1.0 / i / df; double T2 = 1.0 / (i + n1) / df; double dphi = -2.0 * Math.PI * (T - T2) * (i + n1) * df; s = Math.Sin(dphi); c = Math.Cos(dphi); double _re = re[i] * c - im[i] * s; double _im = re[i] * s + im[i] * c; re[i] = _re; im[i] = _im; } } if (n1 < 0) { n1 = -n1; Array.Copy(re, n1 + 1, re, 1, blockSize / 2 - n1 - 1); Array.Copy(im, n1 + 1, im, 1, blockSize / 2 - n1 - 1); Array.Clear(re, blockSize / 2 - 1 - n1, n1); Array.Clear(im, blockSize / 2 - 1 - n1, n1); } break; } // Transfer Back fft.runIFFT(ref re, ref im, ref fftOut); Array.Copy(buffOut, blockSize / 2, buffOut, 0, blockSize / 2); Array.Clear(buffOut, blockSize / 2, blockSize / 2); for (int i = 0; i < blockSize; i++) { buffOut[i] += fftOut[i]; } buffOutFill = blockSize / 2; buffOutRead = 0; } if (buffOutFill > 0) { if (dbout != null) { Array.Copy(buffOut, buffOutRead, dbout.data, 0, owner.blockSize); buffOutRead += owner.blockSize; } } } }