Reverse delay?

Software questions and issues with the FV-1

Moderator: frank

Digital Larry
Posts: 279
Joined: Mon Nov 12, 2012 12:12 pm
Contact:

Post by Digital Larry » Mon Jun 19, 2017 9:23 pm

Few comments.

1) Best place to ask about SpinCAD is over at my forum.

2) Someone sent me the reverse delay code and I slapped it into SpinCAD without thinking about it very much. Off the top of my head I do not know how it works. It could be improved no doubt. Reverse engineering FV-1 code makes my brain hurt.

3) If you come up with an improved version and would like me to include it in SpinCAD, please let me know.

Thanks,

DL

the_frey
Posts: 13
Joined: Sat Jun 04, 2016 9:56 am

Post by the_frey » Wed Jun 21, 2017 2:25 am

Cool, was just curious. The crossfade is very dreamy, I was basically wanting to get something going with that. I'll reverse engineer it and see what I can do :)

knutolai
Posts: 33
Joined: Wed Nov 23, 2016 8:43 am
Location: Bergen, Norway

Post by knutolai » Wed Jun 21, 2017 3:21 am

Reviving an old thread!

I wrote this code that gets you 500 ms of reverse delay. The delay time, or rather the size of each reversed segment can be adjuster with POT0.

The program uses a counter to increment ADDR_PTR to read though the delay buffer at double the speed of the audio samples (creating reverse playback). I'm having trouble properly removing the "click" sound when the "read head" wraps around/resets. I need to add some kind of envelope that gradually mutes the signal when the "read head" approaches the end of the delay buffer, and gradually un-mutes it when it has reset.

I've tried a couple of things, all very crude. Any suggestions would be great!

Code: Select all

; Reverse Delay 
; Knut Helle
; June 2017
; 
; POT0 = Reverse segment length
;
equ	length	32767 	; Buffer length
equ	inc	512	; increment
;
mem	echo	length	; Delay Buffer 
;
equ	addr	reg0	; rmpa / addr_ptr addres
equ	size	reg1	; delay buffer size value
;
; Startup Initialization ################################
;
skp   RUN,   loop 
clr 
wrax	addr, 0		; Clear reg on startup
loop: 
;
; Reset address pointer ################################
;
sof	0, 0.1		; +0.1
rdax	POT0, 0.9	; Pot / 'size' range 0.1 to 1
wrax	size, 0		; write to reg, clear
;
clr	
or	length*256	; add max delay addres	( or 8388352 ) 
mulx	size		; * size variable
rdax	addr, -1		; subtract current addres
;
skp	GEZ, reset	; if NEG (addr > max addres)
clr
wrax	addr, 0		; Reset addr ( = 0 )
reset:
;
; Set address pointer 	USES '-1' instead og 1.0 for better accuracy ###################
;
clr			; acc = 0
or	inc		; add increment (+)
sof	-1, 0		; -> (-)
rdax	addr, -1		; add addr (-)
sof	-1, 0		; -> (+)
wrax	addr, -1		; write to addr, then (-)
sof	-1, 0		; -> (+)
wrax	ADDR_PTR, 0	; write to addr_ptr (+), clear acc
;
; Audio In/Out	###########################################
;
ldax	ADCL		; Get input 
wra	echo, 0		; Write it to the head of the delay buffer
rmpa	1		; Read from memory (set by ADDR_PTR)
wrax	DACL, 0		; ACC-> DAC 

Digital Larry
Posts: 279
Joined: Mon Nov 12, 2012 12:12 pm
Contact:

Post by Digital Larry » Wed Jun 21, 2017 5:57 am

Some high level thoughts about putting crossfades on the ends of knulotai's code.

The delay time goes from 0.1 to 1.0 times the pot setting. So the minimum would be 100 msec at 32 kHz if you allocated the whole memory for this.

A 50 msec fade is probably fine.

You can check whether addr_ptr is near either end of the buffer and whether a fade up or fade down is in order.

Big question here is whether you are just going to fade up and down at the ends to get rid of the glitch, or are you going to crossfade to something else? If your plan is to crossfade then you would need either another trailing pointer running at mid buffer, or maybe a separate buffer.

- a parenthetical note about writing blocks for SpinCAD - you can't make simplifying assumptions such as being sure that the memory buffer always starts at zero. I wish! But you have to assume that the buffer will have an offset.

knutolai
Posts: 33
Joined: Wed Nov 23, 2016 8:43 am
Location: Bergen, Norway

Post by knutolai » Wed Jun 28, 2017 3:31 am

The delay time goes from 0.1 to 1.0 times the pot setting. So the minimum would be 100 msec at 32 kHz if you allocated the whole memory for this.

A 50 msec fade is probably fine.
The minimum "read window" would be 100 msec, but that translates to 50ms of reverse delay. The problem might be that I've made the fade out/in too sharp. I'll try to change the delay time pot to 0.2 to 1.0 and add 50ms fade in and 50ms fade out. A 50ms fade would be spread across ~1639 program cycles.
You can check whether addr_ptr is near either end of the buffer and whether a fade up or fade down is in order.
Good idea. Something like this would add a linear fade. Might be good enough:

Code: Select all

increment = +/- 1/(32768*0.050) = +/- 0.00061   ; will increment from 0 to 1 in 50ms

if ADDR_PTR < &#91;pot-derived buffersize - 1639&#93;   ; if less than fade out point
   increment = +&#40;1/1639&#41;  ; Positive increment, Fade In &#40;1 + increment = 1 because of reg value limit&#41; 
else if ADDR_PTR>= &#91;pot-derived buffersize - 1639&#93;   ; if at or beyond fade out point
   increment = -&#40;1/1639&#41;   ; Negative increment, Fade Out

volume = volume + increment   ; add increment
if volume < 0   ; if less than 0 &#58; set to 0
   volume = 0


drolo
Posts: 10
Joined: Tue Feb 10, 2015 2:14 am
Location: BE
Contact:

Post by drolo » Tue Aug 29, 2017 1:47 am

knutolai wrote:Reviving an old thread!

I wrote this code that gets you 500 ms of reverse delay. The delay time, or rather the size of each reversed segment can be adjuster with POT0.

The program uses a counter to increment ADDR_PTR to read though the delay buffer at double the speed of the audio samples (creating reverse playback). I'm having trouble properly removing the "click" sound when the "read head" wraps around/resets. I need to add some kind of envelope that gradually mutes the signal when the "read head" approaches the end of the delay buffer, and gradually un-mutes it when it has reset.

I've tried a couple of things, all very crude. Any suggestions would be great!

Code: Select all

; Reverse Delay 
; Knut Helle
; June 2017
; 
; POT0 = Reverse segment length
;
equ	length	32767 	; Buffer length
equ	inc	512	; increment
;
mem	echo	length	; Delay Buffer 
;
equ	addr	reg0	; rmpa / addr_ptr addres
equ	size	reg1	; delay buffer size value
;
; Startup Initialization ################################
;
skp   RUN,   loop 
clr 
wrax	addr, 0		; Clear reg on startup
loop&#58; 
;
; Reset address pointer ################################
;
sof	0, 0.1		; +0.1
rdax	POT0, 0.9	; Pot / 'size' range 0.1 to 1
wrax	size, 0		; write to reg, clear
;
clr	
or	length*256	; add max delay addres	&#40; or 8388352 &#41; 
mulx	size		; * size variable
rdax	addr, -1		; subtract current addres
;
skp	GEZ, reset	; if NEG &#40;addr > max addres&#41;
clr
wrax	addr, 0		; Reset addr &#40; = 0 &#41;
reset&#58;
;
; Set address pointer 	USES '-1' instead og 1.0 for better accuracy ###################
;
clr			; acc = 0
or	inc		; add increment &#40;+&#41;
sof	-1, 0		; -> &#40;-&#41;
rdax	addr, -1		; add addr &#40;-&#41;
sof	-1, 0		; -> &#40;+&#41;
wrax	addr, -1		; write to addr, then &#40;-&#41;
sof	-1, 0		; -> &#40;+&#41;
wrax	ADDR_PTR, 0	; write to addr_ptr &#40;+&#41;, clear acc
;
; Audio In/Out	###########################################
;
ldax	ADCL		; Get input 
wra	echo, 0		; Write it to the head of the delay buffer
rmpa	1		; Read from memory &#40;set by ADDR_PTR&#41;
wrax	DACL, 0		; ACC-> DAC 
Knut, this is great !
(still not getting notifications for post replies ...)
Between this and your advice on the other thread about playback speed, I was able to understand a lot better how the memory can be addressed in different ways. This has been really helpful. Thanks !! :)

potul
Posts: 18
Joined: Tue Sep 26, 2017 12:33 am

Post by potul » Fri Dec 01, 2017 4:42 am

Hi

Were you able to add a crossfade to the reverse delay?
I like your code, but the cliking is quite annoying.

Mate

igorp
Posts: 21
Joined: Tue May 19, 2015 6:10 am
Location: RU

Post by igorp » Mon Jan 29, 2018 2:29 pm

I am trying to made reverse delay too , wrote own dummy code, it's very close to knutolai one (2Hz ramp LFO from 0 to -1) and now working on crossfades.

My scope show what sometimes it's too much "constant voltage" in reversed loop , accumulator saturated and locks , so some experiments were started.
(first of all- it's hpf in the loop)

if we roll back 2 samples every tick, our backward pointer never play even or odd samples. They are always skipped.
So, it may be a good way to make delay loop odd, for exaple, 16383 samples, not 16384

This may avoid aliasing and "constant voltage", because HPF on forward loop is working with sequental signal, not interleaved.

Or , another idea is to use these unused steps in manner of 7 second delay.
Even lines will contain guitar input, odd will contain delay loop and both could be crossfaded

igorp
Posts: 21
Joined: Tue May 19, 2015 6:10 am
Location: RU

Post by igorp » Mon Feb 05, 2018 5:31 am

4 msec before and 4 msec after zero adress X-fade was enough.
longer falling eat attack

Image

alpignolo
Posts: 16
Joined: Tue May 27, 2014 8:40 am

Post by alpignolo » Mon Jun 18, 2018 9:02 am

igorp wrote:4 msec before and 4 msec after zero adress X-fade was enough.
longer falling eat attack

Image
Someone has solved the clicking problem?

Post Reply