float FourthOrderFilter::process(float sample){ float Aout, Bout; vDSP_vmul(A, 1, za1, 1, temp, 1, 4); vDSP_sve(temp, 1, &Aout, 4); vDSP_vmul(B, 1, zb1, 1, temp, 1, 4); vDSP_sve(temp, 1, &Bout, 4); float output = b0*sample + Bout - Aout; za1--; zb1--; if (za1 < Za) { // if we have reached the beginning of the buffer // copy za2, za3, za4, zb2, zb3, zb4 back to the end of the array *ZaEnd = *(Za + 2); *(ZaEnd - 1) = *(Za + 1); *(ZaEnd - 2) = *Za; *ZbEnd = *(Za + 2); *(ZbEnd - 1) = *(Zb + 1); *(ZbEnd - 2) = *Zb; // reset pointers za1 = ZaEnd - 3; zb1 = ZbEnd - 3; } *za1 = output; *zb1 = sample; return output; }
void scfft_dowindowing(float *data, unsigned int winsize, unsigned int fullsize, unsigned short log2_winsize, short wintype, float scalefac){ int i; if(wintype != WINDOW_RECT){ float *win = fftWindow[wintype][log2_winsize]; if (!win) return; #if SC_DARWIN vDSP_vmul(data, 1, win, 1, data, 1, winsize); #else --win; float *in = data - 1; for (i=0; i< winsize ; ++i) { *++in *= *++win; } #endif } // scale factor is different for different libs. But the compiler switch here is about using vDSP's fast multiplication method. #if SC_DARWIN vDSP_vsmul(data, 1, &scalefac, data, 1, winsize); #else for(int i=0; i<winsize; ++i){ data[i] *= scalefac; } #endif // Zero-padding: memset(data + winsize, 0, (fullsize - winsize) * sizeof(float)); }
void FFTAccelerate::doFFTReal(float samples[], float amp[], int numSamples) { int i; vDSP_Length log2n = log2f(numSamples); int nOver2 = numSamples/2; //-- window //vDSP_blkman_window(window, windowSize, 0); vDSP_vmul(samples, 1, window, 1, in_real, 1, numSamples); //Convert float array of reals samples to COMPLEX_SPLIT array A vDSP_ctoz((COMPLEX*)in_real,2,&A,1,nOver2); //Perform FFT using fftSetup and A //Results are returned in A vDSP_fft_zrip(fftSetup, &A, 1, log2n, FFT_FORWARD); // scale by 1/2*n because vDSP_fft_zrip doesn't use the right scaling factors natively ("for better performances") { const float scale = 1.0f/(2.0f*(float)numSamples); vDSP_vsmul( A.realp, 1, &scale, A.realp, 1, numSamples/2 ); vDSP_vsmul( A.imagp, 1, &scale, A.imagp, 1, numSamples/2 ); } //Convert COMPLEX_SPLIT A result to float array to be returned /*amp[0] = A.realp[0]/(numSamples*2); for(i=1;i<numSamples/2;i++) amp[i]=sqrt(A.realp[i]*A.realp[i]+A.imagp[i]*A.imagp[i]);*/ // collapse split complex array into a real array. // split[0] contains the DC, and the values we're interested in are split[1] to split[len/2] (since the rest are complex conjugates) vDSP_zvabs( &A, 1, amp, 1, numSamples/2 ); }
// windowSize and windowInterval are constrained to be multiples of the block size void DspEnvelope::processDspWithIndex(int fromIndex, int toIndex) { // copy the input into the signal buffer memcpy(signalBuffer + numSamplesReceived, dspBufferAtInlet0, numBytesInBlock); numSamplesReceived += blockSizeInt; numSamplesReceivedSinceLastInterval += blockSizeInt; if (numSamplesReceived >= windowSize) { numSamplesReceived = 0; } if (numSamplesReceivedSinceLastInterval == windowInterval) { numSamplesReceivedSinceLastInterval -= windowInterval; // apply hanning window to signal and calculate Root Mean Square float rms = 0.0f; if (ArrayArithmetic::hasAccelerate) { #if __APPLE__ vDSP_vsq(signalBuffer, 1, rmsBuffer, 1, windowSize); // signalBuffer^2 vDSP_vmul(rmsBuffer, 1, hanningCoefficients, 1, rmsBuffer, 1, windowSize); // * hanning window vDSP_sve(rmsBuffer, 1, &rms, windowSize); // sum the result #endif } else { for (int i = 0; i < windowSize; i++) { rms += signalBuffer[i] * signalBuffer[i] * hanningCoefficients[i]; } } // finish RMS calculation. sqrt is removed as it can be combined with the log operation. // result is normalised such that 1 RMS == 100 dB rms = 10.0f * log10f(rms) + 100.0f; PdMessage *outgoingMessage = getNextOutgoingMessage(0); // graph will schedule this at the beginning of the next block because the timestamp will be // behind the block start timestamp outgoingMessage->setTimestamp(0.0); outgoingMessage->setFloat(0, (rms < 0.0f) ? 0.0f : rms); graph->scheduleMessage(this, 0, outgoingMessage); } }
/******************************************************************************* VectorVectorMultiply */ Error_t VectorVectorMultiply(float *dest, const float *in1, const float *in2, unsigned length) { #ifdef __APPLE__ // Use the Accelerate framework if we have it vDSP_vmul(in1, 1, in2, 1, dest, 1, length); #else // Otherwise do it manually unsigned i; const unsigned end = 4 * (length / 4); for (i = 0; i < end; i+=4) { dest[i] = in1[i] * in2[i]; dest[i + 1] = in1[i + 1] * in2[i + 1]; dest[i + 2] = in1[i + 2] * in2[i + 2]; dest[i + 3] = in1[i + 3] * in2[i + 3]; } for (i = end; i < length; ++i) { dest[i] = in1[i] * in2[i]; } #endif return NOERR; }
/* Calculate the power spectrum */ void fft::powerSpectrum_vdsp(int start, float *data, float *window, float *magnitude,float *phase) { uint32_t i; //multiply by window vDSP_vmul(data, 1, window, 1, in_real, 1, n); //convert to split complex format - evens and odds vDSP_ctoz((COMPLEX *) in_real, 2, &A, 1, half); //calc fft vDSP_fft_zrip(setupReal, &A, 1, log2n, FFT_FORWARD); //scale by 2 (see vDSP docs) static float scale=0.5 ; vDSP_vsmul(A.realp, 1, &scale, A.realp, 1, half); vDSP_vsmul(A.imagp, 1, &scale, A.imagp, 1, half); //back to split complex format vDSP_ztoc(&A, 1, (COMPLEX*) out_real, 2, half); //convert to polar vDSP_polar(out_real, 2, polar, 2, half); for (i = 0; i < half; i++) { magnitude[i]=polar[2*i]+1.0; phase[i]=polar[2*i + 1]; } }
void vmul(const float* source1P, int sourceStride1, const float* source2P, int sourceStride2, float* destP, int destStride, size_t framesToProcess) { #if CPU(X86) ::vmul(source1P, sourceStride1, source2P, sourceStride2, destP, destStride, framesToProcess); #else vDSP_vmul(source1P, sourceStride1, source2P, sourceStride2, destP, destStride, framesToProcess); #endif }
void BinaryMultiplyUGenInternal::processBlock(bool& shouldDelete, const unsigned int blockID, const int channel) throw() { const int numSamplesToProcess = uGenOutput.getBlockSize(); float* const outputSamples = uGenOutput.getSampleData(); const float* const leftOperandSamples = inputs[LeftOperand].processBlock(shouldDelete, blockID, channel); const float* const rightOperandSamples = inputs[RightOperand].processBlock(shouldDelete, blockID, channel); vDSP_vmul(leftOperandSamples, 1, rightOperandSamples, 1, outputSamples, 1, numSamplesToProcess); }
void vmul(const float* source1P, int sourceStride1, const float* source2P, int sourceStride2, float* destP, int destStride, size_t framesToProcess) { #if defined(__ppc__) || defined(__i386__) ::vmul(source1P, sourceStride1, source2P, sourceStride2, destP, destStride, framesToProcess); #else vDSP_vmul(source1P, sourceStride1, source2P, sourceStride2, destP, destStride, framesToProcess); #endif }
static void PerformFFT(float * input, float * window, COMPLEX_SPLIT &fftData, FFTSetup &setup, size_t N) { // windowing vDSP_vmul(input, 1, window, 1, input, 1, N); // FFT vDSP_ctoz((COMPLEX *) input, 2, &fftData, 1, N/2); vDSP_fft_zrip(setup, &fftData, 1, (size_t)ceilf(log2f(N)), kFFTDirection_Forward); // zero-ing out Nyquist freq fftData.imagp[0] = 0.0f; }
t_int *errfilt_perf_coeff(t_int *w) { t_float *in = (t_float *)(w[1]); t_float *coeffIn = (t_float *)(w[2]); t_float *coeffIdxIn = (t_float *)(w[3]); t_errfilt *x = (t_errfilt *)(w[4]); t_float *out = (t_float *)(w[5]); int n = (int)(w[6]); int order = x->a_order; int i, in_idx = 0, out_idx = 0; t_float val = 0.0; float sum = 0.0; while(n--) { //get rid of NANs if(IS_NAN_FLOAT(coeffIn[in_idx])) coeffIn[in_idx] = 0.0; in_idx++; } in_idx = 0; n = (int)(w[6]); //look at coefficient index, if not zeros, buffer in coefficients while (n--) { if ((int)(coeffIdxIn[in_idx]) > 0) { x->a_bBuff[(int)(coeffIdxIn[in_idx])-1] = coeffIn[in_idx]; if ((int)(coeffIdxIn[in_idx]) == order) { for(i = 0; i < order; i++) { x->a_b[i] = x->a_bBuff[i]; } } } in_idx++; } n = (int)(w[6]); while (n--) { val = in[out_idx]; vDSP_vmul(x->a_b,1,x->a_x,1,x->a_tempVec,1,order); vDSP_sve(x->a_tempVec,1,&sum,order); val -= sum; //for (i=0; i < order; i++) val -= x->a_b[i] * x->a_x[i]; for (i=order-1; i>0; i--) x->a_x[i] = x->a_x[i-1]; x->a_x[0] = in[out_idx]; out[out_idx] = (float)val; out_idx++; } return (w+7); }
Pitch PitchDetector::process(float *input, unsigned int numberOfSamples) { assert(this->numberOfSamples==numberOfSamples); int n = numberOfSamples; float *originalReal = this->FFTBuffer; // 1.1.时域上加窗 vDSP_vmul(input, 1, this->windowFunc, 1, originalReal, 1, n); // 分前后加窗没什么不一样啊 // vDSP_vmul(input, 1, this->windowFunc, 1, originalReal+(n/2), 1, n/2); // vDSP_vmul(input+(n/2), 1, this->windowFunc+(n/2), 1, originalReal, 1, n/2); // 2.拆成复数形似{1+2i, 3+4i, ..., 1023+1024i} 原始数组可以认为是(COMPLEX*)交错存储 现在拆成COMPLEX_SPLIT非交错(分轨式)存储 vDSP_ctoz((COMPLEX*)originalReal, 2, &this->A, 1, n/2); // 读取originalReal以2的步长塞进A里面 // // 3.fft变换的预设 float originalRealInLog2 = log2f(n); // FFTSetup setupReal = vDSP_create_fftsetup(originalRealInLog2, FFT_RADIX2); // 4.傅里叶变换 vDSP_fft_zrip(this->setupReal, &this->A, 1, originalRealInLog2, FFT_FORWARD); // 5.转换成能量值 vDSP_zvabs(&this->A, 1, this->magnitudes, 1, n/2); Float32 one = 1; vDSP_vdbcon(this->magnitudes, 1, &one, this->magnitudes, 1, n/2, 0); // 6.获取基频f0 float maxValue; vDSP_Length index; vDSP_maxvi(this->magnitudes, 1, &maxValue, &index, n/2); // 6.1.微调参数 double alpha = this->magnitudes[index - 1]; double beta = this->magnitudes[index]; double gamma = this->magnitudes[index + 1]; double p = 0.5 * (alpha - gamma) / (alpha - 2 * beta + gamma); // 7.转换为频率 indexHZ = index * (SampleRate / (n/2)) float indexHZ = (index+p) * ((this->sampleRate*1.0) / n); // 8.乐理信息生成 Pitch pitch; pitch.frequency = indexHZ; pitch.amplitude = beta; pitch.key = 12 * log2(indexHZ / 127.09) + 28.5; pitch.octave = (pitch.key - 3.0) / 12 + 1; calStep(&pitch); pitch.stepString = calStep(indexHZ); return pitch; }
void ifft(FFT_FRAME* frame, float* outputBuffer) { // get pointer to fft object FFT* fft = frame->fft; // perform in-place fft inverse vDSP_fft_zrip(fft->fftSetup, &frame->buffer, 1, fft->logTwo, FFT_INVERSE); // The output signal is now in a split real form. Use the function vDSP_ztoc to get a split real vector. vDSP_ztoc(&frame->buffer, 1, (COMPLEX *)outputBuffer, 2, fft->sizeOverTwo); // This applies the windowing if (fft->window != NULL) vDSP_vmul(outputBuffer, 1, fft->window, 1, outputBuffer, 1, fft->size); }
void fft(FFT_FRAME* frame, float* audioBuffer) { FFT* fft = frame->fft; // Do some data packing stuff vDSP_ctoz((COMPLEX*)audioBuffer, 2, &frame->buffer, 1, fft->sizeOverTwo); // This applies the windowing if (fft->window != NULL) vDSP_vmul(audioBuffer, 1, fft->window, 1, audioBuffer, 1, fft->size); // Actually perform the fft vDSP_fft_zrip(fft->fftSetup, &frame->buffer, 1, fft->logTwo, FFT_FORWARD); // Do some scaling vDSP_vsmul(frame->buffer.realp, 1, &fft->normalize, frame->buffer.realp, 1, fft->sizeOverTwo); vDSP_vsmul(frame->buffer.imagp, 1, &fft->normalize, frame->buffer.imagp, 1, fft->sizeOverTwo); // Zero out DC offset frame->buffer.imagp[0] = 0.0; }
void FFTAccelerate::doFFTReal(float samples[], float amp[], int numSamples) { int i; vDSP_Length log2n = log2f(numSamples); int nOver2 = numSamples/2; //-- window //vDSP_blkman_window(window, windowSize, 0); vDSP_vmul(samples, 1, window, 1, in_real, 1, numSamples); //Convert float array of reals samples to COMPLEX_SPLIT array A vDSP_ctoz((COMPLEX*)in_real,2,&A,1,nOver2); //Perform FFT using fftSetup and A //Results are returned in A vDSP_fft_zrip(fftSetup, &A, 1, log2n, FFT_FORWARD); //Convert COMPLEX_SPLIT A result to float array to be returned amp[0] = A.realp[0]/(numSamples*2); for(i=1;i<numSamples/2;i++) amp[i]=sqrt(A.realp[i]*A.realp[i]+A.imagp[i]*A.imagp[i]); }
void fftIp(FFT* fftObject, float* audioBuffer) { // Creating pointer of COMPLEX_SPLIT to use in calculations (points to same data as audioBuffer) COMPLEX_SPLIT* fftBuffer = (COMPLEX_SPLIT *)&audioBuffer[0]; // Apply windowing if (fftObject->window != NULL) vDSP_vmul(audioBuffer, 1, fftObject->window, 1, audioBuffer, 1, fftObject->size); // This seems correct-ish TODO: check casting vDSP_ctoz((COMPLEX*)audioBuffer, 2, fftBuffer, 1, fftObject->sizeOverTwo); // Perform fft vDSP_fft_zrip(fftObject->fftSetup, fftBuffer, 1, fftObject->logTwo, FFT_FORWARD); // Do scaling vDSP_vsmul(fftBuffer->realp, 1, &fftObject->normalize, fftBuffer->realp, 1, fftObject->sizeOverTwo); vDSP_vsmul(fftBuffer->imagp, 1, &fftObject->normalize, fftBuffer->imagp, 1, fftObject->sizeOverTwo); // zero out DC offset fftBuffer->imagp[0] = 0.0; }
void fft::inversePowerSpectrum_vdsp(int start, float *finalOut, float *window, float *magnitude,float *phase) { uint32_t i; for (i = 0; i < half; i++) { // polar[2*i] = pow(10.0, magnitude[i] / 20.0) - 1.0; polar[2*i] = magnitude[i] - 1.0; polar[2*i + 1] = phase[i]; } vDSP_rect(polar, 2, in_real, 2, half); vDSP_ctoz((COMPLEX*) in_real, 2, &A, 1, half); vDSP_fft_zrip(setupReal, &A, 1, log2n, FFT_INVERSE); vDSP_ztoc(&A, 1, (COMPLEX*) out_real, 2, half); static float scale = 1./n; vDSP_vsmul(out_real, 1, &scale, out_real, 1, n); //multiply by window vDSP_vmul(out_real, 1, window, 1, finalOut, 1, n); }
void mul( const float *arrayA, const float *arrayB, float *result, size_t length ) { vDSP_vmul( arrayA, 1, arrayB, 1, result, 1, length ); }
// --------------------------------------------- // vector math // void siglab_sbMpy3(float *src1, float *src2, float *dst, int nel) { vDSP_vmul(src1, 1, src2, 1, dst, 1, nel); }
inline void maxiCollider::createGabor(flArr &atom, const float freq, const float sampleRate, const uint length, float startPhase, const float kurtotis, const float amp) { atom.resize(length); flArr sine; sine.resize(length); // float gausDivisor = (-2.0 * kurtotis * kurtotis); // float phase =-1.0; double *env = maxiCollider::envCache.getWindow(length); #ifdef __APPLE_CC__ vDSP_vdpsp(env, 1, &atom[0], 1, length); #else for(uint i=0; i < length; i++) { atom[i] = env[i]; } #endif //#ifdef __APPLE_CC__ // vDSP_vramp(&phase, &inc, &atom[0], 1, length); // vDSP_vsq(&atom[0], 1, &atom[0], 1, length); // vDSP_vsdiv(&atom[0], 1, &gausDivisor, &atom[0], 1, length); // for(uint i=0; i < length; i++) atom[i] = exp(atom[i]); //#else // for(uint i=0; i < length; i++) { // //gaussian envelope // atom[i] = exp((phase* phase) / gausDivisor); // phase += inc; // } //#endif float cycleLen = sampleRate / freq; float maxPhase = length / cycleLen; float inc = 1.0 / length; #ifdef __APPLE_CC__ flArr interpConstants; interpConstants.resize(length); float phase = 0.0; vDSP_vramp(&phase, &inc, &interpConstants[0], 1, length); vDSP_vsmsa(&interpConstants[0], 1, &maxPhase, &startPhase, &interpConstants[0], 1, length); float waveTableLength = 512; vDSP_vsmul(&interpConstants[0], 1, &waveTableLength, &interpConstants[0], 1, length); for(uint i=0; i < length; i++) { interpConstants[i] = fmod(interpConstants[i], 512.0f); } vDSP_vlint(sineBuffer2, &interpConstants[0], 1, &sine[0], 1, length, 514); vDSP_vmul(&atom[0], 1, &sine[0], 1, &atom[0], 1, length); vDSP_vsmul(&atom[0], 1, &, &atom[0], 1, length); #else maxPhase *= TWOPI; for(uint i=0; i < length; i++) { //multiply by sinewave float x = inc * i; sine[i] = sin((x * maxPhase) + startPhase); } for(uint i=0; i < length; i++) { atom[i] *= sine[i]; atom[i] *= amp; } #endif }