summaryrefslogtreecommitdiffstats
path: root/arm-wt-22k/lib_src/ARM-E_interpolate_loop_gnu.s
blob: 847a7f00ecf2e99e224bb8fe89ce02a187c25492 (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
@***********************************************************
@ Function:    WT_Interpolate
@ Processor:   ARM-E
@ Description: the main synthesis function when fetching 
@			   wavetable samples.
@              C-callable.
@
@ Usage: 
@	void WT_Interpolate(
@		S_WT_VOICE *pWTVoice,
@		S_WT_FRAME *pWTFrame);
@
@ Copyright Sonic Network Inc. 2004
@****************************************************************
@ Revision Control:
@   $Revision: 496 $
@   $Date: 2006-12-11 14:33:26 -0800 (Mon, 11 Dec 2006) $
@****************************************************************
@
@   where:
@	S_WT_VOICE *pWTVoice
@	PASSED IN: r0
@
@	S_WT_FRAME *pWTFrame;
@	PASSED IN: r1
@****************************************************************

	.include	"ARM_synth_constants_gnu.inc"

	.arm
	.text

	.global	WT_Interpolate


@ Register usage
@ --------------
pWTVoice	.req	r0
pWTFrame	.req	r1

numSamples	.req	r2
phaseIncrement	.req	r3
pOutputBuffer	.req	r4

tmp0	.req	r1	@reuse register
tmp1	.req	r5
tmp2	.req	r6

pLoopEnd	.req	r7
pLoopStart	.req	r8

pPhaseAccum	.req	r9
phaseFrac	.req	r10
phaseFracMask	.req	r11

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

	.func	WT_Interpolate
WT_Interpolate:

	STMFD	sp!,{r4-r11,lr}

@
@ Fetch parameters from structures
@----------------------------------------------------------------

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

	LDR		phaseIncrement, [pWTFrame, #m_phaseIncrement]
	LDR		pPhaseAccum, [pWTVoice, #m_pPhaseAccum]
	LDR		phaseFrac, [pWTVoice, #m_phaseFrac]
	LDR		phaseFracMask,=PHASE_FRAC_MASK

	LDR		pLoopStart, [pWTVoice, #m_pLoopStart]
	LDR		pLoopEnd, [pWTVoice, #m_pLoopEnd]
	ADD		pLoopEnd, pLoopEnd, #1					@ need loop end to equal last sample + 1

InterpolationLoop:
	SUBS	tmp0, pPhaseAccum, pLoopEnd		@ check for loop end
	ADDGE	pPhaseAccum, pLoopStart, tmp0	@ loop back to start

	.ifdef	SAMPLES_8_BIT
	LDRSB	tmp0, [pPhaseAccum]				@ tmp0 = x0
	LDRSB	tmp1, [pPhaseAccum, #1]			@ tmp1 = x1
	.else
	LDRSH	tmp0, [pPhaseAccum]				@ tmp0 = x0
	LDRSH	tmp1, [pPhaseAccum, #2]			@ tmp1 = x1
	.endif

	ADD		tmp2, phaseIncrement, phaseFrac	@ increment pointer here to avoid pipeline stall

	SUB		tmp1, tmp1, tmp0						@ tmp1 = x1 - x0
	SMULBB	tmp1, phaseFrac, tmp1			@ tmp1 = phaseFrac * tmp2

@ This section performs a gain adjustment of -12dB for 16-bit samples
@ or +36dB for 8-bit samples. For a high quality synthesizer, the output
@ can be set to full scale, however if the filter is used, it can overflow
@ with certain coefficients and signal sources. In this case, either a
@ saturation operation should take in the filter before scaling back to
@ 16 bits or the signal path should be increased to 18 bits or more.

	.ifdef	SAMPLES_8_BIT
	MOV		tmp0, tmp0, LSL #6							@ boost 8-bit signal by 36dB
	.else
	MOV		tmp0, tmp0, ASR #2							@ reduce 16-bit signal by 12dB
	.endif															
	
	ADD		tmp1, tmp0, tmp1, ASR #(NUM_EG1_FRAC_BITS-6)	@ tmp1 = tmp0 + (tmp1 >> (15-6))
															@	   = x0 + f * (x1 - x0) == interpolated result
	
	STRH	tmp1, [pOutputBuffer], #NEXT_OUTPUT_PCM	@ *pOutputBuffer++ = interpolated result
	
@ carry overflow from fraction to integer portion
	ADD	pPhaseAccum, pPhaseAccum, tmp2, LSR #(NUM_PHASE_FRAC_BITS - NEXT_INPUT_PCM_SHIFT)
	AND	phaseFrac, tmp2, phaseFracMask		@ nphaseFrac = frac part

	SUBS	numSamples, numSamples, #1
	BGT		InterpolationLoop
	
@ update and store phase
	STR		pPhaseAccum, [pWTVoice, #m_pPhaseAccum]
	STR		phaseFrac, [pWTVoice, #m_phaseFrac]

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

	.endfunc
	.end