;*******************************************************************************
; C H A M E L E O N   DSP Assembler file                                       *
;*******************************************************************************
; Copyright (C) 2001-2002 Soundart                                             *
; www.soundart-hot.com                                                         *
; support@soundart-hot.com                                                     *
;
; Stereo Filter modified by Aleix Riera					       
; aleix@fjarre.com                 					       
; www.fjarre.com/~aleix
;*******************************************************************************
;
; MODULE: Filter2 (CUTOFF ISN'T A BUFFER)
;	Implements a 24dB resonant lowpass filter (the code is based in the 
;	source code of the filter Moog VCF variation2 of the musicdsp.org 
;	filters source code page, thanks to Bram de Jong).
;
;	Basicly, this filter implements this algorithm (four 1-pole
;	stages with feedback) without optimization:
;
;	fb = res * (1.0 - 0.15 * f * f); 
;	input -= out4 * fb; 
;	input *= 0.35013 * (f*f)*(f*f); 
;	out1 = input + 0.3 * in1 + (1 - f) * out1; // Pole 1 
;	in1  = input; 
;	out2 = out1 + 0.3 * in2 + (1 - f) * out2;  // Pole 2 
;	in2  = out1; 
;	out3 = out2 + 0.3 * in3 + (1 - f) * out3;  // Pole 3 
;	in3  = out2; 
;	out4 = out3 + 0.3 * in4 + (1 - f) * out4;  // Pole 4 
;	in4  = out3; 
;	output = out4
;
; NOTE: The filter cutoff range should be revised because values close to 0.0
;	makes the filter unstable.
;
; ARGUMENTS:
;	(X)   = InAddr		- Input stereo buffer (L)
;	(X+1) = OutAddr		- Output stereo buffer (L)
;	(X+2) = Control		- Cutoff input (Y)
;	LEFT:
;	(X+3) = Resonance	- Resonance constant
;	(X+4) = In1		- Input1 state
;	(X+5) = Out1		- Output1 state
;	(X+6) = In2		- Input2 state
;	(X+7) = Out2		- Output2 state
;	(X+8) = In3		- Input3 state
;	(X+9) = Out3		- Output3 state
;	(X+10)= In4		- Input4 state
;	(X+11)= Out4		- Output4 state
;	RIGHT:
;	(X+12) = Resonance	- Resonance constant
;	(X+13) = In1		- Input1 state
;	(X+14) = Out1		- Output1 state
;	(X+15) = In2		- Input2 state
;	(X+16) = Out2		- Output2 state
;	(X+17) = In3		- Input3 state
;	(X+18) = Out3		- Output3 state
;	(X+19)= In4		- Input4 state
;	(X+20)= Out4		- Output4 state
;
;******************************************************************************
module_filter:
	define	R_InL			'R1'
	define	R_OutL			'R2'
	define	R_InR			'R6'
	define	R_OutR			'R7'
	define	R_Control		'R5'
;===============================CODE=====================================

	MOVE 	X:(R_X)+,R_InL
	MOVE	X:(R_X)+,R_OutL
	MOVE	R_InL,R_InR
	MOVE	X:(R_X)+,R_Control
	MOVE	R_OutL,R_OutR
	MOVE	#8,N_X

	.LOOP	#BUFFER_SIZE
	;----------------------------------------------------------------
	;MOVE	Y:(R_Control)+,X0			; X0=f
	MOVE	Y:(R_Control),X0			; X0=f
		
	MPY	X0,X0,A					; A=K1=f*f
	MOVE	X:(R_X)+,X1				; X1=res
	MOVE	A,Y0					; Y0=K1
	MPY	X1,Y0,B					; B=K2=X1*Y0=res*K1
	MOVE	#0.15,Y1				; Y1=0.15
	TFR	X1,B		B,X1			; X1=K2, B=res
	MAC	-Y1,X1,B				; B=fb=B-Y1*X1=res-0.15*K2

	MOVE	X:(R_InL)+,A				; A=input
	MOVE	X:(R_X+7),X1				; X1=out4
	MPY	Y0,Y0,B		B,Y0			; Y0=fb, B=K3=Y0*Y0=K1*K1
	ASR	#2,A,A					; A=input=0.25*A=0.25*input
	MAC	-X1,Y0,A				; A=input=A-X1*Y0=input-out4*fb
	MOVE	#0.35013,Y0				; Y0=0.35013
	MOVE	A,X1					; X1=A=input
	MPY	Y0,X1,A		B,Y0			; A=input=Y0*X1=0.35013*input, Y0=B=K3
	ASL	#2,A,A					; A=input=4*A=4*input
	NOP
	MOVE	A,X1					; X1=A=input
	MPY	X1,Y0,A		#0.3,Y0			; A=input=X1*Y0=input*K3, Y0=0.3

	MOVE	X:(R_X)+,X1				; X1=in1
	MAC	Y0,X1,A		X:(R_X)-,X1	A,Y1	; A=K4=A+Y0*X1=input+0.3*in1, X1=out1, Y1=input
	MAC	-X0,X1,A	Y1,X:(R_X)+		; A=K5=A-X0*X1=K4-f*out1, in1=Y1=input
	ADD	X1,A					; A=out1=A+X1=K5+out1
	NOP
	MOVE	A,X:(R_X)+				; out1=A=out1
	
	MOVE	X:(R_X)+,X1				; X1=in2
	MAC	Y0,X1,A		X:(R_X)-,X1	A,Y1	; A=K6=A+Y0*X1=out1+0.3*in2, X1=out2, Y1=out1
	MAC	-X0,X1,A	Y1,X:(R_X)+		; A=K7=A-X0*X1=K6-f*out2, in2=Y1=out1
	ADD	X1,A					; A=out2=A+X1=K7+out2
	NOP
	MOVE	A,X:(R_X)+				; out2=A=out2

	MOVE	X:(R_X)+,X1				; X1=in3
	MAC	Y0,X1,A		X:(R_X)-,X1	A,Y1	; A=K8=A+Y0*X1=out2+0.3*in3, X1=out3, Y1=out2
	MAC	-X0,X1,A	Y1,X:(R_X)+		; A=K9=A-X0*X1=K8-f*out3, in3=Y1=out2
	ADD	X1,A					; A=out3=A+X1=K9+out3
	NOP
	MOVE	A,X:(R_X)+				; out3=A=out3

	MOVE	X:(R_X)+,X1				; X1=in4
	MAC	Y0,X1,A		X:(R_X)-,X1	A,Y1	; A=K10=A+Y0*X1=out3+0.3*in4, X1=out4, Y1=out3
	MAC	-X0,X1,A	Y1,X:(R_X)+		; A=K11=A-X0*X1=K10-f*out4, in3=Y1=out3
	ADD	X1,A					; A=out4=A+X1=K11+out4
	NOP
	MOVE	A,X:(R_X)-N_X				; out4=A=out4
	MOVE	A,X:(R_OutL)+				; output=A=out4
	;----------------------------------------------------------------
	.ENDL

	LUA	(R_X+9),R_X
	
	.LOOP	#BUFFER_SIZE
	;----------------------------------------------------------------
	;MOVE	Y:(R_Control)+,X0			; X0=f
	MOVE	Y:(R_Control),X0			; X0=f
	
	MPY	X0,X0,A					; A=K1=f*f
	MOVE	X:(R_X)+,X1				; X1=res
	MOVE	A,Y0					; Y0=K1
	MPY	X1,Y0,B					; B=K2=X1*Y0=res*K1
	MOVE	#0.15,Y1				; Y1=0.15
	TFR	X1,B		B,X1			; X1=K2, B=res
	MAC	-Y1,X1,B				; B=fb=B-Y1*X1=res-0.15*K2

	MOVE	Y:(R_InR)+,A				; A=input
	MOVE	X:(R_X+7),X1				; X1=out4
	MPY	Y0,Y0,B		B,Y0			; Y0=fb, B=K3=Y0*Y0=K1*K1
	ASR	#2,A,A					; A=input=0.25*A=0.25*input
	MAC	-X1,Y0,A				; A=input=A-X1*Y0=input-out4*fb
	MOVE	#0.35013,Y0				; Y0=0.35013
	MOVE	A,X1					; X1=A=input
	MPY	Y0,X1,A		B,Y0			; A=input=Y0*X1=0.35013*input, Y0=B=K3
	ASL	#2,A,A					; A=input=4*A=4*input
	NOP
	MOVE	A,X1					; X1=A=input
	MPY	X1,Y0,A		#0.3,Y0			; A=input=X1*Y0=input*K3, Y0=0.3

	MOVE	X:(R_X)+,X1				; X1=in1
	MAC	Y0,X1,A		X:(R_X)-,X1	A,Y1	; A=K4=A+Y0*X1=input+0.3*in1, X1=out1, Y1=input
	MAC	-X0,X1,A	Y1,X:(R_X)+		; A=K5=A-X0*X1=K4-f*out1, in1=Y1=input
	ADD	X1,A					; A=out1=A+X1=K5+out1
	NOP
	MOVE	A,X:(R_X)+				; out1=A=out1
	
	MOVE	X:(R_X)+,X1				; X1=in2
	MAC	Y0,X1,A		X:(R_X)-,X1	A,Y1	; A=K6=A+Y0*X1=out1+0.3*in2, X1=out2, Y1=out1
	MAC	-X0,X1,A	Y1,X:(R_X)+		; A=K7=A-X0*X1=K6-f*out2, in2=Y1=out1
	ADD	X1,A					; A=out2=A+X1=K7+out2
	NOP
	MOVE	A,X:(R_X)+				; out2=A=out2

	MOVE	X:(R_X)+,X1				; X1=in3
	MAC	Y0,X1,A		X:(R_X)-,X1	A,Y1	; A=K8=A+Y0*X1=out2+0.3*in3, X1=out3, Y1=out2
	MAC	-X0,X1,A	Y1,X:(R_X)+		; A=K9=A-X0*X1=K8-f*out3, in3=Y1=out2
	ADD	X1,A					; A=out3=A+X1=K9+out3
	NOP
	MOVE	A,X:(R_X)+				; out3=A=out3

	MOVE	X:(R_X)+,X1				; X1=in4
	MAC	Y0,X1,A		X:(R_X)-,X1	A,Y1	; A=K10=A+Y0*X1=out3+0.3*in4, X1=out4, Y1=out3
	MAC	-X0,X1,A	Y1,X:(R_X)+		; A=K11=A-X0*X1=K10-f*out4, in3=Y1=out3
	ADD	X1,A					; A=out4=A+X1=K11+out4
	NOP
	MOVE	A,X:(R_X)-N_X				; out4=A=out4
	MOVE	A,Y:(R_OutR)+				; output=A=out4
	;----------------------------------------------------------------
	.ENDL
;===============================CODE=====================================

	undef	R_InL
	undef	R_OutL
	undef	R_InR
	undef	R_OutR
	undef	R_Control

	RTS