int OfdmGenerator::process(Buffer* const dataIn, Buffer* dataOut) { PDEBUG("OfdmGenerator::process(dataIn: %p, dataOut: %p)\n", dataIn, dataOut); dataOut->setLength(myNbSymbols * mySpacing * sizeof(complexf)); FFT_TYPE* in = reinterpret_cast<FFT_TYPE*>(dataIn->getData()); FFT_TYPE* out = reinterpret_cast<FFT_TYPE*>(dataOut->getData()); size_t sizeIn = dataIn->getLength() / sizeof(complexf); size_t sizeOut = dataOut->getLength() / sizeof(complexf); if (sizeIn != myNbSymbols * myNbCarriers) { PDEBUG("Nb symbols: %zu\n", myNbSymbols); PDEBUG("Nb carriers: %zu\n", myNbCarriers); PDEBUG("Spacing: %zu\n", mySpacing); PDEBUG("\n%zu != %zu\n", sizeIn, myNbSymbols * myNbCarriers); throw std::runtime_error( "OfdmGenerator::process input size not valid!"); } if (sizeOut != myNbSymbols * mySpacing) { PDEBUG("Nb symbols: %zu\n", myNbSymbols); PDEBUG("Nb carriers: %zu\n", myNbCarriers); PDEBUG("Spacing: %zu\n", mySpacing); PDEBUG("\n%zu != %zu\n", sizeIn, myNbSymbols * mySpacing); throw std::runtime_error( "OfdmGenerator::process output size not valid!"); } #if USE_FFTW // No SIMD/no-SIMD distinction, it's too early to optimize anything for (size_t i = 0; i < myNbSymbols; ++i) { myFftIn[0][0] = 0; myFftIn[0][1] = 0; bzero(&myFftIn[myZeroDst], myZeroSize * sizeof(FFT_TYPE)); memcpy(&myFftIn[myPosDst], &in[myPosSrc], myPosSize * sizeof(FFT_TYPE)); memcpy(&myFftIn[myNegDst], &in[myNegSrc], myNegSize * sizeof(FFT_TYPE)); fftwf_execute(myFftPlan); memcpy(out, myFftOut, mySpacing * sizeof(FFT_TYPE)); in += myNbCarriers; out += mySpacing; } #else # ifdef USE_SIMD for (size_t i = 0, j = 0; i < sizeIn; ) { // Pack 4 fft operations typedef struct { float r[4]; float i[4]; } fft_data; assert(sizeof(FFT_TYPE) == sizeof(fft_data)); complexf *cplxIn = (complexf*)in; complexf *cplxOut = (complexf*)out; fft_data *dataBuffer = (fft_data*)myFftBuffer; FFT_REAL(myFftBuffer[0]) = _mm_setzero_ps(); FFT_IMAG(myFftBuffer[0]) = _mm_setzero_ps(); for (size_t k = 0; k < myZeroSize; ++k) { FFT_REAL(myFftBuffer[myZeroDst + k]) = _mm_setzero_ps(); FFT_IMAG(myFftBuffer[myZeroDst + k]) = _mm_setzero_ps(); } for (int k = 0; k < 4; ++k) { if (i < sizeIn) { for (size_t l = 0; l < myPosSize; ++l) { dataBuffer[myPosDst + l].r[k] = cplxIn[i + myPosSrc + l].real(); dataBuffer[myPosDst + l].i[k] = cplxIn[i + myPosSrc + l].imag(); } for (size_t l = 0; l < myNegSize; ++l) { dataBuffer[myNegDst + l].r[k] = cplxIn[i + myNegSrc + l].real(); dataBuffer[myNegDst + l].i[k] = cplxIn[i + myNegSrc + l].imag(); } i += myNbCarriers; } else { for (size_t l = 0; l < myNbCarriers; ++l) { dataBuffer[l].r[k] = 0.0f; dataBuffer[l].i[k] = 0.0f; } } } kiss_fft(myFftPlan, myFftBuffer, myFftBuffer); for (int k = 0; k < 4; ++k) { if (j < sizeOut) { for (size_t l = 0; l < mySpacing; ++l) { cplxOut[j + l] = complexf(dataBuffer[l].r[k], dataBuffer[l].i[k]); } j += mySpacing; } } } # else for (size_t i = 0; i < myNbSymbols; ++i) { FFT_REAL(myFftBuffer[0]) = 0; FFT_IMAG(myFftBuffer[0]) = 0; bzero(&myFftBuffer[myZeroDst], myZeroSize * sizeof(FFT_TYPE)); memcpy(&myFftBuffer[myPosDst], &in[myPosSrc], myPosSize * sizeof(FFT_TYPE)); memcpy(&myFftBuffer[myNegDst], &in[myNegSrc], myNegSize * sizeof(FFT_TYPE)); kiss_fft(myFftPlan, myFftBuffer, out); in += myNbCarriers; out += mySpacing; } # endif #endif return sizeOut; }
int Resampler::process(Buffer* const dataIn, Buffer* dataOut) { PDEBUG("Resampler::process(dataIn: %p, dataOut: %p)\n", dataIn, dataOut); dataOut->setLength(dataIn->getLength() * L / M); FFT_TYPE* in = reinterpret_cast<FFT_TYPE*>(dataIn->getData()); FFT_TYPE* out = reinterpret_cast<FFT_TYPE*>(dataOut->getData()); size_t sizeIn = dataIn->getLength() / sizeof(complexf); for (size_t i = 0, j = 0; i < sizeIn; i += myFftSizeIn / 2, j += myFftSizeOut / 2) { memcpy(myFftIn, myBufferIn, myFftSizeIn / 2 * sizeof(FFT_TYPE)); memcpy(myFftIn + (myFftSizeIn / 2), in + i, myFftSizeIn / 2 * sizeof(FFT_TYPE)); memcpy(myBufferIn, in + i, myFftSizeIn / 2 * sizeof(FFT_TYPE)); for (size_t k = 0; k < myFftSizeIn; ++k) { FFT_REAL(myFftIn[k]) *= myWindow[k]; FFT_IMAG(myFftIn[k]) *= myWindow[k]; } fftwf_execute(myFftPlan1); if (myFftSizeOut > myFftSizeIn) { memset(myBack, 0, myFftSizeOut * sizeof(FFT_TYPE)); memcpy(myBack, myFront, myFftSizeIn / 2 * sizeof(FFT_TYPE)); memcpy(&myBack[myFftSizeOut - (myFftSizeIn / 2)], &myFront[myFftSizeIn / 2], myFftSizeIn / 2 * sizeof(FFT_TYPE)); // Copy input Fs FFT_REAL(myBack[myFftSizeIn / 2]) = FFT_REAL(myFront[myFftSizeIn / 2]); FFT_IMAG(myBack[myFftSizeIn / 2]) = FFT_IMAG(myFront[myFftSizeIn / 2]); } else { memcpy(myBack, myFront, myFftSizeOut / 2 * sizeof(FFT_TYPE)); memcpy(&myBack[myFftSizeOut / 2], &myFront[myFftSizeIn - (myFftSizeOut / 2)], myFftSizeOut / 2 * sizeof(FFT_TYPE)); // Average output Fs from input FFT_REAL(myBack[myFftSizeOut / 2]) += FFT_REAL(myFront[myFftSizeOut / 2]); FFT_IMAG(myBack[myFftSizeOut / 2]) += FFT_IMAG(myFront[myFftSizeOut / 2]); FFT_REAL(myBack[myFftSizeOut / 2]) *= 0.5f; FFT_IMAG(myBack[myFftSizeOut / 2]) *= 0.5f; } for (size_t k = 0; k < myFftSizeOut; ++k) { FFT_REAL(myBack[k]) *= myFactor; FFT_IMAG(myBack[k]) *= myFactor; } fftwf_execute(myFftPlan2); for (size_t k = 0; k < myFftSizeOut / 2; ++k) { FFT_REAL(out[j + k]) = myBufferOut[k].real() + FFT_REAL(myFftOut[k]); FFT_IMAG(out[j + k]) = myBufferOut[k].imag() + FFT_IMAG(myFftOut[k]); } memcpy(myBufferOut, myFftOut + (myFftSizeOut / 2), (myFftSizeOut / 2) * sizeof(FFT_TYPE)); } return 1; }