/******************************************************************************* Convolve */ Error_t Convolve(float *in1, unsigned in1_length, float *in2, unsigned in2_length, float *dest) { unsigned resultLength = in1_length + (in2_length - 1); #ifdef __APPLE__ //Use Native vectorized convolution function if available float *in2_end = in2 + (in2_length - 1); unsigned signalLength = (in2_length + resultLength); float padded[signalLength]; //float zero = 0.0; ClearBuffer(padded, signalLength); // Pad the input signal with (filter_length - 1) zeros. cblas_scopy(in1_length, in1, 1, (padded + (in2_length - 1)), 1); vDSP_conv(padded, 1, in2_end, -1, dest, 1, resultLength, in2_length); #else // Use (boring, slow) canonical implementation unsigned i; for (i = 0; i <resultLength; ++i) { unsigned kmin, kmax, k; dest[i] = 0; kmin = (i >= (in2_length - 1)) ? i - (in2_length - 1) : 0; kmax = (i < in1_length - 1) ? i : in1_length - 1; for (k = kmin; k <= kmax; k++) { dest[i] += in1[k] * in2[i - k]; } } #endif return NOERR; }
void CorrelationUGenInternal::processBlock(bool& shouldDelete, const unsigned int blockID, const int channel) throw() { const int blockSize = uGenOutput.getBlockSize(); int numSamplesToProcess = blockSize; float* inputASamples = inputs[InputA].processBlock(shouldDelete, blockID, channel); float* inputBSamples = inputs[InputB].processBlock(shouldDelete, blockID, channel); float* outputSamples = uGenOutput.getSampleData(); float* const windowsSamples = window.getDataUnchecked(0); float* const scoreSamples = score.getDataUnchecked(0); float* const bufferASamples = buffers.getDataUnchecked(InputBufferA); float* const bufferBSamples = buffers.getDataUnchecked(InputBufferB); float* const outputBufferSamples = buffers.getDataUnchecked(OutputBuffer); while(numSamplesToProcess > 0) { int bufferSamplesToProcess = length_ - bufferIndex; if(bufferSamplesToProcess > numSamplesToProcess) { // buffer the inputs memcpy(bufferASamples + bufferIndex, inputASamples, numSamplesToProcess * sizeof(float)); memcpy(bufferBSamples + bufferIndex, inputBSamples, numSamplesToProcess * sizeof(float)); bufferIndex += numSamplesToProcess; inputASamples += numSamplesToProcess; inputBSamples += numSamplesToProcess; // ...and the output - output the lockedIndexOfMax into the outputSamples outputIndex(outputSamples, numSamplesToProcess); // outputBuffer(outputSamples, numSamplesToProcess); // outputScore(outputSamples, numSamplesToProcess); outputSamples += numSamplesToProcess; numSamplesToProcess = 0; } else { numSamplesToProcess -= bufferSamplesToProcess; memcpy(bufferASamples + bufferIndex, inputASamples, bufferSamplesToProcess * sizeof(float)); memcpy(bufferBSamples + bufferIndex, inputBSamples, bufferSamplesToProcess * sizeof(float)); memset(outputBufferSamples, 0, (length_ + length_) * sizeof(float)); //apply windows for (int i = 0; i < length_; i++) { bufferASamples[i] *= windowsSamples[i]; bufferBSamples[i] *= windowsSamples[i]; } bufferIndex += bufferSamplesToProcess; inputASamples += bufferSamplesToProcess; inputBSamples += bufferSamplesToProcess; vDSP_conv (bufferASamples, 1, bufferBSamples, 1, outputBufferSamples, 1, length_, length_); for (int i = 0; i < length_; i++) scoreSamples[i] *= 0.9f; indexOfMax = findPeak(outputBufferSamples, length_); if ((indexOfMax >= 0) && (indexOfMax < length_)) { if (lockedIndexOfMax >= 0) { int diff = indexOfMax - lockedIndexOfMax; if (diff < 0) diff = -diff; int maximum = length_ / 4; diff = ugen::min(diff, maximum); int score = maximum - diff; float fScore = (float)score / maximum; fScore = ugen::cubed(fScore); scoreSamples[indexOfMax] += fScore; } else { scoreSamples[indexOfMax] += 1.f; } } lockedIndexOfMax = findPeak(scoreSamples, length_); // output the lockedIndexOfMax into the outputSamples outputIndex(outputSamples, bufferSamplesToProcess); // outputBuffer(outputSamples, bufferSamplesToProcess); // outputScore(outputSamples, bufferSamplesToProcess); outputSamples += bufferSamplesToProcess; bufferSamplesToProcess = 0; bufferIndex = 0; } } }