Optimize circular ring bugger for coefficients

This commit is contained in:
DataHoarder 2022-07-15 15:05:37 +02:00
parent c20789e8ce
commit 57709448de
Signed by: DataHoarder
SSH key fingerprint: SHA256:OLTRf6Fl87G52SiR7sWLGNzlJt4WOX+tfI2yxo0z7xk

View file

@ -56,10 +56,8 @@ public:
coefficientSize = (latency + 2*blockSize) / frequencyBinTimeStepSize;
coefficients.resize(coefficientSize);
for (auto & coefficient : coefficients){
coefficient.resize(numberOfBandsCache);
}
//Allocate ring buffer and members in a contiguous array
coefficients = static_cast<float *>(calloc(coefficientSize * numberOfBandsCache, sizeof(float)));
assert(t_in == 0);
@ -94,7 +92,9 @@ public:
return numberOfBandsCache;
}
~Gaborator()= default;
~Gaborator() {
free(coefficients);
}
private:
@ -122,27 +122,17 @@ private:
//flush remaining
for (int i = 1; i < coefficientSize; ++i) {
int64_t circularIndex = (mostRecentCoefficentIndex + i) % coefficientSize;
float* currentCoefficient = &coefficients[((mostRecentCoefficentIndex + i) % coefficientSize) * numberOfBandsCache];
auto& currentCoefficient = coefficients[circularIndex];
resultCache.insert(resultCache.end(), currentCoefficient.begin(), currentCoefficient.end());
resultCache.insert(resultCache.end(), currentCoefficient, currentCoefficient + numberOfBandsCache);
// fill the oldest with zeros, but only the first round
if(i <= coefficientSize) {
std::fill(currentCoefficient.begin(), currentCoefficient.end(), 0);
std::fill(currentCoefficient, currentCoefficient + numberOfBandsCache, 0);
}
}
}
inline void gaborApplySlice(int64_t st0, int64_t st1) {
/*
Following code is equivalent, but it has been inlined for performance
gaborator::process([&](int band, int64_t audioSampleIndex, std::complex<float>& coef) {
gaborProcessEntry(band, audioSampleIndex, coef);
}, min_band, INT_MAX, st0, st1, coefs);
*/
//Adjust start to match gaborProcessEntry requirements
if((st0 / frequencyBinTimeStepSize) <= 0){
st0 = frequencyBinTimeStepSize;
@ -153,6 +143,17 @@ private:
return;
}
int b0 = min_band;
int b1 = numberOfBandsCache + firstBandCache;
/*
Following code is equivalent, but it has been inlined for performance
gaborator::process([&](int band, int64_t audioSampleIndex, std::complex<float>& coef) {
gaborProcessEntry(band, audioSampleIndex, coef);
}, b0, b1, st0, st1, coefs);
*/
gaborator::apply_to_slice(false, [&](int band, int64_t sampleIndex, int time_step, unsigned len, const std::complex<float> *p0) {
//process magnitudes beforehand for easier auto-vectorization
@ -180,23 +181,21 @@ private:
for (int64_t j = i; j < len; j++) {
#else
for (unsigned int j = 0; j < len; j++) {
for (int64_t j = 0; j < len; j++) {
#endif
magnitudeCache[j] = std::abs(p0[j]);
}
for(auto magnitude : magnitudeCache){
gaborProcessEntry(band, sampleIndex, magnitude);
sampleIndex += time_step;
int bandIndex = band - firstBandCache;
for (unsigned int j = 0; j < len; j++) {
gaborProcessEntry(bandIndex, (sampleIndex + time_step * j) / frequencyBinTimeStepSize, magnitudeCache[j]);
}
}, min_band, numberOfBandsCache + firstBandCache, st0, st1, coefs);
}, b0, b1, st0, st1, coefs);
}
inline void gaborProcessEntry(int band, int64_t sampleIndex, float coefficient) {
int64_t coefficientIndex = sampleIndex / frequencyBinTimeStepSize;
int bandIndex = band - firstBandCache;
int64_t circularIndex = coefficientIndex % coefficientSize;
auto& currentCoefficient = coefficients[circularIndex];
inline void gaborProcessEntry(int bandIndex, int64_t coefficientIndex, float coefficient) {
float* currentCoefficient = &coefficients[(coefficientIndex % coefficientSize) * numberOfBandsCache];
// If a new index is reached, save the old (fixed) coefficients in the history
// Fill the array with zeros to get the max
@ -205,16 +204,15 @@ private:
mostRecentCoefficentIndex = coefficientIndex;
// "copy" the oldest data to the history
// the slice can be reused thanks to the oldest being filled with zeros just after
resultCache.insert(resultCache.end(), currentCoefficient.begin(), currentCoefficient.end());
resultCache.insert(resultCache.end(), currentCoefficient, currentCoefficient + numberOfBandsCache);
// fill the oldest with zeros
std::fill(currentCoefficient.begin(), currentCoefficient.end(), 0);
std::fill(currentCoefficient, currentCoefficient + numberOfBandsCache, 0);
}
// due to reduction in precision (from audio sample accuracy to steps) multiple
// magnitudes could be placed in the same stepIndex, bandIndex pair.
// We take the maximum magnitudes value.
currentCoefficient[bandIndex] = std::max(currentCoefficient[bandIndex], coefficient);
}
private:
@ -222,12 +220,12 @@ private:
std::vector<float> resultCache;
//circular buffer with current coefficents
std::vector<std::vector<float>> coefficients;
//circular buffer with current coefficients
float* coefficients = nullptr;
int firstBandCache = -1;
int numberOfBandsCache = 0;
//The index of the most recent coefficent (in steps)
//The index of the most recent coefficient (in steps)
int64_t mostRecentCoefficentIndex = 0;
const int blockSize;