Initial Commit

This commit is contained in:
Jeff Farrand
2014-01-12 09:48:16 -06:00
commit 5b1ff23e0f
759 changed files with 319871 additions and 0 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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
*
*----------------------------------------------------------------------------
*/
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:
*
*----------------------------------------------------------------------------
*/
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
*----------------------------------------------------------------------------
*/
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 */

View File

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

View File

@@ -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
*
*----------------------------------------------------------------------------
*/
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:
*
*----------------------------------------------------------------------------
*/
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
*----------------------------------------------------------------------------
*/
EAS_RESULT ChorusUpdate(S_CHORUS_OBJECT* pChorusData);
#endif /* #ifndef _EAS_CHORUSDATA_H */

View File

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

View File

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

View File

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

View File

@@ -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;
}
}

View File

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

View File

@@ -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 */

View File

@@ -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;
}

View File

@@ -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
};

View File

@@ -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;
}

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -0,0 +1,74 @@
/*----------------------------------------------------------------------------
*
* 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 */
EAS_I32 repeatTime; /* time at 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

View File

@@ -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);
}

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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 */

View File

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

View File

@@ -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 */

View File

@@ -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];

View File

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

View File

@@ -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 */

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

@@ -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;
}

View File

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

View File

@@ -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 */

File diff suppressed because it is too large Load Diff

View File

@@ -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 */

View File

@@ -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];

View File

@@ -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 */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -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
} S_REVERB_PRESET;
typedef struct
{
S_REVERB_PRESET m_sPreset[REVERB_MAX_ROOM_TYPE]; //array of presets
} S_REVERB_PRESET_BANK;
/* parameters for each reverb */
typedef struct
{
/* controls entire reverb playback volume */
/* to conserve memory, use the MSB and ignore the LSB */
EAS_U8 m_nMasterVolume;
/* update counter keeps track of when synth params need updating */
/* only needs to be as large as REVERB_UPDATE_PERIOD_IN_SAMPLES */
EAS_I16 m_nUpdateCounter;
EAS_U16 m_nMinSamplesToAdd; /* ComputeReverb() generates this many samples */
EAS_U8 m_nFlags; /* misc flags/bit fields */
EAS_PCM *m_pOutputBuffer;
EAS_PCM *m_pInputBuffer;
EAS_U16 m_nNumSamplesInOutputBuffer;
EAS_U16 m_nNumSamplesInInputBuffer;
EAS_U16 m_nNumInputSamplesRead; // if m_nNumInputSamplesRead >= NumSamplesInInputBuffer
// then get a new input buffer
EAS_PCM *m_pNextInputSample;
EAS_U16 m_nBaseIndex; // base index for circular buffer
// reverb delay line offsets, allpass parameters, etc:
EAS_PCM m_nRevOutFbkR; // combine feedback reverb right out with dry left in
S_ALLPASS_OBJECT m_sAp0; // allpass 0 (left channel)
EAS_U16 m_zD0In; // delay offset for delay line D0 in
EAS_PCM m_nRevOutFbkL; // combine feedback reverb left out with dry right in
S_ALLPASS_OBJECT m_sAp1; // allpass 1 (right channel)
EAS_U16 m_zD1In; // delay offset for delay line D1 in
// delay output taps, notice criss cross order
EAS_U16 m_zD0Self; // self feeds forward d0 --> d0
EAS_U16 m_zD1Cross; // cross feeds across d1 --> d0
EAS_PCM m_zLpf0; // actual state variable, not a length
EAS_U16 m_zD1Self; // self feeds forward d1 --> d1
EAS_U16 m_zD0Cross; // cross feeds across d0 --> d1
EAS_PCM m_zLpf1; // actual state variable, not a length
EAS_I16 m_nSin; // gain for self taps
EAS_I16 m_nCos; // gain for cross taps
EAS_I16 m_nSinIncrement; // increment for gain
EAS_I16 m_nCosIncrement; // increment for gain
EAS_I16 m_nLpfFwd; // lpf forward gain (includes scaling for mixer)
EAS_I16 m_nLpfFbk; // lpf feedback gain
EAS_U16 m_nXfadeInterval; // update/xfade after this many samples
EAS_U16 m_nXfadeCounter; // keep track of when to xfade
EAS_I16 m_nPhase; // -1 <= m_nPhase < 1
// but during sin,cos calculations
// use m_nPhase/2
EAS_I16 m_nPhaseIncrement; // add this to m_nPhase each frame
EAS_I16 m_nNoise; // random noise sample
EAS_U16 m_nMaxExcursion; // the taps can excurse +/- this amount
EAS_BOOL m_bUseNoise; // if EAS_TRUE, use noise as input signal
EAS_BOOL m_bBypass; // if EAS_TRUE, then bypass reverb and copy input to output
EAS_I16 m_nCurrentRoom; // preset number for current room
EAS_I16 m_nNextRoom; // preset number for next room
EAS_I16 m_nWet; // gain for wet (processed) signal
EAS_I16 m_nDry; // gain for dry (unprocessed) signal
EAS_I16 m_nEarly; // gain for early (widen) signal
S_EARLY_REFLECTION_OBJECT m_sEarlyL; // left channel early reflections
S_EARLY_REFLECTION_OBJECT m_sEarlyR; // right channel early reflections
EAS_PCM m_nDelayLine[REVERB_BUFFER_SIZE_IN_SAMPLES]; // one large delay line for all reverb elements
S_REVERB_PRESET pPreset;
S_REVERB_PRESET_BANK m_sPreset;
//EAS_I8 preset;
} S_REVERB_OBJECT;
/*------------------------------------
* prototypes
*------------------------------------
*/
/*----------------------------------------------------------------------------
* 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
*
*----------------------------------------------------------------------------
*/
EAS_RESULT ReverbUpdateXfade(S_REVERB_OBJECT* pReverbData, EAS_INT nNumSamplesToAdd);
/*----------------------------------------------------------------------------
* 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
*
*----------------------------------------------------------------------------
*/
EAS_U16 ReverbCalculateNoise(EAS_U16 nMaxExcursion, EAS_I16 *pnNoise);
/*----------------------------------------------------------------------------
* 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
*
*----------------------------------------------------------------------------
*/
EAS_RESULT ReverbCalculateSinCos(EAS_I16 nPhase, EAS_I16 *pnSin, EAS_I16 *pnCos);
/*----------------------------------------------------------------------------
* 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:
*
*----------------------------------------------------------------------------
*/
EAS_RESULT Reverb(S_REVERB_OBJECT* pReverbData, EAS_INT nNumSamplesToAdd, EAS_PCM *pOutputBuffer, EAS_PCM *pInputBuffer);
/*----------------------------------------------------------------------------
* ReverbReadInPresets()
*----------------------------------------------------------------------------
* Purpose: sets global reverb preset bank to defaults
*
* Inputs:
*
* Outputs:
*
*----------------------------------------------------------------------------
*/
EAS_RESULT ReverbReadInPresets(S_REVERB_OBJECT* pReverbData);
/*----------------------------------------------------------------------------
* 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
*----------------------------------------------------------------------------
*/
EAS_RESULT ReverbUpdateRoom(S_REVERB_OBJECT* pReverbData);
#endif /* #ifndef _EAS_REVERBDATA_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,41 @@
/*----------------------------------------------------------------------------
*
* File:
* eas_rtttldata.c
*
* Contents and purpose:
* RTTTL File Parser data module for static memory models
*
* 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_rtttldata.h"
/*----------------------------------------------------------------------------
*
* eas_RTTTLData
*
* Static memory allocation for RTTTL parser
*----------------------------------------------------------------------------
*/
S_RTTTL_DATA eas_RTTTLData;

View File

@@ -0,0 +1,70 @@
/*----------------------------------------------------------------------------
*
* File:
* eas_rtttldata.h
*
* Contents and purpose:
* SMF File Parser
*
* This file contains data declarations for the RTTTL 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_RTTTLDATA_H
#define EAS_RTTTLDATA_H
#include "eas_data.h"
/* maximum line size as specified in iMelody V1.2 spec */
#define MAX_LINE_SIZE 75
/*----------------------------------------------------------------------------
*
* S_RTTTL_DATA
*
* This structure contains the state data for the iMelody parser
*----------------------------------------------------------------------------
*/
typedef struct
{
EAS_FILE_HANDLE fileHandle; /* file handle */
S_SYNTH *pSynth; /* synthesizer handle */
S_METADATA_CB metadata; /* metadata callback */
EAS_I32 fileOffset; /* offset to start of data */
EAS_I32 time; /* current time in 256ths of a msec */
EAS_I32 tick; /* length of 32nd note in 256th of a msec */
EAS_I32 restTicks; /* ticks to rest after current note */
EAS_I32 repeatOffset; /* file offset to start of repeat section */
EAS_U8 repeatCount; /* repeat counter */
EAS_I8 dataByte; /* storage for characters that are "put back" */
EAS_U8 state; /* current state EAS_STATE_XXXX */
EAS_I8 style; /* from STYLE */
EAS_U8 note; /* MIDI note number */
EAS_U8 octave; /* decault octave prefix */
EAS_I8 duration; /* default note duration */
} S_RTTTL_DATA;
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,49 @@
/*----------------------------------------------------------------------------
*
* File:
* eas_smf.h
*
* Contents and purpose:
* SMF Type 0 and 1 File 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_SMF_H
#define _EAS_SMF_H
/* prototypes for private interface to SMF parser */
EAS_RESULT SMF_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset);
EAS_RESULT SMF_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
EAS_RESULT SMF_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime);
EAS_RESULT SMF_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode);
EAS_RESULT SMF_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState);
EAS_RESULT SMF_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
EAS_RESULT SMF_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
EAS_RESULT SMF_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
EAS_RESULT SMF_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
EAS_RESULT SMF_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value);
EAS_RESULT SMF_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue);
EAS_RESULT SMF_ParseHeader (EAS_HW_DATA_HANDLE hwInstData, S_SMF_DATA *pSMFData);
#endif /* end _EAS_SMF_H */

View File

@@ -0,0 +1,66 @@
/*----------------------------------------------------------------------------
*
* File:
* eas_smfdata.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: 778 $
* $Date: 2007-07-23 16:45:17 -0700 (Mon, 23 Jul 2007) $
*----------------------------------------------------------------------------
*/
#include "eas_miditypes.h"
#include "eas_smfdata.h"
/*----------------------------------------------------------------------------
*
* S_SMF_STREAM
*
* Static memory allocation for SMF parser
*----------------------------------------------------------------------------
*/
static S_SMF_STREAM eas_SMFStreams[MAX_SMF_STREAMS];
/*----------------------------------------------------------------------------
*
* eas_SMFData
*
* Static memory allocation for SMF parser
*----------------------------------------------------------------------------
*/
S_SMF_DATA eas_SMFData =
{
eas_SMFStreams, /* pointer to individual streams in file */
0, /* pointer to next stream with event */
0, /* pointer to synth */
0, /* file handle */
{ 0, 0, 0, 0}, /* metadata callback */
0, /* file offset */
0, /* current time in milliseconds/256 */
0, /* actual number of streams */
0, /* current MIDI tick to msec conversion */
0, /* ticks per quarter note */
0, /* current state EAS_STATE_XXXX */
0 /* flags */
};

View File

@@ -0,0 +1,66 @@
/*----------------------------------------------------------------------------
*
* File:
* eas_smfdata.h
*
* 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: 686 $
* $Date: 2007-05-03 14:10:54 -0700 (Thu, 03 May 2007) $
*----------------------------------------------------------------------------
*/
#ifndef _EAS_SMF_DATA_H
#define _EAS_SMF_DATA_H
#ifndef MAX_SMF_STREAMS
#define MAX_SMF_STREAMS 128
#endif
/* offsets in to the SMF file */
#define SMF_OFS_HEADER_SIZE 4
#define SMF_OFS_FILE_TYPE 8
#define SMF_OFS_NUM_TRACKS 10
/* size of chunk info (chunk ID + chunk size) */
#define SMF_CHUNK_INFO_SIZE 8
/* 'MTrk' track chunk ID */
#define SMF_CHUNK_TYPE_TRACK 0x4d54726bL
/* some useful meta-events */
#define SMF_META_TEXT 0x01
#define SMF_META_COPYRIGHT 0x02
#define SMF_META_SEQTRK_NAME 0x03
#define SMF_META_LYRIC 0x05
#define SMF_META_END_OF_TRACK 0x2f
#define SMF_META_TEMPO 0x51
#define SMF_META_TIME_SIGNATURE 0x58
/* default timebase (120BPM) */
#define SMF_DEFAULT_TIMEBASE 500000L
/* value for pSMFStream->ticks to signify end of track */
#define SMF_END_OF_TRACK 0xffffffff
#endif

View File

@@ -0,0 +1,406 @@
/*----------------------------------------------------------------------------
*
* File:
* eas_sndlib.h
*
* Contents and purpose:
* Declarations for the sound library
*
* 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: 550 $
* $Date: 2007-02-02 09:37:03 -0800 (Fri, 02 Feb 2007) $
*----------------------------------------------------------------------------
*/
#ifndef _EAS_SNDLIB_H
#define _EAS_SNDLIB_H
#include "eas_types.h"
#include "eas_synthcfg.h"
#ifdef _WT_SYNTH
#include "eas_wtengine.h"
#endif
/*----------------------------------------------------------------------------
* This is bit of a hack to allow us to keep the same structure
* declarations for the DLS parser. Normally, the data is located
* in read-only memory, but for DLS, we store the data in RW
* memory.
*----------------------------------------------------------------------------
*/
#ifndef SCNST
#define SCNST const
#endif
/*----------------------------------------------------------------------------
* sample size
*----------------------------------------------------------------------------
*/
#ifdef _16_BIT_SAMPLES
typedef EAS_I16 EAS_SAMPLE;
#else
typedef EAS_I8 EAS_SAMPLE;
#endif
/*----------------------------------------------------------------------------
* EAS Library ID - quick check for valid library and version
*----------------------------------------------------------------------------
*/
#define _EAS_LIBRARY_VERSION 0x01534145
#define NUM_PROGRAMS_IN_BANK 128
#define INVALID_REGION_INDEX 0xffff
/* this bit in region index indicates that region is for secondary synth */
#define FLAG_RGN_IDX_FM_SYNTH 0x8000
#define FLAG_RGN_IDX_DLS_SYNTH 0x4000
#define REGION_INDEX_MASK 0x3fff
/*----------------------------------------------------------------------------
* Generic region data structure
*
* This must be the first element in each region structure
*----------------------------------------------------------------------------
*/
typedef struct s_region_tag
{
EAS_U16 keyGroupAndFlags;
EAS_U8 rangeLow;
EAS_U8 rangeHigh;
} S_REGION;
/*
* Bit fields for m_nKeyGroupAndFlags
* Bits 0-2 are mode bits in FM synth
* Bits 8-11 are the key group
*/
#define REGION_FLAG_IS_LOOPED 0x01
#define REGION_FLAG_USE_WAVE_GENERATOR 0x02
#define REGION_FLAG_USE_ADPCM 0x04
#define REGION_FLAG_ONE_SHOT 0x08
#define REGION_FLAG_SQUARE_WAVE 0x10
#define REGION_FLAG_OFF_CHIP 0x20
#define REGION_FLAG_NON_SELF_EXCLUSIVE 0x40
#define REGION_FLAG_LAST_REGION 0x8000
/*----------------------------------------------------------------------------
* Envelope data structure
*----------------------------------------------------------------------------
*/
typedef struct s_envelope_tag
{
EAS_I16 attackTime;
EAS_I16 decayTime;
EAS_I16 sustainLevel;
EAS_I16 releaseTime;
} S_ENVELOPE;
/*----------------------------------------------------------------------------
* DLS envelope data structure
*----------------------------------------------------------------------------
*/
typedef struct s_dls_envelope_tag
{
EAS_I16 delayTime;
EAS_I16 attackTime;
EAS_I16 holdTime;
EAS_I16 decayTime;
EAS_I16 sustainLevel;
EAS_I16 releaseTime;
EAS_I16 velToAttack;
EAS_I16 keyNumToDecay;
EAS_I16 keyNumToHold;
} S_DLS_ENVELOPE;
/*----------------------------------------------------------------------------
* LFO data structure
*----------------------------------------------------------------------------
*/
typedef struct s_lfo_params_tag
{
EAS_I16 lfoFreq;
EAS_I16 lfoDelay;
} S_LFO_PARAMS;
/*----------------------------------------------------------------------------
* Articulation data structure
*----------------------------------------------------------------------------
*/
typedef struct s_articulation_tag
{
S_ENVELOPE eg1;
S_ENVELOPE eg2;
EAS_I16 lfoToPitch;
EAS_I16 lfoDelay;
EAS_I16 lfoFreq;
EAS_I16 eg2ToPitch;
EAS_I16 eg2ToFc;
EAS_I16 filterCutoff;
EAS_I8 lfoToGain;
EAS_U8 filterQ;
EAS_I8 pan;
} S_ARTICULATION;
/*----------------------------------------------------------------------------
* DLS articulation data structure
*----------------------------------------------------------------------------
*/
typedef struct s_dls_articulation_tag
{
S_LFO_PARAMS modLFO;
S_LFO_PARAMS vibLFO;
S_DLS_ENVELOPE eg1;
S_DLS_ENVELOPE eg2;
EAS_I16 eg1ShutdownTime;
EAS_I16 filterCutoff;
EAS_I16 modLFOToFc;
EAS_I16 modLFOCC1ToFc;
EAS_I16 modLFOChanPressToFc;
EAS_I16 eg2ToFc;
EAS_I16 velToFc;
EAS_I16 keyNumToFc;
EAS_I16 modLFOToGain;
EAS_I16 modLFOCC1ToGain;
EAS_I16 modLFOChanPressToGain;
EAS_I16 tuning;
EAS_I16 keyNumToPitch;
EAS_I16 vibLFOToPitch;
EAS_I16 vibLFOCC1ToPitch;
EAS_I16 vibLFOChanPressToPitch;
EAS_I16 modLFOToPitch;
EAS_I16 modLFOCC1ToPitch;
EAS_I16 modLFOChanPressToPitch;
EAS_I16 eg2ToPitch;
/* pad to 4-byte boundary */
EAS_U16 pad;
EAS_I8 pan;
EAS_U8 filterQandFlags;
#ifdef _REVERB
EAS_I16 reverbSend;
EAS_I16 cc91ToReverbSend;
#endif
#ifdef _CHORUS
EAS_I16 chorusSend;
EAS_I16 cc93ToChorusSend;
#endif
} S_DLS_ARTICULATION;
/* flags in filterQandFlags
* NOTE: Q is stored in bottom 5 bits
*/
#define FLAG_DLS_VELOCITY_SENSITIVE 0x80
#define FILTER_Q_MASK 0x1f
/*----------------------------------------------------------------------------
* Wavetable region data structure
*----------------------------------------------------------------------------
*/
typedef struct s_wt_region_tag
{
S_REGION region;
EAS_I16 tuning;
EAS_I16 gain;
EAS_U32 loopStart;
EAS_U32 loopEnd;
EAS_U16 waveIndex;
EAS_U16 artIndex;
} S_WT_REGION;
/*----------------------------------------------------------------------------
* DLS region data structure
*----------------------------------------------------------------------------
*/
typedef struct s_dls_region_tag
{
S_WT_REGION wtRegion;
EAS_U8 velLow;
EAS_U8 velHigh;
} S_DLS_REGION;
/*----------------------------------------------------------------------------
* FM synthesizer data structures
*----------------------------------------------------------------------------
*/
typedef struct s_fm_oper_tag
{
EAS_I16 tuning;
EAS_U8 attackDecay;
EAS_U8 velocityRelease;
EAS_U8 egKeyScale;
EAS_U8 sustain;
EAS_U8 gain;
EAS_U8 flags;
} S_FM_OPER;
/* defines for S_FM_OPER.m_nFlags */
#define FM_OPER_FLAG_MONOTONE 0x01
#define FM_OPER_FLAG_NO_VIBRATO 0x02
#define FM_OPER_FLAG_NOISE 0x04
#define FM_OPER_FLAG_LINEAR_VELOCITY 0x08
/* NOTE: The first two structure elements are common with S_WT_REGION
* and we will rely on that in the voice management code and must
* remain there unless the voice management code is revisited.
*/
typedef struct s_fm_region_tag
{
S_REGION region;
EAS_U8 vibTrem;
EAS_U8 lfoFreqDelay;
EAS_U8 feedback;
EAS_I8 pan;
S_FM_OPER oper[4];
} S_FM_REGION;
/*----------------------------------------------------------------------------
* Common data structures
*----------------------------------------------------------------------------
*/
/*----------------------------------------------------------------------------
* Program data structure
* Used for individual programs not stored as a complete bank.
*----------------------------------------------------------------------------
*/
typedef struct s_program_tag
{
EAS_U32 locale;
EAS_U16 regionIndex;
} S_PROGRAM;
/*----------------------------------------------------------------------------
* Bank data structure
*
* A bank always consists of 128 programs. If a bank is less than 128
* programs, it should be stored as a spare matrix in the pPrograms
* array.
*
* bankNum: MSB/LSB of MIDI bank select controller
* regionIndex: Index of first region in program
*----------------------------------------------------------------------------
*/
typedef struct s_bank_tag
{
EAS_U16 locale;
EAS_U16 regionIndex[NUM_PROGRAMS_IN_BANK];
} S_BANK;
/* defines for libFormat field
* bits 0-17 are the sample rate
* bit 18 is true if wavetable is present
* bit 19 is true if FM is present
* bit 20 is true if filter is enabled
* bit 21 is sample depth (0 = 8-bits, 1 = 16-bits)
* bits 22-31 are reserved
*/
#define LIBFORMAT_SAMPLE_RATE_MASK 0x0003ffff
#define LIB_FORMAT_TYPE_MASK 0x000c0000
#define LIB_FORMAT_WAVETABLE 0x00000000
#define LIB_FORMAT_FM 0x00040000
#define LIB_FORMAT_HYBRID 0x00080000
#define LIB_FORMAT_FILTER_ENABLED 0x00100000
#define LIB_FORMAT_16_BIT_SAMPLES 0x00200000
#ifdef DLS_SYNTHESIZER
/*----------------------------------------------------------------------------
* DLS data structure
*
* pDLSPrograms pointer to array of DLS programs
* pDLSRegions pointer to array of DLS regions
* pDLSArticulations pointer to array of DLS articulations
* pSampleLen pointer to array of sample lengths
* ppSamples pointer to array of sample pointers
* numDLSPrograms number of DLS programs
* numDLSRegions number of DLS regions
* numDLSArticulations number of DLS articulations
* numDLSSamples number of DLS samples
*----------------------------------------------------------------------------
*/
typedef struct s_eas_dls_tag
{
S_PROGRAM *pDLSPrograms;
S_DLS_REGION *pDLSRegions;
S_DLS_ARTICULATION *pDLSArticulations;
EAS_U32 *pDLSSampleLen;
EAS_U32 *pDLSSampleOffsets;
EAS_SAMPLE *pDLSSamples;
EAS_U16 numDLSPrograms;
EAS_U16 numDLSRegions;
EAS_U16 numDLSArticulations;
EAS_U16 numDLSSamples;
EAS_U8 refCount;
} S_DLS;
#endif
/*----------------------------------------------------------------------------
* Sound library data structure
*
* pBanks pointer to array of banks
* pPrograms pointer to array of programs
* pWTRegions pointer to array of wavetable regions
* pFMRegions pointer to array of FM regions
* pArticulations pointer to array of articulations
* pSampleLen pointer to array of sample lengths
* ppSamples pointer to array of sample pointers
* numBanks number of banks
* numPrograms number of individual program
* numRegions number of regions
* numArticulations number of articulations
* numSamples number of samples
*----------------------------------------------------------------------------
*/
typedef struct s_eas_sndlib_tag
{
SCNST EAS_U32 identifier;
SCNST EAS_U32 libAttr;
SCNST S_BANK *pBanks;
SCNST S_PROGRAM *pPrograms;
SCNST S_WT_REGION *pWTRegions;
SCNST S_ARTICULATION *pArticulations;
SCNST EAS_U32 *pSampleLen;
SCNST EAS_U32 *pSampleOffsets;
SCNST EAS_SAMPLE *pSamples;
SCNST S_FM_REGION *pFMRegions;
SCNST EAS_U16 numBanks;
SCNST EAS_U16 numPrograms;
SCNST EAS_U16 numWTRegions;
SCNST EAS_U16 numArticulations;
SCNST EAS_U16 numSamples;
SCNST EAS_U16 numFMRegions;
} S_EAS;
#endif

View File

@@ -0,0 +1,395 @@
/*----------------------------------------------------------------------------
*
* File:
* eas_synth.h
*
* Contents and purpose:
* Declarations, interfaces, and prototypes for synth.
*
* Copyright Sonic Network Inc. 2004, 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: 718 $
* $Date: 2007-06-08 16:43:16 -0700 (Fri, 08 Jun 2007) $
*----------------------------------------------------------------------------
*/
#ifndef _EAS_SYNTH_H
#define _EAS_SYNTH_H
#include "eas_types.h"
#include "eas_sndlib.h"
#ifdef _WT_SYNTH
#include "eas_wtsynth.h"
#endif
#ifdef _FM_SYNTH
#include "eas_fmsynth.h"
#endif
#ifndef NUM_OUTPUT_CHANNELS
#define NUM_OUTPUT_CHANNELS 2
#endif
#ifndef MAX_SYNTH_VOICES
#define MAX_SYNTH_VOICES 64
#endif
#ifndef MAX_VIRTUAL_SYNTHESIZERS
#define MAX_VIRTUAL_SYNTHESIZERS 4
#endif
/* defines */
#ifndef NUM_PRIMARY_VOICES
#define NUM_PRIMARY_VOICES MAX_SYNTH_VOICES
#elif !defined(NUM_SECONDARY_VOICES)
#define NUM_SECONDARY_VOICES (MAX_SYNTH_VOICES - NUM_PRIMARY_VOICES)
#endif
#if defined(EAS_WT_SYNTH)
#define NUM_WT_VOICES MAX_SYNTH_VOICES
/* FM on MCU */
#elif defined(EAS_FM_SYNTH)
#define NUM_FM_VOICES MAX_SYNTH_VOICES
/* wavetable drums on MCU, wavetable melodic on DSP */
#elif defined(EAS_SPLIT_WT_SYNTH)
#define NUM_WT_VOICES MAX_SYNTH_VOICES
/* wavetable drums and FM melodic on MCU */
#elif defined(EAS_HYBRID_SYNTH)
#define NUM_WT_VOICES NUM_PRIMARY_VOICES
#define NUM_FM_VOICES NUM_SECONDARY_VOICES
/* wavetable drums on MCU, FM melodic on DSP */
#elif defined(EAS_SPLIT_HYBRID_SYNTH)
#define NUM_WT_VOICES NUM_PRIMARY_VOICES
#define NUM_FM_VOICES NUM_SECONDARY_VOICES
/* FM synth on DSP */
#elif defined(EAS_SPLIT_FM_SYNTH)
#define NUM_FM_VOICES MAX_SYNTH_VOICES
#else
#error "Unrecognized architecture option"
#endif
#define NUM_SYNTH_CHANNELS 16
#define DEFAULT_SYNTH_VOICES MAX_SYNTH_VOICES
/* use the following values to specify unassigned channels or voices */
#define UNASSIGNED_SYNTH_CHANNEL NUM_SYNTH_CHANNELS
#define UNASSIGNED_SYNTH_VOICE MAX_SYNTH_VOICES
/* synth parameters are updated every SYNTH_UPDATE_PERIOD_IN_SAMPLES */
#define SYNTH_UPDATE_PERIOD_IN_SAMPLES (EAS_I32)(0x1L << SYNTH_UPDATE_PERIOD_IN_BITS)
/* stealing weighting factors */
#define NOTE_AGE_STEAL_WEIGHT 1
#define NOTE_GAIN_STEAL_WEIGHT 4
#define CHANNEL_POLY_STEAL_WEIGHT 12
#define CHANNEL_PRIORITY_STEAL_WEIGHT 2
#define NOTE_MATCH_PENALTY 128
#define SYNTH_PRIORITY_WEIGHT 8
/* default synth master volume */
#define DEFAULT_SYNTH_MASTER_VOLUME 0x7fff
#define DEFAULT_SYNTH_PRIORITY 5
/* default tuning values */
#define DEFAULT_PITCH_BEND_SENSITIVITY 200 /* 2 semitones */
#define DEFAULT_FINE_PITCH 0 /* 0 cents */
#define DEFAULT_COARSE_PITCH 0 /* 0 semitones */
/* default drum channel is 10, but is internally 9 due to unit offset */
#define DEFAULT_DRUM_CHANNEL 9
/* drum channel can simultaneously play this many voices at most */
#define DEFAULT_CHANNEL_POLYPHONY_LIMIT 2
/* default instrument is acoustic piano */
#define DEFAULT_MELODY_BANK_MSB 0x79
#define DEFAULT_RHYTHM_BANK_MSB 0x78
#define DEFAULT_MELODY_BANK_NUMBER (DEFAULT_MELODY_BANK_MSB << 8)
#define DEFAULT_RHYTHM_BANK_NUMBER (DEFAULT_RHYTHM_BANK_MSB << 8)
#define DEFAULT_SYNTH_PROGRAM_NUMBER 0
#define DEFAULT_PITCH_BEND 0x2000 /* 0x2000 == (0x40 << 7) | 0x00 */
#define DEFAULT_MOD_WHEEL 0
#define DEFAULT_CHANNEL_VOLUME 0x64
#define DEFAULT_PAN 0x40 /* decimal 64, center */
#ifdef _REVERB
#define DEFAULT_REVERB_SEND 40 /* some reverb */
#endif
#ifdef _CHORUS
#define DEFAULT_CHORUS_SEND 0 /* no chorus */
#endif
#define DEFAULT_EAS_FILTER_CUTOFF_FREQUENCY 0 /* EAS synth uses a different default */
#define DEFAULT_FILTER_RESONANCE 0
#define DEFAULT_EXPRESSION 0x7F
#define DEFAULT_CHANNEL_PRESSURE 0
#define DEFAULT_REGISTERED_PARAM 0x3FFF
#define DEFAULT_CHANNEL_STATIC_GAIN 0
#define DEFAULT_CHANNEL_STATIC_PITCH 0
#define DEFAULT_LFO_MOD_WHEEL_TO_PITCH_CENTS 50
#define DEFAULT_LFO_CHANNEL_PRESSURE_TO_PITCH_CENTS 50
#define DEFAULT_KEY_NUMBER 0x69
#define DEFAULT_VELOCITY 0x64
#define DEFAULT_REGION_INDEX 0
#define DEFAULT_ARTICULATION_INDEX 0
#define DEFAULT_VOICE_GAIN 0
#define DEFAULT_AGE 0
#define DEFAULT_SP_MIDI_PRIORITY 16
/* filter defines */
#define DEFAULT_FILTER_ZERO 0
#define FILTER_CUTOFF_MAX_PITCH_CENTS 1919
#define FILTER_CUTOFF_MIN_PITCH_CENTS -4467
#define A5_PITCH_OFFSET_IN_CENTS 6900
/*------------------------------------
* S_SYNTH_CHANNEL data structure
*------------------------------------
*/
/* S_SYNTH_CHANNEL.m_nFlags */
#define CHANNEL_FLAG_SUSTAIN_PEDAL 0x01
#define CHANNEL_FLAG_MUTE 0x02
#define CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS 0x04
#define CHANNEL_FLAG_RHYTHM_CHANNEL 0x08
#define CHANNEL_FLAG_EXTERNAL_AUDIO 0x10
#define DEFAULT_CHANNEL_FLAGS 0
/* macros for extracting virtual synth and channel numbers */
#define GET_VSYNTH(a) ((a) >> 4)
#define GET_CHANNEL(a) ((a) & 15)
typedef struct s_synth_channel_tag
{
/* use static channel parameters to reduce MIPs */
/* parameters shared by multiple voices assigned to same channel */
EAS_I32 staticPitch; /* (pitch bend * pitch sens) + fine pitch */
EAS_I16 staticGain; /* (CC7 * CC11 * master vol)^2 */
EAS_U16 regionIndex; /* index of first region in program */
EAS_U16 bankNum; /* play programs from this bank */
EAS_I16 pitchBend; /* pitch wheel value */
EAS_I16 pitchBendSensitivity;
EAS_I16 registeredParam; /* currently selected registered param */
#if defined(_FM_SYNTH)
EAS_I16 lfoAmt; /* amount of LFO to apply to voice */
#endif
EAS_U8 programNum; /* play this instrument number */
EAS_U8 modWheel; /* CC1 */
EAS_U8 volume; /* CC7 */
EAS_U8 pan; /* CC10 */
EAS_U8 expression; /* CC11 */
/* the following parameters are controlled by RPNs */
EAS_I8 finePitch;
EAS_I8 coarsePitch;
EAS_U8 channelPressure; /* applied to all voices on a given channel */
EAS_U8 channelFlags; /* bit field channelFlags for */
/* CC64, SP-MIDI channel masking */
EAS_U8 pool; /* SPMIDI channel voice pool */
EAS_U8 mip; /* SPMIDI MIP setting */
#ifdef _REVERB
EAS_U8 reverbSend; /* CC91 */
#endif
#ifdef _CHORUS
EAS_U8 chorusSend; /* CC93 */
#endif
} S_SYNTH_CHANNEL;
/*------------------------------------
* S_SYNTH_VOICE data structure
*------------------------------------
*/
/* S_SYNTH_VOICE.m_nFlags */
#define VOICE_FLAG_UPDATE_VOICE_PARAMETERS 0x01
#define VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF 0x02
#define VOICE_FLAG_DEFER_MIDI_NOTE_OFF 0x04
#define VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET 0x08
#define VOICE_FLAG_DEFER_MUTE 0x40
#define DEFAULT_VOICE_FLAGS 0
/* S_SYNTH_VOICE.m_eState */
typedef enum {
eVoiceStateFree = 0,
eVoiceStateStart,
eVoiceStatePlay,
eVoiceStateRelease,
eVoiceStateMuting,
eVoiceStateStolen,
eVoiceStateInvalid /* should never be in this state! */
} E_VOICE_STATE;
#define DEFAULT_VOICE_STATE eVoiceStateFree
typedef struct s_synth_voice_tag
{
/* These parameters are common to both wavetable and FM
* synthesizers. The voice manager should only access this data.
* Any other data should be manipulated by the code that is
* specific to that synthesizer and reflected back through the
* common state data available here.
*/
EAS_U16 regionIndex; /* index to wave and playback params */
EAS_I16 gain; /* current gain */
EAS_U16 age; /* large value means old note */
EAS_U16 nextRegionIndex; /* index to wave and playback params */
EAS_U8 voiceState; /* current voice state */
EAS_U8 voiceFlags; /* misc flags/bit fields */
EAS_U8 channel; /* this voice plays on this synth channel */
EAS_U8 note; /* 12 <= key number <= 108 */
EAS_U8 velocity; /* 0 <= velocity <= 127 */
EAS_U8 nextChannel; /* play stolen voice on this channel */
EAS_U8 nextNote; /* 12 <= key number <= 108 */
EAS_U8 nextVelocity; /* 0 <= velocity <= 127 */
} S_SYNTH_VOICE;
/*------------------------------------
* S_SYNTH data structure
*
* One instance for each MIDI stream
*------------------------------------
*/
/* S_SYNTH.m_nFlags */
#define SYNTH_FLAG_RESET_IS_REQUESTED 0x01
#define SYNTH_FLAG_SP_MIDI_ON 0x02
#define SYNTH_FLAG_UPDATE_ALL_CHANNEL_PARAMETERS 0x04
#define SYNTH_FLAG_DEFERRED_MIDI_NOTE_OFF_PENDING 0x08
#define DEFAULT_SYNTH_FLAGS SYNTH_FLAG_UPDATE_ALL_CHANNEL_PARAMETERS
typedef struct s_synth_tag
{
struct s_eas_data_tag *pEASData;
const S_EAS *pEAS;
#ifdef DLS_SYNTHESIZER
S_DLS *pDLS;
#endif
#ifdef EXTERNAL_AUDIO
EAS_EXT_PRG_CHG_FUNC cbProgChgFunc;
EAS_EXT_EVENT_FUNC cbEventFunc;
EAS_VOID_PTR *pExtAudioInstData;
#endif
S_SYNTH_CHANNEL channels[NUM_SYNTH_CHANNELS];
EAS_I32 totalNoteCount;
EAS_U16 maxPolyphony;
EAS_U16 numActiveVoices;
EAS_U16 masterVolume;
EAS_U8 channelsByPriority[NUM_SYNTH_CHANNELS];
EAS_U8 poolCount[NUM_SYNTH_CHANNELS];
EAS_U8 poolAlloc[NUM_SYNTH_CHANNELS];
EAS_U8 synthFlags;
EAS_I8 globalTranspose;
EAS_U8 vSynthNum;
EAS_U8 refCount;
EAS_U8 priority;
} S_SYNTH;
/*------------------------------------
* S_VOICE_MGR data structure
*
* One instance for each EAS library instance
*------------------------------------
*/
typedef struct s_voice_mgr_tag
{
S_SYNTH *pSynth[MAX_VIRTUAL_SYNTHESIZERS];
EAS_PCM voiceBuffer[SYNTH_UPDATE_PERIOD_IN_SAMPLES];
#ifdef _FM_SYNTH
EAS_PCM operMixBuffer[SYNTH_UPDATE_PERIOD_IN_SAMPLES];
S_FM_VOICE fmVoices[NUM_FM_VOICES];
#endif
#ifdef _WT_SYNTH
S_WT_VOICE wtVoices[NUM_WT_VOICES];
#endif
#ifdef _REVERB
EAS_PCM reverbSendBuffer[NUM_OUTPUT_CHANNELS * SYNTH_UPDATE_PERIOD_IN_SAMPLES];
#endif
#ifdef _CHORUS
EAS_PCM chorusSendBuffer[NUM_OUTPUT_CHANNELS * SYNTH_UPDATE_PERIOD_IN_SAMPLES];
#endif
S_SYNTH_VOICE voices[MAX_SYNTH_VOICES];
EAS_SNDLIB_HANDLE pGlobalEAS;
#ifdef DLS_SYNTHESIZER
S_DLS *pGlobalDLS;
#endif
#ifdef _SPLIT_ARCHITECTURE
EAS_FRAME_BUFFER_HANDLE pFrameBuffer;
#endif
#if defined(_SECONDARY_SYNTH) || defined(EAS_SPLIT_WT_SYNTH)
EAS_U16 maxPolyphonyPrimary;
EAS_U16 maxPolyphonySecondary;
#endif
EAS_I32 workload;
EAS_I32 maxWorkLoad;
EAS_U16 activeVoices;
EAS_U16 maxPolyphony;
EAS_U16 age;
/* limits the number of voice starts in a frame for split architecture */
#ifdef MAX_VOICE_STARTS
EAS_U16 numVoiceStarts;
#endif
} S_VOICE_MGR;
#endif /* #ifdef _EAS_SYNTH_H */

View File

@@ -0,0 +1,60 @@
/*----------------------------------------------------------------------------
*
* File:
* eas_synth_protos.h
*
* Contents and purpose:
* Declarations, interfaces, and prototypes for synth.
*
* 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) $
*----------------------------------------------------------------------------
*/
#ifndef _EAS_SYNTH_PROTOS_H
#define _EAS_SYNTH_PROTOS_H
/* includes */
#include "eas_data.h"
#include "eas_sndlib.h"
#ifdef _SPLIT_ARCHITECTURE
typedef struct s_frame_interface_tag
{
EAS_BOOL (* EAS_CONST pfStartFrame)(EAS_FRAME_BUFFER_HANDLE pFrameBuffer);
EAS_BOOL (* EAS_CONST pfEndFrame)(EAS_FRAME_BUFFER_HANDLE pFrameBuffer, EAS_I32 *pMixBuffer, EAS_I16 masterGain);
} S_FRAME_INTERFACE;
#endif
/* generic synthesizer interface */
typedef struct
{
EAS_RESULT (* EAS_CONST pfInitialize)(S_VOICE_MGR *pVoiceMgr);
EAS_RESULT (* EAS_CONST pfStartVoice)(S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_U16 regionIndex);
EAS_BOOL (* EAS_CONST pfUpdateVoice)(S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_I32 *pMixBuffer, EAS_I32 numSamples);
void (* EAS_CONST pfReleaseVoice)(S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum);
void (* EAS_CONST pfMuteVoice)(S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum);
void (* EAS_CONST pfSustainPedal)(S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, S_SYNTH_CHANNEL *pChannel, EAS_I32 voiceNum);
void (* EAS_CONST pfUpdateChannel)(S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel);
} S_SYNTH_INTERFACE;
#endif

View File

@@ -0,0 +1,70 @@
/*----------------------------------------------------------------------------
*
* File:
* eas_synthcfg.h
*
* Contents and purpose:
* Defines for various synth configurations
*
* Copyright Sonic Network Inc. 2004, 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: 664 $
* $Date: 2007-04-25 13:11:22 -0700 (Wed, 25 Apr 2007) $
*----------------------------------------------------------------------------
*/
#ifndef _EAS_SYNTHCFG_H
#define _EAS_SYNTHCFG_H
#if defined(EAS_WT_SYNTH)
#define _WT_SYNTH
/* FM on MCU */
#elif defined(EAS_FM_SYNTH)
#define _FM_SYNTH
/* wavetable drums and FM melodic on MCU */
#elif defined(EAS_HYBRID_SYNTH)
#define _WT_SYNTH
#define _FM_SYNTH
#define _SECONDARY_SYNTH
#define _HYBRID_SYNTH
/* wavetable drums on MCU, wavetable melodic on DSP */
#elif defined(EAS_SPLIT_WT_SYNTH)
#define _WT_SYNTH
#define _SPLIT_ARCHITECTURE
/* wavetable drums on MCU, FM melodic on DSP */
#elif defined(EAS_SPLIT_HYBRID_SYNTH)
#define _WT_SYNTH
#define _FM_SYNTH
#define _SECONDARY_SYNTH
#define _SPLIT_ARCHITECTURE
#define _HYBRID_SYNTH
/* FM synth on DSP */
#elif defined(EAS_SPLIT_FM_SYNTH)
#define _FM_SYNTH
#define _SPLIT_ARCHITECTURE
#else
#error "Unrecognized architecture option"
#endif
#endif

View File

@@ -0,0 +1,43 @@
/*----------------------------------------------------------------------------
*
* File:
* eas_tcdata.c
*
* Contents and purpose:
* ToneControl Parser data
*
* This file contains static data for the ToneControl 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_tcdata.h"
/*----------------------------------------------------------------------------
*
* eas_iMelodyData
*
* Static memory allocation for iMelody parser
*----------------------------------------------------------------------------
*/
S_TC_DATA eas_TCData;

View File

@@ -0,0 +1,65 @@
/*----------------------------------------------------------------------------
*
* File:
* eas_tcdata.h
*
* Contents and purpose:
* SMF File Parser
*
* This file contains data declarations for the ToneControl parser.
*
* 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: 82 $
* $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $
*----------------------------------------------------------------------------
*/
#ifndef EAS_TFDATA_H
#define EAS_TCDATA_H
#include "eas_data.h"
/*----------------------------------------------------------------------------
*
* S_TC_DATA
*
* This structure contains the state data for the ToneControl parser
*----------------------------------------------------------------------------
*/
typedef struct
{
EAS_FILE_HANDLE fileHandle; /* file handle */
S_SYNTH *pSynth; /* synthesizer handle */
EAS_I32 fileOffset; /* offset to start of data */
EAS_I32 time; /* current time in 256ths of a msec */
EAS_I32 tick; /* tick based on current tempo and resolution */
EAS_I32 length; /* length of current note */
EAS_I32 restorePos; /* return to here after block */
EAS_U8 state; /* current state EAS_STATE_XXXX */
EAS_U8 volume; /* volume */
EAS_I8 note; /* current note */
EAS_I8 repeatCount; /* note repeat counter */
EAS_I8 tempo; /* tempo from file (bpm = tempo * 4) */
EAS_I8 resolution; /* resolution from file */
EAS_I8 dataByte; /* storage for characters that are "put back" */
EAS_BOOL8 byteAvail; /* char in "put back" buffer */
} S_TC_DATA;
#endif

View File

@@ -0,0 +1,941 @@
/*----------------------------------------------------------------------------
*
* File:
* eas_tonecontrol.c
*
* Contents and purpose:
* MMAPI ToneControl parser
*
* 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) $
*----------------------------------------------------------------------------
*/
#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_tcdata.h"
/* default channel and program for TC playback */
#define TC_CHANNEL 0
#define TC_PROGRAM 80
#define TC_VELOCITY 127
#define TC_FIELD_SILENCE -1
#define TC_FIELD_VERSION -2
#define TC_FIELD_TEMPO -3
#define TC_FIELD_RESOLUTION -4
#define TC_FIELD_BLOCK_START -5
#define TC_FIELD_BLOCK_END -6
#define TC_FIELD_PLAY_BLOCK -7
#define TC_FIELD_SET_VOLUME -8
#define TC_FIELD_REPEAT -9
#define TC_FIELD_INVALID -10
/* convert 0-100 volume to 0-127 velocity using fixed point */
#define TC_VOLUME_CONV 21307064
#define TC_VOLUME_SHIFT 24
/* local prototypes */
static EAS_RESULT TC_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset);
static EAS_RESULT TC_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
static EAS_RESULT TC_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime);
static EAS_RESULT TC_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode);
static EAS_RESULT TC_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState);
static EAS_RESULT TC_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
static EAS_RESULT TC_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
static EAS_RESULT TC_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
static EAS_RESULT TC_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
static EAS_RESULT TC_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value);
static EAS_RESULT TC_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue);
static EAS_RESULT TC_ParseHeader (S_EAS_DATA *pEASData, S_TC_DATA* pData);
static EAS_RESULT TC_StartNote (S_EAS_DATA *pEASData, S_TC_DATA* pData, EAS_INT parserMode, EAS_I8 note);
static EAS_RESULT TC_GetRepeat (S_EAS_DATA *pEASData, S_TC_DATA* pData, EAS_INT parserMode);
static EAS_RESULT TC_PlayBlock (S_EAS_DATA *pEASData, S_TC_DATA* pData);
static EAS_RESULT TC_BlockEnd (S_EAS_DATA *pEASData, S_TC_DATA* pData);
static EAS_RESULT TC_GetVolume (S_EAS_DATA *pEASData, S_TC_DATA* pData);
static EAS_RESULT TC_GetTempo (S_EAS_DATA *pEASData, S_TC_DATA* pData);
static EAS_RESULT TC_GetResolution (S_EAS_DATA *pEASData, S_TC_DATA* pData);
static EAS_RESULT TC_GetNextChar (EAS_HW_DATA_HANDLE hwInstData, S_TC_DATA *pData, EAS_I8 *pValue);
static void TC_PutBackChar (S_TC_DATA *pData, EAS_I8 value);
/* calculate a new tick time based on resolution & tempo */
EAS_INLINE void TC_CalcTimeBase (S_TC_DATA *pData)
{
/* ticks in 256ths of a millisecond */
pData->tick = ((60 * 1000) << 8) / (pData->tempo * pData->resolution);
}
/*----------------------------------------------------------------------------
*
* EAS_TC_Parser
*
* This structure contains the functional interface for the iMelody parser
*----------------------------------------------------------------------------
*/
const S_FILE_PARSER_INTERFACE EAS_TC_Parser =
{
TC_CheckFileType,
TC_Prepare,
TC_Time,
TC_Event,
TC_State,
TC_Close,
TC_Reset,
TC_Pause,
TC_Resume,
NULL,
TC_SetData,
TC_GetData,
NULL
};
/*----------------------------------------------------------------------------
* TC_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 TC_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset)
{
S_TC_DATA data;
S_TC_DATA *pData;
/* init data */
EAS_HWMemSet(&data, 0, sizeof(S_TC_DATA));
data.fileHandle = fileHandle;
data.fileOffset = offset;
*ppHandle= NULL;
/* see if we can parse the header */
if (TC_ParseHeader(pEASData, &data) == EAS_SUCCESS)
{
/* check for static memory allocation */
if (pEASData->staticMemoryModel)
pData = EAS_CMEnumOptData(EAS_MODULE_MMAPI_TONE_CONTROL);
else
pData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_TC_DATA));
if (!pData)
return EAS_ERROR_MALLOC_FAILED;
/* copy data to persistent storage */
EAS_HWMemCpy(pData, &data, sizeof(S_TC_DATA));
/* return a pointer to the instance data */
pData->state = EAS_STATE_OPEN;
*ppHandle = pData;
}
return EAS_SUCCESS;
}
/*----------------------------------------------------------------------------
* TC_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 TC_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
{
S_TC_DATA* pData;
EAS_RESULT result;
/* check for valid state */
pData = (S_TC_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;
}
/* set to ready state */
pData->state = EAS_STATE_READY;
return EAS_SUCCESS;
}
/*----------------------------------------------------------------------------
* TC_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) reserved for future use */
static EAS_RESULT TC_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime)
{
S_TC_DATA *pData;
pData = (S_TC_DATA*) pInstData;
/* return time in milliseconds */
/*lint -e{704} use shift instead of division */
*pTime = pData->time >> 8;
return EAS_SUCCESS;
}
/*----------------------------------------------------------------------------
* TC_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 TC_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode)
{
S_TC_DATA* pData;
EAS_RESULT result;
EAS_I8 temp;
pData = (S_TC_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 */
VMProgramChange(pEASData->pVoiceMgr, pData->pSynth, TC_CHANNEL, TC_PROGRAM);
/* set channel volume to max */
VMControlChange(pEASData->pVoiceMgr, pData->pSynth, TC_CHANNEL, 7, 127);
}
/* check for end of note */
if (pData->note >= 0)
{
/* stop the note */
VMStopNote(pEASData->pVoiceMgr, pData->pSynth, TC_CHANNEL, (EAS_U8) pData->note, 0);
/* check for repeat note */
if (pData->repeatCount)
{
pData->repeatCount--;
pData->time += pData->length;
if ((pData->note >= 0) && (parserMode == eParserModePlay))
VMStartNote(pEASData->pVoiceMgr, pData->pSynth, TC_CHANNEL, (EAS_U8) pData->note, pData->volume);
return EAS_SUCCESS;
}
pData->note = TC_FIELD_SILENCE;
}
/* parse stream until we get a note or rest */
for (;;)
{
/* get next byte from stream */
if ((result = TC_GetNextChar(pEASData->hwInstData, pData, &temp)) != EAS_SUCCESS)
{
if (result == EAS_EOF)
{
pData->state = EAS_STATE_STOPPING;
return EAS_SUCCESS;
}
break;
}
/* check for musical events */
if (temp >= TC_FIELD_SILENCE)
{
result = TC_StartNote(pEASData, pData, parserMode, temp);
break;
}
/* must be a control field */
switch (temp)
{
case TC_FIELD_TEMPO:
result = TC_GetTempo(pEASData, pData);
break;
case TC_FIELD_RESOLUTION:
result = TC_GetResolution(pEASData, pData);
break;
case TC_FIELD_SET_VOLUME:
result = TC_GetVolume(pEASData, pData);
break;
case TC_FIELD_REPEAT:
result = TC_GetRepeat(pEASData, pData, parserMode);
break;
case TC_FIELD_PLAY_BLOCK:
result = TC_PlayBlock(pEASData, pData);
break;
case TC_FIELD_BLOCK_START:
result = TC_GetNextChar(pEASData->hwInstData, pData, &temp);
break;
case TC_FIELD_BLOCK_END:
result = TC_BlockEnd(pEASData, pData);
break;
default:
{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unexpected byte 0x%02x in ToneControl stream\n", temp); */ }
result = EAS_ERROR_FILE_FORMAT;
}
/* check for error */
if (result != EAS_SUCCESS)
break;
}
/* check for error */
if (result != EAS_SUCCESS)
{
if (result == EAS_EOF)
result = EAS_ERROR_FILE_FORMAT;
pData->state = EAS_STATE_ERROR;
}
else
pData->state = EAS_STATE_PLAY;
return result;
}
/*----------------------------------------------------------------------------
* TC_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) reserved for future use */
static EAS_RESULT TC_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pState)
{
S_TC_DATA* pData;
/* establish pointer to instance data */
pData = (S_TC_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;
}
/*----------------------------------------------------------------------------
* TC_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 TC_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
{
S_TC_DATA* pData;
EAS_RESULT result;
pData = (S_TC_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;
}
/*----------------------------------------------------------------------------
* TC_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 TC_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
{
S_TC_DATA* pData;
EAS_RESULT result;
pData = (S_TC_DATA*) pInstData;
/* reset the synth */
VMReset(pEASData->pVoiceMgr, pData->pSynth, EAS_TRUE);
/* reset time to zero */
pData->time = 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 = TC_ParseHeader (pEASData, pData)) != EAS_SUCCESS)
return result;
pData->state = EAS_STATE_READY;
return EAS_SUCCESS;
}
/*----------------------------------------------------------------------------
* TC_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 TC_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
{
S_TC_DATA *pData;
/* can't pause a stopped stream */
pData = (S_TC_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;
}
/*----------------------------------------------------------------------------
* TC_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) reserved for future use */
static EAS_RESULT TC_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
{
S_TC_DATA *pData;
/* can't resume a stopped stream */
pData = (S_TC_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;
}
/*----------------------------------------------------------------------------
* TC_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, pInstData, value) reserved for future use */
static EAS_RESULT TC_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value)
{
/* we don't parse any metadata, but we need to return success here */
if (param == PARSER_DATA_METADATA_CB)
return EAS_SUCCESS;
return EAS_ERROR_INVALID_PARAMETER;
}
/*----------------------------------------------------------------------------
* TC_GetData()
*----------------------------------------------------------------------------
* Purpose:
* Return file type
*
* Inputs:
* pEASData - pointer to overall EAS data structure
* handle - pointer to file handle
*
* Outputs:
*
*
* Side Effects:
*
*----------------------------------------------------------------------------
*/
/*lint -e{715} common with other parsers */
static EAS_RESULT TC_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue)
{
S_TC_DATA *pData;
pData = (S_TC_DATA *) pInstData;
switch (param)
{
/* return file type as TC */
case PARSER_DATA_FILE_TYPE:
*pValue = EAS_FILE_MMAPI_TONE_CONTROL;
break;
case PARSER_DATA_SYNTH_HANDLE:
*pValue = (EAS_I32) pData->pSynth;
break;
default:
return EAS_ERROR_INVALID_PARAMETER;
}
return EAS_SUCCESS;
}
/*----------------------------------------------------------------------------
* TC_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 TC_ParseHeader (S_EAS_DATA *pEASData, S_TC_DATA* pData)
{
EAS_RESULT result;
EAS_I8 temp;
/* initialize some defaults */
pData->time = 0;
pData->tempo = 120;
pData->resolution = 64;
pData->volume = 127;
pData->repeatCount = 0;
pData->note = TC_FIELD_SILENCE;
pData->byteAvail = EAS_FALSE;
/* set default timebase */
TC_CalcTimeBase(pData);
/* seek to start of data */
if ((result = EAS_HWFileSeek(pEASData->hwInstData, pData->fileHandle, pData->fileOffset)) != EAS_SUCCESS)
return result;
/* get version */
if ((result = TC_GetNextChar(pEASData->hwInstData, pData, &temp)) != EAS_SUCCESS)
return result;
/* check for version number */
if (temp == TC_FIELD_VERSION)
{
TC_GetNextChar(pEASData->hwInstData, pData, &temp);
// { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "ToneControl sequence version %d\n", temp); */ }
}
else
return EAS_ERROR_FILE_FORMAT;
/* parse the header data until we find the first note or block */
for (;;)
{
/* get next byte from stream */
if ((result = TC_GetNextChar(pEASData->hwInstData, pData, &temp)) != EAS_SUCCESS)
return result;
/* check for tempo */
if (temp == TC_FIELD_TEMPO)
{
if ((result = TC_GetTempo(pEASData, pData)) != EAS_SUCCESS)
return result;
}
/* or resolution */
else if (temp == TC_FIELD_TEMPO)
{
if ((result = TC_GetResolution(pEASData, pData)) != EAS_SUCCESS)
return result;
}
/* must be music data */
else if (temp > TC_FIELD_INVALID)
{
TC_PutBackChar(pData, temp);
return EAS_SUCCESS;
}
/* unknown codes */
else
{
{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unexpected byte 0x%02x in ToneControl stream\n", temp); */ }
return EAS_ERROR_FILE_FORMAT;
}
}
}
/*----------------------------------------------------------------------------
* TC_StartNote()
*----------------------------------------------------------------------------
* Process a note or silence event
*----------------------------------------------------------------------------
*/
static EAS_RESULT TC_StartNote (S_EAS_DATA *pEASData, S_TC_DATA* pData, EAS_INT parserMode, EAS_I8 note)
{
EAS_I8 duration;
/* get the duration */
if (TC_GetNextChar(pEASData->hwInstData, pData, &duration) != EAS_SUCCESS)
return EAS_ERROR_FILE_FORMAT;
/* calculate time of next event */
pData->length = (EAS_I32) duration * pData->tick;
pData->time += pData->length;
/* start the note */
if ((note >= 0) && (parserMode == eParserModePlay))
{
VMStartNote(pEASData->pVoiceMgr, pData->pSynth, TC_CHANNEL, (EAS_U8) note, pData->volume);
pData->note = note;
}
return EAS_SUCCESS;
}
/*----------------------------------------------------------------------------
* TC_GetRepeat()
*----------------------------------------------------------------------------
* Process a repeat code
*----------------------------------------------------------------------------
*/
static EAS_RESULT TC_GetRepeat (S_EAS_DATA *pEASData, S_TC_DATA* pData, EAS_INT parserMode)
{
EAS_I8 count;
/* get the repeat count */
if (TC_GetNextChar(pEASData->hwInstData, pData, &count) != EAS_SUCCESS)
return EAS_ERROR_FILE_FORMAT;
/* validiate it */
if (count < 2)
return EAS_ERROR_FILE_FORMAT;
/* calculate time of next event */
pData->time += pData->length;
pData->repeatCount = count - 2;
/* start the note */
if ((pData->note >= 0) && (parserMode == eParserModePlay))
VMStartNote(pEASData->pVoiceMgr, pData->pSynth, TC_CHANNEL, (EAS_U8) pData->note, pData->volume);
return EAS_SUCCESS;
}
/*----------------------------------------------------------------------------
* TC_PlayBlock()
*----------------------------------------------------------------------------
* Play a block of notes
*----------------------------------------------------------------------------
*/
static EAS_RESULT TC_PlayBlock (S_EAS_DATA *pEASData, S_TC_DATA* pData)
{
EAS_RESULT result;
EAS_I8 blockNum;
EAS_I8 temp;
EAS_I8 temp2;
/* get the block number */
if (TC_GetNextChar(pEASData->hwInstData, pData, &blockNum) != EAS_SUCCESS)
return EAS_ERROR_FILE_FORMAT;
/* validiate it */
if (blockNum < 0)
return EAS_ERROR_FILE_FORMAT;
/* save the current position */
if ((result = EAS_HWFilePos(pEASData->hwInstData, pData->fileHandle, &pData->restorePos)) != EAS_SUCCESS)
return result;
/* return to start of file */
pData->byteAvail = EAS_FALSE;
if ((result = EAS_HWFileSeek(pEASData->hwInstData, pData->fileHandle, pData->fileOffset)) != EAS_SUCCESS)
return result;
/* find the block */
for (;;)
{
if (TC_GetNextChar(pEASData->hwInstData, pData, &temp) != EAS_SUCCESS)
return EAS_ERROR_FILE_FORMAT;
if (TC_GetNextChar(pEASData->hwInstData, pData, &temp2) != EAS_SUCCESS)
return EAS_ERROR_FILE_FORMAT;
if ((temp == TC_FIELD_BLOCK_START) && (temp2 == blockNum))
return EAS_SUCCESS;
}
}
/*----------------------------------------------------------------------------
* TC_BlockEnd()
*----------------------------------------------------------------------------
* Handle end of block
*----------------------------------------------------------------------------
*/
static EAS_RESULT TC_BlockEnd (S_EAS_DATA *pEASData, S_TC_DATA* pData)
{
EAS_I8 blockNum;
/* get the block number */
if (TC_GetNextChar(pEASData->hwInstData, pData, &blockNum) != EAS_SUCCESS)
return EAS_ERROR_FILE_FORMAT;
/* validiate it */
if (blockNum < 0)
return EAS_ERROR_FILE_FORMAT;
/* if we were playing this block, restore to previous position */
pData->byteAvail = EAS_FALSE;
return EAS_HWFileSeek(pEASData->hwInstData, pData->fileHandle, pData->restorePos);
}
/*----------------------------------------------------------------------------
* TC_GetVolume()
*----------------------------------------------------------------------------
* Get the volume field and process it
*----------------------------------------------------------------------------
*/
static EAS_RESULT TC_GetVolume (S_EAS_DATA *pEASData, S_TC_DATA* pData)
{
EAS_I8 volume;
/* get volume */
if (TC_GetNextChar(pEASData->hwInstData, pData, &volume) != EAS_SUCCESS)
return EAS_ERROR_FILE_FORMAT;
if ((volume < 0) || (volume > 100))
return EAS_ERROR_FILE_FORMAT;
/* save volume */
pData->volume = (EAS_U8) ((EAS_I32) (volume * TC_VOLUME_CONV + 1) >> TC_VOLUME_SHIFT);
return EAS_SUCCESS;
}
/*----------------------------------------------------------------------------
* TC_GetTempo()
*----------------------------------------------------------------------------
* Get the tempo field and process it
*----------------------------------------------------------------------------
*/
static EAS_RESULT TC_GetTempo (S_EAS_DATA *pEASData, S_TC_DATA* pData)
{
EAS_I8 tempo;
/* get tempo */
if (TC_GetNextChar(pEASData->hwInstData, pData, &tempo) != EAS_SUCCESS)
return EAS_ERROR_FILE_FORMAT;
if (tempo < 5)
return EAS_ERROR_FILE_FORMAT;
/* save tempo */
pData->tempo = tempo;
/* calculate new timebase */
TC_CalcTimeBase(pData);
return EAS_SUCCESS;
}
/*----------------------------------------------------------------------------
* TC_GetResolution()
*----------------------------------------------------------------------------
* Get the resolution field and process it
*----------------------------------------------------------------------------
*/
static EAS_RESULT TC_GetResolution (S_EAS_DATA *pEASData, S_TC_DATA* pData)
{
EAS_I8 resolution;
/* get resolution */
if (TC_GetNextChar(pEASData->hwInstData, pData, &resolution) != EAS_SUCCESS)
return EAS_ERROR_FILE_FORMAT;
if (resolution < 0)
return EAS_ERROR_FILE_FORMAT;
/* save tempo */
pData->resolution = resolution;
/* calculate new timebase */
TC_CalcTimeBase(pData);
return EAS_SUCCESS;
}
/*----------------------------------------------------------------------------
* TC_GetNextChar()
*----------------------------------------------------------------------------
* Fetch the next character from the stream
*----------------------------------------------------------------------------
*/
static EAS_RESULT TC_GetNextChar (EAS_HW_DATA_HANDLE hwInstData, S_TC_DATA *pData, EAS_I8 *pValue)
{
/* get character from "put back" buffer */
if (pData->byteAvail)
{
pData->byteAvail = EAS_FALSE;
*pValue = pData->dataByte;
return EAS_SUCCESS;
}
/* get character from file */
return EAS_HWGetByte(hwInstData, pData->fileHandle, pValue);
}
/*----------------------------------------------------------------------------
* TC_PutBackChar()
*----------------------------------------------------------------------------
* Put back the character
*----------------------------------------------------------------------------
*/
static void TC_PutBackChar (S_TC_DATA *pData, EAS_I8 value)
{
pData->dataByte = value;
pData->byteAvail = EAS_TRUE;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,867 @@
/*----------------------------------------------------------------------------
*
* File:
* eas_wavefile.c
*
* Contents and purpose:
* This file implements the wave file 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: 852 $
* $Date: 2007-09-04 11:43:49 -0700 (Tue, 04 Sep 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_wavefile.h"
/* lint is choking on the ARM math.h file, so we declare the log10 function here */
extern double log10(double x);
/* increase gain to compensate for loss in mixer */
#define WAVE_GAIN_OFFSET 6
/* constant for 1200 / log10(2.0) */
#define PITCH_CENTS_CONVERSION 3986.313714
/*----------------------------------------------------------------------------
* WAVE file defines
*----------------------------------------------------------------------------
*/
/* RIFF chunks */
#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_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_LIST CHUNK_TYPE('L','I','S','T')
#define CHUNK_INFO CHUNK_TYPE('I','N','F','O')
#define CHUNK_INAM CHUNK_TYPE('I','N','A','M')
#define CHUNK_ICOP CHUNK_TYPE('I','C','O','P')
#define CHUNK_IART CHUNK_TYPE('I','A','R','T')
/* wave file format identifiers */
#define WAVE_FORMAT_PCM 0x0001
#define WAVE_FORMAT_IMA_ADPCM 0x0011
/* file size for streamed file */
#define FILE_SIZE_STREAMING 0x80000000
/*----------------------------------------------------------------------------
* prototypes
*----------------------------------------------------------------------------
*/
static EAS_RESULT WaveCheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *pHandle, EAS_I32 offset);
static EAS_RESULT WavePrepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
static EAS_RESULT WaveState (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState);
static EAS_RESULT WaveClose (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
static EAS_RESULT WaveReset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
static EAS_RESULT WaveLocate (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 time, EAS_BOOL *pParserLocate);
static EAS_RESULT WavePause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
static EAS_RESULT WaveResume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
static EAS_RESULT WaveSetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value);
static EAS_RESULT WaveGetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue);
static EAS_RESULT WaveParseHeader (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, S_WAVE_STATE *pWaveData);
static EAS_RESULT WaveGetMetaData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pMediaLength);
#ifdef MMAPI_SUPPORT
static EAS_RESULT SaveFmtChunk (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, S_WAVE_STATE *pWaveData, EAS_I32 size);
#endif
/*----------------------------------------------------------------------------
*
* EAS_Wave_Parser
*
* This structure contains the functional interface for the Wave file parser
*----------------------------------------------------------------------------
*/
const S_FILE_PARSER_INTERFACE EAS_Wave_Parser =
{
WaveCheckFileType,
WavePrepare,
NULL,
NULL,
WaveState,
WaveClose,
WaveReset,
WavePause,
WaveResume,
WaveLocate,
WaveSetData,
WaveGetData,
WaveGetMetaData
};
/*----------------------------------------------------------------------------
* WaveCheckFileType()
*----------------------------------------------------------------------------
* 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 WaveCheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *pHandle, EAS_I32 offset)
{
S_WAVE_STATE *pWaveData;
/* zero the memory to insure complete initialization */
*pHandle = NULL;
/* read the file header */
if (WaveParseHeader(pEASData, fileHandle, NULL) == EAS_SUCCESS)
{
/* check for static memory allocation */
if (pEASData->staticMemoryModel)
pWaveData = EAS_CMEnumData(EAS_CM_WAVE_DATA);
else
pWaveData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_WAVE_STATE));
if (!pWaveData)
return EAS_ERROR_MALLOC_FAILED;
EAS_HWMemSet(pWaveData, 0, sizeof(S_WAVE_STATE));
/* return a pointer to the instance data */
pWaveData->fileHandle = fileHandle;
pWaveData->fileOffset = offset;
*pHandle = pWaveData;
}
return EAS_SUCCESS;
}
/*----------------------------------------------------------------------------
* WavePrepare()
*----------------------------------------------------------------------------
* Purpose:
* Prepare to parse the file.
*
* Inputs:
* pEASData - pointer to overall EAS data structure
* handle - pointer to file handle
*
* Outputs:
*
*
* Side Effects:
*
*----------------------------------------------------------------------------
*/
static EAS_RESULT WavePrepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
{
S_WAVE_STATE *pWaveData;
EAS_RESULT result;
/* validate parser state */
pWaveData = (S_WAVE_STATE*) pInstData;
if (pWaveData->streamHandle != NULL)
return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
/* back to start of file */
pWaveData->time = 0;
if ((result = EAS_HWFileSeek(pEASData->hwInstData, pWaveData->fileHandle, pWaveData->fileOffset)) != EAS_SUCCESS)
return result;
/* parse the file header */
if ((result = WaveParseHeader(pEASData, pWaveData->fileHandle, pWaveData)) != EAS_SUCCESS)
return result;
return EAS_SUCCESS;
}
/*----------------------------------------------------------------------------
* WaveState()
*----------------------------------------------------------------------------
* 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.
*----------------------------------------------------------------------------
*/
static EAS_RESULT WaveState (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState)
{
S_WAVE_STATE *pWaveData;
/* return current state */
pWaveData = (S_WAVE_STATE*) pInstData;
if (pWaveData->streamHandle)
return EAS_PEState(pEASData, pWaveData->streamHandle, pState);
/* if no stream handle, and time is not zero, we are done */
if (pWaveData->time > 0)
*pState = EAS_STATE_STOPPED;
else
*pState = EAS_STATE_OPEN;
return EAS_SUCCESS;
}
/*----------------------------------------------------------------------------
* WaveClose()
*----------------------------------------------------------------------------
* 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 WaveClose (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
{
S_WAVE_STATE *pWaveData;
EAS_RESULT result;
pWaveData = (S_WAVE_STATE*) pInstData;
/* close the stream */
if (pWaveData->streamHandle)
{
if ((result = EAS_PEClose(pEASData, pWaveData->streamHandle)) != EAS_SUCCESS)
return result;
pWaveData->streamHandle = NULL;
}
/* if using dynamic memory, free it */
if (!pEASData->staticMemoryModel)
{
#ifdef MMAPI_SUPPORT
/* need to free the fmt chunk */
if (pWaveData->fmtChunk != NULL)
EAS_HWFree(pEASData->hwInstData, pWaveData->fmtChunk);
#endif
/* free the instance data */
EAS_HWFree(pEASData->hwInstData, pWaveData);
}
return EAS_SUCCESS;
}
/*----------------------------------------------------------------------------
* WaveReset()
*----------------------------------------------------------------------------
* 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 WaveReset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
{
EAS_PCM_HANDLE streamHandle;
/* reset to first byte of data in the stream */
streamHandle = ((S_WAVE_STATE*)pInstData)->streamHandle;
if (streamHandle)
return EAS_PEReset(pEASData, streamHandle);
return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
}
/*----------------------------------------------------------------------------
* WaveLocate()
*----------------------------------------------------------------------------
* Purpose:
* Rewind/fast-forward in file.
*
* Inputs:
* pEASData - pointer to overall EAS data structure
* handle - pointer to file handle
* time - time (in msecs)
*
* Outputs:
*
*
* Side Effects:
*
*----------------------------------------------------------------------------
*/
/*lint -esym(715, pParserLocate) reserved for future use */
static EAS_RESULT WaveLocate (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 time, EAS_BOOL *pParserLocate)
{
EAS_PCM_HANDLE streamHandle;
/* reset to first byte of data in the stream */
streamHandle = ((S_WAVE_STATE*)pInstData)->streamHandle;
if (streamHandle)
return EAS_PELocate(pEASData, streamHandle, time);
return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
}
/*----------------------------------------------------------------------------
* WavePause()
*----------------------------------------------------------------------------
* 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_WAVE_STATE for this stream
*
* Outputs:
*
*
* Side Effects:
*
*----------------------------------------------------------------------------
*/
/*lint -esym(715, pEASData) reserved for future use */
static EAS_RESULT WavePause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
{
EAS_PCM_HANDLE streamHandle;
/* pause the stream */
streamHandle = ((S_WAVE_STATE*)pInstData)->streamHandle;
if (streamHandle)
return EAS_PEPause(pEASData, streamHandle);
return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
}
/*----------------------------------------------------------------------------
* WaveResume()
*----------------------------------------------------------------------------
* 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_WAVE_STATE for this stream
*
* Outputs:
*
*
* Side Effects:
*
*----------------------------------------------------------------------------
*/
/*lint -esym(715, pEASData) reserved for future use */
static EAS_RESULT WaveResume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
{
EAS_PCM_HANDLE streamHandle;
/* resume the stream */
streamHandle = ((S_WAVE_STATE*)pInstData)->streamHandle;
if (streamHandle)
return EAS_PEResume(pEASData, streamHandle);
return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
}
/*----------------------------------------------------------------------------
* WaveSetData()
*----------------------------------------------------------------------------
* Purpose:
*
* Inputs:
* pEASData - pointer to EAS library instance data
* handle - pointer to S_WAVE_STATE for this stream
*
* Outputs:
*
*
* Side Effects:
*
*----------------------------------------------------------------------------
*/
static EAS_RESULT WaveSetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value)
{
S_WAVE_STATE *pWaveData = (S_WAVE_STATE*) pInstData;
switch (param)
{
/* set metadata callback */
case PARSER_DATA_METADATA_CB:
EAS_HWMemCpy(&pWaveData->metadata, (void*) value, sizeof(S_METADATA_CB));
return EAS_SUCCESS;
case PARSER_DATA_PLAYBACK_RATE:
value = (EAS_I32) (PITCH_CENTS_CONVERSION * log10((double) value / (double) (1 << 28)));
return EAS_PEUpdatePitch(pEASData, pWaveData->streamHandle, (EAS_I16) value);
case PARSER_DATA_VOLUME:
return EAS_PEUpdateVolume(pEASData, pWaveData->streamHandle, (EAS_I16) value);
default:
return EAS_ERROR_INVALID_PARAMETER;
}
}
/*----------------------------------------------------------------------------
* WaveGetData()
*----------------------------------------------------------------------------
* Purpose:
*
* Inputs:
* pEASData - pointer to EAS library instance data
* handle - pointer to S_WAVE_STATE for this stream
*
* Outputs:
*
*
* Side Effects:
*
*----------------------------------------------------------------------------
*/
/*lint -esym(715, pEASData) reserved for future use */
static EAS_RESULT WaveGetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue)
{
S_WAVE_STATE *pWaveData;
pWaveData = (S_WAVE_STATE*) pInstData;
switch (param)
{
/* return file type as WAVE */
case PARSER_DATA_FILE_TYPE:
*pValue = pWaveData->fileType;
break;
#ifdef MMAPI_SUPPORT
/* return pointer to 'fmt' chunk */
case PARSER_DATA_FORMAT:
*pValue = (EAS_I32) pWaveData->fmtChunk;
break;
#endif
case PARSER_DATA_GAIN_OFFSET:
*pValue = WAVE_GAIN_OFFSET;
break;
default:
return EAS_ERROR_INVALID_PARAMETER;
}
return EAS_SUCCESS;
}
/*----------------------------------------------------------------------------
* WaveParseHeader()
*----------------------------------------------------------------------------
* Purpose:
* Parse the WAVE file header.
*
* Inputs:
* pEASData - pointer to EAS library instance data
* handle - pointer to S_WAVE_STATE for this stream
*
* Outputs:
*
*
* Side Effects:
*
*----------------------------------------------------------------------------
*/
static EAS_RESULT WaveParseHeader (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, S_WAVE_STATE *pWaveData)
{
S_PCM_OPEN_PARAMS params;
EAS_RESULT result;
EAS_U32 tag;
EAS_U32 fileSize;
EAS_U32 size;
EAS_I32 pos;
EAS_I32 audioOffset;
EAS_U16 usTemp;
EAS_BOOL parseDone;
EAS_U32 avgBytesPerSec;
/* init some data (and keep lint happy) */
params.sampleRate = 0;
params.size = 0;
audioOffset = 0;
params.decoder = 0;
params.blockSize = 0;
params.pCallbackFunc = NULL;
params.cbInstData = NULL;
params.loopSamples = 0;
params.fileHandle = fileHandle;
params.volume = 0x7fff;
params.envData = 0;
avgBytesPerSec = 8000;
/* check for 'RIFF' tag */
if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &tag, EAS_TRUE)) != EAS_FALSE)
return result;
if (tag != CHUNK_RIFF)
return EAS_ERROR_UNRECOGNIZED_FORMAT;
/* get size */
if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &fileSize, EAS_FALSE)) != EAS_FALSE)
return result;
/* check for 'WAVE' tag */
if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &tag, EAS_TRUE)) != EAS_FALSE)
return result;
if (tag != CHUNK_WAVE)
return EAS_ERROR_UNRECOGNIZED_FORMAT;
/* this is enough to say we recognize the file */
if (pWaveData == NULL)
return EAS_SUCCESS;
/* check for streaming mode */
pWaveData->flags = 0;
pWaveData->mediaLength = -1;
pWaveData->infoChunkPos = -1;
pWaveData->infoChunkSize = -1;
if (fileSize== FILE_SIZE_STREAMING)
{
pWaveData->flags |= PCM_FLAGS_STREAMING;
fileSize = 0x7fffffff;
}
/* find out where we're at */
if ((result = EAS_HWFilePos(pEASData->hwInstData, fileHandle, &pos)) != EAS_SUCCESS)
return result;
fileSize -= 4;
parseDone = EAS_FALSE;
for (;;)
{
/* get tag and size for next chunk */
if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &tag, EAS_TRUE)) != EAS_FALSE)
return result;
if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &size, EAS_FALSE)) != EAS_FALSE)
return result;
/* process chunk */
pos += 8;
switch (tag)
{
case CHUNK_FMT:
#ifdef MMAPI_SUPPORT
if ((result = SaveFmtChunk(pEASData, fileHandle, pWaveData, (EAS_I32) size)) != EAS_SUCCESS)
return result;
#endif
/* get audio format */
if ((result = EAS_HWGetWord(pEASData->hwInstData, fileHandle, &usTemp, EAS_FALSE)) != EAS_FALSE)
return result;
if (usTemp == WAVE_FORMAT_PCM)
{
params.decoder = EAS_DECODER_PCM;
pWaveData->fileType = EAS_FILE_WAVE_PCM;
}
else if (usTemp == WAVE_FORMAT_IMA_ADPCM)
{
params.decoder = EAS_DECODER_IMA_ADPCM;
pWaveData->fileType = EAS_FILE_WAVE_IMA_ADPCM;
}
else
return EAS_ERROR_UNRECOGNIZED_FORMAT;
/* get number of channels */
if ((result = EAS_HWGetWord(pEASData->hwInstData, fileHandle, &usTemp, EAS_FALSE)) != EAS_FALSE)
return result;
if (usTemp == 2)
pWaveData->flags |= PCM_FLAGS_STEREO;
else if (usTemp != 1)
return EAS_ERROR_UNRECOGNIZED_FORMAT;
/* get sample rate */
if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &params.sampleRate, EAS_FALSE)) != EAS_FALSE)
return result;
/* get stream rate */
if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &avgBytesPerSec, EAS_FALSE)) != EAS_FALSE)
return result;
/* get block alignment */
if ((result = EAS_HWGetWord(pEASData->hwInstData, fileHandle, &usTemp, EAS_FALSE)) != EAS_FALSE)
return result;
params.blockSize = usTemp;
/* get bits per sample */
if ((result = EAS_HWGetWord(pEASData->hwInstData, fileHandle, &usTemp, EAS_FALSE)) != EAS_FALSE)
return result;
/* PCM, must be 8 or 16 bit samples */
if (params.decoder == EAS_DECODER_PCM)
{
if (usTemp == 8)
pWaveData->flags |= PCM_FLAGS_8_BIT | PCM_FLAGS_UNSIGNED;
else if (usTemp != 16)
return EAS_ERROR_UNRECOGNIZED_FORMAT;
}
/* for IMA ADPCM, we only support mono 4-bit ADPCM */
else
{
if ((usTemp != 4) || (pWaveData->flags & PCM_FLAGS_STEREO))
return EAS_ERROR_UNRECOGNIZED_FORMAT;
}
break;
case CHUNK_DATA:
audioOffset = pos;
if (pWaveData->flags & PCM_FLAGS_STREAMING)
{
params.size = 0x7fffffff;
parseDone = EAS_TRUE;
}
else
{
params.size = (EAS_I32) size;
params.loopStart = size;
/* use more accurate method if possible */
if (size <= (0x7fffffff / 1000))
pWaveData->mediaLength = (EAS_I32) ((size * 1000) / avgBytesPerSec);
else
pWaveData->mediaLength = (EAS_I32) (size / (avgBytesPerSec / 1000));
}
break;
case CHUNK_LIST:
/* get the list type */
if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &tag, EAS_TRUE)) != EAS_FALSE)
return result;
if (tag == CHUNK_INFO)
{
pWaveData->infoChunkPos = pos + 4;
pWaveData->infoChunkSize = (EAS_I32) size - 4;
}
break;
default:
{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "WaveParseHeader: %c%c%c%c chunk - %d byte(s) ignored\n",
(char) (tag >> 24), (char) (tag >> 16), (char) (tag >> 8), (char) tag, size); */ }
break;
}
if (parseDone)
break;
/* subtract header size */
fileSize -= 8;
/* account for zero-padding on odd length chunks */
if (size & 1)
size++;
/* this check works for files with odd length last chunk and no zero-pad */
if (size >= fileSize)
{
if (size > fileSize)
{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "WaveParseHeader: '%c%c%c%c' chunk size exceeds length of file or is not zero-padded\n",
(char) (tag >> 24), (char) (tag >> 16), (char) (tag >> 8), (char) tag, size); */ }
break;
}
/* subtract size of data chunk (including any zero-pad) */
fileSize -= size;
/* seek to next chunk */
pos += (EAS_I32) size;
if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, pos)) != EAS_SUCCESS)
return result;
}
/* check for valid header */
if ((params.sampleRate == 0) || (params.size == 0))
return EAS_ERROR_UNRECOGNIZED_FORMAT;
/* save the pertinent information */
pWaveData->audioOffset = audioOffset;
params.flags = pWaveData->flags;
/* seek to data */
if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, audioOffset)) != EAS_SUCCESS)
return result;
/* open a stream in the PCM engine */
return EAS_PEOpenStream(pEASData, &params, &pWaveData->streamHandle);
}
/*----------------------------------------------------------------------------
* WaveGetMetaData()
*----------------------------------------------------------------------------
* Purpose:
* Process the INFO chunk and return metadata to host
*----------------------------------------------------------------------------
*/
static EAS_RESULT WaveGetMetaData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pMediaLength)
{
S_WAVE_STATE *pWaveData;
EAS_RESULT result;
EAS_I32 pos;
EAS_U32 size;
EAS_I32 infoSize;
EAS_U32 tag;
EAS_I32 restorePos;
E_EAS_METADATA_TYPE metaType;
EAS_I32 metaLen;
/* get current position so we can restore it */
pWaveData = (S_WAVE_STATE*) pInstData;
/* return media length */
*pMediaLength = pWaveData->mediaLength;
/* did we encounter an INFO chunk? */
if (pWaveData->infoChunkPos < 0)
return EAS_SUCCESS;
if ((result = EAS_HWFilePos(pEASData->hwInstData, pWaveData->fileHandle, &restorePos)) != EAS_SUCCESS)
return result;
/* offset to start of first chunk in INFO chunk */
pos = pWaveData->infoChunkPos;
infoSize = pWaveData->infoChunkSize;
/* read all the chunks in the INFO chunk */
for (;;)
{
/* seek to next chunk */
if ((result = EAS_HWFileSeek(pEASData->hwInstData, pWaveData->fileHandle, pos)) != EAS_SUCCESS)
return result;
/* get tag and size for next chunk */
if ((result = EAS_HWGetDWord(pEASData->hwInstData, pWaveData->fileHandle, &tag, EAS_TRUE)) != EAS_FALSE)
return result;
if ((result = EAS_HWGetDWord(pEASData->hwInstData, pWaveData->fileHandle, &size, EAS_FALSE)) != EAS_FALSE)
return result;
/* process chunk */
pos += 8;
metaType = EAS_METADATA_UNKNOWN;
switch (tag)
{
case CHUNK_INAM:
metaType = EAS_METADATA_TITLE;
break;
case CHUNK_IART:
metaType = EAS_METADATA_AUTHOR;
break;
case CHUNK_ICOP:
metaType = EAS_METADATA_COPYRIGHT;
break;
default:
{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "WaveParseHeader: %c%c%c%c chunk - %d byte(s) ignored\n",
(char) (tag >> 24), (char) (tag >> 16), (char) (tag >> 8), (char) tag, size); */ }
break;
}
/* process known metadata */
if (metaType != EAS_METADATA_UNKNOWN)
{
metaLen = pWaveData->metadata.bufferSize - 1;
if (metaLen > (EAS_I32) size)
metaLen = (EAS_I32) size;
if ((result = EAS_HWReadFile(pEASData->hwInstData, pWaveData->fileHandle, pWaveData->metadata.buffer, metaLen, &metaLen)) != EAS_SUCCESS)
return result;
pWaveData->metadata.buffer[metaLen] = 0;
pWaveData->metadata.callback(metaType, pWaveData->metadata.buffer, pWaveData->metadata.pUserData);
}
/* subtract this block */
if (size & 1)
size++;
infoSize -= (EAS_I32) size + 8;
if (infoSize == 0)
break;
pos += (EAS_I32) size;
}
/* restore original position */
return EAS_HWFileSeek(pEASData->hwInstData, pWaveData->fileHandle, restorePos);
}
#ifdef MMAPI_SUPPORT
/*----------------------------------------------------------------------------
* SaveFmtChunk()
*----------------------------------------------------------------------------
* Purpose:
* Save the fmt chunk for the MMAPI library
*----------------------------------------------------------------------------
*/
static EAS_RESULT SaveFmtChunk (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, S_WAVE_STATE *pWaveData, EAS_I32 fmtSize)
{
EAS_RESULT result;
EAS_I32 pos;
EAS_I32 count;
/* save current file position */
if ((result = EAS_HWFilePos(pEASData->hwInstData, fileHandle, &pos)) != EAS_SUCCESS)
return result;
/* allocate a chunk of memory */
pWaveData->fmtChunk = EAS_HWMalloc(pEASData->hwInstData, fmtSize);
if (!pWaveData->fmtChunk)
return EAS_ERROR_MALLOC_FAILED;
/* read the fmt chunk into memory */
if ((result = EAS_HWReadFile(pEASData->hwInstData, fileHandle, pWaveData->fmtChunk, fmtSize, &count)) != EAS_SUCCESS)
return result;
if (count != fmtSize)
return EAS_ERROR_FILE_READ_FAILED;
/* restore file position */
return EAS_HWFileSeek(pEASData->hwInstData, fileHandle, pos);
}
#endif

View File

@@ -0,0 +1,63 @@
/*----------------------------------------------------------------------------
*
* File:
* eas_wavefile.h
*
* Contents and purpose:
* Static data block for wave file 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: 439 $
* $Date: 2006-10-26 11:53:18 -0700 (Thu, 26 Oct 2006) $
*----------------------------------------------------------------------------
*/
#ifndef _EAS_WAVEFILE_H
#define _EAS_WAVEFILE_H
#include "eas_data.h"
#include "eas_pcm.h"
/*----------------------------------------------------------------------------
*
* S_WAVE_STATE
*
* This structure contains the WAVE file parser state information
*----------------------------------------------------------------------------
*/
typedef struct s_wave_state_tag
{
EAS_FILE_HANDLE fileHandle;
EAS_PCM_HANDLE streamHandle;
S_METADATA_CB metadata;
EAS_U32 time;
EAS_I32 fileOffset;
EAS_I32 audioOffset;
EAS_I32 mediaLength;
EAS_U32 audioSize;
EAS_U32 flags;
EAS_I16 fileType;
#ifdef MMAPI_SUPPORT
EAS_VOID_PTR fmtChunk;
#endif
EAS_I32 infoChunkPos;
EAS_I32 infoChunkSize;
} S_WAVE_STATE;
#endif

View File

@@ -0,0 +1,33 @@
/*----------------------------------------------------------------------------
*
* File:
* eas_wavefiledata.c
*
* Contents and purpose:
* Static data block for wave file 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_wavefile.h"
S_WAVE_STATE eas_WaveData;

View File

@@ -0,0 +1,82 @@
/*----------------------------------------------------------------------------
*
* File:
* eas_wt_IPC_frame.h
*
* Contents and purpose:
* This module contains data definitions for the interprocessor
* communications framework for a split-architecture synthesizer.
*
* This sample version writes IPC data to a file that can be used
* as a test vector for the DSP simulator. For a real-time system
* the file I/O is replaced with an IPC protocol in the hardware.
*
* Synchronization with the DSP is accomplished at the API level,
* i.e. the host code should call EAS_Render when it is ready to
* buffer another block of data for transmission to the DSP.
*
* 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: 818 $
* $Date: 2007-08-02 15:19:41 -0700 (Thu, 02 Aug 2007) $
*----------------------------------------------------------------------------
*/
#ifndef _EAS_WT_IPC_FRAME_H
#define _EAS_WT_IPC_FRAME_H
/*----------------------------------------------------------------------------
* S_WT_FRAME
*
* This structure contains the common parameters that are updated
*for each frame of audio.
*----------------------------------------------------------------------------
*/
typedef struct s_wt_frame_tag
{
EAS_I32 gainTarget;
EAS_I32 phaseIncrement;
#if defined(_FILTER_ENABLED)
EAS_I32 k;
EAS_I32 b1;
EAS_I32 b2;
#endif
} S_WT_FRAME;
/*----------------------------------------------------------------------------
* S_WT_CONFIG
*
* This structure contains state data for the wavetable engine
*----------------------------------------------------------------------------
*/
typedef struct s_wt_config_tag
{
EAS_U32 loopEnd; /* points to last PCM sample (not 1 beyond last) */
EAS_U32 loopStart; /* points to first sample at start of loop */
EAS_U32 phaseAccum; /* current sample, integer portion of phase */
#if (NUM_OUTPUT_CHANNELS == 2)
EAS_I16 gainLeft; /* left channel gain */
EAS_I16 gainRight; /* right channel gain */
#endif
EAS_I16 gain; /* current voice gain */
} S_WT_CONFIG;
#endif

View File

@@ -0,0 +1,661 @@
/*----------------------------------------------------------------------------
*
* File:
* eas_wtengine.c
*
* Contents and purpose:
* This file contains the critical synthesizer components that need to
* be optimized for best performance.
*
* Copyright Sonic Network Inc. 2004-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: 844 $
* $Date: 2007-08-23 14:33:32 -0700 (Thu, 23 Aug 2007) $
*----------------------------------------------------------------------------
*/
/*------------------------------------
* includes
*------------------------------------
*/
#include "eas_types.h"
#include "eas_math.h"
#include "eas_audioconst.h"
#include "eas_sndlib.h"
#include "eas_wtengine.h"
#include "eas_mixer.h"
/*----------------------------------------------------------------------------
* prototypes
*----------------------------------------------------------------------------
*/
extern void WT_NoiseGenerator (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame);
extern void WT_VoiceGain (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame);
#if defined(_OPTIMIZED_MONO)
extern void WT_InterpolateMono (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame);
#else
extern void WT_InterpolateNoLoop (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame);
extern void WT_Interpolate (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame);
#endif
#if defined(_FILTER_ENABLED)
extern void WT_VoiceFilter (S_FILTER_CONTROL*pFilter, S_WT_INT_FRAME *pWTIntFrame);
#endif
#if defined(_OPTIMIZED_MONO) || !defined(NATIVE_EAS_KERNEL)
/*----------------------------------------------------------------------------
* WT_VoiceGain
*----------------------------------------------------------------------------
* Purpose:
* Output gain for individual voice
*
* Inputs:
*
* Outputs:
*
*----------------------------------------------------------------------------
*/
/*lint -esym(715, pWTVoice) reserved for future use */
void WT_VoiceGain (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame)
{
EAS_I32 *pMixBuffer;
EAS_PCM *pInputBuffer;
EAS_I32 gain;
EAS_I32 gainIncrement;
EAS_I32 tmp0;
EAS_I32 tmp1;
EAS_I32 tmp2;
EAS_I32 numSamples;
#if (NUM_OUTPUT_CHANNELS == 2)
EAS_I32 gainLeft, gainRight;
#endif
/* initialize some local variables */
numSamples = pWTIntFrame->numSamples;
pMixBuffer = pWTIntFrame->pMixBuffer;
pInputBuffer = pWTIntFrame->pAudioBuffer;
/*lint -e{703} <avoid multiply for performance>*/
gainIncrement = (pWTIntFrame->frame.gainTarget - pWTIntFrame->prevGain) << (16 - SYNTH_UPDATE_PERIOD_IN_BITS);
if (gainIncrement < 0)
gainIncrement++;
/*lint -e{703} <avoid multiply for performance>*/
gain = pWTIntFrame->prevGain << 16;
#if (NUM_OUTPUT_CHANNELS == 2)
gainLeft = pWTVoice->gainLeft;
gainRight = pWTVoice->gainRight;
#endif
while (numSamples--) {
/* incremental gain step to prevent zipper noise */
tmp0 = *pInputBuffer++;
gain += gainIncrement;
/*lint -e{704} <avoid divide>*/
tmp2 = gain >> 16;
/* scale sample by gain */
tmp2 *= tmp0;
/* stereo output */
#if (NUM_OUTPUT_CHANNELS == 2)
/*lint -e{704} <avoid divide>*/
tmp2 = tmp2 >> 14;
/* get the current sample in the final mix buffer */
tmp1 = *pMixBuffer;
/* left channel */
tmp0 = tmp2 * gainLeft;
/*lint -e{704} <avoid divide>*/
tmp0 = tmp0 >> NUM_MIXER_GUARD_BITS;
tmp1 += tmp0;
*pMixBuffer++ = tmp1;
/* get the current sample in the final mix buffer */
tmp1 = *pMixBuffer;
/* right channel */
tmp0 = tmp2 * gainRight;
/*lint -e{704} <avoid divide>*/
tmp0 = tmp0 >> NUM_MIXER_GUARD_BITS;
tmp1 += tmp0;
*pMixBuffer++ = tmp1;
/* mono output */
#else
/* get the current sample in the final mix buffer */
tmp1 = *pMixBuffer;
/*lint -e{704} <avoid divide>*/
tmp2 = tmp2 >> (NUM_MIXER_GUARD_BITS - 1);
tmp1 += tmp2;
*pMixBuffer++ = tmp1;
#endif
}
}
#endif
#ifndef NATIVE_EAS_KERNEL
/*----------------------------------------------------------------------------
* WT_Interpolate
*----------------------------------------------------------------------------
* Purpose:
* Interpolation engine for wavetable synth
*
* Inputs:
*
* Outputs:
*
*----------------------------------------------------------------------------
*/
void WT_Interpolate (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame)
{
EAS_PCM *pOutputBuffer;
EAS_I32 phaseInc;
EAS_I32 phaseFrac;
EAS_I32 acc0;
const EAS_SAMPLE *pSamples;
const EAS_SAMPLE *loopEnd;
EAS_I32 samp1;
EAS_I32 samp2;
EAS_I32 numSamples;
/* initialize some local variables */
numSamples = pWTIntFrame->numSamples;
pOutputBuffer = pWTIntFrame->pAudioBuffer;
loopEnd = (const EAS_SAMPLE*) pWTVoice->loopEnd + 1;
pSamples = (const EAS_SAMPLE*) pWTVoice->phaseAccum;
/*lint -e{713} truncation is OK */
phaseFrac = pWTVoice->phaseFrac;
phaseInc = pWTIntFrame->frame.phaseIncrement;
/* fetch adjacent samples */
#if defined(_8_BIT_SAMPLES)
/*lint -e{701} <avoid multiply for performance>*/
samp1 = pSamples[0] << 8;
/*lint -e{701} <avoid multiply for performance>*/
samp2 = pSamples[1] << 8;
#else
samp1 = pSamples[0];
samp2 = pSamples[1];
#endif
while (numSamples--) {
/* linear interpolation */
acc0 = samp2 - samp1;
acc0 = acc0 * phaseFrac;
/*lint -e{704} <avoid divide>*/
acc0 = samp1 + (acc0 >> NUM_PHASE_FRAC_BITS);
/* save new output sample in buffer */
/*lint -e{704} <avoid divide>*/
*pOutputBuffer++ = (EAS_I16)(acc0 >> 2);
/* increment phase */
phaseFrac += phaseInc;
/*lint -e{704} <avoid divide>*/
acc0 = phaseFrac >> NUM_PHASE_FRAC_BITS;
/* next sample */
if (acc0 > 0) {
/* advance sample pointer */
pSamples += acc0;
phaseFrac = (EAS_I32)((EAS_U32)phaseFrac & PHASE_FRAC_MASK);
/* check for loop end */
acc0 = (EAS_I32) (pSamples - loopEnd);
if (acc0 >= 0)
pSamples = (const EAS_SAMPLE*) pWTVoice->loopStart + acc0;
/* fetch new samples */
#if defined(_8_BIT_SAMPLES)
/*lint -e{701} <avoid multiply for performance>*/
samp1 = pSamples[0] << 8;
/*lint -e{701} <avoid multiply for performance>*/
samp2 = pSamples[1] << 8;
#else
samp1 = pSamples[0];
samp2 = pSamples[1];
#endif
}
}
/* save pointer and phase */
pWTVoice->phaseAccum = (EAS_U32) pSamples;
pWTVoice->phaseFrac = (EAS_U32) phaseFrac;
}
#endif
#ifndef NATIVE_EAS_KERNEL
/*----------------------------------------------------------------------------
* WT_InterpolateNoLoop
*----------------------------------------------------------------------------
* Purpose:
* Interpolation engine for wavetable synth
*
* Inputs:
*
* Outputs:
*
*----------------------------------------------------------------------------
*/
void WT_InterpolateNoLoop (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame)
{
EAS_PCM *pOutputBuffer;
EAS_I32 phaseInc;
EAS_I32 phaseFrac;
EAS_I32 acc0;
const EAS_SAMPLE *pSamples;
EAS_I32 samp1;
EAS_I32 samp2;
EAS_I32 numSamples;
/* initialize some local variables */
numSamples = pWTIntFrame->numSamples;
pOutputBuffer = pWTIntFrame->pAudioBuffer;
phaseInc = pWTIntFrame->frame.phaseIncrement;
pSamples = (const EAS_SAMPLE*) pWTVoice->phaseAccum;
phaseFrac = (EAS_I32)pWTVoice->phaseFrac;
/* fetch adjacent samples */
#if defined(_8_BIT_SAMPLES)
/*lint -e{701} <avoid multiply for performance>*/
samp1 = pSamples[0] << 8;
/*lint -e{701} <avoid multiply for performance>*/
samp2 = pSamples[1] << 8;
#else
samp1 = pSamples[0];
samp2 = pSamples[1];
#endif
while (numSamples--) {
/* linear interpolation */
acc0 = samp2 - samp1;
acc0 = acc0 * phaseFrac;
/*lint -e{704} <avoid divide>*/
acc0 = samp1 + (acc0 >> NUM_PHASE_FRAC_BITS);
/* save new output sample in buffer */
/*lint -e{704} <avoid divide>*/
*pOutputBuffer++ = (EAS_I16)(acc0 >> 2);
/* increment phase */
phaseFrac += phaseInc;
/*lint -e{704} <avoid divide>*/
acc0 = phaseFrac >> NUM_PHASE_FRAC_BITS;
/* next sample */
if (acc0 > 0) {
/* advance sample pointer */
pSamples += acc0;
phaseFrac = (EAS_I32)((EAS_U32)phaseFrac & PHASE_FRAC_MASK);
/* fetch new samples */
#if defined(_8_BIT_SAMPLES)
/*lint -e{701} <avoid multiply for performance>*/
samp1 = pSamples[0] << 8;
/*lint -e{701} <avoid multiply for performance>*/
samp2 = pSamples[1] << 8;
#else
samp1 = pSamples[0];
samp2 = pSamples[1];
#endif
}
}
/* save pointer and phase */
pWTVoice->phaseAccum = (EAS_U32) pSamples;
pWTVoice->phaseFrac = (EAS_U32) phaseFrac;
}
#endif
#if defined(_FILTER_ENABLED) && !defined(NATIVE_EAS_KERNEL)
/*----------------------------------------------------------------------------
* WT_VoiceFilter
*----------------------------------------------------------------------------
* Purpose:
* Implements a 2-pole filter
*
* Inputs:
*
* Outputs:
*
*----------------------------------------------------------------------------
*/
void WT_VoiceFilter (S_FILTER_CONTROL *pFilter, S_WT_INT_FRAME *pWTIntFrame)
{
EAS_PCM *pAudioBuffer;
EAS_I32 k;
EAS_I32 b1;
EAS_I32 b2;
EAS_I32 z1;
EAS_I32 z2;
EAS_I32 acc0;
EAS_I32 acc1;
EAS_I32 numSamples;
/* initialize some local variables */
numSamples = pWTIntFrame->numSamples;
pAudioBuffer = pWTIntFrame->pAudioBuffer;
z1 = pFilter->z1;
z2 = pFilter->z2;
b1 = -pWTIntFrame->frame.b1;
/*lint -e{702} <avoid divide> */
b2 = -pWTIntFrame->frame.b2 >> 1;
/*lint -e{702} <avoid divide> */
k = pWTIntFrame->frame.k >> 1;
while (numSamples--)
{
/* do filter calculations */
acc0 = *pAudioBuffer;
acc1 = z1 * b1;
acc1 += z2 * b2;
acc0 = acc1 + k * acc0;
z2 = z1;
/*lint -e{702} <avoid divide> */
z1 = acc0 >> 14;
*pAudioBuffer++ = (EAS_I16) z1;
}
/* save delay values */
pFilter->z1 = (EAS_I16) z1;
pFilter->z2 = (EAS_I16) z2;
}
#endif
/*----------------------------------------------------------------------------
* WT_NoiseGenerator
*----------------------------------------------------------------------------
* Purpose:
* Generate pseudo-white noise using PRNG and interpolation engine
*
* Inputs:
*
* Outputs:
*
* Notes:
* This output is scaled -12dB to prevent saturation in the filter. 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. 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.
*----------------------------------------------------------------------------
*/
void WT_NoiseGenerator (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame)
{
EAS_PCM *pOutputBuffer;
EAS_I32 phaseInc;
EAS_I32 tmp0;
EAS_I32 tmp1;
EAS_I32 nInterpolatedSample;
EAS_I32 numSamples;
/* initialize some local variables */
numSamples = pWTIntFrame->numSamples;
pOutputBuffer = pWTIntFrame->pAudioBuffer;
phaseInc = pWTIntFrame->frame.phaseIncrement;
/* get last two samples generated */
/*lint -e{704} <avoid divide for performance>*/
tmp0 = (EAS_I32) (pWTVoice->phaseAccum) >> 18;
/*lint -e{704} <avoid divide for performance>*/
tmp1 = (EAS_I32) (pWTVoice->loopEnd) >> 18;
/* generate a buffer of noise */
while (numSamples--) {
nInterpolatedSample = MULT_AUDIO_COEF( tmp0, (PHASE_ONE - pWTVoice->phaseFrac));
nInterpolatedSample += MULT_AUDIO_COEF( tmp1, pWTVoice->phaseFrac);
*pOutputBuffer++ = (EAS_PCM) nInterpolatedSample;
/* update PRNG */
pWTVoice->phaseFrac += (EAS_U32) phaseInc;
if (GET_PHASE_INT_PART(pWTVoice->phaseFrac)) {
tmp0 = tmp1;
pWTVoice->phaseAccum = pWTVoice->loopEnd;
pWTVoice->loopEnd = (5 * pWTVoice->loopEnd + 1);
tmp1 = (EAS_I32) (pWTVoice->loopEnd) >> 18;
pWTVoice->phaseFrac = GET_PHASE_FRAC_PART(pWTVoice->phaseFrac);
}
}
}
#ifndef _OPTIMIZED_MONO
/*----------------------------------------------------------------------------
* WT_ProcessVoice
*----------------------------------------------------------------------------
* Purpose:
* This routine does the block processing for one voice. It is isolated
* from the main synth code to allow for various implementation-specific
* optimizations. It calls the interpolator, filter, and gain routines
* appropriate for a particular configuration.
*
* Inputs:
*
* Outputs:
*
* Notes:
*----------------------------------------------------------------------------
*/
void WT_ProcessVoice (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame)
{
/* use noise generator */
if (pWTVoice->loopStart == WT_NOISE_GENERATOR)
WT_NoiseGenerator(pWTVoice, pWTIntFrame);
/* generate interpolated samples for looped waves */
else if (pWTVoice->loopStart != pWTVoice->loopEnd)
WT_Interpolate(pWTVoice, pWTIntFrame);
/* generate interpolated samples for unlooped waves */
else
{
WT_InterpolateNoLoop(pWTVoice, pWTIntFrame);
}
#ifdef _FILTER_ENABLED
if (pWTIntFrame->frame.k != 0)
WT_VoiceFilter(&pWTVoice->filter, pWTIntFrame);
#endif
//2 TEST NEW MIXER FUNCTION
#ifdef UNIFIED_MIXER
{
EAS_I32 gainLeft, gainIncLeft;
#if (NUM_OUTPUT_CHANNELS == 2)
EAS_I32 gainRight, gainIncRight;
#endif
gainLeft = (pWTIntFrame->prevGain * pWTVoice->gainLeft) << 1;
gainIncLeft = (((pWTIntFrame->frame.gainTarget * pWTVoice->gainLeft) << 1) - gainLeft) >> SYNTH_UPDATE_PERIOD_IN_BITS;
#if (NUM_OUTPUT_CHANNELS == 2)
gainRight = (pWTIntFrame->prevGain * pWTVoice->gainRight) << 1;
gainIncRight = (((pWTIntFrame->frame.gainTarget * pWTVoice->gainRight) << 1) - gainRight) >> SYNTH_UPDATE_PERIOD_IN_BITS;
EAS_MixStream(
pWTIntFrame->pAudioBuffer,
pWTIntFrame->pMixBuffer,
pWTIntFrame->numSamples,
gainLeft,
gainRight,
gainIncLeft,
gainIncRight,
MIX_FLAGS_STEREO_OUTPUT);
#else
EAS_MixStream(
pWTIntFrame->pAudioBuffer,
pWTIntFrame->pMixBuffer,
pWTIntFrame->numSamples,
gainLeft,
0,
gainIncLeft,
0,
0);
#endif
}
#else
/* apply gain, and left and right gain */
WT_VoiceGain(pWTVoice, pWTIntFrame);
#endif
}
#endif
#if defined(_OPTIMIZED_MONO) && !defined(NATIVE_EAS_KERNEL)
/*----------------------------------------------------------------------------
* WT_InterpolateMono
*----------------------------------------------------------------------------
* Purpose:
* A C version of the sample interpolation + gain routine, optimized for mono.
* It's not pretty, but it matches the assembly code exactly.
*
* Inputs:
*
* Outputs:
*
* Notes:
*----------------------------------------------------------------------------
*/
void WT_InterpolateMono (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame)
{
EAS_I32 *pMixBuffer;
const EAS_I8 *pLoopEnd;
const EAS_I8 *pCurrentPhaseInt;
EAS_I32 numSamples;
EAS_I32 gain;
EAS_I32 gainIncrement;
EAS_I32 currentPhaseFrac;
EAS_I32 phaseInc;
EAS_I32 tmp0;
EAS_I32 tmp1;
EAS_I32 tmp2;
EAS_I8 *pLoopStart;
numSamples = pWTIntFrame->numSamples;
pMixBuffer = pWTIntFrame->pMixBuffer;
/* calculate gain increment */
gainIncrement = (pWTIntFrame->gainTarget - pWTIntFrame->prevGain) << (16 - SYNTH_UPDATE_PERIOD_IN_BITS);
if (gainIncrement < 0)
gainIncrement++;
gain = pWTIntFrame->prevGain << 16;
pCurrentPhaseInt = pWTVoice->pPhaseAccum;
currentPhaseFrac = pWTVoice->phaseFrac;
phaseInc = pWTIntFrame->phaseIncrement;
pLoopStart = pWTVoice->pLoopStart;
pLoopEnd = pWTVoice->pLoopEnd + 1;
InterpolationLoop:
tmp0 = (EAS_I32)(pCurrentPhaseInt - pLoopEnd);
if (tmp0 >= 0)
pCurrentPhaseInt = pLoopStart + tmp0;
tmp0 = *pCurrentPhaseInt;
tmp1 = *(pCurrentPhaseInt + 1);
tmp2 = phaseInc + currentPhaseFrac;
tmp1 = tmp1 - tmp0;
tmp1 = tmp1 * currentPhaseFrac;
tmp1 = tmp0 + (tmp1 >> NUM_EG1_FRAC_BITS);
pCurrentPhaseInt += (tmp2 >> NUM_PHASE_FRAC_BITS);
currentPhaseFrac = tmp2 & PHASE_FRAC_MASK;
gain += gainIncrement;
tmp2 = (gain >> SYNTH_UPDATE_PERIOD_IN_BITS);
tmp0 = *pMixBuffer;
tmp2 = tmp1 * tmp2;
tmp2 = (tmp2 >> 9);
tmp0 = tmp2 + tmp0;
*pMixBuffer++ = tmp0;
numSamples--;
if (numSamples > 0)
goto InterpolationLoop;
pWTVoice->pPhaseAccum = pCurrentPhaseInt;
pWTVoice->phaseFrac = currentPhaseFrac;
/*lint -e{702} <avoid divide>*/
pWTVoice->gain = (EAS_I16)(gain >> SYNTH_UPDATE_PERIOD_IN_BITS);
}
#endif
#ifdef _OPTIMIZED_MONO
/*----------------------------------------------------------------------------
* WT_ProcessVoice
*----------------------------------------------------------------------------
* Purpose:
* This routine does the block processing for one voice. It is isolated
* from the main synth code to allow for various implementation-specific
* optimizations. It calls the interpolator, filter, and gain routines
* appropriate for a particular configuration.
*
* Inputs:
*
* Outputs:
*
* Notes:
* This special version works handles an optimized mono-only signal
* without filters
*----------------------------------------------------------------------------
*/
void WT_ProcessVoice (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame)
{
/* use noise generator */
if (pWTVoice->loopStart== WT_NOISE_GENERATOR)
{
WT_NoiseGenerator(pWTVoice, pWTIntFrame);
WT_VoiceGain(pWTVoice, pWTIntFrame);
}
/* or generate interpolated samples */
else
{
WT_InterpolateMono(pWTVoice, pWTIntFrame);
}
}
#endif

View File

@@ -0,0 +1,171 @@
/*----------------------------------------------------------------------------
*
* File:
* eas_wtengine.h
*
* Contents and purpose:
* This file defines the interface for wavetable synthesis engine
*
* 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: 818 $
* $Date: 2007-08-02 15:19:41 -0700 (Thu, 02 Aug 2007) $
*----------------------------------------------------------------------------
*/
#ifndef _EAS_WTENGINE_H
#define _EAS_WTENGINE_H
/* option sanity check */
#if defined(_OPTIMIZED_MONO) && defined(_FILTER_ENABLED)
#error "Incompatible build settings: _OPTIMIZED_MONO cannot be used with _FILTER_ENABLED"
#endif
#if defined(_OPTIMIZED_MONO) && (NUM_OUTPUT_CHANNELS != 1)
#error "Incompatible build settings: _OPTIMIZED_MONO can only be used with NUM_OUTPUT_CHANNELS = 1"
#endif
#include "eas_wt_IPC_frame.h"
/*----------------------------------------------------------------------------
* defines
*----------------------------------------------------------------------------
*/
#define WT_NOISE_GENERATOR 0xffffffff
/*----------------------------------------------------------------------------
* typedefs
*----------------------------------------------------------------------------
*/
/*----------------------------------------------------------------------------
* S_WT_INT_FRAME
*
* This structure includes S_WT_FRAME plus the bus mixing
* parameters for the internal voices.
*----------------------------------------------------------------------------
*/
typedef struct s_wt_int_frame_tag
{
S_WT_FRAME frame;
EAS_PCM *pAudioBuffer;
EAS_I32 *pMixBuffer;
EAS_I32 numSamples;
EAS_I32 prevGain;
} S_WT_INT_FRAME;
#if defined(_FILTER_ENABLED)
/*----------------------------------------------------------------------------
* S_FILTER_CONTROL data structure
*----------------------------------------------------------------------------
*/
typedef struct s_filter_control_tag
{
EAS_I16 z1; /* 1 sample delay state variable */
EAS_I16 z2; /* 2 sample delay state variable */
} S_FILTER_CONTROL;
#endif
/*------------------------------------
* S_LFO_CONTROL data structure
*------------------------------------
*/
typedef struct s_lfo_control_tag
{
EAS_I16 lfoValue; /* LFO current output value */
EAS_I16 lfoPhase; /* LFO current phase */
} S_LFO_CONTROL;
/* bit definitions for S_WT_VOICE:flags */
#define WT_FLAGS_ADPCM_NIBBLE 1 /* high/low nibble flag */
#define WT_FLAGS_ADPCM_READY 2 /* first 2 samples are decoded */
#define WT_FLAGS_USE_ADPCM 4 /* sample is ADPCM encoded */
/* eg1State and eg2State */
typedef enum {
eEnvelopeStateInit = 0,
eEnvelopeStateDelay,
eEnvelopeStateAttack,
eEnvelopeStateHold,
eEnvelopeStateDecay,
eEnvelopeStateSustain,
eEnvelopeStateRelease,
eEnvelopeStateMuting,
eEnvelopeStateMuted,
eEnvelopeStateInvalid /* should never be in this state! */
} E_ENVELOPE_STATE;
#define DEFAULT_EG1_STATE eEnvelopeStateAttack
#define DEFAULT_EG1_VALUE 0
#define DEFAULT_EG1_INCREMENT 0
#define DEFAULT_EG2_STATE eEnvelopeStateAttack
#define DEFAULT_EG2_VALUE 0
#define DEFAULT_EG2_INCREMENT 0
/*----------------------------------------------------------------------------
* S_WT_VOICE
*
* This structure contains state data for the wavetable engine
*----------------------------------------------------------------------------
*/
typedef struct s_wt_voice_tag
{
EAS_U32 loopEnd; /* points to last PCM sample (not 1 beyond last) */
EAS_U32 loopStart; /* points to first sample at start of loop */
EAS_U32 phaseAccum; /* current sample, integer portion of phase */
EAS_U32 phaseFrac; /* fractional portion of phase */
#if (NUM_OUTPUT_CHANNELS == 2)
EAS_I16 gainLeft; /* current gain, left ch */
EAS_I16 gainRight; /* current gain, right ch */
#endif
#if defined(_FILTER_ENABLED)
S_FILTER_CONTROL filter; /* low pass filter */
#endif
S_LFO_CONTROL modLFO; /* modulator LFO */
#ifdef DLS_SYNTHESIZER
S_LFO_CONTROL vibLFO; /* vibrato LFO */
#endif
/* envelope control */
EAS_I16 eg1Value;
EAS_I16 eg2Value;
EAS_I16 eg1Increment;
EAS_I16 eg2Increment;
EAS_U8 eg1State;
EAS_U8 eg2State;
EAS_U16 artIndex; /* index to articulation params */
} S_WT_VOICE;
/*----------------------------------------------------------------------------
* prototypes
*----------------------------------------------------------------------------
*/
EAS_BOOL WT_CheckSampleEnd (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame, EAS_BOOL update);
void WT_ProcessVoice (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame);
#ifdef EAS_SPLIT_WT_SYNTH
void WTE_ConfigVoice (EAS_I32 voiceNum, S_WT_CONFIG *pWTConfig, EAS_FRAME_BUFFER_HANDLE pFrameBuffer);
void WTE_ProcessVoice (EAS_I32 voiceNum, S_WT_FRAME *pWTParams, EAS_FRAME_BUFFER_HANDLE pFrameBuffer);
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,66 @@
/*----------------------------------------------------------------------------
*
* File:
* eas_wtsynth.h
*
* Contents and purpose:
* This file defines the interface for synthesizer engine
*
* 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) $
*----------------------------------------------------------------------------
*/
#ifndef _EAS_WTSYNTH_H
#define _EAS_WTSYNTH_H
#include "eas_sndlib.h"
#include "eas_wtengine.h"
/* adjust the filter cutoff frequency to the sample rate */
#if defined (_SAMPLE_RATE_8000)
#define FILTER_CUTOFF_FREQ_ADJUST 0
#elif defined (_SAMPLE_RATE_16000)
#define FILTER_CUTOFF_FREQ_ADJUST 1200
#elif defined (_SAMPLE_RATE_20000)
#define FILTER_CUTOFF_FREQ_ADJUST 1586
#elif defined (_SAMPLE_RATE_22050)
#define FILTER_CUTOFF_FREQ_ADJUST 1756
#elif defined (_SAMPLE_RATE_24000)
#define FILTER_CUTOFF_FREQ_ADJUST 1902
#elif defined (_SAMPLE_RATE_32000)
#define FILTER_CUTOFF_FREQ_ADJUST 2400
#elif defined (_SAMPLE_RATE_44100)
#define FILTER_CUTOFF_FREQ_ADJUST 2956
#elif defined (_SAMPLE_RATE_48000)
#define FILTER_CUTOFF_FREQ_ADJUST 3102
#else
#error "_SAMPLE_RATE_XXXXX must be defined to valid rate"
#endif
/* function prototypes */
void WT_UpdateLFO (S_LFO_CONTROL *pLFO, EAS_I16 phaseInc);
#if defined(_FILTER_ENABLED) || defined(DLS_SYNTHESIZER)
void WT_SetFilterCoeffs (S_WT_INT_FRAME *pIntFrame, EAS_I32 cutoff, EAS_I32 resonance);
#endif
#endif

View File

@@ -0,0 +1,850 @@
/*----------------------------------------------------------------------------
*
* File:
* eas_xmf.c
* 5
* Contents and purpose:
* XMF File 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: 501 $
* $Date: 2006-12-11 17:53:36 -0800 (Mon, 11 Dec 2006) $
*----------------------------------------------------------------------------
*/
#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_xmf.h"
#include "eas_xmfdata.h"
#include "eas_config.h"
#include "eas_vm_protos.h"
#include "eas_mdls.h"
#include "eas_smf.h"
/* XMF header file type */
#define XMF_IDENTIFIER 0x584d465f
#define XMF_VERSION_2_00 0x322e3030
#define XMF_FILE_TYPE 0x00000002
#define XMF_SPEC_LEVEL 0x00000001
#define XMF_RIFF_CHUNK 0x52494646
#define XMF_RIFF_DLS 0x444c5320
#define XMF_SMF_CHUNK 0x4d546864
/* local prototypes */
static EAS_RESULT XMF_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset);
static EAS_RESULT XMF_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
static EAS_RESULT XMF_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime);
static EAS_RESULT XMF_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode);
static EAS_RESULT XMF_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState);
static EAS_RESULT XMF_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
static EAS_RESULT XMF_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
static EAS_RESULT XMF_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
static EAS_RESULT XMF_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
static EAS_RESULT XMF_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value);
static EAS_RESULT XMF_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue);
static EAS_RESULT XMF_FindFileContents (EAS_HW_DATA_HANDLE hwInstData, S_XMF_DATA *pXMFData);
static EAS_RESULT XMF_ReadNode (EAS_HW_DATA_HANDLE hwInstData, S_XMF_DATA *pXMFData, EAS_I32 nodeOffset, EAS_I32 *pLength);
static EAS_RESULT XMF_ReadVLQ (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_I32 *value);
/*----------------------------------------------------------------------------
*
* XMF_Parser
*
* This structure contains the functional interface for the XMF parser
*----------------------------------------------------------------------------
*/
const S_FILE_PARSER_INTERFACE EAS_XMF_Parser =
{
XMF_CheckFileType,
XMF_Prepare,
XMF_Time,
XMF_Event,
XMF_State,
XMF_Close,
XMF_Reset,
XMF_Pause,
XMF_Resume,
NULL,
XMF_SetData,
XMF_GetData,
NULL
};
/*----------------------------------------------------------------------------
* XMF_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 XMF_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset)
{
S_XMF_DATA *pXMFData;
EAS_RESULT result;
EAS_U32 temp;
/* assume we don't recognize it initially */
*ppHandle = NULL;
/* read the file identifier */
if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &temp, EAS_TRUE)) != EAS_SUCCESS)
return result;
if (temp != XMF_IDENTIFIER)
return EAS_SUCCESS;
/* read the version */
if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &temp, EAS_TRUE)) != EAS_SUCCESS)
return result;
if (temp != XMF_VERSION_2_00)
{
{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "XMF file version was 0x%08x, expected 0x%08x\n", temp, XMF_VERSION_2_00); */ }
return EAS_SUCCESS;
}
/* read the file type */
if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &temp, EAS_TRUE)) != EAS_SUCCESS)
return result;
if (temp != XMF_FILE_TYPE)
{
{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "XMF file type was 0x%08x, expected 0x%08x\n", temp, XMF_FILE_TYPE); */ }
return EAS_SUCCESS;
}
/* read the spec level */
if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &temp, EAS_TRUE)) != EAS_SUCCESS)
return result;
if (temp != XMF_SPEC_LEVEL)
{
{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "XMF file spec was 0x%08x, expected 0x%08x\n", temp, XMF_SPEC_LEVEL); */ }
return EAS_SUCCESS;
}
/* check for static memory allocation */
if (pEASData->staticMemoryModel)
pXMFData = EAS_CMEnumData(EAS_CM_XMF_DATA);
else
pXMFData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_XMF_DATA));
if (!pXMFData)
return EAS_ERROR_MALLOC_FAILED;
/* zero the memory to insure complete initialization */
EAS_HWMemSet((void *)pXMFData,0, sizeof(S_XMF_DATA));
pXMFData->fileHandle = fileHandle;
pXMFData->fileOffset = offset;
*ppHandle = pXMFData;
/* locate the SMF and DLS contents */
if ((result = XMF_FindFileContents(pEASData->hwInstData, pXMFData)) != EAS_SUCCESS)
{
{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "No SMF data found in XMF file\n"); */ }
return result;
}
/* let the SMF parser take over */
if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, pXMFData->midiOffset)) != EAS_SUCCESS)
return result;
return SMF_CheckFileType(pEASData, fileHandle, &pXMFData->pSMFData, pXMFData->midiOffset);
}
/*----------------------------------------------------------------------------
* XMF_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 XMF_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
{
S_XMF_DATA* pXMFData;
EAS_RESULT result;
/* parse DLS collection */
pXMFData = (S_XMF_DATA*) pInstData;
if (pXMFData->dlsOffset != 0)
{
if ((result = DLSParser(pEASData->hwInstData, pXMFData->fileHandle, pXMFData->dlsOffset, &pXMFData->pDLS)) != EAS_SUCCESS)
{
{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Error converting XMF DLS data\n"); */ }
return result;
}
}
/* Prepare the SMF parser */
if ((result = SMF_Prepare(pEASData, pXMFData->pSMFData)) != EAS_SUCCESS)
return result;
/* if no DLS file, skip this step */
if (pXMFData->pDLS == NULL)
return EAS_SUCCESS;
/* tell the synth to use the DLS collection */
result = VMSetDLSLib(((S_SMF_DATA*) pXMFData->pSMFData)->pSynth, pXMFData->pDLS);
if (result == EAS_SUCCESS)
{
DLSAddRef(pXMFData->pDLS);
VMInitializeAllChannels(pEASData->pVoiceMgr, ((S_SMF_DATA*) pXMFData->pSMFData)->pSynth);
}
return result;
}
/*----------------------------------------------------------------------------
* XMF_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:
*
*----------------------------------------------------------------------------
*/
static EAS_RESULT XMF_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime)
{
return SMF_Time(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData, pTime);
}
/*----------------------------------------------------------------------------
* XMF_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 XMF_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode)
{
return SMF_Event(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData, parserMode);
}
/*----------------------------------------------------------------------------
* XMF_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:
*
*----------------------------------------------------------------------------
*/
static EAS_RESULT XMF_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pState)
{
return SMF_State(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData, pState);
}
/*----------------------------------------------------------------------------
* XMF_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 XMF_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
{
S_XMF_DATA* pXMFData;
EAS_RESULT result;
pXMFData = (S_XMF_DATA *)pInstData;
/* close the SMF stream, it will close the file handle */
if ((result = SMF_Close(pEASData, pXMFData->pSMFData)) != EAS_SUCCESS)
return result;
if (pXMFData->pDLS)
DLSCleanup(pEASData->hwInstData, pXMFData->pDLS);
/* if using dynamic memory, free it */
if (!pEASData->staticMemoryModel)
{
/* free the instance data */
EAS_HWFree(pEASData->hwInstData, pXMFData);
}
return EAS_SUCCESS;
}
/*----------------------------------------------------------------------------
* XMF_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 XMF_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
{
return SMF_Reset(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData);
}
/*----------------------------------------------------------------------------
* XMF_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 XMF_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
{
return SMF_Pause(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData);
}
/*----------------------------------------------------------------------------
* XMF_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:
*
*----------------------------------------------------------------------------
*/
static EAS_RESULT XMF_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
{
return SMF_Resume(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData);
}
/*----------------------------------------------------------------------------
* XMF_SetData()
*----------------------------------------------------------------------------
* Purpose:
* Sets the playback rate of the underlying SMF file
*
* Inputs:
* pEASData - pointer to overall EAS data structure
* handle - pointer to file handle
* rate - rate (28-bit fraction)
*
* Outputs:
*
*
* Side Effects:
*
*----------------------------------------------------------------------------
*/
static EAS_RESULT XMF_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value)
{
return SMF_SetData(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData, param, value);
}
/*----------------------------------------------------------------------------
* XMF_GetData()
*----------------------------------------------------------------------------
* Purpose:
* Gets the file type
*
* Inputs:
* pEASData - pointer to overall EAS data structure
* handle - pointer to file handle
* rate - rate (28-bit fraction)
*
* Outputs:
*
*
* Side Effects:
*
*----------------------------------------------------------------------------
*/
static EAS_RESULT XMF_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue)
{
EAS_RESULT result;
/* call SMF parser to get value */
if ((result = SMF_GetData(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData, param, pValue)) != EAS_SUCCESS)
return result;
/* special case for file type */
if (param == PARSER_DATA_FILE_TYPE)
{
if (*pValue == EAS_FILE_SMF0)
*pValue = EAS_FILE_XMF0;
else if (*pValue == EAS_FILE_SMF1)
*pValue = EAS_FILE_XMF1;
}
return EAS_SUCCESS;
}
/*----------------------------------------------------------------------------
* XMF_FindFileContents()
*----------------------------------------------------------------------------
* Purpose:
* Finds SMF data and DLS data in XMF file, and remembers offset for each.
* If more than one is found, uses the first one found of each.
* Makes assumptions about the format of a mobile XMF file
*
* Inputs:
* pEASData - pointer to overall EAS data structure
* pXMFData - pointer to XMF parser instance data
* handle - pointer to file handle
*
* Outputs:
*
*
* Side Effects:
*
*----------------------------------------------------------------------------
*/
static EAS_RESULT XMF_FindFileContents (EAS_HW_DATA_HANDLE hwInstData, S_XMF_DATA *pXMFData)
{
EAS_RESULT result;
EAS_I32 value;
EAS_I32 length;
/* initialize offsets */
pXMFData->dlsOffset = pXMFData->midiOffset = 0;
/* read file length, ignore it for now */
if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &value)) != EAS_SUCCESS)
return result;
/* read MetaDataTypesTable length and skip over it */
if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &value)) != EAS_SUCCESS)
return result;
if ((result = EAS_HWFileSeekOfs(hwInstData, pXMFData->fileHandle, value)) != EAS_SUCCESS)
return result;
/* get TreeStart offset and jump to it */
if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &value)) != EAS_SUCCESS)
return result;
if ((result = XMF_ReadNode(hwInstData, pXMFData, value, &length)) != EAS_SUCCESS)
return result;
/* check for SMF data */
if (pXMFData->midiOffset == 0)
{
{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "No SMF data found in XMF file\n"); */ }
return EAS_ERROR_FILE_FORMAT;
}
/* check for SFM in wrong order */
if ((pXMFData->dlsOffset > 0) && (pXMFData->midiOffset < pXMFData->dlsOffset))
{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "DLS data must precede SMF data in Mobile XMF file\n"); */ }
return EAS_SUCCESS;
}
/*----------------------------------------------------------------------------
* XMF_ReadNode()
*----------------------------------------------------------------------------
* Purpose:
*
* Inputs:
*
* Outputs:
*
*
* Side Effects:
*
*----------------------------------------------------------------------------
*/
static EAS_RESULT XMF_ReadNode (EAS_HW_DATA_HANDLE hwInstData, S_XMF_DATA *pXMFData, EAS_I32 nodeOffset, EAS_I32 *pLength)
{
EAS_RESULT result;
EAS_I32 refType;
EAS_I32 numItems;
EAS_I32 offset;
EAS_I32 length;
EAS_I32 headerLength;
EAS_U32 chunkType;
/* seek to start of node */
if ((result = EAS_HWFileSeek(hwInstData, pXMFData->fileHandle, nodeOffset)) != EAS_SUCCESS)
return result;
/* get node length */
if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, pLength)) != EAS_SUCCESS)
return result;
/* get number of contained items */
if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &numItems)) != EAS_SUCCESS)
return result;
/* get node header length */
if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &headerLength)) != EAS_SUCCESS)
return result;
/* get metadata length */
if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &length)) != EAS_SUCCESS)
return result;
/* get the current location */
if ((result = EAS_HWFilePos(hwInstData, pXMFData->fileHandle, &offset)) != EAS_SUCCESS)
return result;
/* skip to node contents */
if ((result = EAS_HWFileSeek(hwInstData, pXMFData->fileHandle, nodeOffset + headerLength)) != EAS_SUCCESS)
return result;
/* get reference type */
if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &refType)) != EAS_SUCCESS)
return result;
/* get the current location */
if ((result = EAS_HWFilePos(hwInstData, pXMFData->fileHandle, &offset)) != EAS_SUCCESS)
return result;
/* process file node */
if (numItems == 0)
{
/* if in-file resource, find out where it is and jump to it */
if (refType == 2)
{
if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &offset)) != EAS_SUCCESS)
return result;
offset += pXMFData->fileOffset;
if ((result = EAS_HWFileSeek(hwInstData, pXMFData->fileHandle, offset)) != EAS_SUCCESS)
return result;
}
/* or else it must be an inline resource */
else if (refType != 1)
{
{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unexpected reference type %d\n", refType); */ }
return EAS_ERROR_FILE_FORMAT;
}
/* get the chunk type */
if ((result = EAS_HWGetDWord(hwInstData, pXMFData->fileHandle, &chunkType, EAS_TRUE)) != EAS_SUCCESS)
return result;
/* found a RIFF chunk, check for DLS type */
if (chunkType == XMF_RIFF_CHUNK)
{
/* skip length */
if ((result = EAS_HWFileSeekOfs(hwInstData, pXMFData->fileHandle, sizeof(EAS_I32))) != EAS_SUCCESS)
return result;
/* get RIFF file type */
if ((result = EAS_HWGetDWord(hwInstData, pXMFData->fileHandle, &chunkType, EAS_TRUE)) != EAS_SUCCESS)
return result;
if (chunkType == XMF_RIFF_DLS)
pXMFData->dlsOffset = offset;
}
/* found an SMF chunk */
else if (chunkType == XMF_SMF_CHUNK)
pXMFData->midiOffset = offset;
}
/* folder node, process the items in the list */
else
{
for ( ; numItems > 0; numItems--)
{
/* process this item */
if ((result = XMF_ReadNode(hwInstData, pXMFData, offset, &length)) != EAS_SUCCESS)
return result;
/* seek to start of next item */
offset += length;
if ((result = EAS_HWFileSeek(hwInstData, pXMFData->fileHandle, offset)) != EAS_SUCCESS)
return result;
}
}
return EAS_SUCCESS;
}
#if 0
/*----------------------------------------------------------------------------
* XMF_FindFileContents()
*----------------------------------------------------------------------------
* Purpose:
* Finds SMF data and DLS data in XMF file, and remembers offset for each.
* If more than one is found, uses the first one found of each.
* Makes assumptions about the format of a mobile XMF file
*
* Inputs:
* pEASData - pointer to overall EAS data structure
* pXMFData - pointer to XMF parser instance data
* handle - pointer to file handle
*
* Outputs:
*
*
* Side Effects:
*
*----------------------------------------------------------------------------
*/
static EAS_RESULT XMF_FindFileContents(S_EAS_DATA *pEASData, S_XMF_DATA *pXMFData, EAS_FILE_HANDLE fileHandle)
{
EAS_RESULT result;
EAS_I32 offset;
EAS_I32 value;
EAS_I32 numItems;
EAS_I32 length;
EAS_CHAR id[4];
EAS_I32 location;
/* init dls offset, so that we know we haven't found a dls chunk yet */
pXMFData->dlsOffset = 0;
/* read file length, ignore it for now */
if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS)
return result;
/* read MetaDataTypesTable length and skip over it */
if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS)
return result;
if ((result = EAS_HWFileSeekOfs(pEASData, fileHandle, value)) != EAS_SUCCESS)
return result;
/* get TreeStart offset and jump to it */
if ((result = XMF_ReadVLQ(pEASData, fileHandle, &offset)) != EAS_SUCCESS)
return result;
if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, offset)) != EAS_SUCCESS)
return result;
/* read node length, ignore it for now */
if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS)
return result;
/* read number of contained items */
if ((result = XMF_ReadVLQ(pEASData, fileHandle, &numItems)) != EAS_SUCCESS)
return result;
/*read node header length */
if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS)
return result;
/*go to the node offset */
if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, offset + value)) != EAS_SUCCESS)
return result;
/* read Reference Type */
if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS)
return result;
/* make sure it is an in-line resource, for now */
if (value != 1)
{
{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Problem parsing XMF file tree\n"); */ }
return EAS_FAILURE;
}
/* parse through the list of items */
while (numItems > 0)
{
/*get current offset */
if ((result = EAS_HWFilePos(pEASData->hwInstData, fileHandle, &offset)) != EAS_SUCCESS)
return result;
/*read node length */
if ((result = XMF_ReadVLQ(pEASData, fileHandle, &length)) != EAS_SUCCESS)
return result;
/* read number of items */
if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS)
return result;
/* make sure not a folder */
if (value != 0)
{
{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Problem parsing XMF file node\n"); */ }
return EAS_FAILURE;
}
/* read offset to resource and jump to it */
if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS)
return result;
if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, offset + value)) != EAS_SUCCESS)
return result;
/* read Reference Type */
if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS)
return result;
/* make sure it is an in-line resource */
if (value != 1)
{
{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Problem parsing XMF file node\n"); */ }
return EAS_FAILURE;
}
/* get current offset as a possible location for SMF file or DLS file */
if ((result = EAS_HWFilePos(pEASData->hwInstData, fileHandle, &location)) != EAS_SUCCESS)
return result;
/* read four bytes */
if ((result = EAS_HWReadFile(pEASData->hwInstData, fileHandle, id, sizeof(id), &value)) != EAS_SUCCESS)
return result;
/* check if DLS */
if (pXMFData->dlsOffset == 0 && id[0] == 'R' && id[1] == 'I' && id[2] == 'F' && id[3] == 'F')
{
//remember offset
pXMFData->dlsOffset = location;
}
/* else check if SMF */
else if (id[0] == 'M' && id[1] == 'T' && id[2] == 'h' && id[3] == 'd')
{
//remember offset
pXMFData->midiOffset = location;
//we are done
return EAS_SUCCESS;
}
//one less item
numItems--;
//if more data, go to the next item
if (numItems >0)
{
if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, offset + length)) != EAS_SUCCESS)
return result;
}
}
return EAS_FAILURE;
}
#endif
/*----------------------------------------------------------------------------
* XMF_ReadVLQ()
*----------------------------------------------------------------------------
* Purpose:
* Reads a VLQ encoded value from the file referenced by fileHandle
*
* Inputs:
* pEASData - pointer to overall EAS data structure
* fileHandle - pointer to file handle
*
* Outputs:
* value - pointer to the value decoded from the VLQ data
*
*
* Side Effects:
*
*----------------------------------------------------------------------------
*/
static EAS_RESULT XMF_ReadVLQ (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_I32 *value)
{
EAS_RESULT result;
EAS_U8 c;
*value = 0;
if ((result = EAS_HWGetByte(hwInstData, fileHandle, &c)) != EAS_SUCCESS)
return result;
while (c > 0x7F)
{
/*lint -e{703} shift for performance */
*value = (*value << 7) | (c & 0x7F);
if ((result = EAS_HWGetByte(hwInstData, fileHandle, &c)) != EAS_SUCCESS)
return result;
}
/*lint -e{703} shift for performance */
*value = (*value << 7) | c;
return EAS_SUCCESS;
}

View File

@@ -0,0 +1,60 @@
/*----------------------------------------------------------------------------
*
* File:
* eas_xmf.h
*
* Contents and purpose:
* XMF Type 0 and 1 File 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_XMF_H
#define _EAS_XMF_H
#ifndef MAX_XMF_STREAMS
#define MAX_XMF_STREAMS 16
#endif
/* offsets in to the XMF file */
#define XMF_OFS_HEADER_SIZE 4
#define XMF_OFS_FILE_TYPE 8
#define XMF_OFS_NUM_TRACKS 10
/* size of chunk info (chunk ID + chunk size) */
#define XMF_CHUNK_INFO_SIZE 8
/* 'MTrk' track chunk ID */
#define XMF_CHUNK_TYPE_TRACK 0x4d54726bL
/* some useful meta-events */
#define XMF_META_END_OF_TRACK 0x2f
#define XMF_META_TEMPO 0x51
/* default timebase (120BPM) */
#define XMF_DEFAULT_TIMEBASE 500000L
/* value for pXMFStream->ticks to signify end of track */
#define XMF_END_OF_TRACK 0xffffffff
#endif /* end _EAS_XMF_H */

View File

@@ -0,0 +1,44 @@
/*----------------------------------------------------------------------------
*
* File:
* eas_xmfdata.c
*
* Contents and purpose:
* XMF File Parser
*
* This file contains data definitions for the XMF 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_miditypes.h"
#include "eas_xmf.h"
#include "eas_xmfdata.h"
/*----------------------------------------------------------------------------
*
* eas_XMFData
*
* Static memory allocation for XMF parser
*----------------------------------------------------------------------------
*/
S_XMF_DATA eas_XMFData;

View File

@@ -0,0 +1,55 @@
/*----------------------------------------------------------------------------
*
* File:
* eas_xmfdata.h
*
* Contents and purpose:
* Contains declarations for the XMF file 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_XMFDATA_H
#define _EAS_XMFDATA_H
#include "eas_data.h"
/*----------------------------------------------------------------------------
*
* S_XMF_DATA
*
* This structure contains the instance data required to parse an XMF file.
*
*----------------------------------------------------------------------------
*/
typedef struct
{
EAS_FILE_HANDLE fileHandle;
EAS_I32 fileOffset;
EAS_VOID_PTR pSMFData;
EAS_I32 midiOffset;
EAS_I32 dlsOffset;
S_DLS *pDLS;
} S_XMF_DATA;
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,183 @@
/*----------------------------------------------------------------------------
*
* File:
* jet_data.h
*
* Contents and purpose:
* Internal data structures and interfaces for JET
*
* 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: 554 $
* $Date: 2007-02-02 11:06:10 -0800 (Fri, 02 Feb 2007) $
*----------------------------------------------------------------------------
*/
#ifndef _JET_DATA_H
#define _JET_DATA_H
#include "eas.h"
#include "jet.h"
/* maximum number of segments allowed in a JET file */
#ifndef JET_MAX_SEGMENTS
#define JET_MAX_SEGMENTS 32
#endif
/* maximum number of DLS collections allowed in a JET file */
#ifndef JET_MAX_DLS_COLLECTIONS
#define JET_MAX_DLS_COLLECTIONS 4
#endif
/* maximum number of JET events in internal queue */
#ifndef JET_EVENT_QUEUE_SIZE
#define JET_EVENT_QUEUE_SIZE 32
#endif
/* maximum number of JET events in application queue */
#ifndef APP_EVENT_QUEUE_SIZE
#define APP_EVENT_QUEUE_SIZE 32
#endif
/* maximum number of active mute events */
#ifndef JET_MUTE_QUEUE_SIZE
#define JET_MUTE_QUEUE_SIZE 8
#endif
/*----------------------------------------------------------------------------
* JET event definitions
*----------------------------------------------------------------------------
*/
#define JET_EVENT_APP_LOW 80
#define JET_EVENT_APP_HIGH 83
#define JET_EVENT_LOW 102
#define JET_EVENT_HIGH 119
#define JET_EVENT_MARKER 102
#define JET_EVENT_TRIGGER_CLIP 103
#define JET_MARKER_LOOP_END 0
#define JET_CLIP_ACTIVE_FLAG 0x80
#define JET_CLIP_TRIGGER_FLAG 0x40
#define JET_CLIP_ID_MASK 0x3f
/*----------------------------------------------------------------------------
* JET file definitions
*----------------------------------------------------------------------------
*/
#define JET_TAG(a,b,c,d) (\
( ((EAS_U32)(a) & 0xFF) << 24 ) \
+ ( ((EAS_U32)(b) & 0xFF) << 16 ) \
+ ( ((EAS_U32)(c) & 0xFF) << 8 ) \
+ ( ((EAS_U32)(d) & 0xFF)))
#define JET_VERSION 0x01000000
#define JET_HEADER_TAG JET_TAG('J','E','T',' ')
#define JET_INFO_CHUNK JET_TAG('J','I','N','F')
#define JET_SMF_CHUNK JET_TAG('J','S','M','F')
#define JET_DLS_CHUNK JET_TAG('J','D','L','S')
#define INFO_JET_COPYRIGHT JET_TAG('J','C','O','P')
#define JET_APP_DATA_CHUNK JET_TAG('J','A','P','P')
#define INFO_NUM_SMF_CHUNKS JET_TAG('S','M','F','#')
#define INFO_NUM_DLS_CHUNKS JET_TAG('D','L','S','#')
#define INFO_JET_VERSION JET_TAG('J','V','E','R')
/*----------------------------------------------------------------------------
* S_JET_SEGMENT
*
* JET segment data
*----------------------------------------------------------------------------
*/
typedef struct s_jet_segment_tag
{
EAS_HANDLE streamHandle;
EAS_U32 muteFlags;
EAS_I16 repeatCount;
EAS_U8 userID;
EAS_I8 transpose;
EAS_I8 libNum;
EAS_U8 state;
EAS_U8 flags;
} S_JET_SEGMENT;
/* S_JET_SEGMENT.state */
typedef enum
{
JET_STATE_CLOSED,
JET_STATE_OPEN,
JET_STATE_READY,
JET_STATE_PLAYING,
JET_STATE_PAUSED,
JET_STATE_STOPPING
} E_JET_SEGMENT_STATE;
/* S_JEG_SEGMENT.flags */
#define JET_SEG_FLAG_MUTE_UPDATE 0x01
/*----------------------------------------------------------------------------
* S_JET_DATA
*
* Main JET data structure
*----------------------------------------------------------------------------
*/
#define SEG_QUEUE_DEPTH 3
typedef struct s_jet_data_tag
{
EAS_FILE_HANDLE jetFileHandle;
S_JET_SEGMENT segQueue[SEG_QUEUE_DEPTH];
EAS_I32 segmentOffsets[JET_MAX_SEGMENTS];
EAS_I32 appDataOffset;
EAS_I32 appDataSize;
EAS_DLSLIB_HANDLE libHandles[JET_MAX_DLS_COLLECTIONS];
EAS_U32 jetEventQueue[JET_EVENT_QUEUE_SIZE];
EAS_U32 appEventQueue[APP_EVENT_QUEUE_SIZE];
S_JET_CONFIG config;
EAS_U32 segmentTime;
EAS_U8 muteQueue[JET_MUTE_QUEUE_SIZE];
EAS_U8 numSegments;
EAS_U8 numLibraries;
EAS_U8 flags;
EAS_U8 playSegment;
EAS_U8 queueSegment;
EAS_U8 numQueuedSegments;
EAS_U8 jetEventQueueRead;
EAS_U8 jetEventQueueWrite;
EAS_U8 appEventQueueRead;
EAS_U8 appEventQueueWrite;
} S_JET_DATA;
/* flags for S_JET_DATA.flags */
#define JET_FLAGS_PLAYING 1
#define JET_EVENT_VAL_MASK 0x0000007f /* mask for value */
#define JET_EVENT_CTRL_MASK 0x00003f80 /* mask for controller */
#define JET_EVENT_CHAN_MASK 0x0003c000 /* mask for channel */
#define JET_EVENT_TRACK_MASK 0x00fc0000 /* mask for track number */
#define JET_EVENT_SEG_MASK 0xff000000 /* mask for segment ID */
#define JET_EVENT_CTRL_SHIFT 7 /* shift for controller number */
#define JET_EVENT_CHAN_SHIFT 14 /* shift to for MIDI channel */
#define JET_EVENT_TRACK_SHIFT 18 /* shift to get track ID to bit 0 */
#define JET_EVENT_SEG_SHIFT 24 /* shift to get segment ID to bit 0 */
/* prototype for callback function */
extern void JET_Event (EAS_DATA_HANDLE easHandle, EAS_U32 segTrack, EAS_U8 channel, EAS_U8 controller, EAS_U8 value);
/* prototype for JET render function */
extern EAS_PUBLIC EAS_RESULT JET_Process (EAS_DATA_HANDLE easHandle);
#endif

File diff suppressed because it is too large Load Diff