|
|||
Ichad.c wrote: Sorry -> I was being vague, the code is for a simple delay - but the use will be for a chorus.
Hmmm, then it's not a simple delay—it's a modulated delay. I think you're falling in the trap of thinking, "This is, essentially, an integer delay plus a fractional delay. I know how to do a variable integer delay, so I just add this 0->1 sample allpass delay, and I have my variable fractional delay." But the fractional delay filter has a memory, and you're essentially scrambling that memory continuously as you sweep the delay line. It's clicking because of those discontinuities. This kind of fractional delay is fine for a fixed fractional delay—say you need a delay of 10.13 samples. Last edited by earlevel on Sat Jun 30, 2012 7:53 am; edited 1 time in total |
|||
| ^ | Joined: 04 Apr 2010 Member: #229147 | ||
|
|||
camsr wrote: Quick answer: Allpass interpolator is not designed for modulated delay.
Uhmm - that's false information - here is the practical implementation, ever heard of the Ensoniq DP4? https://ccrma.stanford.edu/~dattorro/DP4.htm Played with one some years ago - an excellent performer in it's price category, and you can go over to gearslutz.com and ask around about it's allpass interpolated delay-line chorusses - people seem to like them. I liked them. Not that I want to do an re-issue of that particular chorus or something. But it seems like a good/unique building block. I'd probably also put Fractionally Addressed Delay in the good/unique class but I'm way too inexperienced in c++ to do an FAD Delay. The allpass seems simpler - but judging by the comments so-far - it obviously harder - than I thought. |
|||
| ^ | Joined: 08 Feb 2012 Member: #274678 Location: South - Africa | ||
|
|||
Ichad.c wrote: camsr wrote: Quick answer: Allpass interpolator is not designed for modulated delay.
Uhmm - that's false information - here is the practical implementation, ever heard of the Ensoniq DP4? Sorry, I looked at your code late last night, but it wasn't clear enough, too much work to make it clear (I see the basic elements of what you're trying to do). I recall trying this, about 12-15 years ago. I beat by head against the code trying to get decent quality out of it before it occurred to be what was fundamentally wrong with the idea. So, either Dattorro didn't get it across clearly to me, or he goofed—at that point I was fed up and went back to doing it the way I wanted to (oversampled, linear interpolation). You seem to be running into the same problem. I admit that I was fed up when I realized the problem, and didn't spend any more time at that point to think of a solution, but I guess someone would have to give me an idea of how you would either keep from scrambling the allpass's memory, or how it wouldn't get scrambled, or how it wouldn't matter that it got scramble, when you change the delay by one sample or more. Not trying to pee in your Cherios—I'd be interested in figuring it out, and the solution. Maybe if you explained your code and the variables more carefully so that I don't have to make assumptions for every single thing, it would help and I could at least tell you where it's going wrong. |
|||
| ^ | Joined: 04 Apr 2010 Member: #229147 | ||
|
|||
Ichad.c wrote: if (delayInt > 65534) delayInt = 65534; // check at delay length calculation else if (delayInt < 1) delayInt = 1; float fractionalDelay = lenf - delayInt; OK, to start, Andrew, you are limiting the integer part integer part here, but not lenf, which means that if you really do hit the limit, the fractional part may be wrong (greater than 1, or negative, depending on which limit). You should limit lenf instead of just its integer part. But you'll only hit this at the extremes, so I doubt it's the problem you are hearing, unless you're running wide open (and you won't hit the high limit in normal chorusing). Still looking at details, but I understand the code now... |
|||
| ^ | Joined: 04 Apr 2010 Member: #229147 | ||
|
|||
earlevel wrote: OK, to start, Andrew, you are limiting the integer part integer part here, but not lenf, which means that if you really do hit the limit, the fractional part may be wrong (greater than 1, or negative, depending on which limit). You should limit lenf instead of just its integer part. Thanks for spotting that! If my code is a little unreadable - you could read the code in DelayA.cpp and DelayA.H in the STK toolkit - it does what I'm trying to do: https://ccrma.stanford.edu/software/stk/download.html The way it's written (micro-functions) is very hard for me to read. But maybe I should take out some time in the following week - try an re-write all it's little functions and then hopefully see where the "trick" lies. Think Datorro fails in explaining what to do when the coefficients are at their extremes and when the interger part updates - both of these conditions happen at the same time - if I understand the theory correctly. Regards Andrew |
|||
| ^ | Joined: 08 Feb 2012 Member: #274678 Location: South - Africa | ||
|
|||
I suspect there could be something wrong with the "unsigned short int delayInt = lenf - c_epsilon;" too...if lenf is 10.41, you end up with int=10, frac=.41; if lenf is 10.39, you get in=9, frac=1.39. I'm not sure of the intent—I suppose something to do with the fractional bias Dattorro mentions, but I'm out of time for now...
Edit: Well, maybe that's right, sounds vaguely familiar, been a long time... Last edited by earlevel on Sat Jun 30, 2012 10:08 am; edited 2 times in total |
|||
| ^ | Joined: 04 Apr 2010 Member: #229147 | ||
|
|||
Quote: Think Datorro fails in explaining what to do when the coefficients are at their extremes and when the interger part updates - both of these conditions happen at the same time - if I understand the theory correctly.
If I recall correctly those papers survey a lot of material, some of which aren't explained. ---- ~stratum~ |
|||
| ^ | Joined: 29 May 2012 Member: #281392 | ||
|
|||
earlevel wrote: I suspect there could be something wrong with the "unsigned short int delayInt = lenf - c_epsilon;" too...if lenf is 10.41, you end up with int=10, frac=.41; if lenf is 10.39, you get in=9, frac=1.39. I'm not sure of the intent—I suppose something to do with the fractional bias Dattorro mentions, but I'm out of time for now...
Hell, I can't exactly remember why I used 0.4, though - once again - if I understand Datorro correctly - his interpolation scheme actually interpolates from 1.5, 2.5, 3.5 samples - think exact 1.0 sample position is lost/traded/shifted, because the allpass rings too long at nyquist if exactly at one. My assumptions might be completely off though. The biggest problem with my code (or this design) to me is the "saw" time response of the coeffcients themselves - when the fractional part goes from 0.9999 to 0.000, the coefficients of the allpass basically "resets" in the time domain - and because of the recursive nature of allpasses - it sticks around for a while. I've actually seen a couple of VSTs here and there that say they use allpass interpolated modulated delays - would be cool if at least one of these people can at least hint if I'm going in the right direction... Thanks to all, for all your help and suggestions so far! Andrew |
|||
| ^ | Joined: 08 Feb 2012 Member: #274678 Location: South - Africa | ||
|
|||
Hey all, after writing and re-writing this dang code about 20 times - it seems to work now (I think)! Seems like I messed up the pointers or something - not the coefficients - the clicks was coming from the integer part. Actually had a listen and did some minor testing, SNR on average is about the same but it's spaced differently - the allpass interpolator has about 10dB less noise below samplerate/8 about 6kHz @ 48kHz SR and quite alot at close to nyquist - still at -100dB on an FFT though, with a modulation speed of 6Hz and depth of 4ms. Less speed = less noise. Which makes it suitable for my chorusing needs. CPU is about 19% more than linear interpolation. Still think the coefficients needs some tweaking though - seems like it rings a bit too long @ nyquist.
Oh, if you Stratum, Borogove, earlevel, or mystran - would like to give the code a spin - just give a shout-out and I'll send it to you via PM. Cheers Andrew |
|||
| ^ | Joined: 08 Feb 2012 Member: #274678 Location: South - Africa | ||
|
|||
I'd probably try 2x oversampling (use HIIR halfband filters) with linear or cubic interpolation (probably cubic to be honest) and some spectral shaping to reduce the interpolation noise at low frequencies. The idea with the last one is to do leaky integration on the input (cutoff around 5-10Hz or so) then run the delay (with interpolation) and take finite difference as output (essentially combining it all into a DC blocker). The differentiation will push the gain at low freqs down attenuating the interpolation noise there. It's not perfect but can improve things a bit (idea is similar to DPW really; won't help with high-freq attenuation though).
If that doesn't work for you, I'd really go for a "sinc" interpolation with tabulated coeffs. As long as the frequency variation isn't too drastic, you can get away with fixed cutoff filter (ie sinc reconstruction and then resampling without further band-limitation). Filter lengths around 12-16 or so should work quite well if you do 2x oversampling (which with HIIR is still cheaper than getting similar quality by increasing the "sinc" length). |
|||
| ^ | Joined: 11 Feb 2006 Member: #97939 Location: Helsinki, Finland | ||
|
|||
mystran wrote: I'd probably try 2x oversampling (use HIIR halfband filters) with linear or cubic interpolation (probably cubic to be honest) and some spectral shaping to reduce the interpolation noise at low frequencies. The idea with the last one is to do leaky integration on the input (cutoff around 5-10Hz or so) then run the delay (with interpolation) and take finite difference as output (essentially combining it all into a DC blocker). The differentiation will push the gain at low freqs down attenuating the interpolation noise there. It's not perfect but can improve things a bit (idea is similar to DPW really; won't help with high-freq attenuation though).
If that doesn't work for you, I'd really go for a "sinc" interpolation with tabulated coeffs. As long as the frequency variation isn't too drastic, you can get away with fixed cutoff filter (ie sinc reconstruction and then resampling without further band-limitation). Filter lengths around 12-16 or so should work quite well if you do 2x oversampling (which with HIIR is still cheaper than getting similar quality by increasing the "sinc" length). Hey mystran - I'm a nOOb, it took me about 18hours to get a simple 25 lines of code to work properly - by pure trial and error - don't even know how to oversample yet(the theory I get - the practice I don't) - thanks for bursting my bubble |
|||
| ^ | Joined: 08 Feb 2012 Member: #274678 Location: South - Africa | ||
|
|||
Random note: I like this song of yours - reminds me of a band called Covenant.
http://soundcloud.com/mystran/static-single-assignment-form |
|||
| ^ | Joined: 08 Feb 2012 Member: #274678 Location: South - Africa | ||
|
|||
Thanks for liking my song.
Actually I replied before I realized there was another page of discussion here, sorry about that. Regarding oversampling.. hmmh.. you should certainly figure that out.. maybe I can help with that later.. right now I'm in a park with laptop so writing forum replies is already quite painful with this horrible keyboard. |
|||
| ^ | Joined: 11 Feb 2006 Member: #97939 Location: Helsinki, Finland | ||
|
|||
mystran wrote: Regarding oversampling.. hmmh.. you should certainly figure that out.. maybe I can help with that later.. right now I'm in a park with laptop so writing forum replies is already quite painful with this horrible keyboard. Yeah, I'm currently bugging Jeff McClintock about that, since most of my code goes freely to the SE community - and also - the chance of me actually understanding it correctly would be enhanced if explained by someone who uses the same SDK - still haven't got it working yet - but I'm a persistent bugger. I also try and spread the nOOb questions as wide as practical, using: stackoverflow - for general c++ questions SynthEditSDK usergroup - for general DSP/SDK stuff KVR - for all the tricky stuff Since most people say that oversampling is so trivial to implement - it qualifies as general DSP in my book. I'd rather only bother you and the others with the harder questions like: How to calculate zero delay feedback for cascaded alllpasses i.e a phaser? (that's a theoretical Q - plz don't answer - my head hurts already). On a delay-related note though - do you or anybody else for that matter - have the DAFX COST G6 c-code archive? I want to try and implement an FAD delay - the parralel between it and analog CCD delays seems interisting, here's the paper: http://arxiv.org/pdf/cs/0005022.pdf If I can get the c-code they mention, I might hopefully be able to figure it out. Regards Andrew |
|||
| ^ | Joined: 08 Feb 2012 Member: #274678 Location: South - Africa | ||
|
|||
Phasers are rather nasty case of zero-delay actually, because unlike most regular filters the BLT warping tends to cause trouble with phasers, because there isn't a single cutoff that you could sensibly warp. Obviously enough oversampling will cure anything, though.. Anyway oversampling in theory goes like this: to upsample by N times, insert N-1 zeroes between any two samples, then filter the result using a low-pass "as steep as possible" at the original Nyquist (ie say oversampling by 4 times, you'd insert 3 zeroes and lowpass at 0.5/4 times the new samplerate; you can ignore the samplerate actually since it cancels out). Since you "spread" energy around you'll also probably want to scale gain by N (assuming your low-pass has unity DC gain). Downsampling after processing is similar: use the same (or similar) filter to get rid of content (assuming you did something non-linear; if not you can just skip this) and then take every Nth sample. Done. So all you really need is a good low-pass filter... which ofcourse is where the trouble starts... the above works fine as-is using FIR filters, but obviously you want to split the filter kernel such that you don't multiply-add the zeroes you added (or downsampling, you don't want to calculate stuff you'll throw away). For the HIIR all-pass stuff.. hmmh.. I'd probably get someone's implementation (there's one in music-dsp archives) and adapt that.. last I checked the theory (math) was too much for me. |
|||
| ^ | Joined: 11 Feb 2006 Member: #97939 Location: Helsinki, Finland |
| KVR Forum Index » DSP and Plug-in Development | All times are GMT - 8 Hours |
|
Printable version |
Disclaimer: All communications made available as part of this forum and any opinions, advice, statements, views or other information expressed in this forum are solely provided by, and the responsibility of, the person posting such communication and not of kvraudio.com (unless kvraudio.com is specifically identified as the author of the communication).
Powered by phpBB © phpBB Group












