public MultirateFilter(int upFactor, int downFactor, Complex32[] taps) { this.upFactor = upFactor; this.downFactor = downFactor; //todo: ipp malloc may be required this.taps = (Complex32[])taps.Clone(); int delayCount = (taps.Length + upFactor - 1) / upFactor; dlySrc = new Complex32[delayCount]; dlyDst = new Complex32[delayCount]; IppStatus rc; int specSize, bufSize; rc = Ipp.ippsFIRMRGetStateSize_32fc(taps.Length, upFactor, downFactor, IppDataType.ipp32fc, &specSize, &bufSize); IppException.Check(rc); spec = new byte[specSize]; buf = new byte[bufSize]; fixed(Complex32 *pTaps = taps) fixed(byte *pSpec = spec) { rc = Ipp.ippsFIRMRInit_32fc(pTaps, taps.Length, upFactor, 0, downFactor, 0, (IppsFIRSpec_32fc *)pSpec); IppException.Check(rc); } }
//filterCutoff is 0..1 (-6 dB point) /// <summary>Initializes a new instance of the <see cref="IppResampler" /> class.</summary> /// <param name="inRate">The input sampling rate.</param> /// <param name="outRate">The output sampling rate.</param> /// <param name="requestedFilterOrder">The requested filter order.</param> /// <param name="filterCutoff">The 6-dB cutoff frequency of the anti-aliasing filter /// as a fraction of the Nyquist frequency. Must be in the range of 0...1.</param> /// <param name="kaiserAlpha">The alpha parameter of the Kaiser filter.</param> public IppResampler(int inRate, int outRate, int requestedFilterOrder, float filterCutoff, float kaiserAlpha) { this.inRate = inRate; this.outRate = outRate; //allocate memory for the resampler structure int specSize, filterOrder, filterHeight; IppStatus rc; rc = Ipp.ippsResamplePolyphaseFixedGetSize_32f(inRate, outRate, requestedFilterOrder, &specSize, &filterOrder, &filterHeight, IppHintAlgorithm.ippAlgHintFast); IppException.Check(rc); //{!} docs suggest to use ippsMalloc_8u(specSize), but that results in memory corruption pSpec = (IppsResamplingPolyphaseFixed_32f *)Ipp.ippsMalloc_8u(specSize * filterHeight); //initialize IPP resampler rc = Ipp.ippsResamplePolyphaseFixedInit_32f(inRate, outRate, filterOrder, filterCutoff, kaiserAlpha, pSpec, IppHintAlgorithm.ippAlgHintFast); IppException.Check(rc); //set up input buffer inData = new float[filterOrder]; readIndex = readIndex0 = filterOrder / 2; writeIndex = writeIndex0 = filterOrder; }
/// <summary>Compute the power spectrum from the complex spectrum in the <see cref="FreqData" /> array.</summary> /// <param name="power">The buffer for the power spectrum, or <c>null</c>.</param> /// <returns>The power spectrum.</returns> public float[] PowerSpectrum(float[] power = null) { int len = FreqData.Length; int half = len / 2; if (power == null) power = new float[len]; fixed(Complex32 *p_spectrum = FreqData) fixed(float *p_power = power) { IppStatus rc; if ((1 << order) == FreqData.Length) { //complex to power, swap the halves rc = sp.ippsPowerSpectr_32fc((Ipp32fc *)p_spectrum, p_power + half, half); IppException.Check(rc); rc = sp.ippsPowerSpectr_32fc((Ipp32fc *)p_spectrum + half, p_power, half); IppException.Check(rc); } else { rc = sp.ippsPowerSpectr_32fc((Ipp32fc *)p_spectrum, p_power, power.Length); IppException.Check(rc); } } return(power); }
/// <summary>Initializes a new instance of the <see cref="ComplexFft" /> class.</summary> /// <param name="size">The size of the FFT transform.</param> public ComplexFft(int size) : base(size) { //allocate input buffer TimeData = new Complex32[size]; FreqData = new Complex32[size]; //calculate FFT buffer sizes int specBufSize, initBufSize, workBufSize; IppStatus rc = sp.ippsFFTGetSize_C_32fc(order, IPP_FFT_NODIV_BY_ANY, IppHintAlgorithm.ippAlgHintNone, &specBufSize, &initBufSize, &workBufSize); IppException.Check(rc); //allocate FFT buffers Dispose(); specBuffer = Ipp.ippsMalloc_8u(specBufSize); byte[] initBuf = new byte[initBufSize]; workBuf = new byte[workBufSize]; //initialize FFT fixed(byte *pInitBuf = initBuf) fixed(IppsFFTSpec_C_32fc **ppFftSpec = &pFftSpec) { rc = sp.ippsFFTInit_C_32fc(ppFftSpec, order, IPP_FFT_NODIV_BY_ANY, IppHintAlgorithm.ippAlgHintNone, specBuffer, pInitBuf); } IppException.Check(rc); }
/// <summary>Computes the inverse FFT transform.</summary> public void ComputeInverse() { fixed(Complex32 *p_timeData = TimeData, p_freqData = FreqData) fixed(byte *p_workBuf = workBuf) { IppStatus rc = sp.ippsFFTInv_CToC_32fc((Ipp32fc *)p_freqData, (Ipp32fc *)p_timeData, pFftSpec, p_workBuf); IppException.Check(rc); } }
/// <summary>Computes the forward FFT transform.</summary> public void ComputeForward() { fixed(float *p_timeData = TimeData) fixed(Complex32 * p_freqData = FreqData) fixed(byte *p_workBuf = workBuf) { IppStatus rc = sp.ippsFFTFwd_RToCCS_32f((float *)p_timeData, (float *)p_freqData, pFftSpec, p_workBuf); IppException.Check(rc); } }
/// <summary>Converts power ratios to decibels in-place.</summary> /// <param name="power">The values to convert.</param> public static void PowerToLogPower(float[] power) { IppStatus rc; int len = power.Length; fixed(float *p_power = power) { rc = sp.ippsAddC_32f(p_power, 1f, p_power, len); IppException.Check(rc); rc = sp.ippsLn_32f_I(p_power, len); IppException.Check(rc); rc = sp.ippsMulC_32f_I(LnToDb, p_power, len); IppException.Check(rc); } }
/// <summary>Processes the specified input data.</summary> /// <param name="inputData">The input data.</param> /// <param name="inputOffset">The offset of the first value to process.</param> /// <param name="inputStride">The stride in the input data.</param> /// <param name="count">The number of values to process.</param> /// <returns>The number of resampled values.</returns> public int Process(float[] inputData, int inputOffset, int inputStride, int count) { //resize input buffer, *preserve data* int requiredBufferSize = writeIndex + count; if (inData.Length < requiredBufferSize) { Array.Resize(ref inData, requiredBufferSize); } //de-interleave input data and write to the buffer Dsp.StridedToFloat(inputData, inputOffset, inputStride, inData, writeIndex, count); writeIndex += count; int unusedCount = writeIndex - writeIndex0; //estimate output count int maxOutCount = (int)(((long)unusedCount * outRate) / inRate) + 2; //+2 is from the example if (OutData == null || OutData.Length < maxOutCount) { OutData = new float[maxOutCount]; } int outCount = 0; fixed(float *pSrc = inData, pDst = OutData) fixed(double *pTime = &readIndex) { //resample IppStatus rc = Ipp.ippsResamplePolyphaseFixed_32f(pSrc, unusedCount, pDst, 1f, pTime, &outCount, pSpec); IppException.Check(rc); int usedCount = (int)readIndex - readIndex0; //shift unused data back in the buffer rc = sp.ippsMove_32f(pSrc + usedCount, pSrc, writeIndex - usedCount); IppException.Check(rc); readIndex -= usedCount; writeIndex -= usedCount; } return(outCount); }
public int Process(int inCount) { int numIters = inCount / downFactor; int outCount = numIters * upFactor; if (OutData.Length < outCount) OutData = new Complex32[outCount]; fixed(Complex32 *pSrc = InData) fixed(Complex32 * pDst = OutData) fixed(byte *pSpec = spec) fixed(Complex32 * pDlySrc = dlySrc) fixed(Complex32 * pDlyDst = dlyDst) fixed(byte *pBuf = buf) { IppStatus rc = Ipp.ippsFIRMR_32fc(pSrc, pDst, numIters, (IppsFIRSpec_32fc *)pSpec, pDlySrc, pDlyDst, pBuf); IppException.Check(rc); } return(outCount); }
/// <summary>Initializes a new instance of the <see cref="RealFft" /> class.</summary> /// <param name="size">The size of the FFT transform.</param> public RealFft(int size) : base(size) { TimeData = new float[size]; FreqData = new Complex32[size / 2 + 1]; int specBufSize, initBufSize, workBufSize; IppStatus rc = sp.ippsFFTGetSize_R_32f(order, IPP_FFT_NODIV_BY_ANY, IppHintAlgorithm.ippAlgHintNone, &specBufSize, &initBufSize, &workBufSize); IppException.Check(rc); specBuffer = Ipp.ippsMalloc_8u(specBufSize); byte[] initBuf = new byte[initBufSize]; workBuf = new byte[workBufSize]; fixed(byte *pInitBuf = initBuf) fixed(IppsFFTSpec_R_32f **ppFftSpec = &pFftSpec) { rc = sp.ippsFFTInit_R_32f(ppFftSpec, order, IPP_FFT_NODIV_BY_ANY, IppHintAlgorithm.ippAlgHintNone, specBuffer, pInitBuf); } IppException.Check(rc); }