Spin Semiconductor Forum Index Spin Semiconductor
Support forum
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Phaser/allpass filter code
Goto page 1, 2  Next
 
Post new topic   Reply to topic    Spin Semiconductor Forum Index -> Algorithm development
View previous topic :: View next topic  
Author Message
livingston



Joined: 15 Nov 2009
Posts: 131
Location: New Orleans, LA US

PostPosted: Tue Dec 22, 2009 12:16 am    Post subject: Phaser/allpass filter code Reply with quote

I've read this but I must admit I'm not at the point where I can translate these diagrams into the proper opcodes.

How would I write a single allpass stage in code?
Back to top
View user's profile Send private message
frank



Joined: 19 Oct 2005
Posts: 958

PostPosted: Tue Dec 22, 2009 9:29 am    Post subject: Reply with quote

The FV-1 has special instructions for this to make it quick to do. Make the following assumptions:

"IN" is in the accumulator already, may have come from a filter, delay, ADC, etc.
"DELAY" is the name of the delay block in the all-pass.
"K" = 0.37, why? Because I like that number for examples.
Code:

rda DELAY#, 0.37 ; Read end of DELAY, multiply by 0.37 and add to acc
wrap DELAY, 0.37 ; Write acc to delay, multiply acc by -0.37 and add the 'last read' value from delay memory saved in the LR register. OUT is in the acc.

Note the LR register is automatically updated every time a value is read from memory so it holds DELAY# when we execute the wrap instruction.

So there you have it, a 2-tick APD.
_________________
Frank Thomson
Experimental Noize
Back to top
View user's profile Send private message Visit poster's website
livingston



Joined: 15 Nov 2009
Posts: 131
Location: New Orleans, LA US

PostPosted: Tue Dec 22, 2009 2:15 pm    Post subject: Reply with quote

Can I equate K to a register, or is it like my earlier question where it needs to be a specific coefficient? If I can't, how do I create a varying K value for a phaser?
Back to top
View user's profile Send private message
frank



Joined: 19 Oct 2005
Posts: 958

PostPosted: Tue Dec 22, 2009 3:42 pm    Post subject: Reply with quote

In this case K is fixed, you need to use mulx to multiply by a register. An all pass can still be done but it will take 6 or 7 instructions to do it, I haven't written code to do this but it should be:

read end of delay (rda),
multiply by reg (mulx),
add input (rdax or rda depending if from register or memory),
write to head of delay (wra),
multiply by reg (mulx),
multiply by -1 (sof),
read end of delay(rda)
_________________
Frank Thomson
Experimental Noize
Back to top
View user's profile Send private message Visit poster's website
livingston



Joined: 15 Nov 2009
Posts: 131
Location: New Orleans, LA US

PostPosted: Fri Jan 01, 2010 1:07 am    Post subject: Reply with quote

I hacked up what I thought a 4-stage phaser might look like using your suggestions. It uses the envelope to vary the phasing.

Code:
mem   delay   205   
mem   delay2   205
mem   delay3   205
mem   delay4   205
mem   delay5   205
mem   delay6   205
mem   delay7   205
mem   delay8   205
equ   ap1out   reg1
equ   ap2out   reg2
equ   ap3out   reg3
equ   ap4out   reg4
equ   ap5out   reg5
equ   env   reg6
equ   envfil   reg7

rdax   adcr,1
absa
RDFX   envfil,0.001   ;use LPF opcode for filtering
WRLX   envfil,-1      ;infinite shelf LPF (could have used WRAX avgfil,1)
sof   1.5,0      ;get bigger envelope
wrax   env,0      

rda    DELAY#,    1    ; Read end of DELAY,
mulx    env
rdax   adcr,   1
wra   delay,    1   ;write to head of delay (wra),
mulx   env      ;multiply by reg (mulx),
sof   -1,   0   ;multiply by -1 (sof),
rda    DELAY#,    1    ;read end of delay(rda)
wrax   ap1out,   0

rda    DELAY2#, 1    ; Read end of DELAY,
mulx    env
rdax   ap1out,   1
wra   delay2,    1   ;write to head of delay (wra),
mulx   env      ;multiply by reg (mulx),
sof   -1,   0   ;multiply by -1 (sof),
rda    DELAY2#, 1    ;read end of delay(rda)
wrax   ap2out,   0

rda    DELAY3#, 1    ; Read end of DELAY,
mulx    env
rdax   ap2out,   1
wra   delay3,    1   ;write to head of delay (wra),
mulx   env      ;multiply by reg (mulx),
sof   -1,   0   ;multiply by -1 (sof),
rda    DELAY3#, 1    ;read end of delay(rda)
wrax   ap3out,   0

rda    DELAY4#, 1    ; Read end of DELAY,
mulx    env
rdax   ap3out,   1
wra   delay4,    1   ;write to head of delay (wra),
mulx   env      ;multiply by reg (mulx),
sof   -1,   0   ;multiply by -1 (sof),
rda    DELAY4#, 1    ;read end of delay(rda)
wrax   ap4out,   1

mulx   pot1
rdax   adcr,   1

wrax   dacr,   0


So far it doesn't work, but it involved a lot of guessing so I didn't really expect it to. I can't remember now why I made the delays 205 samples, and I'm guessing this is one thing that isn't right, but I don't really know how to figure them.

Any suggestions on where I'm going wrong?
Back to top
View user's profile Send private message
frank



Joined: 19 Oct 2005
Posts: 958

PostPosted: Fri Jan 01, 2010 10:29 am    Post subject: Reply with quote

A quick look seems OK (will take a closer look Monday when back in the office), try making it just one AP and seeing if it works than add in the LP filter, then the additional stages, etc. We need to isolate where it fails.
_________________
Frank Thomson
Experimental Noize
Back to top
View user's profile Send private message Visit poster's website
mdroberts1243



Joined: 22 Jul 2008
Posts: 18
Location: Ottawa, Canada

PostPosted: Sat Sep 11, 2010 1:09 pm    Post subject: Reply with quote

frank wrote:
In this case K is fixed, you need to use mulx to multiply by a register. An all pass can still be done but it will take 6 or 7 instructions to do it, I haven't written code to do this but it should be:

read end of delay (rda),
multiply by reg (mulx),
add input (rdax or rda depending if from register or memory),
write to head of delay (wra),
multiply by reg (mulx),
multiply by -1 (sof),
read end of delay(rda)


I just had to do a similar thing, where the allpass coefficient was in a register, derived from a pot. Input is in the ACC, so I didn't think you needed to add the input, it is done in the first rda. I came up with this (hopefully it is right):

rda delay#, 1 ; allpass with WRAP replaced to use variable coefficient
mulx coefficient
wra delay, -1 ; store to delay and then negate ACC
mulx coefficient ; apply 'negative' coefficient
rda delay#, 1 ; add in the end entry in the delay
_________________
-mark
My blog: http://tubenexus.com
Back to top
View user's profile Send private message Visit poster's website
frank



Joined: 19 Oct 2005
Posts: 958

PostPosted: Sat Sep 11, 2010 3:21 pm    Post subject: Reply with quote

mdroberts1243 wrote:


I just had to do a similar thing, where the allpass coefficient was in a register, derived from a pot. Input is in the ACC, so I didn't think you needed to add the input, it is done in the first rda. I came up with this (hopefully it is right):

rda delay#, 1 ; allpass with WRAP replaced to use variable coefficient
mulx coefficient
wra delay, -1 ; store to delay and then negate ACC
mulx coefficient ; apply 'negative' coefficient
rda delay#, 1 ; add in the end entry in the delay


Not quite correct, input to all-pass is: input + (delayout * K)

If input is in ACC then you are doing: (input + delayout) * K

Not the same result
_________________
Frank Thomson
Experimental Noize
Back to top
View user's profile Send private message Visit poster's website
mdroberts1243



Joined: 22 Jul 2008
Posts: 18
Location: Ottawa, Canada

PostPosted: Sat Sep 11, 2010 8:05 pm    Post subject: Reply with quote

frank wrote:
mdroberts1243 wrote:


I just had to do a similar thing, where the allpass coefficient was in a register, derived from a pot. Input is in the ACC, so I didn't think you needed to add the input, it is done in the first rda. I came up with this (hopefully it is right):

rda delay#, 1 ; allpass with WRAP replaced to use variable coefficient
mulx coefficient
wra delay, -1 ; store to delay and then negate ACC
mulx coefficient ; apply 'negative' coefficient
rda delay#, 1 ; add in the end entry in the delay


Not quite correct, input to all-pass is: input + (delayout * K)

If input is in ACC then you are doing: (input + delayout) * K

Not the same result


Thanks Frank!

Had to go over it a few times to understand... ended up storing the input to a temp register, clearing the ACC and adding a line:

wrax temp, 0
rda delay#, 1 ; allpass with WRAP replaced to use variable coefficient
mulx coefficient
rdax temp,1 ; add input *NEW*
wra delay, -1 ; store to delay and then negate ACC
mulx coefficient ; apply 'negative' coefficient
rda delay#, 1 ; add in the end entry in the delay
_________________
-mark
My blog: http://tubenexus.com
Back to top
View user's profile Send private message Visit poster's website
frank



Joined: 19 Oct 2005
Posts: 958

PostPosted: Sat Sep 11, 2010 11:15 pm    Post subject: Reply with quote

That looks good, think that will work.
_________________
Frank Thomson
Experimental Noize
Back to top
View user's profile Send private message Visit poster's website
mdroberts1243



Joined: 22 Jul 2008
Posts: 18
Location: Ottawa, Canada

PostPosted: Sun Sep 12, 2010 9:08 am    Post subject: Reply with quote

frank wrote:
That looks good, think that will work.


I think it works, but I went and tried to add chorusing on the delay taps, screwing everything up, which requires me to re-think the flow again.

I don't understand the 'post' processing chorus stuff that is done in a lot of the reverb example programmes... is that explained anywhere? I'm trying to implement the modulated output taps directly in the allpass as shown in a lot of reverb flow-diagrams instead.

Thanks,
_________________
-mark
My blog: http://tubenexus.com
Back to top
View user's profile Send private message Visit poster's website
frank



Joined: 19 Oct 2005
Posts: 958

PostPosted: Sun Sep 12, 2010 7:54 pm    Post subject: Reply with quote

Can you post or link directly to an example so I can see the code you are talking about? Lots of reasons to do things in a reverb program.
_________________
Frank Thomson
Experimental Noize
Back to top
View user's profile Send private message Visit poster's website
mdroberts1243



Joined: 22 Jul 2008
Posts: 18
Location: Ottawa, Canada

PostPosted: Mon Sep 13, 2010 3:54 am    Post subject: Reply with quote

frank wrote:
Can you post or link directly to an example so I can see the code you are talking about? Lots of reasons to do things in a reverb program.


Hi Frank,
Thanks. I've been coding up the Dattorro plate reverb as an exercise (in frustration) Wink
I will start a separate thread... the result might be interesting for others.
_________________
-mark
My blog: http://tubenexus.com
Back to top
View user's profile Send private message Visit poster's website
mdroberts1243



Joined: 22 Jul 2008
Posts: 18
Location: Ottawa, Canada

PostPosted: Mon Sep 13, 2010 5:10 am    Post subject: Reply with quote

frank wrote:
Can you post or link directly to an example so I can see the code you are talking about? Lots of reasons to do things in a reverb program.


I think the plate reverb examples on spinsemi use a block of chorus statements at the end of the code to affect each delay. I don't understand that... It seems to just juggle some samples in the interior of the delay. If this is somehow equivalent to modulating the read from the end of the delay/AP then it would be a lot more efficient to implement the Dattorro diagram in the FV-1!
_________________
-mark
My blog: http://tubenexus.com
Back to top
View user's profile Send private message Visit poster's website
frank



Joined: 19 Oct 2005
Posts: 958

PostPosted: Mon Sep 13, 2010 9:44 am    Post subject: Reply with quote

A quick look at the code makes me believe the chorusing of values in the all-pass' is to stop any repetitive noise from happening. With these kind of structures you can get a repetitive sound at a particular frequency, by slightly shifting the sound with a chorus type effect you can stop that from happening.
_________________
Frank Thomson
Experimental Noize
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic    Spin Semiconductor Forum Index -> Algorithm development All times are GMT - 8 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group