summaryrefslogtreecommitdiffstats
path: root/arm-wt-22k/lib_src
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-04 03:30:38 (GMT)
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-04 03:30:38 (GMT)
commit7df30109963092559d3760c0661a020f9daf1030 (patch)
tree5780537d7996618fb7e1754bbd27361f3ccb9286 /arm-wt-22k/lib_src
parent1b52a76815aa068a3477bfdfaf58718d41d7f9b4 (diff)
downloadandroid_external_sonivox-7df30109963092559d3760c0661a020f9daf1030.zip
android_external_sonivox-7df30109963092559d3760c0661a020f9daf1030.tar.gz
android_external_sonivox-7df30109963092559d3760c0661a020f9daf1030.tar.bz2
auto import from //depot/cupcake/@135843
Diffstat (limited to 'arm-wt-22k/lib_src')
-rw-r--r--arm-wt-22k/lib_src/ARM-E_filter_gnu.s134
-rw-r--r--arm-wt-22k/lib_src/ARM-E_interpolate_loop_gnu.s131
-rw-r--r--arm-wt-22k/lib_src/ARM-E_interpolate_noloop_gnu.s130
-rw-r--r--arm-wt-22k/lib_src/ARM-E_mastergain_gnu.s109
-rw-r--r--arm-wt-22k/lib_src/ARM-E_voice_gain_gnu.s166
-rw-r--r--arm-wt-22k/lib_src/ARM_synth_constants_gnu.inc153
-rw-r--r--arm-wt-22k/lib_src/arm-wt-22k_lib.mak25
-rw-r--r--arm-wt-22k/lib_src/dls.h268
-rw-r--r--arm-wt-22k/lib_src/dls2.h122
-rw-r--r--arm-wt-22k/lib_src/eas_audioconst.h97
-rw-r--r--arm-wt-22k/lib_src/eas_chorus.c604
-rw-r--r--arm-wt-22k/lib_src/eas_chorusdata.c34
-rw-r--r--arm-wt-22k/lib_src/eas_chorusdata.h160
-rw-r--r--arm-wt-22k/lib_src/eas_ctype.h41
-rw-r--r--arm-wt-22k/lib_src/eas_data.c37
-rw-r--r--arm-wt-22k/lib_src/eas_data.h133
-rw-r--r--arm-wt-22k/lib_src/eas_dlssynth.c578
-rw-r--r--arm-wt-22k/lib_src/eas_dlssynth.h41
-rw-r--r--arm-wt-22k/lib_src/eas_effects.h61
-rw-r--r--arm-wt-22k/lib_src/eas_flog.c96
-rw-r--r--arm-wt-22k/lib_src/eas_ima_tables.c54
-rw-r--r--arm-wt-22k/lib_src/eas_imaadpcm.c368
-rw-r--r--arm-wt-22k/lib_src/eas_imelody.c1742
-rw-r--r--arm-wt-22k/lib_src/eas_imelodydata.c43
-rw-r--r--arm-wt-22k/lib_src/eas_imelodydata.h73
-rw-r--r--arm-wt-22k/lib_src/eas_math.c168
-rw-r--r--arm-wt-22k/lib_src/eas_math.h412
-rw-r--r--arm-wt-22k/lib_src/eas_mdls.c2668
-rw-r--r--arm-wt-22k/lib_src/eas_mdls.h295
-rw-r--r--arm-wt-22k/lib_src/eas_midi.c569
-rw-r--r--arm-wt-22k/lib_src/eas_midi.h71
-rw-r--r--arm-wt-22k/lib_src/eas_midictrl.h64
-rw-r--r--arm-wt-22k/lib_src/eas_mididata.c34
-rw-r--r--arm-wt-22k/lib_src/eas_miditypes.h138
-rw-r--r--arm-wt-22k/lib_src/eas_mixbuf.c36
-rw-r--r--arm-wt-22k/lib_src/eas_mixer.c464
-rw-r--r--arm-wt-22k/lib_src/eas_mixer.h137
-rw-r--r--arm-wt-22k/lib_src/eas_ota.c1077
-rw-r--r--arm-wt-22k/lib_src/eas_otadata.c41
-rw-r--r--arm-wt-22k/lib_src/eas_otadata.h81
-rw-r--r--arm-wt-22k/lib_src/eas_pan.c98
-rw-r--r--arm-wt-22k/lib_src/eas_pan.h66
-rw-r--r--arm-wt-22k/lib_src/eas_parser.h98
-rw-r--r--arm-wt-22k/lib_src/eas_pcm.c1482
-rw-r--r--arm-wt-22k/lib_src/eas_pcm.h359
-rw-r--r--arm-wt-22k/lib_src/eas_pcmdata.c35
-rw-r--r--arm-wt-22k/lib_src/eas_pcmdata.h157
-rw-r--r--arm-wt-22k/lib_src/eas_public.c2601
-rw-r--r--arm-wt-22k/lib_src/eas_reverb.c1154
-rw-r--r--arm-wt-22k/lib_src/eas_reverbdata.c34
-rw-r--r--arm-wt-22k/lib_src/eas_reverbdata.h486
-rw-r--r--arm-wt-22k/lib_src/eas_rtttl.c1197
-rw-r--r--arm-wt-22k/lib_src/eas_rtttldata.c41
-rw-r--r--arm-wt-22k/lib_src/eas_rtttldata.h70
-rw-r--r--arm-wt-22k/lib_src/eas_smf.c1207
-rw-r--r--arm-wt-22k/lib_src/eas_smf.h49
-rw-r--r--arm-wt-22k/lib_src/eas_smfdata.c66
-rw-r--r--arm-wt-22k/lib_src/eas_smfdata.h66
-rw-r--r--arm-wt-22k/lib_src/eas_sndlib.h406
-rw-r--r--arm-wt-22k/lib_src/eas_synth.h395
-rw-r--r--arm-wt-22k/lib_src/eas_synth_protos.h60
-rw-r--r--arm-wt-22k/lib_src/eas_synthcfg.h70
-rw-r--r--arm-wt-22k/lib_src/eas_tcdata.c43
-rw-r--r--arm-wt-22k/lib_src/eas_tcdata.h65
-rw-r--r--arm-wt-22k/lib_src/eas_tonecontrol.c941
-rw-r--r--arm-wt-22k/lib_src/eas_vm_protos.h1086
-rw-r--r--arm-wt-22k/lib_src/eas_voicemgt.c3971
-rw-r--r--arm-wt-22k/lib_src/eas_wavefile.c867
-rw-r--r--arm-wt-22k/lib_src/eas_wavefile.h63
-rw-r--r--arm-wt-22k/lib_src/eas_wavefiledata.c33
-rw-r--r--arm-wt-22k/lib_src/eas_wt_IPC_frame.h82
-rw-r--r--arm-wt-22k/lib_src/eas_wtengine.c661
-rw-r--r--arm-wt-22k/lib_src/eas_wtengine.h171
-rw-r--r--arm-wt-22k/lib_src/eas_wtsynth.c1257
-rw-r--r--arm-wt-22k/lib_src/eas_wtsynth.h66
-rw-r--r--arm-wt-22k/lib_src/eas_xmf.c850
-rw-r--r--arm-wt-22k/lib_src/eas_xmf.h60
-rw-r--r--arm-wt-22k/lib_src/eas_xmfdata.c44
-rw-r--r--arm-wt-22k/lib_src/eas_xmfdata.h55
-rw-r--r--arm-wt-22k/lib_src/jet.c1125
-rw-r--r--arm-wt-22k/lib_src/jet_data.h183
-rw-r--r--arm-wt-22k/lib_src/wt_22khz.c11423
82 files changed, 44898 insertions, 0 deletions
diff --git a/arm-wt-22k/lib_src/ARM-E_filter_gnu.s b/arm-wt-22k/lib_src/ARM-E_filter_gnu.s
new file mode 100644
index 0000000..871cd7d
--- /dev/null
+++ b/arm-wt-22k/lib_src/ARM-E_filter_gnu.s
@@ -0,0 +1,134 @@
+@***********************************************************
+@ Function: WT_VoiceFilter
+@ Processor: ARM
+@ Description:
+@ Implements a 2-pole low-pass filter with resonanance
+@
+@ Usage:
+@ void WT_VoiceFilter(
+@ S_FILTER CONTROL *pFilter,
+@ S_WT_FRAME *pWTFrame);
+@
+@ Copyright 2005 Sonic Network, Inc.
+@****************************************************************
+@ Revision Control:
+@ $Revision: 496 $
+@ $Date: 2006-12-11 14:33:26 -0800 (Mon, 11 Dec 2006) $
+@****************************************************************
+@
+@ where:
+@ S_FILTER_CONTROL *pFilter
+@ PASSED IN: r0
+@
+@ S_WT_FRAME *pWTFrame
+@ PASSED IN: r1
+@****************************************************************
+
+ .include "ARM_synth_constants_gnu.inc"
+
+ .arm
+ .text
+
+
+ .global WT_VoiceFilter
+
+
+@ Register usage
+@ --------------
+pFilter .req r0
+pWTFrame .req r1
+pBuffer .req r2
+numSamples .req r3
+
+z1 .req r4
+z2 .req r5
+b1 .req r6
+b2 .req r7
+K .req r8
+
+tmp0 .req r1 @ reuse register
+tmp1 .req r9
+tmp2 .req r10
+
+
+@SaveRegs RLIST {r4-r10, lr}
+@RestoreRegs RLIST {r4-r10, pc}
+
+
+ .func WT_VoiceFilter
+WT_VoiceFilter:
+
+ STMFD sp!, {r4-r10, lr}
+
+@
+@ Setup passed parameters in their destination registers
+@----------------------------------------------------------------
+
+ LDR pBuffer, [pWTFrame, #m_pAudioBuffer]
+ LDR numSamples, [pWTFrame, #m_numSamples]
+
+ @load state variables from pFilter structure
+ LDRSH z1, [pFilter, #m_z1]
+ LDRSH z2, [pFilter, #m_z2]
+
+ @load coefficients from pWTFrame structure
+ LDR K, [pWTFrame, #m_k]
+ LDR b1, [pWTFrame, #m_b1]
+ LDR b2, [pWTFrame, #m_b2]
+
+ RSB b1, b1, #0 @ b1 = -b1
+ RSB b2, b2, #0 @ b2 = -b2
+ MOV b2, b2, ASR #1 @ b2 = b2 >> 1
+ MOV K, K, ASR #1 @ K = K >> 1
+
+@
+@ Start processing
+@----------------------------------------------------------------
+
+ LDRSH tmp0, [pBuffer] @ fetch sample
+
+FilterLoop:
+ SMULBB tmp2, z1, b1 @ tmp2 = z1 * -b1
+ SMLABB tmp2, z2, b2, tmp2 @ tmp2 = (-b1 * z1) + (-b2 * z2)
+
+ MOV z2, z1 @ delay line
+
+ SMLABB tmp0, tmp0, K, tmp2 @ tmp1 = (K * x[n]) + (-b1 * z1) + (-b2 * z2)
+
+ LDRSH tmp1, [pBuffer, #NEXT_OUTPUT_PCM] @ fetch next sample
+
+ MOV z1, tmp0, ASR #14 @ shift result to low word
+ STRH z1, [pBuffer], #NEXT_OUTPUT_PCM @ write back to buffer
+
+ SMULBB tmp2, z1, b1 @ tmp2 = z1 * -b1
+
+ SUBS numSamples, numSamples, #2 @ unroll loop once
+
+ SMLABB tmp2, z2, b2, tmp2 @ tmp2 = (-b1 * z1) + (-b2 * z2)
+
+ SMLABB tmp1, tmp1, K, tmp2 @ tmp1 = (K * x[n]) + (-b1 * z1) + (-b2 * z2)
+
+ MOV z2, z1 @ delay line
+
+ MOV z1, tmp1, ASR #14 @ shift result to low word
+
+ LDRGTSH tmp0, [pBuffer, #NEXT_OUTPUT_PCM] @ fetch next sample
+
+ STRH z1, [pBuffer], #NEXT_OUTPUT_PCM @ write back to buffer
+
+ BGT FilterLoop
+@ save z terms
+@----------------------------------------------------------------
+
+ STRH z1, [pFilter, #m_z1]
+ STRH z2, [pFilter, #m_z2]
+
+@ Return to calling function
+@----------------------------------------------------------------
+
+ LDMFD sp!,{r4-r10, lr}
+ BX lr
+
+ .endfunc
+ .end
+
diff --git a/arm-wt-22k/lib_src/ARM-E_interpolate_loop_gnu.s b/arm-wt-22k/lib_src/ARM-E_interpolate_loop_gnu.s
new file mode 100644
index 0000000..847a7f0
--- /dev/null
+++ b/arm-wt-22k/lib_src/ARM-E_interpolate_loop_gnu.s
@@ -0,0 +1,131 @@
+@***********************************************************
+@ Function: WT_Interpolate
+@ Processor: ARM-E
+@ Description: the main synthesis function when fetching
+@ wavetable samples.
+@ C-callable.
+@
+@ Usage:
+@ void WT_Interpolate(
+@ 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_Interpolate
+
+
+@ Register usage
+@ --------------
+pWTVoice .req r0
+pWTFrame .req r1
+
+numSamples .req r2
+phaseIncrement .req r3
+pOutputBuffer .req r4
+
+tmp0 .req r1 @reuse register
+tmp1 .req r5
+tmp2 .req r6
+
+pLoopEnd .req r7
+pLoopStart .req r8
+
+pPhaseAccum .req r9
+phaseFrac .req r10
+phaseFracMask .req r11
+
+@SaveRegs RLIST {r4-r11,lr}
+@RestoreRegs RLIST {r4-r11,pc}
+
+ .func WT_Interpolate
+WT_Interpolate:
+
+ STMFD sp!,{r4-r11,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
+
+ LDR pLoopStart, [pWTVoice, #m_pLoopStart]
+ LDR pLoopEnd, [pWTVoice, #m_pLoopEnd]
+ ADD pLoopEnd, pLoopEnd, #1 @ need loop end to equal last sample + 1
+
+InterpolationLoop:
+ SUBS tmp0, pPhaseAccum, pLoopEnd @ check for loop end
+ ADDGE pPhaseAccum, pLoopStart, tmp0 @ loop back to start
+
+ .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
+
+@ update and store phase
+ STR pPhaseAccum, [pWTVoice, #m_pPhaseAccum]
+ STR phaseFrac, [pWTVoice, #m_phaseFrac]
+
+ LDMFD sp!,{r4-r11,lr}
+ BX lr
+
+ .endfunc
+ .end
+
diff --git a/arm-wt-22k/lib_src/ARM-E_interpolate_noloop_gnu.s b/arm-wt-22k/lib_src/ARM-E_interpolate_noloop_gnu.s
new file mode 100644
index 0000000..6343762
--- /dev/null
+++ b/arm-wt-22k/lib_src/ARM-E_interpolate_noloop_gnu.s
@@ -0,0 +1,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
+
diff --git a/arm-wt-22k/lib_src/ARM-E_mastergain_gnu.s b/arm-wt-22k/lib_src/ARM-E_mastergain_gnu.s
new file mode 100644
index 0000000..b4e905b
--- /dev/null
+++ b/arm-wt-22k/lib_src/ARM-E_mastergain_gnu.s
@@ -0,0 +1,109 @@
+@***********************************************************
+@ Function: SynthMasterGain
+@ Processor: ARM-E
+@ Description: Copies 32-bit synth output to 16-bit buffer
+@ with saturated gain control
+@ C-callable.
+@
+@ Usage:
+@ SynthMasterGain(
+@ pInputBuffer
+@ pOutputBuffer,
+@ nGain,
+@ nNumLoopSamples
+@ );
+@
+@ Copyright Sonic Network Inc. 2004
+@****************************************************************
+@ Revision Control:
+@ $Revision: 496 $
+@ $Date: 2006-12-11 14:33:26 -0800 (Mon, 11 Dec 2006) $
+@****************************************************************
+@
+@ where:
+@ long *pInputBuffer
+@ PASSED IN: r0
+@
+@ EAS_PCM *pOutputBuffer
+@ PASSED IN: r1
+@
+@ short nGain
+@ PASSED IN: r2
+@
+@ EAS_U16 nNumLoopSamples
+@ PASSED IN: r3
+@
+@****************************************************************
+
+ .include "ARM_synth_constants_gnu.inc"
+
+ .arm
+ .text
+
+ .func SynthMasterGain
+SynthMasterGain:
+
+ .global SynthMasterGain @ allow other files to use this function
+
+
+
+
+
+@ Stack frame
+@ -----------
+ .equ RET_ADDR_SZ, 0 @return address
+ .equ REG_SAVE_SZ, 0 @save-on-entry registers saved
+ .equ FRAME_SZ, (8) @local variables
+ .equ ARG_BLK_SZ, 0 @argument block
+
+ .equ PARAM_OFFSET, (ARG_BLK_SZ + FRAME_SZ + REG_SAVE_SZ + RET_ADDR_SZ)
+
+@ Register usage
+@ --------------
+pnInputBuffer .req r0
+pnOutputBuffer .req r1
+nGain .req r2
+nNumLoopSamples .req r3
+
+ STMFD sp!,{r4-r6,r14} @Save any save-on-entry registers that are used
+
+ LDR r6, =0x7fff @constant for saturation tests
+
+loop:
+ LDR r4, [pnInputBuffer], #4 @fetch 1st output sample
+
+ LDR r5, [pnInputBuffer], #4 @fetch 2nd output sample
+
+ SMULWB r4, r4, nGain @output = gain * input
+
+ CMP r4, r6 @check for positive saturation
+ MOVGT r4, r6 @saturate
+ CMN r4, r6 @check for negative saturation
+ MVNLT r4, r6 @saturate
+
+ SMULWB r5, r5, nGain @output = gain * input
+
+ STRH r4, [pnOutputBuffer], #NEXT_OUTPUT_PCM @save 1st output sample
+
+ CMP r5, r6 @check for positive saturation
+ MOVGT r5, r6 @saturate
+ CMN r5, r6 @check for negative saturation
+ MVNLT r5, r6 @saturate
+ STRH r5, [pnOutputBuffer], #NEXT_OUTPUT_PCM @save 2nd output sample
+
+ SUBS nNumLoopSamples, nNumLoopSamples, #2
+ BGT loop
+
+@
+@ Return to calling function
+@----------------------------------------------------------------
+
+ LDMFD sp!,{r4-r6, lr} @ return to calling function
+ BX lr
+
+@*****************************************************************************
+
+ .endfunc @ end of function/procedure
+
+ .end @ end of assembly code
+
diff --git a/arm-wt-22k/lib_src/ARM-E_voice_gain_gnu.s b/arm-wt-22k/lib_src/ARM-E_voice_gain_gnu.s
new file mode 100644
index 0000000..4517a3d
--- /dev/null
+++ b/arm-wt-22k/lib_src/ARM-E_voice_gain_gnu.s
@@ -0,0 +1,166 @@
+@***********************************************************
+@ Function: WT_VoiceGain
+@ Processor: ARM-E
+@ Description: the main synthesis function when fetching
+@ wavetable samples.
+@ C-callable.
+@
+@ Usage:
+@ Usage:
+@ WT_VoiceGain(
+@ S_WT_VOICE *pWTVoice,
+@ S_WT_FRAME *pWTFrame);
+@
+@ Copyright 2004, 2005 Sonic Network, Inc.
+@****************************************************************
+@ Revision Control:
+@ $Revision: 814 $
+@ $Date: 2007-08-02 10:34:53 -0700 (Thu, 02 Aug 2007) $
+@****************************************************************
+@
+@ where:
+@ S_WT_VOICE *psVoice
+@ PASSED IN: r0
+@
+@ S_WT_FRAME *pWTFrame
+@ PASSED IN: r1
+@****************************************************************
+
+
+
+ .include "ARM_synth_constants_gnu.inc"
+
+ .arm
+ .text
+
+ .global WT_VoiceGain
+
+@ Register usage
+@ --------------
+pWTVoice .req r0
+pWTFrame .req r1
+pInputBuffer .req r2
+pMixBuffer .req r3
+
+tmp0 .req r4
+tmp1 .req r5
+tmp2 .req r1 @ reuse register
+tmp3 .req r6
+
+numSamples .req r9
+
+ .if STEREO_OUTPUT
+gainIncLeft .req r7
+gainIncRight .req r8
+gainLeft .req r10
+gainRight .req r11
+ .else
+gainIncrement .req r7
+gain .req r8
+ .endif
+
+
+@ register context for local variables
+@SaveRegs RLIST {r4-r11,lr}
+@RestoreRegs RLIST {r4-r11,pc}
+
+ .func WT_VoiceGain
+WT_VoiceGain:
+
+ STMFD sp!, {r4-r11,lr}
+
+ LDR pInputBuffer, [pWTFrame, #m_pAudioBuffer]
+ LDR pMixBuffer, [pWTFrame, #m_pMixBuffer]
+ LDR numSamples, [pWTFrame, #m_numSamples]
+
+@----------------------------------------------------------------
+@ Stereo version
+@----------------------------------------------------------------
+@ NOTE: instructions are reordered to reduce the effect of latency
+@ due to storage and computational dependencies.
+@----------------------------------------------------------------
+
+ .if STEREO_OUTPUT
+
+ LDR tmp0, [pWTFrame, #m_prevGain]
+ LDR tmp1, [pWTFrame, #m_gainTarget]
+
+ LDRSH gainLeft, [pWTVoice, #m_gainLeft]
+ LDRSH gainRight, [pWTVoice, #m_gainRight]
+
+ MOV gainIncLeft, gainLeft
+ SMULBB gainLeft, tmp0, gainLeft
+
+ SMULBB gainIncLeft, tmp1, gainIncLeft
+ SUB gainIncLeft, gainIncLeft, gainLeft
+ MOV gainLeft, gainLeft, ASR #(NUM_MIXER_GUARD_BITS - 2)
+ MOV gainIncLeft, gainIncLeft, ASR #(SYNTH_UPDATE_PERIOD_IN_BITS + NUM_MIXER_GUARD_BITS - 2)
+
+ MOV gainIncRight, gainRight
+ SMULBB gainRight, tmp0, gainRight
+
+ SMULBB gainIncRight, tmp1, gainIncRight
+ SUB gainIncRight, gainIncRight, gainRight
+ MOV gainRight, gainRight, ASR #(NUM_MIXER_GUARD_BITS - 2)
+ MOV gainIncRight, gainIncRight, ASR #(SYNTH_UPDATE_PERIOD_IN_BITS + NUM_MIXER_GUARD_BITS - 2)
+
+ LDRSH tmp0, [pInputBuffer], #2
+
+StereoGainLoop:
+ LDR tmp1, [pMixBuffer]
+
+ ADD gainLeft, gainLeft, gainIncLeft
+
+ SMLAWB tmp1, gainLeft, tmp0, tmp1
+
+ LDR tmp2, [pMixBuffer, #4]
+
+ ADD gainRight, gainRight, gainIncRight
+
+ STR tmp1, [pMixBuffer], #4
+
+ SMLAWB tmp2, gainRight, tmp0, tmp2
+
+ SUBS numSamples, numSamples, #1
+
+ LDRGTSH tmp0, [pInputBuffer], #2
+
+ STR tmp2, [pMixBuffer], #4
+
+ BGT StereoGainLoop
+
+@----------------------------------------------------------------
+@ Mono version
+@----------------------------------------------------------------
+ .else
+
+ LDR gain, [pWTFrame, #m_prevGain]
+ MOV gain, gain, LSL #(NUM_MIXER_GUARD_BITS + 4)
+ LDR gainIncrement, [pWTFrame, #m_gainTarget]
+ MOV gainIncrement, gainIncrement, LSL #(NUM_MIXER_GUARD_BITS + 4)
+ SUB gainIncrement, gainIncrement, gain
+ MOV gainIncrement, gainIncrement, ASR #SYNTH_UPDATE_PERIOD_IN_BITS
+
+MonoGainLoop:
+
+ LDRSH tmp0, [pInputBuffer], #NEXT_OUTPUT_PCM @ fetch voice output
+
+ LDR tmp1, [pMixBuffer] @ get left channel output sample
+ ADD gain, gain, gainIncrement @ gain step to eliminate zipper noise
+ SMULWB tmp0, gain, tmp0 @ sample * local gain
+
+ MOV tmp0, tmp0, ASR #1 @ add 6dB headroom
+ ADD tmp1, tmp0, tmp1
+ STR tmp1, [pMixBuffer], #4 @ save and bump pointer
+
+ SUBS numSamples, numSamples, #1
+ BGT MonoGainLoop
+
+ .endif @end Mono version
+
+ LDMFD sp!,{r4-r11,lr}
+ BX lr
+
+ .endfunc
+ .end
+
diff --git a/arm-wt-22k/lib_src/ARM_synth_constants_gnu.inc b/arm-wt-22k/lib_src/ARM_synth_constants_gnu.inc
new file mode 100644
index 0000000..b4cd29a
--- /dev/null
+++ b/arm-wt-22k/lib_src/ARM_synth_constants_gnu.inc
@@ -0,0 +1,153 @@
+@***********************************************************
+@ File: ARM_synth_constants.inc
+@ Processor: ARM
+@ Description: Contains constants and defines, most of which
+@ are mirrored in synth.h
+@
+@ Copyright Sonic Network Inc. 2004
+@****************************************************************
+@ Revision Control:
+@ $Revision: 741 $
+@ $Date: 2007-06-22 16:39:21 -0700 (Fri, 22 Jun 2007) $
+@****************************************************************
+
+
+ .ifdef SAMPLE_RATE_8000
+ .equ SYNTH_UPDATE_PERIOD_IN_BITS, 5
+ .equ BUFFER_SIZE_IN_MONO_SAMPLES, 32
+ .endif
+
+ .ifdef SAMPLE_RATE_16000
+ .equ SYNTH_UPDATE_PERIOD_IN_BITS, 6
+ .equ BUFFER_SIZE_IN_MONO_SAMPLES, 64
+ .endif
+
+ .ifdef SAMPLE_RATE_20000
+ .equ SYNTH_UPDATE_PERIOD_IN_BITS, 7
+ .equ BUFFER_SIZE_IN_MONO_SAMPLES, 128
+ .endif
+
+ .ifdef SAMPLE_RATE_22050
+ .equ SYNTH_UPDATE_PERIOD_IN_BITS, 7
+ .equ BUFFER_SIZE_IN_MONO_SAMPLES, 128
+ .endif
+
+ .ifdef SAMPLE_RATE_24000
+ .equ SYNTH_UPDATE_PERIOD_IN_BITS, 7
+ .equ BUFFER_SIZE_IN_MONO_SAMPLES, 128
+ .endif
+
+ .ifdef SAMPLE_RATE_32000
+ .equ SYNTH_UPDATE_PERIOD_IN_BITS, 7
+ .equ BUFFER_SIZE_IN_MONO_SAMPLES, 128
+ .endif
+
+ .ifdef SAMPLE_RATE_44100
+ .equ SYNTH_UPDATE_PERIOD_IN_BITS, 8
+ .equ BUFFER_SIZE_IN_MONO_SAMPLES, 256
+ .endif
+
+ .ifdef SAMPLE_RATE_48000
+ .equ SYNTH_UPDATE_PERIOD_IN_BITS, 8
+ .equ BUFFER_SIZE_IN_MONO_SAMPLES, 256
+ .endif
+
+
+@ if the OUTPUT PCM sample is 16-bits, then when using indexed addressing,
+@ the next sample is this many bytes away
+ .equ NEXT_OUTPUT_PCM, 2
+
+@****************************************************************************
+@/* macros for fractional phase accumulator */
+ .equ NUM_PHASE_FRAC_BITS, 15
+
+ .equ PHASE_FRAC_MASK, 0x7FFF
+
+@ shift for phase accumulator when fraction carries over
+ .ifdef SAMPLES_8_BIT
+ .equ NEXT_INPUT_PCM_SHIFT, 0
+ .endif
+
+ .ifdef SAMPLES_16_BIT
+ .equ NEXT_INPUT_PCM_SHIFT, 1
+ .endif
+
+@****************************************************************************
+ .equ NUM_MIXER_GUARD_BITS, 4
+
+@****************************************************************************
+@/* Envelope 1 (EG1) calculation macros */
+ .equ NUM_EG1_FRAC_BITS, 15
+
+@****************************************************************************
+
+ .equ NUM_ENHANCER_FILTER_COEF_FRAC_BITS, 5
+
+@****************************************************************************
+
+@
+@ I've temporarily given up on the idea of getting ADS/RV and gcc to
+@ handle a struct in a compatible fashion. Switching to old fashion EQU
+@
+
+ .if FILTER_ENABLED
+@**************************************
+@ typedef struct s_filter_tag
+ .equ m_z1, 0
+ .equ m_z2, 2
+ .endif
+
+@**************************************
+@ typedef struct s_wt_frame_tag
+ .equ m_gainTarget, 0
+ .equ m_phaseIncrement, 4
+
+ .if FILTER_ENABLED
+ .equ m_k, 8
+ .equ m_b1, 12
+ .equ m_b2, 16
+ .equ m_pAudioBuffer, 20
+ .equ m_pMixBuffer, 24
+ .equ m_numSamples, 28
+ .equ m_prevGain, 32
+ .else
+ .equ m_pAudioBuffer, 8
+ .equ m_pMixBuffer, 12
+ .equ m_numSamples, 16
+ .equ m_prevGain, 20
+ .endif
+
+
+@**************************************
+@ typedef struct s_wt_voice_tag
+ .equ m_pLoopEnd, 0 @ /* points to last PCM sample (not 1 beyond last) */
+ .equ m_pLoopStart, 4 @ /* points to first sample at start of loop */
+ .equ m_pPhaseAccum, 8 @ /* points to first sample at start of loop */
+ .equ m_phaseFrac, 12 @ /* points to first sample at start of loop */
+
+ .if STEREO_OUTPUT
+ .equ m_gainLeft, 16 @ /* current gain, left ch */
+ .equ m_gainRight, 18 @ /* current gain, right ch */
+ .endif
+
+
+@****************************************************************************
+@ enhancer
+ .equ m_nEnhancerFeedForward1, 0
+ .equ m_nEnhancerFeedback1, 1
+ .equ m_nDriveCoef, 2
+ .equ m_nEnhancerFeedback2, 3
+ .equ m_nWet, 4
+ .equ m_nDry, 5
+
+ .equ m_zF0L, 6 @ filter 1 zero state var, left
+ .equ m_zF1L, 8 @ filter 1 pole state var, left
+ .equ m_zF2L, 10 @ filter 2 zero state var, left
+ .equ m_zF0R, 12 @ filter 1 zero state var, right
+ .equ m_zF1R, 14 @ filter 1 pole state var, right
+ .equ m_zF2R, 16 @ filter 2 zero state var, right
+
+@****************************************************************************
+
+
+
diff --git a/arm-wt-22k/lib_src/arm-wt-22k_lib.mak b/arm-wt-22k/lib_src/arm-wt-22k_lib.mak
new file mode 100644
index 0000000..8e9824f
--- /dev/null
+++ b/arm-wt-22k/lib_src/arm-wt-22k_lib.mak
@@ -0,0 +1,25 @@
+#
+# Auto-generated sample makefile
+#
+# This makefile is intended for use with GNU make.
+# Set the paths to the tools (CC, AR, LD, etc.)
+#
+
+vpath %.c lib_src
+
+CC = C:\Program Files\GNUARM\bin\arm-elf-gcc.exe
+AS = C:\Program Files\GNUARM\bin\arm-elf-as.exe
+LD = C:\Program Files\GNUARM\bin\arm-elf-gcc.exe
+AR = C:\Program Files\GNUARM\bin\arm-elf-ar.exe
+
+%.o: %.c
+ $(CC) -c -O2 -o $@ -I lib_src -I host_src -D NUM_OUTPUT_CHANNELS=2 -D _SAMPLE_RATE_22050 -D MAX_SYNTH_VOICES=64 -D EAS_WT_SYNTH -D _8_BIT_SAMPLES -D _FILTER_ENABLED -D _IMELODY_PARSER -D _RTTTL_PARSER -D _OTA_PARSER -D _XMF_PARSER -D _WAVE_PARSER -D _REVERB_ENABLED -D _CHORUS_ENABLED -D DLS_SYNTHESIZER -D _IMA_DECODER -D MMAPI_SUPPORT -D NATIVE_EAS_KERNEL -D JET_INTERFACE $<
+
+%.o: %.s
+ $(AS) -o $@ -EL -mcpu=arm946e-s -mfpu=softfpa -I lib_src --defsym CHECK_STACK=0 --defsym REVERB=0 --defsym CHORUS=0 --defsym STEREO_OUTPUT=1 --defsym SAMPLE_RATE_22050=1 --defsym SAMPLES_8_BIT=1 --defsym FILTER_ENABLED=1 $<
+
+OBJS = eas_mididata.o eas_pan.o eas_wavefiledata.o eas_imelody.o eas_xmfdata.o ARM-E_interpolate_noloop_gnu.o eas_chorusdata.o ARM-E_voice_gain_gnu.o eas_ota.o eas_reverbdata.o eas_rtttl.o eas_reverb.o jet.o eas_mdls.o eas_mixbuf.o eas_smf.o eas_tcdata.o eas_chorus.o eas_pcmdata.o eas_xmf.o eas_smfdata.o eas_math.o eas_tonecontrol.o eas_rtttldata.o eas_voicemgt.o eas_public.o eas_dlssynth.o ARM-E_interpolate_loop_gnu.o ARM-E_filter_gnu.o eas_midi.o eas_otadata.o eas_flog.o eas_wtengine.o eas_imaadpcm.o eas_wtsynth.o wt_22khz.o eas_pcm.o eas_mixer.o eas_wavefile.o eas_ima_tables.o eas_data.o ARM-E_mastergain_gnu.o eas_imelodydata.o
+
+arm-wt-22k.a: $(OBJS)
+ $(AR) rc lib$@ $(OBJS)
+
diff --git a/arm-wt-22k/lib_src/dls.h b/arm-wt-22k/lib_src/dls.h
new file mode 100644
index 0000000..ca1d4c7
--- /dev/null
+++ b/arm-wt-22k/lib_src/dls.h
@@ -0,0 +1,268 @@
+ /*
+
+ dls.h
+
+ Description:
+
+ Interface defines and structures for the Instrument Collection Form
+ RIFF DLS.
+
+ Written by Sonic Foundry 1996. Released for public use.
+
+ */
+
+ #ifndef _INC_DLS
+ #define _INC_DLS
+
+ /*
+
+ Layout of an instrument collection:
+
+
+ RIFF [] 'DLS ' [colh,INSTLIST,WAVEPOOL,INFOLIST]
+
+ INSTLIST
+ LIST [] 'lins'
+ LIST [] 'ins ' [insh,RGNLIST,ARTLIST,INFOLIST]
+ LIST [] 'ins ' [insh,RGNLIST,ARTLIST,INFOLIST]
+ LIST [] 'ins ' [insh,RGNLIST,ARTLIST,INFOLIST]
+
+ RGNLIST
+ LIST [] 'lrgn'
+ LIST [] 'rgn ' [rgnh,wsmp,wlnk,ARTLIST]
+ LIST [] 'rgn ' [rgnh,wsmp,wlnk,ARTLIST]
+ LIST [] 'rgn ' [rgnh,wsmp,wlnk,ARTLIST]
+
+ ARTLIST
+ LIST [] 'lart'
+ 'art1' level 1 Articulation connection graph
+ 'art2' level 2 Articulation connection graph
+ '3rd1' Possible 3rd party articulation structure 1
+ '3rd2' Possible 3rd party articulation structure 2 .... and so on
+
+ WAVEPOOL
+ ptbl [] [pool table]
+ LIST [] 'wvpl'
+ [path],
+ [path],
+ LIST [] 'wave',RIFFWAVE
+ LIST [] 'wave',RIFFWAVE
+ LIST [] 'wave',RIFFWAVE
+ LIST [] 'wave',RIFFWAVE
+ LIST [] 'wave',RIFFWAVE
+
+ INFOLIST
+ LIST [] 'INFO'
+ 'icmt' 'One of those crazy comments.'
+ 'icop' 'Copyright (C) 1996 Sonic Foundry'
+
+ */
+
+
+ /*
+ FOURCC's used in the DLS file
+ */
+/* shree */
+//#define FAR
+
+/* shree
+
+ #define FOURCC_DLS mmioFOURCC('D','L','S',' ')
+ #define FOURCC_COLH mmioFOURCC('c','o','l','h')
+ #define FOURCC_WVPL mmioFOURCC('w','v','p','l')
+ #define FOURCC_PTBL mmioFOURCC('p','t','b','l')
+ #define FOURCC_PATH mmioFOURCC('p','a','t','h')
+ #define FOURCC_wave mmioFOURCC('w','a','v','e')
+ #define FOURCC_LINS mmioFOURCC('l','i','n','s')
+ #define FOURCC_INS mmioFOURCC('i','n','s',' ')
+ #define FOURCC_INSH mmioFOURCC('i','n','s','h')
+ #define FOURCC_LRGN mmioFOURCC('l','r','g','n')
+ #define FOURCC_RGN mmioFOURCC('r','g','n',' ')
+ #define FOURCC_RGNH mmioFOURCC('r','g','n','h')
+ #define FOURCC_LART mmioFOURCC('l','a','r','t')
+ #define FOURCC_ART1 mmioFOURCC('a','r','t','1')
+ #define FOURCC_WLNK mmioFOURCC('w','l','n','k')
+ #define FOURCC_WSMP mmioFOURCC('w','s','m','p')
+ #define FOURCC_VERS mmioFOURCC('v','e','r','s')
+*/
+ /*
+ Articulation connection graph definitions
+ */
+
+ /* Generic Sources */
+ #define CONN_SRC_NONE 0x0000
+ #define CONN_SRC_LFO 0x0001
+ #define CONN_SRC_KEYONVELOCITY 0x0002
+ #define CONN_SRC_KEYNUMBER 0x0003
+ #define CONN_SRC_EG1 0x0004
+ #define CONN_SRC_EG2 0x0005
+ #define CONN_SRC_PITCHWHEEL 0x0006
+
+ /* Midi Controllers 0-127 */
+ #define CONN_SRC_CC1 0x0081
+ #define CONN_SRC_CC7 0x0087
+ #define CONN_SRC_CC10 0x008a
+ #define CONN_SRC_CC11 0x008b
+
+ /* Registered Parameter Numbers */
+ #define CONN_SRC_RPN0 0x0100
+ #define CONN_SRC_RPN1 0x0101
+ #define CONN_SRC_RPN2 0x0102
+
+ /* Generic Destinations */
+ #define CONN_DST_NONE 0x0000
+ #define CONN_DST_ATTENUATION 0x0001
+ #define CONN_DST_RESERVED 0x0002
+ #define CONN_DST_PITCH 0x0003
+ #define CONN_DST_PAN 0x0004
+
+ /* LFO Destinations */
+ #define CONN_DST_LFO_FREQUENCY 0x0104
+ #define CONN_DST_LFO_STARTDELAY 0x0105
+
+ /* EG1 Destinations */
+ #define CONN_DST_EG1_ATTACKTIME 0x0206
+ #define CONN_DST_EG1_DECAYTIME 0x0207
+ #define CONN_DST_EG1_RESERVED 0x0208
+ #define CONN_DST_EG1_RELEASETIME 0x0209
+ #define CONN_DST_EG1_SUSTAINLEVEL 0x020a
+
+ /* EG2 Destinations */
+ #define CONN_DST_EG2_ATTACKTIME 0x030a
+ #define CONN_DST_EG2_DECAYTIME 0x030b
+ #define CONN_DST_EG2_RESERVED 0x030c
+ #define CONN_DST_EG2_RELEASETIME 0x030d
+ #define CONN_DST_EG2_SUSTAINLEVEL 0x030e
+
+ #define CONN_TRN_NONE 0x0000
+ #define CONN_TRN_CONCAVE 0x0001
+
+ typedef struct _DLSVERSION {
+ DWORD dwVersionMS;
+ DWORD dwVersionLS;
+ }DLSVERSION, FAR *LPDLSVERSION;
+
+
+ typedef struct _CONNECTION {
+ USHORT usSource;
+ USHORT usControl;
+ USHORT usDestination;
+ USHORT usTransform;
+ LONG lScale;
+ }CONNECTION, FAR *LPCONNECTION;
+
+
+ /* Level 1 Articulation Data */
+
+ typedef struct _CONNECTIONLIST {
+ ULONG cbSize; /* size of the connection list structure */
+ ULONG cConnections; /* count of connections in the list */
+ } CONNECTIONLIST, FAR *LPCONNECTIONLIST;
+
+
+
+ /*
+ Generic type defines for regions and instruments
+ */
+
+ typedef struct _RGNRANGE {
+ USHORT usLow;
+ USHORT usHigh;
+ }RGNRANGE, FAR * LPRGNRANGE;
+
+ #define F_INSTRUMENT_DRUMS 0x80000000
+
+ typedef struct _MIDILOCALE {
+ ULONG ulBank;
+ ULONG ulInstrument;
+ }MIDILOCALE, FAR *LPMIDILOCALE;
+
+ /*
+ Header structures found in an DLS file for collection, instruments, and
+ regions.
+ */
+
+ #define F_RGN_OPTION_SELFNONEXCLUSIVE 0x0001
+
+ typedef struct _RGNHEADER {
+ RGNRANGE RangeKey; /* Key range */
+ RGNRANGE RangeVelocity; /* Velocity Range */
+ USHORT fusOptions; /* Synthesis options for this range */
+ USHORT usKeyGroup; /* Key grouping for non simultaneous play
+ 0 = no group, 1 up is group
+ for Level 1 only groups 1-15 are allowed */
+ }RGNHEADER, FAR *LPRGNHEADER;
+
+ typedef struct _INSTHEADER {
+ ULONG cRegions; /* Count of regions in this instrument */
+ MIDILOCALE Locale; /* Intended MIDI locale of this instrument */
+ }INSTHEADER, FAR *LPINSTHEADER;
+
+ typedef struct _DLSHEADER {
+ ULONG cInstruments; /* Count of instruments in the collection */
+ }DLSHEADER, FAR *LPDLSHEADER;
+
+ /*
+ definitions for the Wave link structure
+ */
+
+ /***** For level 1 only WAVELINK_CHANNEL_MONO is valid ****
+ ulChannel allows for up to 32 channels of audio with each bit position
+ specifiying a channel of playback */
+
+ #define WAVELINK_CHANNEL_LEFT 0x0001
+ #define WAVELINK_CHANNEL_RIGHT 0x0002
+
+ #define F_WAVELINK_PHASE_MASTER 0x0001
+
+ typedef struct _WAVELINK { /* any paths or links are stored right after struct */
+ USHORT fusOptions; /* options flags for this wave */
+ USHORT usPhaseGroup; /* Phase grouping for locking channels */
+ ULONG ulChannel; /* channel placement */
+ ULONG ulTableIndex; /* index into the wave pool table, 0 based */
+ }WAVELINK, FAR *LPWAVELINK;
+
+ #define POOL_CUE_NULL 0xffffffff
+
+ typedef struct _POOLCUE {
+ // ULONG ulEntryIndex; /* Index entry in the list */
+ ULONG ulOffset; /* Offset to the entry in the list */
+ }POOLCUE, FAR *LPPOOLCUE;
+
+ typedef struct _POOLTABLE {
+ ULONG cbSize; /* size of the pool table structure */
+ ULONG cCues; /* count of cues in the list */
+ } POOLTABLE, FAR *LPPOOLTABLE;
+
+ /*
+ Structures for the "wsmp" chunk
+ */
+
+ #define F_WSMP_NO_TRUNCATION 0x0001
+ #define F_WSMP_NO_COMPRESSION 0x0002
+
+
+ typedef struct _rwsmp {
+ ULONG cbSize;
+ USHORT usUnityNote; /* MIDI Unity Playback Note */
+ SHORT sFineTune; /* Fine Tune in log tuning */
+ LONG lAttenuation; /* Overall Attenuation to be applied to data */
+ ULONG fulOptions; /* Flag options */
+ ULONG cSampleLoops; /* Count of Sample loops, 0 loops is one shot */
+ } WSMPL, FAR *LPWSMPL;
+
+
+ /* This loop type is a normal forward playing loop which is continually
+ played until the envelope reaches an off threshold in the release
+ portion of the volume envelope */
+
+ #define WLOOP_TYPE_FORWARD 0
+
+ typedef struct _rloop {
+ ULONG cbSize;
+ ULONG ulType; /* Loop Type */
+ ULONG ulStart; /* Start of loop in samples */
+ ULONG ulLength; /* Length of loop in samples */
+ } WLOOP, FAR *LPWLOOP;
+
+ #endif /* _INC_DLS */
diff --git a/arm-wt-22k/lib_src/dls2.h b/arm-wt-22k/lib_src/dls2.h
new file mode 100644
index 0000000..17d6efd
--- /dev/null
+++ b/arm-wt-22k/lib_src/dls2.h
@@ -0,0 +1,122 @@
+/*
+
+ dls2.h
+
+ Description:
+
+ Interface defines and structures for the DLS2 extensions of DLS.
+
+
+ Written by Microsoft 1998. Released for public use.
+
+*/
+
+#ifndef _INC_DLS2
+#define _INC_DLS2
+
+/*
+ FOURCC's used in the DLS2 file, in addition to DLS1 chunks
+*/
+
+#define FOURCC_RGN2 mmioFOURCC('r','g','n','2')
+#define FOURCC_LAR2 mmioFOURCC('l','a','r','2')
+#define FOURCC_ART2 mmioFOURCC('a','r','t','2')
+#define FOURCC_CDL mmioFOURCC('c','d','l',' ')
+#define FOURCC_DLID mmioFOURCC('d','l','i','d')
+
+/*
+ Articulation connection graph definitions. These are in addition to
+ the definitions in the DLS1 header.
+*/
+
+/* Generic Sources (in addition to DLS1 sources. */
+#define CONN_SRC_POLYPRESSURE 0x0007 /* Polyphonic Pressure */
+#define CONN_SRC_CHANNELPRESSURE 0x0008 /* Channel Pressure */
+#define CONN_SRC_VIBRATO 0x0009 /* Vibrato LFO */
+#define CONN_SRC_MONOPRESSURE 0x000a /* MIDI Mono pressure */
+
+
+/* Midi Controllers */
+#define CONN_SRC_CC91 0x00db /* Reverb Send */
+#define CONN_SRC_CC93 0x00dd /* Chorus Send */
+
+
+/* Generic Destinations */
+#define CONN_DST_GAIN 0x0001 /* Same as CONN_DST_ ATTENUATION, but more appropriate terminology. */
+#define CONN_DST_KEYNUMBER 0x0005 /* Key Number Generator */
+
+/* Audio Channel Output Destinations */
+#define CONN_DST_LEFT 0x0010 /* Left Channel Send */
+#define CONN_DST_RIGHT 0x0011 /* Right Channel Send */
+#define CONN_DST_CENTER 0x0012 /* Center Channel Send */
+#define CONN_DST_LEFTREAR 0x0013 /* Left Rear Channel Send */
+#define CONN_DST_RIGHTREAR 0x0014 /* Right Rear Channel Send */
+#define CONN_DST_LFE_CHANNEL 0x0015 /* LFE Channel Send */
+#define CONN_DST_CHORUS 0x0080 /* Chorus Send */
+#define CONN_DST_REVERB 0x0081 /* Reverb Send */
+
+/* Vibrato LFO Destinations */
+#define CONN_DST_VIB_FREQUENCY 0x0114 /* Vibrato Frequency */
+#define CONN_DST_VIB_STARTDELAY 0x0115 /* Vibrato Start Delay */
+
+/* EG1 Destinations */
+#define CONN_DST_EG1_DELAYTIME 0x020B /* EG1 Delay Time */
+#define CONN_DST_EG1_HOLDTIME 0x020C /* EG1 Hold Time */
+#define CONN_DST_EG1_SHUTDOWNTIME 0x020D /* EG1 Shutdown Time */
+
+
+/* EG2 Destinations */
+#define CONN_DST_EG2_DELAYTIME 0x030F /* EG2 Delay Time */
+#define CONN_DST_EG2_HOLDTIME 0x0310 /* EG2 Hold Time */
+
+
+/* Filter Destinations */
+#define CONN_DST_FILTER_CUTOFF 0x0500 /* Filter Cutoff Frequency */
+#define CONN_DST_FILTER_Q 0x0501 /* Filter Resonance */
+
+
+/* Transforms */
+#define CONN_TRN_CONVEX 0x0002 /* Convex Transform */
+#define CONN_TRN_SWITCH 0x0003 /* Switch Transform */
+
+
+/* Conditional chunk operators */
+ #define DLS_CDL_AND 0x0001 /* X = X & Y */
+ #define DLS_CDL_OR 0x0002 /* X = X | Y */
+ #define DLS_CDL_XOR 0x0003 /* X = X ^ Y */
+ #define DLS_CDL_ADD 0x0004 /* X = X + Y */
+ #define DLS_CDL_SUBTRACT 0x0005 /* X = X - Y */
+ #define DLS_CDL_MULTIPLY 0x0006 /* X = X * Y */
+ #define DLS_CDL_DIVIDE 0x0007 /* X = X / Y */
+ #define DLS_CDL_LOGICAL_AND 0x0008 /* X = X && Y */
+ #define DLS_CDL_LOGICAL_OR 0x0009 /* X = X || Y */
+ #define DLS_CDL_LT 0x000A /* X = (X < Y) */
+ #define DLS_CDL_LE 0x000B /* X = (X <= Y) */
+ #define DLS_CDL_GT 0x000C /* X = (X > Y) */
+ #define DLS_CDL_GE 0x000D /* X = (X >= Y) */
+ #define DLS_CDL_EQ 0x000E /* X = (X == Y) */
+ #define DLS_CDL_NOT 0x000F /* X = !X */
+ #define DLS_CDL_CONST 0x0010 /* 32-bit constant */
+ #define DLS_CDL_QUERY 0x0011 /* 32-bit value returned from query */
+ #define DLS_CDL_QUERYSUPPORTED 0x0012 /* 32-bit value returned from query */
+
+/*
+ Loop and release
+*/
+
+#define WLOOP_TYPE_RELEASE 1
+
+/*
+ DLSID queries for <cdl-ck>
+*/
+DEFINE_DLSID(DLSID_GMInHardware, 0x178f2f24, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);
+DEFINE_DLSID(DLSID_GSInHardware, 0x178f2f25, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);
+DEFINE_DLSID(DLSID_XGInHardware, 0x178f2f26, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);
+DEFINE_DLSID(DLSID_SupportsDLS1, 0x178f2f27, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);
+DEFINE_DLSID(DLSID_SupportsDLS2, 0xf14599e5, 0x4689, 0x11d2, 0xaf, 0xa6, 0x0, 0xaa, 0x0, 0x24, 0xd8, 0xb6);
+DEFINE_DLSID(DLSID_SampleMemorySize, 0x178f2f28, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);
+DEFINE_DLSID(DLSID_ManufacturersID, 0xb03e1181, 0x8095, 0x11d2, 0xa1, 0xef, 0x0, 0x60, 0x8, 0x33, 0xdb, 0xd8);
+DEFINE_DLSID(DLSID_ProductID, 0xb03e1182, 0x8095, 0x11d2, 0xa1, 0xef, 0x0, 0x60, 0x8, 0x33, 0xdb, 0xd8);
+DEFINE_DLSID(DLSID_SamplePlaybackRate, 0x2a91f713, 0xa4bf, 0x11d2, 0xbb, 0xdf, 0x0, 0x60, 0x8, 0x33, 0xdb, 0xd8);
+#endif /* _INC_DLS2 */
+
diff --git a/arm-wt-22k/lib_src/eas_audioconst.h b/arm-wt-22k/lib_src/eas_audioconst.h
new file mode 100644
index 0000000..1cfa404
--- /dev/null
+++ b/arm-wt-22k/lib_src/eas_audioconst.h
@@ -0,0 +1,97 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_audioconst.h
+ *
+ * Contents and purpose:
+ * Defines audio constants related to the sample rate, bit size, etc.
+ *
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 82 $
+ * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $
+ *----------------------------------------------------------------------------
+*/
+
+#ifndef _EAS_AUDIOCONST_H
+#define _EAS_AUDIOCONST_H
+
+/*----------------------------------------------------------------------------
+ * These macros define the various characteristics of the defined sample rates
+ *----------------------------------------------------------------------------
+ * BUFFER_SIZE_IN_MONO_SAMPLES size of buffer in samples
+ * _OUTPUT_SAMPLE_RATE compiled output sample rate
+ * AUDIO_FRAME_LENGTH length of an audio frame in 256ths of a millisecond
+ * SYNTH_UPDATE_PERIOD_IN_BITS length of an audio frame (2^x samples)
+ *----------------------------------------------------------------------------
+*/
+
+#if defined (_SAMPLE_RATE_8000)
+#define BUFFER_SIZE_IN_MONO_SAMPLES 32
+#define _OUTPUT_SAMPLE_RATE 8000
+#define AUDIO_FRAME_LENGTH 1024
+#define SYNTH_UPDATE_PERIOD_IN_BITS 5
+
+#elif defined (_SAMPLE_RATE_16000)
+#define BUFFER_SIZE_IN_MONO_SAMPLES 64
+#define _OUTPUT_SAMPLE_RATE 16000
+#define AUDIO_FRAME_LENGTH 1024
+#define SYNTH_UPDATE_PERIOD_IN_BITS 6
+
+#elif defined (_SAMPLE_RATE_20000)
+#define BUFFER_SIZE_IN_MONO_SAMPLES 128
+#define _OUTPUT_SAMPLE_RATE 20000
+#define AUDIO_FRAME_LENGTH 1638
+#define SYNTH_UPDATE_PERIOD_IN_BITS 7
+
+#elif defined (_SAMPLE_RATE_22050)
+#define BUFFER_SIZE_IN_MONO_SAMPLES 128
+#define _OUTPUT_SAMPLE_RATE 22050
+#define AUDIO_FRAME_LENGTH 1486
+#define SYNTH_UPDATE_PERIOD_IN_BITS 7
+
+#elif defined (_SAMPLE_RATE_24000)
+#define BUFFER_SIZE_IN_MONO_SAMPLES 128
+#define _OUTPUT_SAMPLE_RATE 24000
+#define AUDIO_FRAME_LENGTH 1365
+#define SYNTH_UPDATE_PERIOD_IN_BITS 7
+
+#elif defined (_SAMPLE_RATE_32000)
+#define BUFFER_SIZE_IN_MONO_SAMPLES 128
+#define _OUTPUT_SAMPLE_RATE 32000
+#define AUDIO_FRAME_LENGTH 1024
+#define SYNTH_UPDATE_PERIOD_IN_BITS 7
+
+#elif defined (_SAMPLE_RATE_44100)
+#define BUFFER_SIZE_IN_MONO_SAMPLES 256
+#define _OUTPUT_SAMPLE_RATE 44100
+#define AUDIO_FRAME_LENGTH 1486
+#define SYNTH_UPDATE_PERIOD_IN_BITS 8
+
+#elif defined (_SAMPLE_RATE_48000)
+#define BUFFER_SIZE_IN_MONO_SAMPLES 256
+#define _OUTPUT_SAMPLE_RATE 48000
+#define AUDIO_FRAME_LENGTH 1365
+#define SYNTH_UPDATE_PERIOD_IN_BITS 8
+
+#else
+#error "_SAMPLE_RATE_XXXXX must be defined to valid rate"
+#endif
+
+#endif /* #ifndef _EAS_AUDIOCONST_H */
+
diff --git a/arm-wt-22k/lib_src/eas_chorus.c b/arm-wt-22k/lib_src/eas_chorus.c
new file mode 100644
index 0000000..bc42237
--- /dev/null
+++ b/arm-wt-22k/lib_src/eas_chorus.c
@@ -0,0 +1,604 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_chorus.c
+ *
+ * Contents and purpose:
+ * Contains the implementation of the Chorus effect.
+ *
+ *
+ * Copyright Sonic Network Inc. 2006
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 499 $
+ * $Date: 2006-12-11 16:07:20 -0800 (Mon, 11 Dec 2006) $
+ *----------------------------------------------------------------------------
+*/
+
+#include "eas_data.h"
+#include "eas_effects.h"
+#include "eas_math.h"
+#include "eas_chorusdata.h"
+#include "eas_chorus.h"
+#include "eas_config.h"
+#include "eas_host.h"
+#include "eas_report.h"
+
+/* prototypes for effects interface */
+static EAS_RESULT ChorusInit (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData);
+static void ChorusProcess (EAS_VOID_PTR pInstData, EAS_PCM *pSrc, EAS_PCM *pDst, EAS_I32 numSamples);
+static EAS_RESULT ChorusShutdown (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData);
+static EAS_RESULT ChorusGetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue);
+static EAS_RESULT ChorusSetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value);
+
+/* common effects interface for configuration module */
+const S_EFFECTS_INTERFACE EAS_Chorus =
+{
+ ChorusInit,
+ ChorusProcess,
+ ChorusShutdown,
+ ChorusGetParam,
+ ChorusSetParam
+};
+
+
+
+//LFO shape table used by the chorus, larger table would sound better
+//this is a sine wave, where 32767 = 1.0
+static const EAS_I16 EAS_chorusShape[CHORUS_SHAPE_SIZE] = {
+ 0, 1608, 3212, 4808, 6393, 7962, 9512, 11309, 12539, 14010, 15446, 16846, 18204, 19519, 20787, 22005, 23170,
+ 24279, 25329, 26319, 27245, 28105, 28898, 29621, 30273, 30852, 31356, 31785, 32137, 32412, 32609, 32728,
+ 32767, 32728, 32609, 32412, 32137, 31785, 31356, 30852, 30273, 29621, 28898, 28105, 27245, 26319, 25329,
+ 24279, 23170, 22005, 20787, 19519, 18204, 16846, 15446, 14010, 12539, 11039, 9512, 7962, 6393, 4808, 3212,
+ 1608, 0, -1608, -3212, -4808, -6393, -7962, -9512, -11309, -12539, -14010, -15446, -16846, -18204, -19519,
+ -20787, -22005, -23170, -24279, -25329, -26319, -27245, -28105, -28898, -29621, -30273, -30852, -31356, -31785,
+ -32137, -32412, -32609, -32728, -32767, -32728, -32609, -32412, -32137, -31785, -31356, -30852, -30273, -29621,
+ -28898, -28105, -27245, -26319, -25329, -24279, -23170, -22005, -20787, -19519, -18204, -16846, -15446, -14010,
+ -12539, -11039, -9512, -7962, -6393, -4808, -3212, -1608
+};
+
+/*----------------------------------------------------------------------------
+ * InitializeChorus()
+ *----------------------------------------------------------------------------
+ * Purpose: Initializes chorus parameters
+ *
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT ChorusInit (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData)
+{
+ S_CHORUS_OBJECT *pChorusData;
+ S_CHORUS_PRESET *pPreset;
+ EAS_I32 index;
+
+ /* check Configuration Module for data allocation */
+ if (pEASData->staticMemoryModel)
+ pChorusData = EAS_CMEnumFXData(EAS_MODULE_CHORUS);
+
+ /* allocate dynamic memory */
+ else
+ pChorusData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_CHORUS_OBJECT));
+
+ if (pChorusData == NULL)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate Chorus memory\n"); */ }
+ return EAS_ERROR_MALLOC_FAILED;
+ }
+
+ /* clear the structure */
+ EAS_HWMemSet(pChorusData, 0, sizeof(S_CHORUS_OBJECT));
+
+ ChorusReadInPresets(pChorusData);
+
+ /* set some default values */
+ pChorusData->bypass = EAS_CHORUS_BYPASS_DEFAULT;
+ pChorusData->preset = EAS_CHORUS_PRESET_DEFAULT;
+ pChorusData->m_nLevel = EAS_CHORUS_LEVEL_DEFAULT;
+ pChorusData->m_nRate = EAS_CHORUS_RATE_DEFAULT;
+ pChorusData->m_nDepth = EAS_CHORUS_DEPTH_DEFAULT;
+
+ //chorus rate and depth need some massaging from preset value (which is sample rate independent)
+
+ //convert rate from steps of .05 Hz to value which can be used as phase increment,
+ //with current CHORUS_SHAPE_SIZE and rate limits, this fits into 16 bits
+ //want to compute ((shapeSize * 65536) * (storedRate/20))/sampleRate;
+ //computing it as below allows rate steps to be evenly spaced
+ //uses 32 bit divide, but only once when new value is selected
+ pChorusData->m_nRate = (EAS_I16)
+ ((((EAS_I32)CHORUS_SHAPE_SIZE<<16)/(20*(EAS_I32)_OUTPUT_SAMPLE_RATE)) * pChorusData->m_nRate);
+
+ //convert depth from steps of .05 ms, to samples, with 16 bit whole part, discard fraction
+ //want to compute ((depth * sampleRate)/20000)
+ //use the following approximation since 105/32 is roughly 65536/20000
+ /*lint -e{704} use shift for performance */
+ pChorusData->m_nDepth = (EAS_I16)
+ (((((EAS_I32)pChorusData->m_nDepth * _OUTPUT_SAMPLE_RATE)>>5) * 105) >> 16);
+
+ pChorusData->m_nLevel = pChorusData->m_nLevel;
+
+ //zero delay memory for chorus
+ for (index = CHORUS_L_SIZE - 1; index >= 0; index--)
+ {
+ pChorusData->chorusDelayL[index] = 0;
+ }
+ for (index = CHORUS_R_SIZE - 1; index >= 0; index--)
+ {
+ pChorusData->chorusDelayR[index] = 0;
+ }
+
+ //init delay line index, these are used to implement circular delay buffer
+ pChorusData->chorusIndexL = 0;
+ pChorusData->chorusIndexR = 0;
+
+ //init LFO phase
+ //16 bit whole part, 16 bit fraction
+ pChorusData->lfoLPhase = 0;
+ pChorusData->lfoRPhase = (CHORUS_SHAPE_SIZE << 16) >> 2; // 1/4 of total, i.e. 90 degrees out of phase;
+
+ //init chorus delay position
+ //right now chorus delay is a compile-time value, as is sample rate
+ pChorusData->chorusTapPosition = (EAS_I16)((CHORUS_DELAY_MS * _OUTPUT_SAMPLE_RATE)/1000);
+
+ //now copy from the new preset into Chorus
+ pPreset = &pChorusData->m_sPreset.m_sPreset[pChorusData->m_nNextChorus];
+
+ pChorusData->m_nLevel = pPreset->m_nLevel;
+ pChorusData->m_nRate = pPreset->m_nRate;
+ pChorusData->m_nDepth = pPreset->m_nDepth;
+
+ pChorusData->m_nRate = (EAS_I16)
+ ((((EAS_I32)CHORUS_SHAPE_SIZE<<16)/(20*(EAS_I32)_OUTPUT_SAMPLE_RATE)) * pChorusData->m_nRate);
+
+ /*lint -e{704} use shift for performance */
+ pChorusData->m_nDepth = (EAS_I16)
+ (((((EAS_I32)pChorusData->m_nDepth * _OUTPUT_SAMPLE_RATE)>>5) * 105) >> 16);
+
+ *pInstData = pChorusData;
+
+ return EAS_SUCCESS;
+} /* end ChorusInit */
+
+/*----------------------------------------------------------------------------
+ * WeightedTap()
+ *----------------------------------------------------------------------------
+ * Purpose: Does fractional array look-up using linear interpolation
+ *
+ * first convert indexDesired to actual desired index by taking into account indexReference
+ * then do linear interpolation between two actual samples using fractional part
+ *
+ * Inputs:
+ * array: pointer to array of signed 16 bit values, typically either PCM data or control data
+ * indexReference: the circular buffer relative offset
+ * indexDesired: the fractional index we are looking up (16 bits index + 16 bits fraction)
+ * indexLimit: the total size of the array, used to compute buffer wrap
+ *
+ * Outputs:
+ * Value from the input array, linearly interpolated between two actual data values
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_I16 WeightedTap(const EAS_I16 *array, EAS_I16 indexReference, EAS_I32 indexDesired, EAS_I16 indexLimit)
+{
+ EAS_I16 index;
+ EAS_I16 fraction;
+ EAS_I16 val1;
+ EAS_I16 val2;
+
+ //separate indexDesired into whole and fractional parts
+ /*lint -e{704} use shift for performance */
+ index = (EAS_I16)(indexDesired >> 16);
+ /*lint -e{704} use shift for performance */
+ fraction = (EAS_I16)((indexDesired>>1) & 0x07FFF); //just use 15 bits of fractional part
+
+ //adjust whole part by indexReference
+ index = indexReference - index;
+ //make sure we stay within array bounds, this implements circular buffer
+ while (index < 0)
+ {
+ index += indexLimit;
+ }
+
+ //get two adjacent values from the array
+ val1 = array[index];
+
+ //handle special case when index == 0, else typical case
+ if (index == 0)
+ {
+ val2 = array[indexLimit-1]; //get last value from array
+ }
+ else
+ {
+ val2 = array[index-1]; //get previous value from array
+ }
+
+ //compute linear interpolation as (val1 + ((val2-val1)*fraction))
+ return(val1 + (EAS_I16)MULT_EG1_EG1(val2-val1,fraction));
+}
+
+/*----------------------------------------------------------------------------
+ * ChorusProcess()
+ *----------------------------------------------------------------------------
+ * Purpose: compute the chorus on the input buffer, and mix into output buffer
+ *
+ *
+ * Inputs:
+ * src: pointer to input buffer of PCM values to be processed
+ * dst: pointer to output buffer of PCM values we are to sume the result with
+ * bufSize: the number of sample frames (i.e. stereo samples) in the buffer
+ *
+ * Outputs:
+ * None
+ *
+ *----------------------------------------------------------------------------
+*/
+//compute the chorus, and mix into output buffer
+static void ChorusProcess (EAS_VOID_PTR pInstData, EAS_PCM *pSrc, EAS_PCM *pDst, EAS_I32 numSamples)
+{
+ EAS_I32 ix;
+ EAS_I32 nChannelNumber;
+ EAS_I16 lfoValueLeft;
+ EAS_I16 lfoValueRight;
+ EAS_I32 positionOffsetL;
+ EAS_I32 positionOffsetR;
+ EAS_PCM tapL;
+ EAS_PCM tapR;
+ EAS_I32 tempValue;
+ EAS_PCM nInputSample;
+ EAS_I32 nOutputSample;
+ EAS_PCM *pIn;
+ EAS_PCM *pOut;
+
+ S_CHORUS_OBJECT *pChorusData;
+
+ pChorusData = (S_CHORUS_OBJECT*) pInstData;
+
+ //if the chorus is disabled or turned all the way down
+ if (pChorusData->bypass == EAS_TRUE || pChorusData->m_nLevel == 0)
+ {
+ if (pSrc != pDst)
+ EAS_HWMemCpy(pSrc, pDst, numSamples * NUM_OUTPUT_CHANNELS * (EAS_I32) sizeof(EAS_PCM));
+ return;
+ }
+
+ if (pChorusData->m_nNextChorus != pChorusData->m_nCurrentChorus)
+ {
+ ChorusUpdate(pChorusData);
+ }
+
+ for (nChannelNumber = 0; nChannelNumber < NUM_OUTPUT_CHANNELS; nChannelNumber++)
+ {
+
+ pIn = pSrc + nChannelNumber;
+ pOut = pDst + nChannelNumber;
+
+ if(nChannelNumber==0)
+ {
+ for (ix = 0; ix < numSamples; ix++)
+ {
+ nInputSample = *pIn;
+ pIn += NUM_OUTPUT_CHANNELS;
+
+ //feed input into chorus delay line
+ pChorusData->chorusDelayL[pChorusData->chorusIndexL] = nInputSample;
+
+ //compute chorus lfo value using phase as fractional index into chorus shape table
+ //resulting value is between -1.0 and 1.0, expressed as signed 16 bit number
+ lfoValueLeft = WeightedTap(EAS_chorusShape, 0, pChorusData->lfoLPhase, CHORUS_SHAPE_SIZE);
+
+ //scale chorus depth by lfo value to get relative fractional sample index
+ //index is expressed as 32 bit number with 16 bit fractional part
+ /*lint -e{703} use shift for performance */
+ positionOffsetL = pChorusData->m_nDepth * (((EAS_I32)lfoValueLeft) << 1);
+
+ //add fixed chorus delay to get actual fractional sample index
+ positionOffsetL += ((EAS_I32)pChorusData->chorusTapPosition) << 16;
+
+ //get tap value from chorus delay using fractional sample index
+ tapL = WeightedTap(pChorusData->chorusDelayL, pChorusData->chorusIndexL, positionOffsetL, CHORUS_L_SIZE);
+
+ //scale by chorus level, then sum with input buffer contents and saturate
+ tempValue = MULT_EG1_EG1(tapL, pChorusData->m_nLevel);
+ nOutputSample = SATURATE(tempValue + nInputSample);
+
+ *pOut = (EAS_I16)SATURATE(nOutputSample);
+ pOut += NUM_OUTPUT_CHANNELS;
+
+
+ //increment chorus delay index and make it wrap as needed
+ //this implements circular buffer
+ if ((pChorusData->chorusIndexL+=1) >= CHORUS_L_SIZE)
+ pChorusData->chorusIndexL = 0;
+
+ //increment fractional lfo phase, and make it wrap as needed
+ pChorusData->lfoLPhase += pChorusData->m_nRate;
+ while (pChorusData->lfoLPhase >= (CHORUS_SHAPE_SIZE<<16))
+ {
+ pChorusData->lfoLPhase -= (CHORUS_SHAPE_SIZE<<16);
+ }
+ }
+ }
+ else
+ {
+ for (ix = 0; ix < numSamples; ix++)
+ {
+ nInputSample = *pIn;
+ pIn += NUM_OUTPUT_CHANNELS;
+
+ //feed input into chorus delay line
+ pChorusData->chorusDelayR[pChorusData->chorusIndexR] = nInputSample;
+
+ //compute chorus lfo value using phase as fractional index into chorus shape table
+ //resulting value is between -1.0 and 1.0, expressed as signed 16 bit number
+ lfoValueRight = WeightedTap(EAS_chorusShape, 0, pChorusData->lfoRPhase, CHORUS_SHAPE_SIZE);
+
+ //scale chorus depth by lfo value to get relative fractional sample index
+ //index is expressed as 32 bit number with 16 bit fractional part
+ /*lint -e{703} use shift for performance */
+ positionOffsetR = pChorusData->m_nDepth * (((EAS_I32)lfoValueRight) << 1);
+
+ //add fixed chorus delay to get actual fractional sample index
+ positionOffsetR += ((EAS_I32)pChorusData->chorusTapPosition) << 16;
+
+ //get tap value from chorus delay using fractional sample index
+ tapR = WeightedTap(pChorusData->chorusDelayR, pChorusData->chorusIndexR, positionOffsetR, CHORUS_R_SIZE);
+
+ //scale by chorus level, then sum with output buffer contents and saturate
+ tempValue = MULT_EG1_EG1(tapR, pChorusData->m_nLevel);
+ nOutputSample = SATURATE(tempValue + nInputSample);
+
+ *pOut = (EAS_I16)SATURATE(nOutputSample);
+ pOut += NUM_OUTPUT_CHANNELS;
+
+ //increment chorus delay index and make it wrap as needed
+ //this implements circular buffer
+ if ((pChorusData->chorusIndexR+=1) >= CHORUS_R_SIZE)
+ pChorusData->chorusIndexR = 0;
+
+ //increment fractional lfo phase, and make it wrap as needed
+ pChorusData->lfoRPhase += pChorusData->m_nRate;
+ while (pChorusData->lfoRPhase >= (CHORUS_SHAPE_SIZE<<16))
+ {
+ pChorusData->lfoRPhase -= (CHORUS_SHAPE_SIZE<<16);
+ }
+ }
+ }
+
+ }
+} /* end ChorusProcess */
+
+
+
+/*----------------------------------------------------------------------------
+ * ChorusShutdown()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Initializes the Chorus effect.
+ *
+ * Inputs:
+ * pInstData - handle to instance data
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT ChorusShutdown (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData)
+{
+ /* check Configuration Module for static memory allocation */
+ if (!pEASData->staticMemoryModel)
+ EAS_HWFree(pEASData->hwInstData, pInstData);
+ return EAS_SUCCESS;
+} /* end ChorusShutdown */
+
+/*----------------------------------------------------------------------------
+ * ChorusGetParam()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Get a Chorus parameter
+ *
+ * Inputs:
+ * pInstData - handle to instance data
+ * param - parameter index
+ * *pValue - pointer to variable to hold retrieved value
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT ChorusGetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue)
+{
+ S_CHORUS_OBJECT *p;
+
+ p = (S_CHORUS_OBJECT*) pInstData;
+
+ switch (param)
+ {
+ case EAS_PARAM_CHORUS_BYPASS:
+ *pValue = (EAS_I32) p->bypass;
+ break;
+ case EAS_PARAM_CHORUS_PRESET:
+ *pValue = (EAS_I8) p->m_nCurrentChorus;
+ break;
+ case EAS_PARAM_CHORUS_RATE:
+ *pValue = (EAS_I32) p->m_nRate;
+ break;
+ case EAS_PARAM_CHORUS_DEPTH:
+ *pValue = (EAS_I32) p->m_nDepth;
+ break;
+ case EAS_PARAM_CHORUS_LEVEL:
+ *pValue = (EAS_I32) p->m_nLevel;
+ break;
+ default:
+ return EAS_ERROR_INVALID_PARAMETER;
+ }
+ return EAS_SUCCESS;
+} /* end ChorusGetParam */
+
+
+/*----------------------------------------------------------------------------
+ * ChorusSetParam()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Set a Chorus parameter
+ *
+ * Inputs:
+ * pInstData - handle to instance data
+ * param - parameter index
+ * *pValue - new paramter value
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT ChorusSetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value)
+{
+ S_CHORUS_OBJECT *p;
+
+ p = (S_CHORUS_OBJECT*) pInstData;
+
+ switch (param)
+ {
+ case EAS_PARAM_CHORUS_BYPASS:
+ p->bypass = (EAS_BOOL) value;
+ break;
+ case EAS_PARAM_CHORUS_PRESET:
+ if(value!=EAS_PARAM_CHORUS_PRESET1 && value!=EAS_PARAM_CHORUS_PRESET2 &&
+ value!=EAS_PARAM_CHORUS_PRESET3 && value!=EAS_PARAM_CHORUS_PRESET4)
+ return EAS_ERROR_INVALID_PARAMETER;
+ p->m_nNextChorus = (EAS_I8)value;
+ break;
+ case EAS_PARAM_CHORUS_RATE:
+ if(value<EAS_CHORUS_RATE_MIN || value>EAS_CHORUS_RATE_MAX)
+ return EAS_ERROR_INVALID_PARAMETER;
+ p->m_nRate = (EAS_I16) value;
+ break;
+ case EAS_PARAM_CHORUS_DEPTH:
+ if(value<EAS_CHORUS_DEPTH_MIN || value>EAS_CHORUS_DEPTH_MAX)
+ return EAS_ERROR_INVALID_PARAMETER;
+ p->m_nDepth = (EAS_I16) value;
+ break;
+ case EAS_PARAM_CHORUS_LEVEL:
+ if(value<EAS_CHORUS_LEVEL_MIN || value>EAS_CHORUS_LEVEL_MAX)
+ return EAS_ERROR_INVALID_PARAMETER;
+ p->m_nLevel = (EAS_I16) value;
+ break;
+
+ default:
+ return EAS_ERROR_INVALID_PARAMETER;
+ }
+ return EAS_SUCCESS;
+} /* end ChorusSetParam */
+
+
+/*----------------------------------------------------------------------------
+ * ChorusReadInPresets()
+ *----------------------------------------------------------------------------
+ * Purpose: sets global Chorus preset bank to defaults
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT ChorusReadInPresets(S_CHORUS_OBJECT *pChorusData)
+{
+
+ int preset = 0;
+ int defaultPreset = 0;
+
+ //now init any remaining presets to defaults
+ for (defaultPreset = preset; defaultPreset < CHORUS_MAX_TYPE; defaultPreset++)
+ {
+ S_CHORUS_PRESET *pPreset = &pChorusData->m_sPreset.m_sPreset[defaultPreset];
+ if (defaultPreset == 0 || defaultPreset > CHORUS_MAX_TYPE-1)
+ {
+ pPreset->m_nDepth = 39;
+ pPreset->m_nRate = 30;
+ pPreset->m_nLevel = 32767;
+ }
+ else if (defaultPreset == 1)
+ {
+ pPreset->m_nDepth = 21;
+ pPreset->m_nRate = 45;
+ pPreset->m_nLevel = 25000;
+ }
+ else if (defaultPreset == 2)
+ {
+ pPreset->m_nDepth = 53;
+ pPreset->m_nRate = 25;
+ pPreset->m_nLevel = 32000;
+ }
+ else if (defaultPreset == 3)
+ {
+ pPreset->m_nDepth = 32;
+ pPreset->m_nRate = 37;
+ pPreset->m_nLevel = 29000;
+ }
+ }
+
+ return EAS_SUCCESS;
+}
+
+
+/*----------------------------------------------------------------------------
+ * ChorusUpdate
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Update the Chorus preset parameters as required
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ * - chorus paramters will be changed
+ * - m_nCurrentRoom := m_nNextRoom
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT ChorusUpdate(S_CHORUS_OBJECT *pChorusData)
+{
+ S_CHORUS_PRESET *pPreset = &pChorusData->m_sPreset.m_sPreset[pChorusData->m_nNextChorus];
+
+ pChorusData->m_nLevel = pPreset->m_nLevel;
+ pChorusData->m_nRate = pPreset->m_nRate;
+ pChorusData->m_nDepth = pPreset->m_nDepth;
+
+ pChorusData->m_nRate = (EAS_I16)
+ ((((EAS_I32)CHORUS_SHAPE_SIZE<<16)/(20*(EAS_I32)_OUTPUT_SAMPLE_RATE)) * pChorusData->m_nRate);
+
+ /*lint -e{704} use shift for performance */
+ pChorusData->m_nDepth = (EAS_I16)
+ (((((EAS_I32)pChorusData->m_nDepth * _OUTPUT_SAMPLE_RATE)>>5) * 105) >> 16);
+
+ pChorusData->m_nCurrentChorus = pChorusData->m_nNextChorus;
+
+ return EAS_SUCCESS;
+
+} /* end ChorusUpdate */
diff --git a/arm-wt-22k/lib_src/eas_chorusdata.c b/arm-wt-22k/lib_src/eas_chorusdata.c
new file mode 100644
index 0000000..caee1ed
--- /dev/null
+++ b/arm-wt-22k/lib_src/eas_chorusdata.c
@@ -0,0 +1,34 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_chorusdata.c
+ *
+ * Contents and purpose:
+ * Contains the static data allocation for the Chorus effect
+ *
+ *
+ * Copyright Sonic Network Inc. 2006
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 550 $
+ * $Date: 2007-02-02 09:37:03 -0800 (Fri, 02 Feb 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+#include "eas_chorusdata.h"
+
+S_CHORUS_OBJECT eas_ChorusData;
+
diff --git a/arm-wt-22k/lib_src/eas_chorusdata.h b/arm-wt-22k/lib_src/eas_chorusdata.h
new file mode 100644
index 0000000..4420ddd
--- /dev/null
+++ b/arm-wt-22k/lib_src/eas_chorusdata.h
@@ -0,0 +1,160 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_chorusdata.h
+ *
+ * Contents and purpose:
+ * Contains the prototypes for the Chorus effect.
+ *
+ *
+ * Copyright Sonic Network Inc. 2006
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 309 $
+ * $Date: 2006-09-12 18:52:45 -0700 (Tue, 12 Sep 2006) $
+ *----------------------------------------------------------------------------
+*/
+
+#ifndef _EAS_CHORUS_H
+#define _EAS_CHORUS_H
+
+#include "eas_types.h"
+#include "eas_audioconst.h"
+
+//defines for chorus
+
+#define EAS_CHORUS_BYPASS_DEFAULT 1
+#define EAS_CHORUS_PRESET_DEFAULT 0
+#define EAS_CHORUS_RATE_DEFAULT 30
+#define EAS_CHORUS_DEPTH_DEFAULT 39
+#define EAS_CHORUS_LEVEL_DEFAULT 32767
+
+#define EAS_CHORUS_LEVEL_MIN 0
+#define EAS_CHORUS_LEVEL_MAX 32767
+
+#define EAS_CHORUS_RATE_MIN 10
+#define EAS_CHORUS_RATE_MAX 50
+
+#define EAS_CHORUS_DEPTH_MIN 15
+#define EAS_CHORUS_DEPTH_MAX 60
+
+#define CHORUS_SIZE_MS 20
+#define CHORUS_L_SIZE ((CHORUS_SIZE_MS*_OUTPUT_SAMPLE_RATE)/1000)
+#define CHORUS_R_SIZE CHORUS_L_SIZE
+#define CHORUS_SHAPE_SIZE 128
+#define CHORUS_DELAY_MS 10
+
+#define CHORUS_MAX_TYPE 4 // any Chorus numbers larger than this are invalid
+
+typedef struct
+{
+ EAS_I16 m_nRate;
+ EAS_I16 m_nDepth;
+ EAS_I16 m_nLevel;
+
+} S_CHORUS_PRESET;
+
+typedef struct
+{
+ S_CHORUS_PRESET m_sPreset[CHORUS_MAX_TYPE]; //array of presets
+
+} S_CHORUS_PRESET_BANK;
+
+/* parameters for each Chorus */
+typedef struct
+{
+ EAS_I32 lfoLPhase;
+ EAS_I32 lfoRPhase;
+ EAS_I16 chorusIndexL;
+ EAS_I16 chorusIndexR;
+ EAS_U16 chorusTapPosition;
+
+ EAS_I16 m_nRate;
+ EAS_I16 m_nDepth;
+ EAS_I16 m_nLevel;
+
+ //delay lines used by the chorus, longer would sound better
+ EAS_PCM chorusDelayL[CHORUS_L_SIZE];
+ EAS_PCM chorusDelayR[CHORUS_R_SIZE];
+
+ EAS_BOOL bypass;
+ EAS_I8 preset;
+
+ EAS_I16 m_nCurrentChorus; // preset number for current Chorus
+ EAS_I16 m_nNextChorus; // preset number for next Chorus
+
+ S_CHORUS_PRESET pPreset;
+
+ S_CHORUS_PRESET_BANK m_sPreset;
+
+} S_CHORUS_OBJECT;
+
+
+/*----------------------------------------------------------------------------
+ * WeightedTap()
+ *----------------------------------------------------------------------------
+ * Purpose: Does fractional array look-up using linear interpolation
+ *
+ * first convert indexDesired to actual desired index by taking into account indexReference
+ * then do linear interpolation between two actual samples using fractional part
+ *
+ * Inputs:
+ * array: pointer to array of signed 16 bit values, typically either PCM data or control data
+ * indexReference: the circular buffer relative offset
+ * indexDesired: the fractional index we are looking up (16 bits index + 16 bits fraction)
+ * indexLimit: the total size of the array, used to compute buffer wrap
+ *
+ * Outputs:
+ * Value from the input array, linearly interpolated between two actual data values
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_I16 WeightedTap(const EAS_I16 *array, EAS_I16 indexReference, EAS_I32 indexDesired, EAS_I16 indexLimit);
+
+/*----------------------------------------------------------------------------
+ * ChorusReadInPresets()
+ *----------------------------------------------------------------------------
+ * Purpose: sets global Chorus preset bank to defaults
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT ChorusReadInPresets(S_CHORUS_OBJECT *pChorusData);
+
+/*----------------------------------------------------------------------------
+ * ChorusUpdate
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Update the Chorus preset parameters as required
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ * - chorus paramters will be changed
+ * - m_nCurrentChorus := m_nNextChorus
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT ChorusUpdate(S_CHORUS_OBJECT* pChorusData);
+
+#endif /* #ifndef _EAS_CHORUSDATA_H */
+
+
diff --git a/arm-wt-22k/lib_src/eas_ctype.h b/arm-wt-22k/lib_src/eas_ctype.h
new file mode 100644
index 0000000..8503870
--- /dev/null
+++ b/arm-wt-22k/lib_src/eas_ctype.h
@@ -0,0 +1,41 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_ctype.h
+ *
+ * Contents and purpose:
+ * This is a replacement for the CRT ctype.h functions. These
+ * functions are currently ASCII only, but eventually, we will want
+ * to support wide-characters for localization.
+ *
+ * Copyright (c) 2005 Sonic Network Inc.
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 429 $
+ * $Date: 2006-10-19 23:50:15 -0700 (Thu, 19 Oct 2006) $
+ *----------------------------------------------------------------------------
+*/
+
+#ifndef _EAS_CTYPE_H
+#define _EAS_CTYPE_H
+
+EAS_INLINE EAS_I8 IsDigit (EAS_I8 c) { return ((c >= '0') && (c <= '9')); }
+EAS_INLINE EAS_I8 IsSpace (EAS_I8 c) { return (((c >= 9) && (c <= 13)) || (c == ' ')); }
+EAS_INLINE EAS_I8 ToUpper (EAS_I8 c) { if ((c >= 'a') && (c <= 'z')) return c & ~0x20; else return c; }
+EAS_INLINE EAS_I8 ToLower (EAS_I8 c) { if ((c >= 'A') && (c <= 'Z')) return c |= 0x20; else return c; }
+
+#endif
+
diff --git a/arm-wt-22k/lib_src/eas_data.c b/arm-wt-22k/lib_src/eas_data.c
new file mode 100644
index 0000000..bb60ef2
--- /dev/null
+++ b/arm-wt-22k/lib_src/eas_data.c
@@ -0,0 +1,37 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_data.c
+ *
+ * Contents and purpose:
+ * Contains a data allocation for synthesizer
+ *
+ * Copyright Sonic Network Inc. 2004
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 547 $
+ * $Date: 2007-01-31 16:30:17 -0800 (Wed, 31 Jan 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+// includes
+#include "eas_data.h"
+
+// globals
+S_EAS_DATA eas_Data;
+S_VOICE_MGR eas_Synth;
+S_SYNTH eas_MIDI;
+
diff --git a/arm-wt-22k/lib_src/eas_data.h b/arm-wt-22k/lib_src/eas_data.h
new file mode 100644
index 0000000..28957fd
--- /dev/null
+++ b/arm-wt-22k/lib_src/eas_data.h
@@ -0,0 +1,133 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_data.h
+ *
+ * Contents and purpose:
+ * This header defines all types, to support dynamic allocation of the
+ * memory resources needed for persistent EAS data.
+ *
+ * Copyright 2004 Sonic Network Inc.
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 842 $
+ * $Date: 2007-08-23 14:32:31 -0700 (Thu, 23 Aug 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+#ifndef _EAS_DATA_H
+#define _EAS_DATA_H
+
+#define JET_INTERFACE
+
+#include "eas_types.h"
+#include "eas_synthcfg.h"
+#include "eas.h"
+#include "eas_audioconst.h"
+#include "eas_sndlib.h"
+#include "eas_pcm.h"
+#include "eas_pcmdata.h"
+#include "eas_synth.h"
+#include "eas_miditypes.h"
+#include "eas_effects.h"
+
+#ifdef AUX_MIXER
+#include "eas_auxmixdata.h"
+#endif
+
+#ifdef JET_INTERFACE
+#include "jet.h"
+#endif
+
+#ifdef _METRICS_ENABLED
+#include "eas_perf.h"
+#endif
+
+#ifndef MAX_NUMBER_STREAMS
+#define MAX_NUMBER_STREAMS 4
+#endif
+
+/* flags for S_EAS_STREAM */
+#define STREAM_FLAGS_PARSED 1
+#define STREAM_FLAGS_PAUSE 2
+#define STREAM_FLAGS_LOCATE 4
+#define STREAM_FLAGS_RESUME 8
+
+/* structure for parsing a stream */
+typedef struct s_eas_stream_tag
+{
+ void *pParserModule;
+ EAS_U32 time;
+ EAS_U32 frameLength;
+ EAS_I32 repeatCount;
+ EAS_VOID_PTR handle;
+ EAS_U8 volume;
+ EAS_BOOL8 streamFlags;
+} S_EAS_STREAM;
+
+/* default master volume is -10dB */
+#define DEFAULT_VOLUME 90
+#define DEFAULT_STREAM_VOLUME 100
+#define DEFAULT_STREAM_GAIN 14622
+
+/* 10 dB of boost available for individual parsers */
+#define STREAM_VOLUME_HEADROOM 10
+
+/* amalgamated persistent data type */
+typedef struct s_eas_data_tag
+{
+#ifdef _CHECKED_BUILD
+ EAS_U32 handleCheck;
+#endif
+ EAS_HW_DATA_HANDLE hwInstData;
+
+ S_EFFECTS_MODULE effectsModules[NUM_EFFECTS_MODULES];
+
+#ifdef _METRICS_ENABLED
+ S_METRICS_INTERFACE *pMetricsModule;
+ EAS_VOID_PTR pMetricsData;
+#endif
+
+ EAS_I32 *pMixBuffer;
+ EAS_PCM *pOutputAudioBuffer;
+
+#ifdef AUX_MIXER
+ S_EAS_AUX_MIXER auxMixer;
+#endif
+
+#ifdef _MAXIMIZER_ENABLED
+ EAS_VOID_PTR pMaximizerData;
+#endif
+
+ S_EAS_STREAM streams[MAX_NUMBER_STREAMS];
+
+ S_PCM_STATE *pPCMStreams;
+
+ S_VOICE_MGR *pVoiceMgr;
+
+#ifdef JET_INTERFACE
+ JET_DATA_HANDLE jetHandle;
+#endif
+
+ EAS_U32 renderTime;
+ EAS_I16 masterGain;
+ EAS_U8 masterVolume;
+ EAS_BOOL8 staticMemoryModel;
+ EAS_BOOL8 searchHeaderFlag;
+} S_EAS_DATA;
+
+#endif
+
diff --git a/arm-wt-22k/lib_src/eas_dlssynth.c b/arm-wt-22k/lib_src/eas_dlssynth.c
new file mode 100644
index 0000000..c1fa1ef
--- /dev/null
+++ b/arm-wt-22k/lib_src/eas_dlssynth.c
@@ -0,0 +1,578 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_dlssynth.c
+ *
+ * Contents and purpose:
+ * Implements the Mobile DLS synthesizer.
+ *
+ * Copyright Sonic Network Inc. 2006
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 795 $
+ * $Date: 2007-08-01 00:14:45 -0700 (Wed, 01 Aug 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+// includes
+#include "eas_data.h"
+#include "eas_report.h"
+#include "eas_host.h"
+#include "eas_math.h"
+#include "eas_synth_protos.h"
+#include "eas_wtsynth.h"
+#include "eas_pan.h"
+#include "eas_mdls.h"
+#include "eas_dlssynth.h"
+
+#ifdef _METRICS_ENABLED
+#include "eas_perf.h"
+#endif
+
+static void DLS_UpdateEnvelope (S_SYNTH_VOICE *pVoice, S_SYNTH_CHANNEL *pChannel, const S_DLS_ENVELOPE *pEnvParams, EAS_I16 *pValue, EAS_I16 *pIncrement, EAS_U8 *pState);
+
+/*----------------------------------------------------------------------------
+ * DLS_MuteVoice()
+ *----------------------------------------------------------------------------
+ * Mute the voice using shutdown time from the DLS articulation data
+ *----------------------------------------------------------------------------
+*/
+void DLS_MuteVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum)
+{
+ S_WT_VOICE *pWTVoice;
+ const S_DLS_ARTICULATION *pDLSArt;
+
+ pWTVoice = &pVoiceMgr->wtVoices[voiceNum];
+ pDLSArt = &pSynth->pDLS->pDLSArticulations[pWTVoice->artIndex];
+
+ /* clear deferred action flags */
+ pVoice->voiceFlags &=
+ ~(VOICE_FLAG_DEFER_MIDI_NOTE_OFF |
+ VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF |
+ VOICE_FLAG_DEFER_MUTE);
+
+ /* set the envelope state */
+ pVoiceMgr->wtVoices[voiceNum].eg1State = eEnvelopeStateRelease;
+ pWTVoice->eg1Increment = pDLSArt->eg1ShutdownTime;
+ pVoiceMgr->wtVoices[voiceNum].eg2State = eEnvelopeStateRelease;
+ pWTVoice->eg2Increment = pDLSArt->eg2.releaseTime;
+}
+
+/*----------------------------------------------------------------------------
+ * DLS_ReleaseVoice()
+ *----------------------------------------------------------------------------
+ * Release the selected voice.
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pVoice) standard API, pVoice may be used by other synthesizers */
+void DLS_ReleaseVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum)
+{
+ S_WT_VOICE *pWTVoice;
+ const S_DLS_ARTICULATION *pDLSArt;
+
+ pWTVoice = &pVoiceMgr->wtVoices[voiceNum];
+ pDLSArt = &pSynth->pDLS->pDLSArticulations[pWTVoice->artIndex];
+
+ /* if still in attack phase, convert units to log */
+ /*lint -e{732} eg1Value is never negative */
+ /*lint -e{703} use shift for performance */
+ if (pWTVoice->eg1State == eEnvelopeStateAttack)
+ pWTVoice->eg1Value = (EAS_I16) ((EAS_flog2(pWTVoice->eg1Value) << 1) + 2048);
+
+ /* release EG1 */
+ pWTVoice->eg1State = eEnvelopeStateRelease;
+ pWTVoice->eg1Increment = pDLSArt->eg1.releaseTime;
+
+ /* release EG2 */
+ pWTVoice->eg2State = eEnvelopeStateRelease;
+ pWTVoice->eg2Increment = pDLSArt->eg2.releaseTime;
+}
+
+/*----------------------------------------------------------------------------
+ * DLS_SustainPedal()
+ *----------------------------------------------------------------------------
+ * The sustain pedal was just depressed. If the voice is still
+ * above the sustain level, catch the voice and continue holding.
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pChannel) pChannel reserved for future use */
+void DLS_SustainPedal (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, S_SYNTH_CHANNEL *pChannel, EAS_I32 voiceNum)
+{
+ S_WT_VOICE *pWTVoice;
+ const S_DLS_ARTICULATION *pDLSArt;
+
+ pWTVoice = &pVoiceMgr->wtVoices[voiceNum];
+ pDLSArt = &pSynth->pDLS->pDLSArticulations[pWTVoice->artIndex];
+
+ /* don't catch the voice if below the sustain level */
+ if (pWTVoice->eg1Value < pDLSArt->eg1.sustainLevel)
+ return;
+
+ /* defer releasing this note until the damper pedal is off */
+ pWTVoice->eg1State = eEnvelopeStateDecay;
+ pVoice->voiceState = eVoiceStatePlay;
+ pVoice->voiceFlags |= VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF;
+
+#ifdef _DEBUG_SYNTH
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "DLS_SustainPedal: defer note off because sustain pedal is on\n"); */ }
+#endif
+}
+
+/*----------------------------------------------------------------------------
+ * DLS_UpdatePhaseInc()
+ *----------------------------------------------------------------------------
+ * Calculate the oscillator phase increment for the next frame
+ *----------------------------------------------------------------------------
+*/
+static EAS_I32 DLS_UpdatePhaseInc (S_WT_VOICE *pWTVoice, const S_DLS_ARTICULATION *pDLSArt, S_SYNTH_CHANNEL *pChannel, EAS_I32 pitchCents)
+{
+ EAS_I32 temp;
+
+ /* start with base mod LFO modulation */
+ temp = pDLSArt->modLFOToPitch;
+
+ /* add mod wheel effect */
+ /*lint -e{702} use shift for performance */
+ temp += ((pDLSArt->modLFOCC1ToPitch * pChannel->modWheel) >> 7);
+
+ /* add channel pressure effect */
+ /*lint -e{702} use shift for performance */
+ temp += ((pDLSArt->modLFOChanPressToPitch * pChannel->channelPressure) >> 7);
+
+ /* add total mod LFO effect */
+ pitchCents += FMUL_15x15(temp, pWTVoice->modLFO.lfoValue);
+
+ /* start with base vib LFO modulation */
+ temp = pDLSArt->vibLFOToPitch;
+
+ /* add mod wheel effect */
+ /*lint -e{702} use shift for performance */
+ temp += ((pDLSArt->vibLFOCC1ToPitch * pChannel->modWheel) >> 7);
+
+ /* add channel pressure effect */
+ /*lint -e{702} use shift for performance */
+ temp += ((pDLSArt->vibLFOChanPressToPitch * pChannel->channelPressure) >> 7);
+
+ /* add total vibrato LFO effect */
+ pitchCents += FMUL_15x15(temp, pWTVoice->vibLFO.lfoValue);
+
+ /* add EG2 effect */
+ pitchCents += FMUL_15x15(pDLSArt->eg2ToPitch, pWTVoice->eg2Value);
+
+ /* convert from cents to linear phase increment */
+ return EAS_Calculate2toX(pitchCents);
+}
+
+/*----------------------------------------------------------------------------
+ * DLS_UpdateGain()
+ *----------------------------------------------------------------------------
+ * Calculate the gain for the next frame
+ *----------------------------------------------------------------------------
+*/
+static EAS_I32 DLS_UpdateGain (S_WT_VOICE *pWTVoice, const S_DLS_ARTICULATION *pDLSArt, S_SYNTH_CHANNEL *pChannel, EAS_I32 gain, EAS_U8 velocity)
+{
+ EAS_I32 temp;
+
+ /* start with base mod LFO modulation */
+ temp = pDLSArt->modLFOToGain;
+
+ /* add mod wheel effect */
+ /*lint -e{702} use shift for performance */
+ temp += ((pDLSArt->modLFOCC1ToGain * pChannel->modWheel) >> 7);
+
+ /* add channel pressure effect */
+ /*lint -e{702} use shift for performance */
+ temp += ((pDLSArt->modLFOChanPressToGain * pChannel->channelPressure) >> 7);
+
+ /* add total mod LFO effect */
+ gain += FMUL_15x15(temp, pWTVoice->modLFO.lfoValue);
+ if (gain > 0)
+ gain = 0;
+
+ /* convert to linear gain including EG1 */
+ if (pWTVoice->eg1State != eEnvelopeStateAttack)
+ {
+ gain = (DLS_GAIN_FACTOR * gain) >> DLS_GAIN_SHIFT;
+ /*lint -e{702} use shift for performance */
+#if 1
+ gain += (pWTVoice->eg1Value - 32767) >> 1;
+ gain = EAS_LogToLinear16(gain);
+#else
+ gain = EAS_LogToLinear16(gain);
+ temp = EAS_LogToLinear16((pWTVoice->eg1Value - 32767) >> 1);
+ gain = FMUL_15x15(gain, temp);
+#endif
+ }
+ else
+ {
+ gain = (DLS_GAIN_FACTOR * gain) >> DLS_GAIN_SHIFT;
+ gain = EAS_LogToLinear16(gain);
+ gain = FMUL_15x15(gain, pWTVoice->eg1Value);
+ }
+
+ /* include MIDI channel gain */
+ gain = FMUL_15x15(gain, pChannel->staticGain);
+
+ /* include velocity */
+ if (pDLSArt->filterQandFlags & FLAG_DLS_VELOCITY_SENSITIVE)
+ {
+ temp = velocity << 8;
+ temp = FMUL_15x15(temp, temp);
+ gain = FMUL_15x15(gain, temp);
+ }
+
+ /* return gain */
+ return gain;
+}
+
+/*----------------------------------------------------------------------------
+ * DLS_UpdateFilter()
+ *----------------------------------------------------------------------------
+ * Update the Filter parameters
+ *----------------------------------------------------------------------------
+*/
+static void DLS_UpdateFilter (S_SYNTH_VOICE *pVoice, S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pIntFrame, S_SYNTH_CHANNEL *pChannel, const S_DLS_ARTICULATION *pDLSArt)
+{
+ EAS_I32 cutoff;
+ EAS_I32 temp;
+
+ /* no need to calculate filter coefficients if it is bypassed */
+ if (pDLSArt->filterCutoff == DEFAULT_DLS_FILTER_CUTOFF_FREQUENCY)
+ {
+ pIntFrame->frame.k = 0;
+ return;
+ }
+
+ /* start with base cutoff frequency */
+ cutoff = pDLSArt->filterCutoff;
+
+ /* get base mod LFO modulation */
+ temp = pDLSArt->modLFOToFc;
+
+ /* add mod wheel effect */
+ /*lint -e{702} use shift for performance */
+ temp += ((pDLSArt->modLFOCC1ToFc * pChannel->modWheel) >> 7);
+
+ /* add channel pressure effect */
+ /*lint -e{702} use shift for performance */
+ temp += ((pDLSArt->modLFOChanPressToFc* pChannel->channelPressure) >> 7);
+
+ /* add total mod LFO effect */
+ cutoff += FMUL_15x15(temp, pWTVoice->modLFO.lfoValue);
+
+ /* add EG2 effect */
+ cutoff += FMUL_15x15(pWTVoice->eg2Value, pDLSArt->eg2ToFc);
+
+ /* add velocity effect */
+ /*lint -e{702} use shift for performance */
+ cutoff += (pVoice->velocity * pDLSArt->velToFc) >> 7;
+
+ /* add velocity effect */
+ /*lint -e{702} use shift for performance */
+ cutoff += (pVoice->note * pDLSArt->keyNumToFc) >> 7;
+
+ /* subtract the A5 offset and the sampling frequency */
+ cutoff -= FILTER_CUTOFF_FREQ_ADJUST + A5_PITCH_OFFSET_IN_CENTS;
+
+ /* limit the cutoff frequency */
+ if (cutoff > FILTER_CUTOFF_MAX_PITCH_CENTS)
+ cutoff = FILTER_CUTOFF_MAX_PITCH_CENTS;
+ else if (cutoff < FILTER_CUTOFF_MIN_PITCH_CENTS)
+ cutoff = FILTER_CUTOFF_MIN_PITCH_CENTS;
+
+ WT_SetFilterCoeffs(pIntFrame, cutoff, pDLSArt->filterQandFlags & FILTER_Q_MASK);
+}
+
+/*----------------------------------------------------------------------------
+ * DLS_StartVoice()
+ *----------------------------------------------------------------------------
+ * Start up a DLS voice
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT DLS_StartVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_U16 regionIndex)
+{
+ S_WT_VOICE *pWTVoice;
+ const S_DLS_REGION *pDLSRegion;
+ const S_DLS_ARTICULATION *pDLSArt;
+ S_SYNTH_CHANNEL *pChannel;
+
+#ifdef _DEBUG_SYNTH
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "DLS_StartVoice: Voice %ld; Region %d\n", (EAS_I32) (pVoice - pVoiceMgr->voices), regionIndex); */ }
+#endif
+
+ pWTVoice = &pVoiceMgr->wtVoices[voiceNum];
+ pChannel = &pSynth->channels[pVoice->channel & 15];
+ pDLSRegion = &pSynth->pDLS->pDLSRegions[regionIndex & REGION_INDEX_MASK];
+ pWTVoice->artIndex = pDLSRegion->wtRegion.artIndex;
+ pDLSArt = &pSynth->pDLS->pDLSArticulations[pWTVoice->artIndex];
+
+ /* initialize the envelopes */
+ pWTVoice->eg1State = eEnvelopeStateInit;
+ DLS_UpdateEnvelope(pVoice, pChannel, &pDLSArt->eg1, &pWTVoice->eg1Value, &pWTVoice->eg1Increment, &pWTVoice->eg1State);
+ pWTVoice->eg2State = eEnvelopeStateInit;
+ DLS_UpdateEnvelope(pVoice, pChannel, &pDLSArt->eg2, &pWTVoice->eg2Value, &pWTVoice->eg2Increment, &pWTVoice->eg2State);
+
+ /* initialize the LFOs */
+ pWTVoice->modLFO.lfoValue = 0;
+ pWTVoice->modLFO.lfoPhase = pDLSArt->modLFO.lfoDelay;
+ pWTVoice->vibLFO.lfoValue = 0;
+ pWTVoice->vibLFO.lfoPhase = pDLSArt->vibLFO.lfoDelay;
+
+ /* initalize the envelopes and calculate initial gain */
+ DLS_UpdateEnvelope(pVoice, pChannel, &pDLSArt->eg1, &pWTVoice->eg1Value, &pWTVoice->eg1Increment, &pWTVoice->eg1State);
+ DLS_UpdateEnvelope(pVoice, pChannel, &pDLSArt->eg2, &pWTVoice->eg2Value, &pWTVoice->eg2Increment, &pWTVoice->eg2State);
+ pVoice->gain = (EAS_I16) DLS_UpdateGain(pWTVoice, pDLSArt, pChannel, pDLSRegion->wtRegion.gain, pVoice->velocity);
+
+#if (NUM_OUTPUT_CHANNELS == 2)
+ EAS_CalcPanControl((EAS_INT) pChannel->pan - 64 + (EAS_INT) pDLSArt->pan, &pWTVoice->gainLeft, &pWTVoice->gainRight);
+#endif
+
+ /* initialize the filter states */
+ pWTVoice->filter.z1 = 0;
+ pWTVoice->filter.z2 = 0;
+
+ /* initialize the oscillator */
+ pWTVoice->phaseAccum = (EAS_U32) pSynth->pDLS->pDLSSamples + pSynth->pDLS->pDLSSampleOffsets[pDLSRegion->wtRegion.waveIndex];
+ if (pDLSRegion->wtRegion.region.keyGroupAndFlags & REGION_FLAG_IS_LOOPED)
+ {
+ pWTVoice->loopStart = pWTVoice->phaseAccum + pDLSRegion->wtRegion.loopStart;
+ pWTVoice->loopEnd = pWTVoice->phaseAccum + pDLSRegion->wtRegion.loopEnd - 1;
+ }
+ else
+ pWTVoice->loopStart = pWTVoice->loopEnd = pWTVoice->phaseAccum + pSynth->pDLS->pDLSSampleLen[pDLSRegion->wtRegion.waveIndex] - 1;
+
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * DLS_UpdateVoice()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Synthesize a block of samples for the given voice.
+ * Use linear interpolation.
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ *
+ * Outputs:
+ * number of samples actually written to buffer
+ *
+ * Side Effects:
+ * - samples are added to the presently free buffer
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_BOOL DLS_UpdateVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_I32 *pMixBuffer, EAS_I32 numSamples)
+{
+ S_WT_VOICE *pWTVoice;
+ S_SYNTH_CHANNEL *pChannel;
+ const S_DLS_REGION *pDLSRegion;
+ const S_DLS_ARTICULATION *pDLSArt;
+ S_WT_INT_FRAME intFrame;
+ EAS_I32 temp;
+ EAS_BOOL done = EAS_FALSE;
+
+ /* establish pointers to critical data */
+ pWTVoice = &pVoiceMgr->wtVoices[voiceNum];
+ pDLSRegion = &pSynth->pDLS->pDLSRegions[pVoice->regionIndex & REGION_INDEX_MASK];
+ pChannel = &pSynth->channels[pVoice->channel & 15];
+ pDLSArt = &pSynth->pDLS->pDLSArticulations[pWTVoice->artIndex];
+
+ /* update the envelopes */
+ DLS_UpdateEnvelope(pVoice, pChannel, &pDLSArt->eg1, &pWTVoice->eg1Value, &pWTVoice->eg1Increment, &pWTVoice->eg1State);
+ DLS_UpdateEnvelope(pVoice, pChannel, &pDLSArt->eg2, &pWTVoice->eg2Value, &pWTVoice->eg2Increment, &pWTVoice->eg2State);
+
+ /* update the LFOs using the EAS synth function */
+ WT_UpdateLFO(&pWTVoice->modLFO, pDLSArt->modLFO.lfoFreq);
+ WT_UpdateLFO(&pWTVoice->vibLFO, pDLSArt->vibLFO.lfoFreq);
+
+ /* calculate base frequency */
+ temp = pDLSArt->tuning + pChannel->staticPitch + pDLSRegion->wtRegion.tuning +
+ (((EAS_I32) pVoice->note * (EAS_I32) pDLSArt->keyNumToPitch) >> 7);
+
+ /* don't transpose rhythm channel */
+ if ((pChannel ->channelFlags & CHANNEL_FLAG_RHYTHM_CHANNEL) == 0)
+ temp += pSynth->globalTranspose * 100;
+
+ /* calculate phase increment including modulation effects */
+ intFrame.frame.phaseIncrement = DLS_UpdatePhaseInc(pWTVoice, pDLSArt, pChannel, temp);
+
+ /* calculate gain including modulation effects */
+ intFrame.frame.gainTarget = DLS_UpdateGain(pWTVoice, pDLSArt, pChannel, pDLSRegion->wtRegion.gain, pVoice->velocity);
+ intFrame.prevGain = pVoice->gain;
+
+ DLS_UpdateFilter(pVoice, pWTVoice, &intFrame, pChannel, pDLSArt);
+
+ /* call into engine to generate samples */
+ intFrame.pAudioBuffer = pVoiceMgr->voiceBuffer;
+ intFrame.pMixBuffer = pMixBuffer;
+ intFrame.numSamples = numSamples;
+ if (numSamples < 0)
+ return EAS_FALSE;
+
+ /* check for end of sample */
+ if ((pWTVoice->loopStart != WT_NOISE_GENERATOR) && (pWTVoice->loopStart == pWTVoice->loopEnd))
+ done = WT_CheckSampleEnd(pWTVoice, &intFrame, EAS_FALSE);
+
+ WT_ProcessVoice(pWTVoice, &intFrame);
+
+ /* clear flag */
+ pVoice->voiceFlags &= ~VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET;
+
+ /* if the update interval has elapsed, then force the current gain to the next
+ * gain since we never actually reach the next gain when ramping -- we just get
+ * very close to the target gain.
+ */
+ pVoice->gain = (EAS_I16) intFrame.frame.gainTarget;
+
+ /* if voice has finished, set flag for voice manager */
+ if ((pVoice->voiceState != eVoiceStateStolen) && (pWTVoice->eg1State == eEnvelopeStateMuted))
+ done = EAS_TRUE;
+
+ return done;
+}
+
+/*----------------------------------------------------------------------------
+ * DLS_UpdateEnvelope()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Synthesize a block of samples for the given voice.
+ * Use linear interpolation.
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ *
+ * Outputs:
+ * number of samples actually written to buffer
+ *
+ * Side Effects:
+ * - samples are added to the presently free buffer
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pChannel) pChannel not used in this instance */
+static void DLS_UpdateEnvelope (S_SYNTH_VOICE *pVoice, S_SYNTH_CHANNEL *pChannel, const S_DLS_ENVELOPE *pEnvParams, EAS_I16 *pValue, EAS_I16 *pIncrement, EAS_U8 *pState)
+{
+ EAS_I32 temp;
+
+ switch (*pState)
+ {
+ /* initial state */
+ case eEnvelopeStateInit:
+ *pState = eEnvelopeStateDelay;
+ *pValue = 0;
+ *pIncrement = pEnvParams->delayTime;
+ if (*pIncrement != 0)
+ return;
+ /*lint -e{825} falls through to next case */
+
+ case eEnvelopeStateDelay:
+ if (*pIncrement)
+ {
+ *pIncrement = *pIncrement - 1;
+ return;
+ }
+
+ /* calculate attack rate */
+ *pState = eEnvelopeStateAttack;
+ if (pEnvParams->attackTime != ZERO_TIME_IN_CENTS)
+ {
+ /*lint -e{702} use shift for performance */
+ temp = pEnvParams->attackTime + ((pEnvParams->velToAttack * pVoice->velocity) >> 7);
+ *pIncrement = ConvertRate(temp);
+ return;
+ }
+
+ *pValue = SYNTH_FULL_SCALE_EG1_GAIN;
+ /*lint -e{825} falls through to next case */
+
+ case eEnvelopeStateAttack:
+ if (*pValue < SYNTH_FULL_SCALE_EG1_GAIN)
+ {
+ temp = *pValue + *pIncrement;
+ *pValue = (EAS_I16) (temp < SYNTH_FULL_SCALE_EG1_GAIN ? temp : SYNTH_FULL_SCALE_EG1_GAIN);
+ return;
+ }
+
+ /* calculate hold time */
+ *pState = eEnvelopeStateHold;
+ if (pEnvParams->holdTime != ZERO_TIME_IN_CENTS)
+ {
+ /*lint -e{702} use shift for performance */
+ temp = pEnvParams->holdTime + ((pEnvParams->keyNumToHold * pVoice->note) >> 7);
+ *pIncrement = ConvertDelay(temp);
+ return;
+ }
+ else
+ *pIncrement = 0;
+ /*lint -e{825} falls through to next case */
+
+ case eEnvelopeStateHold:
+ if (*pIncrement)
+ {
+ *pIncrement = *pIncrement - 1;
+ return;
+ }
+
+ /* calculate decay rate */
+ *pState = eEnvelopeStateDecay;
+ if (pEnvParams->decayTime != ZERO_TIME_IN_CENTS)
+ {
+ /*lint -e{702} use shift for performance */
+ temp = pEnvParams->decayTime + ((pEnvParams->keyNumToDecay * pVoice->note) >> 7);
+ *pIncrement = ConvertRate(temp);
+ return;
+ }
+
+// *pValue = pEnvParams->sustainLevel;
+ /*lint -e{825} falls through to next case */
+
+ case eEnvelopeStateDecay:
+ if (*pValue > pEnvParams->sustainLevel)
+ {
+ temp = *pValue - *pIncrement;
+ *pValue = (EAS_I16) (temp > pEnvParams->sustainLevel ? temp : pEnvParams->sustainLevel);
+ return;
+ }
+
+ *pState = eEnvelopeStateSustain;
+ *pValue = pEnvParams->sustainLevel;
+ /*lint -e{825} falls through to next case */
+
+ case eEnvelopeStateSustain:
+ return;
+
+ case eEnvelopeStateRelease:
+ temp = *pValue - *pIncrement;
+ if (temp <= 0)
+ {
+ *pState = eEnvelopeStateMuted;
+ *pValue = 0;
+ }
+ else
+ *pValue = (EAS_I16) temp;
+ break;
+
+ case eEnvelopeStateMuted:
+ *pValue = 0;
+ return;
+
+ default:
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Envelope in invalid state %d\n", *pState); */ }
+ break;
+ }
+}
+
diff --git a/arm-wt-22k/lib_src/eas_dlssynth.h b/arm-wt-22k/lib_src/eas_dlssynth.h
new file mode 100644
index 0000000..0dab41e
--- /dev/null
+++ b/arm-wt-22k/lib_src/eas_dlssynth.h
@@ -0,0 +1,41 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_dlssynth.h
+ *
+ * Contents and purpose:
+ * Implements the Mobile DLS synthesizer.
+ *
+ * Copyright Sonic Network Inc. 2006
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 143 $
+ * $Date: 2006-07-17 14:09:35 -0700 (Mon, 17 Jul 2006) $
+ *----------------------------------------------------------------------------
+*/
+
+#ifndef _EAS_DLSSYNTH_H
+#define _EAS_DLSSYNTH_H
+
+/* prototypes */
+void DLS_MuteVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum);
+void DLS_ReleaseVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum);
+void DLS_SustainPedal (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, S_SYNTH_CHANNEL *pChannel, EAS_I32 voiceNum);
+EAS_RESULT DLS_StartVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_U16 regionIndex);
+EAS_BOOL DLS_UpdateVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_I32 *pMixBuffer, EAS_I32 numSamples);
+
+#endif
+
diff --git a/arm-wt-22k/lib_src/eas_effects.h b/arm-wt-22k/lib_src/eas_effects.h
new file mode 100644
index 0000000..01e64c0
--- /dev/null
+++ b/arm-wt-22k/lib_src/eas_effects.h
@@ -0,0 +1,61 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_effects.h
+ *
+ * Contents and purpose:
+ * Defines a generic effects interface.
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 82 $
+ * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $
+ *----------------------------------------------------------------------------
+*/
+
+#ifndef _EAS_EFFECTS_H
+#define _EAS_EFFECTS_H
+
+#include "eas_types.h"
+
+typedef struct
+{
+ EAS_RESULT (*pfInit)(EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData);
+ void (*pfProcess)(EAS_VOID_PTR pInstData, EAS_PCM *in, EAS_PCM *out, EAS_I32 numSamples);
+ EAS_RESULT (*pfShutdown)(EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData);
+ EAS_RESULT (*pFGetParam)(EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue);
+ EAS_RESULT (*pFSetParam)(EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value);
+} S_EFFECTS_INTERFACE;
+
+typedef struct
+{
+ EAS_RESULT (*pfInit)(EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData);
+ void (*pfProcess)(EAS_VOID_PTR pInstData, EAS_I32 *in, EAS_I32 *out, EAS_I32 numSamples);
+ EAS_RESULT (*pfShutdown)(EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData);
+ EAS_RESULT (*pFGetParam)(EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue);
+ EAS_RESULT (*pFSetParam)(EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value);
+} S_EFFECTS32_INTERFACE;
+
+/* mixer instance data */
+typedef struct
+{
+ S_EFFECTS_INTERFACE *effect;
+ EAS_VOID_PTR effectData;
+} S_EFFECTS_MODULE;
+
+#endif /* end _EAS_EFFECTS_H */
+
diff --git a/arm-wt-22k/lib_src/eas_flog.c b/arm-wt-22k/lib_src/eas_flog.c
new file mode 100644
index 0000000..647da2f
--- /dev/null
+++ b/arm-wt-22k/lib_src/eas_flog.c
@@ -0,0 +1,96 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_flog2.c
+ *
+ * Contents and purpose:
+ * Fixed point square root
+ *
+ *
+ * Copyright (c) 2006 Sonic Network Inc.
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision$
+ * $Date$
+ *----------------------------------------------------------------------------
+*/
+
+#include "eas_types.h"
+#include "eas_math.h"
+
+#define MANTISSA_SHIFT 27
+#define MANTISSA_MASK 0x0000000f
+#define MANTISSA_LSB_SHIFT 7
+#define MANTISSA_LSB_MASK 0x000fffff
+#define LOG_EXPONENT_SHIFT 10
+#define INTERPOLATION_SHIFT 20
+#define MAX_NEGATIVE (-2147483647-1)
+
+/* log lookup table */
+static const EAS_U16 eas_log2_table[] =
+{
+ 0, 90, 174, 254, 330, 402, 470, 536,
+ 599, 659, 717, 773, 827, 879, 929, 977,
+ 1024
+};
+
+/*----------------------------------------------------------------------------
+ * EAS_flog2()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Calculates the log2 of a 32-bit fixed point value
+ *
+ * Inputs:
+ * n = value of interest
+ *
+ * Outputs:
+ * returns the log2 of n
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_I32 EAS_flog2 (EAS_U32 n)
+{
+ EAS_U32 exp;
+ EAS_U32 interp;
+
+ /* check for error condition */
+ if (n == 0)
+ return MAX_NEGATIVE;
+
+ /* find exponent */
+ for (exp = 31; exp > 0; exp--)
+ {
+ /* shift until we get a 1 bit in bit 31 */
+ if ((n & (EAS_U32) MAX_NEGATIVE) != 0)
+ break;
+ n <<= 1;
+ }
+ /*lint -e{701} use shift for performance */
+ exp <<= LOG_EXPONENT_SHIFT;
+
+ /* get the least significant bits for interpolation */
+ interp = (n >> MANTISSA_LSB_SHIFT) & MANTISSA_LSB_MASK;
+
+ /* get the most significant bits for mantissa lookup */
+ n = (n >> MANTISSA_SHIFT) & MANTISSA_MASK;
+
+ /* interpolate mantissa */
+ interp = ((eas_log2_table[n+1] - eas_log2_table[n]) * interp) >> INTERPOLATION_SHIFT;
+ exp += eas_log2_table[n] + interp;
+
+ return (EAS_I32) exp;
+}
+
diff --git a/arm-wt-22k/lib_src/eas_ima_tables.c b/arm-wt-22k/lib_src/eas_ima_tables.c
new file mode 100644
index 0000000..56bd1eb
--- /dev/null
+++ b/arm-wt-22k/lib_src/eas_ima_tables.c
@@ -0,0 +1,54 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_ima_tables.c
+ *
+ * Contents and purpose:
+ * Contains the constant tables for IMA encode/decode
+ *
+ * Copyright (c) 2005 Sonic Network Inc.
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 760 $
+ * $Date: 2007-07-17 23:09:36 -0700 (Tue, 17 Jul 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+#include "eas_types.h"
+
+/*----------------------------------------------------------------------------
+ * ADPCM decode tables
+ *----------------------------------------------------------------------------
+*/
+const EAS_I16 imaIndexTable[16] =
+{
+ -1, -1, -1, -1, 2, 4, 6, 8,
+ -1, -1, -1, -1, 2, 4, 6, 8
+};
+
+const EAS_I16 imaStepSizeTable[89] =
+{
+ 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
+ 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
+ 50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
+ 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
+ 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
+ 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
+ 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
+ 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
+ 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
+};
+
diff --git a/arm-wt-22k/lib_src/eas_imaadpcm.c b/arm-wt-22k/lib_src/eas_imaadpcm.c
new file mode 100644
index 0000000..68bf257
--- /dev/null
+++ b/arm-wt-22k/lib_src/eas_imaadpcm.c
@@ -0,0 +1,368 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_imaadpcm.c
+ *
+ * Contents and purpose:
+ * Implements the IMA ADPCM decoder
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 847 $
+ * $Date: 2007-08-27 21:30:08 -0700 (Mon, 27 Aug 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+#include "eas_data.h"
+#include "eas_host.h"
+#include "eas_pcm.h"
+#include "eas_math.h"
+#include "eas_report.h"
+
+// #define _DEBUG_IMA_ADPCM_LOCATE
+
+/*----------------------------------------------------------------------------
+ * externs
+ *----------------------------------------------------------------------------
+*/
+extern const EAS_I16 imaIndexTable[];
+extern const EAS_I16 imaStepSizeTable[];
+
+/*----------------------------------------------------------------------------
+ * prototypes
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT IMADecoderInit (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState);
+static EAS_RESULT IMADecoderSample (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState);
+static void IMADecoderADPCM (S_DECODER_STATE *pState, EAS_U8 nibble);
+static EAS_RESULT IMADecoderLocate (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState, EAS_I32 time);
+
+/*----------------------------------------------------------------------------
+ * IMA ADPCM Decoder interface
+ *----------------------------------------------------------------------------
+*/
+const S_DECODER_INTERFACE IMADecoder =
+{
+ IMADecoderInit,
+ IMADecoderSample,
+ IMADecoderLocate
+};
+
+/*----------------------------------------------------------------------------
+ * IMADecoderInit()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Initializes the IMA ADPCM decoder
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pEASData) common decoder interface - pEASData not used */
+static EAS_RESULT IMADecoderInit (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState)
+{
+ pState->decoderL.step = 0;
+ pState->decoderR.step = 0;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * IMADecoderSample()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Decodes an IMA ADPCM sample
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT IMADecoderSample (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState)
+{
+ EAS_RESULT result;
+ EAS_I16 sTemp;
+
+ /* if high nibble, decode */
+ if (pState->hiNibble)
+ {
+ IMADecoderADPCM(&pState->decoderL, (EAS_U8)(pState->srcByte >> 4));
+ pState->hiNibble = EAS_FALSE;
+ }
+
+ /* low nibble, need to fetch another byte */
+ else
+ {
+ /* check for loop */
+ if ((pState->bytesLeft == 0) && (pState->loopSamples != 0))
+ {
+ /* seek to start of loop */
+ if ((result = EAS_HWFileSeek(pEASData->hwInstData, pState->fileHandle, (EAS_I32) (pState->startPos + pState->loopLocation))) != EAS_SUCCESS)
+ return result;
+ pState->bytesLeft = pState->byteCount = (EAS_I32) pState->bytesLeftLoop;
+ pState->blockCount = 0;
+ pState->flags &= ~PCM_FLAGS_EMPTY;
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMADecoderSample: Rewind file to %d, bytesLeft = %d\n", pState->startPos, pState->bytesLeft); */ }
+ }
+
+ /* if start of block, fetch new predictor and step index */
+ if ((pState->blockSize != 0) && (pState->blockCount == 0) && (pState->bytesLeft != 0))
+ {
+
+ /* get predicted sample for left channel */
+ if ((result = EAS_HWGetWord(pEASData->hwInstData, pState->fileHandle, &sTemp, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+#ifdef _DEBUG_IMA_ADPCM
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Predictor: Was %d, now %d\n", pState->decoderL.acc, sTemp); */ }
+#endif
+ pState->decoderL.acc = pState->decoderL.x1 = sTemp;
+
+ /* get step index for left channel - upper 8 bits are reserved */
+ if ((result = EAS_HWGetWord(pEASData->hwInstData, pState->fileHandle, &sTemp, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+#ifdef _DEBUG_IMA_ADPCM
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Step: Was %d, now %d\n", pState->decoderL.step, sTemp); */ }
+#endif
+ pState->decoderL.step = sTemp & 0xff;
+
+ if (pState->flags & PCM_FLAGS_STEREO)
+ {
+ /* get predicted sample for right channel */
+ if ((result = EAS_HWGetWord(pEASData->hwInstData, pState->fileHandle, &sTemp, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+ pState->decoderR.acc = pState->decoderR.x1 = sTemp;
+
+ /* get step index for right channel - upper 8 bits are reserved */
+ if ((result = EAS_HWGetWord(pEASData->hwInstData, pState->fileHandle, &sTemp, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+#ifdef _DEBUG_IMA_ADPCM
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Step: Was %d, now %d\n", pState->decoderR.step, sTemp); */ }
+#endif
+ pState->decoderR.step = sTemp & 0xff;
+
+ pState->blockCount = pState->blockSize - 8;
+ pState->bytesLeft -= 8;
+ }
+ else
+ {
+ pState->blockCount = pState->blockSize - 4;
+ pState->bytesLeft -= 4;
+ }
+ }
+ else
+ {
+
+ /* get another ADPCM data pair */
+ if (pState->bytesLeft)
+ {
+
+ if ((result = EAS_HWGetByte(pEASData->hwInstData, pState->fileHandle, &pState->srcByte)) != EAS_SUCCESS)
+ return result;
+
+ /* decode the low nibble */
+ pState->bytesLeft--;
+ pState->blockCount--;
+ IMADecoderADPCM(&pState->decoderL, (EAS_U8)(pState->srcByte & 0x0f));
+
+ if (pState->flags & PCM_FLAGS_STEREO)
+ IMADecoderADPCM(&pState->decoderR, (EAS_U8)(pState->srcByte >> 4));
+ else
+ pState->hiNibble = EAS_TRUE;
+ }
+
+ /* out of ADPCM data, generate enough samples to fill buffer */
+ else
+ {
+ pState->decoderL.x1 = pState->decoderL.x0;
+ pState->decoderR.x1 = pState->decoderR.x0;
+ }
+ }
+ }
+
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * IMADecoderADPCM()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Decodes an IMA ADPCM sample
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static void IMADecoderADPCM (S_DECODER_STATE *pState, EAS_U8 nibble)
+{
+ EAS_INT delta;
+ EAS_INT stepSize;
+
+ /* get stepsize from table */
+ stepSize = imaStepSizeTable[pState->step];
+
+ /* delta = (abs(delta) + 0.5) * step / 4 */
+ delta = 0;
+ if (nibble & 4)
+ delta += stepSize;
+
+ if (nibble & 2)
+ /*lint -e{702} use shift for performance */
+ delta += stepSize >> 1;
+
+ if (nibble & 1)
+ /*lint -e{702} use shift for performance */
+ delta += stepSize >> 2;
+
+ /*lint -e{702} use shift for performance */
+ delta += stepSize >> 3;
+
+ /* integrate the delta */
+ if (nibble & 8)
+ pState->acc -= delta;
+ else
+ pState->acc += delta;
+
+ /* saturate */
+ if (pState->acc > 32767)
+ pState->acc = 32767;
+ if (pState->acc < -32768)
+ pState->acc = -32768;
+ pState->x1 = (EAS_PCM) pState->acc;
+
+ /* compute new step size */
+ pState->step += imaIndexTable[nibble];
+ if (pState->step < 0)
+ pState->step = 0;
+ if (pState->step > 88)
+ pState->step = 88;
+
+#ifdef _DEBUG_IMA_ADPCM
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "In=%u, Pred=%d, Step=%d\n", nibble, pState->acc, imaStepSizeTable[pState->step]); */ }
+#endif
+}
+
+/*----------------------------------------------------------------------------
+ * IMADecoderLocate()
+ *----------------------------------------------------------------------------
+ * Locate in an IMA ADPCM stream
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT IMADecoderLocate (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState, EAS_I32 time)
+{
+ EAS_RESULT result;
+ EAS_I32 temp;
+ EAS_I32 samplesPerBlock;
+ EAS_I32 secs, msecs;
+
+ /* no need to calculate if time is zero */
+ if (time == 0)
+ temp = 0;
+
+ /* not zero */
+ else
+ {
+
+ /* can't seek if not a blocked file */
+ if (pState->blockSize == 0)
+ return EAS_ERROR_FEATURE_NOT_AVAILABLE;
+
+ /* calculate number of samples per block */
+ if (pState->flags & PCM_FLAGS_STEREO)
+ samplesPerBlock = pState->blockSize - 7;
+ else
+ samplesPerBlock = (pState->blockSize << 1) - 7;
+
+ /* break down into secs and msecs */
+ secs = time / 1000;
+ msecs = time - (secs * 1000);
+
+ /* calculate sample number fraction from msecs */
+ temp = (msecs * pState->sampleRate);
+ temp = (temp >> 10) + ((temp * 49) >> 21);
+
+ /* add integer sample count */
+ temp += secs * pState->sampleRate;
+
+#ifdef _DEBUG_IMA_ADPCM_LOCATE
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x2380b977, 0x00000006 , time, temp);
+#endif
+
+ /* for looped samples, calculate position in the loop */
+ if ((temp > pState->byteCount) && (pState->loopSamples != 0))
+ {
+ EAS_I32 numBlocks;
+ EAS_I32 samplesPerLoop;
+ EAS_I32 samplesInLastBlock;
+
+ numBlocks = (EAS_I32) (pState->loopStart / pState->blockSize);
+ samplesInLastBlock = (EAS_I32) pState->loopStart - (numBlocks * pState->blockSize);
+ if (samplesInLastBlock)
+ {
+ if (pState->flags & PCM_FLAGS_STEREO)
+ samplesInLastBlock = samplesInLastBlock - 7;
+ else
+ /*lint -e{703} use shift for performance */
+ samplesInLastBlock = (samplesInLastBlock << 1) - 7;
+ }
+ samplesPerLoop = numBlocks * samplesPerBlock + samplesInLastBlock;
+ temp = temp % samplesPerLoop;
+#ifdef _DEBUG_IMA_ADPCM_LOCATE
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x2380b977, 0x00000007 , numBlocks, samplesPerLoop, samplesInLastBlock, temp);
+#endif
+ }
+
+ /* find start of block for requested sample */
+ temp = (temp / samplesPerBlock) * pState->blockSize;
+#ifdef _DEBUG_IMA_ADPCM_LOCATE
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x2380b977, 0x00000008 , temp);
+#endif
+
+ }
+
+ /* seek to new location */
+ if ((result = EAS_PESeek(pEASData, pState, &temp)) != EAS_SUCCESS)
+ return result;
+
+#ifdef _DEBUG_IMA_ADPCM_LOCATE
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x2380b977, 0x00000009 , pState->bytesLeft);
+#endif
+
+ /* reset state */
+ pState->blockCount = 0;
+ pState->hiNibble = EAS_FALSE;
+ if ((pState->state != EAS_STATE_PAUSING) && (pState->state != EAS_STATE_PAUSED))
+ pState->state = EAS_STATE_READY;
+
+ return EAS_SUCCESS;
+}
+
diff --git a/arm-wt-22k/lib_src/eas_imelody.c b/arm-wt-22k/lib_src/eas_imelody.c
new file mode 100644
index 0000000..5b7e7b8
--- /dev/null
+++ b/arm-wt-22k/lib_src/eas_imelody.c
@@ -0,0 +1,1742 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_imelody.c
+ *
+ * Contents and purpose:
+ * iMelody parser
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 797 $
+ * $Date: 2007-08-01 00:15:56 -0700 (Wed, 01 Aug 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+/* lint doesn't like the way some string.h files look */
+#ifdef _lint
+#include "lint_stdlib.h"
+#else
+#include <string.h>
+#endif
+
+#include "eas_data.h"
+#include "eas_miditypes.h"
+#include "eas_parser.h"
+#include "eas_report.h"
+#include "eas_host.h"
+#include "eas_midi.h"
+#include "eas_config.h"
+#include "eas_vm_protos.h"
+#include "eas_imelodydata.h"
+#include "eas_ctype.h"
+
+// #define _DEBUG_IMELODY
+
+/* increase gain for mono ringtones */
+#define IMELODY_GAIN_OFFSET 8
+
+/* length of 32nd note in 1/256ths of a msec for 120 BPM tempo */
+#define DEFAULT_TICK_CONV 16000
+#define TICK_CONVERT 1920000
+
+/* default channel and program for iMelody playback */
+#define IMELODY_CHANNEL 0
+#define IMELODY_PROGRAM 80
+#define IMELODY_VEL_MUL 4
+#define IMELODY_VEL_OFS 67
+
+/* multiplier for fixed point triplet conversion */
+#define TRIPLET_MULTIPLIER 683
+#define TRIPLET_SHIFT 10
+
+static const char* const tokens[] =
+{
+ "BEGIN:IMELODY",
+ "VERSION:",
+ "FORMAT:CLASS",
+ "NAME:",
+ "COMPOSER:",
+ "BEAT:",
+ "STYLE:",
+ "VOLUME:",
+ "MELODY:",
+ "END:IMELODY"
+};
+
+/* ledon or ledoff */
+static const char ledStr[] = "edo";
+
+/* vibeon or vibeoff */
+static const char vibeStr[] = "ibeo";
+
+/* backon or backoff */
+static const char backStr[] = "cko";
+
+typedef enum
+{
+ TOKEN_BEGIN,
+ TOKEN_VERSION,
+ TOKEN_FORMAT,
+ TOKEN_NAME,
+ TOKEN_COMPOSER,
+ TOKEN_BEAT,
+ TOKEN_STYLE,
+ TOKEN_VOLUME,
+ TOKEN_MELODY,
+ TOKEN_END,
+ TOKEN_INVALID
+} ENUM_IMELODY_TOKENS;
+
+/* lookup table for note values */
+static const EAS_I8 noteTable[] = { 9, 11, 0, 2, 4, 5, 7 };
+
+/* inline functions */
+#ifdef _DEBUG_IMELODY
+static void PutBackChar (S_IMELODY_DATA *pData)
+{
+ if (pData->index)
+ pData->index--;
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "PutBackChar '%c'\n", pData->buffer[pData->index]); */ }
+}
+#else
+EAS_INLINE void PutBackChar (S_IMELODY_DATA *pData) { if (pData->index) pData->index--; }
+#endif
+
+
+/* local prototypes */
+static EAS_RESULT IMY_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset);
+static EAS_RESULT IMY_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
+static EAS_RESULT IMY_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime);
+static EAS_RESULT IMY_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode);
+static EAS_RESULT IMY_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState);
+static EAS_RESULT IMY_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
+static EAS_RESULT IMY_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
+static EAS_RESULT IMY_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
+static EAS_RESULT IMY_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
+static EAS_RESULT IMY_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value);
+static EAS_RESULT IMY_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue);
+static EAS_BOOL IMY_PlayNote (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData, EAS_I8 note, EAS_INT parserMode);
+static EAS_BOOL IMY_PlayRest (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData);
+static EAS_BOOL IMY_GetDuration (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_I32 *pDuration);
+static EAS_BOOL IMY_GetLEDState (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData);
+static EAS_BOOL IMY_GetVibeState (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData);
+static EAS_BOOL IMY_GetBackState (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData);
+static EAS_BOOL IMY_GetVolume (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_BOOL inHeader);
+static EAS_BOOL IMY_GetNumber (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_INT *temp, EAS_BOOL inHeader);
+static EAS_RESULT IMY_ParseHeader (S_EAS_DATA *pEASData, S_IMELODY_DATA* pData);
+static EAS_I8 IMY_GetNextChar (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_BOOL inHeader);
+static EAS_RESULT IMY_ReadLine (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_I8 *buffer, EAS_I32 *pStartLine);
+static EAS_INT IMY_ParseLine (EAS_I8 *buffer, EAS_U8 *pIndex);
+
+
+/*----------------------------------------------------------------------------
+ *
+ * EAS_iMelody_Parser
+ *
+ * This structure contains the functional interface for the iMelody parser
+ *----------------------------------------------------------------------------
+*/
+const S_FILE_PARSER_INTERFACE EAS_iMelody_Parser =
+{
+ IMY_CheckFileType,
+ IMY_Prepare,
+ IMY_Time,
+ IMY_Event,
+ IMY_State,
+ IMY_Close,
+ IMY_Reset,
+ IMY_Pause,
+ IMY_Resume,
+ NULL,
+ IMY_SetData,
+ IMY_GetData,
+ NULL
+};
+
+/*----------------------------------------------------------------------------
+ * IMY_CheckFileType()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Check the file type to see if we can parse it
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT IMY_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset)
+{
+ S_IMELODY_DATA* pData;
+ EAS_I8 buffer[MAX_LINE_SIZE+1];
+ EAS_U8 index;
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_CheckFileType\n"); */ }
+#endif
+
+ /* read the first line of the file */
+ *ppHandle = NULL;
+ if (IMY_ReadLine(pEASData->hwInstData, fileHandle, buffer, NULL) != EAS_SUCCESS)
+ return EAS_SUCCESS;
+
+ /* check for header string */
+ if (IMY_ParseLine(buffer, &index) == TOKEN_BEGIN)
+ {
+
+ /* check for static memory allocation */
+ if (pEASData->staticMemoryModel)
+ pData = EAS_CMEnumData(EAS_CM_IMELODY_DATA);
+ else
+ pData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_IMELODY_DATA));
+ if (!pData)
+ return EAS_ERROR_MALLOC_FAILED;
+ EAS_HWMemSet(pData, 0, sizeof(S_IMELODY_DATA));
+
+ /* initialize */
+ pData->fileHandle = fileHandle;
+ pData->fileOffset = offset;
+ pData->state = EAS_STATE_ERROR;
+ pData->state = EAS_STATE_OPEN;
+
+ /* return a pointer to the instance data */
+ *ppHandle = pData;
+ }
+
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_Prepare()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Prepare to parse the file. Allocates instance data (or uses static allocation for
+ * static memory model).
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT IMY_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
+{
+ S_IMELODY_DATA* pData;
+ EAS_RESULT result;
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_Prepare\n"); */ }
+#endif
+
+ /* check for valid state */
+ pData = (S_IMELODY_DATA*) pInstData;
+ if (pData->state != EAS_STATE_OPEN)
+ return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
+
+ /* instantiate a synthesizer */
+ if ((result = VMInitMIDI(pEASData, &pData->pSynth)) != EAS_SUCCESS)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMInitMIDI returned %d\n", result); */ }
+ return result;
+ }
+
+ /* parse the header */
+ if ((result = IMY_ParseHeader(pEASData, pData)) != EAS_SUCCESS)
+ return result;
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Prepare: state set to EAS_STATE_READY\n"); */ }
+#endif
+
+ pData ->state = EAS_STATE_READY;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_Time()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Returns the time of the next event in msecs
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ * pTime - pointer to variable to hold time of next event (in msecs)
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pEASData) common decoder interface - pEASData not used */
+static EAS_RESULT IMY_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime)
+{
+ S_IMELODY_DATA *pData;
+
+ pData = (S_IMELODY_DATA*) pInstData;
+
+ /* return time in milliseconds */
+ /*lint -e{704} use shift instead of division */
+ *pTime = pData->time >> 8;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_Event()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Parse the next event in the file
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT IMY_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode)
+{
+ S_IMELODY_DATA* pData;
+ EAS_RESULT result;
+ EAS_I8 c;
+ EAS_BOOL eof;
+ EAS_INT temp;
+
+ pData = (S_IMELODY_DATA*) pInstData;
+ if (pData->state >= EAS_STATE_OPEN)
+ return EAS_SUCCESS;
+
+ if (pData->state == EAS_STATE_READY) {
+ pData->state = EAS_STATE_PLAY;
+ }
+
+ /* initialize MIDI channel when the track starts playing */
+ if (pData->time == 0)
+ {
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Event: Reset\n"); */ }
+#endif
+ /* set program to square lead */
+ VMProgramChange(pEASData->pVoiceMgr, pData->pSynth, IMELODY_CHANNEL, IMELODY_PROGRAM);
+
+ /* set channel volume to max */
+ VMControlChange(pEASData->pVoiceMgr, pData->pSynth, IMELODY_CHANNEL, 7, 127);
+ }
+
+ /* check for end of note */
+ if (pData->note)
+ {
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Stopping note %d\n", pData->note); */ }
+#endif
+ /* stop the note */
+ VMStopNote(pEASData->pVoiceMgr, pData->pSynth, IMELODY_CHANNEL, pData->note, 0);
+ pData->note = 0;
+
+ /* check for rest between notes */
+ if (pData->restTicks)
+ {
+ pData->time += pData->restTicks;
+ pData->restTicks = 0;
+ return EAS_SUCCESS;
+ }
+ }
+
+ /* parse the next event */
+ eof = EAS_FALSE;
+ while (!eof)
+ {
+
+ /* get next character */
+ c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_FALSE);
+
+ switch (c)
+ {
+ /* start repeat */
+ case '(':
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter repeat section\n", c); */ }
+#endif
+
+ if (pData->repeatOffset < 0)
+ {
+ pData->repeatOffset = pData->startLine + (EAS_I32) pData->index;
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Repeat offset = %d\n", pData->repeatOffset); */ }
+#endif
+ }
+ else
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Ignoring nested repeat section\n"); */ }
+ break;
+
+ /* end repeat */
+ case ')':
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "End repeat section, repeat offset = %d\n", pData->repeatOffset); */ }
+#endif
+ /* ignore invalid repeats */
+ if (pData->repeatCount >= 0)
+ {
+
+ /* decrement repeat count (repeatCount == 0 means infinite loop) */
+ if (pData->repeatCount > 0)
+ {
+ if (--pData->repeatCount == 0)
+ {
+ pData->repeatCount = -1;
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Repeat loop complete\n"); */ }
+#endif
+ }
+ }
+
+//2 TEMPORARY FIX: If locating, don't do infinite loops.
+//3 We need a different mode for metadata parsing where we don't loop at all
+ if ((parserMode == eParserModePlay) || (pData->repeatCount != 0))
+ {
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Rewinding file for repeat\n"); */ }
+#endif
+ /* rewind to start of loop */
+ if ((result = EAS_HWFileSeek(pEASData->hwInstData, pData->fileHandle, pData->repeatOffset)) != EAS_SUCCESS)
+ return result;
+ IMY_ReadLine(pEASData->hwInstData, pData->fileHandle, pData->buffer, &pData->startLine);
+ pData->index = 0;
+
+ /* if last loop, prevent future loops */
+ if (pData->repeatCount == -1)
+ pData->repeatOffset = -1;
+ }
+ }
+ break;
+
+ /* repeat count */
+ case '@':
+ if (!IMY_GetNumber(pEASData->hwInstData, pData, &temp, EAS_FALSE))
+ eof = EAS_TRUE;
+ else if (pData->repeatOffset > 0)
+ {
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Repeat count = %dt", pData->repeatCount); */ }
+#endif
+ if (pData->repeatCount < 0)
+ pData->repeatCount = (EAS_I16) temp;
+ }
+ break;
+
+ /* volume */
+ case 'V':
+ if (!IMY_GetVolume(pEASData->hwInstData, pData, EAS_FALSE))
+ eof = EAS_TRUE;
+ break;
+
+ /* flat */
+ case '&':
+ pData->noteModifier = -1;
+ break;
+
+ /* sharp */
+ case '#':
+ pData->noteModifier = +1;
+ break;
+
+ /* octave */
+ case '*':
+ c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_FALSE);
+ if (IsDigit(c))
+ pData->octave = (EAS_U8) ((c - '0' + 1) * 12);
+ else if (!c)
+ eof = EAS_TRUE;
+ break;
+
+ /* ledon or ledoff */
+ case 'l':
+ if (!IMY_GetLEDState(pEASData, pData))
+ eof = EAS_TRUE;
+ break;
+
+ /* vibeon or vibeoff */
+ case 'v':
+ if (!IMY_GetVibeState(pEASData, pData))
+ eof = EAS_TRUE;
+ break;
+
+ /* either a B note or backon or backoff */
+ case 'b':
+ if (IMY_GetNextChar(pEASData->hwInstData, pData, EAS_FALSE) == 'a')
+ {
+ if (!IMY_GetBackState(pEASData, pData))
+ eof = EAS_TRUE;
+ }
+ else
+ {
+ PutBackChar(pData);
+ if (IMY_PlayNote(pEASData, pData, c, parserMode))
+ return EAS_SUCCESS;
+ eof = EAS_TRUE;
+ }
+ break;
+
+ /* rest */
+ case 'r':
+ case 'R':
+ if (IMY_PlayRest(pEASData, pData))
+ return EAS_SUCCESS;
+ eof = EAS_TRUE;
+ break;
+
+ /* EOF */
+ case 0:
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Event: end of iMelody file detected\n"); */ }
+#endif
+ eof = EAS_TRUE;
+ break;
+
+ /* must be a note */
+ default:
+ c = ToLower(c);
+ if ((c >= 'a') && (c <= 'g'))
+ {
+ if (IMY_PlayNote(pEASData, pData, c, parserMode))
+ return EAS_SUCCESS;
+ eof = EAS_TRUE;
+ }
+ else
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Ignoring unexpected character '%c' [0x%02x]\n", c, c); */ }
+ break;
+ }
+ }
+
+ /* handle EOF */
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Event: state set to EAS_STATE_STOPPING\n"); */ }
+#endif
+ pData->state = EAS_STATE_STOPPING;
+ VMReleaseAllVoices(pEASData->pVoiceMgr, pData->pSynth);
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_State()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Returns the current state of the stream
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ * pState - pointer to variable to store state
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pEASData) common decoder interface - pEASData not used */
+static EAS_RESULT IMY_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pState)
+{
+ S_IMELODY_DATA* pData;
+
+ /* establish pointer to instance data */
+ pData = (S_IMELODY_DATA*) pInstData;
+
+ /* if stopping, check to see if synth voices are active */
+ if (pData->state == EAS_STATE_STOPPING)
+ {
+ if (VMActiveVoices(pData->pSynth) == 0)
+ {
+ pData->state = EAS_STATE_STOPPED;
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_State: state set to EAS_STATE_STOPPED\n"); */ }
+#endif
+ }
+ }
+
+ if (pData->state == EAS_STATE_PAUSING)
+ {
+ if (VMActiveVoices(pData->pSynth) == 0)
+ {
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_State: state set to EAS_STATE_PAUSED\n"); */ }
+#endif
+ pData->state = EAS_STATE_PAUSED;
+ }
+ }
+
+ /* return current state */
+ *pState = pData->state;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_Close()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Close the file and clean up
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT IMY_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
+{
+ S_IMELODY_DATA* pData;
+ EAS_RESULT result;
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Close: close file\n"); */ }
+#endif
+
+ pData = (S_IMELODY_DATA*) pInstData;
+
+ /* close the file */
+ if ((result = EAS_HWCloseFile(pEASData->hwInstData, pData->fileHandle)) != EAS_SUCCESS)
+ return result;
+
+ /* free the synth */
+ if (pData->pSynth != NULL)
+ VMMIDIShutdown(pEASData, pData->pSynth);
+
+ /* if using dynamic memory, free it */
+ if (!pEASData->staticMemoryModel)
+ EAS_HWFree(pEASData->hwInstData, pData);
+
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_Reset()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Reset the sequencer. Used for locating backwards in the file.
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT IMY_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
+{
+ S_IMELODY_DATA* pData;
+ EAS_RESULT result;
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Reset: reset file\n"); */ }
+#endif
+ pData = (S_IMELODY_DATA*) pInstData;
+
+ /* reset the synth */
+ VMReset(pEASData->pVoiceMgr, pData->pSynth, EAS_TRUE);
+
+ /* reset time to zero */
+ pData->time = 0;
+ pData->note = 0;
+
+ /* reset file position and re-parse header */
+ pData->state = EAS_STATE_ERROR;
+ if ((result = EAS_HWFileSeek(pEASData->hwInstData, pData->fileHandle, pData->fileOffset)) != EAS_SUCCESS)
+ return result;
+ if ((result = IMY_ParseHeader (pEASData, pData)) != EAS_SUCCESS)
+ return result;
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Reset: state set to EAS_STATE_ERROR\n"); */ }
+#endif
+
+ pData->state = EAS_STATE_READY;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_Pause()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Pauses the sequencer. Mutes all voices and sets state to pause.
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT IMY_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
+{
+ S_IMELODY_DATA *pData;
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Pause: pause file\n"); */ }
+#endif
+
+ /* can't pause a stopped stream */
+ pData = (S_IMELODY_DATA*) pInstData;
+ if (pData->state == EAS_STATE_STOPPED)
+ return EAS_ERROR_ALREADY_STOPPED;
+
+ /* mute the synthesizer */
+ VMMuteAllVoices(pEASData->pVoiceMgr, pData->pSynth);
+ pData->state = EAS_STATE_PAUSING;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_Resume()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Resume playing after a pause, sets state back to playing.
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pEASData) common decoder interface - pEASData not used */
+static EAS_RESULT IMY_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
+{
+ S_IMELODY_DATA *pData;
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Resume: resume file\n"); */ }
+#endif
+
+ /* can't resume a stopped stream */
+ pData = (S_IMELODY_DATA*) pInstData;
+ if (pData->state == EAS_STATE_STOPPED)
+ return EAS_ERROR_ALREADY_STOPPED;
+
+ /* nothing to do but resume playback */
+ pData->state = EAS_STATE_PLAY;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_SetData()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Adjust tempo relative to song tempo
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * pInstData - pointer to iMelody instance data
+ * rate - rate (28-bit fractional amount)
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pEASData) common decoder interface - pEASData not used */
+static EAS_RESULT IMY_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value)
+{
+ S_IMELODY_DATA *pData;
+
+ pData = (S_IMELODY_DATA*) pInstData;
+ switch (param)
+ {
+
+ /* set metadata callback */
+ case PARSER_DATA_METADATA_CB:
+ EAS_HWMemCpy(&pData->metadata, (void*) value, sizeof(S_METADATA_CB));
+ break;
+
+ default:
+ return EAS_ERROR_INVALID_PARAMETER;
+ }
+
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_GetData()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Return the file type
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * pInstData - pointer to iMelody instance data
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pEASData) common decoder interface - pEASData not used */
+static EAS_RESULT IMY_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue)
+{
+ S_IMELODY_DATA *pData;
+
+ pData = (S_IMELODY_DATA*) pInstData;
+
+ switch (param)
+ {
+ /* return file type as iMelody */
+ case PARSER_DATA_FILE_TYPE:
+ *pValue = EAS_FILE_IMELODY;
+ break;
+
+ case PARSER_DATA_SYNTH_HANDLE:
+ *pValue = (EAS_I32) pData->pSynth;
+ break;
+
+ case PARSER_DATA_GAIN_OFFSET:
+ *pValue = IMELODY_GAIN_OFFSET;
+ break;
+
+ default:
+ return EAS_ERROR_INVALID_PARAMETER;
+ }
+
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_PlayNote()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_BOOL IMY_PlayNote (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData, EAS_I8 note, EAS_INT parserMode)
+{
+ EAS_I32 duration;
+ EAS_U8 velocity;
+
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_PlayNote: start note %d\n", note); */ }
+#endif
+
+ /* get the duration */
+ if (!IMY_GetDuration(pEASData->hwInstData, pData, &duration))
+ return EAS_FALSE;
+
+ /* save note value */
+ pData->note = (EAS_U8) (pData->octave + noteTable[note - 'a'] + pData->noteModifier);
+ velocity = (EAS_U8) (pData->volume ? pData->volume * IMELODY_VEL_MUL + IMELODY_VEL_OFS : 0);
+
+ /* start note only if in play mode */
+ if (parserMode == eParserModePlay)
+ VMStartNote(pEASData->pVoiceMgr, pData->pSynth, IMELODY_CHANNEL, pData->note, velocity);
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_PlayNote: Start note %d, duration %d\n", pData->note, duration); */ }
+#endif
+
+ /* determine note length */
+ switch (pData->style)
+ {
+ case 0:
+ /*lint -e{704} shift for performance */
+ pData->restTicks = duration >> 4;
+ break;
+ case 1:
+ pData->restTicks = 0;
+ break;
+ case 2:
+ /*lint -e{704} shift for performance */
+ pData->restTicks = duration >> 1;
+ break;
+ default:
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "IMY_PlayNote: Note style out of range: %d\n", pData->style); */ }
+ /*lint -e{704} shift for performance */
+ pData->restTicks = duration >> 4;
+ break;
+ }
+
+ /* next event is at end of this note */
+ pData->time += duration - pData->restTicks;
+
+ /* reset the flat/sharp modifier */
+ pData->noteModifier = 0;
+
+ return EAS_TRUE;
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_PlayRest()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_BOOL IMY_PlayRest (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData)
+{
+ EAS_I32 duration;
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_PlayRest]n"); */ }
+#endif
+
+ /* get the duration */
+ if (!IMY_GetDuration(pEASData->hwInstData, pData, &duration))
+ return EAS_FALSE;
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_PlayRest: note duration %d\n", duration); */ }
+#endif
+
+ /* next event is at end of this note */
+ pData->time += duration;
+ return EAS_TRUE;
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_GetDuration()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+
+static EAS_BOOL IMY_GetDuration (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_I32 *pDuration)
+{
+ EAS_I32 duration;
+ EAS_I8 c;
+
+ /* get the duration */
+ *pDuration = 0;
+ c = IMY_GetNextChar(hwInstData, pData, EAS_FALSE);
+ if (!c)
+ return EAS_FALSE;
+ if ((c < '0') || (c > '5'))
+ {
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetDuration: error in duration '%c'\n", c); */ }
+#endif
+ return EAS_FALSE;
+ }
+
+ /* calculate total length of note */
+ duration = pData->tick * (1 << ('5' - c));
+
+ /* check for duration modifier */
+ c = IMY_GetNextChar(hwInstData, pData, EAS_FALSE);
+ if (c)
+ {
+ if (c == '.')
+ /*lint -e{704} shift for performance */
+ duration += duration >> 1;
+ else if (c == ':')
+ /*lint -e{704} shift for performance */
+ duration += (duration >> 1) + (duration >> 2);
+ else if (c == ';')
+ /*lint -e{704} shift for performance */
+ duration = (duration * TRIPLET_MULTIPLIER) >> TRIPLET_SHIFT;
+ else
+ PutBackChar(pData);
+ }
+
+ *pDuration = duration;
+ return EAS_TRUE;
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_GetLEDState()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_BOOL IMY_GetLEDState (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData)
+{
+ EAS_I8 c;
+ EAS_INT i;
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_GetLEDState\n"); */ }
+#endif
+
+ for (i = 0; i < 5; i++)
+ {
+ c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_FALSE);
+ if (!c)
+ return EAS_FALSE;
+ switch (i)
+ {
+ case 3:
+ if (c == 'n')
+ {
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetLEDState: LED on\n"); */ }
+#endif
+ EAS_HWLED(pEASData->hwInstData, EAS_TRUE);
+ return EAS_TRUE;
+ }
+ else if (c != 'f')
+ return EAS_FALSE;
+ break;
+
+ case 4:
+ if (c == 'f')
+ {
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetLEDState: LED off\n"); */ }
+#endif
+ EAS_HWLED(pEASData->hwInstData, EAS_FALSE);
+ return EAS_TRUE;
+ }
+ return EAS_FALSE;
+
+ default:
+ if (c != ledStr[i])
+ return EAS_FALSE;
+ break;
+ }
+ }
+ return EAS_FALSE;
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_GetVibeState()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_BOOL IMY_GetVibeState (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData)
+{
+ EAS_I8 c;
+ EAS_INT i;
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_GetVibeState\n"); */ }
+#endif
+
+ for (i = 0; i < 6; i++)
+ {
+ c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_FALSE);
+ if (!c)
+ return EAS_FALSE;
+ switch (i)
+ {
+ case 4:
+ if (c == 'n')
+ {
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetVibeState: vibrate on\n"); */ }
+#endif
+ EAS_HWVibrate(pEASData->hwInstData, EAS_TRUE);
+ return EAS_TRUE;
+ }
+ else if (c != 'f')
+ return EAS_FALSE;
+ break;
+
+ case 5:
+ if (c == 'f')
+ {
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetVibeState: vibrate off\n"); */ }
+#endif
+ EAS_HWVibrate(pEASData->hwInstData, EAS_FALSE);
+ return EAS_TRUE;
+ }
+ return EAS_FALSE;
+
+ default:
+ if (c != vibeStr[i])
+ return EAS_FALSE;
+ break;
+ }
+ }
+ return EAS_FALSE;
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_GetBackState()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_BOOL IMY_GetBackState (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData)
+{
+ EAS_I8 c;
+ EAS_INT i;
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_GetBackState\n"); */ }
+#endif
+
+ for (i = 0; i < 5; i++)
+ {
+ c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_FALSE);
+ if (!c)
+ return EAS_FALSE;
+ switch (i)
+ {
+ case 3:
+ if (c == 'n')
+ {
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetBackState: backlight on\n"); */ }
+#endif
+ EAS_HWBackLight(pEASData->hwInstData, EAS_TRUE);
+ return EAS_TRUE;
+ }
+ else if (c != 'f')
+ return EAS_FALSE;
+ break;
+
+ case 4:
+ if (c == 'f')
+ {
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetBackState: backlight off\n"); */ }
+#endif
+ EAS_HWBackLight(pEASData->hwInstData, EAS_FALSE);
+ return EAS_TRUE;
+ }
+ return EAS_FALSE;
+
+ default:
+ if (c != backStr[i])
+ return EAS_FALSE;
+ break;
+ }
+ }
+ return EAS_FALSE;
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_GetVolume()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_BOOL IMY_GetVolume (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_BOOL inHeader)
+{
+ EAS_INT temp;
+ EAS_I8 c;
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_GetVolume\n"); */ }
+#endif
+
+ c = IMY_GetNextChar(hwInstData, pData, inHeader);
+ if (c == '+')
+ {
+ if (pData->volume < 15)
+ pData->volume++;
+ return EAS_TRUE;
+ }
+ else if (c == '-')
+ {
+ if (pData->volume > 0)
+ pData->volume--;
+ return EAS_TRUE;
+ }
+ else if (IsDigit(c))
+ temp = c - '0';
+ else
+ return EAS_FALSE;
+
+ c = IMY_GetNextChar(hwInstData, pData, inHeader);
+ if (IsDigit(c))
+ temp = temp * 10 + c - '0';
+ else if (c)
+ PutBackChar(pData);
+ if ((temp >= 0) && (temp <= 15))
+ {
+ if (inHeader && (temp == 0))
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Ignoring V0 encountered in header\n"); */ }
+ else
+ pData->volume = (EAS_U8) temp;
+ }
+ return EAS_TRUE;
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_GetNumber()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_BOOL IMY_GetNumber (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_INT *temp, EAS_BOOL inHeader)
+{
+ EAS_BOOL ok;
+ EAS_I8 c;
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_GetNumber\n"); */ }
+#endif
+
+ *temp = 0;
+ ok = EAS_FALSE;
+ for (;;)
+ {
+ c = IMY_GetNextChar(hwInstData, pData, inHeader);
+ if (IsDigit(c))
+ {
+ *temp = *temp * 10 + c - '0';
+ ok = EAS_TRUE;
+ }
+ else
+ {
+ if (c)
+ PutBackChar(pData);
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetNumber: value %d\n", *temp); */ }
+#endif
+
+ return ok;
+ }
+ }
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_GetVersion()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_BOOL IMY_GetVersion (S_IMELODY_DATA *pData, EAS_INT *pVersion)
+{
+ EAS_I8 c;
+ EAS_INT temp;
+ EAS_INT version;
+
+ version = temp = 0;
+ for (;;)
+ {
+ c = pData->buffer[pData->index++];
+ if ((c == 0) || (c == '.'))
+ {
+ /*lint -e{701} use shift for performance */
+ version = (version << 8) + temp;
+ if (c == 0)
+ {
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetVersion: version 0x%04x\n", version); */ }
+#endif
+
+ *pVersion = version;
+ return EAS_TRUE;
+ }
+ temp = 0;
+ }
+ else if (IsDigit(c))
+ temp = (temp * 10) + c - '0';
+ }
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_MetaData()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Prepare to parse the file. Allocates instance data (or uses static allocation for
+ * static memory model).
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static void IMY_MetaData (S_IMELODY_DATA *pData, E_EAS_METADATA_TYPE metaType, EAS_I8 *buffer)
+{
+ EAS_I32 len;
+
+ /* check for callback */
+ if (!pData->metadata.callback)
+ return;
+
+ /* copy data to host buffer */
+ len = (EAS_I32) strlen((char*) buffer);
+ if (len >pData->metadata.bufferSize)
+ len = pData->metadata.bufferSize;
+ strncpy((char*) pData->metadata.buffer, (char*) buffer, (size_t) len);
+ pData->metadata.buffer[len] = 0;
+
+ /* callback to host */
+ pData->metadata.callback(metaType, pData->metadata.buffer, pData->metadata.pUserData);
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_ParseHeader()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Prepare to parse the file. Allocates instance data (or uses static allocation for
+ * static memory model).
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT IMY_ParseHeader (S_EAS_DATA *pEASData, S_IMELODY_DATA* pData)
+{
+ EAS_RESULT result;
+ EAS_INT token;
+ EAS_INT temp;
+ EAS_I8 c;
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_ParseHeader\n"); */ }
+#endif
+
+ /* initialize some defaults */
+ pData->time = 0;
+ pData->tick = DEFAULT_TICK_CONV;
+ pData->note = 0;
+ pData->noteModifier = 0;
+ pData ->restTicks = 0;
+ pData->volume = 7;
+ pData->octave = 60;
+ pData->repeatOffset = -1;
+ pData->repeatCount = -1;
+ pData->style = 0;
+
+ /* force the read of the first line */
+ pData->index = 1;
+
+ /* read data until we get to melody */
+ for (;;)
+ {
+ /* read a line from the file and parse the token */
+ if (pData->index != 0)
+ {
+ if ((result = IMY_ReadLine(pEASData->hwInstData, pData->fileHandle, pData->buffer, &pData->startLine)) != EAS_SUCCESS)
+ {
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_ParseHeader: IMY_ReadLine returned %d\n", result); */ }
+#endif
+ return result;
+ }
+ }
+ token = IMY_ParseLine(pData->buffer, &pData->index);
+
+ switch (token)
+ {
+ /* ignore these valid tokens */
+ case TOKEN_BEGIN:
+ break;
+
+ case TOKEN_FORMAT:
+ if (!IMY_GetVersion(pData, &temp))
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Invalid FORMAT field '%s'\n", pData->buffer); */ }
+ return EAS_ERROR_FILE_FORMAT;
+ }
+ if ((temp != 0x0100) && (temp != 0x0200))
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Unsupported FORMAT %02x\n", temp); */ }
+ return EAS_ERROR_UNRECOGNIZED_FORMAT;
+ }
+ break;
+
+ case TOKEN_VERSION:
+ if (!IMY_GetVersion(pData, &temp))
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Invalid VERSION field '%s'\n", pData->buffer); */ }
+ return EAS_ERROR_FILE_FORMAT;
+ }
+ if ((temp != 0x0100) && (temp != 0x0102))
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Unsupported VERSION %02x\n", temp); */ }
+ return EAS_ERROR_UNRECOGNIZED_FORMAT;
+ }
+ break;
+
+ case TOKEN_NAME:
+ IMY_MetaData(pData, EAS_METADATA_TITLE, pData->buffer + pData->index);
+ break;
+
+ case TOKEN_COMPOSER:
+ IMY_MetaData(pData, EAS_METADATA_AUTHOR, pData->buffer + pData->index);
+ break;
+
+ /* handle beat */
+ case TOKEN_BEAT:
+ IMY_GetNumber(pEASData->hwInstData, pData, &temp, EAS_TRUE);
+ if ((temp >= 25) && (temp <= 900))
+ pData->tick = TICK_CONVERT / temp;
+ break;
+
+ /* handle style */
+ case TOKEN_STYLE:
+ c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_TRUE);
+ if (c == 'S')
+ c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_TRUE);
+ if ((c >= '0') && (c <= '2'))
+ pData->style = (EAS_U8) (c - '0');
+ else
+ {
+ PutBackChar(pData);
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Error in style command: %s\n", pData->buffer); */ }
+ }
+ break;
+
+ /* handle volume */
+ case TOKEN_VOLUME:
+ c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_TRUE);
+ if (c != 'V')
+ {
+ PutBackChar(pData);
+ if (!IsDigit(c))
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Error in volume command: %s\n", pData->buffer); */ }
+ break;
+ }
+ }
+ IMY_GetVolume(pEASData->hwInstData, pData, EAS_TRUE);
+ break;
+
+ case TOKEN_MELODY:
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Header successfully parsed\n"); */ }
+#endif
+ return EAS_SUCCESS;
+
+ case TOKEN_END:
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Unexpected END:IMELODY encountered\n"); */ }
+ return EAS_ERROR_FILE_FORMAT;
+
+ default:
+ /* force a read of the next line */
+ pData->index = 1;
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Ignoring unrecognized token in iMelody file: %s\n", pData->buffer); */ }
+ break;
+ }
+ }
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_GetNextChar()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_I8 IMY_GetNextChar (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_BOOL inHeader)
+{
+ EAS_I8 c;
+ EAS_U8 index;
+
+ for (;;)
+ {
+ /* get next character */
+ c = pData->buffer[pData->index++];
+
+ /* buffer empty, read more */
+ if (!c)
+ {
+ /* don't read the next line in the header */
+ if (inHeader)
+ return 0;
+
+ pData->index = 0;
+ pData->buffer[0] = 0;
+ if (IMY_ReadLine(hwInstData, pData->fileHandle, pData->buffer, &pData->startLine) != EAS_SUCCESS)
+ {
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetNextChar: EOF\n"); */ }
+#endif
+ return 0;
+ }
+
+ /* check for END:IMELODY token */
+ if (IMY_ParseLine(pData->buffer, &index) == TOKEN_END)
+ {
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetNextChar: found END:IMELODY\n"); */ }
+#endif
+ pData->buffer[0] = 0;
+ return 0;
+ }
+ continue;
+ }
+
+ /* ignore white space */
+ if (!IsSpace(c))
+ {
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetNextChar returned '%c'\n", c); */ }
+#endif
+ return c;
+ }
+ }
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_ReadLine()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Reads a line of input from the file, discarding the CR/LF
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT IMY_ReadLine (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_I8 *buffer, EAS_I32 *pStartLine)
+{
+ EAS_RESULT result;
+ EAS_INT i;
+ EAS_I8 c;
+
+ /* fetch current file position and save it */
+ if (pStartLine != NULL)
+ {
+ if ((result = EAS_HWFilePos(hwInstData, fileHandle, pStartLine)) != EAS_SUCCESS)
+ {
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_ParseHeader: EAS_HWFilePos returned %d\n", result); */ }
+#endif
+ return result;
+ }
+ }
+
+ buffer[0] = 0;
+ for (i = 0; i < MAX_LINE_SIZE; )
+ {
+ if ((result = EAS_HWGetByte(hwInstData, fileHandle, &c)) != EAS_SUCCESS)
+ {
+ if ((result == EAS_EOF) && (i > 0))
+ break;
+ return result;
+ }
+
+ /* return on LF or end of data */
+ if (c == '\n')
+ break;
+
+ /* store characters in buffer */
+ if (c != '\r')
+ buffer[i++] = c;
+ }
+ buffer[i] = 0;
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_ReadLine read %s\n", buffer); */ }
+#endif
+
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_ParseLine()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_INT IMY_ParseLine (EAS_I8 *buffer, EAS_U8 *pIndex)
+{
+ EAS_INT i;
+ EAS_INT j;
+
+ /* there's no strnicmp() in stdlib, so we have to roll our own */
+ for (i = 0; i < TOKEN_INVALID; i++)
+ {
+ for (j = 0; ; j++)
+ {
+ /* end of token, must be a match */
+ if (tokens[i][j] == 0)
+ {
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_ParseLine found token %d\n", i); */ }
+#endif
+ *pIndex = (EAS_U8) j;
+ return i;
+ }
+ if (tokens[i][j] != ToUpper(buffer[j]))
+ break;
+ }
+ }
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_ParseLine: no token found\n"); */ }
+#endif
+ return TOKEN_INVALID;
+}
+
diff --git a/arm-wt-22k/lib_src/eas_imelodydata.c b/arm-wt-22k/lib_src/eas_imelodydata.c
new file mode 100644
index 0000000..e72dc0b
--- /dev/null
+++ b/arm-wt-22k/lib_src/eas_imelodydata.c
@@ -0,0 +1,43 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_imelodydata.c
+ *
+ * Contents and purpose:
+ * SMF File Parser
+ *
+ * This file contains data definitions for the SMF parser.
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 547 $
+ * $Date: 2007-01-31 16:30:17 -0800 (Wed, 31 Jan 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+#include "eas_types.h"
+#include "eas_imelodydata.h"
+
+/*----------------------------------------------------------------------------
+ *
+ * eas_iMelodyData
+ *
+ * Static memory allocation for iMelody parser
+ *----------------------------------------------------------------------------
+*/
+S_IMELODY_DATA eas_iMelodyData;
+
diff --git a/arm-wt-22k/lib_src/eas_imelodydata.h b/arm-wt-22k/lib_src/eas_imelodydata.h
new file mode 100644
index 0000000..303b8f6
--- /dev/null
+++ b/arm-wt-22k/lib_src/eas_imelodydata.h
@@ -0,0 +1,73 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_imelodydata.h
+ *
+ * Contents and purpose:
+ * SMF File Parser
+ *
+ * This file contains data declarations for the iMelody parser.
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 778 $
+ * $Date: 2007-07-23 16:45:17 -0700 (Mon, 23 Jul 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+#ifndef EAS_IMELODYDATA_H
+#define EAS_IMELODYDATA_H
+
+#include "eas_data.h"
+
+/* maximum line size as specified in iMelody V1.2 spec */
+#define MAX_LINE_SIZE 75
+
+/*----------------------------------------------------------------------------
+ *
+ * S_IMELODY_DATA
+ *
+ * This structure contains the state data for the iMelody parser
+ *----------------------------------------------------------------------------
+*/
+
+typedef struct
+{
+ EAS_FILE_HANDLE fileHandle; /* file handle */
+ S_SYNTH *pSynth; /* pointer to synth */
+ EAS_I32 fileOffset; /* offset to start of data */
+ EAS_I32 time; /* current time in 256ths of a msec */
+ EAS_I32 tickBase; /* basline length of 32nd note in 256th of a msec */
+ EAS_I32 tick; /* actual length of 32nd note in 256th of a msec */
+ EAS_I32 restTicks; /* ticks to rest after current note */
+ EAS_I32 startLine; /* file offset at start of line (for repeats) */
+ EAS_I32 repeatOffset; /* file offset to start of repeat section */
+ S_METADATA_CB metadata; /* metadata callback */
+ EAS_I16 repeatCount; /* repeat counter */
+ EAS_U8 state; /* current state EAS_STATE_XXXX */
+ EAS_U8 style; /* from STYLE */
+ EAS_U8 index; /* index into buffer */
+ EAS_U8 octave; /* octave prefix */
+ EAS_U8 volume; /* current volume */
+ EAS_U8 note; /* MIDI note number */
+ EAS_I8 noteModifier; /* sharp or flat */
+ EAS_I8 buffer[MAX_LINE_SIZE+1]; /* buffer for ASCII data */
+} S_IMELODY_DATA;
+
+#endif
+
+
diff --git a/arm-wt-22k/lib_src/eas_math.c b/arm-wt-22k/lib_src/eas_math.c
new file mode 100644
index 0000000..12d788e
--- /dev/null
+++ b/arm-wt-22k/lib_src/eas_math.c
@@ -0,0 +1,168 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_math.c
+ *
+ * Contents and purpose:
+ * Contains common math routines for the various audio engines.
+ *
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 586 $
+ * $Date: 2007-03-08 20:33:04 -0800 (Thu, 08 Mar 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+#include "eas.h"
+#include "eas_math.h"
+
+/* anything less than this converts to a fraction too small to represent in 32-bits */
+#define MIN_CENTS -18000
+
+/*----------------------------------------------------------------------------
+ * EAS_Calculate2toX()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Calculate 2^x
+ *
+ * Inputs:
+ * nCents - measured in cents
+ * psEASData - pointer to overall EAS data structure
+ *
+ * Outputs:
+ * nResult - int.frac result (where frac has NUM_DENTS_FRAC_BITS)
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_I32 EAS_Calculate2toX (EAS_I32 nCents)
+{
+ EAS_I32 nDents;
+ EAS_I32 nExponentInt, nExponentFrac;
+ EAS_I32 nTemp1, nTemp2;
+ EAS_I32 nResult;
+
+ /* check for minimum value */
+ if (nCents < MIN_CENTS)
+ return 0;
+
+ /* for the time being, convert cents to dents */
+ nDents = FMUL_15x15(nCents, CENTS_TO_DENTS);
+
+ nExponentInt = GET_DENTS_INT_PART(nDents);
+ nExponentFrac = GET_DENTS_FRAC_PART(nDents);
+
+ /*
+ implement 2^(fracPart) as a power series
+ */
+ nTemp1 = GN2_TO_X2 + MULT_DENTS_COEF(nExponentFrac, GN2_TO_X3);
+ nTemp2 = GN2_TO_X1 + MULT_DENTS_COEF(nExponentFrac, nTemp1);
+ nTemp1 = GN2_TO_X0 + MULT_DENTS_COEF(nExponentFrac, nTemp2);
+
+ /*
+ implement 2^(intPart) as
+ a left shift for intPart >= 0 or
+ a left shift for intPart < 0
+ */
+ if (nExponentInt >= 0)
+ {
+ /* left shift for positive exponents */
+ /*lint -e{703} <avoid multiply for performance>*/
+ nResult = nTemp1 << nExponentInt;
+ }
+ else
+ {
+ /* right shift for negative exponents */
+ nExponentInt = -nExponentInt;
+ nResult = nTemp1 >> nExponentInt;
+ }
+
+ return nResult;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_LogToLinear16()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Transform log value to linear gain multiplier using piece-wise linear
+ * approximation
+ *
+ * Inputs:
+ * nGain - log scale value in 20.10 format. Even though gain is normally
+ * stored in 6.10 (16-bit) format we use 32-bit numbers here to eliminate
+ * the need for saturation checking when combining gain values.
+ *
+ * Outputs:
+ * Returns a 16-bit linear value approximately equal to 2^(nGain/1024)
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_U16 EAS_LogToLinear16 (EAS_I32 nGain)
+{
+ EAS_INT nExp;
+ EAS_U16 nTemp;
+
+ /* bias to positive */
+ nGain += 32767;
+
+ /* check for infinite attenuation */
+ if (nGain < 0)
+ return 0;
+
+ /* extract the exponent */
+ nExp = 31 - (nGain >> 10);
+
+ /* check for maximum output */
+ if (nExp < 0)
+ return 0x7fff;
+
+ /* extract mantissa and restore implied 1 bit */
+ nTemp = (EAS_U16)((((nGain & 0x3ff) << 4) | 0x4000) >> nExp);
+
+ /* use shift to approximate power-of-2 operation */
+ return nTemp;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_VolumeToGain()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Transform volume control in 1dB increments to gain multiplier
+ *
+ * Inputs:
+ * volume - 100 = 0dB, 99 = -1dB, 0 = -inf
+ *
+ * Outputs:
+ * Returns a 16-bit linear value
+ *----------------------------------------------------------------------------
+*/
+EAS_I16 EAS_VolumeToGain (EAS_INT volume)
+{
+ /* check for limits */
+ if (volume <= 0)
+ return 0;
+ if (volume >= 100)
+ return 0x7fff;
+
+ /*lint -e{702} use shift instead of division */
+ return (EAS_I16) EAS_Calculate2toX((((volume - EAS_MAX_VOLUME) * 204099) >> 10) - 1);
+}
+
diff --git a/arm-wt-22k/lib_src/eas_math.h b/arm-wt-22k/lib_src/eas_math.h
new file mode 100644
index 0000000..719270b
--- /dev/null
+++ b/arm-wt-22k/lib_src/eas_math.h
@@ -0,0 +1,412 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_math.h
+ *
+ * Contents and purpose:
+ * Contains common math routines for the various audio engines.
+ *
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 584 $
+ * $Date: 2007-03-08 09:49:24 -0800 (Thu, 08 Mar 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+#ifndef _EAS_MATH_H
+#define _EAS_MATH_H
+
+
+/** coefs for pan, generates sin, cos */
+#define COEFF_PAN_G2 -27146 /* -0.82842712474619 = 2 - 4/sqrt(2) */
+#define COEFF_PAN_G0 23170 /* 0.707106781186547 = 1/sqrt(2) */
+
+/*
+coefficients for approximating
+2^x = gn2toX0 + gn2toX1*x + gn2toX2*x^2 + gn2toX3*x^3
+where x is a int.frac number representing number of octaves.
+Actually, we approximate only the 2^(frac) using the power series
+and implement the 2^(int) as a shift, so that
+2^x == 2^(int.frac) == 2^(int) * 2^(fract)
+ == (gn2toX0 + gn2toX1*x + gn2toX2*x^2 + gn2toX3*x^3) << (int)
+
+The gn2toX.. were generated using a best fit for a 3rd
+order polynomial, instead of taking the coefficients from
+a truncated Taylor (or Maclaurin?) series.
+*/
+
+#define GN2_TO_X0 32768 /* 1 */
+#define GN2_TO_X1 22833 /* 0.696807861328125 */
+#define GN2_TO_X2 7344 /* 0.22412109375 */
+#define GN2_TO_X3 2588 /* 0.0789794921875 */
+
+/*----------------------------------------------------------------------------
+ * Fixed Point Math
+ *----------------------------------------------------------------------------
+ * These macros are used for fixed point multiplies. If the processor
+ * supports fixed point multiplies, replace these macros with inline
+ * assembly code to improve performance.
+ *----------------------------------------------------------------------------
+*/
+
+/* Fixed point multiply 0.15 x 0.15 = 0.15 returned as 32-bits */
+#define FMUL_15x15(a,b) \
+ /*lint -e(704) <avoid multiply for performance>*/ \
+ (((EAS_I32)(a) * (EAS_I32)(b)) >> 15)
+
+/* Fixed point multiply 0.7 x 0.7 = 0.15 returned as 32-bits */
+#define FMUL_7x7(a,b) \
+ /*lint -e(704) <avoid multiply for performance>*/ \
+ (((EAS_I32)(a) * (EAS_I32)(b) ) << 1)
+
+/* Fixed point multiply 0.8 x 0.8 = 0.15 returned as 32-bits */
+#define FMUL_8x8(a,b) \
+ /*lint -e(704) <avoid multiply for performance>*/ \
+ (((EAS_I32)(a) * (EAS_I32)(b) ) >> 1)
+
+/* Fixed point multiply 0.8 x 1.15 = 0.15 returned as 32-bits */
+#define FMUL_8x15(a,b) \
+ /*lint -e(704) <avoid divide for performance>*/ \
+ (((EAS_I32)((a) << 7) * (EAS_I32)(b)) >> 15)
+
+/* macros for fractional phase accumulator */
+/*
+Note: changed the _U32 to _I32 on 03/14/02. This should not
+affect the phase calculations, and should allow us to reuse these
+macros for other audio sample related math.
+*/
+#define HARDWARE_BIT_WIDTH 32
+
+#define NUM_PHASE_INT_BITS 1
+#define NUM_PHASE_FRAC_BITS 15
+
+#define PHASE_FRAC_MASK (EAS_U32) ((0x1L << NUM_PHASE_FRAC_BITS) -1)
+
+#define GET_PHASE_INT_PART(x) (EAS_U32)((EAS_U32)(x) >> NUM_PHASE_FRAC_BITS)
+#define GET_PHASE_FRAC_PART(x) (EAS_U32)((EAS_U32)(x) & PHASE_FRAC_MASK)
+
+#define DEFAULT_PHASE_FRAC 0
+#define DEFAULT_PHASE_INT 0
+
+/*
+Linear interpolation calculates:
+output = (1-frac) * sample[n] + (frac) * sample[n+1]
+
+where conceptually 0 <= frac < 1
+
+For a fixed point implementation, frac is actually an integer value
+with an implied binary point one position to the left. The value of
+one (unity) is given by PHASE_ONE
+one half and one quarter are useful for 4-point linear interp.
+*/
+#define PHASE_ONE (EAS_I32) (0x1L << NUM_PHASE_FRAC_BITS)
+
+/*
+ Multiply the signed audio sample by the unsigned fraction.
+- a is the signed audio sample
+- b is the unsigned fraction (cast to signed int as long as coef
+ uses (n-1) or less bits, where n == hardware bit width)
+*/
+#define MULT_AUDIO_COEF(audio,coef) /*lint -e704 <avoid divide for performance>*/ \
+ (EAS_I32)( \
+ ( \
+ ((EAS_I32)(audio)) * ((EAS_I32)(coef)) \
+ ) \
+ >> NUM_PHASE_FRAC_BITS \
+ ) \
+ /* lint +704 <restore checking>*/
+
+/* wet / dry calculation macros */
+#define NUM_WET_DRY_FRAC_BITS 7 // 15
+#define NUM_WET_DRY_INT_BITS 9 // 1
+
+/* define a 1.0 */
+#define WET_DRY_ONE (EAS_I32) ((0x1L << NUM_WET_DRY_FRAC_BITS))
+#define WET_DRY_MINUS_ONE (EAS_I32) (~WET_DRY_ONE)
+#define WET_DRY_FULL_SCALE (EAS_I32) (WET_DRY_ONE - 1)
+
+#define MULT_AUDIO_WET_DRY_COEF(audio,coef) /*lint -e(702) <avoid divide for performance>*/ \
+ (EAS_I32)( \
+ ( \
+ ((EAS_I32)(audio)) * ((EAS_I32)(coef)) \
+ ) \
+ >> NUM_WET_DRY_FRAC_BITS \
+ )
+
+/* Envelope 1 (EG1) calculation macros */
+#define NUM_EG1_INT_BITS 1
+#define NUM_EG1_FRAC_BITS 15
+
+/* the max positive gain used in the synth for EG1 */
+/* SYNTH_FULL_SCALE_EG1_GAIN must match the value in the dls2eas
+converter, otherwise, the values we read from the .eas file are bogus. */
+#define SYNTH_FULL_SCALE_EG1_GAIN (EAS_I32) ((0x1L << NUM_EG1_FRAC_BITS) -1)
+
+/* define a 1.0 */
+#define EG1_ONE (EAS_I32) ((0x1L << NUM_EG1_FRAC_BITS))
+#define EG1_MINUS_ONE (EAS_I32) (~SYNTH_FULL_SCALE_EG1_GAIN)
+
+#define EG1_HALF (EAS_I32) (EG1_ONE/2)
+#define EG1_MINUS_HALF (EAS_I32) (EG1_MINUS_ONE/2)
+
+/*
+We implement the EG1 using a linear gain value, which means that the
+attack segment is handled by incrementing (adding) the linear gain.
+However, EG1 treats the Decay, Sustain, and Release differently than
+the Attack portion. For Decay, Sustain, and Release, the gain is
+linear on dB scale, which is equivalent to exponential damping on
+a linear scale. Because we use a linear gain for EG1, we implement
+the Decay and Release as multiplication (instead of incrementing
+as we did for the attack segment).
+Therefore, we need the following macro to implement the multiplication
+(i.e., exponential damping) during the Decay and Release segments of
+the EG1
+*/
+#define MULT_EG1_EG1(gain,damping) /*lint -e(704) <avoid divide for performance>*/ \
+ (EAS_I32)( \
+ ( \
+ ((EAS_I32)(gain)) * ((EAS_I32)(damping)) \
+ ) \
+ >> NUM_EG1_FRAC_BITS \
+ )
+
+// Use the following macro specifically for the filter, when multiplying
+// the b1 coefficient. The 0 <= |b1| < 2, which therefore might overflow
+// in certain conditions because we store b1 as a 1.15 value.
+// Instead, we could store b1 as b1p (b1' == b1 "prime") where
+// b1p == b1/2, thus ensuring no potential overflow for b1p because
+// 0 <= |b1p| < 1
+// However, during the filter calculation, we must account for the fact
+// that we are using b1p instead of b1, and thereby multiply by
+// an extra factor of 2. Rather than multiply by an extra factor of 2,
+// we can instead shift the result right by one less, hence the
+// modified shift right value of (NUM_EG1_FRAC_BITS -1)
+#define MULT_EG1_EG1_X2(gain,damping) /*lint -e(702) <avoid divide for performance>*/ \
+ (EAS_I32)( \
+ ( \
+ ((EAS_I32)(gain)) * ((EAS_I32)(damping)) \
+ ) \
+ >> (NUM_EG1_FRAC_BITS -1) \
+ )
+
+#define SATURATE_EG1(x) /*lint -e{734} saturation operation */ \
+ ((EAS_I32)(x) > SYNTH_FULL_SCALE_EG1_GAIN) ? (SYNTH_FULL_SCALE_EG1_GAIN) : \
+ ((EAS_I32)(x) < EG1_MINUS_ONE) ? (EG1_MINUS_ONE) : (x);
+
+
+/* use "digital cents" == "dents" instead of cents */
+/* we coudl re-use the phase frac macros, but if we do,
+we must change the phase macros to cast to _I32 instead of _U32,
+because using a _U32 cast causes problems when shifting the exponent
+for the 2^x calculation, because right shift a negative values MUST
+be sign extended, or else the 2^x calculation is wrong */
+
+/* use "digital cents" == "dents" instead of cents */
+#define NUM_DENTS_FRAC_BITS 12
+#define NUM_DENTS_INT_BITS (HARDWARE_BIT_WIDTH - NUM_DENTS_FRAC_BITS)
+
+#define DENTS_FRAC_MASK (EAS_I32) ((0x1L << NUM_DENTS_FRAC_BITS) -1)
+
+#define GET_DENTS_INT_PART(x) /*lint -e(704) <avoid divide for performance>*/ \
+ (EAS_I32)((EAS_I32)(x) >> NUM_DENTS_FRAC_BITS)
+
+#define GET_DENTS_FRAC_PART(x) (EAS_I32)((EAS_I32)(x) & DENTS_FRAC_MASK)
+
+#define DENTS_ONE (EAS_I32) (0x1L << NUM_DENTS_FRAC_BITS)
+
+/* use CENTS_TO_DENTS to convert a value in cents to dents */
+#define CENTS_TO_DENTS (EAS_I32) (DENTS_ONE * (0x1L << NUM_EG1_FRAC_BITS) / 1200L) \
+
+
+/*
+For gain, the LFO generates a value that modulates in terms
+of dB. However, we use a linear gain value, so we must convert
+the LFO value in dB to a linear gain. Normally, we would use
+linear gain = 10^x, where x = LFO value in dB / 20.
+Instead, we implement 10^x using our 2^x approximation.
+because
+
+ 10^x = 2^(log2(10^x)) = 2^(x * log2(10))
+
+so we need to multiply by log2(10) which is just a constant.
+Ah, but just wait -- our 2^x actually doesn't exactly implement
+2^x, but it actually assumes that the input is in cents, and within
+the 2^x approximation converts its input from cents to octaves
+by dividing its input by 1200.
+
+So, in order to convert the LFO gain value in dB to something
+that our existing 2^x approximation can use, multiply the LFO gain
+by log2(10) * 1200 / 20
+
+The divide by 20 helps convert dB to linear gain, and we might
+as well incorporate that operation into this conversion.
+Of course, we need to keep some fractional bits, so multiply
+the constant by NUM_EG1_FRAC_BITS
+*/
+
+/* use LFO_GAIN_TO_CENTS to convert the LFO gain value to cents */
+#if 0
+#define DOUBLE_LOG2_10 (double) (3.32192809488736) /* log2(10) */
+
+#define DOUBLE_LFO_GAIN_TO_CENTS (double) \
+ ( \
+ (DOUBLE_LOG2_10) * \
+ 1200.0 / \
+ 20.0 \
+ )
+
+#define LFO_GAIN_TO_CENTS (EAS_I32) \
+ ( \
+ DOUBLE_LFO_GAIN_TO_CENTS * \
+ (0x1L << NUM_EG1_FRAC_BITS) \
+ )
+#endif
+
+#define LFO_GAIN_TO_CENTS (EAS_I32) (1671981156L >> (23 - NUM_EG1_FRAC_BITS))
+
+
+#define MULT_DENTS_COEF(dents,coef) /*lint -e704 <avoid divide for performance>*/ \
+ (EAS_I32)( \
+ ( \
+ ((EAS_I32)(dents)) * ((EAS_I32)(coef)) \
+ ) \
+ >> NUM_DENTS_FRAC_BITS \
+ ) \
+ /* lint +e704 <restore checking>*/
+
+/* we use 16-bits in the PC per audio sample */
+#define BITS_PER_AUDIO_SAMPLE 16
+
+/* we define 1 as 1.0 - 1 LSbit */
+#define DISTORTION_ONE (EAS_I32)((0x1L << (BITS_PER_AUDIO_SAMPLE-1)) -1)
+#define DISTORTION_MINUS_ONE (EAS_I32)(~DISTORTION_ONE)
+
+/* drive coef is given as int.frac */
+#define NUM_DRIVE_COEF_INT_BITS 1
+#define NUM_DRIVE_COEF_FRAC_BITS 4
+
+#define MULT_AUDIO_DRIVE(audio,drive) /*lint -e(702) <avoid divide for performance>*/ \
+ (EAS_I32) ( \
+ ( \
+ ((EAS_I32)(audio)) * ((EAS_I32)(drive)) \
+ ) \
+ >> NUM_DRIVE_COEF_FRAC_BITS \
+ )
+
+#define MULT_AUDIO_AUDIO(audio1,audio2) /*lint -e(702) <avoid divide for performance>*/ \
+ (EAS_I32) ( \
+ ( \
+ ((EAS_I32)(audio1)) * ((EAS_I32)(audio2)) \
+ ) \
+ >> (BITS_PER_AUDIO_SAMPLE-1) \
+ )
+
+#define SATURATE(x) \
+ ((((EAS_I32)(x)) > DISTORTION_ONE) ? (DISTORTION_ONE) : \
+ (((EAS_I32)(x)) < DISTORTION_MINUS_ONE) ? (DISTORTION_MINUS_ONE) : ((EAS_I32)(x)));
+
+
+
+/*----------------------------------------------------------------------------
+ * EAS_Calculate2toX()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Calculate 2^x
+ *
+ * Inputs:
+ * nCents - measured in cents
+ *
+ * Outputs:
+ * nResult - int.frac result (where frac has NUM_DENTS_FRAC_BITS)
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_I32 EAS_Calculate2toX (EAS_I32 nCents);
+
+/*----------------------------------------------------------------------------
+ * EAS_LogToLinear16()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Transform log value to linear gain multiplier using piece-wise linear
+ * approximation
+ *
+ * Inputs:
+ * nGain - log scale value in 20.10 format. Even though gain is normally
+ * stored in 6.10 (16-bit) format we use 32-bit numbers here to eliminate
+ * the need for saturation checking when combining gain values.
+ *
+ * Outputs:
+ * Returns a 16-bit linear value approximately equal to 2^(nGain/1024)
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_U16 EAS_LogToLinear16 (EAS_I32 nGain);
+
+/*----------------------------------------------------------------------------
+ * EAS_VolumeToGain()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Transform volume control in 1dB increments to gain multiplier
+ *
+ * Inputs:
+ * volume - 100 = 0dB, 99 = -1dB, 0 = -inf
+ *
+ * Outputs:
+ * Returns a 16-bit linear value
+ *----------------------------------------------------------------------------
+*/
+EAS_I16 EAS_VolumeToGain (EAS_INT volume);
+
+/*----------------------------------------------------------------------------
+ * EAS_fsqrt()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Calculates the square root of a 32-bit fixed point value
+ *
+ * Inputs:
+ * n = value of interest
+ *
+ * Outputs:
+ * returns the square root of n
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_U16 EAS_fsqrt (EAS_U32 n);
+
+/*----------------------------------------------------------------------------
+ * EAS_flog2()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Calculates the log2 of a 32-bit fixed point value
+ *
+ * Inputs:
+ * n = value of interest
+ *
+ * Outputs:
+ * returns the log2 of n
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_I32 EAS_flog2 (EAS_U32 n);
+
+#endif
+
diff --git a/arm-wt-22k/lib_src/eas_mdls.c b/arm-wt-22k/lib_src/eas_mdls.c
new file mode 100644
index 0000000..3da3b06
--- /dev/null
+++ b/arm-wt-22k/lib_src/eas_mdls.c
@@ -0,0 +1,2668 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_mdls.c
+ *
+ * Contents and purpose:
+ * This file contains DLS to EAS converter.
+ *
+ * Copyright (c) 2005 Sonic Network Inc.
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 818 $
+ * $Date: 2007-08-02 15:19:41 -0700 (Thu, 02 Aug 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+/*
+ * NOTES:
+ *
+ * Processor Endian-ness:
+ *
+ * We use the EAS_HWGetDWord() and EAS_HWGetWord () functions
+ * extensively in this module. It would probably be faster to read
+ * an entire data structure, but this introduces the problem of
+ * sensitivity to processor endian-ness to the parser. By utlilizing
+ * the host wrapper functions, we avoid having to flip bytes around
+ * for big-endian processors. The default host wrapper versions of
+ * these functions are insensitive to processor endian-ness due to
+ * the fact that they read the file as a byte stream.
+ *
+ * Dynamic Memory:
+ *
+ * Dynamic memory allocation is a risky proposition in a mobile
+ * device. The memory can become fragmented, resulting in an
+ * inability to allocate a memory block, or garbage collection
+ * routines can use many CPU cycles. Either can contribute to
+ * failures of critical systems. Therefore, we try to minimize the
+ * number of memory allocations we make.
+ *
+ * We allocate a single large block of memory for the entire
+ * converted DLS collection, including the articulation data and
+ * samples. This block is then sub-allocated for the various
+ * data structures.
+ *
+ * Parser Overview:
+ *
+ * We make two passes through the file, the first pass to count the
+ * number of instruments, regions, etc. and allocate memory for
+ * them. The second pass parses the data into the allocated data
+ * structures.
+ *
+ * Conditional chunks are challenging in that they can occur
+ * anywhere in the list chunk that contains them. To simplify, we
+ * parse the blocks in a list in specific order, no matter which
+ * order they appear in the file. This way we don't allocate memory
+ * and parse a block that we end up throwing away later due to
+ * a conditional chunk.
+ *
+ * Assumptions that may bite us in the future:
+ *
+ * We make some assumptions to simplify things. The most fundamental
+ * assumption is that there will be no more than one of any type of
+ * chunk in a list. While this is consistent with the block diagram
+ * of the file layout in the mDLS spec, there is nothing in the
+ * spec that precludes having mulitple lar2 or rgn2 chunks, with
+ * conditional blocks that dictate their usage.
+ *
+ * DLS -> EAS Conversion Process:
+ *
+ * Another challenge is that the DLS structure does not map well to
+ * the current EAS sound library structure. Not all DLS constructs
+ * are supported, and data from DLS structures must sometimes be
+ * mapped to multiple EAS data structures. To simplify the process,
+ * the EAS region, articulation, and envelopes are treated as a
+ * single combined unit. Thus for each region, there must be one
+ * articulation element and two envelope elements.
+ *
+ * The sample processing is also a multi-step process. First the
+ * ptbl chunk is pre-parsed to determine the number of samples
+ * in the collection. The next step is to parse the instrument data
+ * to determine which samples are actually used by instruments.
+ * Some samples may not be used because they are used only in
+ * conditional blocks that the synthesizer cannot parse, or the
+ * author neglected to remove unused samples from the collection.
+ * In the next step, the active samples are read into memory and
+ * converted to the appropriate playback format. Finally, as the
+ * instruments are processed, the links are made to the samples and
+ * wsmp data is extracted for the region and articulation data
+ * structures.
+*/
+
+#ifndef _FILTER_ENABLED
+#error "Filter must be enabled if DLS_SYNTHESIZER is enabled"
+#endif
+
+/*------------------------------------
+ * includes
+ *------------------------------------
+*/
+
+/* this define allows us to use the sndlib.h structures as RW memory */
+#define SCNST
+
+#include "eas_data.h"
+#include "eas_host.h"
+#include "eas_mdls.h"
+#include "eas_math.h"
+#include "dls.h"
+#include "dls2.h"
+#include "eas_report.h"
+
+//2 we should replace log10() function with fixed point routine in ConvertSampleRate()
+/* lint is choking on the ARM math.h file, so we declare the log10 function here */
+extern double log10(double x);
+
+/*------------------------------------
+ * defines
+ *------------------------------------
+*/
+
+// #define _DEBUG_DLS
+
+#define DLS_MAX_WAVE_COUNT 1024
+#define DLS_MAX_ART_COUNT 2048
+#define DLS_MAX_REGION_COUNT 2048
+#define DLS_MAX_INST_COUNT 256
+#define MAX_DLS_WAVE_SIZE (1024*1024)
+
+/*------------------------------------
+ * typedefs
+ *------------------------------------
+*/
+
+/* offsets to articulation data */
+typedef enum
+{
+ PARAM_MODIFIED = 0,
+ PARAM_MOD_LFO_FREQ,
+ PARAM_MOD_LFO_DELAY,
+
+ PARAM_VIB_LFO_FREQ,
+ PARAM_VIB_LFO_DELAY,
+
+ PARAM_VOL_EG_DELAY,
+ PARAM_VOL_EG_ATTACK,
+ PARAM_VOL_EG_HOLD,
+ PARAM_VOL_EG_DECAY,
+ PARAM_VOL_EG_SUSTAIN,
+ PARAM_VOL_EG_RELEASE,
+ PARAM_VOL_EG_SHUTDOWN,
+ PARAM_VOL_EG_VEL_TO_ATTACK,
+ PARAM_VOL_EG_KEY_TO_DECAY,
+ PARAM_VOL_EG_KEY_TO_HOLD,
+
+ PARAM_MOD_EG_DELAY,
+ PARAM_MOD_EG_ATTACK,
+ PARAM_MOD_EG_HOLD,
+ PARAM_MOD_EG_DECAY,
+ PARAM_MOD_EG_SUSTAIN,
+ PARAM_MOD_EG_RELEASE,
+ PARAM_MOD_EG_VEL_TO_ATTACK,
+ PARAM_MOD_EG_KEY_TO_DECAY,
+ PARAM_MOD_EG_KEY_TO_HOLD,
+
+ PARAM_INITIAL_FC,
+ PARAM_INITIAL_Q,
+ PARAM_MOD_LFO_TO_FC,
+ PARAM_MOD_LFO_CC1_TO_FC,
+ PARAM_MOD_LFO_CHAN_PRESS_TO_FC,
+ PARAM_MOD_EG_TO_FC,
+ PARAM_VEL_TO_FC,
+ PARAM_KEYNUM_TO_FC,
+
+ PARAM_MOD_LFO_TO_GAIN,
+ PARAM_MOD_LFO_CC1_TO_GAIN,
+ PARAM_MOD_LFO_CHAN_PRESS_TO_GAIN,
+ PARAM_VEL_TO_GAIN,
+
+ PARAM_TUNING,
+ PARAM_KEYNUM_TO_PITCH,
+ PARAM_VIB_LFO_TO_PITCH,
+ PARAM_VIB_LFO_CC1_TO_PITCH,
+ PARAM_VIB_LFO_CHAN_PRESS_TO_PITCH,
+ PARAM_MOD_LFO_TO_PITCH,
+ PARAM_MOD_LFO_CC1_TO_PITCH,
+ PARAM_MOD_LFO_CHAN_PRESS_TO_PITCH,
+ PARAM_MOD_EG_TO_PITCH,
+
+ PARAM_DEFAULT_PAN,
+ PARAM_MIDI_CC91_TO_REVERB_SEND,
+ PARAM_DEFAULT_REVERB_SEND,
+ PARAM_MIDI_CC93_TO_CHORUS_SEND,
+ PARAM_DEFAULT_CHORUS_SEND,
+ PARAM_TABLE_SIZE
+} E_ART_INDEX;
+
+/* temporary data structure combining region, articulation, and envelope data */
+typedef struct s_art_dls_tag
+{
+ EAS_I16 values[PARAM_TABLE_SIZE];
+} S_DLS_ART_VALUES;
+
+/* temporary data structure for wlnk chunk data */
+typedef struct
+{
+ EAS_I32 gain;
+ EAS_U32 loopStart;
+ EAS_U32 loopLength;
+ EAS_U32 sampleRate;
+ EAS_U16 bitsPerSample;
+ EAS_I16 fineTune;
+ EAS_U8 unityNote;
+} S_WSMP_DATA;
+
+/* temporary data structure used while parsing a DLS file */
+typedef struct
+{
+ S_DLS *pDLS;
+ EAS_HW_DATA_HANDLE hwInstData;
+ EAS_FILE_HANDLE fileHandle;
+ S_WSMP_DATA *wsmpData;
+ EAS_U32 instCount;
+ EAS_U32 regionCount;
+ EAS_U32 artCount;
+ EAS_U32 waveCount;
+ EAS_U32 wavePoolSize;
+ EAS_U32 wavePoolOffset;
+ EAS_BOOL bigEndian;
+ EAS_BOOL filterUsed;
+} SDLS_SYNTHESIZER_DATA;
+
+/* connection lookup table */
+typedef struct s_connection_tag
+{
+ EAS_U16 source;
+ EAS_U16 control;
+ EAS_U16 destination;
+ EAS_U16 connection;
+} S_CONNECTION;
+
+static const S_CONNECTION connTable[] =
+{
+ { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_LFO_FREQUENCY, PARAM_MOD_LFO_FREQ },
+ { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_LFO_STARTDELAY, PARAM_MOD_LFO_DELAY},
+
+ { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_VIB_FREQUENCY, PARAM_VIB_LFO_FREQ },
+ { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_VIB_STARTDELAY, PARAM_VIB_LFO_DELAY },
+
+ { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG1_DELAYTIME, PARAM_VOL_EG_DELAY },
+ { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG1_ATTACKTIME, PARAM_VOL_EG_ATTACK },
+ { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG1_HOLDTIME, PARAM_VOL_EG_HOLD },
+ { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG1_DECAYTIME, PARAM_VOL_EG_DECAY },
+ { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG1_SUSTAINLEVEL, PARAM_VOL_EG_SUSTAIN },
+ { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG1_RELEASETIME, PARAM_VOL_EG_RELEASE },
+ { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG1_SHUTDOWNTIME, PARAM_VOL_EG_SHUTDOWN },
+ { CONN_SRC_KEYONVELOCITY, CONN_SRC_NONE, CONN_DST_EG1_ATTACKTIME, PARAM_VOL_EG_VEL_TO_ATTACK },
+ { CONN_SRC_KEYNUMBER, CONN_SRC_NONE, CONN_DST_EG1_DECAYTIME, PARAM_VOL_EG_KEY_TO_DECAY },
+ { CONN_SRC_KEYNUMBER, CONN_SRC_NONE, CONN_DST_EG1_HOLDTIME, PARAM_VOL_EG_KEY_TO_HOLD },
+
+ { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG2_DELAYTIME, PARAM_MOD_EG_DELAY },
+ { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG2_ATTACKTIME, PARAM_MOD_EG_ATTACK },
+ { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG2_HOLDTIME, PARAM_MOD_EG_HOLD },
+ { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG2_DECAYTIME, PARAM_MOD_EG_DECAY },
+ { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG2_SUSTAINLEVEL, PARAM_MOD_EG_SUSTAIN },
+ { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG2_RELEASETIME, PARAM_MOD_EG_RELEASE },
+ { CONN_SRC_KEYONVELOCITY, CONN_SRC_NONE, CONN_DST_EG2_ATTACKTIME, PARAM_MOD_EG_VEL_TO_ATTACK },
+ { CONN_SRC_KEYNUMBER, CONN_SRC_NONE, CONN_DST_EG2_DECAYTIME, PARAM_MOD_EG_KEY_TO_DECAY },
+ { CONN_SRC_KEYNUMBER, CONN_SRC_NONE, CONN_DST_EG2_HOLDTIME, PARAM_MOD_EG_KEY_TO_HOLD },
+
+ { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_FILTER_CUTOFF, PARAM_INITIAL_FC },
+ { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_FILTER_Q, PARAM_INITIAL_Q },
+ { CONN_SRC_LFO, CONN_SRC_NONE, CONN_DST_FILTER_CUTOFF, PARAM_MOD_LFO_TO_FC },
+ { CONN_SRC_LFO, CONN_SRC_CC1, CONN_DST_FILTER_CUTOFF, PARAM_MOD_LFO_CC1_TO_FC },
+ { CONN_SRC_LFO, CONN_SRC_CHANNELPRESSURE, CONN_DST_FILTER_CUTOFF, PARAM_MOD_LFO_CHAN_PRESS_TO_FC },
+ { CONN_SRC_EG2, CONN_SRC_NONE, CONN_DST_FILTER_CUTOFF, PARAM_MOD_EG_TO_FC },
+ { CONN_SRC_KEYONVELOCITY, CONN_SRC_NONE, CONN_DST_FILTER_CUTOFF, PARAM_VEL_TO_FC },
+ { CONN_SRC_KEYNUMBER, CONN_SRC_NONE, CONN_DST_FILTER_CUTOFF, PARAM_KEYNUM_TO_FC },
+
+ { CONN_SRC_LFO, CONN_SRC_NONE, CONN_DST_GAIN, PARAM_MOD_LFO_TO_GAIN },
+ { CONN_SRC_LFO, CONN_SRC_CC1, CONN_DST_GAIN, PARAM_MOD_LFO_CC1_TO_GAIN },
+ { CONN_SRC_LFO, CONN_SRC_CHANNELPRESSURE, CONN_DST_GAIN, PARAM_MOD_LFO_CHAN_PRESS_TO_GAIN },
+ { CONN_SRC_KEYONVELOCITY, CONN_SRC_NONE, CONN_DST_GAIN, PARAM_VEL_TO_GAIN },
+
+ { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_PITCH, PARAM_TUNING },
+ { CONN_SRC_KEYNUMBER, CONN_SRC_NONE, CONN_DST_PITCH, PARAM_KEYNUM_TO_PITCH },
+ { CONN_SRC_VIBRATO, CONN_SRC_NONE, CONN_DST_PITCH, PARAM_VIB_LFO_TO_PITCH },
+ { CONN_SRC_VIBRATO, CONN_SRC_CC1, CONN_DST_PITCH, PARAM_VIB_LFO_CC1_TO_PITCH },
+ { CONN_SRC_VIBRATO, CONN_SRC_CHANNELPRESSURE, CONN_DST_PITCH, PARAM_VIB_LFO_CHAN_PRESS_TO_PITCH },
+ { CONN_SRC_LFO, CONN_SRC_NONE, CONN_DST_PITCH, PARAM_MOD_LFO_TO_PITCH },
+ { CONN_SRC_LFO, CONN_SRC_CC1, CONN_DST_PITCH, PARAM_MOD_LFO_CC1_TO_PITCH },
+ { CONN_SRC_LFO, CONN_SRC_CHANNELPRESSURE, CONN_DST_PITCH, PARAM_MOD_LFO_CHAN_PRESS_TO_PITCH },
+ { CONN_SRC_EG2, CONN_SRC_NONE, CONN_DST_PITCH, PARAM_MOD_EG_TO_PITCH },
+
+ { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_PAN, PARAM_DEFAULT_PAN },
+ { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_REVERB, PARAM_DEFAULT_REVERB_SEND },
+ { CONN_SRC_CC91, CONN_SRC_NONE, CONN_DST_REVERB, PARAM_MIDI_CC91_TO_REVERB_SEND },
+ { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_CHORUS, PARAM_DEFAULT_CHORUS_SEND },
+ { CONN_SRC_CC93, CONN_SRC_NONE, CONN_DST_REVERB, PARAM_MIDI_CC93_TO_CHORUS_SEND }
+};
+#define ENTRIES_IN_CONN_TABLE (sizeof(connTable)/sizeof(S_CONNECTION))
+
+static const S_DLS_ART_VALUES defaultArt =
+{
+ 0, /* not modified */
+ -851, /* Mod LFO frequency: 5 Hz */
+ -7973, /* Mod LFO delay: 10 milliseconds */
+
+ -851, /* Vib LFO frequency: 5 Hz */
+ -7973, /* Vib LFO delay: 10 milliseconds */
+
+ -32768, /* EG1 delay time: 0 secs */
+ -32768, /* EG1 attack time: 0 secs */
+ -32768, /* EG1 hold time: 0 secs */
+ -32768, /* EG1 decay time: 0 secs */
+ 1000, /* EG1 sustain level: 100.0% */
+ -32768, /* EG1 release time: 0 secs */
+ -7271, /* EG1 shutdown time: 15 msecs */
+ 0, /* EG1 velocity to attack: 0 time cents */
+ 0, /* EG1 key number to decay: 0 time cents */
+ 0, /* EG1 key number to hold: 0 time cents */
+
+ -32768, /* EG2 delay time: 0 secs */
+ -32768, /* EG2 attack time: 0 secs */
+ -32768, /* EG2 hold time: 0 secs */
+ -32768, /* EG2 decay time: 0 secs */
+ 1000, /* EG2 sustain level: 100.0% */
+ -32768, /* EG2 release time: 0 secs */
+ 0, /* EG2 velocity to attack: 0 time cents */
+ 0, /* EG2 key number to decay: 0 time cents */
+ 0, /* EG2 key number to hold: 0 time cents */
+
+ 0x7fff, /* Initial Fc: Disabled */
+ 0, /* Initial Q: 0 dB */
+ 0, /* Mod LFO to Fc: 0 cents */
+ 0, /* Mod LFO CC1 to Fc: 0 cents */
+ 0, /* Mod LFO channel pressure to Fc: 0 cents */
+ 0, /* EG2 to Fc: 0 cents */
+ 0, /* Velocity to Fc: 0 cents */
+ 0, /* Key number to Fc: 0 cents */
+
+ 0, /* Mod LFO to gain: 0 dB */
+ 0, /* Mod LFO CC1 to gain: 0 dB */
+ 0, /* Mod LFO channel pressure to gain: 0 dB */
+ 960, /* Velocity to gain: 96 dB */
+
+ 0, /* Tuning: 0 cents */
+ 12800, /* Key number to pitch: 12,800 cents */
+ 0, /* Vibrato to pitch: 0 cents */
+ 0, /* Vibrato CC1 to pitch: 0 cents */
+ 0, /* Vibrato channel pressure to pitch: 0 cents */
+ 0, /* Mod LFO to pitch: 0 cents */
+ 0, /* Mod LFO CC1 to pitch: 0 cents */
+ 0, /* Mod LFO channel pressure to pitch: 0 cents */
+ 0, /* Mod EG to pitch: 0 cents */
+
+ 0, /* Default pan: 0.0% */
+ 0, /* Default reverb send: 0.0% */
+ 1000, /* Default CC91 to reverb send: 100.0% */
+ 0, /* Default chorus send: 0.0% */
+ 1000 /* Default CC93 to chorus send: 100.0% */
+};
+
+/*------------------------------------
+ * local variables
+ *------------------------------------
+*/
+
+#if defined(_8_BIT_SAMPLES)
+static const EAS_INT bitDepth = 8;
+#elif defined(_16_BIT_SAMPLES)
+static const EAS_INT bitDepth = 16;
+#else
+#error "Must define _8_BIT_SAMPLES or _16_BIT_SAMPLES"
+#endif
+
+static const EAS_U32 outputSampleRate = _OUTPUT_SAMPLE_RATE;
+static const EAS_I32 dlsRateConvert = DLS_RATE_CONVERT;
+static const EAS_I32 dlsLFOFrequencyConvert = DLS_LFO_FREQUENCY_CONVERT;
+
+/*------------------------------------
+ * inline functions
+ *------------------------------------
+*/
+EAS_INLINE void *PtrOfs (void *p, EAS_I32 offset)
+{
+ return (void*) (((EAS_U8*) p) + offset);
+}
+
+/*------------------------------------
+ * prototypes
+ *------------------------------------
+*/
+static EAS_RESULT NextChunk (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 *pPos, EAS_U32 *pChunkType, EAS_I32 *pSize);
+static EAS_RESULT Parse_ptbl (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 wsmpPos, EAS_I32 wsmpSize);
+static EAS_RESULT Parse_wave (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_U16 waveIndex);
+static EAS_RESULT Parse_wsmp (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, S_WSMP_DATA *p);
+static EAS_RESULT Parse_fmt (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, S_WSMP_DATA *p);
+static EAS_RESULT Parse_data (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size, S_WSMP_DATA *p, EAS_SAMPLE *pSample);
+static EAS_RESULT Parse_lins(SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size);
+static EAS_RESULT Parse_ins (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size);
+static EAS_RESULT Parse_insh (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_U32 *pRgnCount, EAS_U32 *pLocale);
+static EAS_RESULT Parse_lrgn (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size, EAS_U16 artIndex, EAS_U32 numRegions);
+static EAS_RESULT Parse_rgn (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size, EAS_U16 artIndex);
+static EAS_RESULT Parse_rgnh (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, S_DLS_REGION *pRgn);
+static EAS_RESULT Parse_lart (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size, S_DLS_ART_VALUES *pArt);
+static EAS_RESULT Parse_art (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, S_DLS_ART_VALUES *pArt);
+static EAS_RESULT Parse_wlnk (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_U32 *pWaveIndex);
+static EAS_RESULT Parse_cdl (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 size, EAS_U32 *pValue);
+static void Convert_rgn (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_U16 regionIndex, EAS_U16 artIndex, EAS_U16 waveIndex, S_WSMP_DATA *pWsmp);
+static void Convert_art (SDLS_SYNTHESIZER_DATA *pDLSData, const S_DLS_ART_VALUES *pDLSArt, EAS_U16 artIndex);
+static EAS_I16 ConvertSampleRate (EAS_U32 sampleRate);
+static EAS_I16 ConvertSustain (EAS_I32 sustain);
+static EAS_I16 ConvertLFOPhaseIncrement (EAS_I32 pitchCents);
+static EAS_I8 ConvertPan (EAS_I32 pan);
+static EAS_U8 ConvertQ (EAS_I32 q);
+
+#ifdef _DEBUG_DLS
+static void DumpDLS (S_EAS *pEAS);
+#endif
+
+
+/*----------------------------------------------------------------------------
+ * DLSParser ()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ * Inputs:
+ * pEASData - pointer to over EAS data instance
+ * fileHandle - file handle for input file
+ * offset - offset into file where DLS data starts
+ *
+ * Outputs:
+ * EAS_RESULT
+ * ppEAS - address of pointer to alternate EAS wavetable
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT DLSParser (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_I32 offset, EAS_DLSLIB_HANDLE *ppDLS)
+{
+ EAS_RESULT result;
+ SDLS_SYNTHESIZER_DATA dls;
+ EAS_U32 temp;
+ EAS_I32 pos;
+ EAS_I32 chunkPos;
+ EAS_I32 size;
+ EAS_I32 instSize;
+ EAS_I32 rgnPoolSize;
+ EAS_I32 artPoolSize;
+ EAS_I32 waveLenSize;
+ EAS_I32 endDLS;
+ EAS_I32 wvplPos;
+ EAS_I32 wvplSize;
+ EAS_I32 linsPos;
+ EAS_I32 linsSize;
+ EAS_I32 ptblPos;
+ EAS_I32 ptblSize;
+ void *p;
+
+ /* zero counts and pointers */
+ EAS_HWMemSet(&dls, 0, sizeof(dls));
+
+ /* save file handle and hwInstData to save copying pointers around */
+ dls.hwInstData = hwInstData;
+ dls.fileHandle = fileHandle;
+
+ /* NULL return value in case of error */
+ *ppDLS = NULL;
+
+ /* seek to start of DLS and read in RIFF tag and set processor endian flag */
+ if ((result = EAS_HWFileSeek(dls.hwInstData, dls.fileHandle, offset)) != EAS_SUCCESS)
+ return result;
+ if ((result = EAS_HWReadFile(dls.hwInstData, dls.fileHandle, &temp, sizeof(temp), &size)) != EAS_SUCCESS)
+ return result;
+
+ /* check for processor endian-ness */
+ dls.bigEndian = (temp == CHUNK_RIFF);
+
+ /* first chunk should be DLS */
+ pos = offset;
+ if ((result = NextChunk(&dls, &pos, &temp, &size)) != EAS_SUCCESS)
+ return result;
+ if (temp != CHUNK_DLS)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Expected DLS chunk, got %08lx\n", temp); */ }
+ return EAS_ERROR_FILE_FORMAT;
+ }
+
+ /* no instrument or wavepool chunks */
+ linsSize = wvplSize = ptblSize = linsPos = wvplPos = ptblPos = 0;
+
+ /* scan the chunks in the DLS list */
+ endDLS = offset + size;
+ pos = offset + 12;
+ while (pos < endDLS)
+ {
+ chunkPos = pos;
+
+ /* get the next chunk type */
+ if ((result = NextChunk(&dls, &pos, &temp, &size)) != EAS_SUCCESS)
+ return result;
+
+ /* parse useful chunks */
+ switch (temp)
+ {
+ case CHUNK_CDL:
+ if ((result = Parse_cdl(&dls, size, &temp)) != EAS_SUCCESS)
+ return result;
+ if (!temp)
+ return EAS_ERROR_UNRECOGNIZED_FORMAT;
+ break;
+
+ case CHUNK_LINS:
+ linsPos = chunkPos + 12;
+ linsSize = size - 4;
+ break;
+
+ case CHUNK_WVPL:
+ wvplPos = chunkPos + 12;
+ wvplSize = size - 4;
+ break;
+
+ case CHUNK_PTBL:
+ ptblPos = chunkPos + 8;
+ ptblSize = size - 4;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /* must have a lins chunk */
+ if (linsSize == 0)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "No lins chunk found"); */ }
+ return EAS_ERROR_UNRECOGNIZED_FORMAT;
+ }
+
+ /* must have a wvpl chunk */
+ if (wvplSize == 0)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "No wvpl chunk found"); */ }
+ return EAS_ERROR_UNRECOGNIZED_FORMAT;
+ }
+
+ /* must have a ptbl chunk */
+ if ((ptblSize == 0) || (ptblSize > DLS_MAX_WAVE_COUNT * sizeof(POOLCUE) + sizeof(POOLTABLE)))
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "No ptbl chunk found"); */ }
+ return EAS_ERROR_UNRECOGNIZED_FORMAT;
+ }
+
+ /* pre-parse the wave pool chunk */
+ if ((result = Parse_ptbl(&dls, ptblPos, wvplPos, wvplSize)) != EAS_SUCCESS)
+ return result;
+
+ /* limit check */
+ if ((dls.waveCount == 0) || (dls.waveCount > DLS_MAX_WAVE_COUNT))
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS file contains invalid #waves [%u]\n", dls.waveCount); */ }
+ return EAS_ERROR_FILE_FORMAT;
+ }
+
+ /* allocate memory for wsmp data */
+ dls.wsmpData = EAS_HWMalloc(dls.hwInstData, (EAS_I32) (sizeof(S_WSMP_DATA) * dls.waveCount));
+ if (dls.wsmpData == NULL)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_HWMalloc for wsmp data failed\n"); */ }
+ return EAS_ERROR_MALLOC_FAILED;
+ }
+ EAS_HWMemSet(dls.wsmpData, 0, (EAS_I32) (sizeof(S_WSMP_DATA) * dls.waveCount));
+
+ /* pre-parse the lins chunk */
+ result = Parse_lins(&dls, linsPos, linsSize);
+ if (result == EAS_SUCCESS)
+ {
+
+ /* limit check */
+ if ((dls.regionCount == 0) || (dls.regionCount > DLS_MAX_REGION_COUNT))
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS file contains invalid #regions [%u]\n", dls.regionCount); */ }
+ return EAS_ERROR_FILE_FORMAT;
+ }
+
+ /* limit check */
+ if ((dls.artCount == 0) || (dls.artCount > DLS_MAX_ART_COUNT))
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS file contains invalid #articulations [%u]\n", dls.regionCount); */ }
+ return EAS_ERROR_FILE_FORMAT;
+ }
+
+ /* limit check */
+ if ((dls.instCount == 0) || (dls.instCount > DLS_MAX_INST_COUNT))
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS file contains invalid #instruments [%u]\n", dls.instCount); */ }
+ return EAS_ERROR_FILE_FORMAT;
+ }
+
+ /* Allocate memory for the converted DLS data */
+ /* calculate size of instrument data */
+ instSize = (EAS_I32) (sizeof(S_PROGRAM) * dls.instCount);
+
+ /* calculate size of region pool */
+ rgnPoolSize = (EAS_I32) (sizeof(S_DLS_REGION) * dls.regionCount);
+
+ /* calculate size of articulation pool, add one for default articulation */
+ dls.artCount++;
+ artPoolSize = (EAS_I32) (sizeof(S_DLS_ARTICULATION) * dls.artCount);
+
+ /* calculate size of wave length and offset arrays */
+ waveLenSize = (EAS_I32) (dls.waveCount * sizeof(EAS_U32));
+
+ /* calculate final memory size */
+ size = (EAS_I32) sizeof(S_EAS) + instSize + rgnPoolSize + artPoolSize + (2 * waveLenSize) + (EAS_I32) dls.wavePoolSize;
+ if (size <= 0) {
+ return EAS_ERROR_FILE_FORMAT;
+ }
+
+ /* allocate the main EAS chunk */
+ dls.pDLS = EAS_HWMalloc(dls.hwInstData, size);
+ if (dls.pDLS == NULL)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_HWMalloc failed for DLS memory allocation size %ld\n", size); */ }
+ return EAS_ERROR_MALLOC_FAILED;
+ }
+ EAS_HWMemSet(dls.pDLS, 0, size);
+ dls.pDLS->refCount = 1;
+ p = PtrOfs(dls.pDLS, sizeof(S_EAS));
+
+ /* setup pointer to programs */
+ dls.pDLS->numDLSPrograms = (EAS_U16) dls.instCount;
+ dls.pDLS->pDLSPrograms = p;
+ p = PtrOfs(p, instSize);
+
+ /* setup pointer to regions */
+ dls.pDLS->pDLSRegions = p;
+ dls.pDLS->numDLSRegions = (EAS_U16) dls.regionCount;
+ p = PtrOfs(p, rgnPoolSize);
+
+ /* setup pointer to articulations */
+ dls.pDLS->numDLSArticulations = (EAS_U16) dls.artCount;
+ dls.pDLS->pDLSArticulations = p;
+ p = PtrOfs(p, artPoolSize);
+
+ /* setup pointer to wave length table */
+ dls.pDLS->numDLSSamples = (EAS_U16) dls.waveCount;
+ dls.pDLS->pDLSSampleLen = p;
+ p = PtrOfs(p, waveLenSize);
+
+ /* setup pointer to wave offsets table */
+ dls.pDLS->pDLSSampleOffsets = p;
+ p = PtrOfs(p, waveLenSize);
+
+ /* setup pointer to wave pool */
+ dls.pDLS->pDLSSamples = p;
+
+ /* clear filter flag */
+ dls.filterUsed = EAS_FALSE;
+
+ /* parse the wave pool and load samples */
+ result = Parse_ptbl(&dls, ptblPos, wvplPos, wvplSize);
+ }
+
+ /* create the default articulation */
+ Convert_art(&dls, &defaultArt, 0);
+ dls.artCount = 1;
+
+ /* parse the lins chunk and load instruments */
+ dls.regionCount = dls.instCount = 0;
+ if (result == EAS_SUCCESS)
+ result = Parse_lins(&dls, linsPos, linsSize);
+
+ /* clean up any temporary objects that were allocated */
+ if (dls.wsmpData)
+ EAS_HWFree(dls.hwInstData, dls.wsmpData);
+
+ /* if successful, return a pointer to the EAS collection */
+ if (result == EAS_SUCCESS)
+ {
+ *ppDLS = dls.pDLS;
+#ifdef _DEBUG_DLS
+ DumpDLS(dls.pDLS);
+#endif
+ }
+
+ /* something went wrong, deallocate the EAS collection */
+ else
+ DLSCleanup(dls.hwInstData, dls.pDLS);
+
+ return result;
+}
+
+/*----------------------------------------------------------------------------
+ * DLSCleanup ()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ * Inputs:
+ * pEASData - pointer to over EAS data instance
+ * pEAS - pointer to alternate EAS wavetable
+ *
+ * Outputs:
+ * EAS_RESULT
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT DLSCleanup (EAS_HW_DATA_HANDLE hwInstData, S_DLS *pDLS)
+{
+
+ /* free the allocated memory */
+ if (pDLS)
+ {
+ if (pDLS->refCount)
+ {
+ if (--pDLS->refCount == 0)
+ EAS_HWFree(hwInstData, pDLS);
+ }
+ }
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * DLSAddRef ()
+ *----------------------------------------------------------------------------
+ * Increment reference count
+ *----------------------------------------------------------------------------
+*/
+void DLSAddRef (S_DLS *pDLS)
+{
+ if (pDLS)
+ pDLS->refCount++;
+}
+
+/*----------------------------------------------------------------------------
+ * NextChunk ()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Returns the type and size of the next chunk in the file
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT NextChunk (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 *pPos, EAS_U32 *pChunkType, EAS_I32 *pSize)
+{
+ EAS_RESULT result;
+
+ /* seek to start of chunk */
+ if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, *pPos)) != EAS_SUCCESS)
+ return result;
+
+ /* read the chunk type */
+ if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, pChunkType, EAS_TRUE)) != EAS_SUCCESS)
+ return result;
+
+ /* read the chunk size */
+ if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, pSize, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+
+ /* get form type for RIFF and LIST types */
+ if ((*pChunkType == CHUNK_RIFF) || (*pChunkType == CHUNK_LIST))
+ {
+
+ /* read the form type */
+ if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, pChunkType, EAS_TRUE)) != EAS_SUCCESS)
+ return result;
+
+ }
+
+ /* calculate start of next chunk */
+ *pPos += *pSize + 8;
+
+ /* adjust to word boundary */
+ if (*pPos & 1)
+ (*pPos)++;
+
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * Parse_ptbl ()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT Parse_ptbl (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 wtblPos, EAS_I32 wtblSize)
+{
+ EAS_RESULT result;
+ EAS_U32 temp;
+ EAS_FILE_HANDLE tempFile;
+ EAS_U16 waveIndex;
+
+ /* seek to start of chunk */
+ if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS)
+ return result;
+
+ /* get the structure size */
+ if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &temp, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+
+ /* get the number of waves */
+ if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &pDLSData->waveCount, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+
+#if 0
+ /* just need the wave count on the first pass */
+ if (!pDLSData->pDLS)
+ return EAS_SUCCESS;
+#endif
+
+ /* open duplicate file handle */
+ if ((result = EAS_HWDupHandle(pDLSData->hwInstData, pDLSData->fileHandle, &tempFile)) != EAS_SUCCESS)
+ return result;
+
+ /* read to end of chunk */
+ for (waveIndex = 0; waveIndex < pDLSData->waveCount; waveIndex++)
+ {
+
+ /* get the offset to the wave and make sure it is within the wtbl chunk */
+ if ((result = EAS_HWGetDWord(pDLSData->hwInstData, tempFile, &temp, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+ if (temp > (EAS_U32) wtblSize)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Ptbl offset exceeds size of wtbl\n"); */ }
+ EAS_HWCloseFile(pDLSData->hwInstData, tempFile);
+ return EAS_ERROR_FILE_FORMAT;
+ }
+
+ /* parse the wave */
+ if ((result = Parse_wave(pDLSData, wtblPos +(EAS_I32) temp, waveIndex)) != EAS_SUCCESS)
+ return result;
+ }
+
+ /* close the temporary handle and return */
+ EAS_HWCloseFile(pDLSData->hwInstData, tempFile);
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * Parse_wave ()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT Parse_wave (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_U16 waveIndex)
+{
+ EAS_RESULT result;
+ EAS_U32 temp;
+ EAS_I32 size;
+ EAS_I32 endChunk;
+ EAS_I32 chunkPos;
+ EAS_I32 wsmpPos = 0;
+ EAS_I32 fmtPos = 0;
+ EAS_I32 dataPos = 0;
+ EAS_I32 dataSize = 0;
+ S_WSMP_DATA *p;
+ void *pSample;
+ S_WSMP_DATA wsmp;
+
+ /* seek to start of chunk */
+ chunkPos = pos + 12;
+ if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS)
+ return result;
+
+ /* get the chunk type */
+ if ((result = NextChunk(pDLSData, &pos, &temp, &size)) != EAS_SUCCESS)
+ return result;
+
+ /* make sure it is a wave chunk */
+ if (temp != CHUNK_WAVE)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Offset in ptbl does not point to wave chunk\n"); */ }
+ return EAS_ERROR_FILE_FORMAT;
+ }
+
+ /* read to end of chunk */
+ pos = chunkPos;
+ endChunk = pos + size;
+ while (pos < endChunk)
+ {
+ chunkPos = pos;
+
+ /* get the chunk type */
+ if ((result = NextChunk(pDLSData, &pos, &temp, &size)) != EAS_SUCCESS)
+ return result;
+
+ /* parse useful chunks */
+ switch (temp)
+ {
+ case CHUNK_WSMP:
+ wsmpPos = chunkPos + 8;
+ break;
+
+ case CHUNK_FMT:
+ fmtPos = chunkPos + 8;
+ break;
+
+ case CHUNK_DATA:
+ dataPos = chunkPos + 8;
+ dataSize = size;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ // limit to reasonable size
+ if (dataSize > MAX_DLS_WAVE_SIZE)
+ {
+ return EAS_ERROR_SOUND_LIBRARY;
+ }
+
+ /* for first pass, use temporary variable */
+ if (pDLSData->pDLS == NULL)
+ p = &wsmp;
+ else
+ p = &pDLSData->wsmpData[waveIndex];
+
+ /* set the defaults */
+ p->fineTune = 0;
+ p->unityNote = 60;
+ p->gain = 0;
+ p->loopStart = 0;
+ p->loopLength = 0;
+
+ /* must have a fmt chunk */
+ if (!fmtPos)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS wave chunk has no fmt chunk\n"); */ }
+ return EAS_ERROR_UNRECOGNIZED_FORMAT;
+ }
+
+ /* must have a data chunk */
+ if (!dataPos)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS wave chunk has no data chunk\n"); */ }
+ return EAS_ERROR_UNRECOGNIZED_FORMAT;
+ }
+
+ /* parse the wsmp chunk */
+ if (wsmpPos)
+ {
+ if ((result = Parse_wsmp(pDLSData, wsmpPos, p)) != EAS_SUCCESS)
+ return result;
+ }
+
+ /* parse the fmt chunk */
+ if ((result = Parse_fmt(pDLSData, fmtPos, p)) != EAS_SUCCESS)
+ return result;
+
+ /* calculate the size of the wavetable needed. We need only half
+ * the memory for 16-bit samples when in 8-bit mode, and we need
+ * double the memory for 8-bit samples in 16-bit mode. For
+ * unlooped samples, we may use ADPCM. If so, we need only 1/4
+ * the memory.
+ *
+ * We also need to add one for looped samples to allow for
+ * the first sample to be copied to the end of the loop.
+ */
+
+ /* use ADPCM encode for unlooped 16-bit samples if ADPCM is enabled */
+ /*lint -e{506} -e{774} groundwork for future version to support 8 & 16 bit */
+ if (bitDepth == 8)
+ {
+ if (p->bitsPerSample == 8)
+ size = dataSize;
+ else
+ /*lint -e{704} use shift for performance */
+ size = dataSize >> 1;
+ if (p->loopLength)
+ size++;
+ }
+
+ else
+ {
+ if (p->bitsPerSample == 16)
+ size = dataSize;
+ else
+ /*lint -e{703} use shift for performance */
+ size = dataSize << 1;
+ if (p->loopLength)
+ size += 2;
+ }
+
+ /* for first pass, add size to wave pool size and return */
+ if (pDLSData->pDLS == NULL)
+ {
+ pDLSData->wavePoolSize += (EAS_U32) size;
+ return EAS_SUCCESS;
+ }
+
+ /* allocate memory and read in the sample data */
+ pSample = pDLSData->pDLS->pDLSSamples + pDLSData->wavePoolOffset;
+ pDLSData->pDLS->pDLSSampleOffsets[waveIndex] = pDLSData->wavePoolOffset;
+ pDLSData->pDLS->pDLSSampleLen[waveIndex] = (EAS_U32) size;
+ pDLSData->wavePoolOffset += (EAS_U32) size;
+ if (pDLSData->wavePoolOffset > pDLSData->wavePoolSize)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Wave pool exceeded allocation\n"); */ }
+ return EAS_ERROR_SOUND_LIBRARY;
+ }
+
+ if ((result = Parse_data(pDLSData, dataPos, dataSize, p, pSample)) != EAS_SUCCESS)
+ return result;
+
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * Parse_wsmp ()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT Parse_wsmp (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, S_WSMP_DATA *p)
+{
+ EAS_RESULT result;
+ EAS_U16 wtemp;
+ EAS_U32 ltemp;
+ EAS_U32 cbSize;
+
+ /* seek to start of chunk */
+ if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS)
+ return result;
+
+ /* get structure size */
+ if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &cbSize, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+
+ /* get unity note */
+ if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &wtemp, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+ if (wtemp <= 127)
+ p->unityNote = (EAS_U8) wtemp;
+ else
+ {
+ p->unityNote = 60;
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Invalid unity note [%u] in DLS wsmp ignored, set to 60\n", wtemp); */ }
+ }
+
+ /* get fine tune */
+ if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &p->fineTune, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+
+ /* get gain */
+ if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &p->gain, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+ if (p->gain > 0)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Positive gain [%ld] in DLS wsmp ignored, set to 0dB\n", p->gain); */ }
+ p->gain = 0;
+ }
+
+ /* option flags */
+ if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &ltemp, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+
+ /* sample loops */
+ if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &ltemp, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+
+ /* if looped sample, get loop data */
+ if (ltemp)
+ {
+
+ if (ltemp > 1)
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "DLS sample with %lu loops, ignoring extra loops\n", ltemp); */ }
+
+ /* skip ahead to loop data */
+ if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos + (EAS_I32) cbSize)) != EAS_SUCCESS)
+ return result;
+
+ /* get structure size */
+ if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &ltemp, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+
+ /* get loop type */
+ if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &ltemp, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+
+ /* get loop start */
+ if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &p->loopStart, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+
+ /* get loop length */
+ if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &p->loopLength, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+ }
+
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * Parse_fmt ()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT Parse_fmt (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, S_WSMP_DATA *p)
+{
+ EAS_RESULT result;
+ EAS_U16 wtemp;
+ EAS_U32 ltemp;
+
+ /* seek to start of chunk */
+ if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS)
+ return result;
+
+ /* get format tag */
+ if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &wtemp, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+ if (wtemp != WAVE_FORMAT_PCM)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unsupported DLS sample format %04x\n", wtemp); */ }
+ return EAS_ERROR_UNRECOGNIZED_FORMAT;
+ }
+
+ /* get number of channels */
+ if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &wtemp, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+ if (wtemp != 1)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "No support for DLS multi-channel samples\n"); */ }
+ return EAS_ERROR_UNRECOGNIZED_FORMAT;
+ }
+
+ /* get sample rate */
+ if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &p->sampleRate, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+
+ /* bytes/sec */
+ if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &ltemp, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+
+ /* block align */
+ if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &wtemp, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+
+ /* bits/sample */
+ if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &p->bitsPerSample, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+
+ if ((p->bitsPerSample != 8) && (p->bitsPerSample != 16))
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unsupported DLS bits-per-sample %d\n", p->bitsPerSample); */ }
+ return EAS_ERROR_UNRECOGNIZED_FORMAT;
+ }
+
+ return EAS_SUCCESS;
+}
+
+#if defined( _8_BIT_SAMPLES)
+/*----------------------------------------------------------------------------
+ * Parse_data ()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ * NOTE: The optimized assembly versions of the interpolator require
+ * an extra sample at the end of the loop - a copy of the first
+ * sample. This routine must allocate an extra sample of data and
+ * copy the first sample of the loop to the end.
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT Parse_data (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size, S_WSMP_DATA *pWsmp, EAS_SAMPLE *pSample)
+{
+ EAS_RESULT result;
+ EAS_U8 convBuf[SAMPLE_CONVERT_CHUNK_SIZE];
+ EAS_I32 count;
+ EAS_I32 i;
+ EAS_I8 *p;
+
+ /* seek to start of chunk */
+ if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS)
+ return result;
+
+ /* 8-bit samples in an 8-bit synth, just copy the data, and flip bit 7 */
+ p = pSample;
+ if (pWsmp->bitsPerSample == 8)
+ {
+ if ((result = EAS_HWReadFile(pDLSData->hwInstData, pDLSData->fileHandle, pSample, size, &count)) != EAS_SUCCESS)
+ return result;
+ for (i = 0; i < size; i++)
+ /*lint -e{734} convert from unsigned to signed audio */
+ *p++ ^= 0x80;
+ }
+
+ /* 16-bit samples, need to convert to 8-bit or ADPCM */
+ else
+ {
+
+ while (size)
+ {
+ EAS_I8 *pInput;
+
+ /* for undithered conversion, we're just copying the 8-bit data */
+ if (pDLSData->bigEndian)
+ pInput = (EAS_I8*) convBuf;
+ else
+ pInput = (EAS_I8*) convBuf + 1;
+
+ /* read a small chunk of data and convert it */
+ count = (size < SAMPLE_CONVERT_CHUNK_SIZE ? size : SAMPLE_CONVERT_CHUNK_SIZE);
+ if ((result = EAS_HWReadFile(pDLSData->hwInstData, pDLSData->fileHandle, convBuf, count, &count)) != EAS_SUCCESS)
+ return result;
+ size -= count;
+ /*lint -e{704} use shift for performance */
+ count = count >> 1;
+
+ while (count--)
+ {
+ *p++ = *pInput;
+ pInput += 2;
+ }
+ }
+ }
+
+ /* for looped samples, copy the last sample to the end */
+ if (pWsmp->loopLength)
+ pSample[pWsmp->loopStart + pWsmp->loopLength] = pSample[pWsmp->loopStart];
+
+ return EAS_SUCCESS;
+}
+#elif defined(_16_BIT_SAMPLES)
+#error "16-bit DLS conversion not implemented yet"
+#else
+#error "Must specifiy _8_BIT_SAMPLES or _16_BIT_SAMPLES"
+#endif
+
+/*----------------------------------------------------------------------------
+ * Parse_lins ()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT Parse_lins (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size)
+{
+ EAS_RESULT result;
+ EAS_U32 temp;
+ EAS_I32 endChunk;
+ EAS_I32 chunkPos;
+
+ /* seek to start of chunk */
+ if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS)
+ return result;
+
+ /* read to end of chunk */
+ endChunk = pos + size;
+ while (pos < endChunk)
+ {
+ chunkPos = pos;
+
+ /* get the next chunk type */
+ if ((result = NextChunk(pDLSData, &pos, &temp, &size)) != EAS_SUCCESS)
+ return result;
+
+ /* only instrument chunks are useful */
+ if (temp != CHUNK_INS)
+ continue;
+
+ if ((result = Parse_ins(pDLSData, chunkPos + 12, size)) != EAS_SUCCESS)
+ return result;
+ }
+
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * Parse_ins ()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT Parse_ins (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size)
+{
+ EAS_RESULT result;
+ EAS_U32 temp;
+ EAS_I32 chunkPos;
+ EAS_I32 endChunk;
+ EAS_I32 lrgnPos;
+ EAS_I32 lrgnSize;
+ EAS_I32 lartPos;
+ EAS_I32 lartSize;
+ EAS_I32 lar2Pos;
+ EAS_I32 lar2Size;
+ EAS_I32 inshPos;
+ EAS_U32 regionCount;
+ EAS_U32 locale;
+ S_DLS_ART_VALUES art;
+ S_PROGRAM *pProgram;
+ EAS_U16 artIndex;
+
+ /* seek to start of chunk */
+ if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS)
+ return result;
+
+ /* no chunks yet */
+ lrgnPos = lrgnSize = lartPos = lartSize = lar2Pos = lar2Size = inshPos = artIndex = 0;
+
+ /* read to end of chunk */
+ endChunk = pos + size;
+ while (pos < endChunk)
+ {
+ chunkPos = pos;
+
+ /* get the next chunk type */
+ if ((result = NextChunk(pDLSData, &pos, &temp, &size)) != EAS_SUCCESS)
+ return result;
+
+ /* parse useful chunks */
+ switch (temp)
+ {
+ case CHUNK_INSH:
+ inshPos = chunkPos + 8;
+ break;
+
+ case CHUNK_LART:
+ lartPos = chunkPos + 12;
+ lartSize = size;
+ break;
+
+ case CHUNK_LAR2:
+ lar2Pos = chunkPos + 12;
+ lar2Size = size;
+ break;
+
+ case CHUNK_LRGN:
+ lrgnPos = chunkPos + 12;
+ lrgnSize = size;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /* must have an lrgn to be useful */
+ if (!lrgnPos)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS ins chunk has no lrgn chunk\n"); */ }
+ return EAS_ERROR_UNRECOGNIZED_FORMAT;
+ }
+
+ /* must have an insh to be useful */
+ if (!inshPos)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS ins chunk has no insh chunk\n"); */ }
+ return EAS_ERROR_UNRECOGNIZED_FORMAT;
+ }
+
+ /* parse the instrument header */
+ if ((result = Parse_insh(pDLSData, inshPos, &regionCount, &locale)) != EAS_SUCCESS)
+ return result;
+
+ /* initialize and parse the global data first */
+ EAS_HWMemCpy(&art, &defaultArt, sizeof(S_DLS_ART_VALUES));
+ if (lartPos)
+ if ((result = Parse_lart(pDLSData, lartPos, lartSize, &art)) != EAS_SUCCESS)
+ return result;
+ if (lar2Pos)
+ if ((result = Parse_lart(pDLSData, lar2Pos, lar2Size, &art)) != EAS_SUCCESS)
+ return result;
+
+ if (art.values[PARAM_MODIFIED])
+ {
+ artIndex = (EAS_U16) pDLSData->artCount;
+ pDLSData->artCount++;
+ }
+
+ /* convert data on second pass */
+ if (pDLSData->pDLS)
+ {
+
+ if (art.values[PARAM_MODIFIED])
+ Convert_art(pDLSData, &art, artIndex);
+
+ /* setup pointers */
+ pProgram = &pDLSData->pDLS->pDLSPrograms[pDLSData->instCount];
+
+ /* initialize instrument */
+ pProgram->locale = locale;
+ pProgram->regionIndex = (EAS_U16) pDLSData->regionCount | FLAG_RGN_IDX_DLS_SYNTH;
+
+ }
+
+ /* parse the region data */
+ if ((result = Parse_lrgn(pDLSData, lrgnPos, lrgnSize, artIndex, regionCount)) != EAS_SUCCESS)
+ return result;
+
+ /* bump instrument count */
+ pDLSData->instCount++;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * Parse_insh ()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT Parse_insh (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_U32 *pRgnCount, EAS_U32 *pLocale)
+{
+ EAS_RESULT result;
+ EAS_U32 bank;
+ EAS_U32 program;
+
+ /* seek to start of chunk */
+ if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS)
+ return result;
+
+ /* get the region count and locale */
+ if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, pRgnCount, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+ if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &bank, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+ if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &program, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+
+ /* verify the parameters are valid */
+ if (bank & 0x7fff8080)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "DLS bank number is out of range: %08lx\n", bank); */ }
+ bank &= 0xff7f;
+ }
+ if (program > 127)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "DLS program number is out of range: %08lx\n", program); */ }
+ program &= 0x7f;
+ }
+
+ /* save the program number */
+ *pLocale = (bank << 8) | program;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * Parse_lrgn ()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT Parse_lrgn (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size, EAS_U16 artIndex, EAS_U32 numRegions)
+{
+ EAS_RESULT result;
+ EAS_U32 temp;
+ EAS_I32 chunkPos;
+ EAS_I32 endChunk;
+ EAS_U16 regionCount;
+
+ /* seek to start of chunk */
+ if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS)
+ return result;
+
+ /* read to end of chunk */
+ regionCount = 0;
+ endChunk = pos + size;
+ while (pos < endChunk)
+ {
+ chunkPos = pos;
+
+ /* get the next chunk type */
+ if ((result = NextChunk(pDLSData, &pos, &temp, &size)) != EAS_SUCCESS)
+ return result;
+
+ if ((temp == CHUNK_RGN) || (temp == CHUNK_RGN2))
+ {
+ if (regionCount == numRegions)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "DLS region count exceeded cRegions value in insh, extra region ignored\n"); */ }
+ return EAS_SUCCESS;
+ }
+ if ((result = Parse_rgn(pDLSData, chunkPos + 12, size, artIndex)) != EAS_SUCCESS)
+ return result;
+ regionCount++;
+ }
+ }
+
+ /* set a flag in the last region */
+ if ((pDLSData->pDLS != NULL) && (regionCount > 0))
+ pDLSData->pDLS->pDLSRegions[pDLSData->regionCount - 1].wtRegion.region.keyGroupAndFlags |= REGION_FLAG_LAST_REGION;
+
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * Parse_rgn ()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT Parse_rgn (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size, EAS_U16 artIndex)
+{
+ EAS_RESULT result;
+ EAS_U32 temp;
+ EAS_I32 chunkPos;
+ EAS_I32 endChunk;
+ EAS_I32 rgnhPos;
+ EAS_I32 lartPos;
+ EAS_I32 lartSize;
+ EAS_I32 lar2Pos;
+ EAS_I32 lar2Size;
+ EAS_I32 wlnkPos;
+ EAS_I32 wsmpPos;
+ EAS_U32 waveIndex;
+ S_DLS_ART_VALUES art;
+ S_WSMP_DATA wsmp;
+ S_WSMP_DATA *pWsmp;
+ EAS_U16 regionIndex;
+
+ /* seek to start of chunk */
+ if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS)
+ return result;
+
+ /* no chunks found yet */
+ rgnhPos = lartPos = lartSize = lar2Pos = lar2Size = wsmpPos = wlnkPos = 0;
+ regionIndex = (EAS_U16) pDLSData->regionCount;
+
+ /* read to end of chunk */
+ endChunk = pos + size;
+ while (pos < endChunk)
+ {
+ chunkPos = pos;
+
+ /* get the next chunk type */
+ if ((result = NextChunk(pDLSData, &pos, &temp, &size)) != EAS_SUCCESS)
+ return result;
+
+ /* parse useful chunks */
+ switch (temp)
+ {
+ case CHUNK_CDL:
+ if ((result = Parse_cdl(pDLSData, size, &temp)) != EAS_SUCCESS)
+ return result;
+
+ /* if conditional chunk evaluates false, skip this list */
+ if (!temp)
+ return EAS_SUCCESS;
+ break;
+
+ case CHUNK_RGNH:
+ rgnhPos = chunkPos + 8;
+ break;
+
+ case CHUNK_WLNK:
+ wlnkPos = chunkPos + 8;
+ break;
+
+ case CHUNK_WSMP:
+ wsmpPos = chunkPos + 8;
+ break;
+
+ case CHUNK_LART:
+ lartPos = chunkPos + 12;
+ lartSize = size;
+ break;
+
+ case CHUNK_LAR2:
+ lar2Pos = chunkPos + 12;
+ lar2Size = size;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /* must have a rgnh chunk to be useful */
+ if (!rgnhPos)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS rgn chunk has no rgnh chunk\n"); */ }
+ return EAS_ERROR_UNRECOGNIZED_FORMAT;
+ }
+
+ /* must have a wlnk chunk to be useful */
+ if (!wlnkPos)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS rgn chunk has no wlnk chunk\n"); */ }
+ return EAS_ERROR_UNRECOGNIZED_FORMAT;
+ }
+
+ /* parse wlnk chunk */
+ if ((result = Parse_wlnk(pDLSData, wlnkPos, &waveIndex)) != EAS_SUCCESS)
+ return result;
+ pWsmp = &pDLSData->wsmpData[waveIndex];
+
+ /* if there is any articulation data, parse it */
+ EAS_HWMemCpy(&art, &defaultArt, sizeof(S_DLS_ART_VALUES));
+ if (lartPos)
+ {
+ if ((result = Parse_lart(pDLSData, lartPos, lartSize, &art)) != EAS_SUCCESS)
+ return result;
+ }
+
+ if (lar2Pos)
+ {
+ if ((result = Parse_lart(pDLSData, lar2Pos, lar2Size, &art)) != EAS_SUCCESS)
+ return result;
+ }
+
+ /* if second pass, process region header */
+ if (pDLSData->pDLS)
+ {
+
+ /* if local data was found convert it */
+ if (art.values[PARAM_MODIFIED] == EAS_TRUE)
+ {
+ Convert_art(pDLSData, &art, (EAS_U16) pDLSData->artCount);
+ artIndex = (EAS_U16) pDLSData->artCount;
+ }
+
+ /* parse region header */
+ if ((result = Parse_rgnh(pDLSData, rgnhPos, &pDLSData->pDLS->pDLSRegions[regionIndex & REGION_INDEX_MASK])) != EAS_SUCCESS)
+ return result;
+
+ /* parse wsmp chunk, copying parameters from original first */
+ if (wsmpPos)
+ {
+ EAS_HWMemCpy(&wsmp, pWsmp, sizeof(wsmp));
+ if ((result = Parse_wsmp(pDLSData, wsmpPos, &wsmp)) != EAS_SUCCESS)
+ return result;
+
+ pWsmp = &wsmp;
+ }
+
+ Convert_rgn(pDLSData, regionIndex, artIndex, (EAS_U16) waveIndex, pWsmp);
+ }
+
+ /* if local articulation, bump count */
+ if (art.values[PARAM_MODIFIED])
+ pDLSData->artCount++;
+
+ /* increment region count */
+ pDLSData->regionCount++;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * Parse_rgnh ()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT Parse_rgnh (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, S_DLS_REGION *pRgn)
+{
+ EAS_RESULT result;
+ EAS_U16 lowKey;
+ EAS_U16 highKey;
+ EAS_U16 lowVel;
+ EAS_U16 highVel;
+ EAS_U16 optionFlags;
+ EAS_U16 keyGroup;
+
+ /* seek to start of chunk */
+ if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS)
+ return result;
+
+ /* get the key range */
+ if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &lowKey, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+ if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &highKey, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+
+ /* check the range */
+ if (lowKey > 127)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "DLS rgnh: Low key out of range [%u]\n", lowKey); */ }
+ lowKey = 127;
+ }
+ if (highKey > 127)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "DLS rgnh: High key out of range [%u]\n", lowKey); */ }
+ highKey = 127;
+ }
+
+ /* get the velocity range */
+ if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &lowVel, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+ if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &highVel, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+
+ /* check the range */
+ if (lowVel > 127)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "DLS rgnh: Low velocity out of range [%u]\n", lowVel); */ }
+ lowVel = 127;
+ }
+ if (highVel > 127)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "DLS rgnh: High velocity out of range [%u]\n", highVel); */ }
+ highVel = 127;
+ }
+
+ /* get the option flags */
+ if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &optionFlags, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+
+ /* get the key group */
+ if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &keyGroup, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+
+ /* save the key range and key group */
+ pRgn->wtRegion.region.rangeLow = (EAS_U8) lowKey;
+ pRgn->wtRegion.region.rangeHigh = (EAS_U8) highKey;
+
+ /*lint -e{734} keyGroup will always be from 0-15 */
+ pRgn->wtRegion.region.keyGroupAndFlags = keyGroup << 8;
+ pRgn->velLow = (EAS_U8) lowVel;
+ pRgn->velHigh = (EAS_U8) highVel;
+ if (optionFlags & F_RGN_OPTION_SELFNONEXCLUSIVE)
+ pRgn->wtRegion.region.keyGroupAndFlags |= REGION_FLAG_NON_SELF_EXCLUSIVE;
+
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * Parse_lart ()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT Parse_lart (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size, S_DLS_ART_VALUES *pArt)
+{
+ EAS_RESULT result;
+ EAS_U32 temp;
+ EAS_I32 endChunk;
+ EAS_I32 chunkPos;
+ EAS_I32 art1Pos;
+ EAS_I32 art2Pos;
+
+ /* seek to start of chunk */
+ if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS)
+ return result;
+
+ /* no articulation chunks yet */
+ art1Pos = art2Pos = 0;
+
+ /* read to end of chunk */
+ endChunk = pos + size;
+ while (pos < endChunk)
+ {
+ chunkPos = pos;
+
+ /* get the next chunk type */
+ if ((result = NextChunk(pDLSData, &pos, &temp, &size)) != EAS_SUCCESS)
+ return result;
+
+ /* parse useful chunks */
+ switch (temp)
+ {
+ case CHUNK_CDL:
+ if ((result = Parse_cdl(pDLSData, size, &temp)) != EAS_SUCCESS)
+ return result;
+
+ /* if conditional chunk evaluates false, skip this list */
+ if (!temp)
+ return EAS_SUCCESS;
+ break;
+
+ case CHUNK_ART1:
+ art1Pos = chunkPos + 8;
+ break;
+
+ case CHUNK_ART2:
+ art2Pos = chunkPos + 8;
+ break;
+
+ default:
+ break;
+
+ }
+ }
+
+ if (art1Pos)
+ {
+ if ((result = Parse_art(pDLSData, art1Pos, pArt)) != EAS_SUCCESS)
+ return result;
+ }
+
+ if (art2Pos)
+ {
+ if ((result = Parse_art(pDLSData, art2Pos, pArt)) != EAS_SUCCESS)
+ return result;
+ }
+
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * Parse_art()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT Parse_art (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, S_DLS_ART_VALUES *pArt)
+{
+ EAS_RESULT result;
+ EAS_U32 structSize;
+ EAS_U32 numConnections;
+ EAS_U16 source;
+ EAS_U16 control;
+ EAS_U16 destination;
+ EAS_U16 transform;
+ EAS_I32 scale;
+ EAS_INT i;
+
+ /* seek to start of data */
+ if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS)
+ return result;
+
+ /* get the structure size */
+ if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &structSize, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+ pos += (EAS_I32) structSize;
+
+ /* get the number of connections */
+ if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &numConnections, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+
+ /* skip to start of connections */
+ if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS)
+ return result;
+
+ while (numConnections--)
+ {
+
+ /* read the connection data */
+ if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &source, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+ if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &control, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+ if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &destination, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+ if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &transform, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+ if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &scale, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+
+ /* look up the connection */
+ for (i = 0; i < (EAS_INT) ENTRIES_IN_CONN_TABLE; i++)
+ {
+ if ((connTable[i].source == source) &&
+ (connTable[i].destination == destination) &&
+ (connTable[i].control == control))
+ {
+ /*lint -e{704} use shift for performance */
+ pArt->values[connTable[i].connection] = (EAS_I16) (scale >> 16);
+ pArt->values[PARAM_MODIFIED] = EAS_TRUE;
+ break;
+ }
+ }
+ if (i == PARAM_TABLE_SIZE)
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "WARN: Unsupported parameter in DLS file\n"); */ }
+ }
+
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * Parse_wlnk ()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT Parse_wlnk (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_U32 *pWaveIndex)
+{
+ EAS_RESULT result;
+
+ /* we only care about the the index */
+ if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos + 8)) != EAS_SUCCESS)
+ return result;
+
+ /* read the index */
+ return EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle,pWaveIndex, EAS_FALSE);
+}
+
+/*----------------------------------------------------------------------------
+ * PopcdlStack ()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT PopcdlStack (EAS_U32 *pStack, EAS_INT *pStackPtr, EAS_U32 *pValue)
+{
+
+ /* stack underflow, cdl block has an errorr */
+ if (*pStackPtr < 0)
+ return EAS_ERROR_FILE_FORMAT;
+
+ /* pop the value off the stack */
+ *pValue = pStack[*pStackPtr];
+ *pStackPtr = *pStackPtr - 1;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * PushcdlStack ()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT PushcdlStack (EAS_U32 *pStack, EAS_INT *pStackPtr, EAS_U32 value)
+{
+
+ /* stack overflow, return an error */
+ if (*pStackPtr >= CDL_STACK_SIZE)
+ return EAS_ERROR_FILE_FORMAT;
+
+ /* push the value onto the stack */
+ *pStackPtr = *pStackPtr + 1;
+ pStack[*pStackPtr] = value;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * QueryGUID ()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_BOOL QueryGUID (const DLSID *pGUID, EAS_U32 *pValue)
+{
+
+ /* assume false */
+ *pValue = 0;
+ if (EAS_HWMemCmp(&DLSID_GMInHardware, pGUID, sizeof(DLSID)) == 0)
+ {
+ *pValue = 0xffffffff;
+ return EAS_TRUE;
+ }
+
+ if (EAS_HWMemCmp(&DLSID_GSInHardware, pGUID, sizeof(DLSID)) == 0)
+ return EAS_TRUE;
+
+ if (EAS_HWMemCmp(&DLSID_XGInHardware, pGUID, sizeof(DLSID)) == 0)
+ return EAS_TRUE;
+
+ if (EAS_HWMemCmp(&DLSID_SupportsDLS1, pGUID, sizeof(DLSID)) == 0)
+ {
+ *pValue = 0xffffffff;
+ return EAS_TRUE;
+ }
+
+ if (EAS_HWMemCmp(&DLSID_SupportsDLS2, pGUID, sizeof(DLSID)) == 0)
+ return EAS_TRUE;
+
+ if (EAS_HWMemCmp(&DLSID_SampleMemorySize, pGUID, sizeof(DLSID)) == 0)
+ {
+ *pValue = MAX_DLS_MEMORY;
+ return EAS_TRUE;
+ }
+
+ if (EAS_HWMemCmp(&DLSID_ManufacturersID, pGUID, sizeof(DLSID)) == 0)
+ {
+ *pValue = 0x0000013A;
+ return EAS_TRUE;
+ }
+
+ if (EAS_HWMemCmp(&DLSID_ProductID, pGUID, sizeof(DLSID)) == 0)
+ {
+ *pValue = LIB_VERSION;
+ return EAS_TRUE;
+ }
+
+ if (EAS_HWMemCmp(&DLSID_SamplePlaybackRate, pGUID, sizeof(DLSID)) == 0)
+ {
+ *pValue = (EAS_U32) outputSampleRate;
+ return EAS_TRUE;
+ }
+
+ /* unrecognized DLSID */
+ return EAS_FALSE;
+}
+
+/*----------------------------------------------------------------------------
+ * ReadDLSID ()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Reads a DLSID in a manner that is not sensitive to processor endian-ness
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT ReadDLSID (SDLS_SYNTHESIZER_DATA *pDLSData, DLSID *pDLSID)
+{
+ EAS_RESULT result;
+ EAS_I32 n;
+
+ if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &pDLSID->Data1, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+ if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &pDLSID->Data2, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+ if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &pDLSID->Data3, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+ return EAS_HWReadFile(pDLSData->hwInstData, pDLSData->fileHandle, pDLSID->Data4, sizeof(pDLSID->Data4), &n);
+}
+
+/*----------------------------------------------------------------------------
+ * Parse_cdl ()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT Parse_cdl (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 size, EAS_U32 *pValue)
+{
+ EAS_RESULT result;
+ EAS_U32 stack[CDL_STACK_SIZE];
+ EAS_U16 opcode;
+ EAS_INT stackPtr;
+ EAS_U32 x, y;
+ DLSID dlsid;
+
+ stackPtr = -1;
+ *pValue = 0;
+ x = 0;
+ while (size)
+ {
+ /* read the opcode */
+ if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &opcode, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+
+ /* handle binary opcodes */
+ if (opcode <= DLS_CDL_EQ)
+ {
+ /* pop X and Y */
+ if ((result = PopcdlStack(stack, &stackPtr, &x)) != EAS_SUCCESS)
+ return result;
+ if ((result = PopcdlStack(stack, &stackPtr, &y)) != EAS_SUCCESS)
+ return result;
+ switch (opcode)
+ {
+ case DLS_CDL_AND:
+ x = x & y;
+ break;
+ case DLS_CDL_OR:
+ x = x | y;
+ break;
+ case DLS_CDL_XOR:
+ x = x ^ y;
+ break;
+ case DLS_CDL_ADD:
+ x = x + y;
+ break;
+ case DLS_CDL_SUBTRACT:
+ x = x - y;
+ break;
+ case DLS_CDL_MULTIPLY:
+ x = x * y;
+ break;
+ case DLS_CDL_DIVIDE:
+ if (!y)
+ return EAS_ERROR_FILE_FORMAT;
+ x = x / y;
+ break;
+ case DLS_CDL_LOGICAL_AND:
+ x = (x && y);
+ break;
+ case DLS_CDL_LOGICAL_OR:
+ x = (x || y);
+ break;
+ case DLS_CDL_LT:
+ x = (x < y);
+ break;
+ case DLS_CDL_LE:
+ x = (x <= y);
+ break;
+ case DLS_CDL_GT:
+ x = (x > y);
+ break;
+ case DLS_CDL_GE:
+ x = (x >= y);
+ break;
+ case DLS_CDL_EQ:
+ x = (x == y);
+ break;
+ default:
+ break;
+ }
+ }
+
+ else if (opcode == DLS_CDL_NOT)
+ {
+ if ((result = PopcdlStack(stack, &stackPtr, &x)) != EAS_SUCCESS)
+ return result;
+ x = !x;
+ }
+
+ else if (opcode == DLS_CDL_CONST)
+ {
+ if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &x, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+ }
+
+ else if (opcode == DLS_CDL_QUERY)
+ {
+ if ((result = ReadDLSID(pDLSData, &dlsid)) != EAS_SUCCESS)
+ return result;
+ QueryGUID(&dlsid, &x);
+ }
+
+ else if (opcode == DLS_CDL_QUERYSUPPORTED)
+ {
+ if ((result = ReadDLSID(pDLSData, &dlsid)) != EAS_SUCCESS)
+ return result;
+ x = QueryGUID(&dlsid, &y);
+ }
+ else
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Unsupported opcode %d in DLS file\n", opcode); */ }
+
+ /* push the result on the stack */
+ if ((result = PushcdlStack(stack, &stackPtr, x)) != EAS_SUCCESS)
+ return result;
+ }
+
+ /* pop the last result off the stack */
+ return PopcdlStack(stack, &stackPtr, pValue);
+}
+
+/*----------------------------------------------------------------------------
+ * Convert_rgn()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Convert region data from DLS to EAS
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ *----------------------------------------------------------------------------
+*/
+static void Convert_rgn (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_U16 regionIndex, EAS_U16 artIndex, EAS_U16 waveIndex, S_WSMP_DATA *pWsmp)
+{
+ S_DLS_REGION *pRgn;
+
+ /* setup pointers to data structures */
+ pRgn = &pDLSData->pDLS->pDLSRegions[regionIndex];
+
+ /* intiailize indices */
+ pRgn->wtRegion.artIndex = artIndex;
+ pRgn->wtRegion.waveIndex = waveIndex;
+
+ /* convert region data */
+ /*lint -e{704} use shift for performance */
+ pRgn->wtRegion.gain = (EAS_I16) (pWsmp->gain >> 16);
+ pRgn->wtRegion.loopStart = pWsmp->loopStart;
+ pRgn->wtRegion.loopEnd = (pWsmp->loopStart + pWsmp->loopLength);
+ pRgn->wtRegion.tuning = pWsmp->fineTune -(pWsmp->unityNote * 100) + ConvertSampleRate(pWsmp->sampleRate);
+ if (pWsmp->loopLength != 0)
+ pRgn->wtRegion.region.keyGroupAndFlags |= REGION_FLAG_IS_LOOPED;
+}
+
+/*----------------------------------------------------------------------------
+ * Convert_art()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Convert articulation data from DLS to EAS
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ *----------------------------------------------------------------------------
+*/
+static void Convert_art (SDLS_SYNTHESIZER_DATA *pDLSData, const S_DLS_ART_VALUES *pDLSArt, EAS_U16 artIndex)
+{
+ S_DLS_ARTICULATION *pArt;
+
+ /* setup pointers to data structures */
+ pArt = &pDLSData->pDLS->pDLSArticulations[artIndex];
+
+ /* LFO parameters */
+ pArt->modLFO.lfoFreq = ConvertLFOPhaseIncrement(pDLSArt->values[PARAM_MOD_LFO_FREQ]);
+ pArt->modLFO.lfoDelay = -ConvertDelay(pDLSArt->values[PARAM_MOD_LFO_DELAY]);
+ pArt->vibLFO.lfoFreq = ConvertLFOPhaseIncrement(pDLSArt->values[PARAM_VIB_LFO_FREQ]);
+ pArt->vibLFO.lfoDelay = -ConvertDelay(pDLSArt->values[PARAM_VIB_LFO_DELAY]);
+
+ /* EG1 parameters */
+ pArt->eg1.delayTime = ConvertDelay(pDLSArt->values[PARAM_VOL_EG_DELAY]);
+ pArt->eg1.attackTime = pDLSArt->values[PARAM_VOL_EG_ATTACK];
+ pArt->eg1.holdTime = pDLSArt->values[PARAM_VOL_EG_HOLD];
+ pArt->eg1.decayTime = pDLSArt->values[PARAM_VOL_EG_DECAY];
+ pArt->eg1.sustainLevel = ConvertSustain(pDLSArt->values[PARAM_VOL_EG_SUSTAIN]);
+ pArt->eg1.releaseTime = ConvertRate(pDLSArt->values[PARAM_VOL_EG_RELEASE]);
+ pArt->eg1.velToAttack = pDLSArt->values[PARAM_VOL_EG_VEL_TO_ATTACK];
+ pArt->eg1.keyNumToDecay = pDLSArt->values[PARAM_VOL_EG_KEY_TO_DECAY];
+ pArt->eg1.keyNumToHold = pDLSArt->values[PARAM_VOL_EG_KEY_TO_HOLD];
+ pArt->eg1ShutdownTime = ConvertRate(pDLSArt->values[PARAM_VOL_EG_SHUTDOWN]);
+
+ /* EG2 parameters */
+ pArt->eg2.delayTime = ConvertDelay(pDLSArt->values[PARAM_MOD_EG_DELAY]);
+ pArt->eg2.attackTime = pDLSArt->values[PARAM_MOD_EG_ATTACK];
+ pArt->eg2.holdTime = pDLSArt->values[PARAM_MOD_EG_HOLD];
+ pArt->eg2.decayTime = pDLSArt->values[PARAM_MOD_EG_DECAY];
+ pArt->eg2.sustainLevel = ConvertSustain(pDLSArt->values[PARAM_MOD_EG_SUSTAIN]);
+ pArt->eg2.releaseTime = ConvertRate(pDLSArt->values[PARAM_MOD_EG_RELEASE]);
+ pArt->eg2.velToAttack = pDLSArt->values[PARAM_MOD_EG_VEL_TO_ATTACK];
+ pArt->eg2.keyNumToDecay = pDLSArt->values[PARAM_MOD_EG_KEY_TO_DECAY];
+ pArt->eg2.keyNumToHold = pDLSArt->values[PARAM_MOD_EG_KEY_TO_HOLD];
+
+ /* filter parameters */
+ pArt->filterCutoff = pDLSArt->values[PARAM_INITIAL_FC];
+ pArt->filterQandFlags = ConvertQ(pDLSArt->values[PARAM_INITIAL_Q]);
+ pArt->modLFOToFc = pDLSArt->values[PARAM_MOD_LFO_TO_FC];
+ pArt->modLFOCC1ToFc = pDLSArt->values[PARAM_MOD_LFO_CC1_TO_FC];
+ pArt->modLFOChanPressToFc = pDLSArt->values[PARAM_MOD_LFO_CHAN_PRESS_TO_FC];
+ pArt->eg2ToFc = pDLSArt->values[PARAM_MOD_EG_TO_FC];
+ pArt->velToFc = pDLSArt->values[PARAM_VEL_TO_FC];
+ pArt->keyNumToFc = pDLSArt->values[PARAM_KEYNUM_TO_FC];
+
+ /* gain parameters */
+ pArt->modLFOToGain = pDLSArt->values[PARAM_MOD_LFO_TO_GAIN];
+ pArt->modLFOCC1ToGain = pDLSArt->values[PARAM_MOD_LFO_CC1_TO_GAIN];
+ pArt->modLFOChanPressToGain = pDLSArt->values[PARAM_MOD_LFO_CHAN_PRESS_TO_GAIN];
+
+ /* pitch parameters */
+ pArt->tuning = pDLSArt->values[PARAM_TUNING];
+ pArt->keyNumToPitch = pDLSArt->values[PARAM_KEYNUM_TO_PITCH];
+ pArt->vibLFOToPitch = pDLSArt->values[PARAM_VIB_LFO_TO_PITCH];
+ pArt->vibLFOCC1ToPitch = pDLSArt->values[PARAM_VIB_LFO_CC1_TO_PITCH];
+ pArt->vibLFOChanPressToPitch = pDLSArt->values[PARAM_VIB_LFO_CHAN_PRESS_TO_PITCH];
+ pArt->modLFOToPitch = pDLSArt->values[PARAM_MOD_LFO_TO_PITCH];
+ pArt->modLFOCC1ToPitch = pDLSArt->values[PARAM_MOD_LFO_CC1_TO_PITCH];
+ pArt->modLFOChanPressToPitch = pDLSArt->values[PARAM_MOD_LFO_CHAN_PRESS_TO_PITCH];
+ pArt->eg2ToPitch = pDLSArt->values[PARAM_MOD_EG_TO_PITCH];
+
+ /* output parameters */
+ pArt->pan = ConvertPan(pDLSArt->values[PARAM_DEFAULT_PAN]);
+
+ if (pDLSArt->values[PARAM_VEL_TO_GAIN] != 0)
+ pArt->filterQandFlags |= FLAG_DLS_VELOCITY_SENSITIVE;
+
+#ifdef _REVERB
+ pArt->reverbSend = pDLSArt->values[PARAM_DEFAULT_REVERB_SEND];
+ pArt->cc91ToReverbSend = pDLSArt->values[PARAM_MIDI_CC91_TO_REVERB_SEND];
+#endif
+
+#ifdef _CHORUS
+ pArt->chorusSend = pDLSArt->values[PARAM_DEFAULT_CHORUS_SEND];
+ pArt->cc93ToChorusSend = pDLSArt->values[PARAM_MIDI_CC93_TO_CHORUS_SEND];
+#endif
+}
+
+/*----------------------------------------------------------------------------
+ * ConvertSampleRate()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *----------------------------------------------------------------------------
+*/
+static EAS_I16 ConvertSampleRate (EAS_U32 sampleRate)
+{
+ return (EAS_I16) (1200.0 * log10((double) sampleRate / (double) outputSampleRate) / log10(2.0));
+}
+
+/*----------------------------------------------------------------------------
+ * ConvertSustainEG2()
+ *----------------------------------------------------------------------------
+ * Convert sustain level to pitch/Fc multipler for EG2
+ *----------------------------------------------------------------------------
+*/
+static EAS_I16 ConvertSustain (EAS_I32 sustain)
+{
+ /* check for sustain level of zero */
+ if (sustain == 0)
+ return 0;
+
+ /* convert to log2 factor */
+ /*lint -e{704} use shift for performance */
+ sustain = (sustain * SUSTAIN_LINEAR_CONVERSION_FACTOR) >> 15;
+
+ if (sustain > SYNTH_FULL_SCALE_EG1_GAIN)
+ return SYNTH_FULL_SCALE_EG1_GAIN;
+ return (EAS_I16) sustain;
+}
+
+/*----------------------------------------------------------------------------
+ * ConvertDelay ()
+ *----------------------------------------------------------------------------
+ * Converts timecents to frame count. Used for LFO and envelope
+ * delay times.
+ *----------------------------------------------------------------------------
+*/
+EAS_I16 ConvertDelay (EAS_I32 timeCents)
+{
+ EAS_I32 temp;
+
+ if (timeCents == ZERO_TIME_IN_CENTS)
+ return 0;
+
+ /* divide time by secs per frame to get number of frames */
+ temp = timeCents - dlsRateConvert;
+
+ /* convert from time cents to 10-bit fraction */
+ temp = FMUL_15x15(temp, TIME_CENTS_TO_LOG2);
+
+ /* convert to frame count */
+ temp = EAS_LogToLinear16(temp - (15 << 10));
+
+ if (temp < SYNTH_FULL_SCALE_EG1_GAIN)
+ return (EAS_I16) temp;
+ return SYNTH_FULL_SCALE_EG1_GAIN;
+}
+
+/*----------------------------------------------------------------------------
+ * ConvertRate ()
+ *----------------------------------------------------------------------------
+ * Convert timecents to rate
+ *----------------------------------------------------------------------------
+*/
+EAS_I16 ConvertRate (EAS_I32 timeCents)
+{
+ EAS_I32 temp;
+
+ if (timeCents == ZERO_TIME_IN_CENTS)
+ return SYNTH_FULL_SCALE_EG1_GAIN;
+
+ /* divide frame rate by time in log domain to get rate */
+ temp = dlsRateConvert - timeCents;
+
+#if 1
+ temp = EAS_Calculate2toX(temp);
+#else
+ /* convert from time cents to 10-bit fraction */
+ temp = FMUL_15x15(temp, TIME_CENTS_TO_LOG2);
+
+ /* convert to rate */
+ temp = EAS_LogToLinear16(temp);
+#endif
+
+ if (temp < SYNTH_FULL_SCALE_EG1_GAIN)
+ return (EAS_I16) temp;
+ return SYNTH_FULL_SCALE_EG1_GAIN;
+}
+
+
+/*----------------------------------------------------------------------------
+ * ConvertLFOPhaseIncrement()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *----------------------------------------------------------------------------
+*/
+static EAS_I16 ConvertLFOPhaseIncrement (EAS_I32 pitchCents)
+{
+
+ /* check range */
+ if (pitchCents > MAX_LFO_FREQUENCY_IN_PITCHCENTS)
+ pitchCents = MAX_LFO_FREQUENCY_IN_PITCHCENTS;
+ if (pitchCents < MIN_LFO_FREQUENCY_IN_PITCHCENTS)
+ pitchCents = MIN_LFO_FREQUENCY_IN_PITCHCENTS;
+
+ /* double the rate and divide by frame rate by subtracting in log domain */
+ pitchCents = pitchCents - dlsLFOFrequencyConvert;
+
+ /* convert to phase increment */
+ return (EAS_I16) EAS_Calculate2toX(pitchCents);
+}
+
+/*----------------------------------------------------------------------------
+ * ConvertPan()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *----------------------------------------------------------------------------
+*/
+static EAS_I8 ConvertPan (EAS_I32 pan)
+{
+
+ /* multiply by conversion factor */
+ pan = FMUL_15x15 (PAN_CONVERSION_FACTOR, pan);
+ if (pan < MIN_PAN_VALUE)
+ return MIN_PAN_VALUE;
+ if (pan > MAX_PAN_VALUE)
+ return MAX_PAN_VALUE;
+ return (EAS_I8) pan;
+}
+
+/*----------------------------------------------------------------------------
+ * ConvertQ()
+ *----------------------------------------------------------------------------
+ * Convert the DLS filter resonance to an index value used by the synth
+ * that accesses tables of coefficients based on the Q.
+ *----------------------------------------------------------------------------
+*/
+static EAS_U8 ConvertQ (EAS_I32 q)
+{
+
+ /* apply limits */
+ if (q <= 0)
+ return 0;
+
+ /* convert to table index */
+ /*lint -e{704} use shift for performance */
+ q = (FILTER_Q_CONVERSION_FACTOR * q + 0x4000) >> 15;
+
+ /* apply upper limit */
+ if (q >= FILTER_RESONANCE_NUM_ENTRIES)
+ q = FILTER_RESONANCE_NUM_ENTRIES - 1;
+ return (EAS_U8) q;
+}
+
+#ifdef _DEBUG_DLS
+/*----------------------------------------------------------------------------
+ * DumpDLS()
+ *----------------------------------------------------------------------------
+*/
+static void DumpDLS (S_EAS *pEAS)
+{
+ S_DLS_ARTICULATION *pArt;
+ S_DLS_REGION *pRegion;
+ EAS_INT i;
+ EAS_INT j;
+
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000022 , pEAS->numPrograms);
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000023 , pEAS->numWTRegions);
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000024 , pEAS->numDLSArticulations);
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000025 , pEAS->numSamples);
+
+ /* dump the instruments */
+ for (i = 0; i < pEAS->numPrograms; i++)
+ {
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000026 ,
+ pEAS->pPrograms[i].locale >> 16,
+ (pEAS->pPrograms[i].locale >> 8) & 0x7f,
+ pEAS->pPrograms[i].locale & 0x7f);
+
+ for (j = pEAS->pPrograms[i].regionIndex; ; j++)
+ {
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000027 , j);
+ pRegion = &pEAS->pWTRegions[j];
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000028 , pRegion->gain);
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000029 , pRegion->region.rangeLow, pRegion->region.rangeHigh);
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000002a , pRegion->region.keyGroupAndFlags);
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000002b , pRegion->loopStart);
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000002c , pRegion->loopEnd);
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000002d , pRegion->tuning);
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000002e , pRegion->artIndex);
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000002f , pRegion->waveIndex);
+
+ if (pRegion->region.keyGroupAndFlags & REGION_FLAG_LAST_REGION)
+ break;
+ }
+
+ }
+
+ /* dump the articulation data */
+ for (i = 0; i < pEAS->numDLSArticulations; i++)
+ {
+ /* articulation data */
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000030 , i);
+ pArt = &pEAS->pDLSArticulations[i];
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000031 , pArt->m_nEG2toFilterDepth);
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000032 , pArt->m_nEG2toPitchDepth);
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000033 , pArt->m_nFilterCutoffFrequency);
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000034 , pArt->m_nFilterResonance);
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000035 , pArt->m_nLFOAmplitudeDepth);
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000036 , pArt->m_nLFODelayTime);
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000037 , pArt->m_nLFOFrequency);
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000038 , pArt->m_nLFOPitchDepth);
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000039 , pArt->m_nPan);
+
+ /* EG1 data */
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000003a , pArt->m_sEG1.m_nAttack);
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000003b , pArt->m_sEG1.m_nDecay);
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000003c , pArt->m_sEG1.m_nSustain);
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000003d , pArt->m_sEG1.m_nRelease);
+
+ /* EG2 data */
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000003e , pArt->m_sEG2.m_nAttack);
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000003f , pArt->m_sEG2.m_nDecay);
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000040 , pArt->m_sEG2.m_nSustain);
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000041 , pArt->m_sEG2.m_nRelease);
+
+ }
+
+ /* dump the waves */
+ for (i = 0; i < pEAS->numSamples; i++)
+ {
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000042 , i);
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000043 , pEAS->pSampleLen[i]);
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000044 , pEAS->ppSamples[i]);
+ }
+
+}
+#endif
+
diff --git a/arm-wt-22k/lib_src/eas_mdls.h b/arm-wt-22k/lib_src/eas_mdls.h
new file mode 100644
index 0000000..f7dbf2f
--- /dev/null
+++ b/arm-wt-22k/lib_src/eas_mdls.h
@@ -0,0 +1,295 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_mdls.h
+ *
+ * Contents and purpose:
+ * Declarations, interfaces, and prototypes for eas_mdls.c
+ *
+ * Copyright Sonic Network Inc. 2004
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+*/
+
+#ifndef _EAS_MDLS_H
+#define _EAS_MDLS_H
+
+/*------------------------------------
+ * includes
+ *------------------------------------
+*/
+#include "eas_data.h"
+
+
+/*------------------------------------
+ * Some defines for dls.h
+ *------------------------------------
+*/
+#ifndef DWORD
+#define DWORD EAS_I32
+#define FAR
+#define SHORT EAS_I16
+#define USHORT EAS_U16
+#define LONG EAS_I32
+#define ULONG EAS_U32
+#endif
+
+
+/* GUID struct (call it DLSID in case GUID is defined elsewhere) */
+typedef struct
+{
+ EAS_U32 Data1;
+ EAS_U16 Data2;
+ EAS_U16 Data3;
+ EAS_U8 Data4[8];
+} DLSID;
+
+#define DEFINE_DLSID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) const DLSID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
+
+/*------------------------------------
+ * defines
+ *------------------------------------
+*/
+
+/* maximum sample memory for DLS query support */
+#ifndef MAX_DLS_MEMORY
+#define MAX_DLS_MEMORY 65536
+#endif
+
+/* size of conditional chunk stack */
+#ifndef CDL_STACK_SIZE
+#define CDL_STACK_SIZE 8
+#endif
+
+/* size of read buffer for sample conversion */
+#ifndef SAMPLE_CONVERT_CHUNK_SIZE
+#define SAMPLE_CONVERT_CHUNK_SIZE 32
+#endif
+
+
+#define ZERO_TIME_IN_CENTS -32768
+
+/* Pan calculation macros */
+#define PAN_CONVERSION_FACTOR 4129
+#define MAX_PAN_VALUE 63
+#define MIN_PAN_VALUE -63
+
+/* multiplier to convert time cents to 10-bit fraction log for EAS_LogToLinear16 */
+#define TIME_CENTS_TO_LOG2 27962
+
+/* conversion factor sustain level from percent to exponent for LogToLinear16 */
+#define SUSTAIN_LOG_CONVERSION_FACTOR 536871
+#define SUSTAIN_LOG_CONVERSION_SHIFT 15
+
+/* conversion factor sustain level from percent to EG full scale */
+#define SUSTAIN_LINEAR_CONVERSION_FACTOR 1073709
+
+/* conversion factor to convert frame period to decay rate */
+#define DECAY_CONVERSION_FACTOR -16
+
+/*----------------------------------------------------------------------------
+ * These macros define the various characteristics of the defined sample rates
+ *----------------------------------------------------------------------------
+ * DLS_ATTACK_TIME_CONVERT log offset for conversion from time cents to attack rate
+ * DLS_LFO_FREQUENCY_CONVERT pitch-cents offset for LFO frequency conversion
+ *----------------------------------------------------------------------------
+*/
+
+#if defined (_SAMPLE_RATE_8000)
+#define DLS_RATE_CONVERT -9559
+#define DLS_LFO_FREQUENCY_CONVERT 5921
+
+#elif defined (_SAMPLE_RATE_16000)
+#define DLS_RATE_CONVERT -9559
+#define DLS_LFO_FREQUENCY_CONVERT 5921
+
+#elif defined (_SAMPLE_RATE_20000)
+#define DLS_RATE_CONVERT -8745
+#define DLS_LFO_FREQUENCY_CONVERT 5108
+
+#elif defined (_SAMPLE_RATE_22050)
+#define DLS_RATE_CONVERT -8914
+#define DLS_LFO_FREQUENCY_CONVERT 5277
+
+#elif defined (_SAMPLE_RATE_24000)
+#define DLS_RATE_CONVERT -9061
+#define DLS_LFO_FREQUENCY_CONVERT 5423
+
+#elif defined (_SAMPLE_RATE_32000)
+#define DLS_RATE_CONVERT -9559
+#define DLS_LFO_FREQUENCY_CONVERT 5921
+
+#elif defined (_SAMPLE_RATE_44100)
+#define DLS_RATE_CONVERT -8914
+#define DLS_LFO_FREQUENCY_CONVERT 5277
+
+#elif defined (_SAMPLE_RATE_48000)
+#define DLS_RATE_CONVERT -9061
+#define DLS_LFO_FREQUENCY_CONVERT 5423
+
+#else
+#error "_SAMPLE_RATE_XXXXX must be defined to valid rate"
+#endif
+
+/*
+ * FILTER_Q_CONVERSION_FACTOR convers the 0.1dB steps in the DLS
+ * file to our internal 0.75 dB steps. The value is calculated
+ * as follows:
+ *
+ * 32768 / (10 * <step-size in dB>)
+ *
+ * FILTER_RESONANCE_NUM_ENTRIES is the number of entries in the table
+*/
+#define FILTER_Q_CONVERSION_FACTOR 4369
+#define FILTER_RESONANCE_NUM_ENTRIES 31
+
+/*
+ * Multiplier to convert DLS gain units (10ths of a dB) to a
+ * power-of-two exponent for conversion to linear gain using our
+ * piece-wise linear approximator. Note that we ignore the lower
+ * 16-bits of the DLS gain value. The result is a 10-bit fraction
+ * that works with the EAS_LogToLinear16 function.
+ *
+ * DLS_GAIN_FACTOR = (2^18) / (200 * log10(2))
+ */
+#define DLS_GAIN_FACTOR 4354
+#define DLS_GAIN_SHIFT 8
+
+/*
+ * Reciprocal of 10 for quick divide by 10's
+ *
+ * DLS_GAIN_FACTOR = (2^18) / (200 * log10(2))
+ */
+#define DLS_DIV_10_FACTOR 3277
+#define DLS_DIV_10_SHIFT 16
+
+/*
+ * Multiplier to convert DLS time cents units to a power-of-two
+ * exponent for conversion to absolute time units using our
+ * piece-wise linear approximator.
+ *
+ * DLS_TIME_FACTOR = (2^22) / 1200
+ */
+#define DLS_TIME_FACTOR 3495
+#define DLS_TIME_SHIFT 22
+
+
+/* LFO limits */
+#define MAX_LFO_FREQUENCY_IN_HERTZ 20
+#define MIN_LFO_FREQUENCY_IN_HERTZ 0.1
+#define MAX_LFO_FREQUENCY_IN_PITCHCENTS 1549
+#define MIN_LFO_FREQUENCY_IN_PITCHCENTS -7624
+#define MAX_LFO_AMPLITUDE_DEPTH 12 /* in dB, DLS2.1 p 31*/
+#define MIN_LFO_AMPLITUDE_DEPTH -12 /* in dB, DLS2.1 p 31*/
+
+/* add to pitch cents before pow(2.0, n) to convert to frequency */
+#define ABSOLUTE_PITCH_BIAS 238395828
+
+#define A5_PITCH_OFFSET 6900
+
+/*
+CHUNK_TYPE is a macro that converts the 4 input args into a 32-bit int
+where
+argument a is placed at the MSB location and
+argument d is placed at the LSB location.
+This is useful for determining the DLS chunk types
+*/
+#define CHUNK_TYPE(a,b,c,d) ( \
+ ( ((EAS_U32)(a) & 0xFF) << 24 ) \
+ + ( ((EAS_U32)(b) & 0xFF) << 16 ) \
+ + ( ((EAS_U32)(c) & 0xFF) << 8 ) \
+ + ( ((EAS_U32)(d) & 0xFF) ) )
+
+#define CHUNK_RIFF CHUNK_TYPE('R','I','F','F')
+#define CHUNK_DLS CHUNK_TYPE('D','L','S',' ')
+#define CHUNK_CDL CHUNK_TYPE('c','d','l',' ')
+#define CHUNK_VERS CHUNK_TYPE('v','e','r','s')
+#define CHUNK_DLID CHUNK_TYPE('d','l','i','d')
+#define CHUNK_LIST CHUNK_TYPE('L','I','S','T')
+#define CHUNK_COLH CHUNK_TYPE('c','o','l','h')
+#define CHUNK_LINS CHUNK_TYPE('l','i','n','s')
+#define CHUNK_PTBL CHUNK_TYPE('p','t','b','l')
+#define CHUNK_WVPL CHUNK_TYPE('w','v','p','l')
+#define CHUNK_INFO CHUNK_TYPE('I','N','F','O')
+#define CHUNK_INAM CHUNK_TYPE('I','N','A','M')
+#define CHUNK_INS CHUNK_TYPE('i','n','s',' ')
+#define CHUNK_INSH CHUNK_TYPE('i','n','s','h')
+#define CHUNK_LRGN CHUNK_TYPE('l','r','g','n')
+#define CHUNK_RGN CHUNK_TYPE('r','g','n',' ')
+#define CHUNK_RGN2 CHUNK_TYPE('r','g','n','2')
+#define CHUNK_RGNH CHUNK_TYPE('r','g','n','h')
+#define CHUNK_WSMP CHUNK_TYPE('w','s','m','p')
+#define CHUNK_WLNK CHUNK_TYPE('w','l','n','k')
+#define CHUNK_LART CHUNK_TYPE('l','a','r','t')
+#define CHUNK_LAR2 CHUNK_TYPE('l','a','r','2')
+#define CHUNK_ART1 CHUNK_TYPE('a','r','t','1')
+#define CHUNK_ART2 CHUNK_TYPE('a','r','t','2')
+#define CHUNK_WAVE CHUNK_TYPE('w','a','v','e')
+#define CHUNK_FMT CHUNK_TYPE('f','m','t',' ')
+#define CHUNK_DATA CHUNK_TYPE('d','a','t','a')
+#define CHUNK_DMPR CHUNK_TYPE('d','m','p','r')
+
+
+#define WAVE_FORMAT_PCM 0x0001 /* Microsoft PCM format, see DLS2.1 p60 */
+#define WAVE_FORMAT_EXTENSIBLE 0xffff
+
+/* defines for wave table structures */
+
+/* initialize each articulation structure to a harmless state */
+/* change art values after we've determined EAS internals */
+#define DEFAULT_DLS_FILTER_CUTOFF_FREQUENCY 0x7FFF /* DLS2.1, p 31 means leave filter off */
+
+/**********/
+
+/* define the waves that we expect to generate instead of store */
+/* NOTE: our comparison routine converts the input string
+to lowercase, so the following comparison values should all
+be in lowercase.
+*/
+#define STRING_NOISE "noise"
+
+
+/*------------------------------------
+ * type definitions
+ *------------------------------------
+*/
+#ifdef _STANDALONE_CONVERTER
+typedef struct s_dls_params
+{
+ EAS_INT sampleRate;
+ EAS_INT samplesPerFrame;
+ EAS_INT bitDepth;
+ double ditherLevel;
+ double ditherFilterCoeff;
+ EAS_BOOL compatibility;
+ EAS_BOOL encodeADPCM;
+} S_DLS_PARAMS;
+#endif
+
+
+/* function prototypes */
+EAS_RESULT DLSParser (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_I32 offset, S_DLS **pDLS);
+EAS_RESULT DLSCleanup (EAS_HW_DATA_HANDLE hwInstData, S_DLS *pDLS);
+void DLSAddRef (S_DLS *pDLS);
+EAS_I16 ConvertDelay (EAS_I32 timeCents);
+EAS_I16 ConvertRate (EAS_I32 timeCents);
+
+
+#ifdef _STANDALONE_CONVERTER
+void DLSConvParams (S_DLS_PARAMS *pParams, EAS_BOOL set);
+#endif
+
+#endif
+
diff --git a/arm-wt-22k/lib_src/eas_midi.c b/arm-wt-22k/lib_src/eas_midi.c
new file mode 100644
index 0000000..0c77aea
--- /dev/null
+++ b/arm-wt-22k/lib_src/eas_midi.c
@@ -0,0 +1,569 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_midi.c
+ *
+ * Contents and purpose:
+ * This file implements the MIDI stream parser. It is called by eas_smf.c to parse MIDI messages
+ * that are streamed out of the file. It can also parse live MIDI streams.
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 794 $
+ * $Date: 2007-08-01 00:08:48 -0700 (Wed, 01 Aug 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+#include "eas_data.h"
+#include "eas_report.h"
+#include "eas_miditypes.h"
+#include "eas_midi.h"
+#include "eas_vm_protos.h"
+#include "eas_parser.h"
+
+#ifdef JET_INTERFACE
+#include "jet_data.h"
+#endif
+
+
+/* state enumerations for ProcessSysExMessage */
+typedef enum
+{
+ eSysEx,
+ eSysExUnivNonRealTime,
+ eSysExUnivNrtTargetID,
+ eSysExGMControl,
+ eSysExUnivRealTime,
+ eSysExUnivRtTargetID,
+ eSysExDeviceControl,
+ eSysExMasterVolume,
+ eSysExMasterVolLSB,
+ eSysExSPMIDI,
+ eSysExSPMIDIchan,
+ eSysExSPMIDIMIP,
+ eSysExMfgID1,
+ eSysExMfgID2,
+ eSysExMfgID3,
+ eSysExEnhancer,
+ eSysExEnhancerSubID,
+ eSysExEnhancerFeedback1,
+ eSysExEnhancerFeedback2,
+ eSysExEnhancerDrive,
+ eSysExEnhancerWet,
+ eSysExEOX,
+ eSysExIgnore
+} E_SYSEX_STATES;
+
+/* local prototypes */
+static EAS_RESULT ProcessMIDIMessage (S_EAS_DATA *pEASData, S_SYNTH *pSynth, S_MIDI_STREAM *pMIDIStream, EAS_INT parserMode);
+static EAS_RESULT ProcessSysExMessage (S_EAS_DATA *pEASData, S_SYNTH *pSynth, S_MIDI_STREAM *pMIDIStream, EAS_U8 c, EAS_INT parserMode);
+
+/*----------------------------------------------------------------------------
+ * EAS_InitMIDIStream()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Initializes the MIDI stream state for parsing.
+ *
+ * Inputs:
+ *
+ * Outputs:
+ * returns EAS_RESULT (EAS_SUCCESS is OK)
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+void EAS_InitMIDIStream (S_MIDI_STREAM *pMIDIStream)
+{
+ pMIDIStream->byte3 = EAS_FALSE;
+ pMIDIStream->pending = EAS_FALSE;
+ pMIDIStream->runningStatus = 0;
+ pMIDIStream->status = 0;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_ParseMIDIStream()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Parses a MIDI input stream character by character. Characters are pushed (rather than pulled)
+ * so the interface works equally well for both file and stream I/O.
+ *
+ * Inputs:
+ * c - character from MIDI stream
+ *
+ * Outputs:
+ * returns EAS_RESULT (EAS_SUCCESS is OK)
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_ParseMIDIStream (S_EAS_DATA *pEASData, S_SYNTH *pSynth, S_MIDI_STREAM *pMIDIStream, EAS_U8 c, EAS_INT parserMode)
+{
+
+ /* check for new status byte */
+ if (c & 0x80)
+ {
+ /* save new running status */
+ if (c < 0xf8)
+ {
+ pMIDIStream->runningStatus = c;
+ pMIDIStream->byte3 = EAS_FALSE;
+
+ /* deal with SysEx */
+ if ((c == 0xf7) || (c == 0xf0))
+ {
+ if (parserMode == eParserModeMetaData)
+ return EAS_SUCCESS;
+ return ProcessSysExMessage(pEASData, pSynth, pMIDIStream, c, parserMode);
+ }
+
+ /* inform the file parser that we're in the middle of a message */
+ if ((c < 0xf4) || (c > 0xf6))
+ pMIDIStream->pending = EAS_TRUE;
+ }
+
+ /* real-time message - ignore it */
+ return EAS_SUCCESS;
+ }
+
+ /* 3rd byte of a 3-byte message? */
+ if (pMIDIStream->byte3)
+ {
+ pMIDIStream->d2 = c;
+ pMIDIStream->byte3 = EAS_FALSE;
+ pMIDIStream->pending = EAS_FALSE;
+ if (parserMode == eParserModeMetaData)
+ return EAS_SUCCESS;
+ return ProcessMIDIMessage(pEASData, pSynth, pMIDIStream, parserMode);
+ }
+
+ /* check for status received */
+ if (pMIDIStream->runningStatus)
+ {
+
+ /* save new status and data byte */
+ pMIDIStream->status = pMIDIStream->runningStatus;
+
+ /* check for 3-byte messages */
+ if (pMIDIStream->status < 0xc0)
+ {
+ pMIDIStream->d1 = c;
+ pMIDIStream->pending = EAS_TRUE;
+ pMIDIStream->byte3 = EAS_TRUE;
+ return EAS_SUCCESS;
+ }
+
+ /* check for 2-byte messages */
+ if (pMIDIStream->status < 0xe0)
+ {
+ pMIDIStream->d1 = c;
+ pMIDIStream->pending = EAS_FALSE;
+ if (parserMode == eParserModeMetaData)
+ return EAS_SUCCESS;
+ return ProcessMIDIMessage(pEASData, pSynth, pMIDIStream, parserMode);
+ }
+
+ /* check for more 3-bytes message */
+ if (pMIDIStream->status < 0xf0)
+ {
+ pMIDIStream->d1 = c;
+ pMIDIStream->pending = EAS_TRUE;
+ pMIDIStream->byte3 = EAS_TRUE;
+ return EAS_SUCCESS;
+ }
+
+ /* SysEx message? */
+ if (pMIDIStream->status == 0xF0)
+ {
+ if (parserMode == eParserModeMetaData)
+ return EAS_SUCCESS;
+ return ProcessSysExMessage(pEASData, pSynth, pMIDIStream, c, parserMode);
+ }
+
+ /* remaining messages all clear running status */
+ pMIDIStream->runningStatus = 0;
+
+ /* F2 is 3-byte message */
+ if (pMIDIStream->status == 0xf2)
+ {
+ pMIDIStream->byte3 = EAS_TRUE;
+ return EAS_SUCCESS;
+ }
+ }
+
+ /* no status byte received, provide a warning, but we should be able to recover */
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Received MIDI data without a valid status byte: %d\n",c); */ }
+ pMIDIStream->pending = EAS_FALSE;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * ProcessMIDIMessage()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * This function processes a typical MIDI message. All of the data has been received, just need
+ * to take appropriate action.
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT ProcessMIDIMessage (S_EAS_DATA *pEASData, S_SYNTH *pSynth, S_MIDI_STREAM *pMIDIStream, EAS_INT parserMode)
+{
+ EAS_U8 channel;
+
+ channel = pMIDIStream->status & 0x0f;
+ switch (pMIDIStream->status & 0xf0)
+ {
+ case 0x80:
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"NoteOff: %02x %02x %02x\n",
+ pMIDIStream->status, pMIDIStream->d1, pMIDIStream->d2); */ }
+ if (parserMode <= eParserModeMute)
+ VMStopNote(pEASData->pVoiceMgr, pSynth, channel, pMIDIStream->d1, pMIDIStream->d2);
+ break;
+
+ case 0x90:
+ if (pMIDIStream->d2)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"NoteOn: %02x %02x %02x\n",
+ pMIDIStream->status, pMIDIStream->d1, pMIDIStream->d2); */ }
+ pMIDIStream->flags |= MIDI_FLAG_FIRST_NOTE;
+ if (parserMode == eParserModePlay)
+ VMStartNote(pEASData->pVoiceMgr, pSynth, channel, pMIDIStream->d1, pMIDIStream->d2);
+ }
+ else
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"NoteOff: %02x %02x %02x\n",
+ pMIDIStream->status, pMIDIStream->d1, pMIDIStream->d2); */ }
+ if (parserMode <= eParserModeMute)
+ VMStopNote(pEASData->pVoiceMgr, pSynth, channel, pMIDIStream->d1, pMIDIStream->d2);
+ }
+ break;
+
+ case 0xa0:
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"PolyPres: %02x %02x %02x\n",
+ pMIDIStream->status, pMIDIStream->d1, pMIDIStream->d2); */ }
+ break;
+
+ case 0xb0:
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"Control: %02x %02x %02x\n",
+ pMIDIStream->status, pMIDIStream->d1, pMIDIStream->d2); */ }
+ if (parserMode <= eParserModeMute)
+ VMControlChange(pEASData->pVoiceMgr, pSynth, channel, pMIDIStream->d1, pMIDIStream->d2);
+#ifdef JET_INTERFACE
+ if (pMIDIStream->jetData & MIDI_FLAGS_JET_CB)
+ {
+ JET_Event(pEASData, pMIDIStream->jetData & (JET_EVENT_SEG_MASK | JET_EVENT_TRACK_MASK),
+ channel, pMIDIStream->d1, pMIDIStream->d2);
+ }
+#endif
+ break;
+
+ case 0xc0:
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"Program: %02x %02x\n",
+ pMIDIStream->status, pMIDIStream->d1); */ }
+ if (parserMode <= eParserModeMute)
+ VMProgramChange(pEASData->pVoiceMgr, pSynth, channel, pMIDIStream->d1);
+ break;
+
+ case 0xd0:
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"ChanPres: %02x %02x\n",
+ pMIDIStream->status, pMIDIStream->d1); */ }
+ if (parserMode <= eParserModeMute)
+ VMChannelPressure(pSynth, channel, pMIDIStream->d1);
+ break;
+
+ case 0xe0:
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"PBend: %02x %02x %02x\n",
+ pMIDIStream->status, pMIDIStream->d1, pMIDIStream->d2); */ }
+ if (parserMode <= eParserModeMute)
+ VMPitchBend(pSynth, channel, pMIDIStream->d1, pMIDIStream->d2);
+ break;
+
+ default:
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"Unknown: %02x %02x %02x\n",
+ pMIDIStream->status, pMIDIStream->d1, pMIDIStream->d2); */ }
+ }
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * ProcessSysExMessage()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Process a SysEx character byte from the MIDI stream. Since we cannot
+ * simply wait for the next character to arrive, we are forced to save
+ * state after each character. It would be easier to parse at the file
+ * level, but then we lose the nice feature of being able to support
+ * these messages in a real-time MIDI stream.
+ *
+ * Inputs:
+ * pEASData - pointer to synthesizer instance data
+ * c - character to be processed
+ * locating - if true, the sequencer is relocating to a new position
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ * Notes:
+ * These are the SysEx messages we can receive:
+ *
+ * SysEx messages
+ * { f0 7e 7f 09 01 f7 } GM 1 On
+ * { f0 7e 7f 09 02 f7 } GM 1/2 Off
+ * { f0 7e 7f 09 03 f7 } GM 2 On
+ * { f0 7f 7f 04 01 lsb msb } Master Volume
+ * { f0 7f 7f 0b 01 ch mip [ch mip ...] f7 } SP-MIDI
+ * { f0 00 01 3a 04 01 fdbk1 fdbk2 drive wet dry f7 } Enhancer
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT ProcessSysExMessage (S_EAS_DATA *pEASData, S_SYNTH *pSynth, S_MIDI_STREAM *pMIDIStream, EAS_U8 c, EAS_INT parserMode)
+{
+
+ /* check for start byte */
+ if (c == 0xf0)
+ {
+ pMIDIStream->sysExState = eSysEx;
+ }
+ /* check for end byte */
+ else if (c == 0xf7)
+ {
+ /* if this was a MIP message, update the MIP table */
+ if ((pMIDIStream->sysExState == eSysExSPMIDIchan) && (parserMode != eParserModeMetaData))
+ VMUpdateMIPTable(pEASData->pVoiceMgr, pSynth);
+ pMIDIStream->sysExState = eSysExIgnore;
+ }
+
+ /* process SysEx message */
+ else
+ {
+ switch (pMIDIStream->sysExState)
+ {
+ case eSysEx:
+
+ /* first byte, determine message class */
+ switch (c)
+ {
+ case 0x7e:
+ pMIDIStream->sysExState = eSysExUnivNonRealTime;
+ break;
+ case 0x7f:
+ pMIDIStream->sysExState = eSysExUnivRealTime;
+ break;
+ case 0x00:
+ pMIDIStream->sysExState = eSysExMfgID1;
+ break;
+ default:
+ pMIDIStream->sysExState = eSysExIgnore;
+ break;
+ }
+ break;
+
+ /* process GM message */
+ case eSysExUnivNonRealTime:
+ if (c == 0x7f)
+ pMIDIStream->sysExState = eSysExUnivNrtTargetID;
+ else
+ pMIDIStream->sysExState = eSysExIgnore;
+ break;
+
+ case eSysExUnivNrtTargetID:
+ if (c == 0x09)
+ pMIDIStream->sysExState = eSysExGMControl;
+ else
+ pMIDIStream->sysExState = eSysExIgnore;
+ break;
+
+ case eSysExGMControl:
+ if ((c == 1) || (c == 3))
+ {
+ /* GM 1 or GM2 On, reset synth */
+ if (parserMode != eParserModeMetaData)
+ {
+ pMIDIStream->flags |= MIDI_FLAG_GM_ON;
+ VMReset(pEASData->pVoiceMgr, pSynth, EAS_FALSE);
+ VMInitMIPTable(pSynth);
+ }
+ pMIDIStream->sysExState = eSysExEOX;
+ }
+ else
+ pMIDIStream->sysExState = eSysExIgnore;
+ break;
+
+ /* Process Master Volume and SP-MIDI */
+ case eSysExUnivRealTime:
+ if (c == 0x7f)
+ pMIDIStream->sysExState = eSysExUnivRtTargetID;
+ else
+ pMIDIStream->sysExState = eSysExIgnore;
+ break;
+
+ case eSysExUnivRtTargetID:
+ if (c == 0x04)
+ pMIDIStream->sysExState = eSysExDeviceControl;
+ else if (c == 0x0b)
+ pMIDIStream->sysExState = eSysExSPMIDI;
+ else
+ pMIDIStream->sysExState = eSysExIgnore;
+ break;
+
+ /* process master volume */
+ case eSysExDeviceControl:
+ if (c == 0x01)
+ pMIDIStream->sysExState = eSysExMasterVolume;
+ else
+ pMIDIStream->sysExState = eSysExIgnore;
+ break;
+
+ case eSysExMasterVolume:
+ /* save LSB */
+ pMIDIStream->d1 = c;
+ pMIDIStream->sysExState = eSysExMasterVolLSB;
+ break;
+
+ case eSysExMasterVolLSB:
+ if (parserMode != eParserModeMetaData)
+ {
+ EAS_I32 gain = ((EAS_I32) c << 8) | ((EAS_I32) pMIDIStream->d1 << 1);
+ gain = (gain * gain) >> 15;
+ VMSetVolume(pSynth, (EAS_U16) gain);
+ }
+ pMIDIStream->sysExState = eSysExEOX;
+ break;
+
+ /* process SP-MIDI MIP message */
+ case eSysExSPMIDI:
+ if (c == 0x01)
+ {
+ /* assume all channels are muted */
+ if (parserMode != eParserModeMetaData)
+ VMInitMIPTable(pSynth);
+ pMIDIStream->d1 = 0;
+ pMIDIStream->sysExState = eSysExSPMIDIchan;
+ }
+ else
+ pMIDIStream->sysExState = eSysExIgnore;
+ break;
+
+ case eSysExSPMIDIchan:
+ if (c < NUM_SYNTH_CHANNELS)
+ {
+ pMIDIStream->d2 = c;
+ pMIDIStream->sysExState = eSysExSPMIDIMIP;
+ }
+ else
+ {
+ /* bad MIP message - unmute channels */
+ if (parserMode != eParserModeMetaData)
+ VMInitMIPTable(pSynth);
+ pMIDIStream->sysExState = eSysExIgnore;
+ }
+ break;
+
+ case eSysExSPMIDIMIP:
+ /* process MIP entry here */
+ if (parserMode != eParserModeMetaData)
+ VMSetMIPEntry(pEASData->pVoiceMgr, pSynth, pMIDIStream->d2, pMIDIStream->d1, c);
+ pMIDIStream->sysExState = eSysExSPMIDIchan;
+
+ /* if 16 channels received, update MIP table */
+ if (++pMIDIStream->d1 == NUM_SYNTH_CHANNELS)
+ {
+ if (parserMode != eParserModeMetaData)
+ VMUpdateMIPTable(pEASData->pVoiceMgr, pSynth);
+ pMIDIStream->sysExState = eSysExEOX;
+ }
+ break;
+
+ /* process Enhancer */
+ case eSysExMfgID1:
+ if (c == 0x01)
+ pMIDIStream->sysExState = eSysExMfgID1;
+ else
+ pMIDIStream->sysExState = eSysExIgnore;
+ break;
+
+ case eSysExMfgID2:
+ if (c == 0x3a)
+ pMIDIStream->sysExState = eSysExMfgID1;
+ else
+ pMIDIStream->sysExState = eSysExIgnore;
+ break;
+
+ case eSysExMfgID3:
+ if (c == 0x04)
+ pMIDIStream->sysExState = eSysExEnhancer;
+ else
+ pMIDIStream->sysExState = eSysExIgnore;
+ break;
+
+ case eSysExEnhancer:
+ if (c == 0x01)
+ pMIDIStream->sysExState = eSysExEnhancerSubID;
+ else
+ pMIDIStream->sysExState = eSysExIgnore;
+ break;
+
+ case eSysExEnhancerSubID:
+ pMIDIStream->sysExState = eSysExEnhancerFeedback1;
+ break;
+
+ case eSysExEnhancerFeedback1:
+ pMIDIStream->sysExState = eSysExEnhancerFeedback2;
+ break;
+
+ case eSysExEnhancerFeedback2:
+ pMIDIStream->sysExState = eSysExEnhancerDrive;
+ break;
+
+ case eSysExEnhancerDrive:
+ pMIDIStream->sysExState = eSysExEnhancerWet;
+ break;
+
+ case eSysExEnhancerWet:
+ pMIDIStream->sysExState = eSysExEOX;
+ break;
+
+ case eSysExEOX:
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Expected F7, received %02x\n", c); */ }
+ pMIDIStream->sysExState = eSysExIgnore;
+ break;
+
+ case eSysExIgnore:
+ break;
+
+ default:
+ pMIDIStream->sysExState = eSysExIgnore;
+ break;
+ }
+ }
+
+ if (pMIDIStream->sysExState == eSysExIgnore)
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Ignoring SysEx byte %02x\n", c); */ }
+ return EAS_SUCCESS;
+} /* end ProcessSysExMessage */
+
diff --git a/arm-wt-22k/lib_src/eas_midi.h b/arm-wt-22k/lib_src/eas_midi.h
new file mode 100644
index 0000000..37a03ee
--- /dev/null
+++ b/arm-wt-22k/lib_src/eas_midi.h
@@ -0,0 +1,71 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_midi.h
+ *
+ * Contents and purpose:
+ * Prototypes for MIDI stream parsing functions
+ *
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 82 $
+ * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $
+ *----------------------------------------------------------------------------
+*/
+
+#ifndef _EAS_MIDI_H
+#define _EAS_MIDI_H
+
+/*----------------------------------------------------------------------------
+ * EAS_InitMIDIStream()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Initializes the MIDI stream state for parsing.
+ *
+ * Inputs:
+ *
+ * Outputs:
+ * returns EAS_RESULT (EAS_SUCCESS is OK)
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+void EAS_InitMIDIStream (S_MIDI_STREAM *pMIDIStream);
+
+/*----------------------------------------------------------------------------
+ * EAS_ParseMIDIStream()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Parses a MIDI input stream character by character. Characters are pushed (rather than pulled)
+ * so the interface works equally well for both file and stream I/O.
+ *
+ * Inputs:
+ * c - character from MIDI stream
+ *
+ * Outputs:
+ * returns EAS_RESULT (EAS_SUCCESS is OK)
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_ParseMIDIStream (S_EAS_DATA *pEASData, S_SYNTH *pSynth, S_MIDI_STREAM *pMIDIStream, EAS_U8 c, EAS_INT parserMode);
+
+#endif /* #define _EAS_MIDI_H */
+
diff --git a/arm-wt-22k/lib_src/eas_midictrl.h b/arm-wt-22k/lib_src/eas_midictrl.h
new file mode 100644
index 0000000..0c4217d
--- /dev/null
+++ b/arm-wt-22k/lib_src/eas_midictrl.h
@@ -0,0 +1,64 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_midictrl.h
+ *
+ * Contents and purpose:
+ * MIDI controller definitions
+ *
+ * This header only contains declarations that are specific
+ * to this implementation.
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 82 $
+ * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $
+ *----------------------------------------------------------------------------
+*/
+
+#ifndef _EAS_MIDICTRL_H
+#define _EAS_MIDICTRL_H
+
+/* define controller types */
+/*
+ Note that these controller types are specified in base 10 (decimal)
+ and not in hexadecimal. The above midi messages are specified
+ in hexadecimal.
+*/
+#define MIDI_CONTROLLER_BANK_SELECT 0
+#define MIDI_CONTROLLER_BANK_SELECT_MSB 0
+#define MIDI_CONTROLLER_MOD_WHEEL 1
+#define MIDI_CONTROLLER_ENTER_DATA_MSB 6
+#define MIDI_CONTROLLER_VOLUME 7
+#define MIDI_CONTROLLER_PAN 10
+#define MIDI_CONTROLLER_EXPRESSION 11
+#define MIDI_CONTROLLER_BANK_SELECT_LSB 32
+#define MIDI_CONTROLLER_ENTER_DATA_LSB 38 /* 0x26 */
+#define MIDI_CONTROLLER_SUSTAIN_PEDAL 64
+#define MIDI_CONTROLLER_SELECT_NRPN_LSB 98
+#define MIDI_CONTROLLER_SELECT_NRPN_MSB 99
+#define MIDI_CONTROLLER_SELECT_RPN_LSB 100 /* 0x64 */
+#define MIDI_CONTROLLER_SELECT_RPN_MSB 101 /* 0x65 */
+#define MIDI_CONTROLLER_ALL_SOUND_OFF 120
+#define MIDI_CONTROLLER_RESET_CONTROLLERS 121
+#define MIDI_CONTROLLER_ALL_NOTES_OFF 123
+#define MIDI_CONTROLLER_OMNI_OFF 124
+#define MIDI_CONTROLLER_OMNI_ON 125
+#define MIDI_CONTROLLER_MONO_ON_POLY_OFF 126
+#define MIDI_CONTROLLER_POLY_ON_MONO_OFF 127
+
+#endif /* #ifndef _EAS_MIDICTRL_H */
diff --git a/arm-wt-22k/lib_src/eas_mididata.c b/arm-wt-22k/lib_src/eas_mididata.c
new file mode 100644
index 0000000..2ee907e
--- /dev/null
+++ b/arm-wt-22k/lib_src/eas_mididata.c
@@ -0,0 +1,34 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_mididata.c
+ *
+ * Contents and purpose:
+ * Data module for MIDI stream interface
+ *
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 547 $
+ * $Date: 2007-01-31 16:30:17 -0800 (Wed, 31 Jan 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+#include "eas_miditypes.h"
+
+S_INTERACTIVE_MIDI eas_MIDIData;
+
diff --git a/arm-wt-22k/lib_src/eas_miditypes.h b/arm-wt-22k/lib_src/eas_miditypes.h
new file mode 100644
index 0000000..0b7f96e
--- /dev/null
+++ b/arm-wt-22k/lib_src/eas_miditypes.h
@@ -0,0 +1,138 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_miditypes.h
+ *
+ * Contents and purpose:
+ * Contains declarations for the MIDI stream parser.
+ *
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 778 $
+ * $Date: 2007-07-23 16:45:17 -0700 (Mon, 23 Jul 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+#ifndef _EAS_MIDITYPES_H
+#define _EAS_MIDITYPES_H
+
+#include "eas_data.h"
+#include "eas_parser.h"
+
+/*----------------------------------------------------------------------------
+ * S_MIDI_STREAM
+ *
+ * Maintains parser state for the MIDI stream parser
+ *
+ *----------------------------------------------------------------------------
+*/
+
+typedef struct s_midi_stream_tag
+{
+ EAS_BOOL8 byte3; /* flag indicates 3rd byte expected */
+ EAS_BOOL8 pending; /* flag indicates more data expected */
+ EAS_U8 sysExState; /* maintains the SysEx state */
+ EAS_U8 runningStatus; /* last running status received */
+ EAS_U8 status; /* status byte */
+ EAS_U8 d1; /* first data byte */
+ EAS_U8 d2; /* second data byte */
+ EAS_U8 flags; /* flags - see below for definition */
+#ifdef JET_INTERFACE
+ EAS_U32 jetData; /* JET data */
+#endif
+} S_MIDI_STREAM;
+
+/* flags for S_MIDI_STREAM.flags */
+#define MIDI_FLAG_GM_ON 0x01 /* GM System On message received */
+#define MIDI_FLAG_FIRST_NOTE 0x02 /* first note received */
+
+/* flags for S_MIDI_STREAM.jetFlags */
+#define MIDI_FLAGS_JET_MUTE 0x00000001 /* track is muted */
+#define MIDI_FLAGS_JET_CB 0x00000002 /* JET callback enabled */
+
+/*----------------------------------------------------------------------------
+ *
+ * S_SMF_STREAM
+ *
+ * This structure contains data required to parse an SMF stream. For SMF0 files, there
+ * will be a single instance of this per file. For SMF1 files, there will be multiple instance,
+ * one for each separate stream in the file.
+ *
+ *----------------------------------------------------------------------------
+*/
+
+typedef struct s_smf_stream_tag
+{
+ EAS_FILE_HANDLE fileHandle; /* host wrapper file handle */
+ EAS_U32 ticks; /* time of next event in stream */
+ EAS_I32 startFilePos; /* start location of track within file */
+ S_MIDI_STREAM midiStream; /* MIDI stream state */
+} S_SMF_STREAM;
+
+/*----------------------------------------------------------------------------
+ *
+ * S_SMF_DATA
+ *
+ * This structure contains the instance data required to parse an SMF stream.
+ *
+ *----------------------------------------------------------------------------
+*/
+
+typedef struct s_smf_data_tag
+{
+#ifdef _CHECKED_BUILD
+ EAS_U32 handleCheck; /* signature check for checked build */
+#endif
+ S_SMF_STREAM *streams; /* pointer to individual streams in file */
+ S_SMF_STREAM *nextStream; /* pointer to next stream with event */
+ S_SYNTH *pSynth; /* pointer to synth */
+ EAS_FILE_HANDLE fileHandle; /* file handle */
+ S_METADATA_CB metadata; /* metadata callback */
+ EAS_I32 fileOffset; /* for embedded files */
+ EAS_I32 time; /* current time in milliseconds/256 */
+ EAS_U16 numStreams; /* actual number of streams */
+ EAS_U16 tickConv; /* current MIDI tick to msec conversion */
+ EAS_U16 ppqn; /* ticks per quarter note */
+ EAS_U8 state; /* current state EAS_STATE_XXXX */
+ EAS_U8 flags; /* flags - see definitions below */
+} S_SMF_DATA;
+
+#define SMF_FLAGS_CHASE_MODE 0x01 /* chase mode - skip to first note */
+#define SMF_FLAGS_HAS_TIME_SIG 0x02 /* time signature encountered at time 0 */
+#define SMF_FLAGS_HAS_TEMPO 0x04 /* tempo encountered at time 0 */
+#define SMF_FLAGS_HAS_GM_ON 0x08 /* GM System On encountered at time 0 */
+#define SMF_FLAGS_JET_STREAM 0x80 /* JET in use - keep strict timing */
+
+/* combo flags indicate setup bar */
+#define SMF_FLAGS_SETUP_BAR (SMF_FLAGS_HAS_TIME_SIG | SMF_FLAGS_HAS_TEMPO | SMF_FLAGS_HAS_GM_ON)
+
+/*----------------------------------------------------------------------------
+ * Interactive MIDI structure
+ *----------------------------------------------------------------------------
+*/
+typedef struct s_interactive_midi_tag
+{
+#ifdef _CHECKED_BUILD
+ EAS_U32 handleCheck; /* signature check for checked build */
+#endif
+ S_SYNTH *pSynth; /* pointer to synth */
+ S_MIDI_STREAM stream; /* stream data */
+} S_INTERACTIVE_MIDI;
+
+#endif /* #ifndef _EAS_MIDITYPES_H */
+
diff --git a/arm-wt-22k/lib_src/eas_mixbuf.c b/arm-wt-22k/lib_src/eas_mixbuf.c
new file mode 100644
index 0000000..73e969a
--- /dev/null
+++ b/arm-wt-22k/lib_src/eas_mixbuf.c
@@ -0,0 +1,36 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_mixbuf.c
+ *
+ * Contents and purpose:
+ * Contains a data allocation for synthesizer
+ *
+ * Copyright Sonic Network Inc. 2004
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 82 $
+ * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $
+ *----------------------------------------------------------------------------
+*/
+
+// includes
+#include "eas_data.h"
+#include "eas_mixer.h"
+
+// globals
+EAS_I32 eas_MixBuffer[BUFFER_SIZE_IN_MONO_SAMPLES * NUM_OUTPUT_CHANNELS];
+
diff --git a/arm-wt-22k/lib_src/eas_mixer.c b/arm-wt-22k/lib_src/eas_mixer.c
new file mode 100644
index 0000000..c4a2f9f
--- /dev/null
+++ b/arm-wt-22k/lib_src/eas_mixer.c
@@ -0,0 +1,464 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_mixer.c
+ *
+ * Contents and purpose:
+ * This file contains the critical components of the mix engine that
+ * must be optimized for best performance.
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 706 $
+ * $Date: 2007-05-31 17:22:51 -0700 (Thu, 31 May 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+//3 dls: This module is in the midst of being converted from a synth
+//3 specific module to a general purpose mix engine
+
+/*------------------------------------
+ * includes
+ *------------------------------------
+*/
+#include "eas_data.h"
+#include "eas_host.h"
+#include "eas_math.h"
+#include "eas_mixer.h"
+#include "eas_config.h"
+#include "eas_report.h"
+
+#ifdef _MAXIMIZER_ENABLED
+EAS_I32 MaximizerProcess (EAS_VOID_PTR pInstData, EAS_I32 *pSrc, EAS_I32 *pDst, EAS_I32 numSamples);
+#endif
+
+/*------------------------------------
+ * defines
+ *------------------------------------
+*/
+
+/* need to boost stereo by ~3dB to compensate for the panner */
+#define STEREO_3DB_GAIN_BOOST 512
+
+/*----------------------------------------------------------------------------
+ * EAS_MixEngineInit()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Prepares the mix engine for work, allocates buffers, locates effects modules, etc.
+ *
+ * Inputs:
+ * pEASData - instance data
+ * pInstData - pointer to variable to receive instance data handle
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_MixEngineInit (S_EAS_DATA *pEASData)
+{
+
+ /* check Configuration Module for mix buffer allocation */
+ if (pEASData->staticMemoryModel)
+ pEASData->pMixBuffer = EAS_CMEnumData(EAS_CM_MIX_BUFFER);
+ else
+ pEASData->pMixBuffer = EAS_HWMalloc(pEASData->hwInstData, BUFFER_SIZE_IN_MONO_SAMPLES * NUM_OUTPUT_CHANNELS * sizeof(EAS_I32));
+ if (pEASData->pMixBuffer == NULL)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate mix buffer memory\n"); */ }
+ return EAS_ERROR_MALLOC_FAILED;
+ }
+ EAS_HWMemSet((void *)(pEASData->pMixBuffer), 0, BUFFER_SIZE_IN_MONO_SAMPLES * NUM_OUTPUT_CHANNELS * sizeof(EAS_I32));
+
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_MixEnginePrep()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Performs prep before synthesize a buffer of audio, such as clearing
+ * audio buffers, etc.
+ *
+ * Inputs:
+ * psEASData - pointer to overall EAS data structure
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+void EAS_MixEnginePrep (S_EAS_DATA *pEASData, EAS_I32 numSamples)
+{
+
+ /* clear the mix buffer */
+#if (NUM_OUTPUT_CHANNELS == 2)
+ EAS_HWMemSet(pEASData->pMixBuffer, 0, numSamples * (EAS_I32) sizeof(long) * 2);
+#else
+ EAS_HWMemSet(pEASData->pMixBuffer, 0, (EAS_I32) numSamples * (EAS_I32) sizeof(long));
+#endif
+
+ /* need to clear other side-chain effect buffers (chorus & reverb) */
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_MixEnginePost
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * This routine does the post-processing after all voices have been
+ * synthesized. It calls any sweeteners and does the final mixdown to
+ * the output buffer.
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ * Notes:
+ *----------------------------------------------------------------------------
+*/
+void EAS_MixEnginePost (S_EAS_DATA *pEASData, EAS_I32 numSamples)
+{
+ EAS_U16 gain;
+
+//3 dls: Need to restore the mix engine metrics
+
+ /* calculate the gain multiplier */
+#ifdef _MAXIMIZER_ENABLED
+ if (pEASData->effectsModules[EAS_MODULE_MAXIMIZER].effect)
+ {
+ EAS_I32 temp;
+ temp = MaximizerProcess(pEASData->effectsModules[EAS_MODULE_MAXIMIZER].effectData, pEASData->pMixBuffer, pEASData->pMixBuffer, numSamples);
+ temp = (temp * pEASData->masterGain) >> 15;
+ if (temp > 32767)
+ gain = 32767;
+ else
+ gain = (EAS_U16) temp;
+ }
+ else
+ gain = (EAS_U16) pEASData->masterGain;
+#else
+ gain = (EAS_U16) pEASData->masterGain;
+#endif
+
+ /* Not using all the gain bits for now
+ * Reduce the input to the compressor by 6dB to prevent saturation
+ */
+#ifdef _COMPRESSOR_ENABLED
+ if (pEASData->effectsModules[EAS_MODULE_COMPRESSOR].effectData)
+ gain = gain >> 5;
+ else
+ gain = gain >> 4;
+#else
+ gain = gain >> 4;
+#endif
+
+ /* convert 32-bit mix buffer to 16-bit output format */
+#if (NUM_OUTPUT_CHANNELS == 2)
+ SynthMasterGain(pEASData->pMixBuffer, pEASData->pOutputAudioBuffer, gain, (EAS_U16) ((EAS_U16) numSamples * 2));
+#else
+ SynthMasterGain(pEASData->pMixBuffer, pEASData->pOutputAudioBuffer, gain, (EAS_U16) numSamples);
+#endif
+
+#ifdef _ENHANCER_ENABLED
+ /* enhancer effect */
+ if (pEASData->effectsModules[EAS_MODULE_ENHANCER].effectData)
+ (*pEASData->effectsModules[EAS_MODULE_ENHANCER].effect->pfProcess)
+ (pEASData->effectsModules[EAS_MODULE_ENHANCER].effectData,
+ pEASData->pOutputAudioBuffer,
+ pEASData->pOutputAudioBuffer,
+ numSamples);
+#endif
+
+#ifdef _GRAPHIC_EQ_ENABLED
+ /* graphic EQ effect */
+ if (pEASData->effectsModules[EAS_MODULE_GRAPHIC_EQ].effectData)
+ (*pEASData->effectsModules[EAS_MODULE_GRAPHIC_EQ].effect->pfProcess)
+ (pEASData->effectsModules[EAS_MODULE_GRAPHIC_EQ].effectData,
+ pEASData->pOutputAudioBuffer,
+ pEASData->pOutputAudioBuffer,
+ numSamples);
+#endif
+
+#ifdef _COMPRESSOR_ENABLED
+ /* compressor effect */
+ if (pEASData->effectsModules[EAS_MODULE_COMPRESSOR].effectData)
+ (*pEASData->effectsModules[EAS_MODULE_COMPRESSOR].effect->pfProcess)
+ (pEASData->effectsModules[EAS_MODULE_COMPRESSOR].effectData,
+ pEASData->pOutputAudioBuffer,
+ pEASData->pOutputAudioBuffer,
+ numSamples);
+#endif
+
+#ifdef _WOW_ENABLED
+ /* WOW requires a 32-bit buffer, borrow the mix buffer and
+ * pass it as the destination buffer
+ */
+ /*lint -e{740} temporarily passing a parameter through an existing I/F */
+ if (pEASData->effectsModules[EAS_MODULE_WOW].effectData)
+ (*pEASData->effectsModules[EAS_MODULE_WOW].effect->pfProcess)
+ (pEASData->effectsModules[EAS_MODULE_WOW].effectData,
+ pEASData->pOutputAudioBuffer,
+ (EAS_PCM*) pEASData->pMixBuffer,
+ numSamples);
+#endif
+
+#ifdef _TONECONTROLEQ_ENABLED
+ /* ToneControlEQ effect */
+ if (pEASData->effectsModules[EAS_MODULE_TONECONTROLEQ].effectData)
+ (*pEASData->effectsModules[EAS_MODULE_TONECONTROLEQ].effect->pfProcess)
+ (pEASData->effectsModules[EAS_MODULE_TONECONTROLEQ].effectData,
+ pEASData->pOutputAudioBuffer,
+ pEASData->pOutputAudioBuffer,
+ numSamples);
+#endif
+
+#ifdef _REVERB_ENABLED
+ /* Reverb effect */
+ if (pEASData->effectsModules[EAS_MODULE_REVERB].effectData)
+ (*pEASData->effectsModules[EAS_MODULE_REVERB].effect->pfProcess)
+ (pEASData->effectsModules[EAS_MODULE_REVERB].effectData,
+ pEASData->pOutputAudioBuffer,
+ pEASData->pOutputAudioBuffer,
+ numSamples);
+#endif
+
+#ifdef _CHORUS_ENABLED
+ /* Chorus effect */
+ if (pEASData->effectsModules[EAS_MODULE_CHORUS].effectData)
+ (*pEASData->effectsModules[EAS_MODULE_CHORUS].effect->pfProcess)
+ (pEASData->effectsModules[EAS_MODULE_CHORUS].effectData,
+ pEASData->pOutputAudioBuffer,
+ pEASData->pOutputAudioBuffer,
+ numSamples);
+#endif
+
+}
+
+#ifndef NATIVE_EAS_KERNEL
+/*----------------------------------------------------------------------------
+ * SynthMasterGain
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Mixes down audio from 32-bit to 16-bit target buffer
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ *----------------------------------------------------------------------------
+*/
+void SynthMasterGain (long *pInputBuffer, EAS_PCM *pOutputBuffer, EAS_U16 nGain, EAS_U16 numSamples) {
+
+ /* loop through the buffer */
+ while (numSamples--) {
+ long s;
+
+ /* read a sample from the input buffer and add some guard bits */
+ s = *pInputBuffer++;
+
+ /* add some guard bits */
+ /*lint -e{704} <avoid divide for performance>*/
+ s = s >> 7;
+
+ /* apply master gain */
+ s *= (long) nGain;
+
+ /* shift to lower 16-bits */
+ /*lint -e{704} <avoid divide for performance>*/
+ s = s >> 9;
+
+ /* saturate */
+ s = SATURATE(s);
+
+ *pOutputBuffer++ = (EAS_PCM)s;
+ }
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ * EAS_MixEngineShutdown()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Shuts down effects modules and deallocates memory
+ *
+ * Inputs:
+ * pEASData - instance data
+ * pInstData - instance data handle
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_MixEngineShutdown (S_EAS_DATA *pEASData)
+{
+
+ /* check Configuration Module for static memory allocation */
+ if (!pEASData->staticMemoryModel && (pEASData->pMixBuffer != NULL))
+ EAS_HWFree(pEASData->hwInstData, pEASData->pMixBuffer);
+
+ return EAS_SUCCESS;
+}
+
+#ifdef UNIFIED_MIXER
+#ifndef NATIVE_MIX_STREAM
+/*----------------------------------------------------------------------------
+ * EAS_MixStream
+ *----------------------------------------------------------------------------
+ * Mix a 16-bit stream into a 32-bit buffer
+ *
+ * pInputBuffer 16-bit input buffer
+ * pMixBuffer 32-bit mix buffer
+ * numSamples number of samples to mix
+ * gainLeft initial gain left or mono
+ * gainRight initial gain right
+ * gainLeft left gain increment per sample
+ * gainRight right gain increment per sample
+ * flags bit 0 = stereo source
+ * bit 1 = stereo output
+ *----------------------------------------------------------------------------
+*/
+void EAS_MixStream (EAS_PCM *pInputBuffer, EAS_I32 *pMixBuffer, EAS_I32 numSamples, EAS_I32 gainLeft, EAS_I32 gainRight, EAS_I32 gainIncLeft, EAS_I32 gainIncRight, EAS_I32 flags)
+{
+ EAS_I32 temp;
+ EAS_INT src, dest;
+
+ /* NOTE: There are a lot of optimizations that can be done
+ * in the native implementations based on register
+ * availability, etc. For example, it may make sense to
+ * break this down into 8 separate routines:
+ *
+ * 1. Mono source to mono output
+ * 2. Mono source to stereo output
+ * 3. Stereo source to mono output
+ * 4. Stereo source to stereo output
+ * 5. Mono source to mono output - no gain change
+ * 6. Mono source to stereo output - no gain change
+ * 7. Stereo source to mono output - no gain change
+ * 8. Stereo source to stereo output - no gain change
+ *
+ * Other possibilities include loop unrolling, skipping
+ * a gain calculation every 2 or 4 samples, etc.
+ */
+
+ /* no gain change, use fast loops */
+ if ((gainIncLeft == 0) && (gainIncRight == 0))
+ {
+ switch (flags & (MIX_FLAGS_STEREO_SOURCE | MIX_FLAGS_STEREO_OUTPUT))
+ {
+ /* mono to mono */
+ case 0:
+ gainLeft >>= 15;
+ for (src = dest = 0; src < numSamples; src++, dest++)
+ {
+
+ pMixBuffer[dest] += (pInputBuffer[src] * gainLeft) >> NUM_MIXER_GUARD_BITS;
+ }
+ break;
+
+ /* mono to stereo */
+ case MIX_FLAGS_STEREO_OUTPUT:
+ gainLeft >>= 15;
+ gainRight >>= 15;
+ for (src = dest = 0; src < numSamples; src++, dest+=2)
+ {
+ pMixBuffer[dest] += (pInputBuffer[src] * gainLeft) >> NUM_MIXER_GUARD_BITS;
+ pMixBuffer[dest+1] += (pInputBuffer[src] * gainRight) >> NUM_MIXER_GUARD_BITS;
+ }
+ break;
+
+ /* stereo to mono */
+ case MIX_FLAGS_STEREO_SOURCE:
+ gainLeft >>= 15;
+ gainRight >>= 15;
+ for (src = dest = 0; src < numSamples; src+=2, dest++)
+ {
+ temp = (pInputBuffer[src] * gainLeft) >> NUM_MIXER_GUARD_BITS;
+ temp += ((pInputBuffer[src+1] * gainRight) >> NUM_MIXER_GUARD_BITS);
+ pMixBuffer[dest] += temp;
+ }
+ break;
+
+ /* stereo to stereo */
+ case MIX_FLAGS_STEREO_SOURCE | MIX_FLAGS_STEREO_OUTPUT:
+ gainLeft >>= 15;
+ gainRight >>= 15;
+ for (src = dest = 0; src < numSamples; src+=2, dest+=2)
+ {
+ pMixBuffer[dest] += (pInputBuffer[src] * gainLeft) >> NUM_MIXER_GUARD_BITS;
+ pMixBuffer[dest+1] += (pInputBuffer[src+1] * gainRight) >> NUM_MIXER_GUARD_BITS;
+ }
+ break;
+ }
+ }
+
+ /* gain change - do gain increment */
+ else
+ {
+ switch (flags & (MIX_FLAGS_STEREO_SOURCE | MIX_FLAGS_STEREO_OUTPUT))
+ {
+ /* mono to mono */
+ case 0:
+ for (src = dest = 0; src < numSamples; src++, dest++)
+ {
+ gainLeft += gainIncLeft;
+ pMixBuffer[dest] += (pInputBuffer[src] * (gainLeft >> 15)) >> NUM_MIXER_GUARD_BITS;
+ }
+ break;
+
+ /* mono to stereo */
+ case MIX_FLAGS_STEREO_OUTPUT:
+ for (src = dest = 0; src < numSamples; src++, dest+=2)
+ {
+ gainLeft += gainIncLeft;
+ gainRight += gainIncRight;
+ pMixBuffer[dest] += (pInputBuffer[src] * (gainLeft >> 15)) >> NUM_MIXER_GUARD_BITS;
+ pMixBuffer[dest+1] += (pInputBuffer[src] * (gainRight >> 15)) >> NUM_MIXER_GUARD_BITS;
+ }
+ break;
+
+ /* stereo to mono */
+ case MIX_FLAGS_STEREO_SOURCE:
+ for (src = dest = 0; src < numSamples; src+=2, dest++)
+ {
+ gainLeft += gainIncLeft;
+ gainRight += gainIncRight;
+ temp = (pInputBuffer[src] * (gainLeft >> 15)) >> NUM_MIXER_GUARD_BITS;
+ temp += ((pInputBuffer[src+1] * (gainRight >> 15)) >> NUM_MIXER_GUARD_BITS);
+ pMixBuffer[dest] += temp;
+ }
+ break;
+
+ /* stereo to stereo */
+ case MIX_FLAGS_STEREO_SOURCE | MIX_FLAGS_STEREO_OUTPUT:
+ for (src = dest = 0; src < numSamples; src+=2, dest+=2)
+ {
+ gainLeft += gainIncLeft;
+ gainRight += gainIncRight;
+ pMixBuffer[dest] += (pInputBuffer[src] * (gainLeft >> 15)) >> NUM_MIXER_GUARD_BITS;
+ pMixBuffer[dest+1] += (pInputBuffer[src+1] * (gainRight >> 15)) >> NUM_MIXER_GUARD_BITS;
+ }
+ break;
+ }
+ }
+}
+#endif
+#endif
+
diff --git a/arm-wt-22k/lib_src/eas_mixer.h b/arm-wt-22k/lib_src/eas_mixer.h
new file mode 100644
index 0000000..2ba2d3d
--- /dev/null
+++ b/arm-wt-22k/lib_src/eas_mixer.h
@@ -0,0 +1,137 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_mixer.h
+ *
+ * Contents and purpose:
+ * This file contains the critical components of the mix engine that
+ * must be optimized for best performance.
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 706 $
+ * $Date: 2007-05-31 17:22:51 -0700 (Thu, 31 May 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+#ifndef _EAS_MIXER_H
+#define _EAS_MIXER_H
+
+//3 dls: This module is in the midst of being converted from a synth
+//3 specific module to a general purpose mix engine
+
+#define MIX_FLAGS_STEREO_SOURCE 1
+#define MIX_FLAGS_STEREO_OUTPUT 2
+#define NUM_MIXER_GUARD_BITS 4
+
+#include "eas_effects.h"
+
+extern void SynthMasterGain( long *pInputBuffer, EAS_PCM *pOutputBuffer, EAS_U16 nGain, EAS_U16 nNumLoopSamples);
+
+/*----------------------------------------------------------------------------
+ * EAS_MixEngineInit()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Prepares the mix engine for work, allocates buffers, locates effects modules, etc.
+ *
+ * Inputs:
+ * pEASData - instance data
+ * pInstData - pointer to variable to receive instance data handle
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_MixEngineInit (EAS_DATA_HANDLE pEASData);
+
+/*----------------------------------------------------------------------------
+ * EAS_MixEnginePrep()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Performs prep before synthesize a buffer of audio, such as clearing
+ * audio buffers, etc.
+ *
+ * Inputs:
+ * psEASData - pointer to overall EAS data structure
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+void EAS_MixEnginePrep (EAS_DATA_HANDLE pEASData, EAS_I32 nNumSamplesToAdd);
+
+/*----------------------------------------------------------------------------
+ * EAS_MixEnginePost
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * This routine does the post-processing after all voices have been
+ * synthesized. It calls any sweeteners and does the final mixdown to
+ * the output buffer.
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ * Notes:
+ *----------------------------------------------------------------------------
+*/
+void EAS_MixEnginePost (EAS_DATA_HANDLE pEASData, EAS_I32 nNumSamplesToAdd);
+
+/*----------------------------------------------------------------------------
+ * EAS_MixEngineShutdown()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Shuts down effects modules and deallocates memory
+ *
+ * Inputs:
+ * pEASData - instance data
+ * pInstData - instance data handle
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_MixEngineShutdown (EAS_DATA_HANDLE pEASData);
+
+#ifdef UNIFIED_MIXER
+/*----------------------------------------------------------------------------
+ * EAS_MixStream
+ *----------------------------------------------------------------------------
+ * Mix a 16-bit stream into a 32-bit buffer
+ *
+ * pInputBuffer 16-bit input buffer
+ * pMixBuffer 32-bit mix buffer
+ * numSamples number of samples to mix
+ * gainLeft initial gain left or mono
+ * gainRight initial gain right
+ * gainLeft left gain increment per sample
+ * gainRight right gain increment per sample
+ * flags bit 0 = stereo source
+ * bit 1 = stereo output
+ *----------------------------------------------------------------------------
+*/
+void EAS_MixStream (EAS_PCM *pInputBuffer, EAS_I32 *pMixBuffer, EAS_I32 numSamples, EAS_I32 gainLeft, EAS_I32 gainRight, EAS_I32 gainIncLeft, EAS_I32 gainIncRight, EAS_I32 flags);
+#endif
+
+#endif /* #ifndef _EAS_MIXER_H */
+
diff --git a/arm-wt-22k/lib_src/eas_ota.c b/arm-wt-22k/lib_src/eas_ota.c
new file mode 100644
index 0000000..fb81d62
--- /dev/null
+++ b/arm-wt-22k/lib_src/eas_ota.c
@@ -0,0 +1,1077 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_ota.c
+ *
+ * Contents and purpose:
+ * OTA parser
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 795 $
+ * $Date: 2007-08-01 00:14:45 -0700 (Wed, 01 Aug 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+#include "eas_data.h"
+#include "eas_miditypes.h"
+#include "eas_parser.h"
+#include "eas_report.h"
+#include "eas_host.h"
+#include "eas_midi.h"
+#include "eas_config.h"
+#include "eas_vm_protos.h"
+#include "eas_otadata.h"
+
+/* increase gain for mono ringtones */
+#define OTA_GAIN_OFFSET 8
+
+/* file definitions */
+#define OTA_RINGTONE 0x25
+#define OTA_SOUND 0x1d
+#define OTA_UNICODE 0x22
+
+/* song type definitions */
+#define OTA_BASIC_SONG_TYPE 0x01
+#define OTA_TEMPORARY_SONG_TYPE 0x02
+
+/* instruction ID coding */
+#define OTA_PATTERN_HEADER_ID 0x00
+#define OTA_NOTE_INST_ID 0x01
+#define OTA_SCALE_INST_ID 0x02
+#define OTA_STYLE_INST_ID 0x03
+#define OTA_TEMPO_INST_ID 0x04
+#define OTA_VOLUME_INST_ID 0x05
+
+/* note durations */
+#define OTA_NORMAL_DURATION 0x00
+#define OTA_DOTTED_NOTE 0x01
+#define OTA_DOUBLE_DOTTED_NOTE 0x02
+#define OTA_TRIPLET_NOTE 0x03
+
+/* loop count value for infinite loop */
+#define OTA_INFINITE_LOOP 0x0f
+
+/* length of 32nd note in 1/256ths of a msec for 63 BPM tempo */
+#define DEFAULT_TICK_CONV 30476
+
+/* default channel and program for OTA playback */
+#define OTA_CHANNEL 0
+#define OTA_PROGRAM 80
+#define OTA_VEL_MUL 4
+#define OTA_VEL_OFS 67
+#define OTA_VEL_DEFAULT 95
+
+/* multiplier for fixed point triplet conversion */
+#define TRIPLET_MULTIPLIER 683
+#define TRIPLET_SHIFT 10
+
+/* local prototypes */
+static EAS_RESULT OTA_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset);
+static EAS_RESULT OTA_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
+static EAS_RESULT OTA_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime);
+static EAS_RESULT OTA_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode);
+static EAS_RESULT OTA_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState);
+static EAS_RESULT OTA_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
+static EAS_RESULT OTA_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
+static EAS_RESULT OTA_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
+static EAS_RESULT OTA_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
+static EAS_RESULT OTA_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value);
+static EAS_RESULT OTA_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue);
+static EAS_RESULT OTA_ParseHeader (S_EAS_DATA *pEASData, S_OTA_DATA* pData);
+static EAS_RESULT OTA_FetchBitField (EAS_HW_DATA_HANDLE hwInstData, S_OTA_DATA *pData, EAS_I32 numBits, EAS_U8 *pValue);
+static EAS_RESULT OTA_SavePosition (EAS_HW_DATA_HANDLE hwInstData, S_OTA_DATA *pData, S_OTA_LOC *pLoc);
+static EAS_RESULT OTA_RestorePosition (EAS_HW_DATA_HANDLE hwInstData, S_OTA_DATA *pData, S_OTA_LOC *pLoc);
+
+
+/*----------------------------------------------------------------------------
+ *
+ * EAS_OTA_Parser
+ *
+ * This structure contains the functional interface for the OTA parser
+ *----------------------------------------------------------------------------
+*/
+const S_FILE_PARSER_INTERFACE EAS_OTA_Parser =
+{
+ OTA_CheckFileType,
+ OTA_Prepare,
+ OTA_Time,
+ OTA_Event,
+ OTA_State,
+ OTA_Close,
+ OTA_Reset,
+ OTA_Pause,
+ OTA_Resume,
+ NULL,
+ OTA_SetData,
+ OTA_GetData,
+ NULL
+};
+
+/*----------------------------------------------------------------------------
+ *
+ * bpmTable
+ *
+ * BPM conversion table. Converts bpm values to 256ths of a millisecond for a 32nd note
+ *----------------------------------------------------------------------------
+*/
+static const EAS_U32 bpmTable[32] =
+{
+ 76800, 68571, 61935, 54857,
+ 48000, 42667, 38400, 34286,
+ 30476, 27429, 24000, 21333,
+ 19200, 17143, 15360, 13714,
+ 12000, 10667, 9600, 8533,
+ 7680, 6737, 6000, 5408,
+ 4800, 4267, 3840, 3398,
+ 3024, 2685, 2400, 2133
+};
+
+/*----------------------------------------------------------------------------
+ * OTA_CheckFileType()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Check the file type to see if we can parse it
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT OTA_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset)
+{
+ S_OTA_DATA* pData;
+ EAS_RESULT result;
+ EAS_INT cmdLen;
+ EAS_INT state;
+ EAS_U8 temp;
+
+ /* read the first byte, should be command length */
+ *ppHandle = NULL;
+ if ((result = EAS_HWGetByte(pEASData->hwInstData, fileHandle, &temp)) != EAS_SUCCESS)
+ return result;
+
+ /* read all the commands */
+ cmdLen = temp;
+ state = 0;
+ while (cmdLen--)
+ {
+
+ /* read the command, upper 7 bits */
+ if ((result = EAS_HWGetByte(pEASData->hwInstData, fileHandle, &temp)) != EAS_SUCCESS)
+ return result;
+ temp = temp >> 1;
+
+ if (state == 0)
+ {
+ if (temp != OTA_RINGTONE)
+ break;
+ state++;
+ }
+ else
+ {
+
+ if (temp == OTA_SOUND)
+ {
+
+ /* check for static memory allocation */
+ if (pEASData->staticMemoryModel)
+ pData = EAS_CMEnumData(EAS_CM_OTA_DATA);
+ else
+ pData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_OTA_DATA));
+ if (!pData)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Malloc failed in OTA_Prepare\n"); */ }
+ return EAS_ERROR_MALLOC_FAILED;
+ }
+ EAS_HWMemSet(pData, 0, sizeof(S_OTA_DATA));
+
+ /* return a pointer to the instance data */
+ pData->fileHandle = fileHandle;
+ pData->fileOffset = offset;
+ pData->state = EAS_STATE_OPEN;
+ *ppHandle = pData;
+ break;
+ }
+
+ if (temp != OTA_UNICODE)
+ break;
+ }
+ }
+
+ /* not recognized */
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * OTA_Prepare()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Prepare to parse the file. Allocates instance data (or uses static allocation for
+ * static memory model).
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT OTA_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
+{
+ S_OTA_DATA* pData;
+ EAS_RESULT result;
+
+ /* check for valid state */
+ pData = (S_OTA_DATA*) pInstData;
+ if (pData->state != EAS_STATE_OPEN)
+ return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
+
+ /* instantiate a synthesizer */
+ if ((result = VMInitMIDI(pEASData, &pData->pSynth)) != EAS_SUCCESS)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMInitMIDI returned %d\n", result); */ }
+ return result;
+ }
+
+ pData->state = EAS_STATE_ERROR;
+ if ((result = OTA_ParseHeader(pEASData, pData)) != EAS_SUCCESS)
+ return result;
+
+ pData->state = EAS_STATE_READY;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * OTA_Time()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Returns the time of the next event in msecs
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ * pTime - pointer to variable to hold time of next event (in msecs)
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pEASData) common decoder interface - pEASData not used */
+static EAS_RESULT OTA_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime)
+{
+ S_OTA_DATA *pData;
+
+ pData = (S_OTA_DATA*) pInstData;
+
+ /* return time in milliseconds */
+ /*lint -e{704} use shift instead of division */
+ *pTime = pData->time >> 8;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * OTA_Event()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Parse the next event in the file
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT OTA_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode)
+{
+ S_OTA_DATA* pData;
+ EAS_RESULT result;
+ EAS_U32 duration;
+ EAS_U8 temp;
+
+ pData = (S_OTA_DATA*) pInstData;
+ if (pData->state >= EAS_STATE_OPEN)
+ return EAS_SUCCESS;
+
+ /* initialize MIDI channel when the track starts playing */
+ if (pData->time == 0)
+ {
+ /* set program to square lead */
+ if (parserMode != eParserModeMetaData)
+ VMProgramChange(pEASData->pVoiceMgr, pData->pSynth, OTA_CHANNEL, OTA_PROGRAM);
+
+ /* set channel volume to max */
+ if (parserMode != eParserModeMetaData)
+ VMControlChange(pEASData->pVoiceMgr, pData->pSynth, OTA_CHANNEL, 7, 127);
+ }
+
+ /* check for end of note */
+ if (pData->note)
+ {
+ /* stop the note */
+ VMStopNote(pEASData->pVoiceMgr, pData->pSynth, OTA_CHANNEL, pData->note, 0);
+ pData->note = 0;
+
+ /* check for rest between notes */
+ if (pData->restTicks)
+ {
+ pData->time += (EAS_I32) pData->restTicks;
+ pData->restTicks = 0;
+ return EAS_SUCCESS;
+ }
+ }
+
+ /* if not in a pattern, read the pattern header */
+ while (pData->current.patternLen == 0)
+ {
+
+ /* check for loop - don't do infinite loops when locating */
+ if (pData->loopCount && ((parserMode == eParserModePlay) || (pData->loopCount != OTA_INFINITE_LOOP)))
+ {
+ /* if not infinite loop, decrement loop count */
+ if (pData->loopCount != OTA_INFINITE_LOOP)
+ pData->loopCount--;
+
+ /* back to start of pattern*/
+ if ((result = OTA_RestorePosition(pEASData->hwInstData, pData, &pData->patterns[pData->currentPattern])) != EAS_SUCCESS)
+ return result;
+ }
+
+ /* if no previous position to restore, continue forward */
+ else if (pData->restore.fileOffset < 0)
+ {
+
+ /* check for end of song */
+ if (pData->numPatterns == 0)
+ {
+ pData->state = EAS_STATE_STOPPING;
+ VMReleaseAllVoices(pEASData->pVoiceMgr, pData->pSynth);
+ return EAS_SUCCESS;
+ }
+
+ /* read the next pattern header */
+ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 3, &temp)) != EAS_SUCCESS)
+ return result;
+ if (temp != OTA_PATTERN_HEADER_ID)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Expected OTA pattern header\n"); */ }
+ return EAS_ERROR_FILE_FORMAT;
+ }
+
+ /* get the pattern ID */
+ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 2, &pData->currentPattern)) != EAS_SUCCESS)
+ return result;
+
+ /* get the loop count */
+ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 4, &pData->loopCount)) != EAS_SUCCESS)
+ return result;
+
+ /* get the pattern length */
+ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 8, &pData->current.patternLen)) != EAS_SUCCESS)
+ return result;
+
+ /* if pattern definition, save the current position */
+ if (pData->current.patternLen)
+ {
+ if ((result = OTA_SavePosition(pEASData->hwInstData, pData, &pData->patterns[pData->currentPattern])) != EAS_SUCCESS)
+ return result;
+ }
+
+ /* if pattern length is zero, repeat a previous pattern */
+ else
+ {
+ /* make sure it's a valid pattern */
+ if (pData->patterns[pData->currentPattern].fileOffset < 0)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "OTA pattern error, invalid pattern specified\n"); */ }
+ return EAS_ERROR_FILE_FORMAT;
+ }
+
+ /* save current position and data */
+ if ((result = OTA_SavePosition(pEASData->hwInstData, pData, &pData->restore)) != EAS_SUCCESS)
+ return result;
+
+ /* seek to the pattern in the file */
+ if ((result = OTA_RestorePosition(pEASData->hwInstData, pData, &pData->patterns[pData->currentPattern])) != EAS_SUCCESS)
+ return result;
+ }
+
+ /* decrement pattern count */
+ pData->numPatterns--;
+ }
+
+ /* restore previous position */
+ else
+ {
+ if ((result = OTA_RestorePosition(pEASData->hwInstData, pData, &pData->restore)) != EAS_SUCCESS)
+ return result;
+ }
+ }
+
+ /* get the next event */
+ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 3, &temp)) != EAS_SUCCESS)
+ return result;
+
+ switch (temp)
+ {
+ case OTA_NOTE_INST_ID:
+ /* fetch note value */
+ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 4, &pData->note)) != EAS_SUCCESS)
+ return result;
+
+ /* fetch note duration */
+ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 3, &temp)) != EAS_SUCCESS)
+ return result;
+ duration = pData->tick * (0x20 >> temp);
+
+ /* fetch note duration modifier */
+ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 2, &temp)) != EAS_SUCCESS)
+ return result;
+ switch (temp)
+ {
+ case OTA_NORMAL_DURATION:
+ break;
+
+ case OTA_DOTTED_NOTE:
+ duration += duration >> 1;
+ break;
+
+ case OTA_DOUBLE_DOTTED_NOTE:
+ duration += (duration >> 1) + (duration >> 2);
+ break;
+
+ case OTA_TRIPLET_NOTE:
+ duration = (duration * TRIPLET_MULTIPLIER) >> TRIPLET_SHIFT;
+ break;
+
+ default:
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Unrecognized note duration ignored\n"); */ }
+ break;
+ }
+
+ /* check for note */
+ if (pData->note)
+ {
+
+ /* determine note length based on style */
+ switch (pData->style)
+ {
+ case 0:
+ pData->restTicks = duration >> 4;
+ break;
+ case 1:
+ pData->restTicks = 0;
+ break;
+ case 2:
+ pData->restTicks = duration >> 1;
+ break;
+ default:
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Unrecognized note style ignored\n"); */ }
+ }
+
+ /* add octave */
+ pData->note += pData->octave;
+ if (parserMode == eParserModePlay)
+ VMStartNote(pEASData->pVoiceMgr, pData->pSynth, OTA_CHANNEL, pData->note, pData->velocity);
+ pData->time += (EAS_I32) duration - (EAS_I32) pData->restTicks;
+ }
+
+ /* this is a rest */
+ else
+ pData->time += (EAS_I32) duration;
+ break;
+
+ case OTA_SCALE_INST_ID:
+ /* fetch octave */
+ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 2, &temp)) != EAS_SUCCESS)
+ return result;
+ pData->octave = (EAS_U8) (temp * 12 + 59);
+ break;
+
+ case OTA_STYLE_INST_ID:
+ /* fetch note style */
+ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 2, &pData->style)) != EAS_SUCCESS)
+ return result;
+ break;
+
+ case OTA_TEMPO_INST_ID:
+ /* fetch tempo */
+ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 5, &temp)) != EAS_SUCCESS)
+ return result;
+ pData->tick = bpmTable[temp];
+ break;
+
+ case OTA_VOLUME_INST_ID:
+ /* fetch volume */
+ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 4, &temp)) != EAS_SUCCESS)
+ return result;
+ pData->velocity = temp ? (EAS_U8) (temp * OTA_VEL_MUL + OTA_VEL_OFS) : 0;
+ break;
+
+ default:
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unexpected instruction ID in OTA stream\n"); */ }
+ return EAS_ERROR_FILE_FORMAT;
+ }
+
+ /* decrement pattern length */
+ pData->current.patternLen--;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * OTA_State()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Returns the current state of the stream
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ * pState - pointer to variable to store state
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pEASData) common decoder interface - pEASData not used */
+static EAS_RESULT OTA_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pState)
+{
+ S_OTA_DATA* pData;
+
+ /* establish pointer to instance data */
+ pData = (S_OTA_DATA*) pInstData;
+
+ /* if stopping, check to see if synth voices are active */
+ if (pData->state == EAS_STATE_STOPPING)
+ {
+ if (VMActiveVoices(pData->pSynth) == 0)
+ pData->state = EAS_STATE_STOPPED;
+ }
+
+ if (pData->state == EAS_STATE_PAUSING)
+ {
+ if (VMActiveVoices(pData->pSynth) == 0)
+ pData->state = EAS_STATE_PAUSED;
+ }
+
+ /* return current state */
+ *pState = pData->state;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * OTA_Close()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Close the file and clean up
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT OTA_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
+{
+ S_OTA_DATA* pData;
+ EAS_RESULT result;
+
+ pData = (S_OTA_DATA*) pInstData;
+
+ /* close the file */
+ if ((result = EAS_HWCloseFile(pEASData->hwInstData, pData->fileHandle)) != EAS_SUCCESS)
+ return result;
+
+ /* free the synth */
+ if (pData->pSynth != NULL)
+ VMMIDIShutdown(pEASData, pData->pSynth);
+
+ /* if using dynamic memory, free it */
+ if (!pEASData->staticMemoryModel)
+ EAS_HWFree(pEASData->hwInstData, pData);
+
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * OTA_Reset()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Reset the sequencer. Used for locating backwards in the file.
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT OTA_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
+{
+ S_OTA_DATA* pData;
+ EAS_RESULT result;
+
+ pData = (S_OTA_DATA*) pInstData;
+
+ /* reset the synth */
+ VMReset(pEASData->pVoiceMgr, pData->pSynth, EAS_TRUE);
+ pData->note = 0;
+
+ /* reset file position and re-parse header */
+ pData->state = EAS_STATE_ERROR;
+ if ((result = OTA_ParseHeader (pEASData, pData)) != EAS_SUCCESS)
+ return result;
+
+ pData->state = EAS_STATE_READY;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * OTA_Pause()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Pauses the sequencer. Mutes all voices and sets state to pause.
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT OTA_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
+{
+ S_OTA_DATA *pData;
+
+ /* can't pause a stopped stream */
+ pData = (S_OTA_DATA*) pInstData;
+ if (pData->state == EAS_STATE_STOPPED)
+ return EAS_ERROR_ALREADY_STOPPED;
+
+ /* mute the synthesizer */
+ VMMuteAllVoices(pEASData->pVoiceMgr, pData->pSynth);
+ pData->state = EAS_STATE_PAUSING;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * OTA_Resume()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Resume playing after a pause, sets state back to playing.
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pEASData) common decoder interface - pEASData not used */
+static EAS_RESULT OTA_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
+{
+ S_OTA_DATA *pData;
+
+ /* can't resume a stopped stream */
+ pData = (S_OTA_DATA*) pInstData;
+ if (pData->state == EAS_STATE_STOPPED)
+ return EAS_ERROR_ALREADY_STOPPED;
+
+ /* nothing to do but resume playback */
+ pData->state = EAS_STATE_PLAY;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * OTA_SetData()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Return file type
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pEASData) common decoder interface - pEASData not used */
+static EAS_RESULT OTA_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value)
+{
+ S_OTA_DATA *pData;
+
+ pData = (S_OTA_DATA *) pInstData;
+ switch (param)
+ {
+
+ /* set metadata callback */
+ case PARSER_DATA_METADATA_CB:
+ EAS_HWMemCpy(&pData->metadata, (void*) value, sizeof(S_METADATA_CB));
+ break;
+
+ default:
+ return EAS_ERROR_INVALID_PARAMETER;
+ }
+
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * OTA_GetData()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Return file type
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pEASData) common decoder interface - pEASData not used */
+static EAS_RESULT OTA_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue)
+{
+ S_OTA_DATA *pData;
+
+ pData = (S_OTA_DATA*) pInstData;
+ switch (param)
+ {
+ /* return file type as OTA */
+ case PARSER_DATA_FILE_TYPE:
+ *pValue = EAS_FILE_OTA;
+ break;
+
+#if 0
+ /* set transposition */
+ case PARSER_DATA_TRANSPOSITION:
+ *pValue = pData->transposition;
+ break;
+#endif
+
+ case PARSER_DATA_SYNTH_HANDLE:
+ *pValue = (EAS_I32) pData->pSynth;
+ break;
+
+ case PARSER_DATA_GAIN_OFFSET:
+ *pValue = OTA_GAIN_OFFSET;
+ break;
+
+ default:
+ return EAS_ERROR_INVALID_PARAMETER;
+ }
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * OTA_ParseHeader()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Prepare to parse the file. Allocates instance data (or uses static allocation for
+ * static memory model).
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT OTA_ParseHeader (S_EAS_DATA *pEASData, S_OTA_DATA* pData)
+{
+ EAS_RESULT result;
+ EAS_INT i;
+ EAS_INT state;
+ EAS_U8 temp;
+ EAS_U8 titleLen;
+
+ /* initialize some data */
+ pData->flags = 0;
+ pData->time = 0;
+ pData->tick = DEFAULT_TICK_CONV;
+ pData->patterns[0].fileOffset = pData->patterns[1].fileOffset =
+ pData->patterns[2].fileOffset = pData->patterns[3].fileOffset = -1;
+ pData->current.bitCount = 0;
+ pData->current.patternLen = 0;
+ pData->loopCount = 0;
+ pData->restore.fileOffset = -1;
+ pData->note = 0;
+ pData->restTicks = 0;
+ pData->velocity = OTA_VEL_DEFAULT;
+ pData->style = 0;
+ pData->octave = 59;
+
+ /* seek to start of data */
+ if ((result = EAS_HWFileSeek(pEASData->hwInstData, pData->fileHandle, pData->fileOffset)) != EAS_SUCCESS)
+ return result;
+
+ /* read the first byte, should be command length */
+ if ((result = EAS_HWGetByte(pEASData->hwInstData, pData->fileHandle, &temp)) != EAS_SUCCESS)
+ return result;
+
+ /* read all the commands */
+ i = temp;
+ state = 0;
+ while (i--)
+ {
+
+ /* fetch command, always starts on byte boundary */
+ pData->current.bitCount = 0;
+ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 7, &temp)) != EAS_SUCCESS)
+ return result;
+
+ if (state == 0)
+ {
+ if (temp != OTA_RINGTONE)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Expected OTA Ring Tone Programming type\n"); */ }
+ return EAS_ERROR_FILE_FORMAT;
+ }
+ state++;
+ }
+ else
+ {
+
+ if (temp == OTA_SOUND)
+ break;
+
+ if (temp == OTA_UNICODE)
+ pData->flags |= OTA_FLAGS_UNICODE;
+ else
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Expected OTA Sound or Unicode type\n"); */ }
+ return EAS_ERROR_FILE_FORMAT;
+ }
+ }
+ }
+
+ /* get song type */
+ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 3, &temp)) != EAS_SUCCESS)
+ return result;
+
+ /* check for basic song type */
+ if (temp == OTA_BASIC_SONG_TYPE)
+ {
+ /* fetch title length */
+ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 4, &titleLen)) != EAS_SUCCESS)
+ return result;
+
+ /* if unicode, double the length */
+ if (pData->flags & OTA_FLAGS_UNICODE)
+ titleLen = (EAS_U8) (titleLen << 1);
+
+ /* zero the metadata buffer */
+ if (pData->metadata.buffer)
+ EAS_HWMemSet(pData->metadata.buffer, 0, pData->metadata.bufferSize);
+
+ /* read the song title */
+ for (i = 0; i < titleLen; i++)
+ {
+ /* fetch character */
+ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 8, &temp)) != EAS_SUCCESS)
+ return result;
+
+ /* check for metadata callback */
+ if (pData->metadata.callback)
+ {
+ if (i < (pData->metadata.bufferSize - 1))
+ pData->metadata.buffer[i] = (char) temp;
+ }
+ }
+
+ /* if host has registered callback, call it now */
+ if (pData->metadata.callback)
+ (*pData->metadata.callback)(EAS_METADATA_TITLE, pData->metadata.buffer, pData->metadata.pUserData);
+ }
+
+ /* must be temporary song */
+ else if (temp != OTA_TEMPORARY_SONG_TYPE)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Expected OTA basic or temporary song type\n"); */ }
+ return EAS_ERROR_FILE_FORMAT;
+ }
+
+ /* get the song length */
+ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 8, &pData->numPatterns)) != EAS_SUCCESS)
+ return result;
+
+ /* sanity check */
+ if (pData->numPatterns == 0)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "OTA number of patterns is zero\n"); */ }
+ return EAS_ERROR_FILE_FORMAT;
+ }
+
+ /* at start of first pattern */
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * OTA_FetchBitField()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Fetch a specified number of bits from the input stream
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT OTA_FetchBitField (EAS_HW_DATA_HANDLE hwInstData, S_OTA_DATA *pData, EAS_I32 numBits, EAS_U8 *pValue)
+{
+ EAS_RESULT result;
+ EAS_I32 bitsLeft;
+ EAS_U8 value;
+
+ value = 0;
+
+ /* do we have enough bits? */
+ bitsLeft = pData->current.bitCount - numBits;
+
+ /* not enough bits, assemble them from 2 characters */
+ if (bitsLeft < 0)
+ {
+ /* grab the remaining bits from the previous byte */
+ if (pData->current.bitCount)
+ /*lint -e{504,734} this is a legitimate shift operation */
+ value = pData->current.dataByte << -bitsLeft;
+
+ /* read the next byte */
+ if ((result = EAS_HWGetByte(hwInstData, pData->fileHandle, &pData->current.dataByte)) != EAS_SUCCESS)
+ return result;
+ bitsLeft += 8;
+ }
+
+ /* more bits than needed? */
+ if (bitsLeft > 0)
+ {
+ value |= pData->current.dataByte >> bitsLeft;
+ pData->current.bitCount = (EAS_U8) bitsLeft;
+ pData->current.dataByte = pData->current.dataByte & (0xff >> (8 - bitsLeft));
+ }
+
+ /* exactly the right number of bits */
+ else
+ {
+ value |= pData->current.dataByte;
+ pData->current.bitCount = 0;
+ }
+
+ *pValue = value;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * OTA_SavePosition()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT OTA_SavePosition (EAS_HW_DATA_HANDLE hwInstData, S_OTA_DATA *pData, S_OTA_LOC *pLoc)
+{
+ EAS_HWMemCpy(pLoc, &pData->current, sizeof(S_OTA_LOC));
+ return EAS_HWFilePos(hwInstData, pData->fileHandle, &pLoc->fileOffset);
+}
+
+/*----------------------------------------------------------------------------
+ * OTA_RestorePosition()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT OTA_RestorePosition (EAS_HW_DATA_HANDLE hwInstData, S_OTA_DATA *pData, S_OTA_LOC *pLoc)
+{
+ EAS_HWMemCpy(&pData->current, pLoc, sizeof(S_OTA_LOC));
+ pData->restore.fileOffset = -1;
+ return EAS_HWFileSeek(hwInstData, pData->fileHandle, pLoc->fileOffset);
+}
+
diff --git a/arm-wt-22k/lib_src/eas_otadata.c b/arm-wt-22k/lib_src/eas_otadata.c
new file mode 100644
index 0000000..237f832
--- /dev/null
+++ b/arm-wt-22k/lib_src/eas_otadata.c
@@ -0,0 +1,41 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_otadata..c
+ *
+ * Contents and purpose:
+ * OTA Stream Parser data module for static memory model
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 547 $
+ * $Date: 2007-01-31 16:30:17 -0800 (Wed, 31 Jan 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+#include "eas_types.h"
+#include "eas_otadata.h"
+
+/*----------------------------------------------------------------------------
+ *
+ * eas_OTAData
+ *
+ * Static memory allocation for OTA parser
+ *----------------------------------------------------------------------------
+*/
+S_OTA_DATA eas_OTAData;
+
diff --git a/arm-wt-22k/lib_src/eas_otadata.h b/arm-wt-22k/lib_src/eas_otadata.h
new file mode 100644
index 0000000..63e963f
--- /dev/null
+++ b/arm-wt-22k/lib_src/eas_otadata.h
@@ -0,0 +1,81 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_otadata.h
+ *
+ * Contents and purpose:
+ * OTA File Parser
+ *
+ * This file contains data declarations for the OTA parser.
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 82 $
+ * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $
+ *----------------------------------------------------------------------------
+*/
+
+#ifndef EAS_OTADATA_H
+#define EAS_OTADATA_H
+
+#include "eas_data.h"
+
+/* definition for state flags */
+#define OTA_FLAGS_UNICODE 0x01 /* unicode text */
+
+/*----------------------------------------------------------------------------
+ *
+ * S_OTA_DATA
+ *
+ * This structure contains the state data for the OTA parser
+ *----------------------------------------------------------------------------
+*/
+
+typedef struct
+{
+ EAS_I32 fileOffset; /* offset to location in file */
+ EAS_U8 patternLen; /* length of current pattern */
+ EAS_U8 dataByte; /* previous char from file */
+ EAS_U8 bitCount; /* bit count in char */
+} S_OTA_LOC;
+
+typedef struct
+{
+ EAS_FILE_HANDLE fileHandle; /* file handle */
+ S_SYNTH *pSynth; /* synth handle */
+ EAS_I32 fileOffset; /* offset to start of data */
+ EAS_I32 time; /* current time in 256ths of a msec */
+ EAS_U32 tick; /* length of 32nd note in 256th of a msec */
+ EAS_U32 restTicks; /* ticks to rest after current note */
+ S_OTA_LOC patterns[4]; /* pattern locations */
+ S_OTA_LOC current; /* current location */
+ S_OTA_LOC restore; /* previous location */
+ S_METADATA_CB metadata; /* metadata callback */
+ EAS_U8 flags; /* bit flags */
+ EAS_U8 numPatterns; /* number of patterns left in song */
+ EAS_U8 currentPattern; /* current pattern for loop */
+ EAS_U8 note; /* MIDI note number */
+ EAS_U8 octave; /* octave modifier */
+ EAS_U8 style; /* from STYLE */
+ EAS_U8 velocity; /* current volume */
+ EAS_U8 state; /* current state EAS_STATE_XXXX */
+ EAS_U8 loopCount; /* loop count for pattern */
+} S_OTA_DATA;
+
+#endif
+
+
diff --git a/arm-wt-22k/lib_src/eas_pan.c b/arm-wt-22k/lib_src/eas_pan.c
new file mode 100644
index 0000000..373d90e
--- /dev/null
+++ b/arm-wt-22k/lib_src/eas_pan.c
@@ -0,0 +1,98 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_pan.c
+ *
+ * Contents and purpose:
+ * Calculates left and right gain multipliers based on a pan value from -63 to +63
+ *
+ * NOTES:
+ * The _CMX_PARSER and _MFI_PARSER preprocessor symbols determine
+ * whether the parser works for those particular file formats.
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 82 $
+ * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $
+ *----------------------------------------------------------------------------
+*/
+
+#include "eas_pan.h"
+#include "eas_math.h"
+
+/*----------------------------------------------------------------------------
+ * EAS_CalcPanControl()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Assign the left and right gain values corresponding to the given pan value.
+ *
+ * This routine uses sin/cos approximations for an equal power curve:
+ *
+ * sin(x) = (2-4*c)*x^2 + c + x
+ * cos(x) = (2-4*c)*x^2 + c - x
+ *
+ * where c = 1/sqrt(2)
+ * using the a0 + x*(a1 + x*a2) approach
+ *
+ * Inputs:
+ * pan - pan value (-63 to + 63)
+ *
+ * Outputs:
+ * pGainLeft linear gain multiplier for left channel (15-bit fraction)
+ * pGainRight linear gain multiplier for left channel (15-bit fraction)
+ *
+ * Side Effects:
+ *----------------------------------------------------------------------------
+*/
+void EAS_CalcPanControl (EAS_INT pan, EAS_I16 *pGainLeft, EAS_I16 *pGainRight)
+{
+ EAS_INT temp;
+ EAS_INT netAngle;
+
+ /* impose hard limit */
+ if (pan < -63)
+ netAngle = -63;
+ else if (pan > 63)
+ netAngle = 63;
+ else
+ netAngle = pan;
+
+ /*lint -e{701} <avoid multiply for performance reasons>*/
+ netAngle = netAngle << 8;
+
+ /* calculate sin */
+ temp = EG1_ONE + FMUL_15x15(COEFF_PAN_G2, netAngle);
+ temp = COEFF_PAN_G0 + FMUL_15x15(temp, netAngle);
+
+ if (temp > SYNTH_FULL_SCALE_EG1_GAIN)
+ temp = SYNTH_FULL_SCALE_EG1_GAIN;
+ else if (temp < 0)
+ temp = 0;
+
+ *pGainRight = (EAS_I16) temp;
+
+ /* calculate cos */
+ temp = -EG1_ONE + FMUL_15x15(COEFF_PAN_G2, netAngle);
+ temp = COEFF_PAN_G0 + FMUL_15x15(temp, netAngle);
+ if (temp > SYNTH_FULL_SCALE_EG1_GAIN)
+ temp = SYNTH_FULL_SCALE_EG1_GAIN;
+ else if (temp < 0)
+ temp = 0;
+
+ *pGainLeft = (EAS_I16) temp;
+}
+
diff --git a/arm-wt-22k/lib_src/eas_pan.h b/arm-wt-22k/lib_src/eas_pan.h
new file mode 100644
index 0000000..cefa650
--- /dev/null
+++ b/arm-wt-22k/lib_src/eas_pan.h
@@ -0,0 +1,66 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_pan.h
+ *
+ * Contents and purpose:
+ * Calculates left and right gain multipliers based on a pan value from -63 to +63
+ *
+ * NOTES:
+ * The _CMX_PARSER and _MFI_PARSER preprocessor symbols determine
+ * whether the parser works for those particular file formats.
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 82 $
+ * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $
+ *----------------------------------------------------------------------------
+*/
+
+#ifndef EAS_PAN_H
+#define _EAS_PAN_H
+
+#include "eas_types.h"
+
+/*----------------------------------------------------------------------------
+ * EAS_CalcPanControl()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Assign the left and right gain values corresponding to the given pan value.
+ *
+ * This routine uses sin/cos approximations for an equal power curve:
+ *
+ * sin(x) = (2-4*c)*x^2 + c + x
+ * cos(x) = (2-4*c)*x^2 + c - x
+ *
+ * where c = 1/sqrt(2)
+ * using the a0 + x*(a1 + x*a2) approach
+ *
+ * Inputs:
+ * pan - pan value (-63 to + 63)
+ *
+ * Outputs:
+ * pGainLeft linear gain multiplier for left channel (15-bit fraction)
+ * pGainRight linear gain multiplier for left channel (15-bit fraction)
+ *
+ * Side Effects:
+ *----------------------------------------------------------------------------
+*/
+void EAS_CalcPanControl (EAS_INT pan, EAS_I16 *pGainLeft, EAS_I16 *pGainRight);
+
+#endif
+
diff --git a/arm-wt-22k/lib_src/eas_parser.h b/arm-wt-22k/lib_src/eas_parser.h
new file mode 100644
index 0000000..5512c82
--- /dev/null
+++ b/arm-wt-22k/lib_src/eas_parser.h
@@ -0,0 +1,98 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_parser.h
+ *
+ * Contents and purpose:
+ * Interface declarations for the generic parser interface
+ *
+ * This header only contains declarations that are specific
+ * to this implementation.
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 767 $
+ * $Date: 2007-07-19 13:47:31 -0700 (Thu, 19 Jul 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+#ifndef _EAS_PARSER_H
+#define _EAS_PARSER_H
+
+#include "eas_types.h"
+
+
+/* metadata callback */
+typedef struct s_metadata_cb_tag
+{
+ EAS_METADATA_CBFUNC callback;
+ char *buffer;
+ EAS_VOID_PTR pUserData;
+ EAS_I32 bufferSize;
+} S_METADATA_CB;
+
+/* generic parser interface */
+typedef struct
+{
+ EAS_RESULT (* EAS_CONST pfCheckFileType)(struct s_eas_data_tag *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset);
+ EAS_RESULT (* EAS_CONST pfPrepare)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData);
+ EAS_RESULT (* EAS_CONST pfTime)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime);
+ EAS_RESULT (* EAS_CONST pfEvent)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData, EAS_INT parseMode);
+ EAS_RESULT (* EAS_CONST pfState)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState);
+ EAS_RESULT (* EAS_CONST pfClose)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData);
+ EAS_RESULT (* EAS_CONST pfReset)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData);
+ EAS_RESULT (* EAS_CONST pfPause)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData);
+ EAS_RESULT (* EAS_CONST pfResume)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData);
+ EAS_RESULT (* EAS_CONST pfLocate)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData, EAS_I32 time, EAS_BOOL *pParserLocate);
+ EAS_RESULT (* EAS_CONST pfSetData)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value);
+ EAS_RESULT (* EAS_CONST pfGetData)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue);
+ EAS_RESULT (* EAS_CONST pfGetMetaData)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pMediaLength);
+} S_FILE_PARSER_INTERFACE;
+
+typedef enum
+{
+ eParserModePlay,
+ eParserModeLocate,
+ eParserModeMute,
+ eParserModeMetaData
+} E_PARSE_MODE;
+
+typedef enum
+{
+ PARSER_DATA_FILE_TYPE,
+ PARSER_DATA_PLAYBACK_RATE,
+ PARSER_DATA_TRANSPOSITION,
+ PARSER_DATA_VOLUME,
+ PARSER_DATA_SYNTH_HANDLE,
+ PARSER_DATA_METADATA_CB,
+ PARSER_DATA_DLS_COLLECTION,
+ PARSER_DATA_EAS_LIBRARY,
+ PARSER_DATA_POLYPHONY,
+ PARSER_DATA_PRIORITY,
+ PARSER_DATA_FORMAT,
+ PARSER_DATA_MEDIA_LENGTH,
+ PARSER_DATA_JET_CB,
+ PARSER_DATA_MUTE_FLAGS,
+ PARSER_DATA_SET_MUTE,
+ PARSER_DATA_CLEAR_MUTE,
+ PARSER_DATA_NOTE_COUNT,
+ PARSER_DATA_MAX_PCM_STREAMS,
+ PARSER_DATA_GAIN_OFFSET,
+ PARSER_DATA_PLAY_MODE
+} E_PARSER_DATA;
+
+#endif /* #ifndef _EAS_PARSER_H */
diff --git a/arm-wt-22k/lib_src/eas_pcm.c b/arm-wt-22k/lib_src/eas_pcm.c
new file mode 100644
index 0000000..64b8f71
--- /dev/null
+++ b/arm-wt-22k/lib_src/eas_pcm.c
@@ -0,0 +1,1482 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_pcm.c
+ *
+ * Contents and purpose:
+ * Implements the PCM engine including ADPCM decode for SMAF and CMX audio playback.
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 849 $
+ * $Date: 2007-08-28 08:59:11 -0700 (Tue, 28 Aug 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+#include "eas_data.h"
+#include "eas_report.h"
+#include "eas_host.h"
+#include "eas_config.h"
+#include "eas_parser.h"
+#include "eas_pcm.h"
+#include "eas_math.h"
+#include "eas_mixer.h"
+
+#define PCM_MIXER_GUARD_BITS (NUM_MIXER_GUARD_BITS + 1)
+
+/*----------------------------------------------------------------------------
+ * Decoder interfaces
+ *----------------------------------------------------------------------------
+*/
+
+static EAS_RESULT LinearPCMDecode (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState);
+static EAS_RESULT LinearPCMLocate (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState, EAS_I32 time);
+
+static const S_DECODER_INTERFACE PCMDecoder =
+{
+ NULL,
+ LinearPCMDecode,
+ LinearPCMLocate,
+};
+
+/* SMAF ADPCM decoder */
+#ifdef _SMAF_PARSER
+extern S_DECODER_INTERFACE SmafDecoder;
+#define SMAF_DECODER &SmafDecoder
+extern S_DECODER_INTERFACE Smaf7BitDecoder;
+#define SMAF_7BIT_DECODER &Smaf7BitDecoder
+#else
+#define SMAF_DECODER NULL
+#define SMAF_7BIT_DECODER NULL
+#endif
+
+/* IMA ADPCM decoder */
+#ifdef _IMA_DECODER
+extern S_DECODER_INTERFACE IMADecoder;
+#define IMA_DECODER &IMADecoder
+#else
+#define IMA_DECODER NULL
+#endif
+
+static const S_DECODER_INTERFACE * const decoders[] =
+{
+ &PCMDecoder,
+ SMAF_DECODER,
+ IMA_DECODER,
+ SMAF_7BIT_DECODER
+};
+
+/*----------------------------------------------------------------------------
+ * Sample rate conversion
+ *----------------------------------------------------------------------------
+*/
+
+#define SRC_RATE_MULTIPLER (0x40000000 / _OUTPUT_SAMPLE_RATE)
+
+#ifdef _LOOKUP_SAMPLE_RATE
+static const EAS_U32 srcConvRate[][2] =
+{
+ 4000L, (4000L << 15) / _OUTPUT_SAMPLE_RATE,
+ 8000L, (8000L << 15) / _OUTPUT_SAMPLE_RATE,
+ 11025L, (11025L << 15) / _OUTPUT_SAMPLE_RATE,
+ 12000L, (12000L << 15) / _OUTPUT_SAMPLE_RATE,
+ 16000L, (16000L << 15) / _OUTPUT_SAMPLE_RATE,
+ 22050L, (22050L << 15) / _OUTPUT_SAMPLE_RATE,
+ 24000L, (24000L << 15) / _OUTPUT_SAMPLE_RATE,
+ 32000L, (32000L << 15) / _OUTPUT_SAMPLE_RATE
+};
+static EAS_U32 CalcBaseFreq (EAS_U32 sampleRate);
+#define SRC_CONV_RATE_ENTRIES (sizeof(srcConvRate)/sizeof(EAS_U32)/2)
+#endif
+
+
+/* interface prototypes */
+static EAS_RESULT RenderPCMStream (S_EAS_DATA *pEASData, S_PCM_STATE *pState, EAS_I32 numSamples);
+
+
+/* local prototypes */
+static S_PCM_STATE *FindSlot (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_PCM_CALLBACK pCallbackFunc, EAS_VOID_PTR cbInstData);
+static EAS_RESULT InitPCMStream (S_EAS_DATA *pEASData, S_PCM_STATE *pState);
+
+/*----------------------------------------------------------------------------
+ * EAS_PEInit()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Initializes the PCM engine
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_PEInit (S_EAS_DATA *pEASData)
+{
+ S_PCM_STATE *pState;
+ EAS_INT i;
+
+ /* check for static memory allocation */
+ if (pEASData->staticMemoryModel)
+ pEASData->pPCMStreams = EAS_CMEnumData(EAS_CM_PCM_DATA);
+ /* allocate dynamic memory */
+ else
+ pEASData->pPCMStreams = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_PCM_STATE) * MAX_PCM_STREAMS);
+
+ if (!pEASData->pPCMStreams)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate memory for PCM streams\n"); */ }
+ return EAS_ERROR_MALLOC_FAILED;
+ }
+
+ //zero the memory to insure complete initialization
+ EAS_HWMemSet((void *)(pEASData->pPCMStreams),0, sizeof(S_PCM_STATE) * MAX_PCM_STREAMS);
+
+ /* initialize the state data */
+ for (i = 0, pState = pEASData->pPCMStreams; i < MAX_PCM_STREAMS; i++, pState++)
+ pState->fileHandle = NULL;
+
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_PEShutdown()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Shuts down the PCM engine
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_PEShutdown (S_EAS_DATA *pEASData)
+{
+
+ /* free any dynamic memory */
+ if (!pEASData->staticMemoryModel)
+ {
+ if (pEASData->pPCMStreams)
+ {
+ EAS_HWFree(pEASData->hwInstData, pEASData->pPCMStreams);
+ pEASData->pPCMStreams = NULL;
+ }
+ }
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_PERender()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Render a buffer of PCM audio
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_PERender (S_EAS_DATA* pEASData, EAS_I32 numSamples)
+{
+ S_PCM_STATE *pState;
+ EAS_RESULT result;
+ EAS_INT i;
+
+ /* render all the active streams */
+ for (i = 0, pState = pEASData->pPCMStreams; i < MAX_PCM_STREAMS; i++, pState++)
+ {
+ if ((pState->fileHandle) && (pState->state != EAS_STATE_STOPPED) && (pState->state != EAS_STATE_PAUSED))
+ if ((result = RenderPCMStream(pEASData, pState, numSamples)) != EAS_SUCCESS)
+ return result;
+ }
+ return EAS_SUCCESS;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EAS_PEState()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Returns the current state of the stream
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ * pState - pointer to variable to store state
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ * Notes:
+ * This interface is also exposed in the internal library for use by the other modules.
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pEASData) reserved for future use */
+EAS_RESULT EAS_PEState (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pInstData, EAS_STATE *pState)
+{
+ /* return current state */
+ *pState = pInstData->state;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_PEClose()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Close the file and clean up
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_PEClose (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState)
+{
+ EAS_RESULT result;
+
+ if ((result = EAS_HWCloseFile(pEASData->hwInstData, pState->fileHandle)) != EAS_SUCCESS)
+ return result;
+
+ pState->fileHandle = NULL;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * PCM_Reset()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Reset the sequencer. Used for locating backwards in the file.
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_PEReset (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState)
+{
+ EAS_RESULT result;
+
+ /* reset file position to first byte of data in the stream */
+ if ((result = EAS_HWFileSeek(pEASData->hwInstData, pState->fileHandle, pState->startPos)) != EAS_SUCCESS)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %d seeking to start of PCM file\n", result); */ }
+ return result;
+ }
+
+ /* re-initialize stream */
+ return InitPCMStream(pEASData, pState);
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_PEOpenStream()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Starts up a PCM playback
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_PEOpenStream (S_EAS_DATA *pEASData, S_PCM_OPEN_PARAMS *pParams, EAS_PCM_HANDLE *pHandle)
+{
+ EAS_RESULT result;
+ S_PCM_STATE *pState;
+ EAS_I32 filePos;
+
+ /* make sure we support this decoder */
+ if (pParams->decoder >= NUM_DECODER_MODULES)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Decoder selector out of range\n"); */ }
+ return EAS_ERROR_PARAMETER_RANGE;
+ }
+ if (decoders[pParams->decoder] == NULL)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Decoder module not available\n"); */ }
+ return EAS_ERROR_FEATURE_NOT_AVAILABLE;
+ }
+
+ /* find a slot for the new stream */
+ if ((pState = FindSlot(pEASData, pParams->fileHandle, pParams->pCallbackFunc, pParams->cbInstData)) == NULL)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unable to open ADPCM stream, too many streams open\n"); */ }
+ return EAS_ERROR_MAX_PCM_STREAMS;
+ }
+
+ /* get the current file position */
+ if ((result = EAS_HWFilePos(pEASData->hwInstData, pState->fileHandle, &filePos)) != EAS_SUCCESS)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_HWFilePos returned %ld\n",result); */ }
+ pState->fileHandle = NULL;
+ return result;
+ }
+
+ pState->pDecoder = decoders[pParams->decoder];
+ pState->startPos = filePos;
+ pState->bytesLeftLoop = pState->byteCount = pParams->size;
+ pState->loopStart = pParams->loopStart;
+ pState->samplesTilLoop = (EAS_I32) pState->loopStart;
+ pState->loopSamples = pParams->loopSamples;
+ pState->samplesInLoop = 0;
+ pState->blockSize = (EAS_U16) pParams->blockSize;
+ pState->flags = pParams->flags;
+ pState->envData = pParams->envData;
+ pState->volume = pParams->volume;
+ pState->sampleRate = (EAS_U16) pParams->sampleRate;
+
+ /* set the base frequency */
+ pState->basefreq = (SRC_RATE_MULTIPLER * (EAS_U32) pParams->sampleRate) >> 15;
+
+ /* calculate shift for frequencies > 1.0 */
+ pState->rateShift = 0;
+ while (pState->basefreq > 32767)
+ {
+ pState->basefreq = pState->basefreq >> 1;
+ pState->rateShift++;
+ }
+
+ /* initialize */
+ if ((result = InitPCMStream(pEASData, pState)) != EAS_SUCCESS)
+ return result;
+
+ *pHandle = pState;
+
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "EAS_PEOpenStream: StartPos=%d, byteCount = %d, loopSamples=%d\n",
+ pState->startPos, pState->byteCount, pState->loopSamples); */ }
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_PEContinueStream()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Continues a PCM stream
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -e{715} reserved for future use */
+EAS_RESULT EAS_PEContinueStream (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState, EAS_I32 size)
+{
+
+ /* add new samples to count */
+ pState->bytesLeft += size;
+ if (pState->bytesLeft > 0)
+ pState->flags &= ~PCM_FLAGS_EMPTY;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_PEGetFileHandle()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Returns the file handle of a stream
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pEASData) reserved for future use */
+EAS_RESULT EAS_PEGetFileHandle (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState, EAS_FILE_HANDLE *pFileHandle)
+{
+ *pFileHandle = pState->fileHandle;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_PEUpdateParams()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Update the pitch and volume parameters for a PCM stream
+ *
+ * Inputs:
+ * pEASData - pointer to EAS library instance data
+ * handle - pointer to S_PCM_STATE for this stream
+ * gainLeft - linear gain multipler in 1.15 fraction format
+ * gainRight - linear gain multipler in 1.15 fraction format
+ * pitch - pitch shift in cents
+ * initial - initial settings, set current gain
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ * Notes
+ * In mono mode, leftGain controls the output gain and rightGain is ignored
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pEASData) reserved for future use */
+/*lint -esym(715, gainRight) used only in 2-channel version */
+EAS_RESULT EAS_PEUpdateParams (S_EAS_DATA* pEASData, EAS_PCM_HANDLE pState, EAS_I16 pitch, EAS_I16 gainLeft, EAS_I16 gainRight)
+{
+
+ pState->gainLeft = gainLeft;
+
+#if (NUM_OUTPUT_CHANNELS == 2)
+ pState->gainRight = gainRight;
+#endif
+
+ pState->pitch = pitch;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_PELocate()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * This function seeks to the requested place in the file. Accuracy
+ * is dependent on the sample rate and block size.
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * pState - stream handle
+ * time - media time in milliseconds
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_PELocate (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState, EAS_I32 time)
+{
+ if (pState->pDecoder->pfLocate == NULL)
+ return EAS_ERROR_FEATURE_NOT_AVAILABLE;
+
+ return pState->pDecoder->pfLocate(pEASData, pState, time);
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_PEUpdateVolume()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Update the volume parameters for a PCM stream
+ *
+ * Inputs:
+ * pEASData - pointer to EAS library instance data
+ * handle - pointer to S_PCM_STATE for this stream
+ * gainLeft - linear gain multipler in 1.15 fraction format
+ * gainRight - linear gain multipler in 1.15 fraction format
+ * initial - initial settings, set current gain
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ * Notes
+ * In mono mode, leftGain controls the output gain and rightGain is ignored
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pEASData) reserved for future use */
+EAS_RESULT EAS_PEUpdateVolume (S_EAS_DATA* pEASData, EAS_PCM_HANDLE pState, EAS_I16 volume)
+{
+ pState->volume = volume;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_PEUpdatePitch()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Update the pitch parameter for a PCM stream
+ *
+ * Inputs:
+ * pEASData - pointer to EAS library instance data
+ * pState - pointer to S_PCM_STATE for this stream
+ * pitch - new pitch value in pitch cents
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pEASData) reserved for future use */
+EAS_RESULT EAS_PEUpdatePitch (S_EAS_DATA* pEASData, EAS_PCM_HANDLE pState, EAS_I16 pitch)
+{
+ pState->pitch = pitch;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_PEPause()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Mute and stop rendering a PCM stream. Sets the gain target to zero and stops the playback
+ * at the end of the next audio frame.
+ *
+ * Inputs:
+ * pEASData - pointer to EAS library instance data
+ * handle - pointer to S_PCM_STATE for this stream
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pEASData) reserved for future use */
+EAS_RESULT EAS_PEPause (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState)
+{
+ /* set state to stopping */
+ pState->state = EAS_STATE_PAUSING;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_PEResume()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Resume rendering a PCM stream. Sets the gain target back to its
+ * previous setting and restarts playback at the end of the next audio
+ * frame.
+ *
+ * Inputs:
+ * pEASData - pointer to EAS library instance data
+ * handle - pointer to S_PCM_STATE for this stream
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pEASData) reserved for future use */
+EAS_RESULT EAS_PEResume (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState)
+{
+ /* set state to stopping */
+ pState->state = EAS_STATE_PLAY;
+ return EAS_SUCCESS;
+}
+
+EAS_U32 getDecayScale(EAS_U32 index)
+{
+ EAS_U32 utemp;
+
+ //envelope decay segment
+ switch (index)
+ {
+ case 0: //no decay
+ utemp = 512;//32768;
+ break;
+ case 1: //.0156 dB per update
+ utemp = 511;//32709;
+ break;
+ case 2: //.03125
+ utemp = 510;//32649;
+ break;
+ case 3: //.0625
+ utemp = 508;//32532;
+ break;
+ case 4: //.125
+ utemp = 505;//32298;
+ break;
+ case 5: //.25
+ utemp = 497;//31835;
+ break;
+ case 6: //.5
+ utemp = 483;//30929;
+ break;
+ case 7: //1.0
+ utemp = 456;//29193;
+ break;
+ case 8: //2.0
+ utemp = 406;//26008;
+ break;
+ case 9: //4.0
+ utemp = 323;//20642;
+ break;
+ case 10: //8.0
+ utemp = 203;//13004;
+ break;
+ case 11: //16.0
+ utemp = 81;//5160;
+ break;
+ case 12: //32.0
+ utemp = 13;//813;
+ break;
+ case 13: //64.0
+ utemp = 0;//20;
+ break;
+ case 14: //128.0
+ utemp = 0;
+ break;
+ case 15: //256.0
+ default:
+ utemp = 0;
+ break;
+ }
+ //printf("getdecayscale returned %d\n",utemp);
+ return utemp;
+}
+
+EAS_U32 getAttackIncrement(EAS_U32 index)
+{
+ EAS_U32 utemp;
+
+ //envelope decay segment
+ switch (index)
+ {
+ case 0:
+ utemp = 32;
+ break;
+ case 1:
+ utemp = 64;
+ break;
+ case 2:
+ utemp = 128;
+ break;
+ case 3:
+ utemp = 256;
+ break;
+ case 4:
+ utemp = 512;
+ break;
+ case 5:
+ utemp = 1024;
+ break;
+ case 6:
+ utemp = 2048;
+ break;
+ case 7:
+ utemp = 4096;
+ break;
+ case 8:
+ utemp = 8192;
+ break;
+ case 9:
+ utemp = 16384;
+ break;
+ case 10:
+ utemp = 32768;
+ break;
+ case 11:
+ utemp = 65536;
+ break;
+ case 12:
+ utemp = 65536;
+ break;
+ case 13:
+ utemp = 65536;
+ break;
+ case 14:
+ utemp = 65535;
+ break;
+ case 15:
+ default:
+ utemp = 0;
+ break;
+ }
+ //printf("getattackincrement returned %d\n",utemp);
+ return utemp;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_PERelease()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Put the PCM stream envelope into release.
+ *
+ * Inputs:
+ * pEASData - pointer to EAS library instance data
+ * handle - pointer to S_PCM_STATE for this stream
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pEASData) reserved for future use */
+EAS_RESULT EAS_PERelease (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState)
+{
+ EAS_U32 utemp;
+
+ //printf("handling note-off part of envelope\n");
+ /*if the note is not ignore release or sustained*/
+ if (((pState->envData >> 24) & 0x0F)==0)
+ {
+ /* set envelope state to release */
+ pState->envState = PCM_ENV_RELEASE;
+ utemp = ((pState->envData >> 20) & 0x0F);
+ pState->envScale = getDecayScale(utemp); //getReleaseScale(utemp);
+ }
+ else
+ {
+ /*else change envelope state to sustain */
+ pState->envState = PCM_ENV_SUSTAIN;
+ utemp = ((pState->envData >> 28) & 0x0F);
+ pState->envScale = getDecayScale(utemp); //getSustainScale(utemp);
+ }
+ //since we are in release, don't let anything hang around too long
+ //printf("checking env scale, val = %d\n",((S_PCM_STATE*) handle)->envScale);
+ if (pState->envScale > 505)
+ pState->envScale = 505;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * FindSlot()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Locates an empty stream slot and assigns the file handle
+ *
+ * Inputs:
+ * pEASData - pointer to EAS library instance data
+ * fileHandle - file handle
+ * pCallbackFunc - function to be called back upon EAS_STATE_STOPPED
+ *
+ * Outputs:
+ * returns handle to slot or NULL if all slots are used
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static S_PCM_STATE *FindSlot (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_PCM_CALLBACK pCallbackFunc, EAS_VOID_PTR cbInstData)
+{
+ EAS_INT i;
+ S_PCM_STATE *pState;
+
+#ifndef NO_PCM_STEAL
+ S_PCM_STATE *foundState = NULL;
+ EAS_INT count = 0;
+ EAS_U32 startOrder = 0xFFFFFFFF;
+ S_PCM_STATE *stealState = NULL;
+ EAS_U32 youngest = 0;
+
+ /* find an empty slot, count total in use, and find oldest in use (lowest start order) */
+ for (i = 0, pState = pEASData->pPCMStreams; i < MAX_PCM_STREAMS; i++, pState++)
+ {
+ /* if this one is available */
+ if (pState->fileHandle == NULL)
+ {
+ foundState = pState;
+ }
+ /* else this one is in use, so see if it is the oldest, and count total in use */
+ /* also find youngest */
+ else
+ {
+ /*one more voice in use*/
+ count++;
+ /* is this the oldest? (lowest start order) */
+ if ((pState->state != EAS_STATE_STOPPING) && (pState->startOrder < startOrder))
+ {
+ /* remember this one */
+ stealState = pState;
+ /* remember the oldest so far */
+ startOrder = pState->startOrder;
+ }
+ /* is this the youngest? (highest start order) */
+ if (pState->startOrder >= youngest)
+ {
+ youngest = pState->startOrder;
+ }
+ }
+ }
+
+ /* if there are too many voices active, stop the oldest one */
+ if (count > PCM_STREAM_THRESHOLD)
+ {
+ //printf("stealing!!!\n");
+ /* make sure we got one, although we should always have one at this point */
+ if (stealState != NULL)
+ {
+ //flag this as stopping, so it will get shut off
+ stealState->state = EAS_STATE_STOPPING;
+ }
+ }
+
+ /* if there are no available open streams (we won't likely see this, due to stealing) */
+ if (foundState == NULL)
+ return NULL;
+
+ /* save info */
+ foundState->startOrder = youngest + 1;
+ foundState->fileHandle = fileHandle;
+ foundState->pCallback = pCallbackFunc;
+ foundState->cbInstData = cbInstData;
+ return foundState;
+#else
+ /* find an empty slot*/
+ for (i = 0; i < MAX_PCM_STREAMS; i++)
+ {
+ pState = &pEASData->pPCMStreams[i];
+ if (pState->fileHandle != NULL)
+ continue;
+
+ pState->fileHandle = fileHandle;
+ pState->pCallback = pCallbackFunc;
+ pState->cbInstData = cbInstData;
+ return pState;
+ }
+ return NULL;
+#endif
+}
+
+#ifdef _LOOKUP_SAMPLE_RATE
+/*----------------------------------------------------------------------------
+ * CalcBaseFreq()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Calculates the fractional phase increment for the sample rate converter
+ *
+ * Inputs:
+ * sampleRate - sample rate in samples/sec
+ *
+ * Outputs:
+ * Returns fractional sample rate with a 15-bit fraction
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_U32 CalcBaseFreq (EAS_U32 sampleRate)
+{
+ EAS_INT i;
+
+ /* look up the conversion rate */
+ for (i = 0; i < (EAS_INT)(SRC_CONV_RATE_ENTRIES); i ++)
+ {
+ if (srcConvRate[i][0] == sampleRate)
+ return srcConvRate[i][1];
+ }
+
+ /* if not found in table, do it the long way */
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Sample rate %u not in table, calculating by division\n", sampleRate); */ }
+
+ return (SRC_RATE_MULTIPLER * (EAS_U32) sampleRate) >> 15;
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ * InitPCMStream()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Start an ADPCM stream playback. Decodes the header, preps the engine.
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT InitPCMStream (S_EAS_DATA *pEASData, S_PCM_STATE *pState)
+{
+
+ /* initialize the data structure */
+ pState->bytesLeft = pState->byteCount;
+ pState->phase = 0;
+ pState->srcByte = 0;
+ pState->decoderL.acc = 0;
+ pState->decoderL.output = 0;
+ pState->decoderL.x0 = pState->decoderL.x1 = 0;
+ pState->decoderL.step = 0;
+ pState->decoderR.acc = 0;
+ pState->decoderR.output = 0;
+ pState->decoderR.x0 = pState->decoderR.x1 = 0;
+ pState->decoderR.step = 0;
+ pState->hiNibble = EAS_FALSE;
+ pState->pitch = 0;
+ pState->blockCount = 0;
+ pState->gainLeft = PCM_DEFAULT_GAIN_SETTING;
+// pState->currentGainLeft = PCM_DEFAULT_GAIN_SETTING;
+ pState->envValue = 0;
+ pState->envState = PCM_ENV_START;
+
+#if (NUM_OUTPUT_CHANNELS == 2)
+ pState->gainRight = PCM_DEFAULT_GAIN_SETTING;
+// pState->currentGainRight = PCM_DEFAULT_GAIN_SETTING;
+#endif
+ pState->state = EAS_STATE_READY;
+
+ /* initialize the decoder */
+ if (pState->pDecoder->pfInit)
+ return (*pState->pDecoder->pfInit)(pEASData, pState);
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * RenderPCMStream()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Decodes a buffer of ADPCM data.
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT RenderPCMStream (S_EAS_DATA *pEASData, S_PCM_STATE *pState, EAS_I32 numSamples)
+{
+ EAS_RESULT result;
+ EAS_U32 phaseInc;
+ EAS_I32 gainLeft, gainIncLeft;
+ EAS_I32 *pOut;
+ EAS_I32 temp;
+ EAS_U32 utemp;
+
+#if (NUM_OUTPUT_CHANNELS == 2)
+ EAS_I32 gainRight, gainIncRight;
+#endif
+
+#if 0
+ printf("env data: AR = %d, DR = %d, SL = %d, SR = %d, RR = %d\n",
+ ((pState->envData >> 12) & 0x0F),
+ ((pState->envData >> 16) & 0x0F),
+ ((pState->envData >> 8) & 0x0F),
+ ((pState->envData >> 28) & 0x0F),
+ ((pState->envData >> 20) & 0x0F));
+#endif
+
+ if (pState->envState == PCM_ENV_START)
+ {
+ //printf("env start\n");
+ utemp = ((pState->envData >> 12) & 0x0F);
+ //if fastest rate, attack is already completed
+ //do the same for slowest rate, since that allows zero to be passed for default envelope
+ if (utemp == 0x0F || utemp == 0x00)
+ {
+ //start envelope at full
+ pState->envValue = (32768<<7);
+ //jump right into decay
+ utemp = ((pState->envData >> 16) & 0x0F);
+ pState->envScale = getDecayScale(utemp);
+ pState->envState = PCM_ENV_DECAY;
+ pState->currentGainLeft = (EAS_I16) FMUL_15x15(pState->gainLeft, pState->volume);
+ pState->currentGainRight = (EAS_I16) FMUL_15x15(pState->gainRight, pState->volume);
+ }
+ //else attack has a ramp
+ else
+ {
+ //start the envelope very low
+ pState->envValue = (2<<7);
+ pState->currentGainLeft = 0;
+ pState->currentGainRight = 0;
+ //get envelope attack scaling value
+ pState->envScale = getAttackIncrement(utemp);
+ //go to attack state
+ pState->envState = PCM_ENV_ATTACK;
+ }
+ }
+ if (pState->envState == PCM_ENV_ATTACK)
+ {
+ //printf("env attack, env value = %d, env scale = %d\n",pState->envValue>>7,pState->envScale);
+ //update envelope value
+ pState->envValue = pState->envValue + (pState->envScale << 7);
+ //check envelope level and update state if needed
+ if (pState->envValue >= (32768<<7))
+ {
+ pState->envValue = (32768<<7);
+ utemp = ((pState->envData >> 16) & 0x0F);
+ pState->envScale = getDecayScale(utemp);
+ pState->envState = PCM_ENV_DECAY;
+ }
+ }
+ else if (pState->envState == PCM_ENV_DECAY)
+ {
+ //printf("env decay, env value = %d, env scale = %d\n",pState->envValue>>7,pState->envScale);
+ //update envelope value
+ pState->envValue = (pState->envValue * pState->envScale)>>9;
+ //check envelope level against sustain level and update state if needed
+ utemp = ((pState->envData >> 8) & 0x0F);
+ if (utemp == (EAS_U32)0x0F)
+ utemp = (2<<7);
+ else
+ {
+ utemp = ((32769<<7) >> (utemp>>1));
+ }
+ if (pState->envValue <= utemp)
+ {
+ utemp = ((pState->envData >> 28) & 0x0F);
+ pState->envScale = getDecayScale(utemp); //getSustainScale(utemp);
+ pState->envState = PCM_ENV_SUSTAIN;
+ }
+ }
+ else if (pState->envState == PCM_ENV_SUSTAIN)
+ {
+ //printf("env sustain, env value = %d, env scale = %d\n",pState->envValue>>7,pState->envScale);
+ //update envelope value
+ pState->envValue = (pState->envValue * pState->envScale)>>9;
+ //check envelope level against bottom level and update state if needed
+ if (pState->envValue <= (2<<7))
+ {
+ //no more decay
+ pState->envScale = 512;
+ pState->envState = PCM_ENV_END;
+ }
+ }
+ else if (pState->envState == PCM_ENV_RELEASE)
+ {
+ //printf("env release, env value = %d, env scale = %d\n",pState->envValue>>7,pState->envScale);
+ //update envelope value
+ pState->envValue = (pState->envValue * pState->envScale)>>9;
+ //check envelope level against bottom level and update state if needed
+ if (pState->envValue <= (2<<7))
+ {
+ //no more decay
+ pState->envScale = 512;
+ pState->envState = PCM_ENV_END;
+ }
+ }
+ else if (pState->envState == PCM_ENV_END)
+ {
+ //printf("env end\n");
+ /* set state to stopping, already ramped down */
+ pState->state = EAS_STATE_STOPPING;
+ }
+
+ //pState->gainLeft = (EAS_U16)((pState->gainLeft * (pState->envValue>>7))>>15);
+ //pState->gainRight = (EAS_U16)((pState->gainRight * (pState->envValue>>7))>>15);
+
+ /* gain to 32-bits to increase resolution on anti-zipper filter */
+ /*lint -e{703} use shift for performance */
+ gainLeft = (EAS_I32) pState->currentGainLeft << SYNTH_UPDATE_PERIOD_IN_BITS;
+#if (NUM_OUTPUT_CHANNELS == 2)
+ /*lint -e{703} use shift for performance */
+ gainRight = (EAS_I32) pState->currentGainRight << SYNTH_UPDATE_PERIOD_IN_BITS;
+#endif
+
+ /* calculate a new gain increment, gain target is zero if pausing */
+ if ((pState->state == EAS_STATE_PAUSING) || (pState->state == EAS_STATE_PAUSED))
+ {
+ gainIncLeft = -pState->currentGainLeft;
+#if (NUM_OUTPUT_CHANNELS == 2)
+ gainIncRight= -pState->currentGainRight;
+#endif
+ }
+ else
+ {
+ EAS_I32 gain = FMUL_15x15(pState->envValue >> 7, pState->volume);
+ gainIncLeft = FMUL_15x15(pState->gainLeft, gain) - pState->currentGainLeft;
+#if (NUM_OUTPUT_CHANNELS == 2)
+ gainIncRight = FMUL_15x15(pState->gainRight, gain) - pState->currentGainRight;
+#endif
+ }
+
+ /* calculate phase increment */
+ phaseInc = pState->basefreq;
+
+ /* convert pitch cents to linear multiplier */
+ if (pState->pitch)
+ {
+ temp = EAS_Calculate2toX(pState->pitch);
+ phaseInc = FMUL_15x15(phaseInc, temp);
+ }
+ phaseInc = phaseInc << pState->rateShift;
+
+ /* pointer to mix buffer */
+ pOut = pEASData->pMixBuffer;
+
+ /* render a buffer of samples */
+ while (numSamples--)
+ {
+
+ /* interpolate an output sample */
+ pState->decoderL.output = pState->decoderL.x0 + FMUL_15x15((pState->decoderL.x1 - pState->decoderL.x0), pState->phase & PHASE_FRAC_MASK);
+
+ /* stereo output */
+#if (NUM_OUTPUT_CHANNELS == 2)
+
+ /* stereo stream? */
+ if (pState->flags & PCM_FLAGS_STEREO)
+ pState->decoderR.output = pState->decoderR.x0 + FMUL_15x15((pState->decoderR.x1 - pState->decoderR.x0), pState->phase & PHASE_FRAC_MASK);
+
+ /* gain scale and mix */
+ /*lint -e{704} use shift instead of division */
+ *pOut++ += (pState->decoderL.output * (gainLeft >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS;
+ gainLeft += gainIncLeft;
+
+ /*lint -e{704} use shift instead of division */
+ if (pState->flags & PCM_FLAGS_STEREO)
+ *pOut++ += (pState->decoderR.output * (gainRight >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS;
+ else
+ *pOut++ += (pState->decoderL.output * (gainRight >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS;
+
+ gainRight += gainIncRight;
+
+ /* mono output */
+#else
+ /* if stereo stream, decode right channel and mix to mono */
+ if (pState->flags & PCM_FLAGS_STEREO)
+ {
+ pState->decoderR.output= pState->decoderR.x0 + FMUL_15x15((pState->decoderR.x1 - pState->decoderR.x0), pState->phase & PHASE_FRAC_MASK);
+
+ /* for mono, sum stereo ADPCM to mono */
+ /*lint -e{704} use shift instead of division */
+ *pOut++ += ((pState->decoderL.output + pState->decoderR.output) * (gainLeft >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS;
+ }
+ else
+ /*lint -e{704} use shift instead of division */
+ *pOut++ += (pState->decoderL.output * (gainLeft >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS;
+
+ gainLeft += gainIncLeft;
+#endif
+
+ /* advance phase accumulator */
+ pState->phase += phaseInc;
+
+ /* if integer part of phase accumulator is non-zero, advance to next sample */
+ while (pState->phase & ~PHASE_FRAC_MASK)
+ {
+ pState->decoderL.x0 = pState->decoderL.x1;
+ pState->decoderR.x0 = pState->decoderR.x1;
+
+ /* give the source a chance to continue the stream */
+ if (!pState->bytesLeft && pState->pCallback && ((pState->flags & PCM_FLAGS_EMPTY) == 0))
+ {
+ pState->flags |= PCM_FLAGS_EMPTY;
+ (*pState->pCallback)(pEASData, pState->cbInstData, pState, EAS_STATE_EMPTY);
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "RenderPCMStream: After empty callback, bytesLeft = %d\n", pState->bytesLeft); */ }
+ }
+
+ /* decode the next sample */
+ if ((result = (*pState->pDecoder->pfDecodeSample)(pEASData, pState)) != EAS_SUCCESS)
+ return result;
+
+ /* adjust phase by one sample */
+ pState->phase -= (1L << NUM_PHASE_FRAC_BITS);
+ }
+
+ }
+
+ /* save new gain */
+ /*lint -e{704} use shift instead of division */
+ pState->currentGainLeft = (EAS_I16) (gainLeft >> SYNTH_UPDATE_PERIOD_IN_BITS);
+
+#if (NUM_OUTPUT_CHANNELS == 2)
+ /*lint -e{704} use shift instead of division */
+ pState->currentGainRight = (EAS_I16) (gainRight >> SYNTH_UPDATE_PERIOD_IN_BITS);
+#endif
+
+ /* if pausing, set new state and notify */
+ if (pState->state == EAS_STATE_PAUSING)
+ {
+ pState->state = EAS_STATE_PAUSED;
+ if (pState->pCallback)
+ (*pState->pCallback)(pEASData, pState->cbInstData, pState, pState->state);
+ }
+
+ /* if out of data, set stopped state and notify */
+ if (pState->bytesLeft == 0 || pState->state == EAS_STATE_STOPPING)
+ {
+ pState->state = EAS_STATE_STOPPED;
+
+ /* do callback unless the file has already been closed */
+ if (pState->pCallback && pState->fileHandle)
+ (*pState->pCallback)(pEASData, pState->cbInstData, pState, pState->state);
+ }
+
+ if (pState->state == EAS_STATE_READY)
+ pState->state = EAS_STATE_PLAY;
+
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * LinearPCMDecode()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Decodes a PCM sample
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT LinearPCMDecode (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState)
+{
+ EAS_RESULT result;
+ EAS_HW_DATA_HANDLE hwInstData;
+
+ hwInstData = ((S_EAS_DATA*) pEASData)->hwInstData;
+
+ /* if out of data, check for loop */
+ if ((pState->bytesLeft == 0) && (pState->loopSamples != 0))
+ {
+ if ((result = EAS_HWFileSeek(pEASData->hwInstData, pState->fileHandle, (EAS_I32) (pState->startPos + pState->loopLocation))) != EAS_SUCCESS)
+ return result;
+ pState->bytesLeft = pState->byteCount = (EAS_I32) pState->bytesLeftLoop;
+ pState->flags &= ~PCM_FLAGS_EMPTY;
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "LinearPCMDecode: Rewind file to %d, bytesLeft = %d\n", pState->startPos, pState->bytesLeft); */ }
+ }
+
+ if (pState->bytesLeft)
+ {
+
+ /* check format byte for 8-bit samples */
+ if (pState->flags & PCM_FLAGS_8_BIT)
+ {
+ /* fetch left or mono sample */
+ if ((result = EAS_HWGetByte(hwInstData, pState->fileHandle, &pState->srcByte)) != EAS_SUCCESS)
+ return result;
+
+ /* if unsigned */
+ if (pState->flags & PCM_FLAGS_UNSIGNED)
+ {
+ /*lint -e{734} converting unsigned 8-bit to signed 16-bit */
+ pState->decoderL.x1 = (EAS_PCM)(((EAS_PCM) pState->srcByte << 8) ^ 0x8000);
+ }
+ else
+ {
+ /*lint -e{734} converting signed 8-bit to signed 16-bit */
+ pState->decoderL.x1 = (EAS_PCM)((EAS_PCM) pState->srcByte << 8);
+ }
+ pState->bytesLeft--;
+
+ /* fetch right sample */
+ if(pState->flags & PCM_FLAGS_STEREO)
+ {
+ if ((result = EAS_HWGetByte(hwInstData, pState->fileHandle, &pState->srcByte)) != EAS_SUCCESS)
+ return result;
+
+ /* if unsigned */
+ if (pState->flags & PCM_FLAGS_UNSIGNED)
+ {
+ /*lint -e{734} converting unsigned 8-bit to signed 16-bit */
+ pState->decoderR.x1 = (EAS_PCM)(((EAS_PCM) pState->srcByte << 8) ^ 0x8000);
+ }
+ else
+ {
+ /*lint -e{734} converting signed 8-bit to signed 16-bit */
+ pState->decoderR.x1 = (EAS_PCM)((EAS_PCM) pState->srcByte << 8);
+ }
+ pState->bytesLeft--;
+ }
+ }
+
+ /* must be 16-bit samples */
+ else
+ {
+ //unsigned 16 bit currently not supported
+ if (pState->flags & PCM_FLAGS_UNSIGNED)
+ {
+ return EAS_ERROR_INVALID_PCM_TYPE;
+ }
+
+ /* fetch left or mono sample */
+ if ((result = EAS_HWGetWord(hwInstData, pState->fileHandle, &pState->decoderL.x1, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+ pState->bytesLeft -= 2;
+
+ /* fetch right sample */
+ if(pState->flags & PCM_FLAGS_STEREO)
+ {
+ if ((result = EAS_HWGetWord(hwInstData, pState->fileHandle, &pState->decoderR.x1, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+ pState->bytesLeft -= 2;
+ }
+ }
+ }
+
+ /* no more data, force zero samples */
+ else
+ pState->decoderL.x1 = pState->decoderR.x1 = 0;
+
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * LinearPCMLocate()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Locate in a linear PCM stream
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT LinearPCMLocate (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState, EAS_I32 time)
+{
+ EAS_RESULT result;
+ EAS_I32 temp;
+ EAS_I32 secs, msecs;
+ EAS_INT shift;
+
+ /* calculate size of sample frame */
+ if (pState->flags & PCM_FLAGS_8_BIT)
+ shift = 0;
+ else
+ shift = 1;
+ if (pState->flags & PCM_FLAGS_STEREO)
+ shift++;
+
+ /* break down into secs and msecs */
+ secs = time / 1000;
+ msecs = time - (secs * 1000);
+
+ /* calculate sample number fraction from msecs */
+ temp = (msecs * pState->sampleRate);
+ temp = (temp >> 10) + ((temp * 49) >> 21);
+
+ /* add integer sample count */
+ temp += secs * pState->sampleRate;
+
+ /* calculate the position based on sample frame size */
+ /*lint -e{703} use shift for performance */
+ temp <<= shift;
+
+ /* past end of sample? */
+ if (temp > (EAS_I32) pState->loopStart)
+ {
+ /* if not looped, flag error */
+ if (pState->loopSamples == 0)
+ {
+ pState->bytesLeft = 0;
+ pState->flags |= PCM_FLAGS_EMPTY;
+ return EAS_ERROR_LOCATE_BEYOND_END;
+ }
+
+ /* looped sample - calculate position in loop */
+ while (temp > (EAS_I32) pState->loopStart)
+ temp -= (EAS_I32) pState->loopStart;
+ }
+
+ /* seek to new position */
+ if ((result = EAS_PESeek(pEASData, pState, &temp)) != EAS_SUCCESS)
+ return result;
+
+ /* reset state */
+ if ((pState->state != EAS_STATE_PAUSING) && (pState->state != EAS_STATE_PAUSED))
+ pState->state = EAS_STATE_READY;
+
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_PESeek
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Locate to a particular byte in a PCM stream
+ *----------------------------------------------------------------------------
+ * This bit is tricky because the chunks may not be contiguous,
+ * so we have to rely on the parser to position in the file. We
+ * do this by seeking to the end of each chunk and simulating an
+ * empty buffer condition until we get to where we want to go.
+ *
+ * A better solution would be a parser API for re-positioning,
+ * but there isn't time at the moment to re-factor all the
+ * parsers to support a new API.
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_PESeek (S_EAS_DATA *pEASData, S_PCM_STATE *pState, EAS_I32 *pLocation)
+{
+ EAS_RESULT result;
+
+ /* seek to start of audio */
+ if ((result = EAS_HWFileSeek(pEASData->hwInstData, pState->fileHandle, pState->startPos)) != EAS_SUCCESS)
+ {
+ pState->state = EAS_STATE_ERROR;
+ return result;
+ }
+ pState->bytesLeft = pState->bytesLeftLoop;
+
+ /* skip through chunks until we find the right chunk */
+ while (*pLocation > (EAS_I32) pState->bytesLeft)
+ {
+ /* seek to end of audio chunk */
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "EAS_PESeek: Seek to offset = %d\n", pState->bytesLeft); */ }
+ if ((result = EAS_HWFileSeekOfs(pEASData->hwInstData, pState->fileHandle, pState->bytesLeft)) != EAS_SUCCESS)
+ {
+ pState->state = EAS_STATE_ERROR;
+ return result;
+ }
+ *pLocation -= pState->bytesLeft;
+ pState->bytesLeft = 0;
+ pState->flags |= PCM_FLAGS_EMPTY;
+
+ /* retrieve more data */
+ if (pState->pCallback)
+ (*pState->pCallback)(pEASData, pState->cbInstData, pState, EAS_STATE_EMPTY);
+
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "EAS_PESeek: bytesLeft=%d, byte location = %d\n", pState->bytesLeft, *pLocation); */ }
+
+ /* no more samples */
+ if (pState->bytesLeft == 0)
+ return EAS_ERROR_LOCATE_BEYOND_END;
+ }
+
+ /* seek to new offset in current chunk */
+ if (*pLocation > 0)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "EAS_PESeek: Seek to offset = %d\n", *pLocation); */ }
+ if ((result = EAS_HWFileSeekOfs(pEASData->hwInstData, pState->fileHandle, *pLocation)) != EAS_SUCCESS)
+ {
+ pState->state = EAS_STATE_ERROR;
+ return result;
+ }
+
+ /* if not streamed, calculate number of bytes left */
+ if (pState->flags & PCM_FLAGS_STREAMING)
+ pState->bytesLeft = 0x7fffffff;
+ else
+ pState->bytesLeft -= *pLocation;
+ }
+ return EAS_SUCCESS;
+}
+
diff --git a/arm-wt-22k/lib_src/eas_pcm.h b/arm-wt-22k/lib_src/eas_pcm.h
new file mode 100644
index 0000000..c161757
--- /dev/null
+++ b/arm-wt-22k/lib_src/eas_pcm.h
@@ -0,0 +1,359 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_pcm.h
+ *
+ * Contents and purpose:
+ * External function prototypes for eas_pcm.c module
+ *
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 847 $
+ * $Date: 2007-08-27 21:30:08 -0700 (Mon, 27 Aug 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+#ifndef _EAS_PCM_H
+#define _EAS_PCM_H
+
+/* default gain setting - roughly unity gain */
+#define PCM_DEFAULT_GAIN_SETTING 0x6000
+
+typedef struct s_pcm_state_tag *EAS_PCM_HANDLE;
+typedef void (*EAS_PCM_CALLBACK) (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR cbInstData, EAS_PCM_HANDLE pcmHandle, EAS_STATE state);
+
+/* parameters for EAS_PEOpenStream */
+typedef struct s_pcm_open_params_tag
+{
+ EAS_FILE_HANDLE fileHandle;
+ EAS_I32 decoder;
+ EAS_U32 sampleRate;
+ EAS_I32 size;
+ EAS_U32 loopStart;
+ EAS_U32 loopSamples;
+ EAS_I32 blockSize;
+ EAS_U32 flags;
+ EAS_U32 envData;
+ EAS_I16 volume;
+ EAS_PCM_CALLBACK pCallbackFunc;
+ EAS_VOID_PTR cbInstData;
+ } S_PCM_OPEN_PARAMS;
+
+/*----------------------------------------------------------------------------
+ * EAS_PEInit()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Initializes the PCM engine
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_PEInit (EAS_DATA_HANDLE pEASData);
+
+/*----------------------------------------------------------------------------
+ * EAS_PEShutdown()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Shuts down the PCM engine
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_PEShutdown (EAS_DATA_HANDLE pEASData);
+
+/*----------------------------------------------------------------------------
+ * EAS_PEOpenStream()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Starts up a PCM playback
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_PEOpenStream (EAS_DATA_HANDLE pEASData, S_PCM_OPEN_PARAMS *pParams, EAS_PCM_HANDLE *pHandle);
+
+/*----------------------------------------------------------------------------
+ * EAS_PEContinueStream()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Continues a PCM stream
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_PEContinueStream (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE handle, EAS_I32 size);
+
+/*----------------------------------------------------------------------------
+ * EAS_PEGetFileHandle()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Returns the file handle of a stream
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_PEGetFileHandle (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE handle, EAS_FILE_HANDLE *pFileHandle);
+
+/*----------------------------------------------------------------------------
+ * EAS_PERender()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Render a buffer of PCM audio
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_PERender (EAS_DATA_HANDLE pEASData, EAS_I32 numSamples);
+
+/*----------------------------------------------------------------------------
+ * EAS_PEUpdateParams()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Update the pitch and volume parameters using MIDI controls
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_PEUpdateParams (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE pState, EAS_I16 pitch, EAS_I16 gainLeft, EAS_I16 gainRight);
+
+/*----------------------------------------------------------------------------
+ * EAS_PELocate()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * This function seeks to the requested place in the file. Accuracy
+ * is dependent on the sample rate and block size.
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * pState - stream handle
+ * time - media time in milliseconds
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_PELocate (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE pState, EAS_I32 time);
+
+/*----------------------------------------------------------------------------
+ * EAS_PEUpdateVolume()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Update the volume parameters for a PCM stream
+ *
+ * Inputs:
+ * pEASData - pointer to EAS library instance data
+ * handle - pointer to S_PCM_STATE for this stream
+ * gainLeft - linear gain multipler in 1.15 fraction format
+ * gainRight - linear gain multipler in 1.15 fraction format
+ * initial - initial settings, set current gain
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ * Notes
+ * In mono mode, leftGain controls the output gain and rightGain is ignored
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pEASData) reserved for future use */
+EAS_RESULT EAS_PEUpdateVolume (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE pState, EAS_I16 volume);
+
+/*----------------------------------------------------------------------------
+ * EAS_PEUpdatePitch()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Update the pitch parameter for a PCM stream
+ *
+ * Inputs:
+ * pEASData - pointer to EAS library instance data
+ * pState - pointer to S_PCM_STATE for this stream
+ * pitch - new pitch value in pitch cents
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pEASData) reserved for future use */
+EAS_RESULT EAS_PEUpdatePitch (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE pState, EAS_I16 pitch);
+
+/*----------------------------------------------------------------------------
+ * EAS_PEState()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Returns the current state of the stream
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ * pState - pointer to variable to store state
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ * Notes:
+ * This interface is also exposed in the internal library for use by the other modules.
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_PEState (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE handle, EAS_STATE *pState);
+
+/*----------------------------------------------------------------------------
+ * EAS_PEClose()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Close the file and clean up
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_PEClose (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE handle);
+
+/*----------------------------------------------------------------------------
+ * EAS_PEReset()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Reset the sequencer. Used for locating backwards in the file.
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_PEReset (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE handle);
+
+/*----------------------------------------------------------------------------
+ * EAS_PEPause()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Mute and pause rendering a PCM stream. Sets the gain target to zero and stops the playback
+ * at the end of the next audio frame.
+ *
+ * Inputs:
+ * pEASData - pointer to EAS library instance data
+ * handle - pointer to S_PCM_STATE for this stream
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_PEPause (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE handle);
+
+/*----------------------------------------------------------------------------
+ * EAS_PEResume()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Resume rendering a PCM stream. Sets the gain target back to its
+ * previous setting and restarts playback at the end of the next audio
+ * frame.
+ *
+ * Inputs:
+ * pEASData - pointer to EAS library instance data
+ * handle - pointer to S_PCM_STATE for this stream
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_PEResume (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE handle);
+
+/*----------------------------------------------------------------------------
+ * EAS_PERelease()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Put the PCM stream envelope into release.
+ *
+ * Inputs:
+ * pEASData - pointer to EAS library instance data
+ * handle - pointer to S_PCM_STATE for this stream
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_PERelease (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE handle);
+
+#endif /* end _EAS_PCM_H */
+
diff --git a/arm-wt-22k/lib_src/eas_pcmdata.c b/arm-wt-22k/lib_src/eas_pcmdata.c
new file mode 100644
index 0000000..5649f07
--- /dev/null
+++ b/arm-wt-22k/lib_src/eas_pcmdata.c
@@ -0,0 +1,35 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_pcmdata.c
+ *
+ * Contents and purpose:
+ * Contains the static data for the PCM engine.
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 547 $
+ * $Date: 2007-01-31 16:30:17 -0800 (Wed, 31 Jan 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+#include "eas_data.h"
+
+/* static data allocation */
+S_PCM_STATE eas_PCMData[MAX_PCM_STREAMS];
+
+
diff --git a/arm-wt-22k/lib_src/eas_pcmdata.h b/arm-wt-22k/lib_src/eas_pcmdata.h
new file mode 100644
index 0000000..be2f8e5
--- /dev/null
+++ b/arm-wt-22k/lib_src/eas_pcmdata.h
@@ -0,0 +1,157 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_pcmdata.h
+ *
+ * Contents and purpose:
+ * Data declarations for the PCM engine
+ *
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 847 $
+ * $Date: 2007-08-27 21:30:08 -0700 (Mon, 27 Aug 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+#ifndef _EAS_PCMDATA_H
+#define _EAS_PCMDATA_H
+
+/* sets the maximum number of simultaneous PCM streams */
+#ifndef MAX_PCM_STREAMS
+#define MAX_PCM_STREAMS 16
+#define PCM_STREAM_THRESHOLD (MAX_PCM_STREAMS - 4)
+#endif
+
+/* coefficents for high-pass filter in ADPCM */
+#define INTEGRATOR_COEFFICIENT 100 /* coefficient for leaky integrator */
+
+/* additional flags in S_PCM_STATE.flags used internal to module */
+#define PCM_FLAGS_EMPTY 0x01000000 /* unsigned format */
+
+/*----------------------------------------------------------------------------
+ * S_PCM_STATE
+ *
+ * Retains state information for PCM streams.
+ *----------------------------------------------------------------------------
+*/
+typedef struct s_decoder_state_tag
+{
+ EAS_I32 output; /* last output for DC offset filter */
+ EAS_I32 acc; /* accumulator for DC offset filter */
+ EAS_I32 step; /* current ADPCM step size */
+ EAS_PCM x1; /* current generated sample */
+ EAS_PCM x0; /* previous generated sample */
+} S_DECODER_STATE;
+
+typedef enum
+{
+ PCM_ENV_START = 0,
+ PCM_ENV_ATTACK,
+ PCM_ENV_DECAY,
+ PCM_ENV_SUSTAIN,
+ PCM_ENV_RELEASE,
+ PCM_ENV_END
+} E_PCM_ENV_STATE;
+
+typedef struct s_pcm_state_tag
+{
+#ifdef _CHECKED_BUILD
+ EAS_U32 handleCheck; /* signature check for checked build */
+#endif
+ EAS_FILE_HANDLE fileHandle; /* pointer to input file */
+ EAS_PCM_CALLBACK pCallback; /* pointer to callback function */
+ EAS_VOID_PTR cbInstData; /* instance data for callback function */
+ struct s_decoder_interface_tag EAS_CONST * pDecoder; /* pointer to decoder interface */
+ EAS_STATE state; /* stream state */
+ EAS_I32 time; /* media time */
+ EAS_I32 startPos; /* start of PCM stream */
+ EAS_I32 loopLocation; /* file location where loop starts */
+ EAS_I32 byteCount; /* size of file */
+ EAS_U32 loopStart; /* loop start, offset in samples from startPos */
+ /* NOTE: For CMF, we use this to store total sample size */
+ EAS_U32 loopSamples; /* total loop length, in samples, 0 means no loop */
+ /* NOTE: For CMF, non-zero means looped */
+ EAS_U32 samplesInLoop; /* samples left in the loop to play back */
+ EAS_I32 samplesTilLoop; /* samples left to play until top of loop */
+ EAS_I32 bytesLeft; /* count of bytes left in stream */
+ EAS_I32 bytesLeftLoop; /* count of bytes left in stream, value at start of loop */
+ EAS_U32 phase; /* current phase for interpolator */
+ EAS_U32 basefreq; /* frequency multiplier */
+ EAS_U32 flags; /* stream flags */
+ EAS_U32 envData; /* envelope data (and LFO data) */
+ EAS_U32 envValue; /* current envelope value */
+ EAS_U32 envScale; /* current envelope scale */
+ EAS_U32 startOrder; /* start order index, first is 0, next is 1, etc. */
+ S_DECODER_STATE decoderL; /* left (mono) ADPCM state */
+ S_DECODER_STATE decoderR; /* right ADPCM state */
+ S_DECODER_STATE decoderLLoop; /* left (mono) ADPCM state, value at start of loop */
+ S_DECODER_STATE decoderRLoop; /* right ADPCM state, value at start of loop */
+ E_PCM_ENV_STATE envState; /* current envelope state */
+ EAS_I16 volume; /* volume for stream */
+ EAS_I16 pitch; /* relative pitch in cents - zero is unity playback */
+ EAS_I16 gainLeft; /* requested gain */
+ EAS_I16 gainRight; /* requested gain */
+ EAS_I16 currentGainLeft; /* current gain for anti-zipper filter */
+ EAS_I16 currentGainRight; /* current gain for anti-zipper filter */
+ EAS_U16 blockSize; /* block size for ADPCM decoder */
+ EAS_U16 blockCount; /* block counter for ADPCM decoder */
+ EAS_U16 sampleRate; /* input sample rate */
+ EAS_U8 srcByte; /* source byte */
+ EAS_U8 msBitCount; /* count keeps track of MS bits */
+ EAS_U8 msBitMask; /* mask keeps track of MS bits */
+ EAS_U8 msBitValue; /* value keeps track of MS bits */
+ EAS_U8 msBitCountLoop; /* count keeps track of MS bits, value at loop start */
+ EAS_U8 msBitMaskLoop; /* mask keeps track of MS bits, value at loop start */
+ EAS_U8 msBitValueLoop; /* value keeps track of MS bits, value at loop start */
+ EAS_BOOL8 hiNibble; /* indicates high/low nibble is next */
+ EAS_BOOL8 hiNibbleLoop; /* indicates high/low nibble is next, value loop start */
+ EAS_U8 rateShift; /* for playback rate greater than 1.0 */
+} S_PCM_STATE;
+
+/*----------------------------------------------------------------------------
+ * S_DECODER_INTERFACE
+ *
+ * Generic interface for audio decoders
+ *----------------------------------------------------------------------------
+*/
+typedef struct s_decoder_interface_tag
+{
+ EAS_RESULT (* EAS_CONST pfInit)(EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState);
+ EAS_RESULT (* EAS_CONST pfDecodeSample)(EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState);
+ EAS_RESULT (* EAS_CONST pfLocate)(EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState, EAS_I32 time);
+} S_DECODER_INTERFACE;
+
+
+/* header chunk for SMAF ADPCM */
+#define TAG_YAMAHA_ADPCM 0x4d776100
+#define TAG_MASK 0xffffff00
+#define TAG_RIFF_FILE 0x52494646
+#define TAG_WAVE_CHUNK 0x57415645
+#define TAG_FMT_CHUNK 0x666d7420
+
+/*----------------------------------------------------------------------------
+ * EAS_PESeek
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Locate to a particular byte in a PCM stream
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_PESeek (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState, EAS_I32 *pLocation);
+
+#endif /* _EAS_PCMDATA_H */
+
diff --git a/arm-wt-22k/lib_src/eas_public.c b/arm-wt-22k/lib_src/eas_public.c
new file mode 100644
index 0000000..d67ef7e
--- /dev/null
+++ b/arm-wt-22k/lib_src/eas_public.c
@@ -0,0 +1,2601 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_public.c
+ *
+ * Contents and purpose:
+ * Contains EAS library public interface
+ *
+ * Copyright Sonic Network Inc. 2004
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 842 $
+ * $Date: 2007-08-23 14:32:31 -0700 (Thu, 23 Aug 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+#include "eas_synthcfg.h"
+#include "eas.h"
+#include "eas_config.h"
+#include "eas_host.h"
+#include "eas_report.h"
+#include "eas_data.h"
+#include "eas_parser.h"
+#include "eas_pcm.h"
+#include "eas_midi.h"
+#include "eas_mixer.h"
+#include "eas_build.h"
+#include "eas_vm_protos.h"
+#include "eas_math.h"
+
+#ifdef JET_INTERFACE
+#include "jet_data.h"
+#endif
+
+#ifdef DLS_SYNTHESIZER
+#include "eas_mdls.h"
+#endif
+
+/* number of events to parse before calling EAS_HWYield function */
+#define YIELD_EVENT_COUNT 10
+
+/*----------------------------------------------------------------------------
+ * easLibConfig
+ *
+ * This structure is available through the EAS public interface to allow
+ * the user to check the configuration of the library.
+ *----------------------------------------------------------------------------
+*/
+static const S_EAS_LIB_CONFIG easLibConfig =
+{
+ LIB_VERSION,
+#ifdef _CHECKED_BUILD
+ EAS_TRUE,
+#else
+ EAS_FALSE,
+#endif
+ MAX_SYNTH_VOICES,
+ NUM_OUTPUT_CHANNELS,
+ _OUTPUT_SAMPLE_RATE,
+ BUFFER_SIZE_IN_MONO_SAMPLES,
+#ifdef _FILTER_ENABLED
+ EAS_TRUE,
+#else
+ EAS_FALSE,
+#endif
+ _BUILD_TIME_,
+ _BUILD_VERSION_
+};
+
+/* local prototypes */
+static EAS_RESULT EAS_ParseEvents (S_EAS_DATA *pEASData, S_EAS_STREAM *pStream, EAS_U32 endTime, EAS_INT parseMode);
+
+/*----------------------------------------------------------------------------
+ * EAS_SetStreamParameter
+ *----------------------------------------------------------------------------
+ * Sets the specified parameter in the stream. Allows access to
+ * customizable settings within the individual file parsers.
+ *----------------------------------------------------------------------------
+ * pEASData - pointer to EAS persistent data object
+ * pStream - stream handle
+ * param - enumerated parameter (see eas_parser.h)
+ * value - new value
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_SetStreamParameter (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_I32 param, EAS_I32 value)
+{
+ S_FILE_PARSER_INTERFACE *pParserModule;
+
+ pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule;
+ if (pParserModule->pfSetData)
+ return (*pParserModule->pfSetData)(pEASData, pStream->handle, param, value);
+ return EAS_ERROR_FEATURE_NOT_AVAILABLE;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_GetStreamParameter
+ *----------------------------------------------------------------------------
+ * Sets the specified parameter in the stream. Allows access to
+ * customizable settings within the individual file parsers.
+ *----------------------------------------------------------------------------
+ * pEASData - pointer to EAS persistent data object
+ * pStream - stream handle
+ * param - enumerated parameter (see eas_parser.h)
+ * pValue - pointer to variable to receive current setting
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_GetStreamParameter (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_I32 param, EAS_I32 *pValue)
+{
+ S_FILE_PARSER_INTERFACE *pParserModule;
+
+ pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule;
+ if (pParserModule->pfGetData)
+ return (*pParserModule->pfGetData)(pEASData, pStream->handle, param, pValue);
+ return EAS_ERROR_FEATURE_NOT_AVAILABLE;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_StreamReady()
+ *----------------------------------------------------------------------------
+ * This routine sets common parameters like transpose, volume, etc.
+ * First, it attempts to use the parser EAS_SetStreamParameter interface. If that
+ * fails, it attempts to get the synth handle from the parser and
+ * set the parameter directly on the synth. This eliminates duplicate
+ * code in the parser.
+ *----------------------------------------------------------------------------
+*/
+EAS_BOOL EAS_StreamReady (S_EAS_DATA *pEASData, EAS_HANDLE pStream)
+{
+ S_FILE_PARSER_INTERFACE *pParserModule;
+ EAS_STATE state;
+
+ pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule;
+ if (pParserModule->pfState(pEASData, pStream->handle, &state) != EAS_SUCCESS)
+ return EAS_FALSE;
+ return (state < EAS_STATE_OPEN);
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_IntSetStrmParam()
+ *----------------------------------------------------------------------------
+ * This routine sets common parameters like transpose, volume, etc.
+ * First, it attempts to use the parser EAS_SetStreamParameter interface. If that
+ * fails, it attempts to get the synth handle from the parser and
+ * set the parameter directly on the synth. This eliminates duplicate
+ * code in the parser.
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_IntSetStrmParam (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_INT param, EAS_I32 value)
+{
+ S_SYNTH *pSynth;
+
+ /* try to set the parameter using stream interface */
+ if (EAS_SetStreamParameter(pEASData, pStream, param, value) == EAS_SUCCESS)
+ return EAS_SUCCESS;
+
+ /* get a pointer to the synth object and set it directly */
+ /*lint -e{740} we are cheating by passing a pointer through this interface */
+ if (EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_SYNTH_HANDLE, (EAS_I32*) &pSynth) != EAS_SUCCESS)
+ return EAS_ERROR_INVALID_PARAMETER;
+
+ if (pSynth == NULL)
+ return EAS_ERROR_INVALID_PARAMETER;
+
+ switch (param)
+ {
+
+#ifdef DLS_SYNTHESIZER
+ case PARSER_DATA_DLS_COLLECTION:
+ {
+ EAS_RESULT result = VMSetDLSLib(pSynth, (EAS_DLSLIB_HANDLE) value);
+ if (result == EAS_SUCCESS)
+ {
+ DLSAddRef((S_DLS*) value);
+ VMInitializeAllChannels(pEASData->pVoiceMgr, pSynth);
+ }
+ return result;
+ }
+#endif
+
+ case PARSER_DATA_EAS_LIBRARY:
+ return VMSetEASLib(pSynth, (EAS_SNDLIB_HANDLE) value);
+
+ case PARSER_DATA_POLYPHONY:
+ return VMSetPolyphony(pEASData->pVoiceMgr, pSynth, value);
+
+ case PARSER_DATA_PRIORITY:
+ return VMSetPriority(pEASData->pVoiceMgr, pSynth, value);
+
+ case PARSER_DATA_TRANSPOSITION:
+ VMSetTranposition(pSynth, value);
+ break;
+
+ case PARSER_DATA_VOLUME:
+ VMSetVolume(pSynth, (EAS_U16) value);
+ break;
+
+ default:
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Invalid paramter %d in call to EAS_IntSetStrmParam", param); */ }
+ return EAS_ERROR_INVALID_PARAMETER;
+ }
+
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_IntGetStrmParam()
+ *----------------------------------------------------------------------------
+ * This routine gets common parameters like transpose, volume, etc.
+ * First, it attempts to use the parser EAS_GetStreamParameter interface. If that
+ * fails, it attempts to get the synth handle from the parser and
+ * get the parameter directly on the synth.
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_IntGetStrmParam (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_INT param, EAS_I32 *pValue)
+{
+ S_SYNTH *pSynth;
+
+ /* try to set the parameter */
+ if (EAS_GetStreamParameter(pEASData, pStream, param, pValue) == EAS_SUCCESS)
+ return EAS_SUCCESS;
+
+ /* get a pointer to the synth object and retrieve data directly */
+ /*lint -e{740} we are cheating by passing a pointer through this interface */
+ if (EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_SYNTH_HANDLE, (EAS_I32*) &pSynth) != EAS_SUCCESS)
+ return EAS_ERROR_INVALID_PARAMETER;
+
+ if (pSynth == NULL)
+ return EAS_ERROR_INVALID_PARAMETER;
+
+ switch (param)
+ {
+ case PARSER_DATA_POLYPHONY:
+ return VMGetPolyphony(pEASData->pVoiceMgr, pSynth, pValue);
+
+ case PARSER_DATA_PRIORITY:
+ return VMGetPriority(pEASData->pVoiceMgr, pSynth, pValue);
+
+ case PARSER_DATA_TRANSPOSITION:
+ VMGetTranposition(pSynth, pValue);
+ break;
+
+ case PARSER_DATA_NOTE_COUNT:
+ *pValue = VMGetNoteCount(pSynth);
+ break;
+
+ default:
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Invalid paramter %d in call to EAS_IntSetStrmParam", param); */ }
+ return EAS_ERROR_INVALID_PARAMETER;
+ }
+
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_AllocateStream()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Allocates a stream handle
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_INT EAS_AllocateStream (EAS_DATA_HANDLE pEASData)
+{
+ EAS_INT streamNum;
+
+ /* check for static allocation, only one stream allowed */
+ if (pEASData->staticMemoryModel)
+ {
+ if (pEASData->streams[0].handle != NULL)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Attempt to open multiple streams in static model\n"); */ }
+ return -1;
+ }
+ return 0;
+ }
+
+ /* dynamic model */
+ for (streamNum = 0; streamNum < MAX_NUMBER_STREAMS; streamNum++)
+ if (pEASData->streams[streamNum].handle == NULL)
+ break;
+ if (streamNum == MAX_NUMBER_STREAMS)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Exceeded maximum number of open streams\n"); */ }
+ return -1;
+ }
+ return streamNum;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_InitStream()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Initialize a stream
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ *----------------------------------------------------------------------------
+*/
+static void EAS_InitStream (S_EAS_STREAM *pStream, EAS_VOID_PTR pParserModule, EAS_VOID_PTR streamHandle)
+{
+ pStream->pParserModule = pParserModule;
+ pStream->handle = streamHandle;
+ pStream->time = 0;
+ pStream->frameLength = AUDIO_FRAME_LENGTH;
+ pStream->repeatCount = 0;
+ pStream->volume = DEFAULT_STREAM_VOLUME;
+ pStream->streamFlags = 0;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_Config()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Returns a pointer to a structure containing the configuration options
+ * in this library build.
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC const S_EAS_LIB_CONFIG *EAS_Config (void)
+{
+ return &easLibConfig;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_Init()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Initialize the synthesizer library
+ *
+ * Inputs:
+ * ppEASData - pointer to data handle variable for this instance
+ *
+ * Outputs:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_Init (EAS_DATA_HANDLE *ppEASData)
+{
+ EAS_HW_DATA_HANDLE pHWInstData;
+ EAS_RESULT result;
+ S_EAS_DATA *pEASData;
+ EAS_INT module;
+ EAS_BOOL staticMemoryModel;
+
+ /* get the memory model */
+ staticMemoryModel = EAS_CMStaticMemoryModel();
+
+ /* initialize the host wrapper interface */
+ *ppEASData = NULL;
+ if ((result = EAS_HWInit(&pHWInstData)) != EAS_SUCCESS)
+ return result;
+
+ /* check Configuration Module for S_EAS_DATA allocation */
+ if (staticMemoryModel)
+ pEASData = EAS_CMEnumData(EAS_CM_EAS_DATA);
+ else
+ pEASData = EAS_HWMalloc(pHWInstData, sizeof(S_EAS_DATA));
+ if (!pEASData)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate EAS library memory\n"); */ }
+ return EAS_ERROR_MALLOC_FAILED;
+ }
+
+ /* initialize some data */
+ EAS_HWMemSet(pEASData, 0, sizeof(S_EAS_DATA));
+ pEASData->staticMemoryModel = (EAS_BOOL8) staticMemoryModel;
+ pEASData->hwInstData = pHWInstData;
+ pEASData->renderTime = 0;
+
+ /* set header search flag */
+#ifdef FILE_HEADER_SEARCH
+ pEASData->searchHeaderFlag = EAS_TRUE;
+#endif
+
+ /* initalize parameters */
+ EAS_SetVolume(pEASData, NULL, DEFAULT_VOLUME);
+
+#ifdef _METRICS_ENABLED
+ /* initalize the metrics module */
+ pEASData->pMetricsModule = EAS_CMEnumOptModules(EAS_MODULE_METRICS);
+ if (pEASData->pMetricsModule != NULL)
+ {
+ if ((result = (*pEASData->pMetricsModule->pfInit)(pEASData, &pEASData->pMetricsData)) != EAS_SUCCESS)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld initializing metrics module\n", result); */ }
+ return result;
+ }
+ }
+#endif
+
+ /* initailize the voice manager & synthesizer */
+ if ((result = VMInitialize(pEASData)) != EAS_SUCCESS)
+ return result;
+
+ /* initialize mix engine */
+ if ((result = EAS_MixEngineInit(pEASData)) != EAS_SUCCESS)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld starting up mix engine\n", result); */ }
+ return result;
+ }
+
+ /* initialize effects modules */
+ for (module = 0; module < NUM_EFFECTS_MODULES; module++)
+ {
+ pEASData->effectsModules[module].effect = EAS_CMEnumFXModules(module);
+ if (pEASData->effectsModules[module].effect != NULL)
+ {
+ if ((result = (*pEASData->effectsModules[module].effect->pfInit)(pEASData, &pEASData->effectsModules[module].effectData)) != EAS_SUCCESS)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Initialization of effects module %d returned %d\n", module, result); */ }
+ return result;
+ }
+ }
+ }
+
+ /* initialize PCM engine */
+ if ((result = EAS_PEInit(pEASData)) != EAS_SUCCESS)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "EAS_PEInit failed with error code %ld\n", result); */ }
+ return result;
+ }
+
+ /* return instance data pointer to host */
+ *ppEASData = pEASData;
+
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_Shutdown()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Shuts down the library. Deallocates any memory associated with the
+ * synthesizer (dynamic memory model only)
+ *
+ * Inputs:
+ * pEASData - handle to data for this instance
+ *
+ * Outputs:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_Shutdown (EAS_DATA_HANDLE pEASData)
+{
+ EAS_HW_DATA_HANDLE hwInstData;
+ EAS_RESULT result, reportResult;
+ EAS_INT i;
+
+ /* establish pointers */
+ hwInstData = pEASData->hwInstData;
+
+ /* check for NULL handle */
+ if (!pEASData)
+ return EAS_ERROR_HANDLE_INTEGRITY;
+
+ /* if there are streams open, close them */
+ reportResult = EAS_SUCCESS;
+ for (i = 0; i < MAX_NUMBER_STREAMS; i++)
+ {
+ if (pEASData->streams[i].pParserModule && pEASData->streams[i].handle)
+ {
+ if ((result = (*((S_FILE_PARSER_INTERFACE*)(pEASData->streams[i].pParserModule))->pfClose)(pEASData, pEASData->streams[i].handle)) != EAS_SUCCESS)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld shutting down parser module\n", result); */ }
+ reportResult = result;
+ }
+ }
+ }
+
+ /* shutdown PCM engine */
+ if ((result = EAS_PEShutdown(pEASData)) != EAS_SUCCESS)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld shutting down PCM engine\n", result); */ }
+ if (reportResult == EAS_SUCCESS)
+ reportResult = result;
+ }
+
+ /* shutdown mix engine */
+ if ((result = EAS_MixEngineShutdown(pEASData)) != EAS_SUCCESS)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld shutting down mix engine\n", result); */ }
+ if (reportResult == EAS_SUCCESS)
+ reportResult = result;
+ }
+
+ /* shutdown effects modules */
+ for (i = 0; i < NUM_EFFECTS_MODULES; i++)
+ {
+ if (pEASData->effectsModules[i].effect)
+ {
+ if ((result = (*pEASData->effectsModules[i].effect->pfShutdown)(pEASData, pEASData->effectsModules[i].effectData)) != EAS_SUCCESS)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Shutdown of effects module %d returned %d\n", i, result); */ }
+ if (reportResult == EAS_SUCCESS)
+ reportResult = result;
+ }
+ }
+ }
+
+ /* shutdown the voice manager & synthesizer */
+ VMShutdown(pEASData);
+
+#ifdef _METRICS_ENABLED
+ /* shutdown the metrics module */
+ if (pEASData->pMetricsModule != NULL)
+ {
+ if ((result = (*pEASData->pMetricsModule->pfShutdown)(pEASData, pEASData->pMetricsData)) != EAS_SUCCESS)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld shutting down metrics module\n", result); */ }
+ if (reportResult == EAS_SUCCESS)
+ reportResult = result;
+ }
+ }
+#endif
+
+ /* release allocated memory */
+ if (!pEASData->staticMemoryModel)
+ EAS_HWFree(hwInstData, pEASData);
+
+ /* shutdown host wrappers */
+ if (hwInstData)
+ {
+ if ((result = EAS_HWShutdown(hwInstData)) != EAS_SUCCESS)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld shutting down host wrappers\n", result); */ }
+ if (reportResult == EAS_SUCCESS)
+ reportResult = result;
+ }
+ }
+
+ return reportResult;
+}
+
+#ifdef JET_INTERFACE
+/*----------------------------------------------------------------------------
+ * EAS_OpenJETStream()
+ *----------------------------------------------------------------------------
+ * Private interface for JET to open an SMF stream with an offset
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_OpenJETStream (EAS_DATA_HANDLE pEASData, EAS_FILE_HANDLE fileHandle, EAS_I32 offset, EAS_HANDLE *ppStream)
+{
+ EAS_RESULT result;
+ EAS_VOID_PTR streamHandle;
+ S_FILE_PARSER_INTERFACE *pParserModule;
+ EAS_INT streamNum;
+
+ /* allocate a stream */
+ if ((streamNum = EAS_AllocateStream(pEASData)) < 0)
+ return EAS_ERROR_MAX_STREAMS_OPEN;
+
+ /* check Configuration Module for SMF parser */
+ *ppStream = NULL;
+ streamHandle = NULL;
+ pParserModule = (S_FILE_PARSER_INTERFACE *) EAS_CMEnumModules(0);
+ if (pParserModule == NULL)
+ return EAS_ERROR_UNRECOGNIZED_FORMAT;
+
+ /* see if SMF parser recognizes the file */
+ if ((result = (*pParserModule->pfCheckFileType)(pEASData, fileHandle, &streamHandle, offset)) != EAS_SUCCESS)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "CheckFileType returned error %ld\n", result); */ }
+ return result;
+ }
+
+ /* parser recognized the file, return the handle */
+ if (streamHandle)
+ {
+ EAS_InitStream(&pEASData->streams[streamNum], pParserModule, streamHandle);
+ *ppStream = &pEASData->streams[streamNum];
+ return EAS_SUCCESS;
+ }
+
+ return EAS_ERROR_UNRECOGNIZED_FORMAT;
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ * EAS_OpenFile()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Opens a file for audio playback.
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * pHandle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_OpenFile (EAS_DATA_HANDLE pEASData, EAS_FILE_LOCATOR locator, EAS_HANDLE *ppStream)
+{
+ EAS_RESULT result;
+ EAS_FILE_HANDLE fileHandle;
+ EAS_VOID_PTR streamHandle;
+ S_FILE_PARSER_INTERFACE *pParserModule;
+ EAS_INT streamNum;
+ EAS_INT moduleNum;
+
+ /* open the file */
+ if ((result = EAS_HWOpenFile(pEASData->hwInstData, locator, &fileHandle, EAS_FILE_READ)) != EAS_SUCCESS)
+ return result;
+
+ /* allocate a stream */
+ if ((streamNum = EAS_AllocateStream(pEASData)) < 0)
+ return EAS_ERROR_MAX_STREAMS_OPEN;
+
+ /* check Configuration Module for file parsers */
+ pParserModule = NULL;
+ *ppStream = NULL;
+ streamHandle = NULL;
+ for (moduleNum = 0; ; moduleNum++)
+ {
+ pParserModule = (S_FILE_PARSER_INTERFACE *) EAS_CMEnumModules(moduleNum);
+ if (pParserModule == NULL)
+ break;
+
+ /* see if this parser recognizes it */
+ if ((result = (*pParserModule->pfCheckFileType)(pEASData, fileHandle, &streamHandle, 0L)) != EAS_SUCCESS)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "CheckFileType returned error %ld\n", result); */ }
+ return result;
+ }
+
+ /* parser recognized the file, return the handle */
+ if (streamHandle)
+ {
+
+ /* save the parser pointer and file handle */
+ EAS_InitStream(&pEASData->streams[streamNum], pParserModule, streamHandle);
+ *ppStream = &pEASData->streams[streamNum];
+ return EAS_SUCCESS;
+ }
+
+ /* rewind the file for the next parser */
+ if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, 0L)) != EAS_SUCCESS)
+ return result;
+ }
+
+ /* no parser was able to recognize the file, close it and return an error */
+ EAS_HWCloseFile(pEASData->hwInstData, fileHandle);
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "No parser recognized the requested file\n"); */ }
+ return EAS_ERROR_UNRECOGNIZED_FORMAT;
+}
+
+#ifdef MMAPI_SUPPORT
+/*----------------------------------------------------------------------------
+ * EAS_MMAPIToneControl()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Opens a ToneControl file for audio playback.
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * pHandle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_MMAPIToneControl (EAS_DATA_HANDLE pEASData, EAS_FILE_LOCATOR locator, EAS_HANDLE *ppStream)
+{
+ EAS_RESULT result;
+ EAS_FILE_HANDLE fileHandle;
+ EAS_VOID_PTR streamHandle;
+ S_FILE_PARSER_INTERFACE *pParserModule;
+ EAS_INT streamNum;
+
+ /* check if the tone control parser is available */
+ *ppStream = NULL;
+ streamHandle = NULL;
+ pParserModule = EAS_CMEnumOptModules(EAS_MODULE_MMAPI_TONE_CONTROL);
+ if (pParserModule == NULL)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_MMAPIToneControl: ToneControl parser not available\n"); */ }
+ return EAS_ERROR_FEATURE_NOT_AVAILABLE;
+ }
+
+ /* open the file */
+ if ((result = EAS_HWOpenFile(pEASData->hwInstData, locator, &fileHandle, EAS_FILE_READ)) != EAS_SUCCESS)
+ return result;
+
+ /* allocate a stream */
+ if ((streamNum = EAS_AllocateStream(pEASData)) < 0)
+ return EAS_ERROR_MAX_STREAMS_OPEN;
+
+ /* see if ToneControl parser recognizes it */
+ if ((result = (*pParserModule->pfCheckFileType)(pEASData, fileHandle, &streamHandle, 0L)) != EAS_SUCCESS)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "CheckFileType returned error %ld\n", result); */ }
+ return result;
+ }
+
+ /* parser accepted the file, return the handle */
+ if (streamHandle)
+ {
+
+ /* save the parser pointer and file handle */
+ EAS_InitStream(&pEASData->streams[streamNum], pParserModule, streamHandle);
+ *ppStream = &pEASData->streams[streamNum];
+ return EAS_SUCCESS;
+ }
+
+ /* parser did not recognize the file, close it and return an error */
+ EAS_HWCloseFile(pEASData->hwInstData, fileHandle);
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "No parser recognized the requested file\n"); */ }
+ return EAS_ERROR_UNRECOGNIZED_FORMAT;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_GetWaveFmtChunk
+ *----------------------------------------------------------------------------
+ * Helper function to retrieve WAVE file fmt chunk for MMAPI
+ *----------------------------------------------------------------------------
+ * pEASData - pointer to EAS persistent data object
+ * pStream - stream handle
+ * pFmtChunk - pointer to variable to receive current setting
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_GetWaveFmtChunk (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_VOID_PTR *ppFmtChunk)
+{
+ EAS_RESULT result;
+ EAS_I32 value;
+
+ if ((result = EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_FORMAT, &value)) != EAS_SUCCESS)
+ return result;
+ *ppFmtChunk = (EAS_VOID_PTR) value;
+ return EAS_SUCCESS;
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ * EAS_GetFileType
+ *----------------------------------------------------------------------------
+ * Returns the file type (see eas_types.h for enumerations)
+ *----------------------------------------------------------------------------
+ * pEASData - pointer to EAS persistent data object
+ * pStream - stream handle
+ * pFileType - pointer to variable to receive file type
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_GetFileType (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_I32 *pFileType)
+{
+ if (!EAS_StreamReady (pEASData, pStream))
+ return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
+ return EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_FILE_TYPE, pFileType);
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_Prepare()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Prepares the synthesizer to play the file or stream. Parses the first
+ * frame of data from the file and arms the synthesizer.
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - file or stream handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_Prepare (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream)
+{
+ S_FILE_PARSER_INTERFACE *pParserModule;
+ EAS_STATE state;
+ EAS_RESULT result;
+
+ pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule;
+ if (pParserModule == NULL)
+ return EAS_ERROR_FEATURE_NOT_AVAILABLE;
+
+ /* check for valid state */
+ result = pParserModule->pfState(pEASData, pStream->handle, &state);
+ if (result == EAS_SUCCESS)
+ {
+ /* prepare the stream */
+ if (state == EAS_STATE_OPEN)
+ {
+ pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule;
+ result = (*pParserModule->pfPrepare)(pEASData, pStream->handle);
+
+ /* set volume */
+ if (result == EAS_SUCCESS)
+ result = EAS_SetVolume(pEASData, pStream, pStream->volume);
+ }
+ else
+ result = EAS_ERROR_NOT_VALID_IN_THIS_STATE;
+
+ }
+
+ return result;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_Render()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Parse the Midi data and render PCM audio data.
+ *
+ * Inputs:
+ * pEASData - buffer for internal EAS data
+ * pOut - output buffer pointer
+ * nNumRequested - requested num samples to generate
+ * pnNumGenerated - actual number of samples generated
+ *
+ * Outputs:
+ * EAS_SUCCESS if PCM data was successfully rendered
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_Render (EAS_DATA_HANDLE pEASData, EAS_PCM *pOut, EAS_I32 numRequested, EAS_I32 *pNumGenerated)
+{
+ S_FILE_PARSER_INTERFACE *pParserModule;
+ EAS_RESULT result;
+ EAS_I32 voicesRendered;
+ EAS_STATE parserState;
+ EAS_INT streamNum;
+
+ /* assume no samples generated and reset workload */
+ *pNumGenerated = 0;
+ VMInitWorkload(pEASData->pVoiceMgr);
+
+ /* no support for other buffer sizes yet */
+ if (numRequested != BUFFER_SIZE_IN_MONO_SAMPLES)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "This library supports only %ld samples in buffer, host requested %ld samples\n",
+ (EAS_I32) BUFFER_SIZE_IN_MONO_SAMPLES, numRequested); */ }
+ return EAS_BUFFER_SIZE_MISMATCH;
+ }
+
+#ifdef _METRICS_ENABLED
+ /* start performance counter */
+ if (pEASData->pMetricsData)
+ (*pEASData->pMetricsModule->pfStartTimer)(pEASData->pMetricsData, EAS_PM_TOTAL_TIME);
+#endif
+
+ /* prep the frame buffer, do mix engine prep only if TRUE */
+#ifdef _SPLIT_ARCHITECTURE
+ if (VMStartFrame(pEASData))
+ EAS_MixEnginePrep(pEASData, numRequested);
+#else
+ /* prep the mix engine */
+ EAS_MixEnginePrep(pEASData, numRequested);
+#endif
+
+ /* save the output buffer pointer */
+ pEASData->pOutputAudioBuffer = pOut;
+
+
+#ifdef _METRICS_ENABLED
+ /* start performance counter */
+ if (pEASData->pMetricsData)
+ (*pEASData->pMetricsModule->pfStartTimer)(pEASData->pMetricsData, EAS_PM_PARSE_TIME);
+#endif
+
+ /* if we haven't finished parsing from last time, do it now */
+ /* need to parse another frame of events before we render again */
+ for (streamNum = 0; streamNum < MAX_NUMBER_STREAMS; streamNum++)
+ {
+ /* clear the locate flag */
+ pEASData->streams[streamNum].streamFlags &= ~STREAM_FLAGS_LOCATE;
+
+ if (pEASData->streams[streamNum].pParserModule)
+ {
+
+ /* establish pointer to parser module */
+ pParserModule = pEASData->streams[streamNum].pParserModule;
+
+ /* handle pause */
+ if (pEASData->streams[streamNum].streamFlags & STREAM_FLAGS_PAUSE)
+ {
+ if (pParserModule->pfPause)
+ result = pParserModule->pfPause(pEASData, pEASData->streams[streamNum].handle);
+ pEASData->streams[streamNum].streamFlags &= ~STREAM_FLAGS_PAUSE;
+ }
+
+ /* get current state */
+ if ((result = (*pParserModule->pfState)(pEASData, pEASData->streams[streamNum].handle, &parserState)) != EAS_SUCCESS)
+ return result;
+
+ /* handle resume */
+ if (parserState == EAS_STATE_PAUSED)
+ {
+ if (pEASData->streams[streamNum].streamFlags & STREAM_FLAGS_RESUME)
+ {
+ if (pParserModule->pfResume)
+ result = pParserModule->pfResume(pEASData, pEASData->streams[streamNum].handle);
+ pEASData->streams[streamNum].streamFlags &= ~STREAM_FLAGS_RESUME;
+ }
+ }
+
+ /* if necessary, parse stream */
+ if ((pEASData->streams[streamNum].streamFlags & STREAM_FLAGS_PARSED) == 0)
+ if ((result = EAS_ParseEvents(pEASData, &pEASData->streams[streamNum], pEASData->streams[streamNum].time + pEASData->streams[streamNum].frameLength, eParserModePlay)) != EAS_SUCCESS)
+ return result;
+
+ /* check for an early abort */
+ if ((pEASData->streams[streamNum].streamFlags) == 0)
+ {
+
+#ifdef _METRICS_ENABLED
+ /* stop performance counter */
+ if (pEASData->pMetricsData)
+ (*pEASData->pMetricsModule->pfStartTimer)(pEASData->pMetricsData, EAS_PM_TOTAL_TIME);
+#endif
+
+ return EAS_SUCCESS;
+ }
+
+ /* check for repeat */
+ if (pEASData->streams[streamNum].repeatCount)
+ {
+
+ /* check for stopped state */
+ if ((result = (*pParserModule->pfState)(pEASData, pEASData->streams[streamNum].handle, &parserState)) != EAS_SUCCESS)
+ return result;
+ if (parserState == EAS_STATE_STOPPED)
+ {
+
+ /* decrement repeat count, unless it is negative */
+ if (pEASData->streams[streamNum].repeatCount > 0)
+ pEASData->streams[streamNum].repeatCount--;
+
+ /* reset the parser */
+ if ((result = (*pParserModule->pfReset)(pEASData, pEASData->streams[streamNum].handle)) != EAS_SUCCESS)
+ return result;
+ pEASData->streams[streamNum].time = 0;
+ }
+ }
+ }
+ }
+
+#ifdef _METRICS_ENABLED
+ /* stop performance counter */
+ if (pEASData->pMetricsData)
+ (void)(*pEASData->pMetricsModule->pfStopTimer)(pEASData->pMetricsData, EAS_PM_PARSE_TIME);
+#endif
+
+#ifdef _METRICS_ENABLED
+ /* start the render timer */
+ if (pEASData->pMetricsData)
+ (*pEASData->pMetricsModule->pfStartTimer)(pEASData->pMetricsData, EAS_PM_RENDER_TIME);
+#endif
+
+ /* render audio */
+ if ((result = VMRender(pEASData->pVoiceMgr, BUFFER_SIZE_IN_MONO_SAMPLES, pEASData->pMixBuffer, &voicesRendered)) != EAS_SUCCESS)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "pfRender function returned error %ld\n", result); */ }
+ return result;
+ }
+
+#ifdef _METRICS_ENABLED
+ /* stop the render timer */
+ if (pEASData->pMetricsData) {
+ (*pEASData->pMetricsModule->pfIncrementCounter)(pEASData->pMetricsData, EAS_PM_FRAME_COUNT, 1);
+ (void)(*pEASData->pMetricsModule->pfStopTimer)(pEASData->pMetricsData, EAS_PM_RENDER_TIME);
+ (*pEASData->pMetricsModule->pfIncrementCounter)(pEASData->pMetricsData, EAS_PM_TOTAL_VOICE_COUNT, (EAS_U32) voicesRendered);
+ (void)(*pEASData->pMetricsModule->pfRecordMaxValue)(pEASData->pMetricsData, EAS_PM_MAX_VOICES, (EAS_U32) voicesRendered);
+ }
+#endif
+
+ //2 Do we really need frameParsed?
+ /* need to parse another frame of events before we render again */
+ for (streamNum = 0; streamNum < MAX_NUMBER_STREAMS; streamNum++)
+ if (pEASData->streams[streamNum].pParserModule != NULL)
+ pEASData->streams[streamNum].streamFlags &= ~STREAM_FLAGS_PARSED;
+
+#ifdef _METRICS_ENABLED
+ /* start performance counter */
+ if (pEASData->pMetricsData)
+ (*pEASData->pMetricsModule->pfStartTimer)(pEASData->pMetricsData, EAS_PM_STREAM_TIME);
+#endif
+
+ /* render PCM audio */
+ if ((result = EAS_PERender(pEASData, numRequested)) != EAS_SUCCESS)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_PERender returned error %ld\n", result); */ }
+ return result;
+ }
+
+#ifdef _METRICS_ENABLED
+ /* stop the stream timer */
+ if (pEASData->pMetricsData)
+ (void)(*pEASData->pMetricsModule->pfStopTimer)(pEASData->pMetricsData, EAS_PM_STREAM_TIME);
+#endif
+
+#ifdef _METRICS_ENABLED
+ /* start the post timer */
+ if (pEASData->pMetricsData)
+ (*pEASData->pMetricsModule->pfStartTimer)(pEASData->pMetricsData, EAS_PM_POST_TIME);
+#endif
+
+ /* for split architecture, send DSP vectors. Do post only if return is TRUE */
+#ifdef _SPLIT_ARCHITECTURE
+ if (VMEndFrame(pEASData))
+ {
+ /* now do post-processing */
+ EAS_MixEnginePost(pEASData, numRequested);
+ *pNumGenerated = numRequested;
+ }
+#else
+ /* now do post-processing */
+ EAS_MixEnginePost(pEASData, numRequested);
+ *pNumGenerated = numRequested;
+#endif
+
+#ifdef _METRICS_ENABLED
+ /* stop the post timer */
+ if (pEASData->pMetricsData)
+ (void)(*pEASData->pMetricsModule->pfStopTimer)(pEASData->pMetricsData, EAS_PM_POST_TIME);
+#endif
+
+ /* advance render time */
+ pEASData->renderTime += AUDIO_FRAME_LENGTH;
+
+#if 0
+ /* dump workload for debug */
+ if (pEASData->pVoiceMgr->workload)
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Workload = %d\n", pEASData->pVoiceMgr->workload); */ }
+#endif
+
+#ifdef _METRICS_ENABLED
+ /* stop performance counter */
+ if (pEASData->pMetricsData)
+ {
+ PERF_TIMER temp;
+ temp = (*pEASData->pMetricsModule->pfStopTimer)(pEASData->pMetricsData, EAS_PM_TOTAL_TIME);
+
+ /* if max render time, record the number of voices and time */
+ if ((*pEASData->pMetricsModule->pfRecordMaxValue)
+ (pEASData->pMetricsData, EAS_PM_MAX_CYCLES, (EAS_U32) temp))
+ {
+ (*pEASData->pMetricsModule->pfRecordValue)(pEASData->pMetricsData, EAS_PM_MAX_CYCLES_VOICES, (EAS_U32) voicesRendered);
+ (*pEASData->pMetricsModule->pfRecordValue)(pEASData->pMetricsData, EAS_PM_MAX_CYCLES_TIME, (EAS_I32) (pEASData->renderTime >> 8));
+ }
+ }
+#endif
+
+#ifdef JET_INTERFACE
+ /* let JET to do its thing */
+ if (pEASData->jetHandle != NULL)
+ {
+ result = JET_Process(pEASData);
+ if (result != EAS_SUCCESS)
+ return result;
+ }
+#endif
+
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_SetRepeat()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Set the selected stream to repeat.
+ *
+ * Inputs:
+ * pEASData - handle to data for this instance
+ * handle - handle to stream
+ * repeatCount - repeat count
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ * Notes:
+ * 0 = no repeat
+ * 1 = repeat once, i.e. play through twice
+ * -1 = repeat forever
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pEASData) reserved for future use */
+EAS_PUBLIC EAS_RESULT EAS_SetRepeat (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 repeatCount)
+{
+ pStream->repeatCount = repeatCount;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_GetRepeat()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Gets the current repeat count for the selected stream.
+ *
+ * Inputs:
+ * pEASData - handle to data for this instance
+ * handle - handle to stream
+ * pRrepeatCount - pointer to variable to hold repeat count
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ * Notes:
+ * 0 = no repeat
+ * 1 = repeat once, i.e. play through twice
+ * -1 = repeat forever
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pEASData) reserved for future use */
+EAS_PUBLIC EAS_RESULT EAS_GetRepeat (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *pRepeatCount)
+{
+ *pRepeatCount = pStream->repeatCount;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_SetPlaybackRate()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Sets the playback rate.
+ *
+ * Inputs:
+ * pEASData - handle to data for this instance
+ * handle - handle to stream
+ * rate - rate (28-bit fractional amount)
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pEASData) reserved for future use */
+EAS_PUBLIC EAS_RESULT EAS_SetPlaybackRate (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_U32 rate)
+{
+
+ /* check range */
+ if ((rate < (1 << 27)) || (rate > (1 << 29)))
+ return EAS_ERROR_INVALID_PARAMETER;
+
+ /* calculate new frame length
+ *
+ * NOTE: The maximum frame length we can accomodate based on a
+ * maximum rate of 2.0 (2^28) is 2047 (2^13-1). To accomodate a
+ * longer frame length or a higher maximum rate, the fixed point
+ * divide below will need to be adjusted
+ */
+ pStream->frameLength = (AUDIO_FRAME_LENGTH * (rate >> 8)) >> 20;
+
+ /* notify stream of new playback rate */
+ EAS_SetStreamParameter(pEASData, pStream, PARSER_DATA_PLAYBACK_RATE, (EAS_I32) rate);
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_SetTransposition)
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Sets the key tranposition for the synthesizer. Transposes all
+ * melodic instruments by the specified amount. Range is limited
+ * to +/-12 semitones.
+ *
+ * Inputs:
+ * pEASData - handle to data for this instance
+ * handle - handle to stream
+ * transposition - +/-12 semitones
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_SetTransposition (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 transposition)
+{
+
+ /* check range */
+ if ((transposition < -12) || (transposition > 12))
+ return EAS_ERROR_INVALID_PARAMETER;
+
+ if (!EAS_StreamReady(pEASData, pStream))
+ return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
+ return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_TRANSPOSITION, transposition);
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_ParseEvents()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Parse events in the current streams until the desired time is reached.
+ *
+ * Inputs:
+ * pEASData - buffer for internal EAS data
+ * endTime - stop parsing if this time is reached
+ * parseMode - play, locate, or metadata
+ *
+ * Outputs:
+ * EAS_SUCCESS if PCM data was successfully rendered
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT EAS_ParseEvents (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_U32 endTime, EAS_INT parseMode)
+{
+ S_FILE_PARSER_INTERFACE *pParserModule;
+ EAS_RESULT result;
+ EAS_I32 parserState;
+ EAS_BOOL done;
+ EAS_INT yieldCount = YIELD_EVENT_COUNT;
+ EAS_U32 time = 0;
+
+ /* does this parser have a time function? */
+ pParserModule = pStream->pParserModule;
+ if (pParserModule->pfTime == NULL)
+ {
+ /* check state */
+ if ((result = (*pParserModule->pfState)(pEASData, pStream->handle, &parserState)) != EAS_SUCCESS)
+ return result;
+ /* if play state, advance time */
+ if ((parserState >= EAS_STATE_READY) && (parserState <= EAS_STATE_PAUSING))
+ pStream->time += pStream->frameLength;
+ done = EAS_TRUE;
+ }
+
+ /* assume we're not done, in case we abort out */
+ else
+ {
+ pStream->streamFlags &= ~STREAM_FLAGS_PARSED;
+ done = EAS_FALSE;
+ }
+
+ while (!done)
+ {
+
+ /* check for stopped state */
+ if ((result = (*pParserModule->pfState)(pEASData, pStream->handle, &parserState)) != EAS_SUCCESS)
+ return result;
+ if (parserState > EAS_STATE_PLAY)
+ {
+ /* save current time if we're not in play mode */
+ if (parseMode != eParserModePlay)
+ pStream->time = time << 8;
+ done = EAS_TRUE;
+ break;
+ }
+
+ /* get the next event time */
+ if (pParserModule->pfTime)
+ {
+ if ((result = (*pParserModule->pfTime)(pEASData, pStream->handle, &time)) != EAS_SUCCESS)
+ return result;
+
+ /* if next event is within this frame, parse it */
+ if (time < (endTime >> 8))
+ {
+
+ /* parse the next event */
+ if (pParserModule->pfEvent)
+ if ((result = (*pParserModule->pfEvent)(pEASData, pStream->handle, parseMode)) != EAS_SUCCESS)
+ return result;
+ }
+
+ /* no more events in this frame, advance time */
+ else
+ {
+ pStream->time = endTime;
+ done = EAS_TRUE;
+ }
+ }
+
+ /* check for max workload exceeded */
+ if (VMCheckWorkload(pEASData->pVoiceMgr))
+ {
+ /* stop even though we may not have parsed
+ * all the events in this frame. The parser will try to
+ * catch up on the next frame.
+ */
+ break;
+ }
+
+ /* give host a chance for an early abort */
+ if (--yieldCount == 0)
+ {
+ if (EAS_HWYield(pEASData->hwInstData))
+ break;
+ yieldCount = YIELD_EVENT_COUNT;
+ }
+ }
+
+ /* if no early abort, parsing is complete for this frame */
+ if (done)
+ pStream->streamFlags |= STREAM_FLAGS_PARSED;
+
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_ParseMetaData()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - file or stream handle
+ * playLength - pointer to variable to store the play length (in msecs)
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ * - resets the parser to the start of the file
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_ParseMetaData (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *playLength)
+{
+ S_FILE_PARSER_INTERFACE *pParserModule;
+ EAS_RESULT result;
+ EAS_STATE state;
+
+ pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule;
+ if (pParserModule == NULL)
+ return EAS_ERROR_FEATURE_NOT_AVAILABLE;
+
+ /* check parser state */
+ if ((result = (*pParserModule->pfState)(pEASData, pStream->handle, &state)) != EAS_SUCCESS)
+ return result;
+ if (state >= EAS_STATE_OPEN)
+ return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
+
+ /* if parser has metadata function, use that */
+ if (pParserModule->pfGetMetaData != NULL)
+ return pParserModule->pfGetMetaData(pEASData, pStream->handle, playLength);
+
+ /* reset the parser to the beginning */
+ if ((result = (*pParserModule->pfReset)(pEASData, pStream->handle)) != EAS_SUCCESS)
+ return result;
+
+ /* parse the file to end */
+ pStream->time = 0;
+ VMInitWorkload(pEASData->pVoiceMgr);
+ if ((result = EAS_ParseEvents(pEASData, pStream, 0x7fffffff, eParserModeMetaData)) != EAS_SUCCESS)
+ return result;
+
+ /* get the parser time */
+ if ((result = EAS_GetLocation(pEASData, pStream, playLength)) != EAS_SUCCESS)
+ return result;
+
+ /* reset the parser to the beginning */
+ pStream->time = 0;
+ return (*pParserModule->pfReset)(pEASData, pStream->handle);
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_RegisterMetaDataCallback()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Registers a metadata callback function for parsed metadata.
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - file or stream handle
+ * cbFunc - pointer to host callback function
+ * metaDataBuffer - pointer to metadata buffer
+ * metaDataBufSize - maximum size of the metadata buffer
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_RegisterMetaDataCallback (
+ EAS_DATA_HANDLE pEASData,
+ EAS_HANDLE pStream,
+ EAS_METADATA_CBFUNC cbFunc,
+ char *metaDataBuffer,
+ EAS_I32 metaDataBufSize,
+ EAS_VOID_PTR pUserData)
+{
+ S_METADATA_CB metadata;
+
+ if (!EAS_StreamReady(pEASData, pStream))
+ return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
+
+ /* register callback function */
+ metadata.callback = cbFunc;
+ metadata.buffer = metaDataBuffer;
+ metadata.bufferSize = metaDataBufSize;
+ metadata.pUserData = pUserData;
+ return EAS_SetStreamParameter(pEASData, pStream, PARSER_DATA_METADATA_CB, (EAS_I32) &metadata);
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_GetNoteCount ()
+ *----------------------------------------------------------------------------
+ * Returns the total number of notes played in this stream
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_GetNoteCount (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *pNoteCount)
+{
+ if (!EAS_StreamReady(pEASData, pStream))
+ return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
+ return EAS_IntGetStrmParam(pEASData, pStream, PARSER_DATA_NOTE_COUNT, pNoteCount);
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_CloseFile()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Closes an audio file or stream. Playback should have either paused or
+ * completed (EAS_State returns EAS_PAUSED or EAS_STOPPED).
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - file or stream handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_CloseFile (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream)
+{
+ S_FILE_PARSER_INTERFACE *pParserModule;
+ EAS_RESULT result;
+
+ /* call the close function */
+ pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule;
+ if (pParserModule == NULL)
+ return EAS_ERROR_FEATURE_NOT_AVAILABLE;
+
+ result = (*pParserModule->pfClose)(pEASData, pStream->handle);
+
+ /* clear the handle and parser interface pointer */
+ pStream->handle = NULL;
+ pStream->pParserModule = NULL;
+ return result;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_OpenMIDIStream()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Opens a raw MIDI stream allowing the host to route MIDI cable data directly to the synthesizer
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * pHandle - pointer to variable to hold file or stream handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_OpenMIDIStream (EAS_DATA_HANDLE pEASData, EAS_HANDLE *ppStream, EAS_HANDLE streamHandle)
+{
+ EAS_RESULT result;
+ S_INTERACTIVE_MIDI *pMIDIStream;
+ EAS_INT streamNum;
+
+ /* initialize some pointers */
+ *ppStream = NULL;
+
+ /* allocate a stream */
+ if ((streamNum = EAS_AllocateStream(pEASData)) < 0)
+ return EAS_ERROR_MAX_STREAMS_OPEN;
+
+ /* check Configuration Module for S_EAS_DATA allocation */
+ if (pEASData->staticMemoryModel)
+ pMIDIStream = EAS_CMEnumData(EAS_CM_MIDI_STREAM_DATA);
+ else
+ pMIDIStream = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_INTERACTIVE_MIDI));
+
+ /* allocate dynamic memory */
+ if (!pMIDIStream)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate MIDI stream data\n"); */ }
+ return EAS_ERROR_MALLOC_FAILED;
+ }
+
+ /* zero the memory to insure complete initialization */
+ EAS_HWMemSet(pMIDIStream, 0, sizeof(S_INTERACTIVE_MIDI));
+ EAS_InitStream(&pEASData->streams[streamNum], NULL, pMIDIStream);
+
+ /* instantiate a new synthesizer */
+ if (streamHandle == NULL)
+ {
+ result = VMInitMIDI(pEASData, &pMIDIStream->pSynth);
+ }
+
+ /* use an existing synthesizer */
+ else
+ {
+ EAS_I32 value;
+ result = EAS_GetStreamParameter(pEASData, streamHandle, PARSER_DATA_SYNTH_HANDLE, &value);
+ pMIDIStream->pSynth = (S_SYNTH*) value;
+ VMIncRefCount(pMIDIStream->pSynth);
+ }
+ if (result != EAS_SUCCESS)
+ {
+ EAS_CloseMIDIStream(pEASData, &pEASData->streams[streamNum]);
+ return result;
+ }
+
+ /* initialize the MIDI stream data */
+ EAS_InitMIDIStream(&pMIDIStream->stream);
+
+ *ppStream = (EAS_HANDLE) &pEASData->streams[streamNum];
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_WriteMIDIStream()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Send data to the MIDI stream device
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - stream handle
+ * pBuffer - pointer to buffer
+ * count - number of bytes to write
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_WriteMIDIStream (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_U8 *pBuffer, EAS_I32 count)
+{
+ S_INTERACTIVE_MIDI *pMIDIStream;
+ EAS_RESULT result;
+
+ pMIDIStream = (S_INTERACTIVE_MIDI*) pStream->handle;
+
+ if (count <= 0)
+ return EAS_ERROR_PARAMETER_RANGE;
+
+ /* send the entire buffer */
+ while (count--)
+ {
+ if ((result = EAS_ParseMIDIStream(pEASData, pMIDIStream->pSynth, &pMIDIStream->stream, *pBuffer++, eParserModePlay)) != EAS_SUCCESS)
+ return result;
+ }
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_CloseMIDIStream()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Closes a raw MIDI stream
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - stream handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_CloseMIDIStream (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream)
+{
+ S_INTERACTIVE_MIDI *pMIDIStream;
+
+ pMIDIStream = (S_INTERACTIVE_MIDI*) pStream->handle;
+
+ /* close synth */
+ if (pMIDIStream->pSynth != NULL)
+ {
+ VMMIDIShutdown(pEASData, pMIDIStream->pSynth);
+ pMIDIStream->pSynth = NULL;
+ }
+
+ /* release allocated memory */
+ if (!pEASData->staticMemoryModel)
+ EAS_HWFree(((S_EAS_DATA*) pEASData)->hwInstData, pMIDIStream);
+
+ pStream->handle = NULL;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_State()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Returns the state of an audio file or stream.
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - file or stream handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_State (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_STATE *pState)
+{
+ S_FILE_PARSER_INTERFACE *pParserModule;
+ EAS_RESULT result;
+
+ /* call the parser to return state */
+ pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule;
+ if (pParserModule == NULL)
+ return EAS_ERROR_FEATURE_NOT_AVAILABLE;
+
+ if ((result = (*pParserModule->pfState)(pEASData, pStream->handle, pState)) != EAS_SUCCESS)
+ return result;
+
+ /* if repeat count is set for this parser, mask the stopped state from the application */
+ if (pStream->repeatCount && (*pState == EAS_STATE_STOPPED))
+ *pState = EAS_STATE_PLAY;
+
+ /* if we're not ready or playing, we don't need to hide state from host */
+ if (*pState > EAS_STATE_PLAY)
+ return EAS_SUCCESS;
+
+ /* if stream is about to be paused, report it as paused */
+ if (pStream->streamFlags & STREAM_FLAGS_PAUSE)
+ {
+ if (pStream->streamFlags & STREAM_FLAGS_LOCATE)
+ *pState = EAS_STATE_PAUSED;
+ else
+ *pState = EAS_STATE_PAUSING;
+ }
+
+ /* if stream is about to resume, report it as playing */
+ if (pStream->streamFlags & STREAM_FLAGS_RESUME)
+ *pState = EAS_STATE_PLAY;
+
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_SetPolyphony()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Set the polyphony of the stream. A value of 0 allows the stream
+ * to use all voices (set by EAS_SetSynthPolyphony).
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * streamHandle - handle returned by EAS_OpenFile
+ * polyphonyCount - the desired polyphony count
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_SetPolyphony (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 polyphonyCount)
+{
+ if (!EAS_StreamReady(pEASData, pStream))
+ return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
+ return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_POLYPHONY, polyphonyCount);
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_GetPolyphony()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Returns the current polyphony setting of the stream
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * streamHandle - handle returned by EAS_OpenFile
+ * pPolyphonyCount - pointer to variable to receive polyphony count
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_GetPolyphony (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *pPolyphonyCount)
+{
+ if (!EAS_StreamReady(pEASData, pStream))
+ return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
+ return EAS_IntGetStrmParam(pEASData, pStream, PARSER_DATA_POLYPHONY, pPolyphonyCount);
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_SetSynthPolyphony()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Set the polyphony of the synth . Value must be >= 1 and <= the
+ * maximum number of voices. This function will pin the polyphony
+ * at those limits
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * synthNum - synthesizer number (0 = onboard, 1 = DSP)
+ * polyphonyCount - the desired polyphony count
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_SetSynthPolyphony (EAS_DATA_HANDLE pEASData, EAS_I32 synthNum, EAS_I32 polyphonyCount)
+{
+ return VMSetSynthPolyphony(pEASData->pVoiceMgr, synthNum, polyphonyCount);
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_GetSynthPolyphony()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Returns the current polyphony setting of the synth
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * synthNum - synthesizer number (0 = onboard, 1 = DSP)
+ * pPolyphonyCount - pointer to variable to receive polyphony count
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_GetSynthPolyphony (EAS_DATA_HANDLE pEASData, EAS_I32 synthNum, EAS_I32 *pPolyphonyCount)
+{
+ return VMGetSynthPolyphony(pEASData->pVoiceMgr, synthNum, pPolyphonyCount);
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_SetPriority()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Set the priority of the stream. Determines which stream's voices
+ * are stolen when there are insufficient voices for all notes.
+ * Value must be in the range of 1-15, lower values are higher
+ * priority.
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * streamHandle - handle returned by EAS_OpenFile
+ * polyphonyCount - the desired polyphony count
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_SetPriority (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 priority)
+{
+ if (!EAS_StreamReady(pEASData, pStream))
+ return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
+ return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_PRIORITY, priority);
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_GetPriority()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Returns the current priority setting of the stream
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * streamHandle - handle returned by EAS_OpenFile
+ * pPriority - pointer to variable to receive priority
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_GetPriority (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *pPriority)
+{
+ if (!EAS_StreamReady(pEASData, pStream))
+ return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
+ return EAS_IntGetStrmParam(pEASData, pStream, PARSER_DATA_PRIORITY, pPriority);
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_SetVolume()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Set the master gain for the mix engine in 1dB increments
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * volume - the desired master gain (100 is max)
+ * handle - file or stream handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ * overrides any previously set master volume from sysex
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_SetVolume (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 volume)
+{
+ EAS_I16 gain;
+
+ /* check range */
+ if ((volume < 0) || (volume > EAS_MAX_VOLUME))
+ return EAS_ERROR_PARAMETER_RANGE;
+
+ /* stream volume */
+ if (pStream != NULL)
+ {
+ EAS_I32 gainOffset;
+ EAS_RESULT result;
+
+ if (!EAS_StreamReady(pEASData, pStream))
+ return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
+
+ /* get gain offset */
+ pStream->volume = (EAS_U8) volume;
+ result = EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_GAIN_OFFSET, &gainOffset);
+ if (result == EAS_SUCCESS)
+ volume += gainOffset;
+
+ /* set stream volume */
+ gain = EAS_VolumeToGain(volume - STREAM_VOLUME_HEADROOM);
+
+ /* convert to linear scalar */
+ return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_VOLUME, gain);
+ }
+
+ /* master volume */
+ pEASData->masterVolume = (EAS_U8) volume;
+#if (NUM_OUTPUT_CHANNELS == 1)
+ /* leave 3dB headroom for mono output */
+ volume -= 3;
+#endif
+
+ gain = EAS_VolumeToGain(volume - STREAM_VOLUME_HEADROOM);
+ pEASData->masterGain = gain;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_GetVolume()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Returns the master volume for the synthesizer. The default volume setting is
+ * 50. The volume range is 0 to 100;
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * volume - the desired master volume
+ * handle - file or stream handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ * overrides any previously set master volume from sysex
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_I32 EAS_GetVolume (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream)
+{
+ if (pStream == NULL)
+ return pEASData->masterVolume;
+
+ if (!EAS_StreamReady(pEASData, pStream))
+ return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
+ return pStream->volume;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_SetMaxLoad()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Sets the maximum workload the parsers will do in a single call to
+ * EAS_Render. The units are currently arbitrary, but should correlate
+ * well to the actual CPU cycles consumed. The primary effect is to
+ * reduce the occasional peaks in CPU cycles consumed when parsing
+ * dense parts of a MIDI score.
+ *
+ * Inputs:
+ * pEASData - handle to data for this instance
+ * maxLoad - the desired maximum workload
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_SetMaxLoad (EAS_DATA_HANDLE pEASData, EAS_I32 maxLoad)
+{
+ VMSetWorkload(pEASData->pVoiceMgr, maxLoad);
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_SetMaxPCMStreams()
+ *----------------------------------------------------------------------------
+ * Sets the maximum number of PCM streams allowed in parsers that
+ * use PCM streaming.
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * streamHandle - handle returned by EAS_OpenFile
+ * maxNumStreams - maximum number of PCM streams
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_SetMaxPCMStreams (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 maxNumStreams)
+{
+ if (!EAS_StreamReady(pEASData, pStream))
+ return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
+ return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_MAX_PCM_STREAMS, maxNumStreams);
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_Locate()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Locate into the file associated with the handle.
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - file handle
+ * milliseconds - playback offset from start of file in milliseconds
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ * the actual offset will be quantized to the closest update period, typically
+ * a resolution of 5.9ms. Notes that are started prior to this time will not
+ * sound. Any notes currently playing will be shut off.
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_Locate (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 milliseconds, EAS_BOOL offset)
+{
+ S_FILE_PARSER_INTERFACE *pParserModule;
+ EAS_RESULT result;
+ EAS_U32 requestedTime;
+ EAS_STATE state;
+
+ /* get pointer to parser function table */
+ pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule;
+ if (pParserModule == NULL)
+ return EAS_ERROR_FEATURE_NOT_AVAILABLE;
+
+ if ((result = (*pParserModule->pfState)(pEASData, pStream->handle, &state)) != EAS_SUCCESS)
+ return result;
+ if (state >= EAS_STATE_OPEN)
+ return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
+
+ /* handle offset and limit to start of file */
+ /*lint -e{704} use shift for performance*/
+ if (offset)
+ milliseconds += (EAS_I32) pStream->time >> 8;
+ if (milliseconds < 0)
+ milliseconds = 0;
+
+ /* check to see if the request is different from the current time */
+ requestedTime = (EAS_U32) milliseconds;
+ if (requestedTime == (pStream->time >> 8))
+ return EAS_SUCCESS;
+
+ /* set the locate flag */
+ pStream->streamFlags |= STREAM_FLAGS_LOCATE;
+
+ /* use the parser locate function, if available */
+ if (pParserModule->pfLocate != NULL)
+ {
+ EAS_BOOL parserLocate = EAS_FALSE;
+ result = pParserModule->pfLocate(pEASData, pStream->handle, (EAS_I32) requestedTime, &parserLocate);
+ if (!parserLocate)
+ {
+ if (result == EAS_SUCCESS)
+ pStream->time = requestedTime << 8;
+ return result;
+ }
+ }
+
+ /* if we were paused and not going to resume, set pause request flag */
+ if (((state == EAS_STATE_PAUSING) || (state == EAS_STATE_PAUSED)) && ((pStream->streamFlags & STREAM_FLAGS_RESUME) == 0))
+ pStream->streamFlags |= STREAM_FLAGS_PAUSE;
+
+ /* reset the synth and parser */
+ if ((result = (*pParserModule->pfReset)(pEASData, pStream->handle)) != EAS_SUCCESS)
+ return result;
+ pStream->time = 0;
+
+ /* locating forward, clear parsed flag and parse data until we get to the requested location */
+ if ((result = EAS_ParseEvents(pEASData, pStream, requestedTime << 8, eParserModeLocate)) != EAS_SUCCESS)
+ return result;
+
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_GetLocation()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Returns the current playback offset
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - file handle
+ *
+ * Outputs:
+ * The offset in milliseconds from the start of the current sequence, quantized
+ * to the nearest update period. Actual resolution is typically 5.9 ms.
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pEASData) reserved for future use */
+EAS_PUBLIC EAS_RESULT EAS_GetLocation (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *pTime)
+{
+ if (!EAS_StreamReady(pEASData, pStream))
+ return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
+
+ *pTime = pStream->time >> 8;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_GetRenderTime()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Returns the current playback offset
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ *
+ * Outputs:
+ * Gets the render time clock in msecs.
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_GetRenderTime (EAS_DATA_HANDLE pEASData, EAS_I32 *pTime)
+{
+ *pTime = pEASData->renderTime >> 8;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_Pause()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Pauses the playback of the data associated with this handle. The audio
+ * is gracefully ramped down to prevent clicks and pops. It may take several
+ * buffers of audio before the audio is muted.
+ *
+ * Inputs:
+ * psEASData - pointer to overall EAS data structure
+ * handle - file or stream handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_Pause (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream)
+{
+ S_FILE_PARSER_INTERFACE *pParserModule;
+ EAS_STATE state;
+ EAS_RESULT result;
+
+ pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule;
+ if (pParserModule == NULL)
+ return EAS_ERROR_FEATURE_NOT_AVAILABLE;
+
+ /* check for valid state */
+ result = pParserModule->pfState(pEASData, pStream->handle, &state);
+ if (result == EAS_SUCCESS)
+ {
+ if ((state != EAS_STATE_PLAY) && (state != EAS_STATE_READY) && ((pStream->streamFlags & STREAM_FLAGS_RESUME) == 0))
+ return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
+
+ /* make sure parser implements pause */
+ if (pParserModule->pfPause == NULL)
+ result = EAS_ERROR_NOT_IMPLEMENTED;
+
+ /* clear resume flag */
+ pStream->streamFlags &= ~STREAM_FLAGS_RESUME;
+
+ /* set pause flag */
+ pStream->streamFlags |= STREAM_FLAGS_PAUSE;
+
+#if 0
+ /* pause the stream */
+ if (pParserModule->pfPause)
+ result = pParserModule->pfPause(pEASData, pStream->handle);
+ else
+ result = EAS_ERROR_NOT_IMPLEMENTED;
+#endif
+ }
+
+ return result;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_Resume()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Resumes the playback of the data associated with this handle. The audio
+ * is gracefully ramped up to prevent clicks and pops.
+ *
+ * Inputs:
+ * psEASData - pointer to overall EAS data structure
+ * handle - file or stream handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_Resume (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream)
+{
+ S_FILE_PARSER_INTERFACE *pParserModule;
+ EAS_STATE state;
+ EAS_RESULT result;
+
+ pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule;
+ if (pParserModule == NULL)
+ return EAS_ERROR_FEATURE_NOT_AVAILABLE;
+
+ /* check for valid state */
+ result = pParserModule->pfState(pEASData, pStream->handle, &state);
+ if (result == EAS_SUCCESS)
+ {
+ if ((state != EAS_STATE_PAUSED) && (state != EAS_STATE_PAUSING) && ((pStream->streamFlags & STREAM_FLAGS_PAUSE) == 0))
+ return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
+
+ /* make sure parser implements this function */
+ if (pParserModule->pfResume == NULL)
+ result = EAS_ERROR_NOT_IMPLEMENTED;
+
+ /* clear pause flag */
+ pStream->streamFlags &= ~STREAM_FLAGS_PAUSE;
+
+ /* set resume flag */
+ pStream->streamFlags |= STREAM_FLAGS_RESUME;
+
+#if 0
+ /* resume the stream */
+ if (pParserModule->pfResume)
+ result = pParserModule->pfResume(pEASData, pStream->handle);
+ else
+ result = EAS_ERROR_NOT_IMPLEMENTED;
+#endif
+ }
+
+ return result;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_GetParameter()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Set the parameter of a module. See E_MODULES for a list of modules
+ * and the header files of the modules for a list of parameters.
+ *
+ * Inputs:
+ * psEASData - pointer to overall EAS data structure
+ * handle - file or stream handle
+ * module - enumerated module number
+ * param - enumerated parameter number
+ * pValue - pointer to variable to receive parameter value
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_GetParameter (EAS_DATA_HANDLE pEASData, EAS_I32 module, EAS_I32 param, EAS_I32 *pValue)
+{
+
+ if (module >= NUM_EFFECTS_MODULES)
+ return EAS_ERROR_INVALID_MODULE;
+
+ if (pEASData->effectsModules[module].effectData == NULL)
+ return EAS_ERROR_INVALID_MODULE;
+
+ return (*pEASData->effectsModules[module].effect->pFGetParam)
+ (pEASData->effectsModules[module].effectData, param, pValue);
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_SetParameter()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Set the parameter of a module. See E_MODULES for a list of modules
+ * and the header files of the modules for a list of parameters.
+ *
+ * Inputs:
+ * psEASData - pointer to overall EAS data structure
+ * handle - file or stream handle
+ * module - enumerated module number
+ * param - enumerated parameter number
+ * value - new parameter value
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_SetParameter (EAS_DATA_HANDLE pEASData, EAS_I32 module, EAS_I32 param, EAS_I32 value)
+{
+
+ if (module >= NUM_EFFECTS_MODULES)
+ return EAS_ERROR_INVALID_MODULE;
+
+ if (pEASData->effectsModules[module].effectData == NULL)
+ return EAS_ERROR_INVALID_MODULE;
+
+ return (*pEASData->effectsModules[module].effect->pFSetParam)
+ (pEASData->effectsModules[module].effectData, param, value);
+}
+
+#ifdef _METRICS_ENABLED
+/*----------------------------------------------------------------------------
+ * EAS_MetricsReport()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Displays the current metrics through the metrics interface.
+ *
+ * Inputs:
+ * p - instance data handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_MetricsReport (EAS_DATA_HANDLE pEASData)
+{
+ if (!pEASData->pMetricsModule)
+ return EAS_ERROR_INVALID_MODULE;
+
+ return (*pEASData->pMetricsModule->pfReport)(pEASData->pMetricsData);
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_MetricsReset()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Resets the metrics.
+ *
+ * Inputs:
+ * p - instance data handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_MetricsReset (EAS_DATA_HANDLE pEASData)
+{
+
+ if (!pEASData->pMetricsModule)
+ return EAS_ERROR_INVALID_MODULE;
+
+ return (*pEASData->pMetricsModule->pfReset)(pEASData->pMetricsData);
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ * EAS_SetSoundLibrary()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Sets the location of the sound library.
+ *
+ * Inputs:
+ * pEASData - instance data handle
+ * pSoundLib - pointer to sound library
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_SetSoundLibrary (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_SNDLIB_HANDLE pSndLib)
+{
+ if (pStream)
+ {
+ if (!EAS_StreamReady(pEASData, pStream))
+ return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
+ return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_EAS_LIBRARY, (EAS_I32) pSndLib);
+ }
+
+ return VMSetGlobalEASLib(pEASData->pVoiceMgr, pSndLib);
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_SetHeaderSearchFlag()
+ *----------------------------------------------------------------------------
+ * By default, when EAS_OpenFile is called, the parsers check the
+ * first few bytes of the file looking for a specific header. Some
+ * mobile devices may add a header to the start of a file, which
+ * will prevent the parser from recognizing the file. If the
+ * searchFlag is set to EAS_TRUE, the parser will search the entire
+ * file looking for the header. This may enable EAS to recognize
+ * some files that it would ordinarily reject. The negative is that
+ * it make take slightly longer to process the EAS_OpenFile request.
+ *
+ * Inputs:
+ * pEASData - instance data handle
+ * searchFlag - search flag (EAS_TRUE or EAS_FALSE)
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_SetHeaderSearchFlag (EAS_DATA_HANDLE pEASData, EAS_BOOL searchFlag)
+{
+ pEASData->searchHeaderFlag = (EAS_BOOL8) searchFlag;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_SetPlayMode()
+ *----------------------------------------------------------------------------
+ * Some file formats support special play modes, such as iMode partial
+ * play mode. This call can be used to change the play mode. The
+ * default play mode (usually straight playback) is always zero.
+ *
+ * Inputs:
+ * pEASData - instance data handle
+ * handle - file or stream handle
+ * playMode - play mode (see file parser for specifics)
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_SetPlayMode (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 playMode)
+{
+ return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_PLAY_MODE, playMode);
+}
+
+#ifdef DLS_SYNTHESIZER
+/*----------------------------------------------------------------------------
+ * EAS_LoadDLSCollection()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Sets the location of the sound library.
+ *
+ * Inputs:
+ * pEASData - instance data handle
+ * pSoundLib - pointer to sound library
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_LoadDLSCollection (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_FILE_LOCATOR locator)
+{
+ EAS_FILE_HANDLE fileHandle;
+ EAS_RESULT result;
+ EAS_DLSLIB_HANDLE pDLS;
+
+ if (pStream != NULL)
+ {
+ if (!EAS_StreamReady(pEASData, pStream))
+ return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
+ }
+
+ /* open the file */
+ if ((result = EAS_HWOpenFile(pEASData->hwInstData, locator, &fileHandle, EAS_FILE_READ)) != EAS_SUCCESS)
+ return result;
+
+ /* parse the file */
+ result = DLSParser(pEASData->hwInstData, fileHandle, 0, &pDLS);
+ EAS_HWCloseFile(pEASData->hwInstData, fileHandle);
+
+ if (result == EAS_SUCCESS)
+ {
+
+ /* if a stream pStream is specified, point it to the DLS collection */
+ if (pStream)
+ result = EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_DLS_COLLECTION, (EAS_I32) pDLS);
+
+ /* global DLS load */
+ else
+ result = VMSetGlobalDLSLib(pEASData, pDLS);
+ }
+
+ return result;
+}
+#endif
+
+#ifdef EXTERNAL_AUDIO
+/*----------------------------------------------------------------------------
+ * EAS_RegExtAudioCallback()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Registers callback functions for audio events.
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - file or stream handle
+ * cbProgChgFunc - pointer to host callback function for program change
+ * cbEventFunc - pointer to host callback functio for note events
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_RegExtAudioCallback (EAS_DATA_HANDLE pEASData,
+ EAS_HANDLE pStream,
+ EAS_VOID_PTR pInstData,
+ EAS_EXT_PRG_CHG_FUNC cbProgChgFunc,
+ EAS_EXT_EVENT_FUNC cbEventFunc)
+{
+ S_SYNTH *pSynth;
+
+ if (!EAS_StreamReady(pEASData, pStream))
+ return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
+
+ if (EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_SYNTH_HANDLE, (EAS_I32*) &pSynth) != EAS_SUCCESS)
+ return EAS_ERROR_INVALID_PARAMETER;
+
+ if (pSynth == NULL)
+ return EAS_ERROR_INVALID_PARAMETER;
+
+ VMRegExtAudioCallback(pSynth, pInstData, cbProgChgFunc, cbEventFunc);
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_GetMIDIControllers()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Returns the current state of MIDI controllers on the requested channel.
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - file or stream handle
+ * pControl - pointer to structure to receive data
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_GetMIDIControllers (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_U8 channel, S_MIDI_CONTROLLERS *pControl)
+{
+ S_SYNTH *pSynth;
+
+ if (!EAS_StreamReady(pEASData, pStream))
+ return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
+
+ if (EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_SYNTH_HANDLE, (EAS_I32*) &pSynth) != EAS_SUCCESS)
+ return EAS_ERROR_INVALID_PARAMETER;
+
+ if (pSynth == NULL)
+ return EAS_ERROR_INVALID_PARAMETER;
+
+ VMGetMIDIControllers(pSynth, channel, pControl);
+ return EAS_SUCCESS;
+}
+#endif
+
+#ifdef _SPLIT_ARCHITECTURE
+/*----------------------------------------------------------------------------
+ * EAS_SetFrameBuffer()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Sets the frame buffer pointer passed to the IPC communications functions
+ *
+ * Inputs:
+ * pEASData - instance data handle
+ * locator - file locator
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ * May overlay instruments in the GM sound set
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_SetFrameBuffer (EAS_DATA_HANDLE pEASData, EAS_FRAME_BUFFER_HANDLE pFrameBuffer)
+{
+ if (pEASData->pVoiceMgr)
+ pEASData->pVoiceMgr->pFrameBuffer = pFrameBuffer;
+ return EAS_SUCCESS;
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ * EAS_SearchFile
+ *----------------------------------------------------------------------------
+ * Search file for specific sequence starting at current file
+ * position. Returns offset to start of sequence.
+ *
+ * Inputs:
+ * pEASData - pointer to EAS persistent data object
+ * fileHandle - file handle
+ * searchString - pointer to search sequence
+ * len - length of search sequence
+ * pOffset - pointer to variable to store offset to sequence
+ *
+ * Returns EAS_EOF if end-of-file is reached
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_SearchFile (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, const EAS_U8 *searchString, EAS_I32 len, EAS_I32 *pOffset)
+{
+ EAS_RESULT result;
+ EAS_INT index;
+ EAS_U8 c;
+
+ *pOffset = -1;
+ index = 0;
+ for (;;)
+ {
+ result = EAS_HWGetByte(pEASData->hwInstData, fileHandle, &c);
+ if (result != EAS_SUCCESS)
+ return result;
+ if (c == searchString[index])
+ {
+ index++;
+ if (index == 4)
+ {
+ result = EAS_HWFilePos(pEASData->hwInstData, fileHandle, pOffset);
+ if (result != EAS_SUCCESS)
+ return result;
+ *pOffset -= len;
+ break;
+ }
+ }
+ else
+ index = 0;
+ }
+ return EAS_SUCCESS;
+}
+
+
diff --git a/arm-wt-22k/lib_src/eas_reverb.c b/arm-wt-22k/lib_src/eas_reverb.c
new file mode 100644
index 0000000..6d99862
--- /dev/null
+++ b/arm-wt-22k/lib_src/eas_reverb.c
@@ -0,0 +1,1154 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_reverb.c
+ *
+ * Contents and purpose:
+ * Contains the implementation of the Reverb effect.
+ *
+ *
+ * Copyright Sonic Network Inc. 2006
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 510 $
+ * $Date: 2006-12-19 01:47:33 -0800 (Tue, 19 Dec 2006) $
+ *----------------------------------------------------------------------------
+*/
+
+/*------------------------------------
+ * includes
+ *------------------------------------
+*/
+
+#include "eas_data.h"
+#include "eas_effects.h"
+#include "eas_math.h"
+#include "eas_reverbdata.h"
+#include "eas_reverb.h"
+#include "eas_config.h"
+#include "eas_host.h"
+#include "eas_report.h"
+
+/* prototypes for effects interface */
+static EAS_RESULT ReverbInit (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData);
+static void ReverbProcess (EAS_VOID_PTR pInstData, EAS_PCM *pSrc, EAS_PCM *pDst, EAS_I32 numSamples);
+static EAS_RESULT ReverbShutdown (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData);
+static EAS_RESULT ReverbGetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue);
+static EAS_RESULT ReverbSetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value);
+
+/* common effects interface for configuration module */
+const S_EFFECTS_INTERFACE EAS_Reverb =
+{
+ ReverbInit,
+ ReverbProcess,
+ ReverbShutdown,
+ ReverbGetParam,
+ ReverbSetParam
+};
+
+
+
+/*----------------------------------------------------------------------------
+ * InitializeReverb()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT ReverbInit(EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData)
+{
+ EAS_I32 i;
+ EAS_U16 nOffset;
+ EAS_INT temp;
+
+ S_REVERB_OBJECT *pReverbData;
+ S_REVERB_PRESET *pPreset;
+
+ /* check Configuration Module for data allocation */
+ if (pEASData->staticMemoryModel)
+ pReverbData = EAS_CMEnumFXData(EAS_MODULE_REVERB);
+
+ /* allocate dynamic memory */
+ else
+ pReverbData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_REVERB_OBJECT));
+
+ if (pReverbData == NULL)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate Reverb memory\n"); */ }
+ return EAS_ERROR_MALLOC_FAILED;
+ }
+
+ /* clear the structure */
+ EAS_HWMemSet(pReverbData, 0, sizeof(S_REVERB_OBJECT));
+
+ ReverbReadInPresets(pReverbData);
+
+ pReverbData->m_nMinSamplesToAdd = REVERB_UPDATE_PERIOD_IN_SAMPLES;
+
+ pReverbData->m_nRevOutFbkR = 0;
+ pReverbData->m_nRevOutFbkL = 0;
+
+ pReverbData->m_sAp0.m_zApIn = AP0_IN;
+ pReverbData->m_sAp0.m_zApOut = AP0_IN + DEFAULT_AP0_LENGTH;
+ pReverbData->m_sAp0.m_nApGain = DEFAULT_AP0_GAIN;
+
+ pReverbData->m_zD0In = DELAY0_IN;
+
+ pReverbData->m_sAp1.m_zApIn = AP1_IN;
+ pReverbData->m_sAp1.m_zApOut = AP1_IN + DEFAULT_AP1_LENGTH;
+ pReverbData->m_sAp1.m_nApGain = DEFAULT_AP1_GAIN;
+
+ pReverbData->m_zD1In = DELAY1_IN;
+
+ pReverbData->m_zLpf0 = 0;
+ pReverbData->m_zLpf1 = 0;
+ pReverbData->m_nLpfFwd = 8837;
+ pReverbData->m_nLpfFbk = 6494;
+
+ pReverbData->m_nSin = 0;
+ pReverbData->m_nCos = 0;
+ pReverbData->m_nSinIncrement = 0;
+ pReverbData->m_nCosIncrement = 0;
+
+ // set xfade parameters
+ pReverbData->m_nXfadeInterval = (EAS_U16)REVERB_XFADE_PERIOD_IN_SAMPLES;
+ pReverbData->m_nXfadeCounter = pReverbData->m_nXfadeInterval + 1; // force update on first iteration
+ pReverbData->m_nPhase = -32768;
+ pReverbData->m_nPhaseIncrement = REVERB_XFADE_PHASE_INCREMENT;
+
+ pReverbData->m_nNoise = (EAS_I16)0xABCD;
+
+ pReverbData->m_nMaxExcursion = 0x007F;
+
+ // set delay tap lengths
+ nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion,
+ &pReverbData->m_nNoise );
+
+ pReverbData->m_zD1Cross =
+ DELAY1_OUT - pReverbData->m_nMaxExcursion + nOffset;
+
+ nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion,
+ &pReverbData->m_nNoise );
+
+ pReverbData->m_zD0Cross =
+ DELAY1_OUT - pReverbData->m_nMaxExcursion - nOffset;
+
+ nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion,
+ &pReverbData->m_nNoise );
+
+ pReverbData->m_zD0Self =
+ DELAY0_OUT - pReverbData->m_nMaxExcursion - nOffset;
+
+ nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion,
+ &pReverbData->m_nNoise );
+
+ pReverbData->m_zD1Self =
+ DELAY1_OUT - pReverbData->m_nMaxExcursion + nOffset;
+
+ // for debugging purposes, allow noise generator
+ pReverbData->m_bUseNoise = EAS_FALSE;
+
+ // for debugging purposes, allow bypass
+ pReverbData->m_bBypass = EAS_TRUE; //EAS_FALSE;
+
+ pReverbData->m_nNextRoom = 1;
+
+ pReverbData->m_nCurrentRoom = pReverbData->m_nNextRoom + 1; // force update on first iteration
+
+ pReverbData->m_nWet = REVERB_DEFAULT_WET;
+
+ pReverbData->m_nDry = REVERB_DEFAULT_DRY;
+
+ // set base index into circular buffer
+ pReverbData->m_nBaseIndex = 0;
+
+ // set the early reflections, L
+ pReverbData->m_sEarlyL.m_nLpfFbk = 4915;
+ pReverbData->m_sEarlyL.m_nLpfFwd = 27852;
+ pReverbData->m_sEarlyL.m_zLpf = 0;
+
+ for (i=0; i < REVERB_MAX_NUM_REFLECTIONS; i++)
+ {
+ pReverbData->m_sEarlyL.m_nGain[i] = 0;
+ pReverbData->m_sEarlyL.m_zDelay[i] = 0;
+ }
+
+ // set the early reflections, R
+ pReverbData->m_sEarlyR.m_nLpfFbk = 4915;
+ pReverbData->m_sEarlyR.m_nLpfFwd = 27852;
+ pReverbData->m_sEarlyR.m_zLpf = 0;
+
+ for (i=0; i < REVERB_MAX_NUM_REFLECTIONS; i++)
+ {
+ pReverbData->m_sEarlyR.m_nGain[i] = 0;
+ pReverbData->m_sEarlyR.m_zDelay[i] = 0;
+ }
+
+ // clear the reverb delay line
+ for (i=0; i < REVERB_BUFFER_SIZE_IN_SAMPLES; i++)
+ {
+ pReverbData->m_nDelayLine[i] = 0;
+ }
+
+ ////////////////////////////////
+ ///code from the EAS DEMO Reverb
+ //now copy from the new preset into the reverb
+ pPreset = &pReverbData->m_sPreset.m_sPreset[pReverbData->m_nNextRoom];
+
+ pReverbData->m_nLpfFbk = pPreset->m_nLpfFbk;
+ pReverbData->m_nLpfFwd = pPreset->m_nLpfFwd;
+
+ pReverbData->m_nEarly = pPreset->m_nEarly;
+ pReverbData->m_nWet = pPreset->m_nWet;
+ pReverbData->m_nDry = pPreset->m_nDry;
+
+ pReverbData->m_nMaxExcursion = pPreset->m_nMaxExcursion;
+ //stored as time based, convert to sample based
+ temp = pPreset->m_nXfadeInterval;
+ /*lint -e{702} shift for performance */
+ temp = (temp * _OUTPUT_SAMPLE_RATE) >> 16;
+ pReverbData->m_nXfadeInterval = (EAS_U16) temp;
+ //gsReverbObject.m_nXfadeInterval = pPreset->m_nXfadeInterval;
+
+ pReverbData->m_sAp0.m_nApGain = pPreset->m_nAp0_ApGain;
+ //stored as time based, convert to absolute sample value
+ temp = pPreset->m_nAp0_ApOut;
+ /*lint -e{702} shift for performance */
+ temp = (temp * _OUTPUT_SAMPLE_RATE) >> 16;
+ pReverbData->m_sAp0.m_zApOut = (EAS_U16) (pReverbData->m_sAp0.m_zApIn + temp);
+ //gsReverbObject.m_sAp0.m_zApOut = pPreset->m_nAp0_ApOut;
+
+ pReverbData->m_sAp1.m_nApGain = pPreset->m_nAp1_ApGain;
+ //stored as time based, convert to absolute sample value
+ temp = pPreset->m_nAp1_ApOut;
+ /*lint -e{702} shift for performance */
+ temp = (temp * _OUTPUT_SAMPLE_RATE) >> 16;
+ pReverbData->m_sAp1.m_zApOut = (EAS_U16) (pReverbData->m_sAp1.m_zApIn + temp);
+ //gsReverbObject.m_sAp1.m_zApOut = pPreset->m_nAp1_ApOut;
+ ///code from the EAS DEMO Reverb
+ ////////////////////////////////
+
+ *pInstData = pReverbData;
+
+ return EAS_SUCCESS;
+
+} /* end InitializeReverb */
+
+
+
+/*----------------------------------------------------------------------------
+ * ReverbProcess()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Reverberate the requested number of samples (block based processing)
+ *
+ * Inputs:
+ * pInputBuffer - src buffer
+ * pOutputBuffer - dst buffer
+ * nNumSamplesToAdd - number of samples to write to buffer
+ *
+ * Outputs:
+ * number of samples actually written to buffer
+ *
+ * Side Effects:
+ * - samples are added to the presently free buffer
+ *
+ *----------------------------------------------------------------------------
+*/
+static void ReverbProcess(EAS_VOID_PTR pInstData, EAS_PCM *pSrc, EAS_PCM *pDst, EAS_I32 numSamples)
+{
+ S_REVERB_OBJECT *pReverbData;
+
+ pReverbData = (S_REVERB_OBJECT*) pInstData;
+
+ //if bypassed or the preset forces the signal to be completely dry
+ if (pReverbData->m_bBypass ||
+ (pReverbData->m_nWet == 0 && pReverbData->m_nDry == 32767))
+ {
+ if (pSrc != pDst)
+ EAS_HWMemCpy(pSrc, pDst, numSamples * NUM_OUTPUT_CHANNELS * (EAS_I32) sizeof(EAS_PCM));
+ return;
+ }
+
+ if (pReverbData->m_nNextRoom != pReverbData->m_nCurrentRoom)
+ {
+ ReverbUpdateRoom(pReverbData);
+ }
+
+ ReverbUpdateXfade(pReverbData, numSamples);
+
+ Reverb(pReverbData, numSamples, pDst, pSrc);
+
+ /* check if update counter needs to be reset */
+ if (pReverbData->m_nUpdateCounter >= REVERB_MODULO_UPDATE_PERIOD_IN_SAMPLES)
+ {
+ /* update interval has elapsed, so reset counter */
+ pReverbData->m_nUpdateCounter = 0;
+ } /* end if m_nUpdateCounter >= update interval */
+
+ /* increment update counter */
+ pReverbData->m_nUpdateCounter += (EAS_I16)numSamples;
+
+} /* end ComputeReverb */
+
+/*----------------------------------------------------------------------------
+ * ReverbUpdateXfade
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Update the xfade parameters as required
+ *
+ * Inputs:
+ * nNumSamplesToAdd - number of samples to write to buffer
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ * - xfade parameters will be changed
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT ReverbUpdateXfade(S_REVERB_OBJECT *pReverbData, EAS_INT nNumSamplesToAdd)
+{
+ EAS_U16 nOffset;
+ EAS_I16 tempCos;
+ EAS_I16 tempSin;
+
+ if (pReverbData->m_nXfadeCounter >= pReverbData->m_nXfadeInterval)
+ {
+ /* update interval has elapsed, so reset counter */
+ pReverbData->m_nXfadeCounter = 0;
+
+ // Pin the sin,cos values to min / max values to ensure that the
+ // modulated taps' coefs are zero (thus no clicks)
+ if (pReverbData->m_nPhaseIncrement > 0)
+ {
+ // if phase increment > 0, then sin -> 1, cos -> 0
+ pReverbData->m_nSin = 32767;
+ pReverbData->m_nCos = 0;
+
+ // reset the phase to match the sin, cos values
+ pReverbData->m_nPhase = 32767;
+
+ // modulate the cross taps because their tap coefs are zero
+ nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, &pReverbData->m_nNoise );
+
+ pReverbData->m_zD1Cross =
+ DELAY1_OUT - pReverbData->m_nMaxExcursion + nOffset;
+
+ nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, &pReverbData->m_nNoise );
+
+ pReverbData->m_zD0Cross =
+ DELAY0_OUT - pReverbData->m_nMaxExcursion - nOffset;
+ }
+ else
+ {
+ // if phase increment < 0, then sin -> 0, cos -> 1
+ pReverbData->m_nSin = 0;
+ pReverbData->m_nCos = 32767;
+
+ // reset the phase to match the sin, cos values
+ pReverbData->m_nPhase = -32768;
+
+ // modulate the self taps because their tap coefs are zero
+ nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, &pReverbData->m_nNoise );
+
+ pReverbData->m_zD0Self =
+ DELAY0_OUT - pReverbData->m_nMaxExcursion - nOffset;
+
+ nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, &pReverbData->m_nNoise );
+
+ pReverbData->m_zD1Self =
+ DELAY1_OUT - pReverbData->m_nMaxExcursion + nOffset;
+
+ } // end if-else (pReverbData->m_nPhaseIncrement > 0)
+
+ // Reverse the direction of the sin,cos so that the
+ // tap whose coef was previously increasing now decreases
+ // and vice versa
+ pReverbData->m_nPhaseIncrement = -pReverbData->m_nPhaseIncrement;
+
+ } // end if counter >= update interval
+
+ //compute what phase will be next time
+ pReverbData->m_nPhase += pReverbData->m_nPhaseIncrement;
+
+ //calculate what the new sin and cos need to reach by the next update
+ ReverbCalculateSinCos(pReverbData->m_nPhase, &tempSin, &tempCos);
+
+ //calculate the per-sample increment required to get there by the next update
+ /*lint -e{702} shift for performance */
+ pReverbData->m_nSinIncrement =
+ (tempSin - pReverbData->m_nSin) >> REVERB_UPDATE_PERIOD_IN_BITS;
+
+ /*lint -e{702} shift for performance */
+ pReverbData->m_nCosIncrement =
+ (tempCos - pReverbData->m_nCos) >> REVERB_UPDATE_PERIOD_IN_BITS;
+
+
+ /* increment update counter */
+ pReverbData->m_nXfadeCounter += (EAS_U16) nNumSamplesToAdd;
+
+ return EAS_SUCCESS;
+
+} /* end ReverbUpdateXfade */
+
+
+/*----------------------------------------------------------------------------
+ * ReverbCalculateNoise
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Calculate a noise sample and limit its value
+ *
+ * Inputs:
+ * nMaxExcursion - noise value is limited to this value
+ * pnNoise - return new noise sample in this (not limited)
+ *
+ * Outputs:
+ * new limited noise value
+ *
+ * Side Effects:
+ * - *pnNoise noise value is updated
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_U16 ReverbCalculateNoise(EAS_U16 nMaxExcursion, EAS_I16 *pnNoise)
+{
+ // calculate new noise value
+ *pnNoise = (EAS_I16) (*pnNoise * 5 + 1);
+
+#if 0 // 1xxx, test
+ *pnNoise = 0;
+#endif // 1xxx, test
+
+ // return the limited noise value
+ return (nMaxExcursion & (*pnNoise));
+
+} /* end ReverbCalculateNoise */
+
+/*----------------------------------------------------------------------------
+ * ReverbCalculateSinCos
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Calculate a new sin and cosine value based on the given phase
+ *
+ * Inputs:
+ * nPhase - phase angle
+ * pnSin - input old value, output new value
+ * pnCos - input old value, output new value
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ * - *pnSin, *pnCos are updated
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT ReverbCalculateSinCos(EAS_I16 nPhase, EAS_I16 *pnSin, EAS_I16 *pnCos)
+{
+ EAS_I32 nTemp;
+ EAS_I32 nNetAngle;
+
+ // -1 <= nPhase < 1
+ // However, for the calculation, we need a value
+ // that ranges from -1/2 to +1/2, so divide the phase by 2
+ /*lint -e{702} shift for performance */
+ nNetAngle = nPhase >> 1;
+
+ /*
+ Implement the following
+ sin(x) = (2-4*c)*x^2 + c + x
+ cos(x) = (2-4*c)*x^2 + c - x
+
+ where c = 1/sqrt(2)
+ using the a0 + x*(a1 + x*a2) approach
+ */
+
+ /* limit the input "angle" to be between -0.5 and +0.5 */
+ if (nNetAngle > EG1_HALF)
+ {
+ nNetAngle = EG1_HALF;
+ }
+ else if (nNetAngle < EG1_MINUS_HALF)
+ {
+ nNetAngle = EG1_MINUS_HALF;
+ }
+
+ /* calculate sin */
+ nTemp = EG1_ONE + MULT_EG1_EG1(REVERB_PAN_G2, nNetAngle);
+ nTemp = REVERB_PAN_G0 + MULT_EG1_EG1(nTemp, nNetAngle);
+ *pnSin = (EAS_I16) SATURATE_EG1(nTemp);
+
+ /* calculate cos */
+ nTemp = -EG1_ONE + MULT_EG1_EG1(REVERB_PAN_G2, nNetAngle);
+ nTemp = REVERB_PAN_G0 + MULT_EG1_EG1(nTemp, nNetAngle);
+ *pnCos = (EAS_I16) SATURATE_EG1(nTemp);
+
+ return EAS_SUCCESS;
+} /* end ReverbCalculateSinCos */
+
+/*----------------------------------------------------------------------------
+ * Reverb
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * apply reverb to the given signal
+ *
+ * Inputs:
+ * nNu
+ * pnSin - input old value, output new value
+ * pnCos - input old value, output new value
+ *
+ * Outputs:
+ * number of samples actually reverberated
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT Reverb(S_REVERB_OBJECT *pReverbData, EAS_INT nNumSamplesToAdd, EAS_PCM *pOutputBuffer, EAS_PCM *pInputBuffer)
+{
+ EAS_I32 i;
+ EAS_I32 nDelayOut;
+ EAS_U16 nBase;
+
+ EAS_U32 nAddr;
+ EAS_I32 nTemp1;
+ EAS_I32 nTemp2;
+ EAS_I32 nApIn;
+ EAS_I32 nApOut;
+
+ EAS_I32 j;
+ EAS_I32 nEarlyOut;
+
+ EAS_I32 tempValue;
+
+
+ // get the base address
+ nBase = pReverbData->m_nBaseIndex;
+
+ for (i=0; i < nNumSamplesToAdd; i++)
+ {
+ // ********** Left Allpass - start
+ // left input = (left dry/4) + right feedback from previous period
+ /*lint -e{702} use shift for performance */
+ nApIn = ((*pInputBuffer++)>>2) + pReverbData->m_nRevOutFbkR;
+// nApIn = *pInputBuffer++; // 1xxx test and debug ap
+
+ // fetch allpass delay line out
+ //nAddr = CIRCULAR(nBase, psAp0->m_zApOut, REVERB_BUFFER_MASK);
+ nAddr = CIRCULAR(nBase, pReverbData->m_sAp0.m_zApOut, REVERB_BUFFER_MASK);
+ nDelayOut = pReverbData->m_nDelayLine[nAddr];
+
+ // calculate allpass feedforward; subtract the feedforward result
+ nTemp1 = MULT_EG1_EG1(nApIn, pReverbData->m_sAp0.m_nApGain);
+ nApOut = SATURATE(nDelayOut - nTemp1); // allpass output
+
+ // calculate allpass feedback; add the feedback result
+ nTemp1 = MULT_EG1_EG1(nApOut, pReverbData->m_sAp0.m_nApGain);
+ nTemp1 = SATURATE(nApIn + nTemp1);
+
+ // inject into allpass delay
+ nAddr = CIRCULAR(nBase, pReverbData->m_sAp0.m_zApIn, REVERB_BUFFER_MASK);
+ pReverbData->m_nDelayLine[nAddr] = (EAS_PCM) nTemp1;
+
+ // inject allpass output into delay line
+ nAddr = CIRCULAR(nBase, pReverbData->m_zD0In, REVERB_BUFFER_MASK);
+ pReverbData->m_nDelayLine[nAddr] = (EAS_PCM) nApOut;
+
+ // ********** Left Allpass - end
+
+ // ********** Right Allpass - start
+ // right input = (right dry/4) + left feedback from previous period
+ /*lint -e{702} use shift for performance */
+ nApIn = ((*pInputBuffer++)>>2) + pReverbData->m_nRevOutFbkL;
+// nApIn = *pInputBuffer++; // 1xxx test and debug ap
+
+ // fetch allpass delay line out
+ nAddr = CIRCULAR(nBase, pReverbData->m_sAp1.m_zApOut, REVERB_BUFFER_MASK);
+ nDelayOut = pReverbData->m_nDelayLine[nAddr];
+
+ // calculate allpass feedforward; subtract the feedforward result
+ nTemp1 = MULT_EG1_EG1(nApIn, pReverbData->m_sAp1.m_nApGain);
+ nApOut = SATURATE(nDelayOut - nTemp1); // allpass output
+
+ // calculate allpass feedback; add the feedback result
+ nTemp1 = MULT_EG1_EG1(nApOut, pReverbData->m_sAp1.m_nApGain);
+ nTemp1 = SATURATE(nApIn + nTemp1);
+
+ // inject into allpass delay
+ nAddr = CIRCULAR(nBase, pReverbData->m_sAp1.m_zApIn, REVERB_BUFFER_MASK);
+ pReverbData->m_nDelayLine[nAddr] = (EAS_PCM) nTemp1;
+
+ // inject allpass output into delay line
+ nAddr = CIRCULAR(nBase, pReverbData->m_zD1In, REVERB_BUFFER_MASK);
+ pReverbData->m_nDelayLine[nAddr] = (EAS_PCM) nApOut;
+
+ // ********** Right Allpass - end
+
+ // ********** D0 output - start
+ // fetch delay line self out
+ nAddr = CIRCULAR(nBase, pReverbData->m_zD0Self, REVERB_BUFFER_MASK);
+ nDelayOut = pReverbData->m_nDelayLine[nAddr];
+
+ // calculate delay line self out
+ nTemp1 = MULT_EG1_EG1(nDelayOut, pReverbData->m_nSin);
+
+ // fetch delay line cross out
+ nAddr = CIRCULAR(nBase, pReverbData->m_zD1Cross, REVERB_BUFFER_MASK);
+ nDelayOut = pReverbData->m_nDelayLine[nAddr];
+
+ // calculate delay line self out
+ nTemp2 = MULT_EG1_EG1(nDelayOut, pReverbData->m_nCos);
+
+ // calculate unfiltered delay out
+ nDelayOut = SATURATE(nTemp1 + nTemp2);
+
+ // calculate lowpass filter (mixer scale factor included in LPF feedforward)
+ nTemp1 = MULT_EG1_EG1(nDelayOut, pReverbData->m_nLpfFwd);
+
+ nTemp2 = MULT_EG1_EG1(pReverbData->m_zLpf0, pReverbData->m_nLpfFbk);
+
+ // calculate filtered delay out and simultaneously update LPF state variable
+ // filtered delay output is stored in m_zLpf0
+ pReverbData->m_zLpf0 = (EAS_PCM) SATURATE(nTemp1 + nTemp2);
+
+ // ********** D0 output - end
+
+ // ********** D1 output - start
+ // fetch delay line self out
+ nAddr = CIRCULAR(nBase, pReverbData->m_zD1Self, REVERB_BUFFER_MASK);
+ nDelayOut = pReverbData->m_nDelayLine[nAddr];
+
+ // calculate delay line self out
+ nTemp1 = MULT_EG1_EG1(nDelayOut, pReverbData->m_nSin);
+
+ // fetch delay line cross out
+ nAddr = CIRCULAR(nBase, pReverbData->m_zD0Cross, REVERB_BUFFER_MASK);
+ nDelayOut = pReverbData->m_nDelayLine[nAddr];
+
+ // calculate delay line self out
+ nTemp2 = MULT_EG1_EG1(nDelayOut, pReverbData->m_nCos);
+
+ // calculate unfiltered delay out
+ nDelayOut = SATURATE(nTemp1 + nTemp2);
+
+ // calculate lowpass filter (mixer scale factor included in LPF feedforward)
+ nTemp1 = MULT_EG1_EG1(nDelayOut, pReverbData->m_nLpfFwd);
+
+ nTemp2 = MULT_EG1_EG1(pReverbData->m_zLpf1, pReverbData->m_nLpfFbk);
+
+ // calculate filtered delay out and simultaneously update LPF state variable
+ // filtered delay output is stored in m_zLpf1
+ pReverbData->m_zLpf1 = (EAS_PCM)SATURATE(nTemp1 + nTemp2);
+
+ // ********** D1 output - end
+
+ // ********** mixer and feedback - start
+ // sum is fedback to right input (R + L)
+ pReverbData->m_nRevOutFbkL =
+ (EAS_PCM)SATURATE((EAS_I32)pReverbData->m_zLpf1 + (EAS_I32)pReverbData->m_zLpf0);
+
+ // difference is feedback to left input (R - L)
+ /*lint -e{685} lint complains that it can't saturate negative */
+ pReverbData->m_nRevOutFbkR =
+ (EAS_PCM)SATURATE((EAS_I32)pReverbData->m_zLpf1 - (EAS_I32)pReverbData->m_zLpf0);
+
+ // ********** mixer and feedback - end
+
+ // ********** start early reflection generator, left
+ //psEarly = &(pReverbData->m_sEarlyL);
+
+ nEarlyOut = 0;
+
+ for (j=0; j < REVERB_MAX_NUM_REFLECTIONS; j++)
+ {
+ // fetch delay line out
+ //nAddr = CIRCULAR(nBase, psEarly->m_zDelay[j], REVERB_BUFFER_MASK);
+ nAddr = CIRCULAR(nBase, pReverbData->m_sEarlyL.m_zDelay[j], REVERB_BUFFER_MASK);
+
+ nDelayOut = pReverbData->m_nDelayLine[nAddr];
+
+ // calculate reflection
+ //nTemp1 = MULT_EG1_EG1(nDelayOut, psEarly->m_nGain[j]);
+ nTemp1 = MULT_EG1_EG1(nDelayOut, pReverbData->m_sEarlyL.m_nGain[j]);
+
+ nEarlyOut = SATURATE(nEarlyOut + nTemp1);
+
+ } // end for (j=0; j < REVERB_MAX_NUM_REFLECTIONS; j++)
+
+ // apply lowpass to early reflections
+ //nTemp1 = MULT_EG1_EG1(nEarlyOut, psEarly->m_nLpfFwd);
+ nTemp1 = MULT_EG1_EG1(nEarlyOut, pReverbData->m_sEarlyL.m_nLpfFwd);
+
+ //nTemp2 = MULT_EG1_EG1(psEarly->m_zLpf, psEarly->m_nLpfFbk);
+ nTemp2 = MULT_EG1_EG1(pReverbData->m_sEarlyL.m_zLpf, pReverbData->m_sEarlyL.m_nLpfFbk);
+
+
+ // calculate filtered out and simultaneously update LPF state variable
+ // filtered output is stored in m_zLpf1
+ //psEarly->m_zLpf = SATURATE(nTemp1 + nTemp2);
+ pReverbData->m_sEarlyL.m_zLpf = (EAS_PCM) SATURATE(nTemp1 + nTemp2);
+
+ // combine filtered early and late reflections for output
+ //*pOutputBuffer++ = inL;
+ //tempValue = SATURATE(psEarly->m_zLpf + pReverbData->m_nRevOutFbkL);
+ tempValue = SATURATE((EAS_I32)pReverbData->m_sEarlyL.m_zLpf + (EAS_I32)pReverbData->m_nRevOutFbkL);
+ //scale reverb output by wet level
+ /*lint -e{701} use shift for performance */
+ tempValue = MULT_EG1_EG1(tempValue, (pReverbData->m_nWet<<1));
+ //sum with output buffer
+ tempValue += *pOutputBuffer;
+ *pOutputBuffer++ = (EAS_PCM)SATURATE(tempValue);
+
+ // ********** end early reflection generator, left
+
+ // ********** start early reflection generator, right
+ //psEarly = &(pReverbData->m_sEarlyR);
+
+ nEarlyOut = 0;
+
+ for (j=0; j < REVERB_MAX_NUM_REFLECTIONS; j++)
+ {
+ // fetch delay line out
+ nAddr = CIRCULAR(nBase, pReverbData->m_sEarlyR.m_zDelay[j], REVERB_BUFFER_MASK);
+ nDelayOut = pReverbData->m_nDelayLine[nAddr];
+
+ // calculate reflection
+ nTemp1 = MULT_EG1_EG1(nDelayOut, pReverbData->m_sEarlyR.m_nGain[j]);
+
+ nEarlyOut = SATURATE(nEarlyOut + nTemp1);
+
+ } // end for (j=0; j < REVERB_MAX_NUM_REFLECTIONS; j++)
+
+ // apply lowpass to early reflections
+ nTemp1 = MULT_EG1_EG1(nEarlyOut, pReverbData->m_sEarlyR.m_nLpfFwd);
+
+ nTemp2 = MULT_EG1_EG1(pReverbData->m_sEarlyR.m_zLpf, pReverbData->m_sEarlyR.m_nLpfFbk);
+
+ // calculate filtered out and simultaneously update LPF state variable
+ // filtered output is stored in m_zLpf1
+ pReverbData->m_sEarlyR.m_zLpf = (EAS_PCM)SATURATE(nTemp1 + nTemp2);
+
+ // combine filtered early and late reflections for output
+ //*pOutputBuffer++ = inR;
+ tempValue = SATURATE((EAS_I32)pReverbData->m_sEarlyR.m_zLpf + (EAS_I32)pReverbData->m_nRevOutFbkR);
+ //scale reverb output by wet level
+ /*lint -e{701} use shift for performance */
+ tempValue = MULT_EG1_EG1(tempValue, (pReverbData->m_nWet << 1));
+ //sum with output buffer
+ tempValue = tempValue + *pOutputBuffer;
+ *pOutputBuffer++ = (EAS_PCM)SATURATE(tempValue);
+
+ // ********** end early reflection generator, right
+
+ // decrement base addr for next sample period
+ nBase--;
+
+ pReverbData->m_nSin += pReverbData->m_nSinIncrement;
+ pReverbData->m_nCos += pReverbData->m_nCosIncrement;
+
+ } // end for (i=0; i < nNumSamplesToAdd; i++)
+
+ // store the most up to date version
+ pReverbData->m_nBaseIndex = nBase;
+
+ return EAS_SUCCESS;
+} /* end Reverb */
+
+
+
+/*----------------------------------------------------------------------------
+ * ReverbShutdown()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Initializes the Reverb effect.
+ *
+ * Inputs:
+ * pInstData - handle to instance data
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT ReverbShutdown (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData)
+{
+ /* check Configuration Module for static memory allocation */
+ if (!pEASData->staticMemoryModel)
+ EAS_HWFree(pEASData->hwInstData, pInstData);
+ return EAS_SUCCESS;
+} /* end ReverbShutdown */
+
+/*----------------------------------------------------------------------------
+ * ReverbGetParam()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Get a Reverb parameter
+ *
+ * Inputs:
+ * pInstData - handle to instance data
+ * param - parameter index
+ * *pValue - pointer to variable to hold retrieved value
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT ReverbGetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue)
+{
+ S_REVERB_OBJECT *p;
+
+ p = (S_REVERB_OBJECT*) pInstData;
+
+ switch (param)
+ {
+ case EAS_PARAM_REVERB_BYPASS:
+ *pValue = (EAS_I32) p->m_bBypass;
+ break;
+ case EAS_PARAM_REVERB_PRESET:
+ *pValue = (EAS_I8) p->m_nCurrentRoom;
+ break;
+ case EAS_PARAM_REVERB_WET:
+ *pValue = p->m_nWet;
+ break;
+ case EAS_PARAM_REVERB_DRY:
+ *pValue = p->m_nDry;
+ break;
+ default:
+ return EAS_ERROR_INVALID_PARAMETER;
+ }
+ return EAS_SUCCESS;
+} /* end ReverbGetParam */
+
+
+/*----------------------------------------------------------------------------
+ * ReverbSetParam()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Set a Reverb parameter
+ *
+ * Inputs:
+ * pInstData - handle to instance data
+ * param - parameter index
+ * *pValue - new paramter value
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT ReverbSetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value)
+{
+ S_REVERB_OBJECT *p;
+
+ p = (S_REVERB_OBJECT*) pInstData;
+
+ switch (param)
+ {
+ case EAS_PARAM_REVERB_BYPASS:
+ p->m_bBypass = (EAS_BOOL) value;
+ break;
+ case EAS_PARAM_REVERB_PRESET:
+ if(value!=EAS_PARAM_REVERB_LARGE_HALL && value!=EAS_PARAM_REVERB_HALL &&
+ value!=EAS_PARAM_REVERB_CHAMBER && value!=EAS_PARAM_REVERB_ROOM)
+ return EAS_ERROR_INVALID_PARAMETER;
+ p->m_nNextRoom = (EAS_I16)value;
+ break;
+ case EAS_PARAM_REVERB_WET:
+ if(value>EAS_REVERB_WET_MAX || value<EAS_REVERB_WET_MIN)
+ return EAS_ERROR_INVALID_PARAMETER;
+ p->m_nWet = (EAS_I16)value;
+ break;
+ case EAS_PARAM_REVERB_DRY:
+ if(value>EAS_REVERB_DRY_MAX || value<EAS_REVERB_DRY_MIN)
+ return EAS_ERROR_INVALID_PARAMETER;
+ p->m_nDry = (EAS_I16)value;
+ break;
+ default:
+ return EAS_ERROR_INVALID_PARAMETER;
+ }
+ return EAS_SUCCESS;
+} /* end ReverbSetParam */
+
+
+/*----------------------------------------------------------------------------
+ * ReverbUpdateRoom
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Update the room's preset parameters as required
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ * - reverb paramters (fbk, fwd, etc) will be changed
+ * - m_nCurrentRoom := m_nNextRoom
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT ReverbUpdateRoom(S_REVERB_OBJECT *pReverbData)
+{
+ EAS_INT temp;
+
+ S_REVERB_PRESET *pPreset = &pReverbData->m_sPreset.m_sPreset[pReverbData->m_nNextRoom];
+
+ pReverbData->m_nLpfFwd = pPreset->m_nLpfFwd;
+ pReverbData->m_nLpfFbk = pPreset->m_nLpfFbk;
+
+ pReverbData->m_nEarly = pPreset->m_nEarly;
+ pReverbData->m_nWet = pPreset->m_nWet;
+ pReverbData->m_nDry = pPreset->m_nDry;
+
+
+ pReverbData->m_nMaxExcursion = pPreset->m_nMaxExcursion;
+ //stored as time based, convert to sample based
+ temp = pPreset->m_nXfadeInterval;
+ /*lint -e{702} shift for performance */
+ temp = (temp * _OUTPUT_SAMPLE_RATE) >> 16;
+ pReverbData->m_nXfadeInterval = (EAS_U16) temp;
+ //gpsReverbObject->m_nXfadeInterval = pPreset->m_nXfadeInterval;
+ pReverbData->m_sAp0.m_nApGain = pPreset->m_nAp0_ApGain;
+ //stored as time based, convert to absolute sample value
+ temp = pPreset->m_nAp0_ApOut;
+ /*lint -e{702} shift for performance */
+ temp = (temp * _OUTPUT_SAMPLE_RATE) >> 16;
+ pReverbData->m_sAp0.m_zApOut = (EAS_U16) (pReverbData->m_sAp0.m_zApIn + temp);
+ //gpsReverbObject->m_sAp0.m_zApOut = pPreset->m_nAp0_ApOut;
+ pReverbData->m_sAp1.m_nApGain = pPreset->m_nAp1_ApGain;
+ //stored as time based, convert to absolute sample value
+ temp = pPreset->m_nAp1_ApOut;
+ /*lint -e{702} shift for performance */
+ temp = (temp * _OUTPUT_SAMPLE_RATE) >> 16;
+ pReverbData->m_sAp1.m_zApOut = (EAS_U16) (pReverbData->m_sAp1.m_zApIn + temp);
+ //gpsReverbObject->m_sAp1.m_zApOut = pPreset->m_nAp1_ApOut;
+
+ pReverbData->m_nCurrentRoom = pReverbData->m_nNextRoom;
+
+ return EAS_SUCCESS;
+
+} /* end ReverbUpdateRoom */
+
+
+/*----------------------------------------------------------------------------
+ * ReverbReadInPresets()
+ *----------------------------------------------------------------------------
+ * Purpose: sets global reverb preset bank to defaults
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT ReverbReadInPresets(S_REVERB_OBJECT *pReverbData)
+{
+
+ int preset = 0;
+ int defaultPreset = 0;
+
+ //now init any remaining presets to defaults
+ for (defaultPreset = preset; defaultPreset < REVERB_MAX_ROOM_TYPE; defaultPreset++)
+ {
+ S_REVERB_PRESET *pPreset = &pReverbData->m_sPreset.m_sPreset[defaultPreset];
+ if (defaultPreset == 0 || defaultPreset > REVERB_MAX_ROOM_TYPE-1)
+ {
+ pPreset->m_nLpfFbk = 8307;
+ pPreset->m_nLpfFwd = 14768;
+ pPreset->m_nEarly = 0;
+ pPreset->m_nWet = 27690;
+ pPreset->m_nDry = 32767;
+ pPreset->m_nEarlyL_LpfFbk = 3692;
+ pPreset->m_nEarlyL_LpfFwd = 29075;
+ pPreset->m_nEarlyL_Delay0 = 922;
+ pPreset->m_nEarlyL_Gain0 = 22152;
+ pPreset->m_nEarlyL_Delay1 = 1462;
+ pPreset->m_nEarlyL_Gain1 = 17537;
+ pPreset->m_nEarlyL_Delay2 = 0;
+ pPreset->m_nEarlyL_Gain2 = 14768;
+ pPreset->m_nEarlyL_Delay3 = 1221;
+ pPreset->m_nEarlyL_Gain3 = 14307;
+ pPreset->m_nEarlyL_Delay4 = 0;
+ pPreset->m_nEarlyL_Gain4 = 13384;
+ pPreset->m_nEarlyR_Delay0 = 502;
+ pPreset->m_nEarlyR_Gain0 = 20306;
+ pPreset->m_nEarlyR_Delay1 = 1762;
+ pPreset->m_nEarlyR_Gain1 = 17537;
+ pPreset->m_nEarlyR_Delay2 = 0;
+ pPreset->m_nEarlyR_Gain2 = 14768;
+ pPreset->m_nEarlyR_Delay3 = 0;
+ pPreset->m_nEarlyR_Gain3 = 16153;
+ pPreset->m_nEarlyR_Delay4 = 0;
+ pPreset->m_nEarlyR_Gain4 = 13384;
+ pPreset->m_nMaxExcursion = 127;
+ pPreset->m_nXfadeInterval = 6388;
+ pPreset->m_nAp0_ApGain = 15691;
+ pPreset->m_nAp0_ApOut = 711;
+ pPreset->m_nAp1_ApGain = 17999;
+ pPreset->m_nAp1_ApOut = 1113;
+ pPreset->m_rfu4 = 0;
+ pPreset->m_rfu5 = 0;
+ pPreset->m_rfu6 = 0;
+ pPreset->m_rfu7 = 0;
+ pPreset->m_rfu8 = 0;
+ pPreset->m_rfu9 = 0;
+ pPreset->m_rfu10 = 0;
+ }
+ else if (defaultPreset == 1)
+ {
+ pPreset->m_nLpfFbk = 6461;
+ pPreset->m_nLpfFwd = 14307;
+ pPreset->m_nEarly = 0;
+ pPreset->m_nWet = 27690;
+ pPreset->m_nDry = 32767;
+ pPreset->m_nEarlyL_LpfFbk = 3692;
+ pPreset->m_nEarlyL_LpfFwd = 29075;
+ pPreset->m_nEarlyL_Delay0 = 922;
+ pPreset->m_nEarlyL_Gain0 = 22152;
+ pPreset->m_nEarlyL_Delay1 = 1462;
+ pPreset->m_nEarlyL_Gain1 = 17537;
+ pPreset->m_nEarlyL_Delay2 = 0;
+ pPreset->m_nEarlyL_Gain2 = 14768;
+ pPreset->m_nEarlyL_Delay3 = 1221;
+ pPreset->m_nEarlyL_Gain3 = 14307;
+ pPreset->m_nEarlyL_Delay4 = 0;
+ pPreset->m_nEarlyL_Gain4 = 13384;
+ pPreset->m_nEarlyR_Delay0 = 502;
+ pPreset->m_nEarlyR_Gain0 = 20306;
+ pPreset->m_nEarlyR_Delay1 = 1762;
+ pPreset->m_nEarlyR_Gain1 = 17537;
+ pPreset->m_nEarlyR_Delay2 = 0;
+ pPreset->m_nEarlyR_Gain2 = 14768;
+ pPreset->m_nEarlyR_Delay3 = 0;
+ pPreset->m_nEarlyR_Gain3 = 16153;
+ pPreset->m_nEarlyR_Delay4 = 0;
+ pPreset->m_nEarlyR_Gain4 = 13384;
+ pPreset->m_nMaxExcursion = 127;
+ pPreset->m_nXfadeInterval = 6391;
+ pPreset->m_nAp0_ApGain = 15230;
+ pPreset->m_nAp0_ApOut = 708;
+ pPreset->m_nAp1_ApGain = 9692;
+ pPreset->m_nAp1_ApOut = 1113;
+ pPreset->m_rfu4 = 0;
+ pPreset->m_rfu5 = 0;
+ pPreset->m_rfu6 = 0;
+ pPreset->m_rfu7 = 0;
+ pPreset->m_rfu8 = 0;
+ pPreset->m_rfu9 = 0;
+ pPreset->m_rfu10 = 0;
+ }
+ else if (defaultPreset == 2)
+ {
+ pPreset->m_nLpfFbk = 5077;
+ pPreset->m_nLpfFwd = 12922;
+ pPreset->m_nEarly = 0;
+ pPreset->m_nWet = 24460;
+ pPreset->m_nDry = 32767;
+ pPreset->m_nEarlyL_LpfFbk = 3692;
+ pPreset->m_nEarlyL_LpfFwd = 29075;
+ pPreset->m_nEarlyL_Delay0 = 922;
+ pPreset->m_nEarlyL_Gain0 = 22152;
+ pPreset->m_nEarlyL_Delay1 = 1462;
+ pPreset->m_nEarlyL_Gain1 = 17537;
+ pPreset->m_nEarlyL_Delay2 = 0;
+ pPreset->m_nEarlyL_Gain2 = 14768;
+ pPreset->m_nEarlyL_Delay3 = 1221;
+ pPreset->m_nEarlyL_Gain3 = 14307;
+ pPreset->m_nEarlyL_Delay4 = 0;
+ pPreset->m_nEarlyL_Gain4 = 13384;
+ pPreset->m_nEarlyR_Delay0 = 502;
+ pPreset->m_nEarlyR_Gain0 = 20306;
+ pPreset->m_nEarlyR_Delay1 = 1762;
+ pPreset->m_nEarlyR_Gain1 = 17537;
+ pPreset->m_nEarlyR_Delay2 = 0;
+ pPreset->m_nEarlyR_Gain2 = 14768;
+ pPreset->m_nEarlyR_Delay3 = 0;
+ pPreset->m_nEarlyR_Gain3 = 16153;
+ pPreset->m_nEarlyR_Delay4 = 0;
+ pPreset->m_nEarlyR_Gain4 = 13384;
+ pPreset->m_nMaxExcursion = 127;
+ pPreset->m_nXfadeInterval = 6449;
+ pPreset->m_nAp0_ApGain = 15691;
+ pPreset->m_nAp0_ApOut = 774;
+ pPreset->m_nAp1_ApGain = 15691;
+ pPreset->m_nAp1_ApOut = 1113;
+ pPreset->m_rfu4 = 0;
+ pPreset->m_rfu5 = 0;
+ pPreset->m_rfu6 = 0;
+ pPreset->m_rfu7 = 0;
+ pPreset->m_rfu8 = 0;
+ pPreset->m_rfu9 = 0;
+ pPreset->m_rfu10 = 0;
+ }
+ else if (defaultPreset == 3)
+ {
+ pPreset->m_nLpfFbk = 5077;
+ pPreset->m_nLpfFwd = 11076;
+ pPreset->m_nEarly = 0;
+ pPreset->m_nWet = 23075;
+ pPreset->m_nDry = 32767;
+ pPreset->m_nEarlyL_LpfFbk = 3692;
+ pPreset->m_nEarlyL_LpfFwd = 29075;
+ pPreset->m_nEarlyL_Delay0 = 922;
+ pPreset->m_nEarlyL_Gain0 = 22152;
+ pPreset->m_nEarlyL_Delay1 = 1462;
+ pPreset->m_nEarlyL_Gain1 = 17537;
+ pPreset->m_nEarlyL_Delay2 = 0;
+ pPreset->m_nEarlyL_Gain2 = 14768;
+ pPreset->m_nEarlyL_Delay3 = 1221;
+ pPreset->m_nEarlyL_Gain3 = 14307;
+ pPreset->m_nEarlyL_Delay4 = 0;
+ pPreset->m_nEarlyL_Gain4 = 13384;
+ pPreset->m_nEarlyR_Delay0 = 502;
+ pPreset->m_nEarlyR_Gain0 = 20306;
+ pPreset->m_nEarlyR_Delay1 = 1762;
+ pPreset->m_nEarlyR_Gain1 = 17537;
+ pPreset->m_nEarlyR_Delay2 = 0;
+ pPreset->m_nEarlyR_Gain2 = 14768;
+ pPreset->m_nEarlyR_Delay3 = 0;
+ pPreset->m_nEarlyR_Gain3 = 16153;
+ pPreset->m_nEarlyR_Delay4 = 0;
+ pPreset->m_nEarlyR_Gain4 = 13384;
+ pPreset->m_nMaxExcursion = 127;
+ pPreset->m_nXfadeInterval = 6470; //6483;
+ pPreset->m_nAp0_ApGain = 14768;
+ pPreset->m_nAp0_ApOut = 792;
+ pPreset->m_nAp1_ApGain = 15783;
+ pPreset->m_nAp1_ApOut = 1113;
+ pPreset->m_rfu4 = 0;
+ pPreset->m_rfu5 = 0;
+ pPreset->m_rfu6 = 0;
+ pPreset->m_rfu7 = 0;
+ pPreset->m_rfu8 = 0;
+ pPreset->m_rfu9 = 0;
+ pPreset->m_rfu10 = 0;
+
+ }
+ }
+
+ return EAS_SUCCESS;
+}
diff --git a/arm-wt-22k/lib_src/eas_reverbdata.c b/arm-wt-22k/lib_src/eas_reverbdata.c
new file mode 100644
index 0000000..5d48c1b
--- /dev/null
+++ b/arm-wt-22k/lib_src/eas_reverbdata.c
@@ -0,0 +1,34 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_reverbdata.c
+ *
+ * Contents and purpose:
+ * Contains the static data allocation for the Reverb effect
+ *
+ *
+ * Copyright Sonic Network Inc. 2006
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 550 $
+ * $Date: 2007-02-02 09:37:03 -0800 (Fri, 02 Feb 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+#include "eas_reverbdata.h"
+
+S_REVERB_OBJECT eas_ReverbData;
+
diff --git a/arm-wt-22k/lib_src/eas_reverbdata.h b/arm-wt-22k/lib_src/eas_reverbdata.h
new file mode 100644
index 0000000..ef424da
--- /dev/null
+++ b/arm-wt-22k/lib_src/eas_reverbdata.h
@@ -0,0 +1,486 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_reverbdata.h
+ *
+ * Contents and purpose:
+ * Contains the prototypes for the Reverb effect.
+ *
+ *
+ * Copyright Sonic Network Inc. 2006
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 499 $
+ * $Date: 2006-12-11 16:07:20 -0800 (Mon, 11 Dec 2006) $
+ *----------------------------------------------------------------------------
+*/
+
+#ifndef _EAS_REVERBDATA_H
+#define _EAS_REVERBDATA_H
+
+#include "eas_types.h"
+#include "eas_audioconst.h"
+
+/*------------------------------------
+ * defines
+ *------------------------------------
+*/
+
+/*
+CIRCULAR() calculates the array index using modulo arithmetic.
+The "trick" is that modulo arithmetic is simplified by masking
+the effective address where the mask is (2^n)-1. This only works
+if the buffer size is a power of two.
+*/
+#define CIRCULAR(base,offset,size) (EAS_U32)( \
+ ( \
+ ((EAS_I32)(base)) + ((EAS_I32)(offset)) \
+ ) \
+ & size \
+ )
+
+/* reverb parameters are updated every 2^(REVERB_UPDATE_PERIOD_IN_BITS) samples */
+#if defined (_SAMPLE_RATE_8000)
+
+#define REVERB_UPDATE_PERIOD_IN_BITS 5
+#define REVERB_BUFFER_SIZE_IN_SAMPLES 2048
+
+#elif defined (_SAMPLE_RATE_16000)
+
+#define REVERB_UPDATE_PERIOD_IN_BITS 6
+#define REVERB_BUFFER_SIZE_IN_SAMPLES 4096
+
+#elif defined (_SAMPLE_RATE_22050)
+
+#define REVERB_UPDATE_PERIOD_IN_BITS 7
+#define REVERB_BUFFER_SIZE_IN_SAMPLES 4096
+
+#elif defined (_SAMPLE_RATE_32000)
+
+#define REVERB_UPDATE_PERIOD_IN_BITS 7
+#define REVERB_BUFFER_SIZE_IN_SAMPLES 8192
+
+#elif defined (_SAMPLE_RATE_44100)
+
+#define REVERB_UPDATE_PERIOD_IN_BITS 8
+#define REVERB_BUFFER_SIZE_IN_SAMPLES 8192
+
+#elif defined (_SAMPLE_RATE_48000)
+
+#define REVERB_UPDATE_PERIOD_IN_BITS 8
+#define REVERB_BUFFER_SIZE_IN_SAMPLES 8192
+
+#endif
+
+// Define a mask for circular addressing, so that array index
+// can wraparound and stay in array boundary of 0, 1, ..., (buffer size -1)
+// The buffer size MUST be a power of two
+#define REVERB_BUFFER_MASK (REVERB_BUFFER_SIZE_IN_SAMPLES -1)
+
+#define REVERB_MAX_ROOM_TYPE 4 // any room numbers larger than this are invalid
+#define REVERB_MAX_NUM_REFLECTIONS 5 // max num reflections per channel
+
+/* synth parameters are updated every SYNTH_UPDATE_PERIOD_IN_SAMPLES */
+#define REVERB_UPDATE_PERIOD_IN_SAMPLES (EAS_I32)(0x1L << REVERB_UPDATE_PERIOD_IN_BITS)
+
+/*
+calculate the update counter by bitwise ANDING with this value to
+generate a 2^n modulo value
+*/
+#define REVERB_MODULO_UPDATE_PERIOD_IN_SAMPLES (EAS_I32)(REVERB_UPDATE_PERIOD_IN_SAMPLES -1)
+
+/* synth parameters are updated every SYNTH_UPDATE_PERIOD_IN_SECONDS seconds */
+#define REVERB_UPDATE_PERIOD_IN_SECONDS (REVERB_UPDATE_PERIOD_IN_SAMPLES / _OUTPUT_SAMPLE_RATE)
+
+// xfade parameters
+#define REVERB_XFADE_PERIOD_IN_SECONDS (100.0 / 1000.0) // xfade once every this many seconds
+
+#define REVERB_XFADE_PERIOD_IN_SAMPLES (REVERB_XFADE_PERIOD_IN_SECONDS * _OUTPUT_SAMPLE_RATE)
+
+#define REVERB_XFADE_PHASE_INCREMENT (EAS_I16)(65536 / ((EAS_I16)REVERB_XFADE_PERIOD_IN_SAMPLES/(EAS_I16)REVERB_UPDATE_PERIOD_IN_SAMPLES))
+
+/**********/
+/* the entire synth uses various flags in a bit field */
+
+/* if flag is set, synth reset has been requested */
+#define REVERB_FLAG_RESET_IS_REQUESTED 0x01 /* bit 0 */
+#define MASK_REVERB_RESET_IS_REQUESTED 0x01
+#define MASK_REVERB_RESET_IS_NOT_REQUESTED (EAS_U32)(~MASK_REVERB_RESET_IS_REQUESTED)
+
+/*
+by default, we always want to update ALL channel parameters
+when we reset the synth (e.g., during GM ON)
+*/
+#define DEFAULT_REVERB_FLAGS 0x0
+
+/* coefficients for generating sin, cos */
+#define REVERB_PAN_G2 4294940151 /* -0.82842712474619 = 2 - 4/sqrt(2) */
+/*
+EAS_I32 nPanG1 = +1.0 for sin
+EAS_I32 nPanG1 = -1.0 for cos
+*/
+#define REVERB_PAN_G0 23170 /* 0.707106781186547 = 1/sqrt(2) */
+
+/*************************************************************/
+// define the input injection points
+#define GUARD 5 // safety guard of this many samples
+
+#define MAX_AP_TIME (double) (20.0/1000.0) // delay time in milliseconds
+#define MAX_DELAY_TIME (double) (65.0/1000.0) // delay time in milliseconds
+
+#define MAX_AP_SAMPLES (int)(((double) MAX_AP_TIME) * ((double) _OUTPUT_SAMPLE_RATE))
+#define MAX_DELAY_SAMPLES (int)(((double) MAX_DELAY_TIME) * ((double) _OUTPUT_SAMPLE_RATE))
+
+#define AP0_IN 0
+#define AP1_IN (AP0_IN + MAX_AP_SAMPLES + GUARD)
+#define DELAY0_IN (AP1_IN + MAX_AP_SAMPLES + GUARD)
+#define DELAY1_IN (DELAY0_IN + MAX_DELAY_SAMPLES + GUARD)
+
+// Define the max offsets for the end points of each section
+// i.e., we don't expect a given section's taps to go beyond
+// the following limits
+#define AP0_OUT (AP0_IN + MAX_AP_SAMPLES -1)
+#define AP1_OUT (AP1_IN + MAX_AP_SAMPLES -1)
+#define DELAY0_OUT (DELAY0_IN + MAX_DELAY_SAMPLES -1)
+#define DELAY1_OUT (DELAY1_IN + MAX_DELAY_SAMPLES -1)
+
+#define REVERB_DEFAULT_ROOM_NUMBER 1 // default preset number
+#define DEFAULT_AP0_LENGTH (int)(((double) (17.0/1000.0)) * ((double) _OUTPUT_SAMPLE_RATE))
+#define DEFAULT_AP0_GAIN 19400
+#define DEFAULT_AP1_LENGTH (int)(((double) (16.5/1000.0)) * ((double) _OUTPUT_SAMPLE_RATE))
+#define DEFAULT_AP1_GAIN -19400
+
+#define REVERB_DEFAULT_WET 32767
+#define REVERB_DEFAULT_DRY 0
+
+#define EAS_REVERB_WET_MAX 32767
+#define EAS_REVERB_WET_MIN 0
+#define EAS_REVERB_DRY_MAX 32767
+#define EAS_REVERB_DRY_MIN 0
+
+/* parameters for each allpass */
+typedef struct
+{
+ EAS_U16 m_zApOut; // delay offset for ap out
+
+ EAS_I16 m_nApGain; // gain for ap
+
+ EAS_U16 m_zApIn; // delay offset for ap in
+
+} S_ALLPASS_OBJECT;
+
+
+/* parameters for each allpass */
+typedef struct
+{
+ EAS_PCM m_zLpf; // actual state variable, not a length
+
+ EAS_I16 m_nLpfFwd; // lpf forward gain
+
+ EAS_I16 m_nLpfFbk; // lpf feedback gain
+
+ EAS_U16 m_zDelay[REVERB_MAX_NUM_REFLECTIONS]; // delay offset for ap out
+
+ EAS_I16 m_nGain[REVERB_MAX_NUM_REFLECTIONS]; // gain for ap
+
+} S_EARLY_REFLECTION_OBJECT;
+
+//demo
+typedef struct
+{
+ EAS_I16 m_nLpfFbk;
+ EAS_I16 m_nLpfFwd;
+
+ EAS_I16 m_nEarly;
+ EAS_I16 m_nWet;
+ EAS_I16 m_nDry;
+
+ EAS_I16 m_nEarlyL_LpfFbk;
+ EAS_I16 m_nEarlyL_LpfFwd;
+
+ EAS_I16 m_nEarlyL_Delay0; //8
+ EAS_I16 m_nEarlyL_Gain0;
+ EAS_I16 m_nEarlyL_Delay1;
+ EAS_I16 m_nEarlyL_Gain1;
+ EAS_I16 m_nEarlyL_Delay2;
+ EAS_I16 m_nEarlyL_Gain2;
+ EAS_I16 m_nEarlyL_Delay3;
+ EAS_I16 m_nEarlyL_Gain3;
+ EAS_I16 m_nEarlyL_Delay4;
+ EAS_I16 m_nEarlyL_Gain4;
+
+ EAS_I16 m_nEarlyR_Delay0; //18
+ EAS_I16 m_nEarlyR_Gain0;
+ EAS_I16 m_nEarlyR_Delay1;
+ EAS_I16 m_nEarlyR_Gain1;
+ EAS_I16 m_nEarlyR_Delay2;
+ EAS_I16 m_nEarlyR_Gain2;
+ EAS_I16 m_nEarlyR_Delay3;
+ EAS_I16 m_nEarlyR_Gain3;
+ EAS_I16 m_nEarlyR_Delay4;
+ EAS_I16 m_nEarlyR_Gain4;
+
+ EAS_U16 m_nMaxExcursion; //28
+ EAS_I16 m_nXfadeInterval;
+
+ EAS_I16 m_nAp0_ApGain; //30
+ EAS_I16 m_nAp0_ApOut;
+ EAS_I16 m_nAp1_ApGain;
+ EAS_I16 m_nAp1_ApOut;
+
+ EAS_I16 m_rfu4;
+ EAS_I16 m_rfu5;
+ EAS_I16 m_rfu6;
+ EAS_I16 m_rfu7;
+ EAS_I16 m_rfu8;
+ EAS_I16 m_rfu9;
+ EAS_I16 m_rfu10; //43
+