1@***********************************************************
2@ Function:    WT_Interpolate
3@ Processor:   ARM-E
4@ Description: the main synthesis function when fetching
5@			   wavetable samples.
6@              C-callable.
7@
8@ Usage:
9@	void WT_Interpolate(
10@		S_WT_VOICE *pWTVoice,
11@		S_WT_FRAME *pWTFrame);
12@
13@ Copyright Sonic Network Inc. 2004
14@****************************************************************
15@ Revision Control:
16@   $Revision: 496 $
17@   $Date: 2006-12-11 14:33:26 -0800 (Mon, 11 Dec 2006) $
18@****************************************************************
19@
20@   where:
21@	S_WT_VOICE *pWTVoice
22@	PASSED IN: r0
23@
24@	S_WT_FRAME *pWTFrame;
25@	PASSED IN: r1
26@****************************************************************
27
28	#include	"ARM_synth_constants_gnu.inc"
29
30	.arm
31	.text
32
33	.global	WT_Interpolate
34
35
36@ Register usage
37@ --------------
38pWTVoice	.req	r0
39pWTFrame	.req	r1
40
41numSamples	.req	r2
42phaseIncrement	.req	r3
43pOutputBuffer	.req	r4
44
45tmp0	.req	r1	@reuse register
46tmp1	.req	r5
47tmp2	.req	r6
48
49pLoopEnd	.req	r7
50pLoopStart	.req	r8
51
52pPhaseAccum	.req	r9
53phaseFrac	.req	r10
54phaseFracMask	.req	r11
55
56@SaveRegs	RLIST	{r4-r11,lr}
57@RestoreRegs	RLIST	{r4-r11,pc}
58
59	.func	WT_Interpolate
60WT_Interpolate:
61
62	STMFD	sp!,{r4-r11,lr}
63
64@
65@ Fetch parameters from structures
66@----------------------------------------------------------------
67
68	LDR		pOutputBuffer, [pWTFrame, #m_pAudioBuffer]
69	LDR		numSamples, [pWTFrame, #m_numSamples]
70
71	LDR		phaseIncrement, [pWTFrame, #m_phaseIncrement]
72	LDR		pPhaseAccum, [pWTVoice, #m_pPhaseAccum]
73	LDR		phaseFrac, [pWTVoice, #m_phaseFrac]
74	LDR		phaseFracMask,=PHASE_FRAC_MASK
75
76	LDR		pLoopStart, [pWTVoice, #m_pLoopStart]
77	LDR		pLoopEnd, [pWTVoice, #m_pLoopEnd]
78	ADD		pLoopEnd, pLoopEnd, #1					@ need loop end to equal last sample + 1
79
80InterpolationLoop:
81	SUBS	tmp0, pPhaseAccum, pLoopEnd		@ check for loop end
82	ADDGE	pPhaseAccum, pLoopStart, tmp0	@ loop back to start
83
84	.ifdef	SAMPLES_8_BIT
85	LDRSB	tmp0, [pPhaseAccum]				@ tmp0 = x0
86	LDRSB	tmp1, [pPhaseAccum, #1]			@ tmp1 = x1
87	.else
88	LDRSH	tmp0, [pPhaseAccum]				@ tmp0 = x0
89	LDRSH	tmp1, [pPhaseAccum, #2]			@ tmp1 = x1
90	.endif
91
92	ADD		tmp2, phaseIncrement, phaseFrac	@ increment pointer here to avoid pipeline stall
93
94	SUB		tmp1, tmp1, tmp0						@ tmp1 = x1 - x0
95	SMULBB	tmp1, phaseFrac, tmp1			@ tmp1 = phaseFrac * tmp2
96
97@ This section performs a gain adjustment of -12dB for 16-bit samples
98@ or +36dB for 8-bit samples. For a high quality synthesizer, the output
99@ can be set to full scale, however if the filter is used, it can overflow
100@ with certain coefficients and signal sources. In this case, either a
101@ saturation operation should take in the filter before scaling back to
102@ 16 bits or the signal path should be increased to 18 bits or more.
103
104	.ifdef	SAMPLES_8_BIT
105	MOV		tmp0, tmp0, LSL #6							@ boost 8-bit signal by 36dB
106	.else
107	MOV		tmp0, tmp0, ASR #2							@ reduce 16-bit signal by 12dB
108	.endif
109
110	ADD		tmp1, tmp0, tmp1, ASR #(NUM_EG1_FRAC_BITS-6)	@ tmp1 = tmp0 + (tmp1 >> (15-6))
111															@	   = x0 + f * (x1 - x0) == interpolated result
112
113	STRH	tmp1, [pOutputBuffer], #NEXT_OUTPUT_PCM	@ *pOutputBuffer++ = interpolated result
114
115@ carry overflow from fraction to integer portion
116	ADD	pPhaseAccum, pPhaseAccum, tmp2, LSR #(NUM_PHASE_FRAC_BITS - NEXT_INPUT_PCM_SHIFT)
117	AND	phaseFrac, tmp2, phaseFracMask		@ nphaseFrac = frac part
118
119	SUBS	numSamples, numSamples, #1
120	BGT		InterpolationLoop
121
122@ update and store phase
123	STR		pPhaseAccum, [pWTVoice, #m_pPhaseAccum]
124	STR		phaseFrac, [pWTVoice, #m_phaseFrac]
125
126	LDMFD	sp!,{r4-r11,lr}
127	BX		lr
128
129	.endfunc
130	.end
131
132