COCKOS
CONFEDERATED FORUMS
Cockos : REAPER : NINJAM : Forums
Forum Home : Register : FAQ : Members List : Search :

Go Back   Cockos Incorporated Forums > Other Software Discussion > WDL users forum

Reply
 
Thread Tools Display Modes
Old 06-30-2016, 07:52 AM   #1
SaschArt
Human being with feelings
 
SaschArt's Avatar
 
Join Date: Aug 2013
Posts: 236
Default Delay with smooth changing delay rate

I made a delay in IPlug but have a problem. Crackling when change rate delay from slider. How smooth changing delay rate to prevent crackling? The recorder is enough to playback I do no why have this.

Code:
repos=pos-delayL;
if (repos<0) repos=buf_size+repos;

replay1=*(buffer+repos);
replay2=*(buffer+repos+1);

*(buffer+pos)=min(*in1 + replay1*feedback,4);
*(buffer+pos+1)=min(*in2 + replay2*feedback,4);

pos=pos+2;
if (pos>= buf_size) pos=0;

*out1=*in1*drymix + replay1*wetmix;
*out2=*in2*drymix + replay2*wetmix;
Tried more simple code with small recorder surprisingly with less crackling

Code:
replay1=*(buffer+pos);
replay2=*(buffer+pos+1);

*(buffer+pos)=min(*in1 + replay1*feedback,4);
*(buffer+pos+1)=min(*in2 + replay2*feedback,4);

pos=pos+2;
if (pos>= delayL*2) pos=0;

*out1=*in1*drymix + replay1*wetmix;
*out2=*in2*drymix + replay2*wetmix;

Last edited by SaschArt; 07-01-2016 at 01:59 PM.
SaschArt is offline   Reply With Quote
Old 07-01-2016, 01:56 AM   #2
SaschArt
Human being with feelings
 
SaschArt's Avatar
 
Join Date: Aug 2013
Posts: 236
Default

No one knows the solution ?
SaschArt is offline   Reply With Quote
Old 07-01-2016, 04:33 AM   #3
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,645
Default

You could try to smooth your slider, but I guess the real problem is that you are using truncation when indexing your buffer. Implementing some sort of interpolation (even linear interpolation) would probaly help a lot.
Tale is offline   Reply With Quote
Old 07-01-2016, 05:37 AM   #4
Staiff
Human being with feelings
 
Join Date: May 2016
Posts: 34
Default

hello !
in my case:
Code:
//delay.h

#pragma once

enum DelayMode
{
	OFF,
	CLASSIC,
	PING_PONG,
	INVERTED,
	kNumDelayModes
};

class DelayGenerator
{
protected:
	int mMode;
	unsigned long delaySamples, bufferSize, dynamicBufferSize, mOffset;
	double* bufferR;
	double* bufferL;
	double mMix;
	int feedsCount;
	double feedsCountM;

	void ClearBuffers()
	{
		for (i = 0; i < bufferSize; i++)
		{
			bufferL[i] = 0.0;
			bufferR[i] = 0.0;
		}
	}

	void UpdateBuffers(double* outL, double* outR)
	{
		bufferL[mOffset] = 0.0;
		bufferR[mOffset] = 0.0;
		
		for (i = 1; i < feedsCountM; i++)
		{
			fact = (feedsCountM - i) / feedsCountM;
			ind = (i * delaySamples + mOffset) % bufferSize;
			switch(mMode)
			{
				case CLASSIC:
					bufferL[ind] += *outL * fact;
					bufferR[ind] += *outR * fact;
					break;
				case PING_PONG:
					if (i % 2 == 0)
					{
						bufferL[ind] += *outL * fact;
					}
					else
					{
						bufferR[ind] += *outR * fact;
					}
					break;
				case INVERTED:
					bufferL[ind] += *outR * fact;
					bufferR[ind] += *outL * fact;
					break;
			}
		}

		mOffset++;
		if (mOffset >= bufferSize) mOffset = 0;
	}
public:
	DelayGenerator(void)
	{
		bufferSize = (unsigned long)(int(DELAY_TIME_MAX) * DELAY_FEED_MAX * long(SAMPLE_RATE));
		bufferR = new double[bufferSize];
		bufferL= new double[bufferSize];
		feedsCount = DELAY_FEED_DEFAULT;
		delaySamples = long(DELAY_TIME_DEFAULT) * long(SAMPLE_RATE);
		dynamicBufferSize = feedsCount * delaySamples;
		mMix = 0.3;
		mOffset = 0;
		mMode = OFF;
		ClearBuffers();
	}

	~DelayGenerator(void)
	{
		ClearBuffers();
		delete bufferR;
		delete bufferL;
	}

	void SetDelayTime(double timeMS) { delaySamples = long(timeMS * long(SAMPLE_RATE)); }

	void SetFeedsCount(int count) 
	{ 
		feedsCount = count; 
		feedsCountM = count + 1;
	}

	void SetMode(int mode) 
	{ 
		mMode = mode; 
		ClearBuffers();
	}

	void SetMix(double mix) { mMix = mix; }

	void process(double* outL, double* outR)
	{
		if (mMode == OFF) return;

		tempR = bufferR[mOffset], tempL = bufferL[mOffset];
		UpdateBuffers(outL, outR);
		*outL = *outL * (1 - mMix) + tempL * mMix;
		*outR = *outR * (1 - mMix) + tempR * mMix;
	}

private:
	unsigned long i, ind;
	double tempR, tempL, fact;
};
i'm not the coder: it's Alexey55 (https://github.com/Alexey55/Plug-In/...layGenerator.h)

it works for me. But i don't know if you use the same delay/code/algo.
Staiff is offline   Reply With Quote
Old 07-01-2016, 07:05 AM   #5
SaschArt
Human being with feelings
 
SaschArt's Avatar
 
Join Date: Aug 2013
Posts: 236
Default

Quote:
Originally Posted by Tale View Post
You could try to smooth your slider, but I guess the real problem is that you are using truncation when indexing your buffer. Implementing some sort of interpolation (even linear interpolation) would probaly help a lot.
Sound very clear when no slider changing, if it was incorrectly indexed buffer was not supposed to sound distorted?

Quote:
Originally Posted by Staiff View Post
hello !
in my case: .....

i'm not the coder: it's Alexey55 (https://github.com/Alexey55/Plug-In/...layGenerator.h)

it works for me. But i don't know if you use the same delay/code/algo.
There is a lot of handy codes, thanks, will check
SaschArt is offline   Reply With Quote
Old 07-01-2016, 09:18 AM   #6
SaschArt
Human being with feelings
 
SaschArt's Avatar
 
Join Date: Aug 2013
Posts: 236
Default

Staiff I tested Alexey55 delay solution and crackling a lot. Try to change delay time while using keyboard.
SaschArt is offline   Reply With Quote
Old 07-01-2016, 11:01 AM   #7
Staiff
Human being with feelings
 
Join Date: May 2016
Posts: 34
Default

maybe i will say stupid thing but: do you test in debug or release mod ?

if i test in debug i've crackles, even with osc.
if i test in release all work fine.

why ?
i don't know.
Staiff is offline   Reply With Quote
Old 07-01-2016, 11:21 AM   #8
SaschArt
Human being with feelings
 
SaschArt's Avatar
 
Join Date: Aug 2013
Posts: 236
Default

I tested FirstPlugIn.dll version from archive build by Alexey55, May be you don't try to change delay time.
SaschArt is offline   Reply With Quote
Old 07-02-2016, 01:35 AM   #9
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,645
Default

Quote:
Originally Posted by SaschArt View Post
Sound very clear when no slider changing, if it was incorrectly indexed buffer was not supposed to sound distorted?
Here is what I think happens: You have a delay of 1 sample, which sounds good. Then you slowly increase it to 1.1, 1.2, etc., up to 2 samples. While changing it nothing happens (because 1.x gets rounded down to 1), until it gets to 2 samples, when it very suddenly changes the delay from 1 to 2 samples. I think these sudden, non-fractional steps cause crackling.
Tale is offline   Reply With Quote
Old 07-02-2016, 04:00 AM   #10
Youlean
Human being with feelings
 
Youlean's Avatar
 
Join Date: May 2015
Location: Serbia
Posts: 654
Default

Try this:
Code:
#include <vector>

using namespace std;

class InterpolatedDelay
{
public:

	void SetMaxBufferSize(int size)
	{
		mem.resize(size);
		MAXDELAY = size;
	}

	double DelaySignal(double in, double delaySamples)
	{
		mem[index] = in;

		intdelay = int(delaySamples - 0.4999999999);
		frac = delaySamples - double(intdelay);

		temp1 = index - intdelay;
		temp2 = temp1 - 1;

		if (temp1 < 0)
		temp1 = temp1 + (double)MAXDELAY;
		temp1 = mem[(int)temp1];

		if (temp2 < 0)
		temp2 = temp2 + (double)MAXDELAY;
		temp2 = mem[(int)temp2];

		frac = (1 - frac) / (1 + frac);
		out = temp2 + frac * (temp1 - out1);
		out1 = out;

		index = index + 1;
		if (index > MAXDELAY) index = 0;
	}

private:
	int index;
	int intdelay;
	double frac;
	double temp1, temp2;
	double out = 0.0, out1 = 0.0;
	vector <double> mem;
	int MAXDELAY;
};
Youlean is offline   Reply With Quote
Old 07-02-2016, 12:53 PM   #11
SaschArt
Human being with feelings
 
SaschArt's Avatar
 
Join Date: Aug 2013
Posts: 236
Default

Quote:
Originally Posted by Tale View Post
Here is what I think happens: You have a delay of 1 sample, which sounds good. Then you slowly increase it to 1.1, 1.2, etc., up to 2 samples. While changing it nothing happens (because 1.x gets rounded down to 1), until it gets to 2 samples, when it very suddenly changes the delay from 1 to 2 samples. I think these sudden, non-fractional steps cause crackling.
My sliders for delay rate are beat sync 1/8, 1/4T,1/8D,1/4 etc


Quote:
Originally Posted by Youlean View Post
Try this:
I will check , thanks but at first sight can not find where to return DelaySignal

Last edited by SaschArt; 07-02-2016 at 01:47 PM.
SaschArt is offline   Reply With Quote
Old 07-03-2016, 12:10 AM   #12
stw
Human being with feelings
 
stw's Avatar
 
Join Date: Apr 2012
Posts: 279
Default

Quote:
Originally Posted by SaschArt View Post
I will check , thanks but at first sight can not find where to return DelaySignal
Add "return out" at the end
stw is offline   Reply With Quote
Old 07-03-2016, 12:30 AM   #13
Youlean
Human being with feelings
 
Youlean's Avatar
 
Join Date: May 2015
Location: Serbia
Posts: 654
Default

Quote:
Originally Posted by stw View Post
Add "return out" at the end
Yep, this should be nice.. 😁
I didn't tested this, but it should work, I converted this from Flowstone interpolated delay module. If you still get glitches, applay low pass filter on parameter...
Youlean is offline   Reply With Quote
Old 07-03-2016, 05:22 AM   #14
Fergler
Human being with feelings
 
Fergler's Avatar
 
Join Date: Jan 2014
Posts: 5,207
Default

Wish ReaDelay worked like this
Fergler is online now   Reply With Quote
Old 07-04-2016, 03:01 AM   #15
jack461
Human being with feelings
 
jack461's Avatar
 
Join Date: Nov 2013
Location: France
Posts: 181
Default

Hi SaschArt !

Quote:
Originally Posted by SaschArt View Post
No one knows the solution ?
I use the following code to read a value from a buffer:
Code:
inline double readBuff(double * Buff, double ind)
{
    long pos;
    double x_1, x0, x1, x2;
    double a, b, c;
    double delta;
    if (ind < 0.0) ind += EchBuffsiz; 
    pos = (long)(ind);
    delta = ind - (double) pos;
    x_1 = Buff[(pos-1) & EchBuffMask];
    x0  = Buff[(pos) & EchBuffMask];
    x1  = Buff[(pos+1) & EchBuffMask];
    x2  = Buff[(pos+2) & EchBuffMask];
    a = (3.0 * (x0-x1) - x_1 + x2) / 2.0;
    b = 2.0*x1 + x_1 - (5.0*x0 + x2) / 2.0;
    c = (x1 - x_1) / 2.0;
    return (((a * delta) + b) * delta + c) * delta + x0;
}
The buffer is Buff, the buffer size is EchBuffsiz, a power of 2, with EchBuffMask= EchBuffsiz-1; ind is the fractional index. It is usually the write position in the buffer, minus a variable delay.
And I use a low pass filter when I perform large changes in the delay.

Precisely, the write position (Wp, an integer) is incremented by 1 for every sample, the delay (Dy, any number), is fixed for a while, and the delay variations (Dv, typically a LFO, an envelop, a parameter from GUI, etc.) is filtered at audio rate. The call is :
Code:
out=readBuff(Buffer, Wp-Dy-Dv);
Reaching a new delay value target (DelayTarget) after a change can be linear (increment = (DelayTarget-Dv)/timeToReachInNumberOfSamples; then use Dv=Dv+increment; in audio loop) or exponential (like Dv=(1.0-A)*Dv+A*DelayTarget; with A between 0.01 and 0.000001 for fast to slow variations, nice for suddenly changing DelayTarget), and execute a test to set Dv=DelayTarget; when the values are very close.

Hope this helps. This works very well for me.
jack461 is offline   Reply With Quote
Old 09-08-2016, 07:01 AM   #16
SaschArt
Human being with feelings
 
SaschArt's Avatar
 
Join Date: Aug 2013
Posts: 236
Default

Thanks for all the posts and help

I test this codes but the results not satisfied me enough. So I did my own research, to see exactly what is happen when the rate change. I made a micro-oscilloscope which stop exactly when the rate change, here's the result:




So the wave are cut, this is the problem. My solution was crossfade about 50-100ms from older wave to the new. The result is perfect and no need any filter, I made all my delays with this solution and works very well.
Attached Images
File Type: gif delay-smooth.gif (2.5 KB, 723 views)
__________________
Audio plugins | BrainWaveProducer | EmRysRa
SaschArt is offline   Reply With Quote
Old 09-20-2016, 10:01 AM   #17
bozmillar
Human being with feelings
 
bozmillar's Avatar
 
Join Date: Sep 2009
Posts: 623
Default

Think of it like a looping tape, and changing the delay time is just moving the head. If you move the head 6 inches instantaneously, it's going to pop. If you move it slowly, it will do sort of a pitch shift thingy while it's moving.

To get smooth delay changes you have to:

1) Prevent the delay value from changing too fast. A simple LPF on the delay value can fix this.

2) Interpolate the delay value between samples. that way as you move your delay value, it has a continuous waveform to pull from.

3) Keep your delay buffer the same size. Obviously if you are resizing your buffer for every delay change, you are going to get pops and other nasties. Also, it would be a beast on your CPU.
__________________
http://www.bozdigitallabs.com
bozmillar is offline   Reply With Quote
Old 07-02-2017, 01:48 AM   #18
mibes
Human being with feelings
 
Join Date: Apr 2017
Posts: 36
Default

Quote:
Originally Posted by bozmillar View Post
Think of it like a looping tape, and changing the delay time is just moving the head. If you move the head 6 inches instantaneously, it's going to pop. If you move it slowly, it will do sort of a pitch shift thingy while it's moving.

To get smooth delay changes you have to:

1) Prevent the delay value from changing too fast. A simple LPF on the delay value can fix this.

2) Interpolate the delay value between samples. that way as you move your delay value, it has a continuous waveform to pull from.

3) Keep your delay buffer the same size. Obviously if you are resizing your buffer for every delay change, you are going to get pops and other nasties. Also, it would be a beast on your CPU.
Reviving an old thread here, but I'm having a similar problem while making a pitch-delay - popping when delay length is changed, but fine when it's static.

I've basically tried all of above, resample and interpolating the signal, lpf on the parameter, cross-fading with the old signal. Still get loads of noise when changing delay (only using milliseconds, not tempo / fractional)

Last edited by mibes; 07-02-2017 at 06:10 AM.
mibes is offline   Reply With Quote
Old 07-02-2017, 11:32 AM   #19
earlevel
Human being with feelings
 
Join Date: Dec 2015
Posts: 331
Default

Quote:
Originally Posted by mibes View Post
Reviving an old thread here, but I'm having a similar problem while making a pitch-delay - popping when delay length is changed, but fine when it's static.

I've basically tried all of above, resample and interpolating the signal, lpf on the parameter, cross-fading with the old signal. Still get loads of noise when changing delay (only using milliseconds, not tempo / fractional)
There are two basic choices: 1) A smoothed control signal along with fractional interpolation of the delay line, or 2) Soft mute/unmute as the delay time is changed. #1 causes pitch shifting, like changing the speed of a tape, while the is no shift in #2. Obviously, you're referring to #1.

You say you're not using fractional, but you must. Otherwise you are violating the "with smooth changing delay rate" title of this thread. If you smooth the parameter with a one-pole lpf (if you choose higher, don't use Butterworth response—the edges ring), and you use fractional delay, I assure you that it will work. Start with linear interpolation, because it's easy to debug and you'll be convinced that it works, then get more sophisticated if you want/need to.
earlevel is offline   Reply With Quote
Old 07-02-2017, 11:50 AM   #20
mibes
Human being with feelings
 
Join Date: Apr 2017
Posts: 36
Default

Quote:
Originally Posted by earlevel View Post

You say you're not using fractional, but you must. Otherwise you are violating the "with smooth changing delay rate" title of this thread. If you smooth the parameter with a one-pole lpf (if you choose higher, don't use Butterworth response—the edges ring), and you use fractional delay, I assure you that it will work. Start with linear interpolation, because it's easy to debug and you'll be convinced that it works, then get more sophisticated if you want/need to.
Thanks for the response

I'm not using "fractional" delay because I'm using the resampler to repitch the significant part of the buffer. So it's doing the interpolating.
mibes is offline   Reply With Quote
Old 07-02-2017, 09:57 PM   #21
earlevel
Human being with feelings
 
Join Date: Dec 2015
Posts: 331
Default

Quote:
Originally Posted by mibes View Post
Thanks for the response

I'm not using "fractional" delay because I'm using the resampler to repitch the significant part of the buffer. So it's doing the interpolating.
OK, but you're reviving a thread that is about something different...many things to go wrong in what you're trying to do...
earlevel is offline   Reply With Quote
Old 07-03-2017, 02:36 PM   #22
mibes
Human being with feelings
 
Join Date: Apr 2017
Posts: 36
Default

Figured it out finally! I'll post the mistakes I made (embarrassingly), just in case someone else has the same problem and comes here to find the answer:

I was crossfading at the new location of the read-pointer - obviously it needs to crossfade with the data just after the OLD location of the read-pointer (duh), because it needs to flow on from what was being read last.
mibes is offline   Reply With Quote
Old 07-09-2017, 02:15 AM   #23
Tired_Joe
Human being with feelings
 
Join Date: Apr 2015
Posts: 55
Default

Oh, this would be great I have the same problem
Tired_Joe is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -7. The time now is 03:58 PM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.