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 59WT_Interpolate: 60 61 STMFD sp!,{r4-r11,lr} 62 63@ 64@ Fetch parameters from structures 65@---------------------------------------------------------------- 66 67 LDR pOutputBuffer, [pWTFrame, #m_pAudioBuffer] 68 LDR numSamples, [pWTFrame, #m_numSamples] 69 70 LDR phaseIncrement, [pWTFrame, #m_phaseIncrement] 71 LDR pPhaseAccum, [pWTVoice, #m_pPhaseAccum] 72 LDR phaseFrac, [pWTVoice, #m_phaseFrac] 73 LDR phaseFracMask,=PHASE_FRAC_MASK 74 75 LDR pLoopStart, [pWTVoice, #m_pLoopStart] 76 LDR pLoopEnd, [pWTVoice, #m_pLoopEnd] 77 ADD pLoopEnd, pLoopEnd, #1 @ need loop end to equal last sample + 1 78 79InterpolationLoop: 80 SUBS tmp0, pPhaseAccum, pLoopEnd @ check for loop end 81 ADDGE pPhaseAccum, pLoopStart, tmp0 @ loop back to start 82 83 #ifdef SAMPLES_8_BIT 84 LDRSB tmp0, [pPhaseAccum] @ tmp0 = x0 85 LDRSB tmp1, [pPhaseAccum, #1] @ tmp1 = x1 86 #elif SAMPLES_16_BIT 87 LDRSH tmp0, [pPhaseAccum] @ tmp0 = x0 88 LDRSH tmp1, [pPhaseAccum, #2] @ tmp1 = x1 89 #else 90 #error Must define one of SAMPLES_8_BIT or SAMPLES_16_BIT. 91 #endif 92 93 ADD tmp2, phaseIncrement, phaseFrac @ increment pointer here to avoid pipeline stall 94 95 SUB tmp1, tmp1, tmp0 @ tmp1 = x1 - x0 96 SMULBB tmp1, phaseFrac, tmp1 @ tmp1 = phaseFrac * tmp2 97 98@ This section performs a gain adjustment of -12dB for 16-bit samples 99@ or +36dB for 8-bit samples. For a high quality synthesizer, the output 100@ can be set to full scale, however if the filter is used, it can overflow 101@ with certain coefficients and signal sources. In this case, either a 102@ saturation operation should take in the filter before scaling back to 103@ 16 bits or the signal path should be increased to 18 bits or more. 104 105 #ifdef SAMPLES_8_BIT 106 MOV tmp0, tmp0, LSL #6 @ boost 8-bit signal by 36dB 107 #elif SAMPLES_16_BIT 108 MOV tmp0, tmp0, ASR #2 @ reduce 16-bit signal by 12dB 109 #else 110 #error Must define one of SAMPLES_8_BIT or SAMPLES_16_BIT. 111 #endif 112 113 ADD tmp1, tmp0, tmp1, ASR #(NUM_EG1_FRAC_BITS-6) @ tmp1 = tmp0 + (tmp1 >> (15-6)) 114 @ = x0 + f * (x1 - x0) == interpolated result 115 116 STRH tmp1, [pOutputBuffer], #NEXT_OUTPUT_PCM @ *pOutputBuffer++ = interpolated result 117 118@ carry overflow from fraction to integer portion 119 ADD pPhaseAccum, pPhaseAccum, tmp2, LSR #(NUM_PHASE_FRAC_BITS - NEXT_INPUT_PCM_SHIFT) 120 AND phaseFrac, tmp2, phaseFracMask @ nphaseFrac = frac part 121 122 SUBS numSamples, numSamples, #1 123 BGT InterpolationLoop 124 125@ update and store phase 126 STR pPhaseAccum, [pWTVoice, #m_pPhaseAccum] 127 STR phaseFrac, [pWTVoice, #m_phaseFrac] 128 129 LDMFD sp!,{r4-r11,lr} 130 BX lr 131 132 .end 133 134