summaryrefslogtreecommitdiffstats
path: root/arm-hybrid-22k/lib_src/ARM-E_interpolate_noloop_gnu.s
blob: 6343762c5c5fab7aae133831d47a1911f7023d04 (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
@***********************************************************
@ Function:    WT_InterpolateNoLoop
@ Processor:   ARM-E
@ Description: the main synthesis function when fetching 
@			   wavetable samples.
@              C-callable.
@
@ Usage: 
@	void WT_InterpolateNoLoop(
@		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_InterpolateNoLoop
	

@ Register usage
@ --------------
pWTVoice	.req	r0
pWTFrame	.req	r1
pOutputBuffer	.req	r2
numSamples	.req	r3

phaseIncrement	.req	r4
pPhaseAccum	.req	r5
phaseFrac	.req	r6
phaseFracMask	.req	r7

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


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

	.func	WT_InterpolateNoLoop
WT_InterpolateNoLoop:

	STMFD	sp!, {r4-r9,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

InterpolationLoop:

	.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

@ Clean up and store any changes that were caused during the loop
@----------------------------------------------------------------

	@ update and store phase
	STR		pPhaseAccum, [pWTVoice, #m_pPhaseAccum]
	STR		phaseFrac, [pWTVoice, #m_phaseFrac]

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

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

	.endfunc
	.end