Sample and Hold

Algorithm development and general DSP issues

Moderator: frank

Post Reply
Aaron
Posts: 54
Joined: Wed Mar 04, 2015 8:10 pm
Location: Oklahoma

Sample and Hold

Post by Aaron »

I am trying to create a sample and hold type of effect using Frank's LFSR code and DigitalLarry's SVF code. I have the output of the LFSR being used as a crossfade coefficient between the lowpass and highpass outputs of the SVR. I can hear that it wants to work but there is a lot of distortion taking place. I assume that there needs to be some kind of filtering on the output of the LFSR but whenever I implement it, it becomes less random. If anyone can point me in the right direction it would be much appreciated. Thanks!

Code: Select all

lfsr           equ reg0 
lfsr2         equ reg1 
temp        equ reg2
mono	equ reg3
lowpass	equ reg4
hipass	equ reg5
bndpass	equ reg6
lfo	        equ reg7 
lfsrfil 	equ reg8
; 
; seed the lfsr with a non-zero value 
skp run,start 
wlds sin0,0,32767


ldax adcl 
or 0x001000   ; just to ensure it is really non-zero 
wrax lfsr,0 
; 
; 
start: 
ldax pot0
mulx pot0
mulx pot0
wrax sin0_rate,0

;rdax adcl,.25
rdax adcr,.5
wrax mono,0


cho rdal,sin0                     ;load sin0 into ACC
sof 1,0.5                           ;scale 0 to 1
sof -1,0                            ;0 to -1
skp neg, shftzro                ;shftzro if ACC is neg(-), otherwise
ldax lfsr      ; get lfsr reg 
and 0x00ffff   ; get rid of upper bits to avoid saturating 
wrax lfsr2,1.0   ; save the result and keep in acc 
rdax lfsr2,0.5   ; get lfsr shifted 1 bit and add it 
rdax lfsr2,0.25   ; get lfsr shifted 2 bits and add 
rdax lfsr2,0.0078125   ; get lfsr shifted 7 bits and add 
and 0x000001   ; only care about lsb of result 
wrax temp,0   ; save result 
rdax lfsr,0.5   ; get lfsr reg shifted right 
and 0x7fffff   ; clear msb 
wrax lfsr,0   ; save result 
ldax temp   ; get the result back 
skp zro,shftzro   ; if 0 jump 
; if here the bit was a 1 
sof 0,0      ; clear acc 
rdax lfsr,1.0   ; get the low 
or 0x800000   ; set the bit
wrax lfsr,0   ; save it 
shftzro: 

rdax mono,1
rdax lowpass,-1			;q * input - LPF 
rdax bndpass,-1			;1 * input - LPF + (-q * BPF) =
wrax hipass,.1224		;HPF * (Fc = 640Hz)
rdax bndpass,1			;HPF * Fc + BPF =
wrax bndpass,.1224		;BPF * Fc
rdax lowpass,1			;BPF * Fc + LPF =
wrax lowpass,.1224		;LPF * Fc
sof 0,0	                        ;clear ACC


rdax lowpass,1         ;read lowpass into ACC
rdax hipass,-1          ;subtract hipass
mulx lfsr                  ;use lfsr for crossfade
rdax hipass,1           ;add hipass
rdax mono,-1           ;subtract mono
mulx pot1                ;use pot1 for blend control
rdax mono,1            ;add mono
;wrax dacl,1
wrax dacr,0             ;write to dacr, clear ACC
frank
Posts: 1244
Joined: Wed Oct 19, 2005 12:26 pm
Contact:

Post by frank »

I would try Jack's code for the random, shorter and cleaner than mine.

I'm no LFSR expert but it would seem to me that filtering could have the effect of making it less random sounding, you are removing part of the information and less information means less states.
Frank Thomson
Experimental Noize
Aaron
Posts: 54
Joined: Wed Mar 04, 2015 8:10 pm
Location: Oklahoma

Post by Aaron »

Trying Jack's code yields the same results in terms of producing distortion. Would this be a scaling issue then?
frank
Posts: 1244
Joined: Wed Oct 19, 2005 12:26 pm
Contact:

Post by frank »

Isolate the SVF outputs and see if the distortion is in there.
Frank Thomson
Experimental Noize
Aaron
Posts: 54
Joined: Wed Mar 04, 2015 8:10 pm
Location: Oklahoma

Post by Aaron »

Using a pot to crossfade between lowpass and high asopposed to the LSFR output, I am able to get a nice clean, filtered signal with no distortion. As soon as the output of the LFSR is applied for the crossfade I get distortion. I'm pretty sure that it is a scaling issue but I am still unclear as to what the actual output of the LFSR is and how to scale it to a usable level.
Aaron
Posts: 54
Joined: Wed Mar 04, 2015 8:10 pm
Location: Oklahoma

Post by Aaron »

So I've reworked this a bit to use a 2pole LPF that I snagged from DigitalLarry's SpinCAD code. Using the LFSR output as the frequency control for this filter gives me less distortion. I am convinced now that it is strictly a scaling issue. However, I am still not sure how to properly scale the LFSR to control the frequency.

Code: Select all

freq	equ reg0
freq2	equ reg1
lp	equ reg2
low	equ reg3
lowpass	equ reg4
lower	equ reg5
lfsr 	equ reg6 
lfsr2	equ reg7 
temp 	equ reg8
mono	equ reg9



skp run,START 
sof 0,0.666      		;to ensure non-zero start 
wrax lfsr,0		;write to lfsr, clear ACC 

wlds sin0,0,32767		;initialize sin0 LFO


START:
rdax adcl,.25		;read adcl * .25
rdax adcr,.25		;read adcr * .25
wrax mono,0		;write to mono, clear ACC

ldax pot0		;load pot0
mulx pot0		;change taper ~ A
mulx pot0			
wrax sin0_rate,0		;write to sin0 rate

cho rdal,sin0		;load sin0 LFO into ACC
sof 1,0.5			;scale 0 to 1
sof -1,0			;-1 to 0
skp neg, SHFTZRO		;skip to shftzro if ACC is neg(-) 
			;otherwise
ldax lfsr        		; load lfsr 
and 0x000001     		;get lsb for lfsr 
wrax temp,0      		;save it to temp, clear ACC 
rdax lfsr,0.5    		;read half of lfsr 
and 0x7FFFFF     		;clear msb 
wrax lfsr,0      		;save to lfsr 
ldax temp		;get output bit 
skp zro,SHFTZRO   	;if ACC is 0 then SHFTZRO 
			;if lsb was set then do process
clr              		;clear ACC 
ldax lfsr			;load lfsr 
xor 0xD80000     		;toggle the MASK bits 
;absa
wrax lfsr,0       		;write to lfsr 

SHFTZRO:
rdax lfsr,1		;read lfsr into ACC
;sof 0.35,-0.35		;scale -.35 to 0
exp 1,0			;~0.705 to 1
;sof 1,-.5
wrax freq,0		;save to freq, clear ACC

rdax lfsr,1		;read lfsr into ACC
sof 1,-0.999		;scale -.999 to .001
exp 1,0			;~ 0.368 to 1
wrax freq2,0		;save to freq2, clear ACC

rdax low,1		;read low into ACC
mulx freq		;multiply by freq
rdax lp,1			;add lp
wrax lp,-1		;save to lp, make neg(-)
wrax lower,0		;save to lower, clear ACC

rdax low,-0.2		;read low * -0.2 into ACC		
rdax lower,1		;add lower
rdax mono,0.5		;add mono * 0.5
wrax lowpass,1		;save to lowpass
mulx freq		;mulx by freq
rdax low,1		;add low
wrax low,0		;save to low, clear ACC

rdax lp,1			;add lp to ACC
rdax mono,-1		;subtract mono
mulx pot1		;crossfade with pot1
rdax mono,1		;add mono
sof -2,0
sof -2,0
;sof -2,0
;sof -2,0
wrax dacr,1		
wrax dacl,0		;write to output
Aaron
Posts: 54
Joined: Wed Mar 04, 2015 8:10 pm
Location: Oklahoma

Post by Aaron »

Alright, so I was able to filter the LFSR once it was scaled and that got rid of the distortion. This code is now working beautifully.

Code: Select all

freq	equ reg0
freq2	equ reg1
lp	equ reg2
low	equ reg3
lowpass	equ reg4
lower	equ reg5
lfsr 	equ reg6 
lfsr2	equ reg7 
temp 	equ reg8
mono	equ reg9



skp run,START 
sof 0,0.666      		;to ensure non-zero start 
wrax lfsr,0		;write to lfsr, clear ACC 

wlds sin0,0,32767		;initialize sin0 LFO


START:
rdax adcl,.25		;read adcl * .25
rdax adcr,.25		;read adcr * .25
wrax mono,0		;write to mono, clear ACC

ldax pot0		;load pot0
mulx pot0		;change taper ~ A
mulx pot0			
wrax sin0_rate,0		;write to sin0 rate

cho rdal,sin0		;load sin0 LFO into ACC
sof 1,0.5			;scale 0 to 1
sof -1,0			;-1 to 0
skp neg, SHFTZRO		;skip to shftzro if ACC is neg(-) 
			;otherwise
ldax lfsr        		; load lfsr 
and 0x000001     		;get lsb for lfsr 
wrax temp,0      		;save it to temp, clear ACC 
rdax lfsr,0.5    		;read half of lfsr 
and 0x7FFFFF     		;clear msb 
wrax lfsr,0      		;save to lfsr 
ldax temp		;get output bit 
skp zro,SHFTZRO   	;if ACC is 0 then SHFTZRO 
			;if lsb was set then do process
clr              		;clear ACC 
ldax lfsr			;load lfsr 
xor 0xD80000     		;toggle the MASK bits 
;absa
wrax lfsr,0       		;write to lfsr 

SHFTZRO:
rdax lfsr,1		;read lfsr into ACC
exp 1,0			;~0.705 to 1
rdfx lfsr2,.003827     ;LPF ~ 20Hz
wrlx lfsr2,-1     ;infinite shelf
wrax freq,0		;save to freq, clear ACC

rdax lfsr,1		;read lfsr into ACC
sof 1,-0.999		;scale -.999 to .001
exp 1,0			;~ 0.368 to 1
wrax freq2,0		;save to freq2, clear ACC

rdax low,1		;read low into ACC
mulx freq		;multiply by freq
rdax lp,1			;add lp
wrax lp,-1		;save to lp, make neg(-)
wrax lower,0		;save to lower, clear ACC

rdax low,-0.2		;read low * -0.2 into ACC		
rdax lower,1		;add lower
rdax mono,0.5		;add mono * 0.5
wrax lowpass,1		;save to lowpass
mulx freq		;mulx by freq
rdax low,1		;add low
wrax low,0		;save to low, clear ACC

rdax lp,1			;add lp to ACC
rdax mono,-1		;subtract mono
mulx pot1		;crossfade with pot1
rdax mono,1		;add mono
sof -2,0
sof -2,0
wrax dacr,1		
wrax dacl,0		;write to output
Digital Larry
Posts: 338
Joined: Mon Nov 12, 2012 1:12 pm
Contact:

Post by Digital Larry »

I haven't done a deep dive on the LFSR, but I presume that it generates both + and - polarity signals. Filter control and crossfade input probably don't really like the negative numbers there. So it might be necessary to add an ABSA after the LFSR.

Your choice as to whether to put a smoothing low pass between the LFSR and the filter control input. Some really great sounds are available either way.

Finally, I tend to restrict my filter control inputs to something like 0.4 or 0.5 minimum - otherwise they are peaking at pretty low frequencies which is not the greatest sound in my opinion.

The other thing which I have NOT yet tried much, but seems like it might be promising, is to use the LOG instruction instead of or in addition to a SOF for filter frequency control.

I made some envelope filters using just SOF, and then I checked the Spin supplied auto-wah and saw that it uses LOG to process the envelope control signal. Either one is OK, so season to taste.
Post Reply