Hi, I tried to implement Lagrange interpolation in a SamplerVoice inherited class replacing this:
while (--numSamples >= 0)
{
auto pos = (int) sourceSamplePosition;
auto alpha = (float) (sourceSamplePosition - pos);
auto invAlpha = 1.0f - alpha;
// just using a very simple linear interpolation here..
float l = (inL[pos] * invAlpha + inL[pos + 1] * alpha);
sourceSamplePosition += pitchRatio;
}
But it produces strange artifacts when playing. Iām sure Iām doing something wrong, but I ignore the reason.
Iām playing an upgraded to 96Khz sine wave sample (using the same Lagrange class, which works fine here), and then resampling it to 44.1Khz in the code used before.
Please, could someone point me in the right direction?
You need to render the amount of samples into the resampler based on the resampling factor, then produce the true numSamplesNeeded.
So if you wanted to go from 88.2k to 44.1k
for (int sample = 0; sample < numSample * 2; sample++) {
in[sample] = sampleAt88.2k[readhead]
readhead += 1 // or your "pitchRatio"
}
interpolator.process(2, in, out, numSamples)
Apologies if iām mistaken reading your source code and this is the approach, but it looks like pitchRatio is somehow being used as a factor in resampling. you should iterate through your source by 1 and resample at the ratio (sourceRate / sampleRate) ā to render it at the same pitch. In any case your desired pitch change / speed you go through the source buffer, doesnāt have much to do with you resampling factor
Well, the solution wasā¦ embarrassingā¦ the weird things I was listening was the host clippingā¦ The piece of code I placed originally seems work fine.
Juan could you provide the full code?
I am also hearing artifacts. I believe because of the casting of the sourceSamplePosition from float to int. I think the āquantisingā introduces little clicks each render of a blockā¦
Hi @dataexcessaudio, the juce interpolator store these remaining decimals inside a variable to use it in the next call. I had a lot of problems with the interpolators (non-related to juce) and I ended creating one myself, based on hermite. But the main point here is it works in the same way. This how I do the call, and as you see, Iām casting a double variable (inPos) to int too:
I actually already fixed it. The problem I was having was the fractional offset caused by the fractional ratio. I had to recalculate the input buffer to account for the fractional part. Shifting all the values so to speak. Iāve put my answer in this thread if youāre interested:
I am trying to implement LagrangeInterpolation into my sampler voice, and iām having issues, iām getting a click every buffer length (2 samples of silence).
This is my current code - wonder if you or anyone else can see what Iām doing wrong?
I feel like it may have to do with your inPos32 or s variables. Thanks
You are passing to your interpolator a nullptr when the signal is mono! (that will produce an error) Simply create an āifā instead that ternary operator thing.
If the code you are showing belong to any kind of processBlock() call (and I really suspect it due to the last line where you advance the position), keep in mind that resamplers are stateful, this mean you need to create an object per audio channel and donāt destroy it. Just create them as member variable. Then only use reset when something really drastic happens to the sample, ie, you load a new one.
The sample dropouts are not as bad as they were!
But still getting clicks when I play pitched samples, any thoughts?? You have no idea how much I appreciate it!
Assuming pitchRatio is right, I donāt see nothing wrong with your source. However, when I posted this I was having similar issues. I found another interpolation algo which I adapted and it worked for me. Unfortunately I donāt remember the link, but I could share it with you (itās an hermite one, however).
You also may try with another juce interpolator to check if there are any problem with it
Thanks!! Got it working but iām still having some light clicking noises happening that I cant figure out the source of They seem to be happening at the start of each buffer. I believe that its my implementation thatās wrong, not the interpolators.
Would love to know if you can see anything wrong with what iām doing ?? even has the clicks when I use a linear interpreter. Thank you !!
Instead, each voice should have its own buffers created and resized as a member variable. Use the AudioProcessor::prepareToPlay() for that. And instead using that buffer, use an dsp::AudioBlock which point to it. The reason is that AudioBlock is lighter (since it hasnāt that atomic flag). Usually I keep both of them as member variables in each voice, then I only use the AudioBlock.
Then, if you suspect the host may send you bigger buffers sizes, you can do something like this at the beggining of your processBlock:
const int numSamples = audioBuffer.getNumSamples();
for (int i=0; i!=numSamples; )
{
const int max = jmin((numSamples - i), m_maxBufferSize);
dsp::AudioBlock<float> outBlock = dsp::AudioBlock<float>(writeData, 2, i, max);
// Then you process the blocks here
i += max;
}
How are you creating a dsp::AudioBlock inside each voice? Are you modifying the modules or creating an inherited class?
Iāve been modifying the juce modules (which I know your advised not to do but I cant see how to do it another way) but I canāt get the dsp files to be included and im getting the error āUse of undeclared identifier ādspāā.