@Christoph-Hart
I added an updateDelta method:
void updateDelta()
{
double semitones = (pitch - 0.5) * 48.0;
double pitch_mult = Math.pow(2.0, semitones / 12.0);
if (data.numSamples > 0 && sr != 0.0) {
const auto newDelta = (data.sampleRate / sr) * pitch_mult;
for (auto& v : voiceData) {
v.delta = newDelta;
}
}
}
And then in the setParameter method I did this:
template <int P> void setParameter(double v)
{
if (P == 0)
{
pitch = v;
updateDelta();
}
}
And then in setExternalData I did this:
void setExternalData(const ExternalData& ed, int index)
{
data = ed;
ed.referBlockTo(sample[0], 0);
ed.referBlockTo(sample[1], 1);
if(data.numSamples > 0 && sr != 0.0)
{
const auto delta = (data.sampleRate / sr) * pitch;
for(auto& v: voiceData)
{
v.delta = delta;
updateDelta();
}
}
}
And I'm getting what I was after I think. I can set my pitch parameter, trigger a voice, and the voice will initialise with the pitch adjustment I've set. Then throughout the length of the sample playing back, I can continue to adjust the pitch and it will change the rate of playback.
The actual parameter in the SNEX module snaps to values of 0.021 in order to simulate snapping to semitones. The updateDelta() function will take the knob values and snap the pitch multiplier to the correct values so that I get -24 and +24 semitone pitch shifting.
I guess now if I wanted a fine-tune pitch knob, I could do the same thing, but change the ranges and multiply the delta by that as well.