The Android Open Source Project | 7df3010 | 2009-03-03 19:30:38 -0800 | [diff] [blame] | 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 |
|
Dan Willemsen | cd67337 | 2016-09-21 15:32:16 -0700 | [diff] [blame] | 28 | #include "ARM_synth_constants_gnu.inc"
|
The Android Open Source Project | 7df3010 | 2009-03-03 19:30:38 -0800 | [diff] [blame] | 29 |
|
| 30 | .arm
|
| 31 | .text
|
| 32 |
|
| 33 | .global WT_Interpolate
|
| 34 |
|
| 35 |
|
| 36 | @ Register usage
|
| 37 | @ --------------
|
| 38 | pWTVoice .req r0
|
| 39 | pWTFrame .req r1
|
| 40 |
|
| 41 | numSamples .req r2
|
| 42 | phaseIncrement .req r3
|
| 43 | pOutputBuffer .req r4
|
| 44 |
|
| 45 | tmp0 .req r1 @reuse register
|
| 46 | tmp1 .req r5
|
| 47 | tmp2 .req r6
|
| 48 |
|
| 49 | pLoopEnd .req r7
|
| 50 | pLoopStart .req r8
|
| 51 |
|
| 52 | pPhaseAccum .req r9
|
| 53 | phaseFrac .req r10
|
| 54 | phaseFracMask .req r11
|
| 55 |
|
| 56 | @SaveRegs RLIST {r4-r11,lr}
|
| 57 | @RestoreRegs RLIST {r4-r11,pc}
|
| 58 |
|
| 59 | .func WT_Interpolate
|
| 60 | WT_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 |
|
| 80 | InterpolationLoop:
|
| 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 |
|