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 @ -------------- 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 132