Reverse delay?

Software questions and issues with the FV-1

Moderator: frank

Mcfly
Posts: 46
Joined: Fri Mar 08, 2013 2:38 pm
Location: Argentina

Reverse delay?

Post by Mcfly »

frank wrote:Since the FV-1 wasn't intended to do this it is really a hack. Try to code it just like a pitch shift but use the

Code: Select all

sof 0, -0.25
wrax rmp0_rate,0 
in an initialization block to set the negative coefficient properly, set range to the desired range.

I have not tried this so it is an experiment.
Frank i've tried this:

Code: Select all

mem delayl 32764 
temp mem 1

skp run, loop 
sof 0, -0.25 
wrax rmp0_rate,0 
wrax rmp0_range, 0

loop: 

ldax ADCR
wra delayl,0
cho rda,RMP0,REG|COMPC,delayl
cho rda,RMP0,,delayl+32763	; since we are reading 
;from the end of delayl interpolate to next addr value
wra temp,0
cho rda,RMP0,RPTR2|COMPC,delayl
cho rda,RMP0,RPTR2,delayl+32763
cho sof,RMP0,NA|COMPC,0
cho rda,RMP0,NA,temp

wrax addr_ptr, 0 
rmpa 1.0 
wrax dacr, 1.0 
wrax dacl, 0.0
But i'm gettin just a noisy output, don't know why.
Another idea: fade in what the ramps read at the start and fade out the last cycle, but don't know how to code this properly.
frank
Posts: 1244
Joined: Wed Oct 19, 2005 12:26 pm
Contact:

Post by frank »

Try what I mentioned, code it just like a pitch shift but with the sof to set the negative coefficient properly.
Frank Thomson
Experimental Noize
Mcfly
Posts: 46
Joined: Fri Mar 08, 2013 2:38 pm
Location: Argentina

Reverse delay?

Post by Mcfly »

Ok i've tried two versions with no results, in this case i got a noisy output again:

Code: Select all

delayd mem 4096 ; Down delay
temp mem 1 ; Temp location for partial calculations
;
skp run,START
sof 0, -0.25
wrax rmp0_rate,0 
wrax rmp0_range,0
;

;
START: ldax ADCR
; Write it to left delay and clear ACC
wra delayd,0
; Read in left
ldax ADCR
;
cho rda,RMP0,REG|COMPC,delayd
cho rda,RMP0,,delayd+1
wra temp,0
cho rda,RMP0,RPTR2|COMPC,delayd
cho rda,RMP0,RPTR2,delayd+1
cho sof,RMP0,NA|COMPC,0
cho rda,RMP0,NA,temp

wrax addr_ptr, 0 
rmpa 1.0 
wrax DACL,1
WRAX	DACR,0
;
An also tried this, even with the sof set to negative the ramp seems to not goin' backwards. It just lowers pitch:

Code: Select all

delayd mem 4096 ; Down delay
temp mem 1 ; Temp location for partial calculations
;
skp run,START
sof 0, -0.25
wrax rmp0_rate,0 
wrax rmp0_range,0
;

;
START: ldax ADCR
; Write it to left delay and clear ACC
wra delayd,0
; Read in left
ldax ADCR
;
cho rda,RMP0,REG|COMPC,delayd
cho rda,RMP0,,delayd+1
wra temp,0
cho rda,RMP0,RPTR2|COMPC,delayd
cho rda,RMP0,RPTR2,delayd+1
cho sof,RMP0,NA|COMPC,0
cho rda,RMP0,NA,temp

wrax DACL,1
WRAX	DACR,0
I've tried several sof coeff but it does not work.
frank
Posts: 1244
Joined: Wed Oct 19, 2005 12:26 pm
Contact:

Post by frank »

Hmmm, well the FV-1 was never intended to do reverse so it may not be possible to do any better than the existing methods. I'll try to think about other possible solutions but it may simply not be possible to improve it.
Frank Thomson
Experimental Noize
slacker
Posts: 116
Joined: Tue Feb 01, 2011 1:13 pm

Post by slacker »

Frank's code from 4 Dec 2007 earlier in the thread works Ok for me, you can change the speed by making the sof command more negative, but it soon gets very fast.
I think the glitching is just the delay grabbing part of the guitar signal as it decays and then playing it backwards, this give a hard edge to the start of the sound so it makes a click. You can prove this by playing one note and then quickly muting it, this plays back cleanly with no glitch, if you let it sustain, you then hear the glitch. You might be able to reduce the click by using some low pass filtering.

I tried making a reverse delay using the code, but it doesn't really work, because when you add feedback to get multiple repeats, the reversed sound gets reversed and comes out forwards, then that gets reversed and so on. This sounds quite interesting but not what you want.

I think a better way to try and make something that sounds like a reverse delay would be to write a normal delay and then feed the output through a reverse reverb. The only reverse reverb I've seen is the Malekko one, which is freely available but I'm not sure what sort of licence it's under so I wouldn't want to just "steal" their code by using it.
Sweetalk
Posts: 141
Joined: Thu Oct 15, 2009 5:13 am

Post by Sweetalk »

Can you copy a block of memory on another block?. If you can do that use an aux block to store some info, than copy it to another block (i'll be FIFO right?), with the addr_ptr reead the info from the begining (last sample recorded) and move it foward to play the next and so on. It's just a toght...
Mcfly
Posts: 46
Joined: Fri Mar 08, 2013 2:38 pm
Location: Argentina

Reverse delay?

Post by Mcfly »

Thanks Frank for checking this out.
Slacker, i will try the idea of using the malekko reverse reverb and see what happens. I liked the filter idea also.

Another solution could be a fade in every reset of the backwards ramp. Is there any counter or flag that i can use for detecting the reset?

Maybe a fade in could be made of a ramp1 mulx the output and stop it before it reachs to zero again. This ramp inits when ramp0 resets.

I'll try to code this solution but i don't know how to detect a reset.
drolo
Posts: 10
Joined: Tue Feb 10, 2015 3:14 am
Location: BE
Contact:

Post by drolo »

Hi,
First post for me.
I have been using the FV-1 mostly with code generated in SpinCad and I'm just slowly learning the actual assembler.

I have been playing with the reverse delay code Frank posted in december 4rth 2007 and was wondering what sets the length of the sample as it is?

It seems a lot shorter than the 1sec that I would have assumed to be the maximum.

Modifying the sof 0,-0.25 to make it more negative changes the length but also the pitch of the sample

Changing the ramp range can shorten the sample while keeping the same pitch but I was wondering if it was possible to increase the initial length?
Digital Larry
Posts: 338
Joined: Mon Nov 12, 2012 1:12 pm
Contact:

Post by Digital Larry »

Just a guess, but if it uses the RAMP LFO then the max it could be would be 4096/32768 or 1/8 second. Does that seem about right?
drolo
Posts: 10
Joined: Tue Feb 10, 2015 3:14 am
Location: BE
Contact:

Post by drolo »

hmm that makes sense, I guess there is no way using that method then ...

I wonder how they did it in the Red Panda Particle. It has a really nice reverse delay, even without clicks ..
Digital Larry
Posts: 338
Joined: Mon Nov 12, 2012 1:12 pm
Contact:

Post by Digital Larry »

I listened to the Red Panda Particle demo video on the reverse delay patch. It's a little hard to tell what is going on. It would be easier, say, if they did a slow descending glissando... then we could hear if it turned into a series of overall descending but ascending mini-glisses, if that makes any sense.

Some of the backwards delay I've heard actually just sounds like envelope processing on a standard delay (slow attack, fast release) that would give you a reverse "ish" sound without the heavy lifting of needing to do glitch management.

I think you could do it with arbitrary delay lengths but you'd no longer be able to use the built in crossfading from pitch shift hardware/ramp LFO - you'd have to create that yourself.
Digital Larry
Posts: 338
Joined: Mon Nov 12, 2012 1:12 pm
Contact:

Post by Digital Larry »

Somebody sent me this code which I made into a block and it does seem to work. Oh, it looks like what Frank posted years ago!

Code: Select all

mem delay 32767

skp run, loop

sof 0, -0.25   ;clear acc and set -0.25
wrax rmp0_rate, 0   ;ramp rate = -.25, clear to 0
wrax rmp0_range, 0 ;ramp range= 0

loop:

sof 0,0      ;clear acc
rdax adcl, 1.0    ;read left adc
wra delay#, 0.0    ;write to delay ram and clear
cho rdal, rmp0    ;get ramp lfo
wrax addr_ptr, 0    ;write data at delay ram address
rmpa 1.0       ;read data at delay ram address 1.0

wrax dacr, 1.0
wrax dacl, 0.0
So we're not using any CHO RDA here to get the delayed signal, only RMPA. And that's probably fine so long as the ratio of the pitch readout is not fractional and we wouldn't be needing to interpolate between samples anyway.

To be honest, the code sample I received did not have anything explicit for this line:

wrax rmp0_range, ;ramp range= 0

I inserted the value 0 based on the comment, so now it's like this:

wrax rmp0_range, 0 ;ramp range= 0

It does work although I don't think the buffer length is a full second.

Here's a few things I don't claim to understand:

1) If you set the RMP0_RANGE to 0, how is it that we get anything useful out of CHO RDAL? Is RMP0_RANGE important here, or not?

2) I'm kinda used to having to multiply an explicit delay RAM reference by 256 prior to RMPA. But here, we pick off the value of the RAMP0 LFO, which supposedly has a width of zero, and then use that directly as the ADDR_PTR value, and it seems to work,

I don't want to give up just because this isn't documented. It's doing something close to what I want. All I want to do now is add some code that would generate explicit crossfade waveforms that I could use if RMPA is the way to go. I haven't tried CHO RDA here yet and if that worked then maybe that other bit wouldn't be necessary.

The other point of confusion I have is why the entire RAM bank is allocated. What range is RMPA really looping over?

One of the previous examples showed both CHO RDA and RMPA methods combined. Unfortunately it looks like the audio result of the standard 6 pitch shift instructions was written to ADDR_PTR, so no wonder it sounded like noise.

So (I'm guessing) this RMPA approach will work but the CHO RDA will not. Crossfading waveforms can be generated from the ramp uch as you'd make a triangle:

SOF 0, -(half of ramp amplitude) ; puts center of ramp at zero
ABSA ; folds lower half up to make triangle
SOF 1.0, -(1/4 of ramp amplitude) ; make triangle symmetrical around 0
SOF -2.0, 0 ; boost level of triangle up to clip off tops and bottoms
SOF -2.0, 0 ; requires a few of these to get there, not sure how many
...
; now you have a triangle with tops and bottoms clipped off
SOF 0.5, 0.5 ; now it is suitable for one half of a crossfade
WRAX REG0, 1.0 ; save it
SOF -0.999, 0.999 ; invert it - now you have the other half of the crossfade waveform
WRAX REG1, 0 ; save it so it can be used with MULX later
------------------------
The next challenge is going to be picking off a delay point "halfway" from what ADDR_PTR is pointing at. I guess you can multiply ADDR_PTR by 0.5 and that solves that problem.

All highly theoretical at this point.

DL
Digital Larry
Posts: 338
Joined: Mon Nov 12, 2012 1:12 pm
Contact:

Post by Digital Larry »

I generated a crossfade waveform. Now I just need to create the Ramp offset by half waveform. I think the way to do this is to add 0.5 of full amplitude to the LFO wave if ramp is less than 0.5 full scale. If ramp is >= 0.5 then subtract 0.5 full scale to get ramp offset. At 0.5 it jumps from 0.0 to 1.0 x full scale.
Digital Larry
Posts: 338
Joined: Mon Nov 12, 2012 1:12 pm
Contact:

Post by Digital Larry »

I sorta got it going but it sounds pretty weird. The crossfading is going between (I think 1/8 second and 1/16 second) and so it pulsates and is a bit distracting. But hey it might just be what you're after. I'm going to think about how to make the delay buffer longer.
the_frey
Posts: 13
Joined: Sat Jun 04, 2016 9:56 am

Post by the_frey »

DL - in spincad (I've been mucking around with build errrm 998 I think) with the reverse delay patch, how do you set the delay buffer time? I'm assuming that the 'feedback' is a fixed amount...

Or do you have to export the patch as ASM and add the control there?
Post Reply