Variable delay line modulated w/ LFO

Algorithm development and general DSP issues

Moderator: frank

Post Reply
edwillys
Posts: 14
Joined: Wed Jun 01, 2011 3:33 pm
Location: France

Variable delay line modulated w/ LFO

Post by edwillys »

Hello all,

I have a little doubt here. I'm working on a chorus in which one one the POTs control the delay time. Therefore if i've got it right, I first have to reserve a memory space for the worst case scenario, which would be the max delay. Then, because we're talking about a variable delay, I wouldn't be able to use the CHO RDA instruction but the CHO SOF instead and then manipulate the ADDR_PTR (correct me if I'm wrong).

I'm getting a bit confused since SpinASM would compile pretty much anything (such as CHO RDA,SIN0,SIN,reg0+reg1+reg2+reg3). I thought about something like that.

mem delay 262 ; delay max of 8ms --> 262 samples at 32768Hz

equ ptr reg2
equ dly_pot reg3
equ delay_offset 0.003
equ delay_slope 0.005

rdax POT1,1.0
sof delay_slope,delay_offset ; adjust delay
wrax dly_pot,0 ; put the value into register, clear acc

rdax ADCR,0.5 ;Read right sample
rdax ADCL,0.5 ;Read left sample

wra delay, 0 ;write to delay, clear accumulator

cho sof,sin0,sin,0 ; read LFO
rdax dly_pot,1.0 ; pot1 offset
sof 1.0,delay^/1024 ; base delay offset
wrax addr_ptr ; write to pointer
rmpa 1.0

I'm getting a bit confused on the conversion types, in particular the delay^/1024. By the way, I didn't find anywhere in the docs that it's possible to do such operation as a pre-assembly line, though the assembler doesn't accuse any errors.
Can you help me out here? Is there a way to make it work through CHO RDA directly?
edwillys
Posts: 14
Joined: Wed Jun 01, 2011 3:33 pm
Location: France

Post by edwillys »

sorry, forgot the argument

wrax addr_ptr,1.0 ; write to pointer
frank
Posts: 1244
Joined: Wed Oct 19, 2005 12:26 pm
Contact:

Post by frank »

Yeah, working out all the bit positions can be a little difficult. A few tips:

If using the LFO like you are then set the amplitude to max and you should get it appearing in the acc ranging +1/-1 if I remember correctly.

The accumulator bits used for addr_ptr are from bits acc[22:8] so adjust values to fit that range.

The accumulator is 24 bits wide and acc[23] is typically considered the sign bit and is the reason it is not used for addr_ptr.
Frank Thomson
Experimental Noize
edwillys
Posts: 14
Joined: Wed Jun 01, 2011 3:33 pm
Location: France

Post by edwillys »

Thanks for your reply Frank. So you mean that the result from CHO SOF will be a S.10 value? Or a S.1.14 on the +1 -1 range?

Also, if the number is, lets say, S.10 and its value is +1 (0.99...). How is it converted internally to a S1.14? Will it be +1 in a S1.14 representation as well or would it be +2?

Edgar
frank
Posts: 1244
Joined: Wed Oct 19, 2005 12:26 pm
Contact:

Post by frank »

The acc is S.23 format which in 2's comp allows for the range -1.000 to +0.999...

In general for additions the sign bits are aligned and if the result exceeds the allowed range it is limited to the range. I.e. -1.123 would get limited to -1.000 and +1.234 to +0.9999...

Most times other formats like S1.14 are the coefficient for a multiply and not the resulting value or it is a special case like "log" where the result has to be carefully handled.

So basically your data will be S.23 format (this is the normal format for 24-bit ADCs and DACs), your coefficients may vary slightly depending on instructions and have integer bits (to allow you to have gain in your code) and we have a few odd-ball instructions that break the rules (log, rmpa etc.) and take a bit more thought to use but can allow for really fun effects.
Frank Thomson
Experimental Noize
frank
Posts: 1244
Joined: Wed Oct 19, 2005 12:26 pm
Contact:

Post by frank »

Saying "the sign bits are aligned" is a poor choice of words. Really the binary points are aligned and any required sign extension is taken care of.
Frank Thomson
Experimental Noize
edwillys
Posts: 14
Joined: Wed Jun 01, 2011 3:33 pm
Location: France

Post by edwillys »

it seems that i'm still not getting it quite right. basically what I'm trying to do is to access the delay line through addr_ptr. So far so good, except that addr_ptr doesn't seem to be modulated by the SIN0 LFO. Can you see something wrong in the method below:

equ aux reg0 ; auxiliar register
equ sigin reg1 ; input signal
equ dly_pot reg3
equ delay_offset 0.003
equ delay_slope 0.005
equ rate_offset 0.073631077818510779026468204295613
equ rate_slope 0.171805848243191817728425810023

skp run,START
wlds SIN0,0,0
clr

rdax POT0,1.0
sof rate_slope,rate_offset ;adjust POT1
wrax sin0_rate,0 ;write value to set sin1 rate, clear acc

rdax POT1,1.0
sof delay_slope,delay_offset ; adjust delay
wrax dly_pot,0 ; put the value into the register clear acc

rdax dly_pot,1.0 ; write delay to acc
wrax aux,0 ; aux = delay, clear acc
rdax POT2,1.0
mulx aux ; multiply acc by dly_pot
sof 32767/16385,0 ; multiply acc by 1.999816
wrax sin0_range,0 ;control lfo width with result, clear acc

rdax ADCR,0.5 ;Read right sample
rdax ADCL,0.5 ;Read left sample

wrax sigin, 1.0 ;write to register sigin, keep accumulator
wra delay, 0 ;write to delay, clear accumulator

cho sof,sin0,sin,0 ; read LFO
rdax dly_pot,1.0 ; pot1 offset
sof 1.0,delay^/32768 ; base delay offset
wrax addr_ptr,0 ; write to pointer, cler acc
rmpa 1.0
rdax sigin, 1.0 ;add to sigin


wrax DACR,1.0 ; write to the right output
wrax DACL,0 ; write to the left output


Thanks in advance
edwillys
Posts: 14
Joined: Wed Jun 01, 2011 3:33 pm
Location: France

Post by edwillys »

By the way I just saw on the website a little trick to servo the delay RAM:

skp run,1 ;only establish the LFO on the first sample pass
wldr rmp0,0,4096 ;set rmp0 to its widest range
cho rdal,rmp0 ;load in the current RMP0 pointer
rdax mpos,-1 ;subtract the desired position
wrax rmp0_rate,0 ;write the position error to the ramp rate register
cho rda,rmp1,reg|compc,del
cho rda,rmp1,0,del+1

I just didn't get exactly how can I change immediately the valur of the ramp lfo by writing on the rmp0_rate register. I mean, I don't get how can I change the rmp0 value only by changing the frequency register. Any hints?

Thanks
edwillys
Posts: 14
Joined: Wed Jun 01, 2011 3:33 pm
Location: France

Post by edwillys »

I think I've got it working even though I don't know how the "servo" addressing works =| I'd appreciate an explanation :)

BTW if anyone is interested on the code let me know.

cheers
frank
Posts: 1244
Joined: Wed Oct 19, 2005 12:26 pm
Contact:

Post by frank »

I'm not sure Keith ever got the servo code fully working but the basic idea was that as the pointer got closer to the desire location you slowed the ramp down by writing to the rate register so that when it got to the desired end point you were writing 0 to the rate register effectively stopping the ramp.

And yes, please post the code, I like to see other peoples styles of coding and I'm sure others can learn from the code.
Frank Thomson
Experimental Noize
Post Reply