@eyalamir I’m allocating buffer only in the prepareToPlay(), not in the realtime thread.
Here is my code with c array:
// 256 * 4 oversampling with 2 channels
typedef double SynthBuffer[constants::BUFFER_SIZE_OVERSAMPLING][constants::CHANNELS_COUNT];
...
inline void processBlock(OscState &oscState, SynthBuffer &buffer, int length) {
auto maxFreq = sampleRate_ * 0.5;
SynthBuffer preBuffer;
for (int i = 0; i < length; ++i) {
preBuffer[i][0] = 0.0;
preBuffer[i][1] = 0.0;
}
for (int i = 0; i < length; ++i) {
// Some ramp and matrix tasks
processRamp();
updateState(oscState);
// Get frequency
auto freq = oscState.freq;
applyFineAndSemi(freq);
freq = tools::clamp(freq, constants::MIN_FREQ, maxFreq);
// Determinate octave for wavetable
auto octave = tools::getOctaveByFreq(freq);
uint32_t sampleOffset = 3 * constants::SAMPLE_LENGTH; // morphIndex * sampleCount;
// Get wave from Wavetable
auto *sample = oscWaveShape.sample_[octave] + sampleOffset;
for (int u = 0; u < numOfUnison_; ++u) {
auto pos = oscState.samplePosition[u];
double sound = sample[uint32_t(pos)];
preBuffer[i][0] += sound * unisonPanMultipliers_[u][0]; // make our unison stereo
preBuffer[i][1] += sound * unisonPanMultipliers_[u][1];
}
// Move sample position in separate loop. +20-30% of performance
for (int u = 0; u < numOfUnison_; ++u) {
auto &pos = oscState.samplePosition[u];
pos = pos + (freq * freqMultipliers_[u]); // * unison detune
if (pos >= constants::SAMPLE_LENGTH_DOUBLE) {
pos = pos - constants::SAMPLE_LENGTH_DOUBLE;
}
}
}
// apply gain
auto gain = oscState.gain;
for (int i = 0; i < length; ++i) {
buffer[i][0] += preBuffer[i][0] * gain;
buffer[i][1] += preBuffer[i][1] * gain;
}
}
Code with AudioBuffer:
void prepareToPlay(int samplesPerBlockExpected, double sampleRate) {
sampleRate_ = sampleRate;
delete preBuffer_;
preBuffer_ = new AudioBuffer<double>(constants::CHANNELS_COUNT, samplesPerBlockExpected);
}
inline void processBlock(OscState &oscState, AudioBuffer<double> &buffer) {
auto maxFreq = sampleRate_ * 0.5;
int length = buffer.getNumSamples();
preBuffer_->clear();
for (int i = 0; i < length; ++i) {
// Some ramp and matrix tasks
processRamp();
updateState(oscState);
// Get frequency
auto freq = oscState.freq;
applyFineAndSemi(freq);
freq = tools::clamp(freq, constants::MIN_FREQ, maxFreq);
// Determinate octave for wavetable
auto octave = tools::getOctaveByFreq(freq);
uint32_t sampleOffset = 3 * constants::SAMPLE_LENGTH; // morphIndex * sampleCount;
// Get wave from Wavetable
auto *sample = oscWaveShape.sample_[octave] + sampleOffset;
for (int u = 0; u < numOfUnison_; ++u) {
auto pos = oscState.samplePosition[u];
double sound = sample[uint32_t(pos)];
preBuffer_->addSample(0, i, sound * unisonPanMultipliers_[u][0]); // make our unison stereo
preBuffer_->addSample(1, i, sound * unisonPanMultipliers_[u][1]);
}
// Move sample position in separate loop. +20-30% of performance
for (int u = 0; u < numOfUnison_; ++u) {
auto &pos = oscState.samplePosition[u];
pos = pos + (freq * freqMultipliers_[u]); // * unison detune
if (pos >= constants::SAMPLE_LENGTH_DOUBLE) {
pos = pos - constants::SAMPLE_LENGTH_DOUBLE;
}
}
}
// apply gain
auto gain = oscState.gain;
for (int i = 0; i < length; ++i) {
buffer.addSample(0, i, preBuffer_->getSample(0, i) * gain);
buffer.addSample(1, i, preBuffer_->getSample(1, i) * gain);
}
}
private:
...
AudioBuffer<double> *preBuffer_{};
I tried also to work with “getArrayOfWritePointers()” or “getArrayOfReadPointers()”, but same result.
And important note. If I don’t use “preBuffer” but directly adding sample to the incoming buffer from function, then the CPU even with c array - 120%.
My wavetable is 10 x 128 x 1024 size. i.e. 10 octaves, in one octave - 128 waves with length 1024 sample. p.s. even if I will use simple double[1024] the performance is same, so for sure, the issue not with wavetable