Page 1 of 1

Latency "trick ?" in Pitch Transposition algo.

Posted: Tue Dec 17, 2013 8:40 pm
by Dedjazzgadgetz
Dear Frank :

I'm having one of those -"uh? say what ?" moments, again...

...quote from donstavely http://www.spinsemi.com/forum/viewtopic.php?p=1506#1506 :
-"Here is one quick and easy trick that reduces the pitch shift latency by 25%: If you look closely at the behavior of the crossfade generation associated with the ramp LFO's, you will see that their value is zero for the first and last 1/8th of the total delay length. So instead of writing your input signal to the head-end of the delay, you just write it 1/8 of the way in. Say for a 4096 word delay, instead of "wra DELAY" you just use "wra DELAY+512". Since the crossfade starts at word 512, you just saved 512 samples worth of unnecessary delay."

I fail to understand the wizardry! that forces the Ramp itself to arbitrarily jump-start from nowhere ?... in other words : what mechanism (hardware, i'm guessing ?) links a Ramp/crossfade-generation to a given memory allocation ? How does leaving-out the first 512 sample mem. slots blank (wra DELAY+512 in this example) makes the ramp (and it's associated crossfade) go :

"-'know what? I'm not gonna start at 0... I'll preset myself to 0,125. There. -HA!"

There's gotta be something more to it, right ?... a whole lot more !? (in addition to having to detect memory position 7/8, in order to JAM the Ramp to 0 -erh, I mean... 0.125 !? HELP ! )
Read all I thought was relevent so, please Don, anybody... feel free to pitch-in; it's drivin' me craaii-zy ! ) Thanks in advance !

Dedjazzgadgetz
(tryin', but not quite gett'n'it ...at all !)

Posted: Tue Dec 17, 2013 9:01 pm
by frank
I really can't go into all the hardware that makes the ramp, cross fade coefficient, etc. Lots of details in it, just accept that the system generates the proper ramps and cross fade coefficients.

Now donstavely is correct in that writing into the buffer could shorten the delay but it can cause an audible discontinuity. Ramps are used and crossed between the pointers to try to hide the discontinuity as the pointer wraps around the buffer, by writing higher into the buffer you are allowing old/wrong data to be used until the pointer hits the write point.

Posted: Tue Dec 17, 2013 9:42 pm
by Dedjazzgadgetz
frank wrote:I really can't go into all the hardware that makes the ramp, cross fade coefficient, etc. Lots of details in it, just accept that the system generates the proper ramps and cross fade coefficients.

-yeah, sure: from having built discrete counters & stuff (that's sooo long ago...), I totally get that, no prob.

Now donstavely is correct in that writing into the buffer could shorten the delay but it can cause an audible discontinuity. Ramps are used and crossed between the pointers to try to hide the discontinuity as the pointer wraps around the buffer, by writing higher into the buffer you are allowing old/wrong data to be used until the pointer hits the write point.

-Now, that's my point... this idea probably refers to his "pretty convoluted/burns pretty much all of the code space" octave up/down uber-program, using s/w-generated ramps for pitch & crossfade, I'm guessing... (oooh : I'd love Don to confirm this, so I can sleep tonight :wink: )
So, the short of it, you're saying : I can reset an internal Ramp (using JAM), but I can't tell it to "get ahead of itself" (arbitrarily start from a preset point in its cycle, namely 1/8 into it)... right ?

Dedjazzgadgetz

Posted: Tue Dec 17, 2013 9:49 pm
by frank
Correct, you cannot set the ramp to an arbitrary point. And, while thinking about it, the trick really won't work. Since the buffer is circular the length is fixed so where you write is not really going to effect the latency.

Posted: Tue Dec 17, 2013 10:22 pm
by Dedjazzgadgetz
Thanks Frank !

You've transmorgrified my "say what ?" moment into an : a-HA ! knew it orgasm...

Again, thanks for all the dedication you put into explaining stuff over, & over, & over...

Dedjazzgadgetz
(still, I'll grind over this... maybe I could... ? )

Posted: Wed Dec 18, 2013 12:08 am
by Dedjazzgadgetz
Someone stop me, please ! Can't help myself... :oops:

-Would the Assembler categorically refuse to let me program a pitch transposer algo. with an internal "4096" Ramp (so far, so good), BUT processing a specified 3584-lenght memory (that's 7/8s) AND resetting (JAM-ing) the ramp upon detection of having reached said 7/8 lenght ?

Since we can't seem to be able to get rid of an internal ramp cycle's first 1/8, wouldn't this strategy work towards at least chopping-off that last 1/8 of dare-I-say "useless" crossfade coefficient (where Pointer1 crossfade lingers at 0/Pointer2 crossfade stalls at 1), thus making the latency 1/8 shorter, hopefully without (from what I can gather) any "disruption" artifacts ?

(it would lend the "warble" a different quality, for better or for worst, loose a little low freq. shifting... and what about the ramp never reaching "1" ie resetting at 0.875 ? That's just a mem. address "vector", right ?)

-or should I just -"for the love of god !" stop torturing those sweet, little innocent ones and zeros :twisted: & finally go to bed ?...

Dedjazzgadgetz
(obsessive/compulsive... yup, that's me allright !)

Posted: Wed Dec 18, 2013 12:35 am
by Dedjazzgadgetz
I think Pointer2 would suffer some disruption... jumping instantly from 0.375 (upon JAM-ing) to 0.5

(unless... we give it a cho rda,x|x|x,-512 offset upon JAM, up until -say mid-mem. is reached... or the other way around : a +512 offset from mid-point 'til JAM ?)

DARN ! :shock:

Oh, well...
I tried.

Dedjazzgadgetz
(if anybody has a go: tell me how it sounds... still not set-up properly for programming :oops: )

Posted: Wed Dec 18, 2013 1:21 pm
by frank
You're not going to gain anything doing this. Look at it logically, writing into the buffer deeper only changes the write point, it is a circular buffer and the pointers are moving through it so the length is the same. Trying to write deeper then JAM the ramp early is effectively using a shorter buffer, why not just use a shorter buffer like 2048 to start with? You are not gaining anything over the shorter buffer by using the longer buffer and doing the deep write/JAM.

Posted: Wed Dec 18, 2013 2:01 pm
by Dedjazzgadgetz
I know, I know ! :oops:

(But it was fun -in a perverse-kinda way- trying to "reverse-engineer" donstavely's idea -if it worked at all... even if a *wee bit* frustrating. AND it got me to think waaay "deeper" into the architecture/the logic behind the FV-1; and that's not wasted !)

As usual Frank, thanks for sharing some great insights !
Much obliged...

Dedjazzgadgetz
(your friendly, neighbourhood *nutcase*. -"Let go, man... let go". :shock: -I'm trying. )

Posted: Wed Dec 18, 2013 2:21 pm
by Dedjazzgadgetz
oh, say :

what's the "properly pitched" lower-bandwidth down to (ballpark figure) when an internal RMP (@32kHz) is set to

-512 ?
-1024 ?
-2048 ?

and finally

-4096 ?

(I figure they'll be "octaves" of each other, just not real-sure of a real-life value... wild guess here : 64Hz, 32Hz, 16Hz & 8Hz ? :? )

Posted: Wed Dec 18, 2013 4:16 pm
by frank
Those frequencies are about right, you want at least one full wave in the buffer or else it doesn't sound right. You could make the argument for a 1/2 wave but it would be 6db down from what it should be (I think, just off the top of my head).

So for a normally tuned guitar you could use 512 since the open E is about 82Hz but for a bass it is about 41Hz so you need at least 1024 and a piano typically goes down to 27Hz so you need at least 2048.

Posted: Wed Dec 18, 2013 4:43 pm
by Dedjazzgadgetz
O.K. great !

(my math/reasoning's much better than I thought... 8) )

Thanks,

Dedjazzgadgetz
(now, off to the programming-cave... make some more Experimental Noize :wink: )

Posted: Fri Jun 27, 2014 1:57 pm
by donstavely
frank wrote: Now donstavely is correct in that writing into the buffer could shorten the delay but it can cause an audible discontinuity. Ramps are used and crossed between the pointers to try to hide the discontinuity as the pointer wraps around the buffer, by writing higher into the buffer you are allowing old/wrong data to be used until the pointer hits the write point.
Frank, I just suggested this trick (of writing into the pitch-transpose buffer 1/8th of the way in) in a more recent post, but never replied to your comment in this one.

I am very confident that this trick works. It is totally glitchless, and reduces the average latency by 1/4 for free. The reason is that even though the crossfade pointers sweep through the entire buffer, the crossfade value is zero until the pointer get 1/8th of the way in. So whatever crap is on that region of memory is multiplied by zero (and added to the good data that comes from the middle section of the buffer read using the other pointer.)

So writing to the head of the buffer just means that the signal "ages" by 512 clocks for a 4096 buffer before it is ever used - adding an unnecessary 15.6ms to the latency.

I have thought this through carefully, as well as testing it pretty thoroughly. Please 'spain it to me if you still think I am wrong.

Don

Posted: Wed Jul 06, 2016 12:17 pm
by MacroMachines
Id be curious to hear an example if you have one you are willing to show. Why not try an open compare/contrast

Re: Latency "trick ?" in Pitch Transposition algo.

Posted: Tue Apr 02, 2019 7:29 am
by DrAlx
There's an obvious test that will demonstrate if this trick works as claimed. Don't know if anyone's done this.

Have two parallel pitch-shift lines of length 8192 each.
First line has signal injected at its start.
Second line has signal injected at offset of 512, but before injection the signal is delayed by a separate delay line of length 512.
Subtract signals from the two paths and listen for what comes out.

If the trick works as claimed then the two paths should cancel out and provide no net output.
If there are any glitches from using this trick, they will show up at the output.

EDIT:

I have now performed the above test, and applied lots of gain after the subtraction.
I made lots of noise at the input and got no audible output.
Therefore I can confirm that the trick of writing into the buffer at an offset does indeed reduce
latency without producing glitches or other bad effects.