Hi all,
I’m a newbie JUCE user trying to implement a pitch-shifter plugin. (By pitch-shifter, I mean retain original playback speed, but change the pitch). I’m using the Soundtouch library, and roughly following the usage in this pehrtree github project.
The pitch shifting sort of works, but the output has a lot of noise in it, crackles, pops, and it also seems to retain the original signal. I’d like only the pitch shifted signal. I suspect I’m not using the library properly at all, and would appreciate advice or comments. The relevant code is included below.
Thanks in advance!
In PluginProcessor.h:
int semitone_shift = 0;
soundtouch::SoundTouch shifter;
In PluginEditor.cpp, in the callback for slider value changed:
audioProcessor.semitone_shift = (int) slider->getValue();
audioProcessor.shifter.setPitchSemiTones(audioProcessor.semitone_shift);
Setup the SoundTouch object, in PluginProcessor.cpp:
void Pitch_shiftAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock)
{
// Use this method as the place to do any pre-playback
// initialisation that you need..
shifter.setSampleRate((int)sampleRate);
shifter.setChannels(2);
}
And the main processing, in PluginProcessor.cpp:
void Pitch_shiftAudioProcessor::processBlock (juce::AudioBuffer<float>& buffer, juce::MidiBuffer& midiMessages)
{
juce::ScopedNoDenormals noDenormals;
auto totalNumInputChannels = getTotalNumInputChannels();
auto totalNumOutputChannels = getTotalNumOutputChannels();
// In case we have more outputs than inputs, this code clears any output
// channels that didn't contain input data, (because these aren't
// guaranteed to be empty - they may contain garbage).
// This is here to avoid people getting screaming feedback
// when they first compile a plugin, but obviously you don't need to keep
// this code if your algorithm always overwrites all the output channels.
for (auto i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
buffer.clear (i, 0, buffer.getNumSamples());
// This is the place where you'd normally do the guts of your plugin's
// audio processing...
// Make sure to reset the state if your inner loop is processing
// the samples and the outer loop is handling the channels.
// Alternatively, you can process the samples with the channels
// interleaved by keeping the same state.
int numSamples = buffer.getNumSamples();
for (int channel = 0; channel < totalNumInputChannels; ++channel)
{
auto* channelData = buffer.getWritePointer (channel);
// ..do something to the data...
}
shifter.putSamples(buffer.getReadPointer(0), numSamples);
shifter.receiveSamples(buffer.getWritePointer(0), numSamples);
}