summaryrefslogtreecommitdiffstats
path: root/arm-wt-22k/lib_src/ARM-E_filter_gnu.s
blob: 871cd7d717c03810a629b935ea23127ca9b7278d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
@***********************************************************
@ Function:    WT_VoiceFilter
@ Processor:   ARM
@ Description:
@ Implements a 2-pole low-pass filter with resonanance
@
@ Usage: 
@	void WT_VoiceFilter(
@		S_FILTER CONTROL *pFilter,
@		S_WT_FRAME *pWTFrame);
@
@ Copyright 2005 Sonic Network, Inc.
@****************************************************************
@ Revision Control:
@   $Revision: 496 $
@   $Date: 2006-12-11 14:33:26 -0800 (Mon, 11 Dec 2006) $
@****************************************************************
@
@   where:
@	S_FILTER_CONTROL *pFilter
@	PASSED IN: r0
@
@	S_WT_FRAME *pWTFrame
@	PASSED IN: r1
@****************************************************************

	.include	"ARM_synth_constants_gnu.inc"

	.arm
	.text


	.global	WT_VoiceFilter
	

@ Register usage
@ --------------
pFilter	.req	r0
pWTFrame	.req	r1
pBuffer	.req	r2
numSamples	.req	r3

z1	.req	r4
z2	.req	r5
b1	.req	r6
b2	.req	r7
K	.req	r8

tmp0	.req	r1	@ reuse register
tmp1	.req	r9
tmp2	.req	r10


@SaveRegs	RLIST	{r4-r10, lr}
@RestoreRegs	RLIST	{r4-r10, pc}


	.func	WT_VoiceFilter
WT_VoiceFilter:

	STMFD	sp!, {r4-r10, lr}

@
@ Setup passed parameters in their destination registers
@----------------------------------------------------------------

	LDR		pBuffer, [pWTFrame, #m_pAudioBuffer]
	LDR		numSamples, [pWTFrame, #m_numSamples]

	@load state variables from pFilter structure
	LDRSH	z1, [pFilter, #m_z1]
	LDRSH	z2, [pFilter, #m_z2]

	@load coefficients from pWTFrame structure
	LDR		K, [pWTFrame, #m_k]
	LDR		b1, [pWTFrame, #m_b1]
	LDR		b2, [pWTFrame, #m_b2]
	
	RSB	b1, b1, #0						@ b1 = -b1
	RSB	b2, b2, #0						@ b2 = -b2
	MOV	b2, b2, ASR #1					@ b2 = b2 >> 1
	MOV	K, K, ASR #1					@ K = K >> 1

@
@ Start processing
@----------------------------------------------------------------

	LDRSH	tmp0, [pBuffer]					@ fetch sample

FilterLoop:
	SMULBB	tmp2, z1, b1					@ tmp2 = z1 * -b1
	SMLABB	tmp2, z2, b2, tmp2				@ tmp2 = (-b1 * z1) + (-b2 * z2)

	MOV		z2, z1							@ delay line

	SMLABB	tmp0, tmp0, K, tmp2				@ tmp1 = (K * x[n]) + (-b1 * z1) + (-b2 * z2)
	
	LDRSH	tmp1, [pBuffer, #NEXT_OUTPUT_PCM]	@ fetch next sample
	
	MOV		z1, tmp0, ASR #14				@ shift result to low word
	STRH	z1, [pBuffer], #NEXT_OUTPUT_PCM	@ write back to buffer

	SMULBB	tmp2, z1, b1					@ tmp2 = z1 * -b1
	
	SUBS	numSamples, numSamples, #2		@ unroll loop once

	SMLABB	tmp2, z2, b2, tmp2				@ tmp2 = (-b1 * z1) + (-b2 * z2)

	SMLABB	tmp1, tmp1, K, tmp2				@ tmp1 = (K * x[n]) + (-b1 * z1) + (-b2 * z2)

	MOV		z2, z1							@ delay line

	MOV		z1, tmp1, ASR #14				@ shift result to low word
	
	LDRGTSH	tmp0, [pBuffer, #NEXT_OUTPUT_PCM]	@ fetch next sample

	STRH	z1, [pBuffer], #NEXT_OUTPUT_PCM	@ write back to buffer

	BGT		FilterLoop
@ save z terms
@----------------------------------------------------------------

	STRH	z1, [pFilter, #m_z1]
	STRH	z2, [pFilter, #m_z2]

@ Return to calling function
@----------------------------------------------------------------

	LDMFD	sp!,{r4-r10, lr}
	BX		lr

	.endfunc
	.end