int test_transform(int n, int sign) { #ifdef HAVE_SSE float __attribute__ ((aligned(32))) *input = _mm_malloc(2 * n * sizeof(float), 32); float __attribute__ ((aligned(32))) *output = _mm_malloc(2 * n * sizeof(float), 32); #else float __attribute__ ((aligned(32))) *input = valloc(2 * n * sizeof(float)); float __attribute__ ((aligned(32))) *output = valloc(2 * n * sizeof(float)); #endif int i; for(i=0;i<n;i++) { input[2*i] = 0.0f; input[2*i+1] = 0.0f; } input[2] = 1.0f; ffts_plan_t *p = ffts_init_1d(i, sign); if(p) { ffts_execute(p, input, output); printf(" %3d | %9d | %10E\n", sign, n, impulse_error(n, sign, output)); ffts_free(p); }else{ printf("Plan unsupported\n"); return 0; } return 1; }
void MyConvolver::process(const float *inBuffer, float *outBuffer, int len) { if (!_init) return; // set input buffer zero memset(_inFFTBuf, 0, 2 * _segmentSize * sizeof(float)); // copy ir to real part of the input buffer for (int i=0; i < jmin(len, _blockSize);i++) { _inFFTBuf[2*i] = inBuffer[i]; } ffts_execute(_ffts_fwd_plan, _inFFTBuf, _outFFTBuf); // complex multiplication for (int i=0; i < 2*_segmentSize; i++) { _inFFTBuf[2*i] = _irFFTBuf[2*i]*_outFFTBuf[2*i] - _irFFTBuf[2*i+1]*_outFFTBuf[2*i+1]; // real _inFFTBuf[2*i+1] = (_outFFTBuf[2*i]+_outFFTBuf[2*i+1])*(_irFFTBuf[2*i]+_irFFTBuf[2*i+1]) - _inFFTBuf[2*i]; // imag } // inverse FFT ffts_execute(_ffts_inv_plan, _inFFTBuf, _outFFTBuf); // overlap and copy to output buffer for (int i=0; i < jmin(len, _blockSize); i++) { outBuffer[i] = _outFFTBuf[2*i] + _outTDBuf[i]; } // store overlap for (int i=0; i < (_segmentSize-jmin(len, _blockSize));i++) { _outTDBuf[i] = _outFFTBuf[2*i+2*jmin(len, _blockSize)]; } }
void MyConvolver::init(int blockSize, const float* irBuffer, int irLength) { // get next ^2 int nextPower2 = 1; while (blockSize < nextPower2) { nextPower2 *= 2; } _blockSize = nextPower2; _segmentSize = 2 * nextPower2; // the segment with overlap // init fft _ffts_fwd_plan = ffts_init_1d_real(_segmentSize, NEGATIVE_SIGN); _ffts_inv_plan = ffts_init_1d_real(_segmentSize, POSITIVE_SIGN); // init aligned complex Buffers #ifdef HAVE_SSE _inFFTBuf = (float*)_mm_malloc(2 * _segmentSize * sizeof(float), 32); _outFFTBuf = (float*)_mm_malloc(2 * _segmentSize * sizeof(float), 32); _irFFTBuf = (float*)_mm_malloc(2 * _segmentSize * sizeof(float), 32); #else _inFFTBuf = (float*)valloc(2 * _segmentSize * sizeof(float)); _outFFTBuf = (float*)valloc(2 * _segmentSize * sizeof(float)); _irFFTBuf = (float*)valloc(2 * _segmentSize * sizeof(float)); #endif // set input buffer zero /* for(int i=0;i<_segmentSize;i++) { _inFFTBuf[2*i] = 0.0f; _inFFTBuf[2*i+1] = 0.0f; } */ memset(_inFFTBuf, 0, 2 * _segmentSize * sizeof(float)); // copy ir to real part of the input buffer for (int i=0; i < jmin(irLength, _blockSize);i++) { _inFFTBuf[2*i] = irBuffer[i]; } ffts_execute(_ffts_fwd_plan, _inFFTBuf, _irFFTBuf); _init = true; }
int main(int argc, char *argv[]) { if(argc == 3) { // test specific transform with test pattern and display output int n = atoi(argv[1]); int sign = atoi(argv[2]); #ifdef HAVE_SSE float __attribute__ ((aligned(32))) *input = _mm_malloc(2 * n * sizeof(float), 32); float __attribute__ ((aligned(32))) *output = _mm_malloc(2 * n * sizeof(float), 32); #else float __attribute__ ((aligned(32))) *input = valloc(2 * n * sizeof(float)); float __attribute__ ((aligned(32))) *output = valloc(2 * n * sizeof(float)); #endif int i; for(i=0;i<n;i++) { input[2*i] = i; input[2*i+1] = 0.0f; } // input[2] = 1.0f; ffts_plan_t *p = ffts_init_1d(i, sign); if(p) { ffts_execute(p, input, output); for(i=0;i<n;i++) printf("%d %d %f %f\n", i, sign, output[2*i], output[2*i+1]); ffts_free(p); }else{ printf("Plan unsupported\n"); return 0; } #ifdef HAVE_NEON _mm_free(input); _mm_free(output); #else free(input); free(output); #endif }else{
static VALUE ffts_plan_execute(VALUE self) { VALUE rb_plan = rb_funcall(self, rb_intern("plan"), 0); VALUE rb_frames = rb_funcall(self, rb_intern("frames"), 0); VALUE rb_n = rb_funcall(self, rb_intern("n"), 0); ffts_plan_t *plan; Data_Get_Struct(rb_plan, ffts_plan_t, plan); size_t n = NUM2INT(rb_n); if (!is_power_of_two(n)) { return Qnil; } size_t alloc_length = 2 * n * sizeof(float); float __attribute__ ((aligned(32))) *input = valloc(alloc_length); float __attribute__ ((aligned(32))) *output = valloc(alloc_length); for (int i = 0; i < n; ++i) { input[i] = (float)NUM2DBL(RARRAY_AREF(rb_frames, i)); } ffts_execute(plan, input, output); VALUE rb_output = rb_ary_new(); for (int i = 0; i < n; ++i) { rb_ary_push(rb_output, DBL2NUM(output[i])); } free(input); free(output); return rb_output; }
void FFTSEngine::transform() { ffts_execute(m_currentplan, m_iptr, m_optr); }