Hello,
I would like to timestretch a sound in realtime with FMOD, using a combination of FMOD_DSP_TYPE_PITCHSHIFT and changing channel frequency, as described in earlier posts. The stretch ratio would be adjusted in realtime based on user input.
The timestretch is working, and the overall quality is acceptable. However, at the time of every change of stretch ratio, there is a short audible audio glitch in the sound - it sounds like it goes slightly out of pitch for a moment.
I tried a number of things, such as:
-pausing sound before calling the DSP parameter change and channel frequency change, then unpausing it right after
-reducing the DSP buffer size
-applying the DSP to Master channel group instead of individual channel
-gradual ramp-up to the new stretch ratio
The audible glitch is still there, every time the speed of sound change gets called.
I would be very grateful for any ideas or suggestions. My last resort would be to start exploring third-party timestretch libraries, through DSP callback with FMOD – however, I wanted to check if I am not missing something obvious here, before going down that route.
Extracts from code are below:
FMOD::System* mpSystem;
FMOD::DSP *myDSP;
FMOD::Channel *mChannel;
//initialize system
FMOD::System_Create(&mpSystem);
mpSystem->setDSPBufferSize(256, 8) );
mpSystem->setSoftwareFormat(0, FMOD_SPEAKERMODE_STEREO, 0);
mpSystem->init(32, FMOD_INIT_NORMAL, extraDriverData);
//Create sound
mpSystem->createSound(strSoundName.c_str(), FMOD_2D | FMOD_LOOP_OFF | FMOD_CREATESAMPLE, nullptr, &mSound);
//Play sound
mpSystem->playSound(sgpImplementation->mSound, nullptr, true, &mChannel));
if (mChannel)
{
mChannel->setVolume(1.0));
mChannel->setPaused(false));
}
…
//Set up the pitch shift dsp
mpSystem->createDSPByType(FMOD_DSP_TYPE_PITCHSHIFT, &myDSP));
myDSP->setParameterFloat(0, 1); //set pitch to 1
myDSP->setParameterFloat(1, 4096); // set FFT buffer size to 4096
mChannel->setMode(FMOD_2D);
mChannel->addDSP(0, myDSP);
…
//Do the timestretch - stretchval in the range of 0.5 to 2.0
mChannel->setFrequency(stretchVal * 44100.0);
myDSP->setParameterFloat(0, 1.0/stretchVal);