Variable time stereo delay

sebxx4
Posts: 26
Joined: Mon Jun 27, 2022 8:08 am

Variable time stereo delay

Post by sebxx4 »

Hello,
I wrote a stereo delay code and it basicly works fine. There is separation between channels.

Code: Select all

.rn	in_l	r0		; left input register
.rn	in_r	r1		; right input register
.rn	out_l	r2		; left output register
.rn	out_r	r3		; right output register

.mem	delay_l	16383		; left channel delay block
.mem	delay_r	16383		; right channel delay block

cpy_cs	acc32, in0		; read in left channel into acc
multri	acc32, 0.707		; scale acc by 0.707
cpy_cc	in_l, acc32		; write acc to variable

cpy_cs	acc32, in1		; read in right channel into acc
multri	acc32, 0.707		; scale acc by 0.707
cpy_cc	in_r, acc32		; write acc to variable

wrdel	delay_l, in_l		; write left channel to delay head
wrdel	delay_r, in_r		; write right channel to delay head
rddel	out_l, delay_l#		; read left delay tail into variable
rddel	out_r, delay_r#		; read right delay tail into variable

cpy_cc	acc32, out_l		; load left delay output into acc
adds	acc32, in_l		; add left input
cpy_sc	out0, acc32		; sent it to left dac

cpy_cc	acc32, out_r		; load right delay output into acc
adds	acc32, in_r		; add right input
cpy_sc	out1, acc32		; sent it to right dac
Now I would like to add delay time control via pot. The main problem is, there are two delay blocks.
I tried to add control to interp instruction, like this:

Code: Select all

cpy_cc	len, POT0_SMTH

wrdld	acc32, 16383
cpy_cc	end_r, acc32
multrr	acc32, len
cpy_cc	end_l, acc32

wrdld	acc32, 16383
multrr	acc32, len
adds	acc32, end_r
cpy_cc	end_r, acc32

wrdel 	0, temp_l
interp	end_l, 32737
cpy_cc	temp_l, acc32

wrdel 	16384, temp_r
interp	end_r, 32737
cpy_cc	temp_r, acc32
But one channel is now playing in both. I tried also read delay with rddelx, but with similar resault. What do I wrong? Or how to do it correctly?
DisasterArea
Posts: 26
Joined: Sat Jul 25, 2020 7:07 pm

Re: Variable time stereo delay

Post by DisasterArea »

I'll take this one.

I'm not going to write code for you, but I'll give you some pointers to help you write the code yourself.

Your second example doesn't work because you aren't using INTERP correctly. Check the FX Core Instruction set and application note AN-1 for good examples.

The instruction syntax is interp creg, delay

That is interpreted as "go to delay memory starting at the lowest address of 'delay,' then go up 'creg' bytes of address and get that sample." It's a little more complex than that but this is a good way to think about it.

Your example does INTERP end_l, 32737, so it's trying to read the delay starting at address 32737 + (16383*pot0) which is not a valid address. I'm surprised it works at all.

Here's the general procedure for reading a delay using INTERP:

Code: Select all

.mem      delay, 16383      ; declare delay size

cpy_cs     r0, in0          ; read input
cpy_cs     r1, pot0_smth    ; read pot
wrdld      acc32, delay!    ; put size of delay into acc32
multrr     acc32, r1        ; multiply delay length * pot value to get delay read position
interp     acc32, delay     ; read "delay" at location "acc32," result of read will be in acc32
cpy_sc     out0, acc32      ; output delay signal to DAC
You don't have to output the delay immediately after reading it, of course, you can process it further. You may also find that you need to increase the pot filtering K values as noise on the control signal for INTERP sounds pretty bad.
sebxx4
Posts: 26
Joined: Mon Jun 27, 2022 8:08 am

Re: Variable time stereo delay

Post by sebxx4 »

Thank you, Sir.
At this moment I got working stereo delay with lenght control. I also found topic on the spinsemi forum called "2 seconds delay". I implemented this trick in my delay code. It works fine.

Code: Select all

; Stereo delay (double delay lenght)
.rn	in_l	r0
.rn	in_r	r1
.rn	out_l	r2
.rn	out_r	r3
.rn	temp_l	r4
.rn	temp_r	r5
.rn	loop	r6
.rn	len_l	r7
.rn	len_r	r8
.rn	pot_val	r9

.creg	loop	1

; Control delay lenght
cpy_cs	pot_val, POT0_SMTH	; read pot0 value into variable
multri	acc32, 0		; clear acc
ori	acc32, 0x3FFE		; insert 0x3FFE into acc (max delay address)
multrr	acc32, pot_val		; multiply it by pot0 value
andi	acc32, 0xFFFE		; make sure address LSB is 0
cpy_cc	len_l, acc32		; save it to first delay block lenght
ori	acc32, 0x4000		; add offset to delay address for next block
cpy_cc	len_r, acc32		; save it to second delay block lenght

; Inputs
cpy_cs 	acc32, in0		; read left channel into acc
multri	acc32, 0.707		; scale it by 0.707
cpy_cc	in_l, acc32		; save it to variable

cpy_cs 	acc32, in1		; read right channel into acc
multri	acc32, 0.707		; scale it by 0.707
cpy_cc	in_r, acc32		; save it to variable

jneg	loop, NegLoop		; jump to NegLoop if loop value < 0
cpy_cc	temp_l, in_l		; if not, copy input to temp variable
cpy_cc	temp_r, in_r		; if not, copy input to temp variable

NegLoop:
; Delay
wrdel	0, temp_l		; write temp variable to delay block
wrdel	16384, temp_r		; write temp variable to delay block

rddelx	temp_l, len_l		; read end of delay block into variable
rddelx	temp_r, len_r		; read end of delay block into variable

jgez	loop, PosLoop		; jump to PosLoop if loop value > 0
cpy_cc	out_l, temp_l		; if not, copy temp to output variable
cpy_cc	out_r, temp_r		; if not, copy temp to output variable

PosLoop:
; Outputs
adds 	out_l, in_l		; add dry and wet signal
cpy_sc 	out0, acc32		; send it do dac

adds 	out_r, in_r		; add dry and wet signal
cpy_sc 	out1, acc32		; send it do dac

; Loop flip
neg	loop			; neg loop value and copy to acc
cpy_cc	loop, acc32		; save new loop value
Only thing I had to change is using rddelx instruction instead of interp.

One more question about it - is it possible to eliminate this "scratch" effect while changing delay lenght?
sebxx4
Posts: 26
Joined: Mon Jun 27, 2022 8:08 am

Re: Variable time stereo delay

Post by sebxx4 »

Is it impossible?
DisasterArea
Posts: 26
Joined: Sat Jul 25, 2020 7:07 pm

Re: Variable time stereo delay

Post by DisasterArea »

sebxx4 wrote: Fri Jul 29, 2022 12:33 pmIs it impossible?
Not impossible but you're not doing yourself any favours here. You're using RDDELX instead of INTERP, so you'll get interpolation noise as you change delay addresses. Check the delay example program for best practices on how to get a nice smooth result.

You can also change the pot smoothing coefficient, that might help too.
sebxx4
Posts: 26
Joined: Mon Jun 27, 2022 8:08 am

Re: Variable time stereo delay

Post by sebxx4 »

DisasterArea wrote: Fri Jul 29, 2022 7:31 pmYou're using RDDELX instead of INTERP, so you'll get interpolation noise as you change delay addresses.
Yes, but how to interpolate when odd samples are first pass delay and even are the second ones? I would have to interpolate every other sample, but I guess it's not possible? At least not directly using the interp function.
Frank
Posts: 159
Joined: Sun May 03, 2015 2:43 pm

Re: Variable time stereo delay

Post by Frank »

Why not just run the chip at a 12KHz sample rate? That give a total of 2.7 seconds of delay and allows you to use interp. If you want to do a trick like interleaving samples or use a loop to only read/write direct every other period or any other trick you will need to write your own interpolation routine or accept the noise.
sebxx4
Posts: 26
Joined: Mon Jun 27, 2022 8:08 am

Re: Variable time stereo delay

Post by sebxx4 »

Well, if I run whole chip at Fs = 12kHz it gives me bandwidth <6kHz. It's not acceptable in audio solutions. But when Fs is set to 48kHz, using this trick gives me delayed signal at 'virtual' Fs = 24kHz so bandwidth of 12kHz, and this mixed back with dry signal of full bandwidth sounds good.

I will try to code interpolation algo then.

Btw - I dont remember well, but when I ran demo delay program on devboard, I think there was this scratch effect too while fast changing delay time. I may be wrong, but maybe we don't mean the same artifacts?
Frank
Posts: 159
Joined: Sun May 03, 2015 2:43 pm

Re: Variable time stereo delay

Post by Frank »

The scratch sound is a result of moving the pointer across samples as you adjust the delay. You can play with things like the smoothing coefficient to minimize it or use the raw pot value but it will jump and cause discontinuities which will result in a different noise.
sebxx4
Posts: 26
Joined: Mon Jun 27, 2022 8:08 am

Re: Variable time stereo delay

Post by sebxx4 »

Thanks Frank, thats what I was talking about. I'll try.
Post Reply