void zvmul(const float* real1P, const float* imag1P, const float* real2P, const float* imag2P, float* realDestP, float* imagDestP, size_t framesToProcess) { DSPSplitComplex sc1; DSPSplitComplex sc2; DSPSplitComplex dest; sc1.realp = const_cast<float*>(real1P); sc1.imagp = const_cast<float*>(imag1P); sc2.realp = const_cast<float*>(real2P); sc2.imagp = const_cast<float*>(imag2P); dest.realp = realDestP; dest.imagp = imagDestP; #if defined(__ppc__) || defined(__i386__) ::zvmul(&sc1, 1, &sc2, 1, &dest, 1, framesToProcess, 1); #else vDSP_zvmul(&sc1, 1, &sc2, 1, &dest, 1, framesToProcess, 1); #endif }
void FFTFrame::multiply(const FFTFrame& frame) { FFTFrame& frame1 = *this; const FFTFrame& frame2 = frame; float* realP1 = frame1.realData(); float* imagP1 = frame1.imagData(); const float* realP2 = frame2.realData(); const float* imagP2 = frame2.imagData(); // Scale accounts for vecLib's peculiar scaling // This ensures the right scaling all the way back to inverse FFT float scale = 0.5f; // Multiply packed DC/nyquist component realP1[0] *= scale * realP2[0]; imagP1[0] *= scale * imagP2[0]; // Multiply the rest, skipping packed DC/Nyquist components DSPSplitComplex sc1 = frame1.dspSplitComplex(); sc1.realp++; sc1.imagp++; DSPSplitComplex sc2 = frame2.dspSplitComplex(); sc2.realp++; sc2.imagp++; unsigned halfSize = m_FFTSize / 2; // Complex multiply vDSP_zvmul(&sc1, 1, &sc2, 1, &sc1, 1, halfSize - 1, 1 /* normal multiplication */); // We've previously scaled the packed part, now scale the rest..... vDSP_vsmul(sc1.realp, 1, &scale, sc1.realp, 1, halfSize - 1); vDSP_vsmul(sc1.imagp, 1, &scale, sc1.imagp, 1, halfSize - 1); }