summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.mk1
-rw-r--r--MODULE_LICENSE_APACHE20
-rw-r--r--arm-fm-22k/Makefile63
-rwxr-xr-xarm-fm-22k/bin/arm-fm-22kbin0 -> 417659 bytes
-rw-r--r--arm-fm-22k/host_src/arm-fm-22k.mak25
-rw-r--r--arm-fm-22k/host_src/eas.h1062
-rw-r--r--arm-fm-22k/host_src/eas_build.h36
-rw-r--r--arm-fm-22k/host_src/eas_chorus.h53
-rw-r--r--arm-fm-22k/host_src/eas_config.c619
-rw-r--r--arm-fm-22k/host_src/eas_config.h191
-rw-r--r--arm-fm-22k/host_src/eas_debugmsgs.h43
-rw-r--r--arm-fm-22k/host_src/eas_host.h83
-rw-r--r--arm-fm-22k/host_src/eas_hostmm.c660
-rw-r--r--arm-fm-22k/host_src/eas_main.c461
-rw-r--r--arm-fm-22k/host_src/eas_report.c264
-rw-r--r--arm-fm-22k/host_src/eas_report.h77
-rw-r--r--arm-fm-22k/host_src/eas_reverb.h54
-rw-r--r--arm-fm-22k/host_src/eas_types.h268
-rw-r--r--arm-fm-22k/host_src/eas_wave.c423
-rw-r--r--arm-fm-22k/host_src/eas_wave.h74
-rw-r--r--arm-fm-22k/lib/libarm-fm-22k.abin0 -> 114668 bytes
-rw-r--r--arm-fm-22k/lib_src/arm-fm-22k_lib.mak25
-rw-r--r--arm-fm-22k/lib_src/eas_audioconst.h97
-rw-r--r--arm-fm-22k/lib_src/eas_chorus.c604
-rw-r--r--arm-fm-22k/lib_src/eas_chorusdata.c34
-rw-r--r--arm-fm-22k/lib_src/eas_chorusdata.h160
-rw-r--r--arm-fm-22k/lib_src/eas_ctype.h41
-rw-r--r--arm-fm-22k/lib_src/eas_data.c37
-rw-r--r--arm-fm-22k/lib_src/eas_data.h131
-rw-r--r--arm-fm-22k/lib_src/eas_effects.h61
-rw-r--r--arm-fm-22k/lib_src/eas_fmengine.c785
-rw-r--r--arm-fm-22k/lib_src/eas_fmengine.h121
-rw-r--r--arm-fm-22k/lib_src/eas_fmsndlib.c1674
-rw-r--r--arm-fm-22k/lib_src/eas_fmsynth.c910
-rw-r--r--arm-fm-22k/lib_src/eas_fmsynth.h81
-rw-r--r--arm-fm-22k/lib_src/eas_fmtables.c368
-rw-r--r--arm-fm-22k/lib_src/eas_ima_tables.c54
-rw-r--r--arm-fm-22k/lib_src/eas_imaadpcm.c368
-rw-r--r--arm-fm-22k/lib_src/eas_imelody.c1738
-rw-r--r--arm-fm-22k/lib_src/eas_imelodydata.c43
-rw-r--r--arm-fm-22k/lib_src/eas_imelodydata.h73
-rw-r--r--arm-fm-22k/lib_src/eas_math.c168
-rw-r--r--arm-fm-22k/lib_src/eas_math.h412
-rw-r--r--arm-fm-22k/lib_src/eas_midi.c569
-rw-r--r--arm-fm-22k/lib_src/eas_midi.h71
-rw-r--r--arm-fm-22k/lib_src/eas_midictrl.h64
-rw-r--r--arm-fm-22k/lib_src/eas_mididata.c34
-rw-r--r--arm-fm-22k/lib_src/eas_miditypes.h138
-rw-r--r--arm-fm-22k/lib_src/eas_mixbuf.c36
-rw-r--r--arm-fm-22k/lib_src/eas_mixer.c464
-rw-r--r--arm-fm-22k/lib_src/eas_mixer.h137
-rw-r--r--arm-fm-22k/lib_src/eas_ota.c1077
-rw-r--r--arm-fm-22k/lib_src/eas_otadata.c41
-rw-r--r--arm-fm-22k/lib_src/eas_otadata.h81
-rw-r--r--arm-fm-22k/lib_src/eas_pan.c98
-rw-r--r--arm-fm-22k/lib_src/eas_pan.h66
-rw-r--r--arm-fm-22k/lib_src/eas_parser.h98
-rw-r--r--arm-fm-22k/lib_src/eas_pcm.c1482
-rw-r--r--arm-fm-22k/lib_src/eas_pcm.h359
-rw-r--r--arm-fm-22k/lib_src/eas_pcmdata.c35
-rw-r--r--arm-fm-22k/lib_src/eas_pcmdata.h157
-rw-r--r--arm-fm-22k/lib_src/eas_public.c2597
-rw-r--r--arm-fm-22k/lib_src/eas_reverb.c1154
-rw-r--r--arm-fm-22k/lib_src/eas_reverbdata.c34
-rw-r--r--arm-fm-22k/lib_src/eas_reverbdata.h486
-rw-r--r--arm-fm-22k/lib_src/eas_rtttl.c1197
-rw-r--r--arm-fm-22k/lib_src/eas_rtttldata.c41
-rw-r--r--arm-fm-22k/lib_src/eas_rtttldata.h70
-rw-r--r--arm-fm-22k/lib_src/eas_smf.c1203
-rw-r--r--arm-fm-22k/lib_src/eas_smf.h49
-rw-r--r--arm-fm-22k/lib_src/eas_smfdata.c66
-rw-r--r--arm-fm-22k/lib_src/eas_smfdata.h66
-rw-r--r--arm-fm-22k/lib_src/eas_sndlib.h406
-rw-r--r--arm-fm-22k/lib_src/eas_synth.h395
-rw-r--r--arm-fm-22k/lib_src/eas_synth_protos.h60
-rw-r--r--arm-fm-22k/lib_src/eas_synthcfg.h70
-rw-r--r--arm-fm-22k/lib_src/eas_vm_protos.h1086
-rw-r--r--arm-fm-22k/lib_src/eas_voicemgt.c3971
-rw-r--r--arm-fm-22k/lib_src/eas_wavefile.c867
-rw-r--r--arm-fm-22k/lib_src/eas_wavefile.h63
-rw-r--r--arm-fm-22k/lib_src/eas_wavefiledata.c33
-rw-r--r--arm-hybrid-22k/Makefile66
-rwxr-xr-xarm-hybrid-22k/bin/arm-hybrid-22kbin0 -> 485468 bytes
-rw-r--r--arm-hybrid-22k/host_src/.DS_Storebin0 -> 6148 bytes
-rw-r--r--arm-hybrid-22k/host_src/._.DS_Storebin0 -> 82 bytes
-rw-r--r--arm-hybrid-22k/host_src/arm-hybrid-22k.mak25
-rw-r--r--arm-hybrid-22k/host_src/eas.h1062
-rw-r--r--arm-hybrid-22k/host_src/eas_build.h36
-rw-r--r--arm-hybrid-22k/host_src/eas_chorus.h53
-rw-r--r--arm-hybrid-22k/host_src/eas_config.c619
-rw-r--r--arm-hybrid-22k/host_src/eas_config.h191
-rw-r--r--arm-hybrid-22k/host_src/eas_debugmsgs.h44
-rw-r--r--arm-hybrid-22k/host_src/eas_host.h83
-rw-r--r--arm-hybrid-22k/host_src/eas_hostmm.c660
-rw-r--r--arm-hybrid-22k/host_src/eas_main.c461
-rw-r--r--arm-hybrid-22k/host_src/eas_report.c264
-rw-r--r--arm-hybrid-22k/host_src/eas_report.h77
-rw-r--r--arm-hybrid-22k/host_src/eas_reverb.h54
-rw-r--r--arm-hybrid-22k/host_src/eas_types.h268
-rw-r--r--arm-hybrid-22k/host_src/eas_wave.c423
-rw-r--r--arm-hybrid-22k/host_src/eas_wave.h74
-rw-r--r--arm-hybrid-22k/lib/libarm-hybrid-22k.abin0 -> 189624 bytes
-rw-r--r--arm-hybrid-22k/lib_src/ARM-E_filter_gnu.s134
-rw-r--r--arm-hybrid-22k/lib_src/ARM-E_interpolate_loop_gnu.s131
-rw-r--r--arm-hybrid-22k/lib_src/ARM-E_interpolate_noloop_gnu.s130
-rw-r--r--arm-hybrid-22k/lib_src/ARM-E_mastergain_gnu.s109
-rw-r--r--arm-hybrid-22k/lib_src/ARM-E_voice_gain_gnu.s166
-rw-r--r--arm-hybrid-22k/lib_src/ARM_synth_constants_gnu.inc153
-rw-r--r--arm-hybrid-22k/lib_src/arm-hybrid-22k_lib.mak25
-rw-r--r--arm-hybrid-22k/lib_src/eas_audioconst.h97
-rw-r--r--arm-hybrid-22k/lib_src/eas_chorus.c604
-rw-r--r--arm-hybrid-22k/lib_src/eas_chorusdata.c34
-rw-r--r--arm-hybrid-22k/lib_src/eas_chorusdata.h160
-rw-r--r--arm-hybrid-22k/lib_src/eas_ctype.h41
-rw-r--r--arm-hybrid-22k/lib_src/eas_data.c37
-rw-r--r--arm-hybrid-22k/lib_src/eas_data.h131
-rw-r--r--arm-hybrid-22k/lib_src/eas_effects.h61
-rw-r--r--arm-hybrid-22k/lib_src/eas_fmengine.c785
-rw-r--r--arm-hybrid-22k/lib_src/eas_fmengine.h121
-rw-r--r--arm-hybrid-22k/lib_src/eas_fmsynth.c910
-rw-r--r--arm-hybrid-22k/lib_src/eas_fmsynth.h81
-rw-r--r--arm-hybrid-22k/lib_src/eas_fmtables.c368
-rw-r--r--arm-hybrid-22k/lib_src/eas_ima_tables.c54
-rw-r--r--arm-hybrid-22k/lib_src/eas_imaadpcm.c368
-rw-r--r--arm-hybrid-22k/lib_src/eas_imelody.c1738
-rw-r--r--arm-hybrid-22k/lib_src/eas_imelodydata.c43
-rw-r--r--arm-hybrid-22k/lib_src/eas_imelodydata.h73
-rw-r--r--arm-hybrid-22k/lib_src/eas_math.c168
-rw-r--r--arm-hybrid-22k/lib_src/eas_math.h412
-rw-r--r--arm-hybrid-22k/lib_src/eas_midi.c569
-rw-r--r--arm-hybrid-22k/lib_src/eas_midi.h71
-rw-r--r--arm-hybrid-22k/lib_src/eas_midictrl.h64
-rw-r--r--arm-hybrid-22k/lib_src/eas_mididata.c34
-rw-r--r--arm-hybrid-22k/lib_src/eas_miditypes.h138
-rw-r--r--arm-hybrid-22k/lib_src/eas_mixbuf.c36
-rw-r--r--arm-hybrid-22k/lib_src/eas_mixer.c464
-rw-r--r--arm-hybrid-22k/lib_src/eas_mixer.h137
-rw-r--r--arm-hybrid-22k/lib_src/eas_ota.c1077
-rw-r--r--arm-hybrid-22k/lib_src/eas_otadata.c41
-rw-r--r--arm-hybrid-22k/lib_src/eas_otadata.h81
-rw-r--r--arm-hybrid-22k/lib_src/eas_pan.c98
-rw-r--r--arm-hybrid-22k/lib_src/eas_pan.h66
-rw-r--r--arm-hybrid-22k/lib_src/eas_parser.h98
-rw-r--r--arm-hybrid-22k/lib_src/eas_pcm.c1482
-rw-r--r--arm-hybrid-22k/lib_src/eas_pcm.h359
-rw-r--r--arm-hybrid-22k/lib_src/eas_pcmdata.c35
-rw-r--r--arm-hybrid-22k/lib_src/eas_pcmdata.h157
-rw-r--r--arm-hybrid-22k/lib_src/eas_public.c2597
-rw-r--r--arm-hybrid-22k/lib_src/eas_reverb.c1154
-rw-r--r--arm-hybrid-22k/lib_src/eas_reverbdata.c34
-rw-r--r--arm-hybrid-22k/lib_src/eas_reverbdata.h486
-rw-r--r--arm-hybrid-22k/lib_src/eas_rtttl.c1197
-rw-r--r--arm-hybrid-22k/lib_src/eas_rtttldata.c41
-rw-r--r--arm-hybrid-22k/lib_src/eas_rtttldata.h70
-rw-r--r--arm-hybrid-22k/lib_src/eas_smf.c1203
-rw-r--r--arm-hybrid-22k/lib_src/eas_smf.h49
-rw-r--r--arm-hybrid-22k/lib_src/eas_smfdata.c66
-rw-r--r--arm-hybrid-22k/lib_src/eas_smfdata.h66
-rw-r--r--arm-hybrid-22k/lib_src/eas_sndlib.h406
-rw-r--r--arm-hybrid-22k/lib_src/eas_synth.h395
-rw-r--r--arm-hybrid-22k/lib_src/eas_synth_protos.h60
-rw-r--r--arm-hybrid-22k/lib_src/eas_synthcfg.h70
-rw-r--r--arm-hybrid-22k/lib_src/eas_vm_protos.h1086
-rw-r--r--arm-hybrid-22k/lib_src/eas_voicemgt.c3971
-rw-r--r--arm-hybrid-22k/lib_src/eas_wavefile.c867
-rw-r--r--arm-hybrid-22k/lib_src/eas_wavefile.h63
-rw-r--r--arm-hybrid-22k/lib_src/eas_wavefiledata.c33
-rw-r--r--arm-hybrid-22k/lib_src/eas_wt_IPC_frame.h82
-rw-r--r--arm-hybrid-22k/lib_src/eas_wtengine.c661
-rw-r--r--arm-hybrid-22k/lib_src/eas_wtengine.h171
-rw-r--r--arm-hybrid-22k/lib_src/eas_wtsynth.c1251
-rw-r--r--arm-hybrid-22k/lib_src/eas_wtsynth.h66
-rw-r--r--arm-hybrid-22k/lib_src/hybrid_22khz_mcu.c5149
-rw-r--r--arm-wt-22k/Android.mk104
-rw-r--r--arm-wt-22k/bin/arm-wt-22kbin0 -> 610752 bytes
-rw-r--r--arm-wt-22k/host_src/arm-wt-22k.mak25
-rw-r--r--arm-wt-22k/host_src/eas.h1062
-rw-r--r--arm-wt-22k/host_src/eas_build.h36
-rw-r--r--arm-wt-22k/host_src/eas_chorus.h53
-rw-r--r--arm-wt-22k/host_src/eas_config.c619
-rw-r--r--arm-wt-22k/host_src/eas_config.h191
-rw-r--r--arm-wt-22k/host_src/eas_debugmsgs.h87
-rw-r--r--arm-wt-22k/host_src/eas_host.h87
-rw-r--r--arm-wt-22k/host_src/eas_hostmm.c687
-rw-r--r--arm-wt-22k/host_src/eas_main.c464
-rw-r--r--arm-wt-22k/host_src/eas_report.c264
-rw-r--r--arm-wt-22k/host_src/eas_report.h77
-rw-r--r--arm-wt-22k/host_src/eas_reverb.h54
-rw-r--r--arm-wt-22k/host_src/eas_types.h273
-rw-r--r--arm-wt-22k/host_src/eas_wave.c423
-rw-r--r--arm-wt-22k/host_src/eas_wave.h74
-rw-r--r--arm-wt-22k/host_src/jet.h199
-rw-r--r--arm-wt-22k/lib/libarm-wt-22k.abin0 -> 322180 bytes
-rw-r--r--arm-wt-22k/lib_src/ARM-E_filter_gnu.s134
-rw-r--r--arm-wt-22k/lib_src/ARM-E_interpolate_loop_gnu.s131
-rw-r--r--arm-wt-22k/lib_src/ARM-E_interpolate_noloop_gnu.s130
-rw-r--r--arm-wt-22k/lib_src/ARM-E_mastergain_gnu.s109
-rw-r--r--arm-wt-22k/lib_src/ARM-E_voice_gain_gnu.s166
-rw-r--r--arm-wt-22k/lib_src/ARM_synth_constants_gnu.inc153
-rw-r--r--arm-wt-22k/lib_src/arm-wt-22k_lib.mak25
-rw-r--r--arm-wt-22k/lib_src/dls.h268
-rw-r--r--arm-wt-22k/lib_src/dls2.h122
-rw-r--r--arm-wt-22k/lib_src/eas_audioconst.h97
-rw-r--r--arm-wt-22k/lib_src/eas_chorus.c604
-rw-r--r--arm-wt-22k/lib_src/eas_chorusdata.c34
-rw-r--r--arm-wt-22k/lib_src/eas_chorusdata.h160
-rw-r--r--arm-wt-22k/lib_src/eas_ctype.h41
-rw-r--r--arm-wt-22k/lib_src/eas_data.c37
-rw-r--r--arm-wt-22k/lib_src/eas_data.h133
-rw-r--r--arm-wt-22k/lib_src/eas_dlssynth.c578
-rw-r--r--arm-wt-22k/lib_src/eas_dlssynth.h41
-rw-r--r--arm-wt-22k/lib_src/eas_effects.h61
-rw-r--r--arm-wt-22k/lib_src/eas_flog.c96
-rw-r--r--arm-wt-22k/lib_src/eas_ima_tables.c54
-rw-r--r--arm-wt-22k/lib_src/eas_imaadpcm.c368
-rw-r--r--arm-wt-22k/lib_src/eas_imelody.c1742
-rw-r--r--arm-wt-22k/lib_src/eas_imelodydata.c43
-rw-r--r--arm-wt-22k/lib_src/eas_imelodydata.h73
-rw-r--r--arm-wt-22k/lib_src/eas_math.c168
-rw-r--r--arm-wt-22k/lib_src/eas_math.h412
-rw-r--r--arm-wt-22k/lib_src/eas_mdls.c2668
-rw-r--r--arm-wt-22k/lib_src/eas_mdls.h295
-rw-r--r--arm-wt-22k/lib_src/eas_midi.c569
-rw-r--r--arm-wt-22k/lib_src/eas_midi.h71
-rw-r--r--arm-wt-22k/lib_src/eas_midictrl.h64
-rw-r--r--arm-wt-22k/lib_src/eas_mididata.c34
-rw-r--r--arm-wt-22k/lib_src/eas_miditypes.h138
-rw-r--r--arm-wt-22k/lib_src/eas_mixbuf.c36
-rw-r--r--arm-wt-22k/lib_src/eas_mixer.c464
-rw-r--r--arm-wt-22k/lib_src/eas_mixer.h137
-rw-r--r--arm-wt-22k/lib_src/eas_ota.c1077
-rw-r--r--arm-wt-22k/lib_src/eas_otadata.c41
-rw-r--r--arm-wt-22k/lib_src/eas_otadata.h81
-rw-r--r--arm-wt-22k/lib_src/eas_pan.c98
-rw-r--r--arm-wt-22k/lib_src/eas_pan.h66
-rw-r--r--arm-wt-22k/lib_src/eas_parser.h98
-rw-r--r--arm-wt-22k/lib_src/eas_pcm.c1482
-rw-r--r--arm-wt-22k/lib_src/eas_pcm.h359
-rw-r--r--arm-wt-22k/lib_src/eas_pcmdata.c35
-rw-r--r--arm-wt-22k/lib_src/eas_pcmdata.h157
-rw-r--r--arm-wt-22k/lib_src/eas_public.c2601
-rw-r--r--arm-wt-22k/lib_src/eas_reverb.c1154
-rw-r--r--arm-wt-22k/lib_src/eas_reverbdata.c34
-rw-r--r--arm-wt-22k/lib_src/eas_reverbdata.h486
-rw-r--r--arm-wt-22k/lib_src/eas_rtttl.c1197
-rw-r--r--arm-wt-22k/lib_src/eas_rtttldata.c41
-rw-r--r--arm-wt-22k/lib_src/eas_rtttldata.h70
-rw-r--r--arm-wt-22k/lib_src/eas_smf.c1207
-rw-r--r--arm-wt-22k/lib_src/eas_smf.h49
-rw-r--r--arm-wt-22k/lib_src/eas_smfdata.c66
-rw-r--r--arm-wt-22k/lib_src/eas_smfdata.h66
-rw-r--r--arm-wt-22k/lib_src/eas_sndlib.h406
-rw-r--r--arm-wt-22k/lib_src/eas_synth.h395
-rw-r--r--arm-wt-22k/lib_src/eas_synth_protos.h60
-rw-r--r--arm-wt-22k/lib_src/eas_synthcfg.h70
-rw-r--r--arm-wt-22k/lib_src/eas_tcdata.c43
-rw-r--r--arm-wt-22k/lib_src/eas_tcdata.h65
-rw-r--r--arm-wt-22k/lib_src/eas_tonecontrol.c941
-rw-r--r--arm-wt-22k/lib_src/eas_vm_protos.h1086
-rw-r--r--arm-wt-22k/lib_src/eas_voicemgt.c3971
-rw-r--r--arm-wt-22k/lib_src/eas_wavefile.c867
-rw-r--r--arm-wt-22k/lib_src/eas_wavefile.h63
-rw-r--r--arm-wt-22k/lib_src/eas_wavefiledata.c33
-rw-r--r--arm-wt-22k/lib_src/eas_wt_IPC_frame.h82
-rw-r--r--arm-wt-22k/lib_src/eas_wtengine.c661
-rw-r--r--arm-wt-22k/lib_src/eas_wtengine.h171
-rw-r--r--arm-wt-22k/lib_src/eas_wtsynth.c1257
-rw-r--r--arm-wt-22k/lib_src/eas_wtsynth.h66
-rw-r--r--arm-wt-22k/lib_src/eas_xmf.c850
-rw-r--r--arm-wt-22k/lib_src/eas_xmf.h60
-rw-r--r--arm-wt-22k/lib_src/eas_xmfdata.c44
-rw-r--r--arm-wt-22k/lib_src/eas_xmfdata.h55
-rw-r--r--arm-wt-22k/lib_src/jet.c1125
-rw-r--r--arm-wt-22k/lib_src/jet_data.h183
-rw-r--r--arm-wt-22k/lib_src/wt_22khz.c11423
-rw-r--r--arm-wt-22k/misc/MMAPI.zipbin0 -> 1050817 bytes
-rw-r--r--arm-wt-22k/misc/eas_host.c787
-rw-r--r--arm-wt-22k/vectors/Leadsol.mxmfbin0 -> 565820 bytes
-rw-r--r--arm-wt-22k/vectors/Leadsol_out.wavbin0 -> 2678828 bytes
-rw-r--r--arm-wt-22k/vectors/WAVEtest.wavbin0 -> 286838 bytes
-rw-r--r--arm-wt-22k/vectors/WAVEtest_out.wavbin0 -> 147500 bytes
-rw-r--r--arm-wt-22k/vectors/abba.imy10
-rw-r--r--arm-wt-22k/vectors/abba_out.wavbin0 -> 2457644 bytes
-rw-r--r--arm-wt-22k/vectors/ants.midbin0 -> 2956 bytes
-rw-r--r--arm-wt-22k/vectors/ants_out.wavbin0 -> 1728556 bytes
-rw-r--r--arm-wt-22k/vectors/greensleeves.rtttl1
-rw-r--r--arm-wt-22k/vectors/greensleeves_out.wavbin0 -> 1712172 bytes
-rw-r--r--arm-wt-22k/vectors/test.otabin0 -> 30 bytes
-rw-r--r--arm-wt-22k/vectors/test_out.wavbin0 -> 528428 bytes
-rw-r--r--docs/EASLibrary3_5.odtbin0 -> 158290 bytes
-rw-r--r--docs/EASLibrary3_5.pdfbin0 -> 371828 bytes
-rw-r--r--docs/EAS_API_Reference.odtbin0 -> 157184 bytes
-rw-r--r--docs/EAS_API_Reference.pdfbin0 -> 379444 bytes
-rw-r--r--docs/EAS_Library_Integration_Guide.odtbin0 -> 106537 bytes
-rw-r--r--docs/EAS_Library_Integration_Guide.pdfbin0 -> 169398 bytes
-rw-r--r--docs/JET_Programming_Manual.odtbin0 -> 267431 bytes
-rw-r--r--docs/JET_Programming_Manual.pdfbin0 -> 226222 bytes
297 files changed, 119733 insertions, 0 deletions
diff --git a/Android.mk b/Android.mk
new file mode 100644
index 0000000..6571161
--- /dev/null
+++ b/Android.mk
@@ -0,0 +1 @@
+include $(all-subdir-makefiles)
diff --git a/MODULE_LICENSE_APACHE2 b/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/MODULE_LICENSE_APACHE2
diff --git a/arm-fm-22k/Makefile b/arm-fm-22k/Makefile
new file mode 100644
index 0000000..8b76c55
--- /dev/null
+++ b/arm-fm-22k/Makefile
@@ -0,0 +1,63 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES = \
+ lib_src/eas_chorus.c \
+ lib_src/eas_chorusdata.c \
+ lib_src/eas_data.c \
+ lib_src/eas_fmengine.c \
+ lib_src/eas_fmsndlib.c \
+ lib_src/eas_fmsynth.c \
+ lib_src/eas_fmtables.c \
+ lib_src/eas_ima_tables.c \
+ lib_src/eas_imaadpcm.c \
+ lib_src/eas_imelody.c \
+ lib_src/eas_imelodydata.c \
+ lib_src/eas_math.c \
+ lib_src/eas_midi.c \
+ lib_src/eas_mididata.c \
+ lib_src/eas_mixbuf.c \
+ lib_src/eas_mixer.c \
+ lib_src/eas_ota.c \
+ lib_src/eas_otadata.c \
+ lib_src/eas_pan.c \
+ lib_src/eas_pcm.c \
+ lib_src/eas_pcmdata.c \
+ lib_src/eas_public.c \
+ lib_src/eas_reverb.c \
+ lib_src/eas_reverbdata.c \
+ lib_src/eas_rtttl.c \
+ lib_src/eas_rtttldata.c \
+ lib_src/eas_smf.c \
+ lib_src/eas_smfdata.c \
+ lib_src/eas_voicemgt.c \
+ lib_src/eas_wavefile.c \
+ lib_src/eas_wavefiledata.c \
+ host_src/eas_config.c \
+ host_src/eas_hostmm.c \
+ host_src/eas_main.c \
+ host_src/eas_report.c \
+ host_src/eas_wave.c
+
+LOCAL_CFLAGS+= -O2 -D NUM_OUTPUT_CHANNELS=2 \
+ -D _SAMPLE_RATE_22050 -D EAS_FM_SYNTH \
+ -D MAX_SYNTH_VOICES=16 -D _IMELODY_PARSER \
+ -D _RTTTL_PARSER -D _OTA_PARSER \
+ -D _WAVE_PARSER -D _REVERB_ENABLED \
+ -D _CHORUS_ENABLED -D _IMA_DECODER \
+ -D UNIFIED_DEBUG_MESSAGES
+
+LOCAL_C_INCLUDES:= \
+ $(LOCAL_PATH)/host_src/ \
+ $(LOCAL_PATH)/lib_src/
+
+LOCAL_ARM_MODE := arm
+
+LOCAL_MODULE := libsonivox
+
+LOCAL_COPY_HEADERS_TO := libsonivox
+LOCAL_COPY_HEADERS := \
+ host_src/eas.h \
+ host_src/eas_types.h
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/arm-fm-22k/bin/arm-fm-22k b/arm-fm-22k/bin/arm-fm-22k
new file mode 100755
index 0000000..50ba4ba
--- /dev/null
+++ b/arm-fm-22k/bin/arm-fm-22k
Binary files differ
diff --git a/arm-fm-22k/host_src/arm-fm-22k.mak b/arm-fm-22k/host_src/arm-fm-22k.mak
new file mode 100644
index 0000000..da12d71
--- /dev/null
+++ b/arm-fm-22k/host_src/arm-fm-22k.mak
@@ -0,0 +1,25 @@
+#
+# Auto-generated sample makefile
+#
+# This makefile is intended for use with GNU make.
+# Set the paths to the tools (CC, AR, LD, etc.)
+#
+
+vpath %.c host_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 host_src -D UNIFIED_DEBUG_MESSAGES -D EAS_FM_SYNTH -D _IMELODY_PARSER -D _RTTTL_PARSER -D _OTA_PARSER -D _WAVE_PARSER -D _REVERB_ENABLED -D _CHORUS_ENABLED $<
+
+%.o: %.s
+ $(AS) -o $@ -EL -mcpu=arm946e-s -mfpu=softfpa $<
+
+OBJS = eas_main.o eas_report.o eas_wave.o eas_hostmm.o eas_config.o
+
+arm-fm-22k: $(OBJS)
+ $(LD) -o $@ $(OBJS) libarm-fm-22k.a -lm
+
diff --git a/arm-fm-22k/host_src/eas.h b/arm-fm-22k/host_src/eas.h
new file mode 100644
index 0000000..0bb04fe
--- /dev/null
+++ b/arm-fm-22k/host_src/eas.h
@@ -0,0 +1,1062 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas.h
+ *
+ * Contents and purpose:
+ * The public interface header for the EAS synthesizer.
+ *
+ * This header only contains declarations that are specific
+ * to this implementation.
+ *
+ * DO NOT MODIFY THIS FILE!
+ *
+ * Copyright Sonic Network Inc. 2005, 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: 852 $
+ * $Date: 2007-09-04 11:43:49 -0700 (Tue, 04 Sep 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+#ifndef _EAS_H
+#define _EAS_H
+
+#include "eas_types.h"
+
+/* for C++ linkage */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* library version macro */
+#define MAKE_LIB_VERSION(a,b,c,d) (((((((EAS_U32) a <<8) | (EAS_U32) b) << 8) | (EAS_U32) c) << 8) | (EAS_U32) d)
+#define LIB_VERSION MAKE_LIB_VERSION(3, 6, 10, 14)
+
+typedef struct
+{
+ EAS_U32 libVersion;
+ EAS_BOOL checkedVersion;
+ EAS_I32 maxVoices;
+ EAS_I32 numChannels;
+ EAS_I32 sampleRate;
+ EAS_I32 mixBufferSize;
+ EAS_BOOL filterEnabled;
+ EAS_U32 buildTimeStamp;
+ EAS_CHAR *buildGUID;
+} S_EAS_LIB_CONFIG;
+
+/* enumerated effects module numbers for configuration */
+typedef enum
+{
+ EAS_MODULE_ENHANCER = 0,
+ EAS_MODULE_COMPRESSOR,
+ EAS_MODULE_REVERB,
+ EAS_MODULE_CHORUS,
+ EAS_MODULE_WIDENER,
+ EAS_MODULE_GRAPHIC_EQ,
+ EAS_MODULE_WOW,
+ EAS_MODULE_MAXIMIZER,
+ EAS_MODULE_TONECONTROLEQ,
+ NUM_EFFECTS_MODULES
+} E_FX_MODULES;
+
+/* enumerated optional module numbers for configuration */
+typedef enum
+{
+ EAS_MODULE_MMAPI_TONE_CONTROL = 0,
+ EAS_MODULE_METRICS
+} E_OPT_MODULES;
+#define NUM_OPTIONAL_MODULES 2
+
+/* enumerated audio decoders for configuration */
+typedef enum
+{
+ EAS_DECODER_PCM = 0,
+ EAS_DECODER_SMAF_ADPCM,
+ EAS_DECODER_IMA_ADPCM,
+ EAS_DECODER_7BIT_SMAF_ADPCM,
+ EAS_DECODER_NOT_SUPPORTED
+} E_DECODER_MODULES;
+#define NUM_DECODER_MODULES 4
+
+/* defines for EAS_PEOpenStream flags parameter */
+#define PCM_FLAGS_STEREO 0x00000100 /* stream is stereo */
+#define PCM_FLAGS_8_BIT 0x00000001 /* 8-bit format */
+#define PCM_FLAGS_UNSIGNED 0x00000010 /* unsigned format */
+#define PCM_FLAGS_STREAMING 0x80000000 /* streaming mode */
+
+/* maximum volume setting */
+#define EAS_MAX_VOLUME 100
+
+/*----------------------------------------------------------------------------
+ * EAS_Init()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Initialize the synthesizer library
+ *
+ * Inputs:
+ * polyphony - number of voices to play (dynamic memory model only)
+ * ppLibData - pointer to data handle variable for this instance
+ *
+ * Outputs:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_Init (EAS_DATA_HANDLE *ppEASData);
+
+/*----------------------------------------------------------------------------
+ * EAS_Config()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Returns a pointer to a structure containing the configuration options
+ * in this library build.
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC const S_EAS_LIB_CONFIG *EAS_Config (void);
+
+/*----------------------------------------------------------------------------
+ * EAS_Shutdown()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Shuts down the library. Deallocates any memory associated with the
+ * synthesizer (dynamic memory model only)
+ *
+ * Inputs:
+ * pEASData - handle to data for this instance
+ *
+ * Outputs:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_Shutdown (EAS_DATA_HANDLE pEASData);
+
+/*----------------------------------------------------------------------------
+ * EAS_Render()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Parse the Midi data and render PCM audio data.
+ *
+ * Inputs:
+ * pEASData - buffer for internal EAS data
+ * pOut - output buffer pointer
+ * nNumRequested - requested num samples to generate
+ * pnNumGenerated - actual number of samples generated
+ *
+ * Outputs:
+ * EAS_SUCCESS if PCM data was successfully rendered
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_Render (EAS_DATA_HANDLE pEASData, EAS_PCM *pOut, EAS_I32 numRequested, EAS_I32 *pNumGenerated);
+
+/*----------------------------------------------------------------------------
+ * EAS_SetRepeat()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Set the selected stream to repeat.
+ *
+ * Inputs:
+ * pEASData - handle to data for this instance
+ * streamHandle - handle to stream
+ * repeatCount - repeat count (0 = no repeat, -1 = repeat forever)
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ * Notes:
+ * 0 = no repeat
+ * 1 = repeat once, i.e. play through twice
+ * -1 = repeat forever
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_SetRepeat (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 repeatCount);
+
+/*----------------------------------------------------------------------------
+ * EAS_GetRepeat()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Gets the current repeat count for the selected stream.
+ *
+ * Inputs:
+ * pEASData - handle to data for this instance
+ * streamHandle - handle to stream
+ * pRrepeatCount - pointer to variable to hold repeat count
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ * Notes:
+ * 0 = no repeat
+ * 1 = repeat once, i.e. play through twice
+ * -1 = repeat forever
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_GetRepeat (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 *pRepeatCount);
+
+/*----------------------------------------------------------------------------
+ * EAS_SetPlaybackRate()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Set the playback rate.
+ *
+ * Inputs:
+ * pEASData - handle to data for this instance
+ * streamHandle - handle to stream
+ * rate - rate (28-bit fractional amount)
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_SetPlaybackRate (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_U32 rate);
+#define MAX_PLAYBACK_RATE (EAS_U32)(1L << 29)
+#define MIN_PLAYBACK_RATE (EAS_U32)(1L << 27)
+
+/*----------------------------------------------------------------------------
+ * EAS_SetTransposition)
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Sets the key tranposition for the synthesizer. Transposes all
+ * melodic instruments by the specified amount. Range is limited
+ * to +/-12 semitones.
+ *
+ * Inputs:
+ * pEASData - handle to data for this instance
+ * streamHandle - handle to stream
+ * transposition - +/-12 semitones
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_SetTransposition (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 transposition);
+#define MAX_TRANSPOSE 12
+
+/*----------------------------------------------------------------------------
+ * EAS_SetSynthPolyphony()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Set the polyphony of the synthesizer. Value must be >= 1 and <= the
+ * maximum number of voices. This function will pin the polyphony
+ * at those limits
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * synthNum - synthesizer number (0 = onboard, 1 = DSP)
+ * polyphonyCount - the desired polyphony count
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_SetSynthPolyphony (EAS_DATA_HANDLE pEASData, EAS_I32 synthNum, EAS_I32 polyphonyCount);
+
+/*----------------------------------------------------------------------------
+ * EAS_GetSynthPolyphony()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Returns the current polyphony setting of the synthesizer
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * synthNum - synthesizer number (0 = onboard, 1 = DSP)
+ * pPolyphonyCount - pointer to variable to receive polyphony count
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_GetSynthPolyphony (EAS_DATA_HANDLE pEASData, EAS_I32 synthNum, EAS_I32 *pPolyphonyCount);
+
+/*----------------------------------------------------------------------------
+ * EAS_SetPolyphony()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Set the polyphony of the stream. Value must be >= 1 and <= the
+ * maximum number of voices. This function will pin the polyphony
+ * at those limits
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * streamHandle - handle returned by EAS_OpenFile
+ * polyphonyCount - the desired polyphony count
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_SetPolyphony (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 polyphonyCount);
+
+/*----------------------------------------------------------------------------
+ * EAS_GetPolyphony()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Returns the current polyphony setting of the stream
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * streamHandle - handle returned by EAS_OpenFile
+ * pPolyphonyCount - pointer to variable to receive polyphony count
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_GetPolyphony (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 *pPolyphonyCount);
+
+/*----------------------------------------------------------------------------
+ * EAS_SetPriority()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Set the priority of the stream. Determines which stream's voices
+ * are stolen when there are insufficient voices for all notes.
+ * Value must be in the range of 1-255, lower values are higher
+ * priority. The default priority is 50.
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * streamHandle - handle returned by EAS_OpenFile
+ * polyphonyCount - the desired polyphony count
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_SetPriority (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 priority);
+
+/*----------------------------------------------------------------------------
+ * EAS_GetPriority()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Returns the current priority setting of the stream
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * streamHandle - handle returned by EAS_OpenFile
+ * pPriority - pointer to variable to receive priority
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_GetPriority (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 *pPriority);
+
+/*----------------------------------------------------------------------------
+ * EAS_SetVolume()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Set the master volume for the mixer. The default volume setting is
+ * 90 (-10 dB). The volume range is 0 to 100 in 1dB increments.
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * volume - the desired master volume
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ * overrides any previously set master volume from sysex
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_SetVolume (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 volume);
+
+/*----------------------------------------------------------------------------
+ * EAS_GetVolume()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Returns the master volume for the mixer in 1dB increments.
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * volume - the desired master volume
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ * overrides any previously set master volume from sysex
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_I32 EAS_GetVolume (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle);
+
+/*----------------------------------------------------------------------------
+ * EAS_SetMaxLoad()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Sets the maximum workload the parsers will do in a single call to
+ * EAS_Render. The units are currently arbitrary, but should correlate
+ * well to the actual CPU cycles consumed. The primary effect is to
+ * reduce the occasional peaks in CPU cycles consumed when parsing
+ * dense parts of a MIDI score. Setting maxWorkLoad to zero disables
+ * the workload limiting function.
+ *
+ * Inputs:
+ * pEASData - handle to data for this instance
+ * maxLoad - the desired maximum workload
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_SetMaxLoad (EAS_DATA_HANDLE pEASData, EAS_I32 maxLoad);
+
+/*----------------------------------------------------------------------------
+ * EAS_SetMaxPCMStreams()
+ *----------------------------------------------------------------------------
+ * Sets the maximum number of PCM streams allowed in parsers that
+ * use PCM streaming.
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * streamHandle - handle returned by EAS_OpenFile
+ * maxNumStreams - maximum number of PCM streams
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_SetMaxPCMStreams (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 maxNumStreams);
+
+/*----------------------------------------------------------------------------
+ * EAS_OpenFile()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Opens a file for audio playback.
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * locator - pointer to filename or other locating information
+ * pStreamHandle - pointer to stream handle variable
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_OpenFile (EAS_DATA_HANDLE pEASData, EAS_FILE_LOCATOR locator, EAS_HANDLE *pStreamHandle);
+
+#ifdef MMAPI_SUPPORT
+/*----------------------------------------------------------------------------
+ * EAS_MMAPIToneControl()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Opens a ToneControl file for audio playback.
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * locator - pointer to filename or other locating information
+ * pStreamHandle - pointer to stream handle variable
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_MMAPIToneControl (EAS_DATA_HANDLE pEASData, EAS_FILE_LOCATOR locator, EAS_HANDLE *pStreamHandle);
+
+/*----------------------------------------------------------------------------
+ * EAS_GetWaveFmtChunk
+ *----------------------------------------------------------------------------
+ * Helper function to retrieve WAVE file fmt chunk for MMAPI
+ *----------------------------------------------------------------------------
+ * pEASData - pointer to EAS persistent data object
+ * streamHandle - stream handle
+ * pFmtChunk - pointer to pointer to FMT chunk data
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_GetWaveFmtChunk (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_VOID_PTR *ppFmtChunk);
+#endif
+
+/*----------------------------------------------------------------------------
+ * EAS_GetFileType
+ *----------------------------------------------------------------------------
+ * Returns the file type (see eas_types.h for enumerations)
+ *----------------------------------------------------------------------------
+ * pEASData - pointer to EAS persistent data object
+ * streamHandle - stream handle
+ * pFileType - pointer to variable to receive file type
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_GetFileType (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 *pFileType);
+
+/*----------------------------------------------------------------------------
+ * EAS_ParseMetaData()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * streamHandle - file or stream handle
+ * playLength - pointer to variable to store the play length (in msecs)
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ * - resets the parser to the start of the file
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_ParseMetaData (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 *pPlayLength);
+
+/*----------------------------------------------------------------------------
+ * EAS_Prepare()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Prepares the synthesizer to play the file or stream. Parses the first
+ * frame of data from the file and arms the synthesizer.
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * streamHandle - file or stream handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_Prepare (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle);
+
+/*----------------------------------------------------------------------------
+ * EAS_State()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Returns the state of an audio file or stream.
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * streamHandle - file or stream handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_State (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_STATE *pState);
+
+/*----------------------------------------------------------------------------
+ * EAS_RegisterMetaDataCallback()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Registers a metadata callback function for parsed metadata. To
+ * de-register the callback, call this function again with parameter
+ * cbFunc set to NULL.
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * streamHandle - file or stream handle
+ * cbFunc - pointer to host callback function
+ * metaDataBuffer - pointer to metadata buffer
+ * metaDataBufSize - maximum size of the metadata buffer
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_RegisterMetaDataCallback (
+ EAS_DATA_HANDLE pEASData,
+ EAS_HANDLE streamHandle,
+ EAS_METADATA_CBFUNC cbFunc,
+ char *metaDataBuffer,
+ EAS_I32 metaDataBufSize,
+ EAS_VOID_PTR pUserData);
+
+/*----------------------------------------------------------------------------
+ * EAS_GetNoteCount ()
+ *----------------------------------------------------------------------------
+ * Returns the total number of notes played in this stream
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * streamHandle - file or stream handle
+ * pNoteCount - pointer to variable to receive note count
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_GetNoteCount (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *pNoteCount);
+
+/*----------------------------------------------------------------------------
+ * EAS_CloseFile()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Closes an audio file or stream. Playback should have either paused or
+ * completed (EAS_State returns EAS_PAUSED or EAS_STOPPED).
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * streamHandle - file or stream handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_CloseFile (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle);
+
+/*----------------------------------------------------------------------------
+ * EAS_OpenMIDIStream()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Opens a raw MIDI stream allowing the host to route MIDI cable data directly to the synthesizer
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * pStreamHandle - pointer to variable to hold file or stream handle
+ * streamHandle - open stream or NULL for new synthesizer instance
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_OpenMIDIStream (EAS_DATA_HANDLE pEASData, EAS_HANDLE *pStreamHandle, EAS_HANDLE streamHandle);
+
+/*----------------------------------------------------------------------------
+ * EAS_WriteMIDIStream()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Send data to the MIDI stream device
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * streamHandle - stream handle
+ * pBuffer - pointer to buffer
+ * count - number of bytes to write
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_WriteMIDIStream(EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_U8 *pBuffer, EAS_I32 count);
+
+/*----------------------------------------------------------------------------
+ * EAS_CloseMIDIStream()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Closes a raw MIDI stream
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * streamHandle - stream handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_CloseMIDIStream (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle);
+
+/*----------------------------------------------------------------------------
+ * EAS_Locate()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Locate into the file associated with the handle.
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * streamHandle - file handle
+ * milliseconds - playback offset from start of file in milliseconds
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ * the actual offset will be quantized to the closest update period, typically
+ * a resolution of 5.9ms. Notes that are started prior to this time will not
+ * sound. Any notes currently playing will be shut off.
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_Locate (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 milliseconds, EAS_BOOL offset);
+
+/*----------------------------------------------------------------------------
+ * EAS_GetRenderTime()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Returns the current playback offset
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ *
+ * Outputs:
+ * Gets the render time clock in msecs.
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_GetRenderTime (EAS_DATA_HANDLE pEASData, EAS_I32 *pTime);
+
+/*----------------------------------------------------------------------------
+ * EAS_GetLocation()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Returns the current playback offset
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * streamHandle - file handle
+ *
+ * Outputs:
+ * The offset in milliseconds from the start of the current sequence, quantized
+ * to the nearest update period. Actual resolution is typically 5.9 ms.
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_GetLocation (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 *pTime);
+
+/*----------------------------------------------------------------------------
+ * EAS_Pause()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Pauses the playback of the data associated with this handle. The audio
+ * is gracefully ramped down to prevent clicks and pops. It may take several
+ * buffers of audio before the audio is muted.
+ *
+ * Inputs:
+ * psEASData - pointer to overall EAS data structure
+ * streamHandle - file or stream handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_Pause (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle);
+
+/*----------------------------------------------------------------------------
+ * EAS_Resume()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Resumes the playback of the data associated with this handle. The audio
+ * is gracefully ramped up to prevent clicks and pops.
+ *
+ * Inputs:
+ * psEASData - pointer to overall EAS data structure
+ * streamHandle - file or stream handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_Resume (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle);
+
+/*----------------------------------------------------------------------------
+ * EAS_GetParameter()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Set the parameter of a module. See E_MODULES for a list of modules
+ * and the header files of the modules for a list of parameters.
+ *
+ * Inputs:
+ * psEASData - pointer to overall EAS data structure
+ * module - enumerated module number
+ * param - enumerated parameter number
+ * pValue - pointer to variable to receive parameter value
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_GetParameter (EAS_DATA_HANDLE pEASData, EAS_I32 module, EAS_I32 param, EAS_I32 *pValue);
+
+/*----------------------------------------------------------------------------
+ * EAS_SetParameter()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Set the parameter of a module. See E_MODULES for a list of modules
+ * and the header files of the modules for a list of parameters.
+ *
+ * Inputs:
+ * psEASData - pointer to overall EAS data structure
+ * handle - file or stream handle
+ * module - enumerated module number
+ * param - enumerated parameter number
+ * value - new parameter value
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_SetParameter (EAS_DATA_HANDLE pEASData, EAS_I32 module, EAS_I32 param, EAS_I32 value);
+
+#ifdef _METRICS_ENABLED
+/*----------------------------------------------------------------------------
+ * EAS_MetricsReport()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Displays the current metrics through the EAS_Report interface.
+ *
+ * Inputs:
+ * pEASData - instance data handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_MetricsReport (EAS_DATA_HANDLE pEASData);
+
+/*----------------------------------------------------------------------------
+ * EAS_MetricsReset()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Displays the current metrics through the EAS_Report interface.
+ *
+ * Inputs:
+ * pEASData - instance data handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_MetricsReset (EAS_DATA_HANDLE pEASData);
+#endif
+
+/*----------------------------------------------------------------------------
+ * EAS_SetSoundLibrary()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Sets the location of the sound library.
+ *
+ * Inputs:
+ * pEASData - instance data handle
+ * streamHandle - file or stream handle
+ * pSoundLib - pointer to sound library
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_SetSoundLibrary (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_SNDLIB_HANDLE pSndLib);
+
+/*----------------------------------------------------------------------------
+ * EAS_SetHeaderSearchFlag()
+ *----------------------------------------------------------------------------
+ * By default, when EAS_OpenFile is called, the parsers check the
+ * first few bytes of the file looking for a specific header. Some
+ * mobile devices may add a header to the start of a file, which
+ * will prevent the parser from recognizing the file. If the
+ * searchFlag is set to EAS_TRUE, the parser will search the entire
+ * file looking for the header. This may enable EAS to recognize
+ * some files that it would ordinarily reject. The negative is that
+ * it make take slightly longer to process the EAS_OpenFile request.
+ *
+ * Inputs:
+ * pEASData - instance data handle
+ * searchFlag - search flag (EAS_TRUE or EAS_FALSE)
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_SetHeaderSearchFlag (EAS_DATA_HANDLE pEASData, EAS_BOOL searchFlag);
+
+/*----------------------------------------------------------------------------
+ * EAS_SetPlayMode()
+ *----------------------------------------------------------------------------
+ * Some file formats support special play modes, such as iMode partial
+ * play mode. This call can be used to change the play mode. The
+ * default play mode (usually straight playback) is always zero.
+ *
+ * Inputs:
+ * pEASData - instance data handle
+ * handle - file or stream handle
+ * playMode - play mode (see eas_types.h for enumerations)
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_SetPlayMode (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 playMode);
+
+#ifdef DLS_SYNTHESIZER
+/*----------------------------------------------------------------------------
+ * EAS_LoadDLSCollection()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Downloads a DLS collection
+ *
+ * Inputs:
+ * pEASData - instance data handle
+ * streamHandle - file or stream handle
+ * locator - file locator
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ * May overlay instruments in the GM sound set
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_LoadDLSCollection (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_FILE_LOCATOR locator);
+#endif
+
+/*----------------------------------------------------------------------------
+ * EAS_SetFrameBuffer()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Sets the frame buffer pointer passed to the IPC communications functions
+ *
+ * Inputs:
+ * pEASData - instance data handle
+ * locator - file locator
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ * May overlay instruments in the GM sound set
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_SetFrameBuffer (EAS_DATA_HANDLE pEASData, EAS_FRAME_BUFFER_HANDLE pFrameBuffer);
+
+#ifdef EXTERNAL_AUDIO
+/*----------------------------------------------------------------------------
+ * EAS_RegExtAudioCallback()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Registers callback functions for audio events.
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * streamHandle - file or stream handle
+ * cbProgChgFunc - pointer to host callback function for program change
+ * cbEventFunc - pointer to host callback functio for note events
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_RegExtAudioCallback (EAS_DATA_HANDLE pEASData,
+ EAS_HANDLE streamHandle,
+ EAS_VOID_PTR pInstData,
+ EAS_EXT_PRG_CHG_FUNC cbProgChgFunc,
+ EAS_EXT_EVENT_FUNC cbEventFunc);
+
+/*----------------------------------------------------------------------------
+ * EAS_GetMIDIControllers()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Returns the current state of MIDI controllers on the requested channel.
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * streamHandle - file or stream handle
+ * pControl - pointer to structure to receive data
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_PUBLIC EAS_RESULT EAS_GetMIDIControllers (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_U8 channel, S_MIDI_CONTROLLERS *pControl);
+#endif
+
+/*----------------------------------------------------------------------------
+ * EAS_SearchFile
+ *----------------------------------------------------------------------------
+ * Search file for specific sequence starting at current file
+ * position. Returns offset to start of sequence.
+ *
+ * Inputs:
+ * pEASData - pointer to EAS persistent data object
+ * fileHandle - file handle
+ * searchString - pointer to search sequence
+ * len - length of search sequence
+ * pOffset - pointer to variable to store offset to sequence
+ *
+ * Returns EAS_EOF if end-of-file is reached
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_SearchFile (EAS_DATA_HANDLE pEASData, EAS_FILE_HANDLE fileHandle, const EAS_U8 *searchString, EAS_I32 len, EAS_I32 *pOffset);
+
+#ifdef __cplusplus
+} /* end extern "C" */
+#endif
+
+#endif /* #ifndef _EAS_H */
diff --git a/arm-fm-22k/host_src/eas_build.h b/arm-fm-22k/host_src/eas_build.h
new file mode 100644
index 0000000..64ccf5a
--- /dev/null
+++ b/arm-fm-22k/host_src/eas_build.h
@@ -0,0 +1,36 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * host_src\eas_build.h
+ *
+ * Contents and purpose:
+ * This file contains the build configuration for this
+ * build. The buildGUIDStr is a GUID created during
+ * the build process and is guaranteed to be unique
+ * for each build.
+ *
+ * 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.
+ *
+ * This file was autogenerated by buildid.exe
+ *----------------------------------------------------------------------------
+*/
+
+#ifndef _GUID_53c2509edf8f42e3975a054126c0cc1b_
+#define _GUID_53c2509edf8f42e3975a054126c0cc1b_
+
+#define _BUILD_VERSION_ "53c2509e-df8f-42e3-975a-054126c0cc1b"
+#define _BUILD_TIME_ 0x4743b8c9
+
+#endif /* _GUID_53c2509edf8f42e3975a054126c0cc1b_ */
diff --git a/arm-fm-22k/host_src/eas_chorus.h b/arm-fm-22k/host_src/eas_chorus.h
new file mode 100644
index 0000000..0e9057f
--- /dev/null
+++ b/arm-fm-22k/host_src/eas_chorus.h
@@ -0,0 +1,53 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_chorus.h
+ *
+ * Contents and purpose:
+ * Contains parameter enumerations 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
+
+/* enumerated parameter settings for Chorus effect */
+typedef enum
+{
+ EAS_PARAM_CHORUS_BYPASS,
+ EAS_PARAM_CHORUS_PRESET,
+ EAS_PARAM_CHORUS_RATE,
+ EAS_PARAM_CHORUS_DEPTH,
+ EAS_PARAM_CHORUS_LEVEL
+} E_CHORUS_PARAMS;
+
+typedef enum
+{
+ EAS_PARAM_CHORUS_PRESET1,
+ EAS_PARAM_CHORUS_PRESET2,
+ EAS_PARAM_CHORUS_PRESET3,
+ EAS_PARAM_CHORUS_PRESET4
+} E_CHORUS_PRESETS;
+
+
+#endif \ No newline at end of file
diff --git a/arm-fm-22k/host_src/eas_config.c b/arm-fm-22k/host_src/eas_config.c
new file mode 100644
index 0000000..c45fbb7
--- /dev/null
+++ b/arm-fm-22k/host_src/eas_config.c
@@ -0,0 +1,619 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_config.c
+ *
+ * Contents and purpose:
+ * This file contains the Configuration Module interface (CM). The CM
+ * is a module compiled external to the library that sets the configuration
+ * for this build. It allows the library to find optional components and
+ * links to static memory allocations (when used in a static configuration).
+ *
+ * DO NOT MODIFY THIS FILE!
+ *
+ * NOTE: This module is not intended to be modified by the customer. It
+ * needs to be included in the build process with the correct configuration
+ * defines (see the library documentation for information on how to configure
+ * the library).
+ *
+ * Copyright Sonic Network Inc. 2004-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: 796 $
+ * $Date: 2007-08-01 00:15:25 -0700 (Wed, 01 Aug 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+#include "eas.h"
+#include "eas_config.h"
+
+
+#ifdef _MFI_PARSER
+/*----------------------------------------------------------------------------
+ * Vendor/Device ID for MFi Extensions
+ *
+ * Define the preprocessor symbols to establish the vendor ID and
+ * device ID for the MFi PCM/ADPCM extensions.
+ *----------------------------------------------------------------------------
+*/
+const EAS_U8 eas_MFIVendorIDMSB = (MFI_VENDOR_ID >> 8) & 0xff;
+const EAS_U8 eas_MFIVendorIDLSB = MFI_VENDOR_ID & 0xff;
+const EAS_U8 eas_MFIDeviceID = MFI_DEVICE_ID;
+#endif
+
+/*----------------------------------------------------------------------------
+ *
+ * parserModules
+ *
+ * This structure is used by the EAS library to locate file parsing
+ * modules.
+ *----------------------------------------------------------------------------
+*/
+
+/* define the external file parsers */
+extern EAS_VOID_PTR EAS_SMF_Parser;
+
+#ifdef _XMF_PARSER
+extern EAS_VOID_PTR EAS_XMF_Parser;
+#endif
+
+#ifdef _SMAF_PARSER
+extern EAS_VOID_PTR EAS_SMAF_Parser;
+#endif
+
+#ifdef _WAVE_PARSER
+extern EAS_VOID_PTR EAS_Wave_Parser;
+#endif
+
+#ifdef _OTA_PARSER
+extern EAS_VOID_PTR EAS_OTA_Parser;
+#endif
+
+#ifdef _IMELODY_PARSER
+extern EAS_VOID_PTR EAS_iMelody_Parser;
+#endif
+
+#ifdef _RTTTL_PARSER
+extern EAS_VOID_PTR EAS_RTTTL_Parser;
+#endif
+
+#if defined (_CMX_PARSER) || defined(_MFI_PARSER)
+extern EAS_VOID_PTR EAS_CMF_Parser;
+#endif
+
+/* initalize pointers to parser interfaces */
+/*lint -e{605} not pretty, but it works */
+EAS_VOID_PTR const parserModules[] =
+{
+ &EAS_SMF_Parser,
+
+#ifdef _XMF_PARSER
+ &EAS_XMF_Parser,
+#endif
+
+#ifdef _WAVE_PARSER
+ &EAS_Wave_Parser,
+#endif
+
+#ifdef _SMAF_PARSER
+ &EAS_SMAF_Parser,
+#endif
+
+#ifdef _OTA_PARSER
+ &EAS_OTA_Parser,
+#endif
+
+#ifdef _IMELODY_PARSER
+ &EAS_iMelody_Parser,
+#endif
+
+#ifdef _RTTTL_PARSER
+ &EAS_RTTTL_Parser,
+#endif
+
+#if defined (_CMX_PARSER) || defined(_MFI_PARSER)
+ &EAS_CMF_Parser
+#endif
+};
+#define NUM_PARSER_MODULES (sizeof(parserModules) / sizeof(EAS_VOID_PTR))
+
+/*----------------------------------------------------------------------------
+ * Data Modules
+ *----------------------------------------------------------------------------
+*/
+
+#ifdef _STATIC_MEMORY
+extern EAS_VOID_PTR eas_SMFData;
+extern EAS_VOID_PTR eas_Data;
+extern EAS_VOID_PTR eas_MixBuffer;
+extern EAS_VOID_PTR eas_Synth;
+extern EAS_VOID_PTR eas_MIDI;
+extern EAS_VOID_PTR eas_PCMData;
+extern EAS_VOID_PTR eas_MIDIData;
+
+#ifdef _XMF_PARSER
+extern EAS_VOID_PTR eas_XMFData;
+#endif
+
+#ifdef _SMAF_PARSER
+extern EAS_VOID_PTR eas_SMAFData;
+#endif
+
+#ifdef _OTA_PARSER
+extern EAS_VOID_PTR eas_OTAData;
+#endif
+
+#ifdef _IMELODY_PARSER
+extern EAS_VOID_PTR eas_iMelodyData;
+#endif
+
+#ifdef _RTTTL_PARSER
+extern EAS_VOID_PTR eas_RTTTLData;
+#endif
+
+#ifdef _WAVE_PARSER
+extern EAS_VOID_PTR eas_WaveData;
+#endif
+
+#if defined (_CMX_PARSER) || defined(_MFI_PARSER)
+extern EAS_VOID_PTR eas_CMFData;
+#endif
+#endif
+
+/*----------------------------------------------------------------------------
+ *
+ * Effects Modules
+ *
+ * These declarations are used by the EAS library to locate
+ * effects modules.
+ *----------------------------------------------------------------------------
+*/
+
+#ifdef _ENHANCER_ENABLED
+extern EAS_VOID_PTR EAS_Enhancer;
+#define EAS_ENHANCER_INTERFACE &EAS_Enhancer
+#ifdef _STATIC_MEMORY
+extern EAS_VOID_PTR eas_EnhancerData;
+#define EAS_ENHANCER_DATA &eas_EnhancerData
+#else
+#define EAS_ENHANCER_DATA NULL
+#endif
+#else
+#define EAS_ENHANCER_INTERFACE NULL
+#define EAS_ENHANCER_DATA NULL
+#endif
+
+#ifdef _COMPRESSOR_ENABLED
+extern EAS_VOID_PTR EAS_Compressor;
+#define EAS_COMPRESSOR_INTERFACE &EAS_Compressor
+#ifdef _STATIC_MEMORY
+extern EAS_VOID_PTR eas_CompressorData;
+#define EAS_COMPRESSOR_DATA &eas_CompressorData
+#else
+#define EAS_COMPRESSOR_DATA NULL
+#endif
+#else
+#define EAS_COMPRESSOR_INTERFACE NULL
+#define EAS_COMPRESSOR_DATA NULL
+#endif
+
+#ifdef _MAXIMIZER_ENABLED
+extern EAS_VOID_PTR EAS_Maximizer;
+#define EAS_MAXIMIZER_INTERFACE &EAS_Maximizer
+#ifdef _STATIC_MEMORY
+extern EAS_VOID_PTR eas_MaximizerData;
+#define EAS_MAXIMIZER_DATA &eas_MaximizerData
+#else
+#define EAS_MAXIMIZER_DATA NULL
+#endif
+#else
+#define EAS_MAXIMIZER_INTERFACE NULL
+#define EAS_MAXIMIZER_DATA NULL
+#endif
+
+
+#ifdef _REVERB_ENABLED
+extern EAS_VOID_PTR EAS_Reverb;
+#define EAS_REVERB_INTERFACE &EAS_Reverb
+#ifdef _STATIC_MEMORY
+extern EAS_VOID_PTR eas_ReverbData;
+#define EAS_REVERB_DATA &eas_ReverbData
+#else
+#define EAS_REVERB_DATA NULL
+#endif
+#else
+#define EAS_REVERB_INTERFACE NULL
+#define EAS_REVERB_DATA NULL
+#endif
+
+#ifdef _CHORUS_ENABLED
+extern EAS_VOID_PTR EAS_Chorus;
+#define EAS_CHORUS_INTERFACE &EAS_Chorus
+#ifdef _STATIC_MEMORY
+extern EAS_VOID_PTR eas_ChorusData;
+#define EAS_CHORUS_DATA &eas_ChorusData
+#else
+#define EAS_CHORUS_DATA NULL
+#endif
+#else
+#define EAS_CHORUS_INTERFACE NULL
+#define EAS_CHORUS_DATA NULL
+#endif
+
+#ifdef _WIDENER_ENABLED
+extern EAS_VOID_PTR EAS_Widener;
+#define EAS_WIDENER_INTERFACE &EAS_Widener
+#ifdef _STATIC_MEMORY
+extern EAS_VOID_PTR eas_WidenerData;
+#define EAS_WIDENER_DATA &eas_WidenerData
+#else
+#define EAS_WIDENER_DATA NULL
+#endif
+#else
+#define EAS_WIDENER_INTERFACE NULL
+#define EAS_WIDENER_DATA NULL
+#endif
+
+#ifdef _GRAPHIC_EQ_ENABLED
+extern EAS_VOID_PTR EAS_GraphicEQ;
+#define EAS_GRAPHIC_EQ_INTERFACE &EAS_GraphicEQ
+#ifdef _STATIC_MEMORY
+extern EAS_VOID_PTR eas_GraphicEQData;
+#define EAS_GRAPHIC_EQ_DATA &eas_GraphicEQData
+#else
+#define EAS_GRAPHIC_EQ_DATA NULL
+#endif
+#else
+#define EAS_GRAPHIC_EQ_INTERFACE NULL
+#define EAS_GRAPHIC_EQ_DATA NULL
+#endif
+
+#ifdef _WOW_ENABLED
+extern EAS_VOID_PTR EAS_Wow;
+#define EAS_WOW_INTERFACE &EAS_Wow
+#ifdef _STATIC_MEMORY
+#error "WOW module requires dynamic memory model"
+#else
+#define EAS_WOW_DATA NULL
+#endif
+#else
+#define EAS_WOW_INTERFACE NULL
+#define EAS_WOW_DATA NULL
+#endif
+
+#ifdef _TONECONTROLEQ_ENABLED
+extern EAS_VOID_PTR EAS_ToneControlEQ;
+#define EAS_TONECONTROLEQ_INTERFACE &EAS_ToneControlEQ
+#ifdef _STATIC_MEMORY
+extern EAS_VOID_PTR eas_ToneControlEQData;
+#define EAS_TONECONTROLEQ_DATA &eas_ToneControlEQData
+#else
+#define EAS_TONECONTROLEQ_DATA NULL
+#endif
+#else
+#define EAS_TONECONTROLEQ_INTERFACE NULL
+#define EAS_TONECONTROLEQ_DATA NULL
+#endif
+
+/*lint -e{605} not pretty, but it works */
+EAS_VOID_PTR const effectsModules[] =
+{
+ EAS_ENHANCER_INTERFACE,
+ EAS_COMPRESSOR_INTERFACE,
+ EAS_REVERB_INTERFACE,
+ EAS_CHORUS_INTERFACE,
+ EAS_WIDENER_INTERFACE,
+ EAS_GRAPHIC_EQ_INTERFACE,
+ EAS_WOW_INTERFACE,
+ EAS_MAXIMIZER_INTERFACE,
+ EAS_TONECONTROLEQ_INTERFACE
+};
+
+EAS_VOID_PTR const effectsData[] =
+{
+ EAS_ENHANCER_DATA,
+ EAS_COMPRESSOR_DATA,
+ EAS_REVERB_DATA,
+ EAS_CHORUS_DATA,
+ EAS_WIDENER_DATA,
+ EAS_GRAPHIC_EQ_DATA,
+ EAS_WOW_DATA,
+ EAS_MAXIMIZER_DATA,
+ EAS_TONECONTROLEQ_DATA
+};
+
+/*----------------------------------------------------------------------------
+ *
+ * Optional Modules
+ *
+ * These declarations are used by the EAS library to locate
+ * effects modules.
+ *----------------------------------------------------------------------------
+*/
+
+#ifdef _METRICS_ENABLED
+extern EAS_VOID_PTR EAS_Metrics;
+#define EAS_METRICS_INTERFACE &EAS_Metrics
+#ifdef _STATIC_MEMORY
+extern EAS_VOID_PTR eas_MetricsData;
+#define EAS_METRICS_DATA &eas_MetricsData
+#else
+#define EAS_METRICS_DATA NULL
+#endif
+#else
+#define EAS_METRICS_INTERFACE NULL
+#define EAS_METRICS_DATA NULL
+#endif
+
+#ifdef MMAPI_SUPPORT
+extern EAS_VOID_PTR EAS_TC_Parser;
+#define EAS_TONE_CONTROL_PARSER &EAS_TC_Parser
+#ifdef _STATIC_MEMORY
+extern EAS_VOID_PTR eas_TCData;
+#define EAS_TONE_CONTROL_DATA &eas_TCData
+#else
+#define EAS_TONE_CONTROL_DATA NULL
+#endif
+#else
+#define EAS_TONE_CONTROL_PARSER NULL
+#define EAS_TONE_CONTROL_DATA NULL
+#endif
+
+/*lint -e{605} not pretty, but it works */
+EAS_VOID_PTR const optionalModules[] =
+{
+ EAS_TONE_CONTROL_PARSER,
+ EAS_METRICS_INTERFACE
+};
+
+EAS_VOID_PTR const optionalData[] =
+{
+ EAS_TONE_CONTROL_DATA,
+ EAS_METRICS_DATA
+};
+
+/*----------------------------------------------------------------------------
+ * EAS_CMStaticMemoryModel()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * This function returns true if EAS has been configured for
+ * a static memory model. There are some limitations in the
+ * static memory model, see the documentation for more
+ * information.
+ *
+ * Outputs:
+ * returns EAS_TRUE if a module is found
+ *----------------------------------------------------------------------------
+*/
+EAS_BOOL EAS_CMStaticMemoryModel (void)
+{
+#ifdef _STATIC_MEMORY
+ return EAS_TRUE;
+#else
+ return EAS_FALSE;
+#endif
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_CMEnumModules()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * This function is used to find pointers to optional modules.
+ *
+ * Inputs:
+ * module - module number
+ *
+ * Outputs:
+ * returns a pointer to the module function table or NULL if no module
+ *----------------------------------------------------------------------------
+*/
+EAS_VOID_PTR EAS_CMEnumModules (EAS_INT module)
+{
+
+ if (module >= (EAS_INT) NUM_PARSER_MODULES)
+ return NULL;
+ return parserModules[module];
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_CMEnumData()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * This function is used to find pointers to static memory allocations.
+ *
+ * Inputs:
+ * dataModule - enumerated module number
+ *
+ * Outputs:
+ * Returns handle to data or NULL if not found
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, dataModule) used only when _STATIC_MEMORY is defined */
+EAS_VOID_PTR EAS_CMEnumData (EAS_INT dataModule)
+{
+
+#ifdef _STATIC_MEMORY
+ switch (dataModule)
+ {
+
+ /* main instance data for synthesizer */
+ case EAS_CM_EAS_DATA:
+ return &eas_Data;
+
+ /* mix buffer for mix engine */
+ case EAS_CM_MIX_BUFFER:
+ /*lint -e{545} lint doesn't like this because it sees the underlying type */
+ return &eas_MixBuffer;
+
+ /* instance data for synth */
+ case EAS_CM_SYNTH_DATA:
+ return &eas_Synth;
+
+ /* instance data for MIDI parser */
+ case EAS_CM_MIDI_DATA:
+ return &eas_MIDI;
+
+ /* instance data for SMF parser */
+ case EAS_CM_SMF_DATA:
+ return &eas_SMFData;
+
+#ifdef _XMF_PARSER
+ /* instance data for XMF parser */
+ case EAS_CM_XMF_DATA:
+ return &eas_XMFData;
+#endif
+
+#ifdef _SMAF_PARSER
+ /* instance data for SMAF parser */
+ case EAS_CM_SMAF_DATA:
+ return &eas_SMAFData;
+#endif
+
+ /* instance data for the PCM engine */
+ case EAS_CM_PCM_DATA:
+ /*lint -e{545} lint doesn't like this because it sees the underlying type */
+ return &eas_PCMData;
+
+ case EAS_CM_MIDI_STREAM_DATA:
+ return &eas_MIDIData;
+
+#ifdef _OTA_PARSER
+ /* instance data for OTA parser */
+ case EAS_CM_OTA_DATA:
+ return &eas_OTAData;
+#endif
+
+#ifdef _IMELODY_PARSER
+ /* instance data for iMelody parser */
+ case EAS_CM_IMELODY_DATA:
+ return &eas_iMelodyData;
+#endif
+
+#ifdef _RTTTL_PARSER
+ /* instance data for RTTTL parser */
+ case EAS_CM_RTTTL_DATA:
+ return &eas_RTTTLData;
+#endif
+
+#ifdef _WAVE_PARSER
+ /* instance data for WAVE parser */
+ case EAS_CM_WAVE_DATA:
+ return &eas_WaveData;
+#endif
+
+#if defined (_CMX_PARSER) || defined(_MFI_PARSER)
+ /* instance data for CMF parser */
+ case EAS_CM_CMF_DATA:
+ return &eas_CMFData;
+#endif
+
+ default:
+ return NULL;
+ }
+
+#else
+ return NULL;
+#endif
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_CMEnumFXModules()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * This function is used to find pointers to optional effects modules.
+ *
+ * Inputs:
+ * module - enumerated module number
+ * pModule - pointer to module interface
+ *
+ * Outputs:
+ * Returns pointer to function table or NULL if not found
+ *----------------------------------------------------------------------------
+*/
+EAS_VOID_PTR EAS_CMEnumFXModules (EAS_INT module)
+{
+
+ if (module >= NUM_EFFECTS_MODULES)
+ return NULL;
+ return effectsModules[module];
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_CMEnumFXData()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * This function is used to find pointers to static memory allocations.
+ *
+ * Inputs:
+ * dataModule - enumerated module number
+ * pData - pointer to handle variable
+ *
+ * Outputs:
+ * Returns handle to data or NULL if not found
+ *----------------------------------------------------------------------------
+*/
+EAS_VOID_PTR EAS_CMEnumFXData (EAS_INT dataModule)
+{
+
+ if (dataModule >= NUM_EFFECTS_MODULES)
+ return NULL;
+ return effectsData[dataModule];
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_CMEnumOptModules()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * This function is used to find pointers to optional modules.
+ *
+ * Inputs:
+ * module - enumerated module number
+ *
+ * Outputs:
+ * returns pointer to function table or NULL if no module
+ *----------------------------------------------------------------------------
+*/
+EAS_VOID_PTR EAS_CMEnumOptModules (EAS_INT module)
+{
+
+ /* sanity check */
+ if (module >= NUM_OPTIONAL_MODULES)
+ return EAS_FALSE;
+ return optionalModules[module];
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_CMEnumOptData()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * This function is used to find pointers to static memory allocations.
+ *
+ * Inputs:
+ * dataModule - enumerated module number
+ *
+ * Outputs:
+ * Returns handle to data or NULL if not found
+ *----------------------------------------------------------------------------
+*/
+EAS_VOID_PTR EAS_CMEnumOptData (EAS_INT dataModule)
+{
+
+ if (dataModule >= NUM_OPTIONAL_MODULES)
+ return NULL;
+ return optionalData[dataModule];
+}
+
+
diff --git a/arm-fm-22k/host_src/eas_config.h b/arm-fm-22k/host_src/eas_config.h
new file mode 100644
index 0000000..d16be4a
--- /dev/null
+++ b/arm-fm-22k/host_src/eas_config.h
@@ -0,0 +1,191 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_config.h
+ *
+ * Contents and purpose:
+ * This header declares the Configuration Module interface (CM). The CM
+ * is a module compiled external to the library that sets the configuration
+ * for this build. It allows the library to find optional components and
+ * links to static memory allocations (when used in a static configuration).
+ *
+ * NOTE: This module is not intended to be modified by the customer. It
+ * needs to be included in the build process with the correct configuration
+ * defines (see the library documentation for information on how to configure
+ * the library).
+ *
+ * DO NOT MODIFY THIS FILE!
+ *
+ * Copyright 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: 82 $
+ * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $
+ *----------------------------------------------------------------------------
+*/
+
+// sentinel
+#ifndef _EAS_CONFIG_H
+#define _EAS_CONFIG_H
+
+#include "eas_types.h"
+
+/* list of enumerators for optional modules */
+typedef enum {
+ EAS_CM_FILE_PARSERS = 1
+} E_CM_ENUM_MODULES;
+
+/* list of enumerators for module and memory pointers */
+typedef enum {
+ EAS_CM_EAS_DATA = 1,
+ EAS_CM_MIX_BUFFER,
+ EAS_CM_SYNTH_DATA,
+ EAS_CM_MIDI_DATA,
+ EAS_CM_SMF_DATA,
+ EAS_CM_XMF_DATA,
+ EAS_CM_SMAF_DATA,
+ EAS_CM_PCM_DATA,
+ EAS_CM_MIDI_STREAM_DATA,
+ EAS_CM_METRICS_DATA,
+ EAS_CM_OTA_DATA,
+ EAS_CM_IMELODY_DATA,
+ EAS_CM_RTTTL_DATA,
+ EAS_CM_WAVE_DATA,
+ EAS_CM_CMF_DATA
+} E_CM_DATA_MODULES;
+
+typedef struct
+{
+ int maxSMFStreams;
+ void *pSMFData;
+ void *pSMFStream;
+} S_EAS_SMF_PTRS;
+
+typedef struct
+{
+ int maxSMAFStreams;
+ void *pSMAFData;
+ void *pSMAFStream;
+} S_EAS_SMAF_PTRS;
+
+/*----------------------------------------------------------------------------
+ * EAS_CMStaticMemoryModel()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * This function returns true if EAS has been configured for
+ * a static memory model. There are some limitations in the
+ * static memory model, see the documentation for more
+ * information.
+ *
+ * Outputs:
+ * returns EAS_TRUE if a module is found
+ *----------------------------------------------------------------------------
+*/
+EAS_BOOL EAS_CMStaticMemoryModel (void);
+
+/*----------------------------------------------------------------------------
+ * EAS_CMEnumModules()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * This function is used to find pointers to optional modules.
+ *
+ * Inputs:
+ * module - module number
+ *
+ * Outputs:
+ * returns a pointer to the module function table or NULL if no module
+ *----------------------------------------------------------------------------
+*/
+EAS_VOID_PTR EAS_CMEnumModules (EAS_INT module);
+
+/*----------------------------------------------------------------------------
+ * EAS_CMEnumData()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * This function is used to find pointers to static memory allocations.
+ *
+ * Inputs:
+ * dataModule - enumerated module number
+ *
+ * Outputs:
+ * Returns handle to data or NULL if not found
+ *----------------------------------------------------------------------------
+*/
+EAS_VOID_PTR EAS_CMEnumData (EAS_INT dataModule);
+
+/*----------------------------------------------------------------------------
+ * EAS_CMEnumFXModules()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * This function is used to find pointers to optional effects modules.
+ *
+ * Inputs:
+ * module - enumerated module number
+ * pModule - pointer to module interface
+ *
+ * Outputs:
+ * Returns pointer to function table or NULL if not found
+ *----------------------------------------------------------------------------
+*/
+EAS_VOID_PTR EAS_CMEnumFXModules (EAS_INT module);
+
+/*----------------------------------------------------------------------------
+ * EAS_CMEnumFXData()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * This function is used to find pointers to static memory allocations.
+ *
+ * Inputs:
+ * dataModule - enumerated module number
+ * pData - pointer to handle variable
+ *
+ * Outputs:
+ * Returns handle to data or NULL if not found
+ *----------------------------------------------------------------------------
+*/
+EAS_VOID_PTR EAS_CMEnumFXData (EAS_INT dataModule);
+
+/*----------------------------------------------------------------------------
+ * EAS_CMEnumOptModules()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * This function is used to find pointers to optional modules.
+ *
+ * Inputs:
+ * module - enumerated module number
+ *
+ * Outputs:
+ * returns pointer to function table or NULL if no module
+ *----------------------------------------------------------------------------
+*/
+EAS_VOID_PTR EAS_CMEnumOptModules (EAS_INT module);
+
+/*----------------------------------------------------------------------------
+ * EAS_CMEnumOptData()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * This function is used to find pointers to static memory allocations.
+ *
+ * Inputs:
+ * dataModule - enumerated module number
+ *
+ * Outputs:
+ * Returns handle to data or NULL if not found
+ *----------------------------------------------------------------------------
+*/
+EAS_VOID_PTR EAS_CMEnumOptData (EAS_INT dataModule);
+
+#endif /* end _EAS_CONFIG_H */
diff --git a/arm-fm-22k/host_src/eas_debugmsgs.h b/arm-fm-22k/host_src/eas_debugmsgs.h
new file mode 100644
index 0000000..436875b
--- /dev/null
+++ b/arm-fm-22k/host_src/eas_debugmsgs.h
@@ -0,0 +1,43 @@
+/* Auto-generated from source file: eas_chorusdata.c */
+/* Auto-generated from source file: eas_imelodydata.c */
+/* Auto-generated from source file: eas_mididata.c */
+/* Auto-generated from source file: eas_pan.c */
+/* Auto-generated from source file: eas_wavefiledata.c */
+/* Auto-generated from source file: eas_voicemgt.c */
+/* Auto-generated from source file: eas_ota.c */
+/* Auto-generated from source file: eas_mixbuf.c */
+/* Auto-generated from source file: eas_fmsndlib.c */
+/* Auto-generated from source file: eas_rtttl.c */
+/* Auto-generated from source file: eas_reverb.c */
+/* Auto-generated from source file: eas_fmsynth.c */
+/* Auto-generated from source file: eas_pcmdata.c */
+/* Auto-generated from source file: eas_chorus.c */
+/* Auto-generated from source file: eas_math.c */
+/* Auto-generated from source file: eas_fmengine.c */
+/* Auto-generated from source file: eas_smfdata.c */
+/* Auto-generated from source file: eas_fmtables.c */
+/* Auto-generated from source file: eas_imelody.c */
+/* Auto-generated from source file: eas_public.c */
+/* Auto-generated from source file: eas_rtttldata.c */
+/* Auto-generated from source file: eas_reverbdata.c */
+/* Auto-generated from source file: eas_imaadpcm.c */
+{ 0x2380b977, 0x00000006, "eas_imaadpcm.c[305]: IMADecoderLocate: Time=%d, samples=%d\n" },
+{ 0x2380b977, 0x00000007, "eas_imaadpcm.c[328]: IMADecoderLocate: Looped sample, numBlocks=%d, samplesPerLoop=%d, samplesInLastBlock=%d, samples=%d\n" },
+{ 0x2380b977, 0x00000008, "eas_imaadpcm.c[335]: IMADecoderLocate: Byte location in audio = %d\n" },
+{ 0x2380b977, 0x00000009, "eas_imaadpcm.c[345]: IMADecoderLocate: bytesLeft = %d\n" },
+/* Auto-generated from source file: eas_midi.c */
+/* Auto-generated from source file: eas_otadata.c */
+/* Auto-generated from source file: eas_ima_tables.c */
+/* Auto-generated from source file: eas_data.c */
+/* Auto-generated from source file: eas_pcm.c */
+/* Auto-generated from source file: eas_mixer.c */
+/* Auto-generated from source file: eas_wavefile.c */
+/* Auto-generated from source file: eas_smf.c */
+/* Auto-generated from source file: eas_wave.c */
+/* Auto-generated from source file: eas_hostmm.c */
+{ 0x1a54b6e8, 0x00000001, "eas_hostmm.c[586]: Vibrate state: %d\n" },
+{ 0x1a54b6e8, 0x00000002, "eas_hostmm.c[601]: LED state: %d\n" },
+{ 0x1a54b6e8, 0x00000003, "eas_hostmm.c[616]: Backlight state: %d\n" },
+/* Auto-generated from source file: eas_config.c */
+/* Auto-generated from source file: eas_main.c */
+{ 0xe624f4d9, 0x00000005, "eas_main.c[106]: Play length: %d.%03d (secs)\n" },
diff --git a/arm-fm-22k/host_src/eas_host.h b/arm-fm-22k/host_src/eas_host.h
new file mode 100644
index 0000000..0db0e30
--- /dev/null
+++ b/arm-fm-22k/host_src/eas_host.h
@@ -0,0 +1,83 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_host.h
+ *
+ * Contents and purpose:
+ * This header defines the host wrapper functions for stdio, stdlib, etc.
+ * The host application must provide an abstraction layer for these functions
+ * to support certain features, such as SMAF and SMF-1 conversion.
+ *
+ * DO NOT MODIFY THIS FILE!
+ *
+ * Copyright 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: 82 $
+ * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $
+ *----------------------------------------------------------------------------
+*/
+
+// sentinel
+#ifndef _EAS_HOST_H
+#define _EAS_HOST_H
+
+#include "eas_types.h"
+
+/* for C++ linkage */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* initialization and shutdown routines */
+extern EAS_RESULT EAS_HWInit(EAS_HW_DATA_HANDLE *hwInstData);
+extern EAS_RESULT EAS_HWShutdown(EAS_HW_DATA_HANDLE hwInstData);
+
+/* memory functions */
+extern void *EAS_HWMemSet(void *s, int c, EAS_I32 n);
+extern void *EAS_HWMemCpy(void *s1, const void *s2, EAS_I32 n);
+extern EAS_I32 EAS_HWMemCmp(const void *s1, const void *s2, EAS_I32 n);
+
+/* memory allocation */
+extern void *EAS_HWMalloc(EAS_HW_DATA_HANDLE hwInstData, EAS_I32 size);
+extern void EAS_HWFree(EAS_HW_DATA_HANDLE hwInstData, void *p);
+
+/* file I/O */
+extern EAS_RESULT EAS_HWOpenFile(EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_LOCATOR locator, EAS_FILE_HANDLE *pFile, EAS_FILE_MODE mode);
+extern EAS_RESULT EAS_HWReadFile(EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *pBuffer, EAS_I32 n, EAS_I32 *pBytesRead);
+extern EAS_RESULT EAS_HWGetByte(EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p);
+extern EAS_RESULT EAS_HWGetWord (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p, EAS_BOOL msbFirst);
+extern EAS_RESULT EAS_HWGetDWord (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p, EAS_BOOL msbFirst);
+extern EAS_RESULT EAS_HWFilePos (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 *pPosition);
+extern EAS_RESULT EAS_HWFileSeek (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 position);
+extern EAS_RESULT EAS_HWFileSeekOfs (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 position);
+extern EAS_RESULT EAS_HWFileLength (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 *pLength);
+extern EAS_RESULT EAS_HWDupHandle (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_FILE_HANDLE* pFile);
+extern EAS_RESULT EAS_HWCloseFile (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file);
+
+/* vibrate, LED, and backlight functions */
+extern EAS_RESULT EAS_HWVibrate(EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state);
+extern EAS_RESULT EAS_HWLED(EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state);
+extern EAS_RESULT EAS_HWBackLight(EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state);
+
+#ifdef __cplusplus
+} /* end extern "C" */
+#endif
+
+
+/* host yield function */
+extern EAS_BOOL EAS_HWYield(EAS_HW_DATA_HANDLE hwInstData);
+#endif /* end _EAS_HOST_H */
diff --git a/arm-fm-22k/host_src/eas_hostmm.c b/arm-fm-22k/host_src/eas_hostmm.c
new file mode 100644
index 0000000..7e58838
--- /dev/null
+++ b/arm-fm-22k/host_src/eas_hostmm.c
@@ -0,0 +1,660 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_hostmm.c
+ *
+ * Contents and purpose:
+ * This file contains the host wrapper functions for stdio, stdlib, etc.
+ * This is a sample version that maps the requested files to an
+ * allocated memory block and uses in-memory pointers to replace
+ * file system calls. The file locator (EAS_FILE_LOCATOR) handle passed
+ * HWOpenFile is the same one that is passed to EAS_OpenFile. If your
+ * system stores data in fixed locations (such as flash) instead of
+ * using a file system, you can use the locator handle to point to
+ * your memory. You will need a way of knowing the length of the
+ * data stored at that location in order to respond correctly in the
+ * HW_FileLength function.
+ *
+ * Modify this file to suit the needs of your particular system.
+ *
+ * EAS_MAX_FILE_HANDLES sets the maximum number of MIDI streams within
+ * a MIDI type 1 file that can be played.
+ *
+ * EAS_HW_FILE is a structure to support the file I/O functions. It
+ * comprises the base memory pointer, the file read pointer, and
+ * the dup flag, which when sets, indicates that the file handle has
+ * been duplicated. If your system uses in-memory resources, you
+ * can eliminate the duplicate handle logic, and simply copy the
+ * base memory pointer and file read pointer to the duplicate handle.
+ *
+ * Copyright 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: 795 $
+ * $Date: 2007-08-01 00:14:45 -0700 (Wed, 01 Aug 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+#ifdef _lint
+#include "lint_stdlib.h"
+#else
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+#include "eas_host.h"
+
+/* Only for debugging LED, vibrate, and backlight functions */
+#include "eas_report.h"
+
+/* this module requires dynamic memory support */
+#ifdef _STATIC_MEMORY
+#error "eas_hostmm.c requires the dynamic memory model!\n"
+#endif
+
+#ifndef EAS_MAX_FILE_HANDLES
+#define EAS_MAX_FILE_HANDLES 32
+#endif
+
+/*
+ * this structure and the related function are here
+ * to support the ability to create duplicate handles
+ * and buffering it in memory. If your system uses
+ * in-memory resources, you can eliminate the calls
+ * to malloc and free, the dup flag, and simply track
+ * the file size and read position.
+ */
+typedef struct eas_hw_file_tag
+{
+ EAS_I32 fileSize;
+ EAS_I32 filePos;
+ EAS_BOOL dup;
+ EAS_U8 *buffer;
+} EAS_HW_FILE;
+
+typedef struct eas_hw_inst_data_tag
+{
+ EAS_HW_FILE files[EAS_MAX_FILE_HANDLES];
+} EAS_HW_INST_DATA;
+
+/*----------------------------------------------------------------------------
+ * EAS_HWInit
+ *
+ * Initialize host wrapper interface
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_HWInit (EAS_HW_DATA_HANDLE *pHWInstData)
+{
+
+ /* need to track file opens for duplicate handles */
+ *pHWInstData = malloc(sizeof(EAS_HW_INST_DATA));
+ if (!(*pHWInstData))
+ return EAS_ERROR_MALLOC_FAILED;
+
+ EAS_HWMemSet(*pHWInstData, 0, sizeof(EAS_HW_INST_DATA));
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_HWShutdown
+ *
+ * Shut down host wrapper interface
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_HWShutdown (EAS_HW_DATA_HANDLE hwInstData)
+{
+
+ free(hwInstData);
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ *
+ * EAS_HWMalloc
+ *
+ * Allocates dynamic memory
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, hwInstData) hwInstData available for customer use */
+void *EAS_HWMalloc (EAS_HW_DATA_HANDLE hwInstData, EAS_I32 size)
+{
+ return malloc((size_t) size);
+}
+
+/*----------------------------------------------------------------------------
+ *
+ * EAS_HWFree
+ *
+ * Frees dynamic memory
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, hwInstData) hwInstData available for customer use */
+void EAS_HWFree (EAS_HW_DATA_HANDLE hwInstData, void *p)
+{
+ free(p);
+}
+
+/*----------------------------------------------------------------------------
+ *
+ * EAS_HWMemCpy
+ *
+ * Copy memory wrapper
+ *
+ *----------------------------------------------------------------------------
+*/
+void *EAS_HWMemCpy (void *dest, const void *src, EAS_I32 amount)
+{
+ return memcpy(dest, src, (size_t) amount);
+}
+
+/*----------------------------------------------------------------------------
+ *
+ * EAS_HWMemSet
+ *
+ * Set memory wrapper
+ *
+ *----------------------------------------------------------------------------
+*/
+void *EAS_HWMemSet (void *dest, int val, EAS_I32 amount)
+{
+ return memset(dest, val, (size_t) amount);
+}
+
+/*----------------------------------------------------------------------------
+ *
+ * EAS_HWMemCmp
+ *
+ * Compare memory wrapper
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_I32 EAS_HWMemCmp (const void *s1, const void *s2, EAS_I32 amount)
+{
+ return (EAS_I32) memcmp(s1, s2, (size_t) amount);
+}
+
+/*----------------------------------------------------------------------------
+ *
+ * EAS_HWOpenFile
+ *
+ * Open a file for read or write
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_HWOpenFile (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_LOCATOR locator, EAS_FILE_HANDLE *pFile, EAS_FILE_MODE mode)
+{
+ EAS_HW_FILE *file;
+ FILE *ioFile;
+ int i, temp;
+
+ /* set return value to NULL */
+ *pFile = NULL;
+
+ /* only support read mode at this time */
+ if (mode != EAS_FILE_READ)
+ return EAS_ERROR_INVALID_FILE_MODE;
+
+ /* find an empty entry in the file table */
+ file = hwInstData->files;
+ for (i = 0; i < EAS_MAX_FILE_HANDLES; i++)
+ {
+ /* is this slot being used? */
+ if (file->buffer == NULL)
+ {
+ /* open the file */
+ if ((ioFile = fopen(locator,"rb")) == NULL)
+ return EAS_ERROR_FILE_OPEN_FAILED;
+
+ /* determine the file size */
+ if (fseek(ioFile, 0L, SEEK_END) != 0)
+ return EAS_ERROR_FILE_LENGTH;
+ if ((file->fileSize = ftell(ioFile)) == -1L)
+ return EAS_ERROR_FILE_LENGTH;
+ if (fseek(ioFile, 0L, SEEK_SET) != 0)
+ return EAS_ERROR_FILE_LENGTH;
+
+ /* allocate a buffer */
+ file->buffer = EAS_HWMalloc(hwInstData, file->fileSize);
+ if (file->buffer == NULL)
+ {
+ fclose(ioFile);
+ return EAS_ERROR_MALLOC_FAILED;
+ }
+
+ /* read the file into memory */
+ temp = (int) fread(file->buffer, (size_t) file->fileSize, 1, ioFile);
+
+ /* close the file - don't need it any more */
+ fclose(ioFile);
+
+ /* check for error reading file */
+ if (temp != 1)
+ return EAS_ERROR_FILE_READ_FAILED;
+
+ /* initialize some values */
+ file->filePos = 0;
+ file->dup = EAS_FALSE;
+
+ *pFile = file;
+ return EAS_SUCCESS;
+ }
+ file++;
+ }
+
+ /* too many open files */
+ return EAS_ERROR_MAX_FILES_OPEN;
+}
+
+/*----------------------------------------------------------------------------
+ *
+ * EAS_HWReadFile
+ *
+ * Read data from a file
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, hwInstData) hwInstData available for customer use */
+EAS_RESULT EAS_HWReadFile (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *pBuffer, EAS_I32 n, EAS_I32 *pBytesRead)
+{
+ EAS_I32 count;
+
+ /* make sure we have a valid handle */
+ if (file->buffer == NULL)
+ return EAS_ERROR_INVALID_HANDLE;
+
+ /* calculate the bytes to read */
+ count = file->fileSize - file->filePos;
+ if (n < count)
+ count = n;
+
+ /* copy the data to the requested location, and advance the pointer */
+ if (count)
+ EAS_HWMemCpy(pBuffer, &file->buffer[file->filePos], count);
+ file->filePos += count;
+ *pBytesRead = count;
+
+ /* were n bytes read? */
+ if (count!= n)
+ return EAS_EOF;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ *
+ * EAS_HWGetByte
+ *
+ * Read a byte from a file
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, hwInstData) hwInstData available for customer use */
+EAS_RESULT EAS_HWGetByte (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p)
+{
+
+ /* make sure we have a valid handle */
+ if (file->buffer == NULL)
+ return EAS_ERROR_INVALID_HANDLE;
+
+ /* check for end of file */
+ if (file->filePos >= file->fileSize)
+ {
+ *((EAS_U8*) p) = 0;
+ return EAS_EOF;
+ }
+
+ /* get a character from the buffer */
+ *((EAS_U8*) p) = file->buffer[file->filePos++];
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ *
+ * EAS_HWGetWord
+ *
+ * Returns the current location in the file
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, hwInstData) hwInstData available for customer use */
+EAS_RESULT EAS_HWGetWord (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p, EAS_BOOL msbFirst)
+{
+ EAS_RESULT result;
+ EAS_U8 c1, c2;
+
+ /* read 2 bytes from the file */
+ if ((result = EAS_HWGetByte(hwInstData, file, &c1)) != EAS_SUCCESS)
+ return result;
+ if ((result = EAS_HWGetByte(hwInstData, file, &c2)) != EAS_SUCCESS)
+ return result;
+
+ /* order them as requested */
+ if (msbFirst)
+ *((EAS_U16*) p) = ((EAS_U16) c1 << 8) | c2;
+ else
+ *((EAS_U16*) p) = ((EAS_U16) c2 << 8) | c1;
+
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ *
+ * EAS_HWGetDWord
+ *
+ * Returns the current location in the file
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, hwInstData) hwInstData available for customer use */
+EAS_RESULT EAS_HWGetDWord (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p, EAS_BOOL msbFirst)
+{
+ EAS_RESULT result;
+ EAS_U8 c1, c2,c3,c4;
+
+ /* read 4 bytes from the file */
+ if ((result = EAS_HWGetByte(hwInstData, file, &c1)) != EAS_SUCCESS)
+ return result;
+ if ((result = EAS_HWGetByte(hwInstData, file, &c2)) != EAS_SUCCESS)
+ return result;
+ if ((result = EAS_HWGetByte(hwInstData, file, &c3)) != EAS_SUCCESS)
+ return result;
+ if ((result = EAS_HWGetByte(hwInstData, file, &c4)) != EAS_SUCCESS)
+ return result;
+
+ /* order them as requested */
+ if (msbFirst)
+ *((EAS_U32*) p) = ((EAS_U32) c1 << 24) | ((EAS_U32) c2 << 16) | ((EAS_U32) c3 << 8) | c4;
+ else
+ *((EAS_U32*) p)= ((EAS_U32) c4 << 24) | ((EAS_U32) c3 << 16) | ((EAS_U32) c2 << 8) | c1;
+
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ *
+ * EAS_HWFilePos
+ *
+ * Returns the current location in the file
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, hwInstData) hwInstData available for customer use */
+EAS_RESULT EAS_HWFilePos (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 *pPosition)
+{
+
+ /* make sure we have a valid handle */
+ if (file->buffer == NULL)
+ return EAS_ERROR_INVALID_HANDLE;
+
+ *pPosition = file->filePos;
+ return EAS_SUCCESS;
+} /* end EAS_HWFilePos */
+
+/*----------------------------------------------------------------------------
+ *
+ * EAS_HWFileSeek
+ *
+ * Seek to a specific location in the file
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, hwInstData) hwInstData available for customer use */
+EAS_RESULT EAS_HWFileSeek (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 position)
+{
+
+ /* make sure we have a valid handle */
+ if (file->buffer == NULL)
+ return EAS_ERROR_INVALID_HANDLE;
+
+ /* validate new position */
+ if ((position < 0) || (position > file->fileSize))
+ return EAS_ERROR_FILE_SEEK;
+
+ /* save new position */
+ file->filePos = position;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ *
+ * EAS_HWFileSeekOfs
+ *
+ * Seek forward or back relative to the current position
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, hwInstData) hwInstData available for customer use */
+EAS_RESULT EAS_HWFileSeekOfs (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 position)
+{
+
+ /* make sure we have a valid handle */
+ if (file->buffer == NULL)
+ return EAS_ERROR_INVALID_HANDLE;
+
+ /* determine the file position */
+ position += file->filePos;
+ if ((position < 0) || (position > file->fileSize))
+ return EAS_ERROR_FILE_SEEK;
+
+ /* save new position */
+ file->filePos = position;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ *
+ * EAS_HWFileLength
+ *
+ * Return the file length
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, hwInstData) hwInstData available for customer use */
+EAS_RESULT EAS_HWFileLength (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 *pLength)
+{
+
+ /* make sure we have a valid handle */
+ if (file->buffer == NULL)
+ return EAS_ERROR_INVALID_HANDLE;
+
+ *pLength = file->fileSize;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ *
+ * EAS_HWDupHandle
+ *
+ * Duplicate a file handle
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_HWDupHandle (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_FILE_HANDLE *pDupFile)
+{
+ EAS_HW_FILE *dupFile;
+ int i;
+
+ /* make sure we have a valid handle */
+ if (file->buffer == NULL)
+ return EAS_ERROR_INVALID_HANDLE;
+
+ /* find an empty entry in the file table */
+ dupFile = hwInstData->files;
+ for (i = 0; i < EAS_MAX_FILE_HANDLES; i++)
+ {
+ /* is this slot being used? */
+ if (dupFile->buffer == NULL)
+ {
+
+ /* copy info from the handle to be duplicated */
+ dupFile->filePos = file->filePos;
+ dupFile->fileSize = file->fileSize;
+ dupFile->buffer = file->buffer;
+
+ /* set the duplicate handle flag */
+ dupFile->dup = file->dup = EAS_TRUE;
+
+ *pDupFile = dupFile;
+ return EAS_SUCCESS;
+ }
+ dupFile++;
+ }
+
+ /* too many open files */
+ return EAS_ERROR_MAX_FILES_OPEN;
+}
+
+/*----------------------------------------------------------------------------
+ *
+ * EAS_HWClose
+ *
+ * Wrapper for fclose function
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_HWCloseFile (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file1)
+{
+ EAS_HW_FILE *file2,*dupFile;
+ int i;
+
+
+ /* make sure we have a valid handle */
+ if (file1->buffer == NULL)
+ return EAS_ERROR_INVALID_HANDLE;
+
+ /* check for duplicate handle */
+ if (file1->dup)
+ {
+ dupFile = NULL;
+ file2 = hwInstData->files;
+ for (i = 0; i < EAS_MAX_FILE_HANDLES; i++)
+ {
+ /* check for duplicate */
+ if ((file1 != file2) && (file2->buffer == file1->buffer))
+ {
+ /* is there more than one duplicate? */
+ if (dupFile != NULL)
+ {
+ /* clear this entry and return */
+ file1->buffer = NULL;
+ return EAS_SUCCESS;
+ }
+
+ /* this is the first duplicate found */
+ else
+ dupFile = file2;
+ }
+ file2++;
+ }
+
+ /* there is only one duplicate, clear the dup flag */
+ if (dupFile)
+ dupFile->dup = EAS_FALSE;
+ else
+ /* if we get here, there's a serious problem */
+ return EAS_ERROR_HANDLE_INTEGRITY;
+
+ /* clear this entry and return */
+ file1->buffer = NULL;
+ return EAS_SUCCESS;
+ }
+
+ /* no duplicates -free the buffer */
+ EAS_HWFree(hwInstData, file1->buffer);
+
+ /* clear this entry and return */
+ file1->buffer = NULL;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ *
+ * EAS_HWVibrate
+ *
+ * Turn on/off vibrate function
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, hwInstData) hwInstData available for customer use */
+EAS_RESULT EAS_HWVibrate (EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state)
+{
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x1a54b6e8, 0x00000001 , state);
+ return EAS_SUCCESS;
+} /* end EAS_HWVibrate */
+
+/*----------------------------------------------------------------------------
+ *
+ * EAS_HWLED
+ *
+ * Turn on/off LED
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, hwInstData) hwInstData available for customer use */
+EAS_RESULT EAS_HWLED (EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state)
+{
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x1a54b6e8, 0x00000002 , state);
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ *
+ * EAS_HWBackLight
+ *
+ * Turn on/off backlight
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, hwInstData) hwInstData available for customer use */
+EAS_RESULT EAS_HWBackLight (EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state)
+{
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x1a54b6e8, 0x00000003 , state);
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ *
+ * EAS_HWYield
+ *
+ * This function is called periodically by the EAS library to give the
+ * host an opportunity to allow other tasks to run. There are two ways to
+ * use this call:
+ *
+ * If you have a multi-tasking OS, you can call the yield function in the
+ * OS to allow other tasks to run. In this case, return EAS_FALSE to tell
+ * the EAS library to continue processing when control returns from this
+ * function.
+ *
+ * If tasks run in a single thread by sequential function calls (sometimes
+ * call a "commutator loop"), return EAS_TRUE to cause the EAS Library to
+ * return to the caller. Be sure to check the number of bytes rendered
+ * before passing the audio buffer to the codec - it may not be filled.
+ * The next call to EAS_Render will continue processing until the buffer
+ * has been filled.
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, hwInstData) hwInstData available for customer use */
+EAS_BOOL EAS_HWYield (EAS_HW_DATA_HANDLE hwInstData)
+{
+ /* put your code here */
+ return EAS_FALSE;
+}
+
diff --git a/arm-fm-22k/host_src/eas_main.c b/arm-fm-22k/host_src/eas_main.c
new file mode 100644
index 0000000..809a132
--- /dev/null
+++ b/arm-fm-22k/host_src/eas_main.c
@@ -0,0 +1,461 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_main.c
+ *
+ * Contents and purpose:
+ * The entry point and high-level functions for the EAS Synthesizer test
+ * harness.
+ *
+ * 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: 775 $
+ * $Date: 2007-07-20 10:11:11 -0700 (Fri, 20 Jul 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+#ifdef _lint
+#include "lint_stdlib.h"
+#else
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+#endif
+
+#include "eas.h"
+#include "eas_wave.h"
+#include "eas_report.h"
+
+/* determines how many EAS buffers to fill a host buffer */
+#define NUM_BUFFERS 8
+
+/* default file to play if no filename is specified on the command line */
+static const char defaultTestFile[] = "test.mid";
+
+EAS_I32 polyphony;
+
+/* prototypes for helper functions */
+static void StrCopy(char *dest, const char *src, EAS_I32 size);
+static EAS_BOOL ChangeFileExt(char *str, const char *ext, EAS_I32 size);
+static EAS_RESULT PlayFile (EAS_DATA_HANDLE easData, const char* filename, const char* outputFile, const S_EAS_LIB_CONFIG *pLibConfig, void *buffer, EAS_I32 bufferSize);
+static EAS_BOOL EASLibraryCheck (const S_EAS_LIB_CONFIG *pLibConfig);
+
+/* main is defined after playfile to avoid the need for two passes through lint */
+
+/*----------------------------------------------------------------------------
+ * PlayFile()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * This function plays the file requested by filename
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ *----------------------------------------------------------------------------
+*/
+
+static EAS_RESULT PlayFile (EAS_DATA_HANDLE easData, const char* filename, const char* outputFile, const S_EAS_LIB_CONFIG *pLibConfig, void *buffer, EAS_I32 bufferSize)
+{
+ EAS_HANDLE handle;
+ EAS_RESULT result, reportResult;
+ EAS_I32 count;
+ EAS_STATE state;
+ EAS_I32 playTime;
+ char waveFilename[256];
+ WAVE_FILE *wFile;
+ EAS_INT i;
+ EAS_PCM *p;
+
+ /* determine the name of the output file */
+ wFile = NULL;
+ if (outputFile == NULL)
+ {
+ StrCopy(waveFilename, filename, sizeof(waveFilename));
+ if (!ChangeFileExt(waveFilename, "wav", sizeof(waveFilename)))
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error in output filename %s\n", waveFilename); */ }
+ return EAS_FAILURE;
+ }
+ outputFile = waveFilename;
+ }
+
+ /* call EAS library to open file */
+ if ((reportResult = EAS_OpenFile(easData, filename, &handle)) != EAS_SUCCESS)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_OpenFile returned %ld\n", reportResult); */ }
+ return reportResult;
+ }
+
+ /* prepare to play the file */
+ if ((result = EAS_Prepare(easData, handle)) != EAS_SUCCESS)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_Prepare returned %ld\n", result); */ }
+ reportResult = result;
+ }
+
+ /* get play length */
+ if ((result = EAS_ParseMetaData(easData, handle, &playTime)) != EAS_SUCCESS)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_ParseMetaData returned %ld\n", result); */ }
+ return result;
+ }
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0xe624f4d9, 0x00000005 , playTime / 1000, playTime % 1000);
+
+ if (reportResult == EAS_SUCCESS)
+ {
+ /* create the output file */
+ wFile = WaveFileCreate(outputFile, pLibConfig->numChannels, pLibConfig->sampleRate, sizeof(EAS_PCM) * 8);
+ if (!wFile)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unable to create output file %s\n", waveFilename); */ }
+ reportResult = EAS_FAILURE;
+ }
+ }
+
+ /* rendering loop */
+ while (reportResult == EAS_SUCCESS)
+ {
+
+ /* we may render several buffers here to fill one host buffer */
+ for (i = 0, p = buffer; i < NUM_BUFFERS; i++, p+= pLibConfig->mixBufferSize * pLibConfig->numChannels)
+ {
+
+ /* get the current time */
+ if ((result = EAS_GetLocation(easData, handle, &playTime)) != EAS_SUCCESS)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_GetLocation returned %d\n",result); */ }
+ if (reportResult == EAS_SUCCESS)
+ reportResult = result;
+ break;
+ }
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Parser time: %d.%03d\n", playTime / 1000, playTime % 1000); */ }
+
+ /* render a buffer of audio */
+ if ((result = EAS_Render(easData, p, pLibConfig->mixBufferSize, &count)) != EAS_SUCCESS)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_Render returned %d\n",result); */ }
+ if (reportResult == EAS_SUCCESS)
+ reportResult = result;
+ }
+ }
+
+ if (result == EAS_SUCCESS)
+ {
+ /* write it to the wave file */
+ if (WaveFileWrite(wFile, buffer, bufferSize) != bufferSize)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "WaveFileWrite failed\n"); */ }
+ reportResult = EAS_FAILURE;
+ }
+ }
+
+ if (reportResult == EAS_SUCCESS)
+ {
+ /* check stream state */
+ if ((result = EAS_State(easData, handle, &state)) != EAS_SUCCESS)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_State returned %d\n", result); */ }
+ reportResult = result;
+ }
+
+ /* is playback complete */
+ if ((state == EAS_STATE_STOPPED) || (state == EAS_STATE_ERROR))
+ break;
+ }
+ }
+
+ /* close the output file */
+ if (wFile)
+ {
+ if (!WaveFileClose(wFile))
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error closing wave file %s\n", waveFilename); */ }
+ if (reportResult == EAS_SUCCESS)
+ result = EAS_FAILURE;
+ }
+ }
+
+ /* close the input file */
+ if ((result = EAS_CloseFile(easData,handle)) != EAS_SUCCESS)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_Close returned %ld\n", result); */ }
+ if (reportResult == EAS_SUCCESS)
+ result = EAS_FAILURE;
+ }
+
+ return reportResult;
+} /* end PlayFile */
+
+/*----------------------------------------------------------------------------
+ * main()
+ *----------------------------------------------------------------------------
+ * Purpose: The entry point for the EAS sample application
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ *----------------------------------------------------------------------------
+*/
+int main( int argc, char **argv )
+{
+ EAS_DATA_HANDLE easData;
+ const S_EAS_LIB_CONFIG *pLibConfig;
+ void *buffer;
+ EAS_RESULT result, playResult;
+ EAS_I32 bufferSize;
+ int i;
+ int temp;
+ FILE *debugFile;
+ char *outputFile = NULL;
+
+ /* set the error reporting level */
+ EAS_SetDebugLevel(_EAS_SEVERITY_INFO);
+ debugFile = NULL;
+
+ /* process command-line arguments */
+ for (i = 1; i < argc; i++)
+ {
+ /* check for switch */
+ if (argv[i][0] == '-')
+ {
+ switch (argv[i][1])
+ {
+ case 'd':
+ temp = argv[i][2];
+ if ((temp >= '0') || (temp <= '9'))
+ EAS_SetDebugLevel(temp);
+ else
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Invalid debug level %d\n", temp); */ }
+ break;
+ case 'f':
+ if ((debugFile = fopen(&argv[i][2],"w")) == NULL)
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Unable to create debug file %s\n", &argv[i][2]); */ }
+ else
+ EAS_SetDebugFile(debugFile, EAS_TRUE);
+ break;
+ case 'o':
+ outputFile = &argv[i][2];
+ break;
+ case 'p':
+ polyphony = atoi(&argv[i][2]);
+ if (polyphony < 1)
+ polyphony = 1;
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "Polyphony set to %d\n", polyphony); */ }
+ break;
+ default:
+ break;
+ }
+ continue;
+ }
+ }
+
+ /* assume success */
+ playResult = EAS_SUCCESS;
+
+ /* get the library configuration */
+ pLibConfig = EAS_Config();
+ if (!EASLibraryCheck(pLibConfig))
+ return -1;
+ if (polyphony > pLibConfig->maxVoices)
+ polyphony = pLibConfig->maxVoices;
+
+ /* calculate buffer size */
+ bufferSize = pLibConfig->mixBufferSize * pLibConfig->numChannels * (EAS_I32)sizeof(EAS_PCM) * NUM_BUFFERS;
+
+ /* allocate output buffer memory */
+ buffer = malloc((EAS_U32)bufferSize);
+ if (!buffer)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Error allocating memory for audio buffer\n"); */ }
+ return EAS_FAILURE;
+ }
+
+ /* initialize the EAS library */
+ polyphony = pLibConfig->maxVoices;
+ if ((result = EAS_Init(&easData)) != EAS_SUCCESS)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "EAS_Init returned %ld - aborting!\n", result); */ }
+ free(buffer);
+ return result;
+ }
+
+ /*
+ * Some debugging environments don't allow for passed parameters.
+ * In this case, just play the default MIDI file "test.mid"
+ */
+ if (argc < 2)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "Playing '%s'\n", defaultTestFile); */ }
+ if ((playResult = PlayFile(easData, defaultTestFile, NULL, pLibConfig, buffer, bufferSize)) != EAS_SUCCESS)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %d playing file %s\n", playResult, defaultTestFile); */ }
+ }
+ }
+ /* iterate through the list of files to be played */
+ else
+ {
+ for (i = 1; i < argc; i++)
+ {
+ /* check for switch */
+ if (argv[i][0] != '-')
+ {
+
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "Playing '%s'\n", argv[i]); */ }
+ if ((playResult = PlayFile(easData, argv[i], outputFile, pLibConfig, buffer, bufferSize)) != EAS_SUCCESS)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %d playing file %s\n", playResult, argv[i]); */ }
+ break;
+ }
+ }
+ }
+ }
+
+ /* shutdown the EAS library */
+ if ((result = EAS_Shutdown(easData)) != EAS_SUCCESS)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "EAS_Shutdown returned %ld\n", result); */ }
+ }
+
+ /* free the output buffer */
+ free(buffer);
+
+ /* close the debug file */
+ if (debugFile)
+ fclose(debugFile);
+
+ /* play errors take precedence over shutdown errors */
+ if (playResult != EAS_SUCCESS)
+ return playResult;
+ return result;
+} /* end main */
+
+/*----------------------------------------------------------------------------
+ * StrCopy()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Safe string copy
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ *----------------------------------------------------------------------------
+*/
+static void StrCopy(char *dest, const char *src, EAS_I32 size)
+{
+ int len;
+
+ strncpy(dest, src, (size_t) size-1);
+ len = (int) strlen(src);
+ if (len < size)
+ dest[len] = 0;
+} /* end StrCopy */
+
+/*----------------------------------------------------------------------------
+ * ChangeFileExt()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Changes the file extension of a filename
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_BOOL ChangeFileExt(char *str, const char *ext, EAS_I32 size)
+{
+ char *p;
+
+ /* find the extension, if any */
+ p = strrchr(str,'.');
+ if (!p)
+ {
+ if ((EAS_I32)(strlen(str) + 5) > size)
+ return EAS_FALSE;
+ strcat(str,".");
+ strcat(str,ext);
+ return EAS_TRUE;
+ }
+
+ /* make sure there's room for the extension */
+ p++;
+ *p = 0;
+ if ((EAS_I32)(strlen(str) + 4) > size)
+ return EAS_FALSE;
+ strcat(str,ext);
+ return EAS_TRUE;
+} /* end ChangeFileExt */
+
+/*----------------------------------------------------------------------------
+ * EASLibraryCheck()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Displays the library version and checks it against the header
+ * file used to build this code.
+ *
+ * Inputs:
+ * pLibConfig - library configuration retrieved from the library
+ *
+ * Outputs:
+ * returns EAS_TRUE if matched
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_BOOL EASLibraryCheck (const S_EAS_LIB_CONFIG *pLibConfig)
+{
+
+ /* display the library version */
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "EAS Library Version %d.%d.%d.%d\n",
+ pLibConfig->libVersion >> 24,
+ (pLibConfig->libVersion >> 16) & 0x0f,
+ (pLibConfig->libVersion >> 8) & 0x0f,
+ pLibConfig->libVersion & 0x0f); */ }
+
+ /* display some info about the library build */
+ if (pLibConfig->checkedVersion)
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tChecked library\n"); */ }
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tMaximum polyphony: %d\n", pLibConfig->maxVoices); */ }
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tNumber of channels: %d\n", pLibConfig->numChannels); */ }
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tSample rate: %d\n", pLibConfig->sampleRate); */ }
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tMix buffer size: %d\n", pLibConfig->mixBufferSize); */ }
+ if (pLibConfig->filterEnabled)
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tFilter enabled\n"); */ }
+#ifndef _WIN32_WCE
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tLibrary Build Timestamp: %s", ctime((time_t*)&pLibConfig->buildTimeStamp)); */ }
+#endif
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tLibrary Build ID: %s\n", pLibConfig->buildGUID); */ }
+
+ /* check it against the header file used to build this code */
+ /*lint -e{778} constant expression used for display purposes may evaluate to zero */
+ if (LIB_VERSION != pLibConfig->libVersion)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Library version does not match header files. EAS Header Version %d.%d.%d.%d\n",
+ LIB_VERSION >> 24,
+ (LIB_VERSION >> 16) & 0x0f,
+ (LIB_VERSION >> 8) & 0x0f,
+ LIB_VERSION & 0x0f); */ }
+ return EAS_FALSE;
+ }
+ return EAS_TRUE;
+} /* end EASLibraryCheck */
+
diff --git a/arm-fm-22k/host_src/eas_report.c b/arm-fm-22k/host_src/eas_report.c
new file mode 100644
index 0000000..d4dd22c
--- /dev/null
+++ b/arm-fm-22k/host_src/eas_report.c
@@ -0,0 +1,264 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_report.c
+ *
+ * Contents and purpose:
+ * This file contains the debug message handling routines for the EAS library.
+ * These routines should be modified as needed for your system.
+ *
+ * Copyright 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: 659 $
+ * $Date: 2007-04-24 13:36:35 -0700 (Tue, 24 Apr 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+#ifdef _lint
+#include "lint_stdlib.h"
+#else
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#endif
+
+#include "eas_report.h"
+
+static int severityLevel = 9999;
+
+/* debug file */
+static FILE *debugFile = NULL;
+int flush = 0;
+
+#ifndef _NO_DEBUG_PREPROCESSOR
+
+/* structure should have an #include for each error message header file */
+S_DEBUG_MESSAGES debugMessages[] =
+{
+#ifndef UNIFIED_DEBUG_MESSAGES
+#include "eas_config_msgs.h"
+
+
+#include "eas_host_msgs.h"
+#include "eas_hostmm_msgs.h"
+#include "eas_math_msgs.h"
+#include "eas_midi_msgs.h"
+#include "eas_mixer_msgs.h"
+#include "eas_pcm_msgs.h"
+#include "eas_public_msgs.h"
+#include "eas_smf_msgs.h"
+#include "eas_wave_msgs.h"
+#include "eas_voicemgt_msgs.h"
+
+#ifdef _FM_SYNTH
+#include "eas_fmsynth_msgs.h"
+#include "eas_fmengine_msgs.h"
+#endif
+
+#ifdef _WT_SYNTH
+#include "eas_wtsynth_msgs.h"
+#include "eas_wtengine_msgs.h"
+#endif
+
+#ifdef _ARM_TEST_MAIN
+#include "arm_main_msgs.h"
+#endif
+
+#ifdef _EAS_MAIN
+#include "eas_main_msgs.h"
+#endif
+
+#ifdef _EAS_MAIN_IPC
+#include "eas_main_ipc_msgs.h"
+#endif
+
+#ifdef _METRICS_ENABLED
+#include "eas_perf_msgs.h"
+#endif
+
+#ifdef _COMPRESSOR_ENABLED
+#include "eas_compressor_msgs.h"
+#endif
+
+#ifdef _ENHANCER_ENABLED
+#include "eas_enhancer_msgs.h"
+#endif
+
+#ifdef _WOW_ENABLED
+#include "eas_wow_msgs.h"
+#endif
+
+#ifdef _SMAF_PARSER
+#include "eas_smaf_msgs.h"
+#endif
+
+#ifdef _OTA_PARSER
+#include "eas_ota_msgs.h"
+#endif
+
+#ifdef _IMELODY_PARSER
+#include "eas_imelody_msgs.h"
+#endif
+
+#ifdef _WAVE_PARSER
+#include "eas_wavefile_msgs.h"
+#endif
+
+#if defined(_CMX_PARSER) || defined(_MFI_PARSER)
+#include "eas_cmf_msgs.h"
+#endif
+
+#if defined(_CMX_PARSER) || defined(_MFI_PARSER) || defined(_WAVE_PARSER)
+#include "eas_imaadpcm_msgs.h"
+#endif
+
+#else
+#include "eas_debugmsgs.h"
+#endif
+
+/* denotes end of error messages */
+{ 0,0,0 }
+};
+
+/*----------------------------------------------------------------------------
+ * EAS_ReportEx()
+ *
+ * This is the error message handler. The default handler outputs error
+ * messages to stdout. Modify this as needed for your system.
+ *----------------------------------------------------------------------------
+*/
+void EAS_ReportEx (int severity, unsigned long hashCode, int serialNum, ...)
+{
+ va_list vargs;
+ int i;
+
+ /* check severity level */
+ if (severity > severityLevel)
+ return;
+
+ /* find the error message and output to stdout */
+ /*lint -e{661} we check for NULL pointer - no fence post error here */
+ for (i = 0; debugMessages[i].m_pDebugMsg; i++)
+ {
+ if ((debugMessages[i].m_nHashCode == hashCode) &&
+ (debugMessages[i].m_nSerialNum == serialNum))
+ {
+ /*lint -e{826} <allow variable args> */
+ va_start(vargs, serialNum);
+ if (debugFile)
+ {
+ vfprintf(debugFile, debugMessages[i].m_pDebugMsg, vargs);
+ if (flush)
+ fflush(debugFile);
+ }
+ else
+ {
+ vprintf(debugMessages[i].m_pDebugMsg, vargs);
+ }
+ va_end(vargs);
+ return;
+ }
+ }
+ printf("Unrecognized error: Severity=%d; HashCode=%lu; SerialNum=%d\n", severity, hashCode, serialNum);
+} /* end EAS_ReportEx */
+
+#else
+/*----------------------------------------------------------------------------
+ * EAS_Report()
+ *
+ * This is the error message handler. The default handler outputs error
+ * messages to stdout. Modify this as needed for your system.
+ *----------------------------------------------------------------------------
+*/
+void EAS_Report (int severity, const char *fmt, ...)
+{
+ va_list vargs;
+
+ /* check severity level */
+ if (severity > severityLevel)
+ return;
+
+ /*lint -e{826} <allow variable args> */
+ va_start(vargs, fmt);
+ if (debugFile)
+ {
+ vfprintf(debugFile, fmt, vargs);
+ if (flush)
+ fflush(debugFile);
+ }
+ else
+ {
+ vprintf(fmt, vargs);
+ }
+ va_end(vargs);
+} /* end EAS_Report */
+
+/*----------------------------------------------------------------------------
+ * EAS_ReportX()
+ *
+ * This is the error message handler. The default handler outputs error
+ * messages to stdout. Modify this as needed for your system.
+ *----------------------------------------------------------------------------
+*/
+void EAS_ReportX (int severity, const char *fmt, ...)
+{
+ va_list vargs;
+
+ /* check severity level */
+ if (severity > severityLevel)
+ return;
+
+ /*lint -e{826} <allow variable args> */
+ va_start(vargs, fmt);
+ if (debugFile)
+ {
+ vfprintf(debugFile, fmt, vargs);
+ if (flush)
+ fflush(debugFile);
+ }
+ else
+ {
+ vprintf(fmt, vargs);
+ }
+ va_end(vargs);
+} /* end EAS_ReportX */
+#endif
+
+/*----------------------------------------------------------------------------
+ * EAS_SetDebugLevel()
+ *
+ * Sets the level for debug message output
+ *----------------------------------------------------------------------------
+*/
+
+void EAS_SetDebugLevel (int severity)
+{
+ severityLevel = severity;
+} /* end EAS_SetDebugLevel */
+
+/*----------------------------------------------------------------------------
+ * EAS_SetDebugFile()
+ *
+ * Redirect debugger output to the specified file.
+ *----------------------------------------------------------------------------
+*/
+void EAS_SetDebugFile (void *file, int flushAfterWrite)
+{
+ debugFile = (FILE*) file;
+ flush = flushAfterWrite;
+} /* end EAS_SetDebugFile */
+
diff --git a/arm-fm-22k/host_src/eas_report.h b/arm-fm-22k/host_src/eas_report.h
new file mode 100644
index 0000000..9d7c8e8
--- /dev/null
+++ b/arm-fm-22k/host_src/eas_report.h
@@ -0,0 +1,77 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_report.h
+ *
+ * Contents and purpose:
+ * This file contains the debug message handling routines for the EAS library.
+ * These routines should be modified as needed for your system.
+ *
+ * DO NOT MODIFY THIS FILE!
+ *
+ * Copyright 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: 82 $
+ * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $
+ *----------------------------------------------------------------------------
+*/
+
+/* sentinel */
+#ifndef _EAS_REPORT_H
+#define _EAS_REPORT_H
+
+#define _EAS_SEVERITY_NOFILTER 0
+#define _EAS_SEVERITY_FATAL 1
+#define _EAS_SEVERITY_ERROR 2
+#define _EAS_SEVERITY_WARNING 3
+#define _EAS_SEVERITY_INFO 4
+#define _EAS_SEVERITY_DETAIL 5
+
+/* for C++ linkage */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _NO_DEBUG_PREPROCESSOR
+
+/* structure for included debug message header files */
+typedef struct
+{
+ unsigned long m_nHashCode;
+ int m_nSerialNum;
+ char *m_pDebugMsg;
+} S_DEBUG_MESSAGES;
+
+/* debug message handling prototypes */
+extern void EAS_ReportEx (int severity, unsigned long hashCode, int serialNum, ...);
+
+#else
+
+/* these prototypes are used if the debug preprocessor is not used */
+extern void EAS_Report (int severity, const char* fmt, ...);
+extern void EAS_ReportX (int severity, const char* fmt, ...);
+
+#endif
+
+extern void EAS_SetDebugLevel (int severity);
+extern void EAS_SetDebugFile (void *file, int flushAfterWrite);
+
+#ifdef __cplusplus
+} /* end extern "C" */
+#endif
+
+#endif
diff --git a/arm-fm-22k/host_src/eas_reverb.h b/arm-fm-22k/host_src/eas_reverb.h
new file mode 100644
index 0000000..a2535fb
--- /dev/null
+++ b/arm-fm-22k/host_src/eas_reverb.h
@@ -0,0 +1,54 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_reverb.h
+ *
+ * Contents and purpose:
+ * Contains parameter enumerations 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: 300 $
+ * $Date: 2006-09-11 17:37:20 -0700 (Mon, 11 Sep 2006) $
+ *----------------------------------------------------------------------------
+*/
+
+#ifndef _EAS_REVERB_H
+#define _EAS_REVERB_H
+
+
+/* enumerated parameter settings for Reverb effect */
+typedef enum
+{
+ EAS_PARAM_REVERB_BYPASS,
+ EAS_PARAM_REVERB_PRESET,
+ EAS_PARAM_REVERB_WET,
+ EAS_PARAM_REVERB_DRY
+} E_REVERB_PARAMS;
+
+
+typedef enum
+{
+ EAS_PARAM_REVERB_LARGE_HALL,
+ EAS_PARAM_REVERB_HALL,
+ EAS_PARAM_REVERB_CHAMBER,
+ EAS_PARAM_REVERB_ROOM,
+} E_REVERB_PRESETS;
+
+
+#endif /* _REVERB_H */
diff --git a/arm-fm-22k/host_src/eas_types.h b/arm-fm-22k/host_src/eas_types.h
new file mode 100644
index 0000000..f0293ef
--- /dev/null
+++ b/arm-fm-22k/host_src/eas_types.h
@@ -0,0 +1,268 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_types.h
+ *
+ * Contents and purpose:
+ * The public interface header for the EAS synthesizer.
+ *
+ * This header only contains declarations that are specific
+ * to this implementation.
+ *
+ * DO NOT MODIFY THIS FILE!
+ *
+ * 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: 726 $
+ * $Date: 2007-06-14 23:10:46 -0700 (Thu, 14 Jun 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+#ifndef _EAS_TYPES_H
+#define _EAS_TYPES_H
+
+/* EAS_RESULT return codes */
+typedef long EAS_RESULT;
+#define EAS_SUCCESS 0
+#define EAS_FAILURE -1
+#define EAS_ERROR_INVALID_MODULE -2
+#define EAS_ERROR_MALLOC_FAILED -3
+#define EAS_ERROR_FILE_POS -4
+#define EAS_ERROR_INVALID_FILE_MODE -5
+#define EAS_ERROR_FILE_SEEK -6
+#define EAS_ERROR_FILE_LENGTH -7
+#define EAS_ERROR_NOT_IMPLEMENTED -8
+#define EAS_ERROR_CLOSE_FAILED -9
+#define EAS_ERROR_FILE_OPEN_FAILED -10
+#define EAS_ERROR_INVALID_HANDLE -11
+#define EAS_ERROR_NO_MIX_BUFFER -12
+#define EAS_ERROR_PARAMETER_RANGE -13
+#define EAS_ERROR_MAX_FILES_OPEN -14
+#define EAS_ERROR_UNRECOGNIZED_FORMAT -15
+#define EAS_BUFFER_SIZE_MISMATCH -16
+#define EAS_ERROR_FILE_FORMAT -17
+#define EAS_ERROR_SMF_NOT_INITIALIZED -18
+#define EAS_ERROR_LOCATE_BEYOND_END -19
+#define EAS_ERROR_INVALID_PCM_TYPE -20
+#define EAS_ERROR_MAX_PCM_STREAMS -21
+#define EAS_ERROR_NO_VOICE_ALLOCATED -22
+#define EAS_ERROR_INVALID_CHANNEL -23
+#define EAS_ERROR_ALREADY_STOPPED -24
+#define EAS_ERROR_FILE_READ_FAILED -25
+#define EAS_ERROR_HANDLE_INTEGRITY -26
+#define EAS_ERROR_MAX_STREAMS_OPEN -27
+#define EAS_ERROR_INVALID_PARAMETER -28
+#define EAS_ERROR_FEATURE_NOT_AVAILABLE -29
+#define EAS_ERROR_SOUND_LIBRARY -30
+#define EAS_ERROR_NOT_VALID_IN_THIS_STATE -31
+#define EAS_ERROR_NO_VIRTUAL_SYNTHESIZER -32
+#define EAS_ERROR_FILE_ALREADY_OPEN -33
+#define EAS_ERROR_FILE_ALREADY_CLOSED -34
+#define EAS_ERROR_INCOMPATIBLE_VERSION -35
+#define EAS_ERROR_QUEUE_IS_FULL -36
+#define EAS_ERROR_QUEUE_IS_EMPTY -37
+#define EAS_ERROR_FEATURE_ALREADY_ACTIVE -38
+
+/* special return codes */
+#define EAS_EOF 3
+#define EAS_STREAM_BUFFERING 4
+#define EAS_BUFFER_FULL 5
+
+/* EAS_STATE return codes */
+typedef long EAS_STATE;
+typedef enum
+{
+ EAS_STATE_READY = 0,
+ EAS_STATE_PLAY,
+ EAS_STATE_STOPPING,
+ EAS_STATE_PAUSING,
+ EAS_STATE_STOPPED,
+ EAS_STATE_PAUSED,
+ EAS_STATE_OPEN,
+ EAS_STATE_ERROR,
+ EAS_STATE_EMPTY
+} E_EAS_STATE;
+
+/* constants */
+#ifndef EAS_CONST
+#define EAS_CONST const
+#endif
+
+/* definition for public interface functions */
+#ifndef EAS_PUBLIC
+#define EAS_PUBLIC
+#endif
+
+/* boolean values */
+typedef unsigned EAS_BOOL;
+typedef unsigned char EAS_BOOL8;
+
+#define EAS_FALSE 0
+#define EAS_TRUE 1
+
+/* scalar variable definitions */
+typedef unsigned char EAS_U8;
+typedef signed char EAS_I8;
+typedef char EAS_CHAR;
+
+typedef unsigned short EAS_U16;
+typedef short EAS_I16;
+
+typedef unsigned long EAS_U32;
+typedef long EAS_I32;
+
+typedef unsigned EAS_UINT;
+typedef int EAS_INT;
+typedef long EAS_LONG;
+
+/* audio output type */
+typedef short EAS_PCM;
+
+/* file open modes */
+typedef EAS_I32 EAS_FILE_MODE;
+#define EAS_FILE_READ 1
+#define EAS_FILE_WRITE 2
+
+/* file locator e.g. filename or memory pointer */
+typedef const void *EAS_FILE_LOCATOR;
+
+/* handle to stream */
+typedef struct s_eas_stream_tag *EAS_HANDLE;
+
+/* handle to file */
+typedef struct eas_hw_file_tag *EAS_FILE_HANDLE;
+
+/* handle for synthesizer data */
+typedef struct s_eas_data_tag *EAS_DATA_HANDLE;
+
+/* handle to persistent data for host wrapper interface */
+typedef struct eas_hw_inst_data_tag *EAS_HW_DATA_HANDLE;
+
+/* handle to sound library */
+typedef struct s_eas_sndlib_tag *EAS_SNDLIB_HANDLE;
+typedef struct s_eas_dls_tag *EAS_DLSLIB_HANDLE;
+
+/* pointer to frame buffer - used in split architecture only */
+typedef struct s_eas_frame_buffer_tag *EAS_FRAME_BUFFER_HANDLE;
+
+/* untyped pointer for instance data */
+typedef void *EAS_VOID_PTR;
+
+/* inline functions */
+#ifndef EAS_INLINE
+#if defined (__XCC__)
+#define EAS_INLINE __inline__
+#elif defined (__GNUC__)
+#define EAS_INLINE inline static
+#else
+#define EAS_INLINE __inline
+#endif
+#endif
+
+/* define NULL value */
+#ifndef NULL
+#define NULL 0
+#endif
+
+/* metadata types for metadata return codes */
+typedef enum
+{
+ EAS_METADATA_UNKNOWN = 0,
+ EAS_METADATA_TITLE,
+ EAS_METADATA_AUTHOR,
+ EAS_METADATA_COPYRIGHT,
+ EAS_METADATA_LYRIC,
+ EAS_METADATA_TEXT
+} E_EAS_METADATA_TYPE;
+
+/* metadata callback function */
+typedef void (*EAS_METADATA_CBFUNC) (E_EAS_METADATA_TYPE metaDataType, char *metaDataBuf, EAS_VOID_PTR pUserData);
+
+/* file types for metadata return codes */
+typedef enum
+{
+ EAS_FILE_UNKNOWN = 0,
+ EAS_FILE_SMF0,
+ EAS_FILE_SMF1,
+ EAS_FILE_SMAF_UNKNOWN,
+ EAS_FILE_SMAF_MA2,
+ EAS_FILE_SMAF_MA3,
+ EAS_FILE_SMAF_MA5,
+ EAS_FILE_CMX,
+ EAS_FILE_MFI,
+ EAS_FILE_OTA,
+ EAS_FILE_IMELODY,
+ EAS_FILE_RTTTL,
+ EAS_FILE_XMF0,
+ EAS_FILE_XMF1,
+ EAS_FILE_WAVE_PCM,
+ EAS_FILE_WAVE_IMA_ADPCM,
+ EAS_FILE_MMAPI_TONE_CONTROL
+} E_EAS_FILE_TYPE;
+
+/* enumeration for synthesizers */
+typedef enum
+{
+ EAS_MCU_SYNTH = 0,
+ EAS_DSP_SYNTH
+} E_SYNTHESIZER;
+
+/* external audio callback program change */
+typedef struct s_ext_audio_prg_chg_tag
+{
+ EAS_U16 bank;
+ EAS_U8 program;
+ EAS_U8 channel;
+} S_EXT_AUDIO_PRG_CHG;
+
+/* external audio callback event */
+typedef struct s_ext_audio_event_tag
+{
+ EAS_U8 channel;
+ EAS_U8 note;
+ EAS_U8 velocity;
+ EAS_BOOL8 noteOn;
+} S_EXT_AUDIO_EVENT;
+
+typedef struct s_midi_controllers_tag
+{
+ EAS_U8 modWheel; /* CC1 */
+ EAS_U8 volume; /* CC7 */
+ EAS_U8 pan; /* CC10 */
+ EAS_U8 expression; /* CC11 */
+ EAS_U8 channelPressure; /* MIDI channel pressure */
+
+#ifdef _REVERB
+ EAS_U8 reverbSend; /* CC91 */
+#endif
+
+#ifdef _CHORUS
+ EAS_U8 chorusSend; /* CC93 */
+#endif
+} S_MIDI_CONTROLLERS;
+
+/* iMode play modes enumeration for EAS_SetPlayMode */
+typedef enum
+{
+ IMODE_PLAY_ALL = 0,
+ IMODE_PLAY_PARTIAL
+} E_I_MODE_PLAY_MODE;
+
+typedef EAS_BOOL (*EAS_EXT_PRG_CHG_FUNC) (EAS_VOID_PTR pInstData, S_EXT_AUDIO_PRG_CHG *pPrgChg);
+typedef EAS_BOOL (*EAS_EXT_EVENT_FUNC) (EAS_VOID_PTR pInstData, S_EXT_AUDIO_EVENT *pEvent);
+
+#endif /* #ifndef _EAS_TYPES_H */
diff --git a/arm-fm-22k/host_src/eas_wave.c b/arm-fm-22k/host_src/eas_wave.c
new file mode 100644
index 0000000..02fed6e
--- /dev/null
+++ b/arm-fm-22k/host_src/eas_wave.c
@@ -0,0 +1,423 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_wave.c
+ *
+ * Contents and purpose:
+ * This module contains .WAV file functions for the EAS synthesizer
+ * test harness.
+ *
+ * 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: 658 $
+ * $Date: 2007-04-24 13:35:49 -0700 (Tue, 24 Apr 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+/* lint complaints about most C library headers, so we use our own during lint step */
+#ifdef _lint
+#include "lint_stdlib.h"
+#else
+#include <stdio.h>
+#include <stdlib.h>
+#endif
+
+#include "eas_wave.h"
+
+/* .WAV file format tags */
+const EAS_U32 riffTag = 0x46464952;
+const EAS_U32 waveTag = 0x45564157;
+const EAS_U32 fmtTag = 0x20746d66;
+const EAS_U32 dataTag = 0x61746164;
+
+#ifdef _BIG_ENDIAN
+/*----------------------------------------------------------------------------
+ * FlipDWord()
+ *----------------------------------------------------------------------------
+ * Purpose: Endian flip a DWORD for big-endian processors
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ *----------------------------------------------------------------------------
+*/
+static void FlipDWord (EAS_U32 *pValue)
+{
+ EAS_U8 *p;
+ EAS_U32 temp;
+
+ p = (EAS_U8*) pValue;
+ temp = (((((p[3] << 8) | p[2]) << 8) | p[1]) << 8) | p[0];
+ *pValue = temp;
+}
+
+/*----------------------------------------------------------------------------
+ * FlipWord()
+ *----------------------------------------------------------------------------
+ * Purpose: Endian flip a WORD for big-endian processors
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ *----------------------------------------------------------------------------
+*/
+static void FlipWord (EAS_U16 *pValue)
+{
+ EAS_U8 *p;
+ EAS_U16 temp;
+
+ p = (EAS_U8*) pValue;
+ temp = (p[1] << 8) | p[0];
+ *pValue = temp;
+}
+
+/*----------------------------------------------------------------------------
+ * FlipWaveHeader()
+ *----------------------------------------------------------------------------
+ * Purpose: Endian flip the wave header for big-endian processors
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ *----------------------------------------------------------------------------
+*/
+static void FlipWaveHeader (WAVE_HEADER *p)
+{
+
+ FlipDWord(&p->nRiffTag);
+ FlipDWord(&p->nRiffSize);
+ FlipDWord(&p->nWaveTag);
+ FlipDWord(&p->nFmtTag);
+ FlipDWord(&p->nFmtSize);
+ FlipDWord(&p->nDataTag);
+ FlipDWord(&p->nDataSize);
+ FlipWord(&p->fc.wFormatTag);
+ FlipWord(&p->fc.nChannels);
+ FlipDWord(&p->fc.nSamplesPerSec);
+ FlipDWord(&p->fc.nAvgBytesPerSec);
+ FlipWord(&p->fc.nBlockAlign);
+ FlipWord(&p->fc.wBitsPerSample);
+
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ * WaveFileCreate()
+ *----------------------------------------------------------------------------
+ * Purpose: Opens a wave file for writing and writes the header
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ *----------------------------------------------------------------------------
+*/
+
+WAVE_FILE *WaveFileCreate (const char *filename, EAS_I32 nChannels, EAS_I32 nSamplesPerSec, EAS_I32 wBitsPerSample)
+{
+ WAVE_FILE *wFile;
+
+ /* allocate memory */
+ wFile = malloc(sizeof(WAVE_FILE));
+ if (!wFile)
+ return NULL;
+ wFile->write = EAS_TRUE;
+
+ /* create the file */
+ wFile->file = fopen(filename,"wb");
+ if (!wFile->file)
+ {
+ free(wFile);
+ return NULL;
+ }
+
+ /* initialize PCM format .WAV file header */
+ wFile->wh.nRiffTag = riffTag;
+ wFile->wh.nRiffSize = sizeof(WAVE_HEADER) - 8;
+ wFile->wh.nWaveTag = waveTag;
+ wFile->wh.nFmtTag = fmtTag;
+ wFile->wh.nFmtSize = sizeof(FMT_CHUNK);
+
+ /* initalize 'fmt' chunk */
+ wFile->wh.fc.wFormatTag = 1;
+ wFile->wh.fc.nChannels = (EAS_U16) nChannels;
+ wFile->wh.fc.nSamplesPerSec = (EAS_U32) nSamplesPerSec;
+ wFile->wh.fc.wBitsPerSample = (EAS_U16) wBitsPerSample;
+ wFile->wh.fc.nBlockAlign = (EAS_U16) (nChannels * (EAS_U16) (wBitsPerSample / 8));
+ wFile->wh.fc.nAvgBytesPerSec = wFile->wh.fc.nBlockAlign * (EAS_U32) nSamplesPerSec;
+
+ /* initialize 'data' chunk */
+ wFile->wh.nDataTag = dataTag;
+ wFile->wh.nDataSize = 0;
+
+#ifdef _BIG_ENDIAN
+ FlipWaveHeader(&wFile->wh);
+#endif
+
+ /* write the header */
+ if (fwrite(&wFile->wh, sizeof(WAVE_HEADER), 1, wFile->file) != 1)
+ {
+ fclose(wFile->file);
+ free(wFile);
+ return NULL;
+ }
+
+#ifdef _BIG_ENDIAN
+ FlipWaveHeader(&wFile->wh);
+#endif
+
+ /* return the file handle */
+ return wFile;
+} /* end WaveFileCreate */
+
+/*----------------------------------------------------------------------------
+ * WaveFileWrite()
+ *----------------------------------------------------------------------------
+ * Purpose: Writes data to the wave file
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_I32 WaveFileWrite (WAVE_FILE *wFile, void *buffer, EAS_I32 n)
+{
+ EAS_I32 count;
+
+ /* make sure we have an open file */
+ if (wFile == NULL)
+ {
+ return 0;
+ }
+
+#ifdef _BIG_ENDIAN
+ {
+ EAS_I32 i;
+ EAS_U16 *p;
+ p = buffer;
+ i = n >> 1;
+ while (i--)
+ FlipWord(p++);
+ }
+#endif
+
+ /* write the data */
+ count = (EAS_I32) fwrite(buffer, 1, (size_t) n, wFile->file);
+
+ /* add the number of bytes written */
+ wFile->wh.nRiffSize += (EAS_U32) count;
+ wFile->wh.nDataSize += (EAS_U32) count;
+
+ /* return the count of bytes written */
+ return count;
+} /* end WriteWaveHeader */
+
+/*----------------------------------------------------------------------------
+ * WaveFileClose()
+ *----------------------------------------------------------------------------
+ * Purpose: Opens a wave file for writing and writes the header
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ *----------------------------------------------------------------------------
+*/
+
+EAS_BOOL WaveFileClose (WAVE_FILE *wFile)
+{
+ EAS_I32 count = 1;
+
+ /* return to beginning of file and write the header */
+ if (wFile->write)
+ {
+ if (fseek(wFile->file, 0L, SEEK_SET) == 0)
+ {
+
+#ifdef _BIG_ENDIAN
+ FlipWaveHeader(&wFile->wh);
+#endif
+ count = (EAS_I32) fwrite(&wFile->wh, sizeof(WAVE_HEADER), 1, wFile->file);
+#ifdef _BIG_ENDIAN
+ FlipWaveHeader(&wFile->wh);
+#endif
+ }
+ }
+
+ /* close the file */
+ if (fclose(wFile->file) != 0)
+ count = 0;
+
+ /* free the memory */
+ free(wFile);
+
+ /* return the file handle */
+ return (count == 1 ? EAS_TRUE : EAS_FALSE);
+} /* end WaveFileClose */
+
+#ifdef _WAVE_FILE_READ
+#ifdef _BIG_ENDIAN
+#error "WaveFileOpen not currently supported on big-endian processors"
+#endif
+/*----------------------------------------------------------------------------
+ * WaveFileOpen()
+ *----------------------------------------------------------------------------
+ * Purpose: Opens a wave file for reading and reads the header
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ *----------------------------------------------------------------------------
+*/
+
+WAVE_FILE *WaveFileOpen (const char *filename)
+{
+ WAVE_FILE *wFile;
+ struct
+ {
+ EAS_U32 tag;
+ EAS_U32 size;
+ } chunk;
+ EAS_U32 tag;
+ EAS_I32 startChunkPos;
+ EAS_INT state;
+ EAS_BOOL done;
+
+ /* allocate memory */
+ wFile = malloc(sizeof(WAVE_FILE));
+ if (!wFile)
+ return NULL;
+
+ /* open the file */
+ wFile->write = EAS_FALSE;
+ wFile->file = fopen(filename,"rb");
+ if (!wFile->file)
+ {
+ free(wFile);
+ return NULL;
+ }
+
+ /* make lint happy */
+ chunk.tag = chunk.size = 0;
+ startChunkPos = 0;
+
+ /* read the RIFF tag and file size */
+ state = 0;
+ done = EAS_FALSE;
+ while (!done)
+ {
+
+ switch(state)
+ {
+ /* read the RIFF tag */
+ case 0:
+ if (fread(&chunk, sizeof(chunk), 1, wFile->file) != 1)
+ done = EAS_TRUE;
+ else
+ {
+ if (chunk.tag != riffTag)
+ done = EAS_TRUE;
+ else
+ state++;
+ }
+ break;
+
+ /* read the WAVE tag */
+ case 1:
+ if (fread(&tag, sizeof(tag), 1, wFile->file) != 1)
+ done = EAS_TRUE;
+ else
+ {
+ if (tag != waveTag)
+ done = EAS_TRUE;
+ else
+ state++;
+ }
+ break;
+
+ /* looking for fmt chunk */
+ case 2:
+ if (fread(&chunk, sizeof(chunk), 1, wFile->file) != 1)
+ done = EAS_TRUE;
+ else
+ {
+ startChunkPos = ftell(wFile->file);
+
+ /* not fmt tag, skip it */
+ if (chunk.tag != fmtTag)
+ fseek(wFile->file, startChunkPos + (EAS_I32) chunk.size, SEEK_SET);
+ else
+ state++;
+ }
+ break;
+
+ /* read fmt chunk */
+ case 3:
+ if (fread(&wFile->wh.fc, sizeof(FMT_CHUNK), 1, wFile->file) != 1)
+ done = EAS_TRUE;
+ else
+ {
+ fseek(wFile->file, startChunkPos + (EAS_I32) chunk.size, SEEK_SET);
+ state++;
+ }
+ break;
+
+ /* looking for data chunk */
+ case 4:
+ if (fread(&chunk, sizeof(chunk), 1, wFile->file) != 1)
+ done = EAS_TRUE;
+ else
+ {
+ startChunkPos = ftell(wFile->file);
+
+ /* not data tag, skip it */
+ if (chunk.tag != dataTag)
+ fseek(wFile->file, startChunkPos + (EAS_I32) chunk.size, SEEK_SET);
+ else
+ {
+ wFile->dataSize = chunk.size;
+ state++;
+ done = EAS_TRUE;
+ }
+ }
+ break;
+
+ default:
+ done = EAS_TRUE;
+ break;
+ }
+ }
+
+ /* if not final state, an error occurred */
+ if (state != 5)
+ {
+ fclose(wFile->file);
+ free(wFile);
+ return NULL;
+ }
+
+ /* return the file handle */
+ return wFile;
+} /* end WaveFileOpen */
+#endif
+
+
+
diff --git a/arm-fm-22k/host_src/eas_wave.h b/arm-fm-22k/host_src/eas_wave.h
new file mode 100644
index 0000000..ca388f5
--- /dev/null
+++ b/arm-fm-22k/host_src/eas_wave.h
@@ -0,0 +1,74 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_wave.h
+ *
+ * Contents and purpose:
+ * Writes output to a .WAV file
+ *
+ * DO NOT MODIFY THIS FILE!
+ *
+ * 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_types.h"
+
+/* sentinel */
+#ifndef _EAS_WAVE_H
+#define _EAS_WAVE_H
+
+/* .WAV file format chunk */
+typedef struct {
+ EAS_U16 wFormatTag;
+ EAS_U16 nChannels;
+ EAS_U32 nSamplesPerSec;
+ EAS_U32 nAvgBytesPerSec;
+ EAS_U16 nBlockAlign;
+ EAS_U16 wBitsPerSample;
+} FMT_CHUNK;
+
+/* .WAV file header */
+typedef struct {
+ EAS_U32 nRiffTag;
+ EAS_U32 nRiffSize;
+ EAS_U32 nWaveTag;
+ EAS_U32 nFmtTag;
+ EAS_U32 nFmtSize;
+ FMT_CHUNK fc;
+ EAS_U32 nDataTag;
+ EAS_U32 nDataSize;
+} WAVE_HEADER;
+
+typedef struct {
+ WAVE_HEADER wh;
+ FILE *file;
+ EAS_BOOL write;
+ EAS_U32 dataSize;
+} WAVE_FILE;
+
+WAVE_FILE *WaveFileCreate (const char *filename, EAS_I32 nChannels, EAS_I32 nSamplesPerSec, EAS_I32 wBitsPerSample);
+EAS_I32 WaveFileWrite (WAVE_FILE *wFile, void *buffer, EAS_I32 n);
+EAS_BOOL WaveFileClose (WAVE_FILE *wFile);
+WAVE_FILE *WaveFileOpen (const char *filename);
+
+#endif /* end #ifndef _EAS_WAVE_H */
+
+
+
diff --git a/arm-fm-22k/lib/libarm-fm-22k.a b/arm-fm-22k/lib/libarm-fm-22k.a
new file mode 100644
index 0000000..303b6b3
--- /dev/null
+++ b/arm-fm-22k/lib/libarm-fm-22k.a
Binary files differ
diff --git a/arm-fm-22k/lib_src/arm-fm-22k_lib.mak b/arm-fm-22k/lib_src/arm-fm-22k_lib.mak
new file mode 100644
index 0000000..e4bc63d
--- /dev/null
+++ b/arm-fm-22k/lib_src/arm-fm-22k_lib.mak
@@ -0,0 +1,25 @@
+#
+# Auto-generated sample makefile
+#
+# This makefile is intended for use with GNU make.
+# Set the paths to the tools (CC, AR, LD, etc.)
+#
+
+vpath %.c lib_src
+
+CC = C:\Program Files\GNUARM\bin\arm-elf-gcc.exe
+AS = C:\Program Files\GNUARM\bin\arm-elf-as.exe
+LD = C:\Program Files\GNUARM\bin\arm-elf-gcc.exe
+AR = C:\Program Files\GNUARM\bin\arm-elf-ar.exe
+
+%.o: %.c
+ $(CC) -c -O2 -o $@ -I lib_src -I host_src -D NUM_OUTPUT_CHANNELS=2 -D _SAMPLE_RATE_22050 -D MAX_SYNTH_VOICES=16 -D EAS_FM_SYNTH -D _IMELODY_PARSER -D _RTTTL_PARSER -D _OTA_PARSER -D _WAVE_PARSER -D _REVERB_ENABLED -D _CHORUS_ENABLED -D _IMA_DECODER $<
+
+%.o: %.s
+ $(AS) -o $@ -EL -mcpu=arm946e-s -mfpu=softfpa $<
+
+OBJS = eas_mididata.o eas_pan.o eas_wavefiledata.o eas_smfdata.o eas_imelody.o eas_math.o eas_fmengine.o eas_chorusdata.o eas_ima_tables.o eas_ota.o eas_rtttldata.o eas_imelodydata.o eas_fmtables.o eas_public.o eas_rtttl.o eas_reverb.o eas_fmsynth.o eas_midi.o eas_otadata.o eas_mixbuf.o eas_fmsndlib.o eas_imaadpcm.o eas_smf.o eas_chorus.o eas_pcm.o eas_mixer.o eas_wavefile.o eas_pcmdata.o eas_data.o eas_reverbdata.o eas_voicemgt.o
+
+arm-fm-22k.a: $(OBJS)
+ $(AR) rc lib$@ $(OBJS)
+
diff --git a/arm-fm-22k/lib_src/eas_audioconst.h b/arm-fm-22k/lib_src/eas_audioconst.h
new file mode 100644
index 0000000..1cfa404
--- /dev/null
+++ b/arm-fm-22k/lib_src/eas_audioconst.h
@@ -0,0 +1,97 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_audioconst.h
+ *
+ * Contents and purpose:
+ * Defines audio constants related to the sample rate, bit size, etc.
+ *
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 82 $
+ * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $
+ *----------------------------------------------------------------------------
+*/
+
+#ifndef _EAS_AUDIOCONST_H
+#define _EAS_AUDIOCONST_H
+
+/*----------------------------------------------------------------------------
+ * These macros define the various characteristics of the defined sample rates
+ *----------------------------------------------------------------------------
+ * BUFFER_SIZE_IN_MONO_SAMPLES size of buffer in samples
+ * _OUTPUT_SAMPLE_RATE compiled output sample rate
+ * AUDIO_FRAME_LENGTH length of an audio frame in 256ths of a millisecond
+ * SYNTH_UPDATE_PERIOD_IN_BITS length of an audio frame (2^x samples)
+ *----------------------------------------------------------------------------
+*/
+
+#if defined (_SAMPLE_RATE_8000)
+#define BUFFER_SIZE_IN_MONO_SAMPLES 32
+#define _OUTPUT_SAMPLE_RATE 8000
+#define AUDIO_FRAME_LENGTH 1024
+#define SYNTH_UPDATE_PERIOD_IN_BITS 5
+
+#elif defined (_SAMPLE_RATE_16000)
+#define BUFFER_SIZE_IN_MONO_SAMPLES 64
+#define _OUTPUT_SAMPLE_RATE 16000
+#define AUDIO_FRAME_LENGTH 1024
+#define SYNTH_UPDATE_PERIOD_IN_BITS 6
+
+#elif defined (_SAMPLE_RATE_20000)
+#define BUFFER_SIZE_IN_MONO_SAMPLES 128
+#define _OUTPUT_SAMPLE_RATE 20000
+#define AUDIO_FRAME_LENGTH 1638
+#define SYNTH_UPDATE_PERIOD_IN_BITS 7
+
+#elif defined (_SAMPLE_RATE_22050)
+#define BUFFER_SIZE_IN_MONO_SAMPLES 128
+#define _OUTPUT_SAMPLE_RATE 22050
+#define AUDIO_FRAME_LENGTH 1486
+#define SYNTH_UPDATE_PERIOD_IN_BITS 7
+
+#elif defined (_SAMPLE_RATE_24000)
+#define BUFFER_SIZE_IN_MONO_SAMPLES 128
+#define _OUTPUT_SAMPLE_RATE 24000
+#define AUDIO_FRAME_LENGTH 1365
+#define SYNTH_UPDATE_PERIOD_IN_BITS 7
+
+#elif defined (_SAMPLE_RATE_32000)
+#define BUFFER_SIZE_IN_MONO_SAMPLES 128
+#define _OUTPUT_SAMPLE_RATE 32000
+#define AUDIO_FRAME_LENGTH 1024
+#define SYNTH_UPDATE_PERIOD_IN_BITS 7
+
+#elif defined (_SAMPLE_RATE_44100)
+#define BUFFER_SIZE_IN_MONO_SAMPLES 256
+#define _OUTPUT_SAMPLE_RATE 44100
+#define AUDIO_FRAME_LENGTH 1486
+#define SYNTH_UPDATE_PERIOD_IN_BITS 8
+
+#elif defined (_SAMPLE_RATE_48000)
+#define BUFFER_SIZE_IN_MONO_SAMPLES 256
+#define _OUTPUT_SAMPLE_RATE 48000
+#define AUDIO_FRAME_LENGTH 1365
+#define SYNTH_UPDATE_PERIOD_IN_BITS 8
+
+#else
+#error "_SAMPLE_RATE_XXXXX must be defined to valid rate"
+#endif
+
+#endif /* #ifndef _EAS_AUDIOCONST_H */
+
diff --git a/arm-fm-22k/lib_src/eas_chorus.c b/arm-fm-22k/lib_src/eas_chorus.c
new file mode 100644
index 0000000..bc42237
--- /dev/null
+++ b/arm-fm-22k/lib_src/eas_chorus.c
@@ -0,0 +1,604 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_chorus.c
+ *
+ * Contents and purpose:
+ * Contains the implementation of the Chorus effect.
+ *
+ *
+ * Copyright Sonic Network Inc. 2006
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 499 $
+ * $Date: 2006-12-11 16:07:20 -0800 (Mon, 11 Dec 2006) $
+ *----------------------------------------------------------------------------
+*/
+
+#include "eas_data.h"
+#include "eas_effects.h"
+#include "eas_math.h"
+#include "eas_chorusdata.h"
+#include "eas_chorus.h"
+#include "eas_config.h"
+#include "eas_host.h"
+#include "eas_report.h"
+
+/* prototypes for effects interface */
+static EAS_RESULT ChorusInit (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData);
+static void ChorusProcess (EAS_VOID_PTR pInstData, EAS_PCM *pSrc, EAS_PCM *pDst, EAS_I32 numSamples);
+static EAS_RESULT ChorusShutdown (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData);
+static EAS_RESULT ChorusGetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue);
+static EAS_RESULT ChorusSetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value);
+
+/* common effects interface for configuration module */
+const S_EFFECTS_INTERFACE EAS_Chorus =
+{
+ ChorusInit,
+ ChorusProcess,
+ ChorusShutdown,
+ ChorusGetParam,
+ ChorusSetParam
+};
+
+
+
+//LFO shape table used by the chorus, larger table would sound better
+//this is a sine wave, where 32767 = 1.0
+static const EAS_I16 EAS_chorusShape[CHORUS_SHAPE_SIZE] = {
+ 0, 1608, 3212, 4808, 6393, 7962, 9512, 11309, 12539, 14010, 15446, 16846, 18204, 19519, 20787, 22005, 23170,
+ 24279, 25329, 26319, 27245, 28105, 28898, 29621, 30273, 30852, 31356, 31785, 32137, 32412, 32609, 32728,
+ 32767, 32728, 32609, 32412, 32137, 31785, 31356, 30852, 30273, 29621, 28898, 28105, 27245, 26319, 25329,
+ 24279, 23170, 22005, 20787, 19519, 18204, 16846, 15446, 14010, 12539, 11039, 9512, 7962, 6393, 4808, 3212,
+ 1608, 0, -1608, -3212, -4808, -6393, -7962, -9512, -11309, -12539, -14010, -15446, -16846, -18204, -19519,
+ -20787, -22005, -23170, -24279, -25329, -26319, -27245, -28105, -28898, -29621, -30273, -30852, -31356, -31785,
+ -32137, -32412, -32609, -32728, -32767, -32728, -32609, -32412, -32137, -31785, -31356, -30852, -30273, -29621,
+ -28898, -28105, -27245, -26319, -25329, -24279, -23170, -22005, -20787, -19519, -18204, -16846, -15446, -14010,
+ -12539, -11039, -9512, -7962, -6393, -4808, -3212, -1608
+};
+
+/*----------------------------------------------------------------------------
+ * InitializeChorus()
+ *----------------------------------------------------------------------------
+ * Purpose: Initializes chorus parameters
+ *
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT ChorusInit (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData)
+{
+ S_CHORUS_OBJECT *pChorusData;
+ S_CHORUS_PRESET *pPreset;
+ EAS_I32 index;
+
+ /* check Configuration Module for data allocation */
+ if (pEASData->staticMemoryModel)
+ pChorusData = EAS_CMEnumFXData(EAS_MODULE_CHORUS);
+
+ /* allocate dynamic memory */
+ else
+ pChorusData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_CHORUS_OBJECT));
+
+ if (pChorusData == NULL)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate Chorus memory\n"); */ }
+ return EAS_ERROR_MALLOC_FAILED;
+ }
+
+ /* clear the structure */
+ EAS_HWMemSet(pChorusData, 0, sizeof(S_CHORUS_OBJECT));
+
+ ChorusReadInPresets(pChorusData);
+
+ /* set some default values */
+ pChorusData->bypass = EAS_CHORUS_BYPASS_DEFAULT;
+ pChorusData->preset = EAS_CHORUS_PRESET_DEFAULT;
+ pChorusData->m_nLevel = EAS_CHORUS_LEVEL_DEFAULT;
+ pChorusData->m_nRate = EAS_CHORUS_RATE_DEFAULT;
+ pChorusData->m_nDepth = EAS_CHORUS_DEPTH_DEFAULT;
+
+ //chorus rate and depth need some massaging from preset value (which is sample rate independent)
+
+ //convert rate from steps of .05 Hz to value which can be used as phase increment,
+ //with current CHORUS_SHAPE_SIZE and rate limits, this fits into 16 bits
+ //want to compute ((shapeSize * 65536) * (storedRate/20))/sampleRate;
+ //computing it as below allows rate steps to be evenly spaced
+ //uses 32 bit divide, but only once when new value is selected
+ pChorusData->m_nRate = (EAS_I16)
+ ((((EAS_I32)CHORUS_SHAPE_SIZE<<16)/(20*(EAS_I32)_OUTPUT_SAMPLE_RATE)) * pChorusData->m_nRate);
+
+ //convert depth from steps of .05 ms, to samples, with 16 bit whole part, discard fraction
+ //want to compute ((depth * sampleRate)/20000)
+ //use the following approximation since 105/32 is roughly 65536/20000
+ /*lint -e{704} use shift for performance */
+ pChorusData->m_nDepth = (EAS_I16)
+ (((((EAS_I32)pChorusData->m_nDepth * _OUTPUT_SAMPLE_RATE)>>5) * 105) >> 16);
+
+ pChorusData->m_nLevel = pChorusData->m_nLevel;
+
+ //zero delay memory for chorus
+ for (index = CHORUS_L_SIZE - 1; index >= 0; index--)
+ {
+ pChorusData->chorusDelayL[index] = 0;
+ }
+ for (index = CHORUS_R_SIZE - 1; index >= 0; index--)
+ {
+ pChorusData->chorusDelayR[index] = 0;
+ }
+
+ //init delay line index, these are used to implement circular delay buffer
+ pChorusData->chorusIndexL = 0;
+ pChorusData->chorusIndexR = 0;
+
+ //init LFO phase
+ //16 bit whole part, 16 bit fraction
+ pChorusData->lfoLPhase = 0;
+ pChorusData->lfoRPhase = (CHORUS_SHAPE_SIZE << 16) >> 2; // 1/4 of total, i.e. 90 degrees out of phase;
+
+ //init chorus delay position
+ //right now chorus delay is a compile-time value, as is sample rate
+ pChorusData->chorusTapPosition = (EAS_I16)((CHORUS_DELAY_MS * _OUTPUT_SAMPLE_RATE)/1000);
+
+ //now copy from the new preset into Chorus
+ pPreset = &pChorusData->m_sPreset.m_sPreset[pChorusData->m_nNextChorus];
+
+ pChorusData->m_nLevel = pPreset->m_nLevel;
+ pChorusData->m_nRate = pPreset->m_nRate;
+ pChorusData->m_nDepth = pPreset->m_nDepth;
+
+ pChorusData->m_nRate = (EAS_I16)
+ ((((EAS_I32)CHORUS_SHAPE_SIZE<<16)/(20*(EAS_I32)_OUTPUT_SAMPLE_RATE)) * pChorusData->m_nRate);
+
+ /*lint -e{704} use shift for performance */
+ pChorusData->m_nDepth = (EAS_I16)
+ (((((EAS_I32)pChorusData->m_nDepth * _OUTPUT_SAMPLE_RATE)>>5) * 105) >> 16);
+
+ *pInstData = pChorusData;
+
+ return EAS_SUCCESS;
+} /* end ChorusInit */
+
+/*----------------------------------------------------------------------------
+ * WeightedTap()
+ *----------------------------------------------------------------------------
+ * Purpose: Does fractional array look-up using linear interpolation
+ *
+ * first convert indexDesired to actual desired index by taking into account indexReference
+ * then do linear interpolation between two actual samples using fractional part
+ *
+ * Inputs:
+ * array: pointer to array of signed 16 bit values, typically either PCM data or control data
+ * indexReference: the circular buffer relative offset
+ * indexDesired: the fractional index we are looking up (16 bits index + 16 bits fraction)
+ * indexLimit: the total size of the array, used to compute buffer wrap
+ *
+ * Outputs:
+ * Value from the input array, linearly interpolated between two actual data values
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_I16 WeightedTap(const EAS_I16 *array, EAS_I16 indexReference, EAS_I32 indexDesired, EAS_I16 indexLimit)
+{
+ EAS_I16 index;
+ EAS_I16 fraction;
+ EAS_I16 val1;
+ EAS_I16 val2;
+
+ //separate indexDesired into whole and fractional parts
+ /*lint -e{704} use shift for performance */
+ index = (EAS_I16)(indexDesired >> 16);
+ /*lint -e{704} use shift for performance */
+ fraction = (EAS_I16)((indexDesired>>1) & 0x07FFF); //just use 15 bits of fractional part
+
+ //adjust whole part by indexReference
+ index = indexReference - index;
+ //make sure we stay within array bounds, this implements circular buffer
+ while (index < 0)
+ {
+ index += indexLimit;
+ }
+
+ //get two adjacent values from the array
+ val1 = array[index];
+
+ //handle special case when index == 0, else typical case
+ if (index == 0)
+ {
+ val2 = array[indexLimit-1]; //get last value from array
+ }
+ else
+ {
+ val2 = array[index-1]; //get previous value from array
+ }
+
+ //compute linear interpolation as (val1 + ((val2-val1)*fraction))
+ return(val1 + (EAS_I16)MULT_EG1_EG1(val2-val1,fraction));
+}
+
+/*----------------------------------------------------------------------------
+ * ChorusProcess()
+ *----------------------------------------------------------------------------
+ * Purpose: compute the chorus on the input buffer, and mix into output buffer
+ *
+ *
+ * Inputs:
+ * src: pointer to input buffer of PCM values to be processed
+ * dst: pointer to output buffer of PCM values we are to sume the result with
+ * bufSize: the number of sample frames (i.e. stereo samples) in the buffer
+ *
+ * Outputs:
+ * None
+ *
+ *----------------------------------------------------------------------------
+*/
+//compute the chorus, and mix into output buffer
+static void ChorusProcess (EAS_VOID_PTR pInstData, EAS_PCM *pSrc, EAS_PCM *pDst, EAS_I32 numSamples)
+{
+ EAS_I32 ix;
+ EAS_I32 nChannelNumber;
+ EAS_I16 lfoValueLeft;
+ EAS_I16 lfoValueRight;
+ EAS_I32 positionOffsetL;
+ EAS_I32 positionOffsetR;
+ EAS_PCM tapL;
+ EAS_PCM tapR;
+ EAS_I32 tempValue;
+ EAS_PCM nInputSample;
+ EAS_I32 nOutputSample;
+ EAS_PCM *pIn;
+ EAS_PCM *pOut;
+
+ S_CHORUS_OBJECT *pChorusData;
+
+ pChorusData = (S_CHORUS_OBJECT*) pInstData;
+
+ //if the chorus is disabled or turned all the way down
+ if (pChorusData->bypass == EAS_TRUE || pChorusData->m_nLevel == 0)
+ {
+ if (pSrc != pDst)
+ EAS_HWMemCpy(pSrc, pDst, numSamples * NUM_OUTPUT_CHANNELS * (EAS_I32) sizeof(EAS_PCM));
+ return;
+ }
+
+ if (pChorusData->m_nNextChorus != pChorusData->m_nCurrentChorus)
+ {
+ ChorusUpdate(pChorusData);
+ }
+
+ for (nChannelNumber = 0; nChannelNumber < NUM_OUTPUT_CHANNELS; nChannelNumber++)
+ {
+
+ pIn = pSrc + nChannelNumber;
+ pOut = pDst + nChannelNumber;
+
+ if(nChannelNumber==0)
+ {
+ for (ix = 0; ix < numSamples; ix++)
+ {
+ nInputSample = *pIn;
+ pIn += NUM_OUTPUT_CHANNELS;
+
+ //feed input into chorus delay line
+ pChorusData->chorusDelayL[pChorusData->chorusIndexL] = nInputSample;
+
+ //compute chorus lfo value using phase as fractional index into chorus shape table
+ //resulting value is between -1.0 and 1.0, expressed as signed 16 bit number
+ lfoValueLeft = WeightedTap(EAS_chorusShape, 0, pChorusData->lfoLPhase, CHORUS_SHAPE_SIZE);
+
+ //scale chorus depth by lfo value to get relative fractional sample index
+ //index is expressed as 32 bit number with 16 bit fractional part
+ /*lint -e{703} use shift for performance */
+ positionOffsetL = pChorusData->m_nDepth * (((EAS_I32)lfoValueLeft) << 1);
+
+ //add fixed chorus delay to get actual fractional sample index
+ positionOffsetL += ((EAS_I32)pChorusData->chorusTapPosition) << 16;
+
+ //get tap value from chorus delay using fractional sample index
+ tapL = WeightedTap(pChorusData->chorusDelayL, pChorusData->chorusIndexL, positionOffsetL, CHORUS_L_SIZE);
+
+ //scale by chorus level, then sum with input buffer contents and saturate
+ tempValue = MULT_EG1_EG1(tapL, pChorusData->m_nLevel);
+ nOutputSample = SATURATE(tempValue + nInputSample);
+
+ *pOut = (EAS_I16)SATURATE(nOutputSample);
+ pOut += NUM_OUTPUT_CHANNELS;
+
+
+ //increment chorus delay index and make it wrap as needed
+ //this implements circular buffer
+ if ((pChorusData->chorusIndexL+=1) >= CHORUS_L_SIZE)
+ pChorusData->chorusIndexL = 0;
+
+ //increment fractional lfo phase, and make it wrap as needed
+ pChorusData->lfoLPhase += pChorusData->m_nRate;
+ while (pChorusData->lfoLPhase >= (CHORUS_SHAPE_SIZE<<16))
+ {
+ pChorusData->lfoLPhase -= (CHORUS_SHAPE_SIZE<<16);
+ }
+ }
+ }
+ else
+ {
+ for (ix = 0; ix < numSamples; ix++)
+ {
+ nInputSample = *pIn;
+ pIn += NUM_OUTPUT_CHANNELS;
+
+ //feed input into chorus delay line
+ pChorusData->chorusDelayR[pChorusData->chorusIndexR] = nInputSample;
+
+ //compute chorus lfo value using phase as fractional index into chorus shape table
+ //resulting value is between -1.0 and 1.0, expressed as signed 16 bit number
+ lfoValueRight = WeightedTap(EAS_chorusShape, 0, pChorusData->lfoRPhase, CHORUS_SHAPE_SIZE);
+
+ //scale chorus depth by lfo value to get relative fractional sample index
+ //index is expressed as 32 bit number with 16 bit fractional part
+ /*lint -e{703} use shift for performance */
+ positionOffsetR = pChorusData->m_nDepth * (((EAS_I32)lfoValueRight) << 1);
+
+ //add fixed chorus delay to get actual fractional sample index
+ positionOffsetR += ((EAS_I32)pChorusData->chorusTapPosition) << 16;
+
+ //get tap value from chorus delay using fractional sample index
+ tapR = WeightedTap(pChorusData->chorusDelayR, pChorusData->chorusIndexR, positionOffsetR, CHORUS_R_SIZE);
+
+ //scale by chorus level, then sum with output buffer contents and saturate
+ tempValue = MULT_EG1_EG1(tapR, pChorusData->m_nLevel);
+ nOutputSample = SATURATE(tempValue + nInputSample);
+
+ *pOut = (EAS_I16)SATURATE(nOutputSample);
+ pOut += NUM_OUTPUT_CHANNELS;
+
+ //increment chorus delay index and make it wrap as needed
+ //this implements circular buffer
+ if ((pChorusData->chorusIndexR+=1) >= CHORUS_R_SIZE)
+ pChorusData->chorusIndexR = 0;
+
+ //increment fractional lfo phase, and make it wrap as needed
+ pChorusData->lfoRPhase += pChorusData->m_nRate;
+ while (pChorusData->lfoRPhase >= (CHORUS_SHAPE_SIZE<<16))
+ {
+ pChorusData->lfoRPhase -= (CHORUS_SHAPE_SIZE<<16);
+ }
+ }
+ }
+
+ }
+} /* end ChorusProcess */
+
+
+
+/*----------------------------------------------------------------------------
+ * ChorusShutdown()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Initializes the Chorus effect.
+ *
+ * Inputs:
+ * pInstData - handle to instance data
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT ChorusShutdown (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData)
+{
+ /* check Configuration Module for static memory allocation */
+ if (!pEASData->staticMemoryModel)
+ EAS_HWFree(pEASData->hwInstData, pInstData);
+ return EAS_SUCCESS;
+} /* end ChorusShutdown */
+
+/*----------------------------------------------------------------------------
+ * ChorusGetParam()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Get a Chorus parameter
+ *
+ * Inputs:
+ * pInstData - handle to instance data
+ * param - parameter index
+ * *pValue - pointer to variable to hold retrieved value
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT ChorusGetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue)
+{
+ S_CHORUS_OBJECT *p;
+
+ p = (S_CHORUS_OBJECT*) pInstData;
+
+ switch (param)
+ {
+ case EAS_PARAM_CHORUS_BYPASS:
+ *pValue = (EAS_I32) p->bypass;
+ break;
+ case EAS_PARAM_CHORUS_PRESET:
+ *pValue = (EAS_I8) p->m_nCurrentChorus;
+ break;
+ case EAS_PARAM_CHORUS_RATE:
+ *pValue = (EAS_I32) p->m_nRate;
+ break;
+ case EAS_PARAM_CHORUS_DEPTH:
+ *pValue = (EAS_I32) p->m_nDepth;
+ break;
+ case EAS_PARAM_CHORUS_LEVEL:
+ *pValue = (EAS_I32) p->m_nLevel;
+ break;
+ default:
+ return EAS_ERROR_INVALID_PARAMETER;
+ }
+ return EAS_SUCCESS;
+} /* end ChorusGetParam */
+
+
+/*----------------------------------------------------------------------------
+ * ChorusSetParam()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Set a Chorus parameter
+ *
+ * Inputs:
+ * pInstData - handle to instance data
+ * param - parameter index
+ * *pValue - new paramter value
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT ChorusSetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value)
+{
+ S_CHORUS_OBJECT *p;
+
+ p = (S_CHORUS_OBJECT*) pInstData;
+
+ switch (param)
+ {
+ case EAS_PARAM_CHORUS_BYPASS:
+ p->bypass = (EAS_BOOL) value;
+ break;
+ case EAS_PARAM_CHORUS_PRESET:
+ if(value!=EAS_PARAM_CHORUS_PRESET1 && value!=EAS_PARAM_CHORUS_PRESET2 &&
+ value!=EAS_PARAM_CHORUS_PRESET3 && value!=EAS_PARAM_CHORUS_PRESET4)
+ return EAS_ERROR_INVALID_PARAMETER;
+ p->m_nNextChorus = (EAS_I8)value;
+ break;
+ case EAS_PARAM_CHORUS_RATE:
+ if(value<EAS_CHORUS_RATE_MIN || value>EAS_CHORUS_RATE_MAX)
+ return EAS_ERROR_INVALID_PARAMETER;
+ p->m_nRate = (EAS_I16) value;
+ break;
+ case EAS_PARAM_CHORUS_DEPTH:
+ if(value<EAS_CHORUS_DEPTH_MIN || value>EAS_CHORUS_DEPTH_MAX)
+ return EAS_ERROR_INVALID_PARAMETER;
+ p->m_nDepth = (EAS_I16) value;
+ break;
+ case EAS_PARAM_CHORUS_LEVEL:
+ if(value<EAS_CHORUS_LEVEL_MIN || value>EAS_CHORUS_LEVEL_MAX)
+ return EAS_ERROR_INVALID_PARAMETER;
+ p->m_nLevel = (EAS_I16) value;
+ break;
+
+ default:
+ return EAS_ERROR_INVALID_PARAMETER;
+ }
+ return EAS_SUCCESS;
+} /* end ChorusSetParam */
+
+
+/*----------------------------------------------------------------------------
+ * ChorusReadInPresets()
+ *----------------------------------------------------------------------------
+ * Purpose: sets global Chorus preset bank to defaults
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT ChorusReadInPresets(S_CHORUS_OBJECT *pChorusData)
+{
+
+ int preset = 0;
+ int defaultPreset = 0;
+
+ //now init any remaining presets to defaults
+ for (defaultPreset = preset; defaultPreset < CHORUS_MAX_TYPE; defaultPreset++)
+ {
+ S_CHORUS_PRESET *pPreset = &pChorusData->m_sPreset.m_sPreset[defaultPreset];
+ if (defaultPreset == 0 || defaultPreset > CHORUS_MAX_TYPE-1)
+ {
+ pPreset->m_nDepth = 39;
+ pPreset->m_nRate = 30;
+ pPreset->m_nLevel = 32767;
+ }
+ else if (defaultPreset == 1)
+ {
+ pPreset->m_nDepth = 21;
+ pPreset->m_nRate = 45;
+ pPreset->m_nLevel = 25000;
+ }
+ else if (defaultPreset == 2)
+ {
+ pPreset->m_nDepth = 53;
+ pPreset->m_nRate = 25;
+ pPreset->m_nLevel = 32000;
+ }
+ else if (defaultPreset == 3)
+ {
+ pPreset->m_nDepth = 32;
+ pPreset->m_nRate = 37;
+ pPreset->m_nLevel = 29000;
+ }
+ }
+
+ return EAS_SUCCESS;
+}
+
+
+/*----------------------------------------------------------------------------
+ * ChorusUpdate
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Update the Chorus preset parameters as required
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ * - chorus paramters will be changed
+ * - m_nCurrentRoom := m_nNextRoom
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT ChorusUpdate(S_CHORUS_OBJECT *pChorusData)
+{
+ S_CHORUS_PRESET *pPreset = &pChorusData->m_sPreset.m_sPreset[pChorusData->m_nNextChorus];
+
+ pChorusData->m_nLevel = pPreset->m_nLevel;
+ pChorusData->m_nRate = pPreset->m_nRate;
+ pChorusData->m_nDepth = pPreset->m_nDepth;
+
+ pChorusData->m_nRate = (EAS_I16)
+ ((((EAS_I32)CHORUS_SHAPE_SIZE<<16)/(20*(EAS_I32)_OUTPUT_SAMPLE_RATE)) * pChorusData->m_nRate);
+
+ /*lint -e{704} use shift for performance */
+ pChorusData->m_nDepth = (EAS_I16)
+ (((((EAS_I32)pChorusData->m_nDepth * _OUTPUT_SAMPLE_RATE)>>5) * 105) >> 16);
+
+ pChorusData->m_nCurrentChorus = pChorusData->m_nNextChorus;
+
+ return EAS_SUCCESS;
+
+} /* end ChorusUpdate */
diff --git a/arm-fm-22k/lib_src/eas_chorusdata.c b/arm-fm-22k/lib_src/eas_chorusdata.c
new file mode 100644
index 0000000..caee1ed
--- /dev/null
+++ b/arm-fm-22k/lib_src/eas_chorusdata.c
@@ -0,0 +1,34 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_chorusdata.c
+ *
+ * Contents and purpose:
+ * Contains the static data allocation for the Chorus effect
+ *
+ *
+ * Copyright Sonic Network Inc. 2006
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 550 $
+ * $Date: 2007-02-02 09:37:03 -0800 (Fri, 02 Feb 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+#include "eas_chorusdata.h"
+
+S_CHORUS_OBJECT eas_ChorusData;
+
diff --git a/arm-fm-22k/lib_src/eas_chorusdata.h b/arm-fm-22k/lib_src/eas_chorusdata.h
new file mode 100644
index 0000000..4420ddd
--- /dev/null
+++ b/arm-fm-22k/lib_src/eas_chorusdata.h
@@ -0,0 +1,160 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_chorusdata.h
+ *
+ * Contents and purpose:
+ * Contains the prototypes for the Chorus effect.
+ *
+ *
+ * Copyright Sonic Network Inc. 2006
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 309 $
+ * $Date: 2006-09-12 18:52:45 -0700 (Tue, 12 Sep 2006) $
+ *----------------------------------------------------------------------------
+*/
+
+#ifndef _EAS_CHORUS_H
+#define _EAS_CHORUS_H
+
+#include "eas_types.h"
+#include "eas_audioconst.h"
+
+//defines for chorus
+
+#define EAS_CHORUS_BYPASS_DEFAULT 1
+#define EAS_CHORUS_PRESET_DEFAULT 0
+#define EAS_CHORUS_RATE_DEFAULT 30
+#define EAS_CHORUS_DEPTH_DEFAULT 39
+#define EAS_CHORUS_LEVEL_DEFAULT 32767
+
+#define EAS_CHORUS_LEVEL_MIN 0
+#define EAS_CHORUS_LEVEL_MAX 32767
+
+#define EAS_CHORUS_RATE_MIN 10
+#define EAS_CHORUS_RATE_MAX 50
+
+#define EAS_CHORUS_DEPTH_MIN 15
+#define EAS_CHORUS_DEPTH_MAX 60
+
+#define CHORUS_SIZE_MS 20
+#define CHORUS_L_SIZE ((CHORUS_SIZE_MS*_OUTPUT_SAMPLE_RATE)/1000)
+#define CHORUS_R_SIZE CHORUS_L_SIZE
+#define CHORUS_SHAPE_SIZE 128
+#define CHORUS_DELAY_MS 10
+
+#define CHORUS_MAX_TYPE 4 // any Chorus numbers larger than this are invalid
+
+typedef struct
+{
+ EAS_I16 m_nRate;
+ EAS_I16 m_nDepth;
+ EAS_I16 m_nLevel;
+
+} S_CHORUS_PRESET;
+
+typedef struct
+{
+ S_CHORUS_PRESET m_sPreset[CHORUS_MAX_TYPE]; //array of presets
+
+} S_CHORUS_PRESET_BANK;
+
+/* parameters for each Chorus */
+typedef struct
+{
+ EAS_I32 lfoLPhase;
+ EAS_I32 lfoRPhase;
+ EAS_I16 chorusIndexL;
+ EAS_I16 chorusIndexR;
+ EAS_U16 chorusTapPosition;
+
+ EAS_I16 m_nRate;
+ EAS_I16 m_nDepth;
+ EAS_I16 m_nLevel;
+
+ //delay lines used by the chorus, longer would sound better
+ EAS_PCM chorusDelayL[CHORUS_L_SIZE];
+ EAS_PCM chorusDelayR[CHORUS_R_SIZE];
+
+ EAS_BOOL bypass;
+ EAS_I8 preset;
+
+ EAS_I16 m_nCurrentChorus; // preset number for current Chorus
+ EAS_I16 m_nNextChorus; // preset number for next Chorus
+
+ S_CHORUS_PRESET pPreset;
+
+ S_CHORUS_PRESET_BANK m_sPreset;
+
+} S_CHORUS_OBJECT;
+
+
+/*----------------------------------------------------------------------------
+ * WeightedTap()
+ *----------------------------------------------------------------------------
+ * Purpose: Does fractional array look-up using linear interpolation
+ *
+ * first convert indexDesired to actual desired index by taking into account indexReference
+ * then do linear interpolation between two actual samples using fractional part
+ *
+ * Inputs:
+ * array: pointer to array of signed 16 bit values, typically either PCM data or control data
+ * indexReference: the circular buffer relative offset
+ * indexDesired: the fractional index we are looking up (16 bits index + 16 bits fraction)
+ * indexLimit: the total size of the array, used to compute buffer wrap
+ *
+ * Outputs:
+ * Value from the input array, linearly interpolated between two actual data values
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_I16 WeightedTap(const EAS_I16 *array, EAS_I16 indexReference, EAS_I32 indexDesired, EAS_I16 indexLimit);
+
+/*----------------------------------------------------------------------------
+ * ChorusReadInPresets()
+ *----------------------------------------------------------------------------
+ * Purpose: sets global Chorus preset bank to defaults
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT ChorusReadInPresets(S_CHORUS_OBJECT *pChorusData);
+
+/*----------------------------------------------------------------------------
+ * ChorusUpdate
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Update the Chorus preset parameters as required
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ * - chorus paramters will be changed
+ * - m_nCurrentChorus := m_nNextChorus
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT ChorusUpdate(S_CHORUS_OBJECT* pChorusData);
+
+#endif /* #ifndef _EAS_CHORUSDATA_H */
+
+
diff --git a/arm-fm-22k/lib_src/eas_ctype.h b/arm-fm-22k/lib_src/eas_ctype.h
new file mode 100644
index 0000000..8503870
--- /dev/null
+++ b/arm-fm-22k/lib_src/eas_ctype.h
@@ -0,0 +1,41 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_ctype.h
+ *
+ * Contents and purpose:
+ * This is a replacement for the CRT ctype.h functions. These
+ * functions are currently ASCII only, but eventually, we will want
+ * to support wide-characters for localization.
+ *
+ * Copyright (c) 2005 Sonic Network Inc.
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 429 $
+ * $Date: 2006-10-19 23:50:15 -0700 (Thu, 19 Oct 2006) $
+ *----------------------------------------------------------------------------
+*/
+
+#ifndef _EAS_CTYPE_H
+#define _EAS_CTYPE_H
+
+EAS_INLINE EAS_I8 IsDigit (EAS_I8 c) { return ((c >= '0') && (c <= '9')); }
+EAS_INLINE EAS_I8 IsSpace (EAS_I8 c) { return (((c >= 9) && (c <= 13)) || (c == ' ')); }
+EAS_INLINE EAS_I8 ToUpper (EAS_I8 c) { if ((c >= 'a') && (c <= 'z')) return c & ~0x20; else return c; }
+EAS_INLINE EAS_I8 ToLower (EAS_I8 c) { if ((c >= 'A') && (c <= 'Z')) return c |= 0x20; else return c; }
+
+#endif
+
diff --git a/arm-fm-22k/lib_src/eas_data.c b/arm-fm-22k/lib_src/eas_data.c
new file mode 100644
index 0000000..bb60ef2
--- /dev/null
+++ b/arm-fm-22k/lib_src/eas_data.c
@@ -0,0 +1,37 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_data.c
+ *
+ * Contents and purpose:
+ * Contains a data allocation for synthesizer
+ *
+ * Copyright Sonic Network Inc. 2004
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 547 $
+ * $Date: 2007-01-31 16:30:17 -0800 (Wed, 31 Jan 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+// includes
+#include "eas_data.h"
+
+// globals
+S_EAS_DATA eas_Data;
+S_VOICE_MGR eas_Synth;
+S_SYNTH eas_MIDI;
+
diff --git a/arm-fm-22k/lib_src/eas_data.h b/arm-fm-22k/lib_src/eas_data.h
new file mode 100644
index 0000000..0a47d04
--- /dev/null
+++ b/arm-fm-22k/lib_src/eas_data.h
@@ -0,0 +1,131 @@
+/*----------------------------------------------------------------------------
+ *
+ * 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
+
+#include "eas_types.h"
+#include "eas_synthcfg.h"
+#include "eas.h"
+#include "eas_audioconst.h"
+#include "eas_sndlib.h"
+#include "eas_pcm.h"
+#include "eas_pcmdata.h"
+#include "eas_synth.h"
+#include "eas_miditypes.h"
+#include "eas_effects.h"
+
+#ifdef AUX_MIXER
+#include "eas_auxmixdata.h"
+#endif
+
+#ifdef JET_INTERFACE
+#include "jet.h"
+#endif
+
+#ifdef _METRICS_ENABLED
+#include "eas_perf.h"
+#endif
+
+#ifndef MAX_NUMBER_STREAMS
+#define MAX_NUMBER_STREAMS 4
+#endif
+
+/* flags for S_EAS_STREAM */
+#define STREAM_FLAGS_PARSED 1
+#define STREAM_FLAGS_PAUSE 2
+#define STREAM_FLAGS_LOCATE 4
+#define STREAM_FLAGS_RESUME 8
+
+/* structure for parsing a stream */
+typedef struct s_eas_stream_tag
+{
+ void *pParserModule;
+ EAS_U32 time;
+ EAS_U32 frameLength;
+ EAS_I32 repeatCount;
+ EAS_VOID_PTR handle;
+ EAS_U8 volume;
+ EAS_BOOL8 streamFlags;
+} S_EAS_STREAM;
+
+/* default master volume is -10dB */
+#define DEFAULT_VOLUME 90
+#define DEFAULT_STREAM_VOLUME 100
+#define DEFAULT_STREAM_GAIN 14622
+
+/* 10 dB of boost available for individual parsers */
+#define STREAM_VOLUME_HEADROOM 10
+
+/* amalgamated persistent data type */
+typedef struct s_eas_data_tag
+{
+#ifdef _CHECKED_BUILD
+ EAS_U32 handleCheck;
+#endif
+ EAS_HW_DATA_HANDLE hwInstData;
+
+ S_EFFECTS_MODULE effectsModules[NUM_EFFECTS_MODULES];
+
+#ifdef _METRICS_ENABLED
+ S_METRICS_INTERFACE *pMetricsModule;
+ EAS_VOID_PTR pMetricsData;
+#endif
+
+ EAS_I32 *pMixBuffer;
+ EAS_PCM *pOutputAudioBuffer;
+
+#ifdef AUX_MIXER
+ S_EAS_AUX_MIXER auxMixer;
+#endif
+
+#ifdef _MAXIMIZER_ENABLED
+ EAS_VOID_PTR pMaximizerData;
+#endif
+
+ S_EAS_STREAM streams[MAX_NUMBER_STREAMS];
+
+ S_PCM_STATE *pPCMStreams;
+
+ S_VOICE_MGR *pVoiceMgr;
+
+#ifdef JET_INTERFACE
+ JET_DATA_HANDLE jetHandle;
+#endif
+
+ EAS_U32 renderTime;
+ EAS_I16 masterGain;
+ EAS_U8 masterVolume;
+ EAS_BOOL8 staticMemoryModel;
+ EAS_BOOL8 searchHeaderFlag;
+} S_EAS_DATA;
+
+#endif
+
diff --git a/arm-fm-22k/lib_src/eas_effects.h b/arm-fm-22k/lib_src/eas_effects.h
new file mode 100644
index 0000000..01e64c0
--- /dev/null
+++ b/arm-fm-22k/lib_src/eas_effects.h
@@ -0,0 +1,61 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_effects.h
+ *
+ * Contents and purpose:
+ * Defines a generic effects interface.
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 82 $
+ * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $
+ *----------------------------------------------------------------------------
+*/
+
+#ifndef _EAS_EFFECTS_H
+#define _EAS_EFFECTS_H
+
+#include "eas_types.h"
+
+typedef struct
+{
+ EAS_RESULT (*pfInit)(EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData);
+ void (*pfProcess)(EAS_VOID_PTR pInstData, EAS_PCM *in, EAS_PCM *out, EAS_I32 numSamples);
+ EAS_RESULT (*pfShutdown)(EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData);
+ EAS_RESULT (*pFGetParam)(EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue);
+ EAS_RESULT (*pFSetParam)(EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value);
+} S_EFFECTS_INTERFACE;
+
+typedef struct
+{
+ EAS_RESULT (*pfInit)(EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData);
+ void (*pfProcess)(EAS_VOID_PTR pInstData, EAS_I32 *in, EAS_I32 *out, EAS_I32 numSamples);
+ EAS_RESULT (*pfShutdown)(EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData);
+ EAS_RESULT (*pFGetParam)(EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue);
+ EAS_RESULT (*pFSetParam)(EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value);
+} S_EFFECTS32_INTERFACE;
+
+/* mixer instance data */
+typedef struct
+{
+ S_EFFECTS_INTERFACE *effect;
+ EAS_VOID_PTR effectData;
+} S_EFFECTS_MODULE;
+
+#endif /* end _EAS_EFFECTS_H */
+
diff --git a/arm-fm-22k/lib_src/eas_fmengine.c b/arm-fm-22k/lib_src/eas_fmengine.c
new file mode 100644
index 0000000..9c3da66
--- /dev/null
+++ b/arm-fm-22k/lib_src/eas_fmengine.c
@@ -0,0 +1,785 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_fmengine.c
+ *
+ * Contents and purpose:
+ * Implements the low-level FM synthesizer functions.
+ *
+ * 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: 795 $
+ * $Date: 2007-08-01 00:14:45 -0700 (Wed, 01 Aug 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+/* includes */
+#include "eas_types.h"
+#include "eas_math.h"
+#include "eas_audioconst.h"
+#include "eas_fmengine.h"
+
+#if defined(EAS_FM_SYNTH) || defined(EAS_HYBRID_SYNTH) || defined(EAS_SPLIT_HYBRID_SYNTH) || defined(EAS_SPLIT_FM_SYNTH)
+#include "eas_data.h"
+#endif
+
+/* externals */
+extern const EAS_I16 sineTable[];
+extern const EAS_U8 fmScaleTable[16];
+
+// saturation constants for 32-bit to 16-bit conversion
+#define _EAS_MAX_OUTPUT 32767
+#define _EAS_MIN_OUTPUT -32767
+
+static S_FM_ENG_VOICE voices[NUM_FM_VOICES];
+
+/* local prototypes */
+void FM_SynthMixVoice (S_FM_ENG_VOICE *p, EAS_U16 gainTarget, EAS_I32 numSamplesToAdd, EAS_PCM *pInputBuffer, EAS_I32 *pBuffer);
+
+/* used in development environment */
+#if defined(_SATURATION_MONITOR)
+static EAS_BOOL bSaturated = EAS_FALSE;
+
+/*----------------------------------------------------------------------------
+ * FM_CheckSaturation()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Allows the sound development tool to check for saturation at the voice
+ * level. Useful for tuning the level controls.
+ *
+ * Inputs:
+ *
+ * Outputs:
+ * Returns true if saturation has occurred since the last time the function
+ * was called.
+ *
+ * Side Effects:
+ * Resets the saturation flag
+ *----------------------------------------------------------------------------
+*/
+EAS_BOOL FM_CheckSaturation ()
+{
+ EAS_BOOL bTemp;
+ bTemp = bSaturated;
+ bSaturated = EAS_FALSE;
+ return bTemp;
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ * FM_Saturate()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * This inline function saturates a 32-bit number to 16-bits
+ *
+ * Inputs:
+ * psEASData - pointer to overall EAS data structure
+ *
+ * Outputs:
+ * Returns a 16-bit integer
+ *----------------------------------------------------------------------------
+*/
+EAS_INLINE EAS_I16 FM_Saturate (EAS_I32 nValue)
+{
+ if (nValue > _EAS_MAX_OUTPUT)
+ {
+#if defined(_SATURATION_MONITOR)
+ bSaturated = EAS_TRUE;
+#endif
+ return _EAS_MAX_OUTPUT;
+ }
+ if (nValue < _EAS_MIN_OUTPUT)
+ {
+#if defined(_SATURATION_MONITOR)
+ bSaturated = EAS_TRUE;
+#endif
+ return _EAS_MIN_OUTPUT;
+ }
+ return (EAS_I16) nValue;
+}
+
+/*----------------------------------------------------------------------------
+ * FM_Noise()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * A 31-bit low-cost linear congruential PRNG algorithm used to
+ * generate noise.
+ *
+ * Inputs:
+ * pnSeed - pointer to 32-bit PRNG seed
+ *
+ * Outputs:
+ * Returns a 16-bit integer
+ *----------------------------------------------------------------------------
+*/
+EAS_INLINE EAS_I16 FM_Noise (EAS_U32 *pnSeed)
+{
+ *pnSeed = *pnSeed * 214013L + 2531011L;
+ return (EAS_I16) ((*pnSeed >> 15) & 0xffff);
+}
+
+/*----------------------------------------------------------------------------
+ * FM_PhaseInc()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Transform pitch cents to linear phase increment
+ *
+ * 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:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_I32 FM_PhaseInc (EAS_I32 nCents)
+{
+ EAS_I32 nDents;
+ EAS_I32 nExponentInt, nExponentFrac;
+ EAS_I32 nTemp1, nTemp2;
+ EAS_I32 nResult;
+
+ /* convert cents to dents */
+ nDents = FMUL_15x15(nCents, CENTS_TO_DENTS);
+ nExponentInt = GET_DENTS_INT_PART(nDents) + (32 - SINE_TABLE_SIZE_IN_BITS - NUM_EG1_FRAC_BITS);
+ 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;
+}
+
+#if (NUM_OUTPUT_CHANNELS == 2)
+/*----------------------------------------------------------------------------
+ * FM_CalculatePan()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Assign the left and right gain values corresponding to the given pan value.
+ *
+ * Inputs:
+ * psVoice - ptr to the voice we have assigned for this channel
+ * psArticulation - ptr to this voice's articulation
+ * psEASData - pointer to overall EAS data structure
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ * the given voice's m_nGainLeft and m_nGainRight are assigned
+ *----------------------------------------------------------------------------
+*/
+static void FM_CalculatePan (EAS_I16 pan, EAS_U16 *pGainLeft, EAS_U16 *pGainRight)
+{
+ EAS_I32 nTemp;
+ EAS_INT nNetAngle;
+
+ /*
+ Implement the following
+ sin(x) = (2-4*c)*x^2 + c + x
+ cos(x) = (2-4*c)*x^2 + c - x
+
+ where c = 1/sqrt(2)
+ using the a0 + x*(a1 + x*a2) approach
+ */
+
+ /*
+ Get the Midi CC10 pan value for this voice's channel
+ convert the pan value to an "angle" representation suitable for
+ our sin, cos calculator. This representation is NOT necessarily the same
+ as the transform in the GM manuals because of our sin, cos calculator.
+ "angle" = (CC10 - 64)/128
+ */
+ /*lint -e{703} <avoid multiply for performance reasons>*/
+ nNetAngle = ((EAS_I32) pan) << (NUM_EG1_FRAC_BITS -7);
+
+ /* calculate sin */
+ nTemp = EG1_ONE + FMUL_15x15(COEFF_PAN_G2, nNetAngle);
+ nTemp = COEFF_PAN_G0 + FMUL_15x15(nTemp, nNetAngle);
+
+ if (nTemp > SYNTH_FULL_SCALE_EG1_GAIN)
+ nTemp = SYNTH_FULL_SCALE_EG1_GAIN;
+ else if (nTemp < 0)
+ nTemp = 0;
+
+ *pGainRight = (EAS_U16) nTemp;
+
+ /* calculate cos */
+ nTemp = -EG1_ONE + FMUL_15x15(COEFF_PAN_G2, nNetAngle);
+ nTemp = COEFF_PAN_G0 + FMUL_15x15(nTemp, nNetAngle);
+
+ if (nTemp > SYNTH_FULL_SCALE_EG1_GAIN)
+ nTemp = SYNTH_FULL_SCALE_EG1_GAIN;
+ else if (nTemp < 0)
+ nTemp = 0;
+
+ *pGainLeft = (EAS_U16) nTemp;
+}
+#endif /* #if (NUM_OUTPUT_CHANNELS == 2) */
+
+/*----------------------------------------------------------------------------
+ * FM_Operator()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Synthesizes a buffer of samples based on passed parameters.
+ *
+ * Inputs:
+ * nNumSamplesToAdd - number of samples to synthesize
+ * psEASData - pointer to overall EAS data structure
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+void FM_Operator (
+ S_FM_ENG_OPER *p,
+ EAS_I32 numSamplesToAdd,
+ EAS_PCM *pBuffer,
+ EAS_PCM *pModBuffer,
+ EAS_BOOL mix,
+ EAS_U16 gainTarget,
+ EAS_I16 pitch,
+ EAS_U8 feedback,
+ EAS_I16 *pLastOutput)
+{
+ EAS_I32 gain;
+ EAS_I32 gainInc;
+ EAS_U32 phase;
+ EAS_U32 phaseInc;
+ EAS_U32 phaseTemp;
+ EAS_I32 temp;
+ EAS_I32 temp2;
+
+ /* establish local gain variable */
+ gain = (EAS_I32) p->gain << 16;
+
+ /* calculate gain increment */
+ /*lint -e{703} use shift for performance */
+ gainInc = ((EAS_I32) gainTarget - (EAS_I32) p->gain) << (16 - SYNTH_UPDATE_PERIOD_IN_BITS);
+
+ /* establish local phase variables */
+ phase = p->phase;
+
+ /* calculate the new phase increment */
+ phaseInc = (EAS_U32) FM_PhaseInc(pitch);
+
+ /* restore final output from previous frame for feedback loop */
+ if (pLastOutput)
+ temp = *pLastOutput;
+ else
+ temp = 0;
+
+ /* generate a buffer of samples */
+ while (numSamplesToAdd--)
+ {
+
+ /* incorporate modulation */
+ if (pModBuffer)
+ {
+ /*lint -e{701} use shift for performance */
+ temp = *pModBuffer++ << FM_MODULATOR_INPUT_SHIFT;
+ }
+
+ /* incorporate feedback */
+ else
+ {
+ /*lint -e{703} use shift for performance */
+ temp = (temp * (EAS_I32) feedback) << FM_FEEDBACK_SHIFT;
+ }
+
+ /*lint -e{737} <use this behavior to avoid extra mask step> */
+ phaseTemp = phase + temp;
+
+ /* fetch sample from wavetable */
+ temp = sineTable[phaseTemp >> (32 - SINE_TABLE_SIZE_IN_BITS)];
+
+ /* increment operator phase */
+ phase += phaseInc;
+
+ /* internal gain for modulation effects */
+ temp = FMUL_15x15(temp, (gain >> 16));
+
+ /* output gain calculation */
+ temp2 = FMUL_15x15(temp, p->outputGain);
+
+ /* saturating add to buffer */
+ if (mix)
+ {
+ temp2 += *pBuffer;
+ *pBuffer++ = FM_Saturate(temp2);
+ }
+
+ /* output to buffer */
+ else
+ *pBuffer++ = (EAS_I16) temp2;
+
+ /* increment gain */
+ gain += gainInc;
+
+ }
+
+ /* save phase and gain */
+ p->phase = phase;
+ p->gain = gainTarget;
+
+ /* save last output for feedback in next frame */
+ if (pLastOutput)
+ *pLastOutput = (EAS_I16) temp;
+}
+
+/*----------------------------------------------------------------------------
+ * FM_NoiseOperator()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Synthesizes a buffer of samples based on passed parameters.
+ *
+ * Inputs:
+ * nNumSamplesToAdd - number of samples to synthesize
+ * psEASData - pointer to overall EAS data structure
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+void FM_NoiseOperator (
+ S_FM_ENG_OPER *p,
+ EAS_I32 numSamplesToAdd,
+ EAS_PCM *pBuffer,
+ EAS_BOOL mix,
+ EAS_U16 gainTarget,
+ EAS_U8 feedback,
+ EAS_I16 *pLastOutput)
+{
+ EAS_I32 gain;
+ EAS_I32 gainInc;
+ EAS_U32 phase;
+ EAS_I32 temp;
+ EAS_I32 temp2;
+
+ /* establish local gain variable */
+ gain = (EAS_I32) p->gain << 16;
+
+ /* calculate gain increment */
+ /*lint -e{703} use shift for performance */
+ gainInc = ((EAS_I32) gainTarget - (EAS_I32) p->gain) << (16 - SYNTH_UPDATE_PERIOD_IN_BITS);
+
+ /* establish local phase variables */
+ phase = p->phase;
+
+ /* establish local phase variables */
+ phase = p->phase;
+
+ /* recall last sample for filter Z-1 term */
+ temp = 0;
+ if (pLastOutput)
+ temp = *pLastOutput;
+
+ /* generate a buffer of samples */
+ while (numSamplesToAdd--)
+ {
+
+ /* if using filter */
+ if (pLastOutput)
+ {
+ /* use PRNG for noise */
+ temp2 = FM_Noise(&phase);
+
+ /*lint -e{704} use shift for performance */
+ temp += ((temp2 -temp) * feedback) >> 8;
+ }
+ else
+ {
+ temp = FM_Noise(&phase);
+ }
+
+ /* internal gain for modulation effects */
+ temp2 = FMUL_15x15(temp, (gain >> 16));
+
+ /* output gain calculation */
+ temp2 = FMUL_15x15(temp2, p->outputGain);
+
+ /* saturating add to buffer */
+ if (mix)
+ {
+ temp2 += *pBuffer;
+ *pBuffer++ = FM_Saturate(temp2);
+ }
+
+ /* output to buffer */
+ else
+ *pBuffer++ = (EAS_I16) temp2;
+
+ /* increment gain */
+ gain += gainInc;
+
+ }
+
+ /* save phase and gain */
+ p->phase = phase;
+ p->gain = gainTarget;
+
+ /* save last output for feedback in next frame */
+ if (pLastOutput)
+ *pLastOutput = (EAS_I16) temp;
+}
+
+/*----------------------------------------------------------------------------
+ * FM_ConfigVoice()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Receives parameters to start a new voice.
+ *
+ * Inputs:
+ * voiceNum - voice number to start
+ * vCfg - configuration data
+ * pMixBuffer - pointer to host supplied buffer
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ * Notes:
+ * pFrameBuffer is not used in the test version, but is passed as a
+ * courtesy to split architecture implementations. It can be used as
+ * as pointer to the interprocessor communications buffer when the
+ * synthesis parameters are passed off to a DSP for synthesis.
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pFrameBuffer) pFrameBuffer not used in test version - see above */
+void FM_ConfigVoice (EAS_I32 voiceNum, S_FM_VOICE_CONFIG *vCfg, EAS_FRAME_BUFFER_HANDLE pFrameBuffer)
+{
+ S_FM_ENG_VOICE *pVoice;
+ EAS_INT i;
+
+ /* establish pointer to voice data */
+ pVoice = &voices[voiceNum];
+
+ /* save data */
+ pVoice->feedback = vCfg->feedback;
+ pVoice->flags = vCfg->flags;
+ pVoice->voiceGain = vCfg->voiceGain;
+
+ /* initialize Z-1 terms */
+ pVoice->op1Out = 0;
+ pVoice->op3Out = 0;
+
+ /* initialize operators */
+ for (i = 0; i < 4; i++)
+ {
+ /* save operator data */
+ pVoice->oper[i].gain = vCfg->gain[i];
+ pVoice->oper[i].outputGain = vCfg->outputGain[i];
+ pVoice->oper[i].outputGain = vCfg->outputGain[i];
+
+ /* initalize operator */
+ pVoice->oper[i].phase = 0;
+ }
+
+ /* calculate pan */
+#if NUM_OUTPUT_CHANNELS == 2
+ FM_CalculatePan(vCfg->pan, &pVoice->gainLeft, &pVoice->gainRight);
+#endif
+}
+
+/*----------------------------------------------------------------------------
+ * FM_ProcessVoice()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Synthesizes a buffer of samples based on calculated parameters.
+ *
+ * Inputs:
+ * nNumSamplesToAdd - number of samples to synthesize
+ * psEASData - pointer to overall EAS data structure
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ * Notes:
+ * pOut is not used in the test version, but is passed as a
+ * courtesy to split architecture implementations. It can be used as
+ * as pointer to the interprocessor communications buffer when the
+ * synthesis parameters are passed off to a DSP for synthesis.
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pOut) pOut not used in test version - see above */
+void FM_ProcessVoice (
+ EAS_I32 voiceNum,
+ S_FM_VOICE_FRAME *pFrame,
+ EAS_I32 numSamplesToAdd,
+ EAS_PCM *pTempBuffer,
+ EAS_PCM *pBuffer,
+ EAS_I32 *pMixBuffer,
+ EAS_FRAME_BUFFER_HANDLE pFrameBuffer)
+{
+ S_FM_ENG_VOICE *p;
+ EAS_PCM *pOutBuf;
+ EAS_PCM *pMod;
+ EAS_BOOL mix;
+ EAS_U8 feedback1;
+ EAS_U8 feedback3;
+ EAS_U8 mode;
+
+ /* establish pointer to voice data */
+ p = &voices[voiceNum];
+ mode = p->flags & 0x07;
+
+ /* lookup feedback values */
+ feedback1 = fmScaleTable[p->feedback >> 4];
+ feedback3 = fmScaleTable[p->feedback & 0x0f];
+
+ /* operator 3 is on output bus in modes 0, 1, and 3 */
+ if ((mode == 0) || (mode == 1) || (mode == 3))
+ pOutBuf = pBuffer;
+ else
+ pOutBuf = pTempBuffer;
+
+ if (p->flags & FLAG_FM_ENG_VOICE_OP3_NOISE)
+ {
+ FM_NoiseOperator(
+ p->oper + 2,
+ numSamplesToAdd,
+ pOutBuf,
+ EAS_FALSE,
+ pFrame->gain[2],
+ feedback3,
+ &p->op3Out);
+ }
+ else
+ {
+ FM_Operator(
+ p->oper + 2,
+ numSamplesToAdd,
+ pOutBuf,
+ 0,
+ EAS_FALSE,
+ pFrame->gain[2],
+ pFrame->pitch[2],
+ feedback3,
+ &p->op3Out);
+ }
+
+ /* operator 4 is on output bus in modes 0, 1, and 2 */
+ if (mode < 3)
+ pOutBuf = pBuffer;
+ else
+ pOutBuf = pTempBuffer;
+
+ /* operator 4 is modulated in modes 2, 4, and 5 */
+ if ((mode == 2) || (mode == 4) || (mode == 5))
+ pMod = pTempBuffer;
+ else
+ pMod = 0;
+
+ /* operator 4 is in mix mode in modes 0 and 1 */
+ mix = (mode < 2);
+
+ if (p->flags & FLAG_FM_ENG_VOICE_OP4_NOISE)
+ {
+ FM_NoiseOperator(
+ p->oper + 3,
+ numSamplesToAdd,
+ pOutBuf,
+ mix,
+ pFrame->gain[3],
+ 0,
+ 0);
+ }
+ else
+ {
+ FM_Operator(
+ p->oper + 3,
+ numSamplesToAdd,
+ pOutBuf,
+ pMod,
+ mix,
+ pFrame->gain[3],
+ pFrame->pitch[3],
+ 0,
+ 0);
+ }
+
+ /* operator 1 is on output bus in mode 0 */
+ if (mode == 0)
+ pOutBuf = pBuffer;
+ else
+ pOutBuf = pTempBuffer;
+
+ /* operator 1 is modulated in modes 3 and 4 */
+ if ((mode == 3) || (mode == 4))
+ pMod = pTempBuffer;
+ else
+ pMod = 0;
+
+ /* operator 1 is in mix mode in modes 0 and 5 */
+ mix = ((mode == 0) || (mode == 5));
+
+ if (p->flags & FLAG_FM_ENG_VOICE_OP1_NOISE)
+ {
+ FM_NoiseOperator(
+ p->oper,
+ numSamplesToAdd,
+ pOutBuf,
+ mix,
+ pFrame->gain[0],
+ feedback1,
+ &p->op1Out);
+ }
+ else
+ {
+ FM_Operator(
+ p->oper,
+ numSamplesToAdd,
+ pOutBuf,
+ pMod,
+ mix,
+ pFrame->gain[0],
+ pFrame->pitch[0],
+ feedback1,
+ &p->op1Out);
+ }
+
+ /* operator 2 is modulated in all modes except 0 */
+ if (mode != 0)
+ pMod = pTempBuffer;
+ else
+ pMod = 0;
+
+ /* operator 1 is in mix mode in modes 0 -3 */
+ mix = (mode < 4);
+
+ if (p->flags & FLAG_FM_ENG_VOICE_OP2_NOISE)
+ {
+ FM_NoiseOperator(
+ p->oper + 1,
+ numSamplesToAdd,
+ pBuffer,
+ mix,
+ pFrame->gain[1],
+ 0,
+ 0);
+ }
+ else
+ {
+ FM_Operator(
+ p->oper + 1,
+ numSamplesToAdd,
+ pBuffer,
+ pMod,
+ mix,
+ pFrame->gain[1],
+ pFrame->pitch[1],
+ 0,
+ 0);
+ }
+
+ /* mix voice output to synthesizer output buffer */
+ FM_SynthMixVoice(p, pFrame->voiceGain, numSamplesToAdd, pBuffer, pMixBuffer);
+}
+
+/*----------------------------------------------------------------------------
+ * FM_SynthMixVoice()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Mixes the voice output buffer into the final mix using an anti-zipper
+ * filter.
+ *
+ * Inputs:
+ * nNumSamplesToAdd - number of samples to synthesize
+ * psEASData - pointer to overall EAS data structure
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+void FM_SynthMixVoice(S_FM_ENG_VOICE *p, EAS_U16 nGainTarget, EAS_I32 numSamplesToAdd, EAS_PCM *pInputBuffer, EAS_I32 *pBuffer)
+{
+ EAS_I32 nGain;
+ EAS_I32 nGainInc;
+ EAS_I32 nTemp;
+
+ /* restore previous gain */
+ /*lint -e{703} <use shift for performance> */
+ nGain = (EAS_I32) p->voiceGain << 16;
+
+ /* calculate gain increment */
+ /*lint -e{703} <use shift for performance> */
+ nGainInc = ((EAS_I32) nGainTarget - (EAS_I32) p->voiceGain) << (16 - SYNTH_UPDATE_PERIOD_IN_BITS);
+
+ /* mix the output buffer */
+ while (numSamplesToAdd--)
+ {
+ /* output gain calculation */
+ nTemp = *pInputBuffer++;
+
+ /* sum to output buffer */
+#if (NUM_OUTPUT_CHANNELS == 2)
+
+ /*lint -e{704} <use shift for performance> */
+ nTemp = ((EAS_I32) nTemp * (nGain >> 16)) >> FM_GAIN_SHIFT;
+
+ /*lint -e{704} <use shift for performance> */
+ {
+ EAS_I32 nTemp2;
+ nTemp = nTemp >> FM_STEREO_PRE_GAIN_SHIFT;
+ nTemp2 = (nTemp * p->gainLeft) >> FM_STEREO_POST_GAIN_SHIFT;
+ *pBuffer++ += nTemp2;
+ nTemp2 = (nTemp * p->gainRight) >> FM_STEREO_POST_GAIN_SHIFT;
+ *pBuffer++ += nTemp2;
+ }
+#else
+ /*lint -e{704} <use shift for performance> */
+ nTemp = ((EAS_I32) nTemp * (nGain >> 16)) >> FM_MONO_GAIN_SHIFT;
+ *pBuffer++ += nTemp;
+#endif
+
+ /* increment gain for anti-zipper filter */
+ nGain += nGainInc;
+ }
+
+ /* save gain */
+ p->voiceGain = nGainTarget;
+}
+
diff --git a/arm-fm-22k/lib_src/eas_fmengine.h b/arm-fm-22k/lib_src/eas_fmengine.h
new file mode 100644
index 0000000..4ddc12b
--- /dev/null
+++ b/arm-fm-22k/lib_src/eas_fmengine.h
@@ -0,0 +1,121 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_fmengine.h
+ *
+ * Contents and purpose:
+ * Declarations, interfaces, and prototypes for FM synthesize low-level.
+ *
+ * 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: 664 $
+ * $Date: 2007-04-25 13:11:22 -0700 (Wed, 25 Apr 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+/* sentinel */
+#ifndef _FMENGINE_H
+#define _FMENGINE_H
+
+/* check for split architecture */
+#if defined (EAS_SPLIT_HYBRID_SYNTH) || defined(EAS_SPLIT_FM_SYNTH)
+#define FM_OFFBOARD
+#endif
+
+/* output level to mix buffer (3 = -24dB) */
+#define FM_GAIN_SHIFT 3
+#define FM_MONO_GAIN_SHIFT 9
+
+/* voice output level for stereo 15 = +6dB */
+#define FM_STEREO_PRE_GAIN_SHIFT 11
+#define FM_STEREO_POST_GAIN_SHIFT 10
+
+/* modulator input level shift (21 = -30dB) */
+#define FM_MODULATOR_INPUT_SHIFT 21
+
+/* feedback control level shift (7 = 0dB) */
+#define FM_FEEDBACK_SHIFT 7
+
+/* synth final output level */
+#define SYNTH_POST_GAIN_SHIFT 14
+
+/* LFO modulation to gain control */
+#define FM_LFO_GAIN_SHIFT 12
+
+/* sine table is always a power of 2 - saves cycles in inner loop */
+#define SINE_TABLE_SIZE_IN_BITS 11
+#define SINE_TABLE_SIZE 2048
+
+/* operator structure for FM engine */
+typedef struct
+{
+ EAS_U32 phase; /* current waveform phase */
+ EAS_U16 gain; /* current internal gain */
+ EAS_U16 outputGain; /* current output gain */
+} S_FM_ENG_OPER;
+
+typedef struct
+{
+ S_FM_ENG_OPER oper[4]; /* operator data */
+ EAS_I16 op1Out; /* op1 output for feedback loop */
+ EAS_I16 op3Out; /* op3 output for feedback loop */
+ EAS_U16 voiceGain; /* LFO + channel parameters */
+#if (NUM_OUTPUT_CHANNELS == 2)
+ EAS_U16 gainLeft; /* left gain multiplier */
+ EAS_U16 gainRight; /* right gain multiplier */
+#endif
+ EAS_U8 flags; /* mode bits and noise waveform flags */
+ EAS_U8 feedback; /* feedback for Op1 and Op3 */
+} S_FM_ENG_VOICE;
+
+typedef struct
+{
+ EAS_U16 gain[4]; /* initial operator gain value */
+ EAS_U16 outputGain[4]; /* initial operator output gain value */
+ EAS_U16 voiceGain; /* initial voice gain */
+ EAS_U8 flags; /* mode bits and noise waveform flags */
+ EAS_U8 feedback; /* feedback for Op1 and Op3 */
+#if (NUM_OUTPUT_CHANNELS == 2)
+ EAS_I8 pan; /* pan value +/-64 */
+#endif
+} S_FM_VOICE_CONFIG;
+
+typedef struct
+{
+ EAS_U16 gain[4]; /* new operator gain value */
+ EAS_I16 pitch[4]; /* new pitch value */
+ EAS_U16 voiceGain; /* new voice gain */
+} S_FM_VOICE_FRAME;
+
+/* bit definitions for S_FM_ENG_VOICE.flags */
+#define FLAG_FM_ENG_VOICE_OP1_NOISE 0x10 /* operator 1 source is PRNG */
+#define FLAG_FM_ENG_VOICE_OP2_NOISE 0x20 /* operator 2 source is PRNG */
+#define FLAG_FM_ENG_VOICE_OP3_NOISE 0x40 /* operator 3 source is PRNG */
+#define FLAG_FM_ENG_VOICE_OP4_NOISE 0x80 /* operator 4 source is PRNG */
+
+#ifdef FM_OFFBOARD
+extern EAS_BOOL FM_StartFrame (EAS_FRAME_BUFFER_HANDLE pFrameBuffer);
+extern EAS_BOOL FM_EndFrame (EAS_FRAME_BUFFER_HANDLE pFrameBuffe, EAS_I32 *pMixBuffer, EAS_I16 masterGain);
+#endif
+
+/* FM engine prototypes */
+extern void FM_ConfigVoice (EAS_I32 voiceNum, S_FM_VOICE_CONFIG *vCfg, EAS_FRAME_BUFFER_HANDLE pFrameBuffer);
+extern void FM_ProcessVoice (EAS_I32 voiceNum, S_FM_VOICE_FRAME *pFrame, EAS_I32 numSamplesToAdd, EAS_PCM *pTempBuffer, EAS_PCM *pBuffer, EAS_I32 *pMixBuffer, EAS_FRAME_BUFFER_HANDLE pFrameBuffer);
+
+#endif
+/* #ifndef _FMENGINE_H */
+
diff --git a/arm-fm-22k/lib_src/eas_fmsndlib.c b/arm-fm-22k/lib_src/eas_fmsndlib.c
new file mode 100644
index 0000000..bdd063c
--- /dev/null
+++ b/arm-fm-22k/lib_src/eas_fmsndlib.c
@@ -0,0 +1,1674 @@
+/********************************************************************
+ *
+ * fmsndlib.c
+ *
+ * (c) Copyright 2005 Sonic Network, Inc. All Rights Reserved
+
+ * 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.
+ *
+ * Source: C:\Sonic\Source\Gen3.3\FMSynth\GMdblib-3.fml
+ ********************************************************************/
+
+
+#include "eas_data.h"
+
+/* begin region data */
+/*lint -e{651} lint complains about unnecessary brackets */
+const S_FM_REGION regions[] =
+{
+
+ /* Region 0 */
+ {
+ 0x8005, 0, 127, 0, 255, 8, 0,
+ 514, 239, 47, 97, 0, 184, 3,
+ 1, 244, 89, 114, 0, 248, 2,
+ 3370, 244, 49, 76, 40, 192, 2,
+ -1, 227, 97, 51, 160, 212, 2
+ },
+
+ /* Region 1 */
+ {
+ 0x8005, 0, 127, 160, 255, 8, 0,
+ 2514, 223, 95, 72, 0, 176, 3,
+ 1, 244, 73, 145, 0, 244, 2,
+ 3600, 245, 81, 198, 40, 192, 2,
+ 3, 246, 81, 163, 108, 212, 2
+ },
+
+ /* Region 2 */
+ {
+ 0x8005, 0, 127, 160, 255, 119, 0,
+ 0, 216, 79, 72, 0, 216, 2,
+ 2, 244, 73, 145, 0, 244, 2,
+ 3370, 247, 33, 182, 60, 204, 2,
+ 1200, 246, 65, 163, 108, 204, 2
+ },
+
+ /* Region 3 */
+ {
+ 0x8005, 0, 127, 160, 255, 1, 0,
+ 3369, 248, 65, 71, 40, 208, 2,
+ -3, 245, 88, 113, 0, 244, 2,
+ 2784, 225, 65, 133, 80, 192, 2,
+ 3, 241, 81, 113, 80, 216, 2
+ },
+
+ /* Region 4 */
+ {
+ 0x8002, 0, 127, 0, 255, 128, 0,
+ 0, 229, 155, 183, 0, 228, 2,
+ -3, 243, 90, 81, 0, 244, 2,
+ 4800, 248, 109, 180, 36, 192, 2,
+ 3, 245, 90, 85, 16, 244, 2
+ },
+
+ /* Region 5 */
+ {
+ 0x8002, 0, 127, 9, 96, 192, 0,
+ 1200, 229, 157, 180, 0, 216, 2,
+ -3, 244, 90, 81, 0, 244, 2,
+ 1902, 255, 111, 182, 80, 208, 2,
+ 3, 246, 92, 83, 0, 244, 2
+ },
+
+ /* Region 6 */
+ {
+ 0x8002, 0, 127, 0, 255, 154, 0,
+ 3102, 244, 63, 102, 228, 228, 2,
+ 1200, 247, 93, 97, 0, 236, 2,
+ 1902, 255, 63, 98, 156, 220, 2,
+ 1200, 244, 92, 98, 0, 236, 2
+ },
+
+ /* Region 7 */
+ {
+ 0x8005, 0, 127, 0, 255, 202, 0,
+ 0, 251, 131, 19, 216, 220, 2,
+ 1201, 247, 62, 113, 0, 240, 2,
+ 0, 243, 154, 36, 240, 224, 2,
+ 2784, 250, 61, 36, 240, 208, 2
+ },
+
+ /* Region 8 */
+ {
+ 0x8001, 0, 127, 0, 255, 80, 0,
+ -1, 213, 191, 183, 0, 204, 2,
+ 1, 245, 154, 129, 0, 244, 2,
+ 3831, 252, 159, 100, 0, 200, 2,
+ 1197, 246, 91, 182, 0, 244, 2
+ },
+
+ /* Region 9 */
+ {
+ 0x8002, 0, 127, 48, 80, 21, 0,
+ 2982, 255, 43, 96, 0, 196, 3,
+ 3, 247, 71, 130, 0, 244, 2,
+ 3358, 253, 40, 98, 144, 208, 2,
+ -2, 246, 70, 130, 0, 236, 2
+ },
+
+ /* Region 10 */
+ {
+ 0x8002, 0, 127, 48, 80, 26, 0,
+ 3096, 249, 72, 100, 0, 208, 2,
+ 2185, 249, 102, 130, 0, 240, 2,
+ 3386, 247, 66, 100, 144, 212, 2,
+ -2, 247, 102, 130, 0, 240, 2
+ },
+
+ /* Region 11 */
+ {
+ 0x8002, 0, 127, 92, 67, 21, 0,
+ 2982, 255, 27, 146, 0, 200, 3,
+ 3, 246, 68, 146, 0, 240, 2,
+ 3358, 250, 149, 116, 144, 208, 2,
+ -3, 245, 68, 146, 0, 240, 0
+ },
+
+ /* Region 12 */
+ {
+ 0x8002, 0, 127, 0, 67, 0, 0,
+ 1500, 239, 60, 151, 0, 220, 2,
+ 0, 247, 76, 146, 0, 240, 2,
+ 2398, 234, 156, 151, 0, 212, 2,
+ 0, 246, 105, 146, 0, 244, 2
+ },
+
+ /* Region 13 */
+ {
+ 0x8002, 0, 127, 0, 67, 0, 0,
+ 2500, 255, 60, 151, 0, 220, 2,
+ 0, 249, 92, 146, 0, 244, 2,
+ 3369, 250, 156, 151, 0, 196, 2,
+ 0, 248, 89, 146, 0, 244, 2
+ },
+
+ /* Region 14 */
+ {
+ 0x8005, 0, 127, 160, 255, 0, 0,
+ 2300, 229, 112, 49, 0, 208, 2,
+ -3, 247, 67, 50, 0, 248, 2,
+ 1074, 255, 41, 49, 0, 196, 2,
+ 686, 240, 97, 18, 0, 196, 2
+ },
+
+ /* Region 15 */
+ {
+ 0x8005, 0, 127, 160, 255, 219, 0,
+ 3369, 255, 65, 70, 40, 216, 2,
+ 1, 246, 72, 113, 0, 240, 2,
+ 1902, 225, 33, 129, 80, 204, 2,
+ 2400, 225, 97, 113, 80, 200, 2
+ },
+
+ /* Region 16 */
+ {
+ 0x8003, 0, 127, 32, 48, 151, 0,
+ 1201, 215, 35, 66, 252, 208, 0,
+ -9581, 254, 63, 177, 240, 240, 3,
+ 1902, 248, 47, 64, 112, 244, 2,
+ 0, 247, 35, 66, 208, 212, 2
+ },
+
+ /* Region 17 */
+ {
+ 0x8001, 0, 127, 0, 255, 153, 0,
+ 1, 252, 31, 3, 244, 196, 2,
+ -1, 208, 31, 4, 248, 244, 2,
+ 1205, 209, 31, 4, 248, 236, 2,
+ 1899, 250, 31, 32, 0, 240, 2
+ },
+
+ /* Region 18 */
+ {
+ 0x8002, 0, 127, 32, 49, 201, 0,
+ 1, 220, 47, 3, 244, 220, 0,
+ -10000, 208, 63, 1, 248, 240, 3,
+ 1586, 255, 47, 3, 188, 216, 2,
+ -1, 202, 63, 32, 80, 232, 2
+ },
+
+ /* Region 19 */
+ {
+ 0x8001, 0, 127, 0, 143, 29, 0,
+ -1200, 223, 64, 0, 252, 216, 2,
+ 1200, 96, 41, 35, 248, 240, 2,
+ 1200, 143, 41, 64, 252, 224, 2,
+ 3102, 161, 41, 96, 248, 216, 2
+ },
+
+ /* Region 20 */
+ {
+ 0x8002, 0, 127, 0, 143, 34, 0,
+ -1200, 133, 79, 1, 252, 212, 2,
+ 1201, 112, 46, 34, 248, 232, 2,
+ 0, 116, 79, 65, 252, 200, 2,
+ 1900, 161, 46, 98, 248, 232, 2
+ },
+
+ /* Region 21 */
+ {
+ 0x8002, 0, 127, 0, 143, 187, 0,
+ 1202, 80, 74, 1, 252, 216, 2,
+ 2402, 112, 46, 34, 248, 232, 2,
+ 0, 99, 78, 97, 184, 216, 2,
+ 1899, 81, 46, 98, 236, 232, 2
+ },
+
+ /* Region 22 */
+ {
+ 0x8005, 0, 127, 22, 141, 34, 0,
+ 2787, 176, 79, 4, 252, 208, 2,
+ 2785, 144, 45, 34, 248, 236, 2,
+ 3369, 83, 77, 100, 184, 172, 2,
+ 1902, 102, 45, 100, 172, 212, 0
+ },
+
+ /* Region 23 */
+ {
+ 0x8002, 0, 127, 0, 143, 135, 0,
+ 1900, 112, 79, 3, 252, 220, 2,
+ 2400, 128, 45, 34, 248, 232, 2,
+ 1200, 115, 77, 98, 184, 220, 2,
+ 1904, 97, 45, 98, 236, 232, 2
+ },
+
+ /* Region 24 */
+ {
+ 0x8005, 0, 127, 0, 255, 157, 0,
+ 1200, 244, 54, 4, 20, 200, 2,
+ 0, 245, 92, 130, 0, 244, 2,
+ 3802, 247, 68, 21, 0, 196, 2,
+ 1, 245, 43, 114, 0, 204, 2
+ },
+
+ /* Region 25 */
+ {
+ 0x8005, 0, 127, 0, 128, 83, 0,
+ 0, 244, 51, 4, 200, 204, 0,
+ 0, 247, 108, 129, 0, 248, 0,
+ 2786, 243, 31, 70, 200, 220, 0,
+ 1902, 246, 44, 113, 12, 188, 0
+ },
+
+ /* Region 26 */
+ {
+ 0x8005, 0, 127, 0, 128, 61, 0,
+ 0, 246, 51, 97, 76, 204, 0,
+ 0, 244, 60, 97, 0, 240, 0,
+ 1786, 255, 31, 64, 0, 180, 0,
+ 1200, 247, 60, 97, 12, 204, 0
+ },
+
+ /* Region 27 */
+ {
+ 0x8005, 0, 127, 0, 128, 153, 0,
+ -2, 243, 53, 99, 96, 200, 0,
+ 0, 243, 60, 97, 0, 240, 0,
+ 3983, 247, 63, 100, 24, 204, 0,
+ 2, 242, 53, 99, 52, 212, 0
+ },
+
+ /* Region 28 */
+ {
+ 0x8005, 0, 127, 0, 128, 205, 0,
+ -2, 244, 47, 97, 20, 208, 0,
+ 0, 252, 75, 193, 0, 248, 0,
+ 0, 254, 63, 98, 132, 224, 0,
+ 2786, 251, 63, 98, 52, 192, 0
+ },
+
+ /* Region 29 */
+ {
+ 0x8005, 0, 127, 0, 128, 221, 0,
+ -1, 208, 191, 99, 220, 224, 0,
+ 1200, 243, 92, 97, 0, 244, 0,
+ 3984, 212, 11, 96, 168, 196, 0,
+ 1, 242, 127, 98, 108, 204, 0
+ },
+
+ /* Region 30 */
+ {
+ 0x8005, 0, 127, 0, 128, 174, 0,
+ -3, 212, 207, 99, 0, 228, 0,
+ 1902, 241, 108, 97, 0, 248, 0,
+ 3805, 212, 59, 98, 0, 220, 0,
+ 1902, 146, 107, 98, 144, 196, 0
+ },
+
+ /* Region 31 */
+ {
+ 0x8009, 0, 127, 0, 255, 128, 0,
+ 1206, 239, 43, 69, 0, 216, 2,
+ 4, 254, 42, 66, 0, 244, 2,
+ 702, 88, 55, 66, 0, 204, 2,
+ -4, 71, 55, 66, 0, 240, 2
+ },
+
+ /* Region 32 */
+ {
+ 0x8005, 0, 127, 0, 255, 85, 0,
+ 500, 239, 95, 82, 0, 184, 3,
+ 0, 248, 73, 132, 0, 252, 2,
+ 2786, 203, 59, 130, 0, 176, 2,
+ 0, 216, 42, 100, 0, 208, 2
+ },
+
+ /* Region 33 */
+ {
+ 0x8005, 0, 127, 0, 128, 73, 0,
+ 1, 229, 54, 131, 160, 208, 0,
+ -1, 244, 62, 97, 0, 248, 0,
+ 3986, 227, 127, 69, 140, 184, 0,
+ 1201, 249, 92, 114, 0, 204, 0
+ },
+
+ /* Region 34 */
+ {
+ 0x8005, 0, 127, 0, 128, 73, 0,
+ 1, 225, 54, 100, 200, 212, 0,
+ -1, 244, 94, 97, 0, 248, 0,
+ 3986, 249, 127, 88, 112, 188, 0,
+ 1201, 249, 92, 85, 52, 208, 0
+ },
+
+ /* Region 35 */
+ {
+ 0x8005, 0, 127, 0, 128, 188, 0,
+ -3, 198, 92, 179, 28, 212, 0,
+ 0, 243, 90, 145, 0, 248, 0,
+ 1901, 215, 95, 69, 28, 196, 0,
+ 3, 84, 108, 196, 32, 208, 0
+ },
+
+ /* Region 36 */
+ {
+ 0x8005, 0, 127, 0, 136, 6, 0,
+ 0, 226, 99, 36, 224, 216, 0,
+ 1902, 248, 78, 33, 0, 252, 0,
+ 3369, 239, 250, 33, 0, 204, 0,
+ 0, 230, 253, 33, 0, 208, 0
+ },
+
+ /* Region 37 */
+ {
+ 0x8005, 0, 127, 0, 136, 195, 0,
+ 0, 245, 99, 36, 152, 208, 0,
+ 1200, 248, 78, 33, 0, 252, 0,
+ 3369, 246, 250, 33, 0, 216, 0,
+ 0, 246, 61, 33, 0, 180, 0
+ },
+
+ /* Region 38 */
+ {
+ 0x8002, 0, 127, 0, 133, 221, 0,
+ 1, 244, 67, 35, 80, 220, 0,
+ 3, 246, 94, 33, 0, 244, 0,
+ -1, 245, 70, 35, 80, 236, 2,
+ -3, 246, 63, 33, 0, 236, 2
+ },
+
+ /* Region 39 */
+ {
+ 0x8002, 0, 127, 0, 133, 220, 0,
+ 0, 114, 51, 34, 132, 208, 0,
+ 3, 214, 62, 33, 0, 248, 0,
+ 0, 85, 54, 34, 44, 224, 2,
+ -3, 214, 63, 33, 0, 236, 2
+ },
+
+ /* Region 40 */
+ {
+ 0x8005, 0, 127, 48, 142, 187, 0,
+ -1, 33, 22, 33, 200, 208, 0,
+ 0, 81, 105, 33, 220, 240, 0,
+ 2786, 245, 19, 50, 208, 192, 0,
+ 1, 245, 21, 82, 200, 220, 0
+ },
+
+ /* Region 41 */
+ {
+ 0x8005, 0, 127, 48, 126, 103, 0,
+ -1, 193, 22, 33, 228, 212, 0,
+ 0, 81, 105, 33, 220, 244, 0,
+ 0, 245, 19, 50, 216, 228, 0,
+ 1200, 245, 19, 82, 200, 188, 0
+ },
+
+ /* Region 42 */
+ {
+ 0x8005, 0, 127, 16, 126, 202, 0,
+ -1, 49, 24, 41, 200, 212, 0,
+ 0, 81, 71, 49, 220, 244, 0,
+ 3371, 243, 19, 36, 232, 192, 0,
+ 1, 242, 24, 36, 220, 212, 0
+ },
+
+ /* Region 43 */
+ {
+ 0x8005, 0, 127, 16, 124, 205, 0,
+ 0, 129, 24, 49, 208, 200, 0,
+ 0, 67, 102, 81, 224, 244, 0,
+ 3804, 246, 23, 36, 160, 196, 0,
+ 1200, 244, 24, 35, 208, 200, 0
+ },
+
+ /* Region 44 */
+ {
+ 0x8005, 0, 127, 48, 144, 208, 0,
+ -3, 209, 22, 33, 200, 204, 2,
+ 0, 81, 89, 33, 220, 240, 2,
+ -5000, 208, 6, 33, 244, 188, 3,
+ 3, 97, 89, 33, 224, 200, 0
+ },
+
+ /* Region 45 */
+ {
+ 0x8005, 0, 127, 0, 255, 186, 0,
+ 500, 223, 95, 0, 0, 192, 3,
+ 0, 247, 89, 100, 0, 248, 2,
+ 3369, 255, 59, 168, 0, 212, 2,
+ 0, 216, 42, 97, 0, 212, 2
+ },
+
+ /* Region 46 */
+ {
+ 0x8002, 0, 127, 0, 255, 221, 0,
+ 1206, 235, 70, 69, 0, 216, 2,
+ 4, 248, 84, 66, 0, 244, 2,
+ 1902, 247, 52, 137, 80, 216, 2,
+ -4, 245, 84, 131, 0, 240, 2
+ },
+
+ /* Region 47 */
+ {
+ 0x8005, 0, 127, 0, 255, 105, 0,
+ 387, 231, 115, 34, 4, 216, 2,
+ 0, 248, 37, 65, 0, 252, 2,
+ 3308, 248, 117, 34, 8, 200, 2,
+ 1900, 213, 82, 50, 0, 192, 2
+ },
+
+ /* Region 48 */
+ {
+ 0x8002, 0, 127, 32, 160, 221, 0,
+ -7, 209, 22, 33, 200, 204, 2,
+ -7, 81, 73, 33, 220, 244, 0,
+ 7, 209, 22, 33, 200, 208, 0,
+ 7, 97, 73, 33, 224, 244, 2
+ },
+
+ /* Region 49 */
+ {
+ 0x8002, 0, 127, 64, 128, 189, 0,
+ -2, 209, 54, 32, 224, 216, 2,
+ -7726, 97, 105, 33, 220, 240, 3,
+ 1902, 209, 54, 34, 216, 208, 0,
+ 2, 81, 105, 33, 224, 236, 0
+ },
+
+ /* Region 50 */
+ {
+ 0x8002, 0, 127, 80, 144, 206, 0,
+ -3, 179, 38, 33, 160, 220, 2,
+ -7726, 81, 69, 34, 220, 244, 3,
+ 3, 193, 38, 33, 240, 212, 0,
+ -8000, 65, 69, 34, 224, 236, 3
+ },
+
+ /* Region 51 */
+ {
+ 0x8005, 0, 127, 96, 128, 204, 0,
+ -3, 97, 38, 33, 180, 216, 0,
+ 0, 81, 69, 34, 220, 240, 2,
+ 3369, 145, 38, 33, 240, 196, 2,
+ -13190, 65, 69, 34, 240, 200, 3
+ },
+
+ /* Region 52 */
+ {
+ 0x8002, 0, 127, 64, 128, 108, 0,
+ -3, 193, 37, 35, 236, 208, 0,
+ 2394, 97, 90, 36, 224, 232, 2,
+ 3, 65, 40, 35, 236, 204, 2,
+ 1203, 97, 89, 33, 224, 240, 0
+ },
+
+ /* Region 53 */
+ {
+ 0x8005, 0, 127, 128, 128, 122, 0,
+ 0, 193, 21, 34, 236, 188, 0,
+ 3, 97, 74, 36, 224, 248, 2,
+ 1906, 251, 24, 32, 96, 192, 3,
+ 1200, 97, 73, 32, 224, 184, 0
+ },
+
+ /* Region 54 */
+ {
+ 0x8002, 0, 127, 64, 133, 135, 0,
+ 0, 194, 25, 35, 120, 200, 2,
+ 0, 97, 75, 36, 224, 240, 0,
+ 2906, 254, 28, 48, 0, 184, 3,
+ 0, 216, 75, 80, 204, 240, 2
+ },
+
+ /* Region 55 */
+ {
+ 0x8009, 0, 127, 208, 64, 255, 0,
+ 475, 249, 16, 32, 252, 240, 2,
+ 702, 248, 71, 32, 0, 244, 2,
+ 1136, 232, 27, 32, 216, 248, 0,
+ 0, 249, 23, 48, 0, 248, 2
+ },
+
+ /* Region 56 */
+ {
+ 0x8005, 0, 127, 0, 132, 233, 0,
+ 0, 195, 95, 64, 240, 208, 0,
+ 0, 225, 94, 64, 248, 240, 0,
+ 0, 254, 127, 0, 4, 196, 4,
+ 1902, 228, 95, 1, 248, 200, 0
+ },
+
+ /* Region 57 */
+ {
+ 0x8005, 0, 127, 16, 140, 238, 0,
+ 0, 163, 90, 67, 228, 208, 0,
+ 0, 209, 77, 65, 248, 240, 0,
+ 1969, 173, 58, 65, 0, 176, 0,
+ 0, 210, 61, 52, 204, 220, 0
+ },
+
+ /* Region 58 */
+ {
+ 0x8005, 0, 127, 16, 140, 222, 0,
+ 0, 119, 74, 67, 160, 212, 0,
+ 0, 146, 61, 65, 248, 244, 0,
+ 1900, 137, 58, 65, 100, 196, 0,
+ 0, 119, 61, 52, 120, 200, 0
+ },
+
+ /* Region 59 */
+ {
+ 0x8005, 0, 127, 16, 135, 219, 0,
+ 0, 176, 79, 69, 240, 216, 0,
+ 0, 193, 79, 64, 248, 236, 0,
+ 0, 178, 123, 54, 92, 228, 0,
+ 3369, 212, 95, 38, 144, 212, 0
+ },
+
+ /* Region 60 */
+ {
+ 0x8002, 0, 127, 0, 119, 203, 0,
+ 2, 65, 77, 66, 228, 204, 0,
+ 2, 161, 74, 64, 240, 240, 0,
+ -2, 85, 60, 66, 180, 216, 2,
+ -2, 162, 74, 64, 220, 240, 2
+ },
+
+ /* Region 61 */
+ {
+ 0x8002, 0, 127, 16, 154, 237, 0,
+ 0, 179, 42, 64, 216, 208, 0,
+ 0, 209, 61, 64, 248, 244, 0,
+ -1200, 226, 55, 65, 244, 220, 2,
+ 1902, 162, 62, 52, 204, 236, 2
+ },
+
+ /* Region 62 */
+ {
+ 0x8002, 0, 127, 48, 119, 221, 0,
+ 2, 119, 79, 64, 208, 212, 0,
+ 2, 209, 110, 64, 248, 236, 0,
+ -2, 84, 79, 64, 136, 212, 2,
+ -2, 209, 110, 64, 240, 240, 2
+ },
+
+ /* Region 63 */
+ {
+ 0x8002, 0, 127, 32, 135, 221, 0,
+ 2, 165, 79, 64, 152, 216, 0,
+ 2, 225, 110, 64, 248, 236, 0,
+ -2, 132, 79, 64, 72, 224, 2,
+ -2, 241, 110, 64, 252, 236, 2
+ },
+
+ /* Region 64 */
+ {
+ 0x8005, 0, 127, 17, 127, 190, 0,
+ 0, 209, 60, 67, 244, 208, 0,
+ 1200, 145, 94, 65, 248, 244, 2,
+ 3369, 197, 47, 4, 128, 192, 0,
+ 1902, 167, 94, 6, 200, 200, 0
+ },
+
+ /* Region 65 */
+ {
+ 0x8005, 0, 127, 17, 143, 190, 0,
+ 0, 209, 60, 67, 244, 216, 0,
+ 1902, 145, 62, 65, 248, 240, 2,
+ 3369, 197, 47, 4, 128, 196, 0,
+ 2400, 167, 94, 6, 200, 212, 2
+ },
+
+ /* Region 66 */
+ {
+ 0x8005, 0, 127, 17, 143, 190, 0,
+ 0, 209, 60, 67, 244, 208, 0,
+ 1902, 145, 62, 65, 248, 240, 2,
+ 3369, 197, 47, 4, 128, 192, 0,
+ 1902, 167, 94, 6, 200, 216, 2
+ },
+
+ /* Region 67 */
+ {
+ 0x8005, 0, 127, 17, 125, 190, 0,
+ 0, 114, 109, 67, 244, 224, 0,
+ 1902, 166, 93, 97, 200, 240, 0,
+ 2786, 165, 95, 52, 160, 200, 0,
+ 2400, 173, 78, 54, 240, 212, 2
+ },
+
+ /* Region 68 */
+ {
+ 0x8002, 0, 127, 16, 140, 205, 0,
+ 0, 211, 55, 66, 244, 208, 0,
+ 1902, 193, 93, 65, 248, 240, 0,
+ 0, 204, 47, 4, 244, 216, 0,
+ 3600, 183, 95, 6, 160, 232, 0
+ },
+
+ /* Region 69 */
+ {
+ 0x8002, 0, 127, 16, 126, 222, 0,
+ 0, 243, 36, 66, 172, 200, 0,
+ 1200, 193, 110, 67, 248, 244, 0,
+ 0, 215, 33, 2, 232, 212, 0,
+ 3369, 178, 63, 6, 184, 240, 0
+ },
+
+ /* Region 70 */
+ {
+ 0x8002, 0, 127, 16, 140, 221, 0,
+ 1200, 213, 61, 66, 136, 200, 0,
+ 1902, 193, 93, 68, 248, 240, 0,
+ 0, 197, 47, 2, 228, 216, 0,
+ 3369, 183, 95, 2, 160, 236, 0
+ },
+
+ /* Region 71 */
+ {
+ 0x8002, 0, 127, 16, 124, 201, 0,
+ 1200, 195, 55, 68, 240, 208, 0,
+ 0, 209, 76, 65, 248, 236, 0,
+ 1902, 147, 47, 19, 208, 212, 0,
+ 0, 183, 79, 22, 156, 228, 0
+ },
+
+ /* Region 72 */
+ {
+ 0x8005, 0, 127, 32, 110, 234, 0,
+ 500, 237, 60, 68, 0, 192, 1,
+ 1, 161, 93, 65, 248, 240, 2,
+ 3365, 154, 47, 16, 48, 180, 6,
+ 1200, 165, 92, 52, 160, 212, 2
+ },
+
+ /* Region 73 */
+ {
+ 0x8005, 0, 127, 32, 142, 200, 0,
+ 0, 193, 60, 68, 248, 200, 0,
+ 1, 129, 61, 65, 248, 240, 2,
+ 3365, 154, 47, 16, 68, 184, 6,
+ 1200, 169, 92, 52, 160, 204, 2
+ },
+
+ /* Region 74 */
+ {
+ 0x8003, 0, 127, 32, 135, 36, 0,
+ 1199, 165, 79, 66, 152, 192, 2,
+ -3, 145, 110, 64, 248, 240, 2,
+ 0, 199, 79, 66, 44, 236, 2,
+ 2986, 136, 110, 67, 100, 196, 2
+ },
+
+ /* Region 75 */
+ {
+ 0x8005, 0, 127, 32, 190, 71, 0,
+ 868, 202, 140, 16, 24, 188, 2,
+ 0, 176, 77, 65, 248, 240, 2,
+ 3750, 169, 127, 16, 36, 228, 6,
+ 2400, 195, 60, 17, 232, 172, 2
+ },
+
+ /* Region 76 */
+ {
+ 0x8005, 0, 127, 224, 16, 123, 0,
+ 275, 202, 14, 2, 44, 196, 2,
+ 0, 165, 89, 65, 56, 244, 2,
+ 0, 255, 12, 2, 64, 216, 6,
+ 963, 169, 14, 4, 40, 196, 2
+ },
+
+ /* Region 77 */
+ {
+ 0x8012, 0, 127, 192, 128, 100, 0,
+ 1500, 202, 79, 68, 76, 204, 2,
+ -2, 97, 26, 64, 248, 232, 2,
+ 1588, 202, 223, 69, 4, 220, 0,
+ 3, 188, 121, 67, 48, 252, 2
+ },
+
+ /* Region 78 */
+ {
+ 0x8002, 0, 127, 112, 140, 205, 0,
+ 0, 68, 47, 66, 60, 176, 2,
+ -2, 113, 94, 64, 248, 236, 0,
+ 5000, 121, 47, 64, 32, 168, 7,
+ 3, 136, 94, 64, 0, 236, 0
+ },
+
+ /* Region 79 */
+ {
+ 0x8003, 0, 127, 32, 135, 33, 0,
+ 1199, 197, 79, 66, 152, 184, 2,
+ 0, 161, 110, 64, 248, 240, 2,
+ 0, 199, 79, 66, 44, 236, 2,
+ 2400, 255, 110, 65, 36, 208, 6
+ },
+
+ /* Region 80 */
+ {
+ 0x8002, 0, 127, 0, 192, 170, 0,
+ 1199, 192, 77, 33, 200, 212, 0,
+ 0, 209, 107, 33, 232, 240, 0,
+ 1201, 80, 77, 33, 200, 212, 0,
+ 0, 241, 107, 33, 232, 240, 0
+ },
+
+ /* Region 81 */
+ {
+ 0x8002, 0, 127, 0, 192, 221, 0,
+ -1, 192, 45, 33, 200, 212, 0,
+ -1, 209, 107, 33, 232, 244, 0,
+ 1, 80, 45, 33, 200, 212, 0,
+ 1, 241, 107, 33, 232, 244, 0
+ },
+
+ /* Region 82 */
+ {
+ 0x8005, 0, 127, 0, 112, 255, 0,
+ 4750, 221, 45, 34, 48, 172, 4,
+ -10000, 161, 107, 33, 200, 244, 3,
+ 2204, 137, 45, 37, 64, 184, 0,
+ -2, 211, 107, 33, 160, 208, 0
+ },
+
+ /* Region 83 */
+ {
+ 0x8005, 0, 127, 16, 127, 238, 0,
+ 2, 248, 45, 32, 204, 208, 0,
+ -9500, 241, 107, 33, 200, 240, 3,
+ 3369, 186, 45, 38, 24, 208, 0,
+ -2, 211, 107, 32, 220, 212, 0
+ },
+
+ /* Region 84 */
+ {
+ 0x8005, 0, 127, 0, 128, 221, 0,
+ -1, 192, 191, 99, 220, 216, 0,
+ 1200, 243, 92, 97, 0, 244, 0,
+ 3984, 200, 11, 96, 168, 192, 0,
+ 1, 194, 127, 98, 108, 200, 0
+ },
+
+ /* Region 85 */
+ {
+ 0x8002, 0, 127, 128, 128, 111, 0,
+ 1, 194, 25, 35, 120, 204, 2,
+ -9750, 193, 107, 36, 224, 244, 3,
+ 3906, 255, 28, 50, 12, 188, 3,
+ -1, 216, 107, 80, 204, 240, 2
+ },
+
+ /* Region 86 */
+ {
+ 0x8002, 0, 127, 32, 134, 222, 0,
+ 0, 195, 52, 33, 200, 208, 0,
+ 0, 177, 90, 33, 232, 240, 2,
+ 702, 195, 52, 33, 200, 208, 2,
+ 702, 177, 90, 34, 232, 240, 2
+ },
+
+ /* Region 87 */
+ {
+ 0x8002, 0, 127, 32, 134, 205, 0,
+ 0, 198, 75, 36, 120, 220, 2,
+ 0, 225, 78, 52, 40, 244, 2,
+ 0, 246, 47, 32, 220, 208, 2,
+ 1902, 241, 124, 32, 240, 236, 2
+ },
+
+ /* Region 88 */
+ {
+ 0x8003, 0, 127, 32, 120, 14, 0,
+ 3600, 244, 67, 34, 88, 208, 0,
+ 3, 194, 84, 33, 84, 240, 2,
+ -3, 194, 84, 33, 172, 236, 2,
+ 902, 254, 114, 34, 0, 224, 3
+ },
+
+ /* Region 89 */
+ {
+ 0x8002, 0, 127, 64, 169, 170, 0,
+ -3, 83, 69, 34, 184, 212, 0,
+ -7500, 50, 69, 33, 176, 244, 3,
+ 3, 81, 69, 34, 212, 212, 2,
+ -8500, 66, 69, 33, 176, 244, 3
+ },
+
+ /* Region 90 */
+ {
+ 0x8002, 0, 127, 64, 120, 221, 0,
+ -2, 82, 69, 34, 244, 216, 0,
+ 0, 145, 102, 33, 228, 240, 0,
+ 2, 81, 69, 34, 244, 208, 2,
+ 0, 145, 102, 33, 224, 240, 2
+ },
+
+ /* Region 91 */
+ {
+ 0x8003, 0, 127, 32, 138, 14, 0,
+ 2400, 148, 67, 34, 176, 200, 0,
+ 3, 194, 85, 33, 220, 236, 2,
+ -3, 194, 69, 33, 220, 236, 2,
+ 1905, 254, 114, 34, 48, 224, 2
+ },
+
+ /* Region 92 */
+ {
+ 0x8002, 0, 127, 82, 67, 71, 0,
+ 2982, 228, 22, 146, 88, 192, 3,
+ 3, 102, 84, 146, 196, 240, 2,
+ 3358, 50, 149, 116, 144, 208, 2,
+ -3, 85, 84, 146, 120, 240, 0
+ },
+
+ /* Region 93 */
+ {
+ 0x8005, 0, 127, 48, 126, 219, 0,
+ -3, 49, 19, 33, 120, 200, 0,
+ 0, 81, 70, 33, 220, 240, 0,
+ 3804, 242, 18, 50, 200, 200, 0,
+ 1203, 82, 19, 82, 200, 176, 0
+ },
+
+ /* Region 94 */
+ {
+ 0x8003, 0, 127, 32, 138, 13, 0,
+ 2786, 116, 67, 34, 204, 184, 0,
+ 1902, 114, 69, 33, 192, 232, 2,
+ -3, 178, 69, 33, 188, 232, 2,
+ 3804, 254, 82, 34, 164, 228, 2
+ },
+
+ /* Region 95 */
+ {
+ 0x8002, 0, 127, 48, 135, 238, 0,
+ -2, 34, 85, 34, 184, 224, 0,
+ 1, 113, 70, 33, 228, 236, 0,
+ 2, 19, 85, 34, 156, 224, 2,
+ -1, 129, 70, 33, 224, 236, 2
+ },
+
+ /* Region 96 */
+ {
+ 0x8012, 0, 127, 240, 112, 221, 0,
+ 3369, 213, 69, 32, 0, 204, 0,
+ 0, 193, 70, 33, 112, 232, 2,
+ 0, 145, 69, 34, 244, 208, 2,
+ -9000, 145, 70, 33, 224, 236, 3
+ },
+
+ /* Region 97 */
+ {
+ 0x8002, 0, 127, 96, 122, 168, 0,
+ -1, 99, 51, 33, 200, 208, 0,
+ -8500, 81, 83, 33, 232, 240, 3,
+ 702, 99, 52, 33, 200, 208, 2,
+ -9500, 65, 83, 34, 224, 240, 3
+ },
+
+ /* Region 98 */
+ {
+ 0x8002, 0, 127, 0, 67, 0, 0,
+ 1500, 217, 55, 151, 20, 224, 2,
+ 3, 231, 70, 146, 88, 220, 2,
+ 2369, 115, 148, 151, 32, 196, 2,
+ -3, 118, 36, 146, 64, 244, 2
+ },
+
+ /* Region 99 */
+ {
+ 0x8002, 0, 127, 64, 169, 204, 0,
+ -3, 228, 69, 34, 148, 220, 0,
+ -7448, 243, 69, 33, 200, 240, 3,
+ 3, 81, 68, 34, 212, 212, 2,
+ -8526, 65, 68, 33, 196, 240, 3
+ },
+
+ /* Region 100 */
+ {
+ 0x8002, 0, 127, 64, 119, 187, 0,
+ 2786, 228, 22, 146, 176, 192, 0,
+ 3, 102, 68, 146, 196, 236, 2,
+ 3369, 178, 149, 116, 176, 208, 2,
+ -3, 231, 68, 146, 120, 240, 0
+ },
+
+ /* Region 101 */
+ {
+ 0x8002, 0, 127, 240, 144, 239, 0,
+ -2, 49, 69, 34, 236, 208, 2,
+ -9000, 113, 102, 33, 228, 236, 3,
+ 2400, 149, 69, 34, 12, 216, 1,
+ 0, 145, 102, 33, 224, 236, 2
+ },
+
+ /* Region 102 */
+ {
+ 0x8012, 0, 127, 241, 176, 6, 0,
+ 1200, 247, 49, 64, 252, 204, 0,
+ 3804, 246, 101, 32, 0, 232, 2,
+ 1902, 247, 32, 32, 112, 188, 2,
+ 0, 228, 84, 32, 0, 240, 2
+ },
+
+ /* Region 103 */
+ {
+ 0x8005, 0, 127, 64, 101, 221, 0,
+ 1, 194, 68, 97, 196, 200, 2,
+ -10001, 247, 100, 114, 176, 240, 3,
+ 3370, 213, 33, 70, 52, 200, 2,
+ -1, 178, 68, 49, 208, 212, 0
+ },
+
+ /* Region 104 */
+ {
+ 0x8002, 0, 127, 0, 255, 203, 0,
+ -3, 245, 82, 99, 200, 232, 2,
+ 2787, 244, 84, 96, 0, 236, 2,
+ 1198, 133, 81, 100, 196, 220, 2,
+ 1902, 147, 67, 80, 0, 232, 2
+ },
+
+ /* Region 105 */
+ {
+ 0x8005, 0, 127, 0, 255, 140, 0,
+ 500, 255, 137, 179, 0, 200, 3,
+ 1902, 248, 90, 160, 0, 244, 2,
+ 3804, 245, 57, 35, 164, 204, 2,
+ 0, 245, 38, 51, 196, 208, 2
+ },
+
+ /* Region 106 */
+ {
+ 0x8005, 0, 127, 0, 255, 72, 0,
+ 1000, 238, 57, 65, 0, 188, 3,
+ 1902, 247, 103, 112, 0, 244, 2,
+ 2786, 250, 36, 81, 68, 212, 2,
+ 0, 249, 50, 49, 172, 204, 2
+ },
+
+ /* Region 107 */
+ {
+ 0x8005, 0, 127, 16, 119, 72, 0,
+ 1500, 255, 89, 65, 0, 196, 3,
+ 2790, 246, 39, 112, 0, 240, 0,
+ 1905, 246, 36, 81, 168, 208, 0,
+ 0, 249, 114, 49, 172, 212, 0
+ },
+
+ /* Region 108 */
+ {
+ 0x8005, 0, 127, 0, 255, 237, 0,
+ 1902, 254, 89, 65, 0, 212, 2,
+ 0, 248, 87, 112, 0, 240, 2,
+ 3369, 231, 62, 81, 0, 208, 2,
+ 3, 245, 118, 49, 96, 196, 2
+ },
+
+ /* Region 109 */
+ {
+ 0x8002, 0, 127, 16, 188, 205, 0,
+ -2, 179, 47, 50, 244, 224, 2,
+ 1900, 145, 94, 49, 248, 232, 2,
+ 3, 210, 46, 2, 244, 208, 2,
+ 2789, 133, 93, 4, 180, 244, 2
+ },
+
+ /* Region 110 */
+ {
+ 0x8005, 0, 127, 48, 135, 220, 0,
+ 1901, 162, 25, 35, 144, 208, 0,
+ 0, 113, 105, 65, 220, 240, 0,
+ 3369, 233, 88, 51, 120, 212, 0,
+ 0, 229, 24, 84, 200, 208, 0
+ },
+
+ /* Region 111 */
+ {
+ 0x8002, 0, 127, 112, 32, 190, 0,
+ 0, 53, 79, 66, 152, 212, 2,
+ 1200, 53, 75, 64, 136, 244, 2,
+ 500, 149, 60, 66, 16, 208, 2,
+ 1902, 200, 78, 64, 0, 248, 0
+ },
+
+ /* Region 112 */
+ {
+ 0x8005, 0, 127, 0, 144, 130, 0,
+ 2514, 255, 68, 53, 0, 204, 2,
+ 2400, 247, 133, 48, 0, 240, 2,
+ 4151, 243, 67, 50, 0, 212, 2,
+ 3369, 243, 66, 56, 0, 204, 2
+ },
+
+ /* Region 113 */
+ {
+ 0x8005, 0, 127, 0, 255, 0, 0,
+ 514, 253, 79, 51, 0, 196, 3,
+ 1905, 252, 89, 51, 0, 244, 2,
+ 4349, 245, 35, 51, 0, 208, 2,
+ 1205, 247, 34, 51, 0, 208, 2
+ },
+
+ /* Region 114 */
+ {
+ 0x8005, 0, 127, 0, 255, 0, 0,
+ 514, 221, 69, 35, 0, 204, 3,
+ 0, 250, 86, 115, 0, 252, 2,
+ 1884, 244, 116, 51, 0, 200, 2,
+ 1208, 210, 35, 51, 0, 208, 2
+ },
+
+ /* Region 115 */
+ {
+ 0x8005, 0, 127, 0, 255, 16, 0,
+ 514, 222, 85, 163, 0, 192, 3,
+ 0, 254, 108, 163, 0, 252, 2,
+ 3800, 255, 143, 160, 0, 176, 2,
+ 1200, 250, 105, 163, 0, 212, 2
+ },
+
+ /* Region 116 */
+ {
+ 0x8005, 0, 127, 0, 255, 16, 0,
+ 1514, 249, 101, 163, 0, 204, 3,
+ -1200, 249, 87, 160, 0, 252, 2,
+ 0, 235, 143, 160, 0, 204, 2,
+ 1200, 234, 73, 163, 0, 204, 2
+ },
+
+ /* Region 117 */
+ {
+ 0x8005, 0, 127, 0, 255, 16, 0,
+ 500, 239, 101, 160, 0, 204, 3,
+ -1195, 248, 104, 160, 0, 252, 2,
+ 1898, 252, 72, 163, 0, 216, 2,
+ 1239, 248, 87, 163, 0, 196, 2
+ },
+
+ /* Region 118 */
+ {
+ 0x8005, 0, 127, 0, 255, 255, 0,
+ 500, 255, 98, 160, 0, 196, 3,
+ -1, 249, 105, 160, 0, 252, 2,
+ 1907, 250, 71, 160, 0, 252, 2,
+ 1182, 249, 87, 161, 0, 192, 2
+ },
+
+ /* Region 119 */
+ {
+ 0x8005, 0, 127, 0, 0, 100, 0,
+ 600, 32, 15, 0, 252, 224, 6,
+ 0, 47, 111, 65, 0, 244, 2,
+ 1826, 16, 47, 0, 252, 216, 2,
+ 3551, 240, 47, 0, 252, 212, 2
+ },
+
+ /* Region 120 */
+ {
+ 0x8014, 0, 127, 240, 128, 235, 0,
+ 1228, 161, 47, 17, 196, 200, 3,
+ 3000, 123, 75, 17, 0, 240, 2,
+ 7022, 72, 43, 17, 0, 216, 0,
+ 4000, 150, 79, 17, 48, 196, 3
+ },
+
+ /* Region 121 */
+ {
+ 0x8005, 0, 127, 224, 16, 86, 0,
+ 275, 251, 6, 0, 36, 200, 2,
+ 0, 101, 104, 65, 56, 240, 2,
+ 0, 240, 6, 0, 252, 208, 6,
+ 1000, 195, 8, 0, 248, 200, 2
+ },
+
+ /* Region 122 */
+ {
+ 0x8002, 0, 127, 0, 0, 185, 0,
+ 600, 35, 66, 17, 72, 224, 4,
+ -13000, 81, 67, 17, 228, 244, 2,
+ 702, 97, 38, 17, 212, 196, 6,
+ -14000, 81, 65, 17, 224, 244, 3
+ },
+
+ /* Region 123 */
+ {
+ 0x8012, 0, 127, 240, 112, 237, 0,
+ -6528, 153, 127, 16, 0, 252, 3,
+ 1200, 105, 109, 16, 0, 216, 2,
+ -6022, 179, 139, 17, 0, 248, 3,
+ 2000, 104, 79, 17, 0, 240, 0
+ },
+
+ /* Region 124 */
+ {
+ 0x8012, 0, 127, 240, 240, 16, 0,
+ 1914, 240, 64, 160, 240, 208, 2,
+ 1200, 240, 73, 163, 240, 244, 0,
+ 1900, 240, 64, 160, 240, 148, 2,
+ 4151, 240, 73, 163, 240, 244, 0
+ },
+
+ /* Region 125 */
+ {
+ 0x8002, 0, 127, 240, 56, 235, 0,
+ -5522, 97, 32, 17, 196, 240, 3,
+ 0, 84, 75, 17, 180, 248, 3,
+ 702, 65, 38, 17, 224, 212, 6,
+ -4000, 161, 73, 17, 224, 252, 1
+ },
+
+ /* Region 126 */
+ {
+ 0x8015, 0, 127, 240, 248, 37, 0,
+ 1050, 243, 0, 0, 252, 224, 7,
+ 2000, 49, 68, 0, 224, 236, 3,
+ 350, 240, 0, 0, 252, 216, 1,
+ 700, 240, 0, 0, 252, 212, 3
+ },
+
+ /* Region 127 */
+ {
+ 0x8015, 0, 127, 240, 248, 37, 0,
+ 1050, 245, 85, 0, 0, 244, 7,
+ -5000, 247, 71, 0, 0, 252, 3,
+ 350, 240, 0, 0, 0, 164, 0,
+ 700, 32, 0, 0, 0, 252, 2
+ },
+
+ /* Region 128 */
+ {
+ 0x0005, 35, 35, 0, 255, 103, 0,
+ 3, 215, 68, 65, 0, 204, 2,
+ -1700, 249, 95, 177, 0, 252, 2,
+ 5374, 236, 144, 204, 0, 176, 3,
+ 114, 253, 144, 179, 0, 200, 3
+ },
+
+ /* Region 129 */
+ {
+ 0x0005, 36, 36, 0, 255, 103, 0,
+ 3, 219, 68, 65, 0, 204, 2,
+ -1700, 251, 95, 177, 0, 252, 2,
+ 5374, 255, 144, 204, 0, 176, 3,
+ 114, 255, 144, 179, 0, 208, 3
+ },
+
+ /* Region 130 */
+ {
+ 0x001a, 37, 37, 240, 128, 216, 0,
+ 2780, 255, 16, 0, 112, 200, 3,
+ 3800, 255, 32, 0, 0, 240, 3,
+ 2501, 251, 48, 0, 48, 240, 3,
+ 2751, 254, 48, 0, 0, 244, 3
+ },
+
+ /* Region 131 */
+ {
+ 0x000d, 38, 38, 0, 255, 190, 0,
+ -2000, 239, 48, 128, 0, 236, 3,
+ -2400, 254, 92, 128, 0, 252, 2,
+ 3374, 255, 33, 192, 240, 244, 2,
+ 1000, 255, 49, 176, 240, 204, 2
+ },
+
+ /* Region 132 */
+ {
+ 0x001a, 39, 39, 240, 128, 254, -10,
+ 5780, 186, 16, 0, 112, 240, 3,
+ 3800, 254, 32, 0, 0, 248, 3,
+ 5780, 234, 16, 0, 112, 240, 3,
+ 4829, 254, 32, 0, 0, 252, 3
+ },
+
+ /* Region 133 */
+ {
+ 0x000d, 40, 40, 0, 255, 203, 0,
+ 0, 254, 74, 128, 0, 176, 3,
+ -600, 252, 73, 128, 0, 252, 3,
+ 3368, 251, 80, 192, 0, 244, 3,
+ 1200, 254, 64, 176, 0, 208, 3
+ },
+
+ /* Region 134 */
+ {
+ 0x000d, 41, 41, 208, 16, 187, -30,
+ -600, 247, 128, 0, 0, 204, 1,
+ -890, 248, 88, 0, 0, 252, 3,
+ 1068, 250, 182, 0, 0, 200, 3,
+ -100, 249, 116, 0, 0, 208, 3
+ },
+
+ /* Region 135 */
+ {
+ 0x0005, 42, 42, 160, 255, 126, 20,
+ 3514, 247, 23, 72, 0, 212, 3,
+ 400, 255, 94, 177, 0, 232, 2,
+ 2347, 250, 47, 0, 196, 184, 6,
+ 4388, 248, 26, 0, 136, 224, 2
+ },
+
+ /* Region 136 */
+ {
+ 0x000d, 43, 43, 208, 16, 187, -20,
+ -500, 247, 128, 0, 0, 204, 1,
+ -690, 249, 88, 0, 0, 252, 3,
+ 1068, 254, 182, 0, 0, 200, 3,
+ 0, 249, 116, 0, 0, 208, 3
+ },
+
+ /* Region 137 */
+ {
+ 0x0005, 44, 44, 160, 255, 126, 20,
+ 3514, 151, 20, 72, 0, 244, 3,
+ 400, 223, 92, 177, 0, 240, 2,
+ 2347, 134, 34, 0, 176, 208, 6,
+ 4388, 200, 21, 0, 100, 220, 2
+ },
+
+ /* Region 138 */
+ {
+ 0x000d, 45, 45, 208, 16, 187, -10,
+ -350, 246, 128, 0, 0, 204, 1,
+ -590, 249, 88, 0, 0, 252, 3,
+ 2368, 254, 182, 0, 0, 196, 3,
+ 500, 249, 116, 0, 0, 208, 3
+ },
+
+ /* Region 139 */
+ {
+ 0x0005, 46, 46, 160, 255, 126, 20,
+ 3510, 147, 51, 72, 0, 236, 3,
+ 400, 219, 90, 177, 0, 240, 2,
+ 2347, 134, 66, 0, 176, 224, 6,
+ 4388, 200, 84, 0, 100, 212, 2
+ },
+
+ /* Region 140 */
+ {
+ 0x000d, 47, 47, 176, 32, 187, 10,
+ 0, 247, 128, 0, 0, 204, 1,
+ -280, 249, 88, 0, 0, 252, 3,
+ 2968, 255, 182, 0, 0, 200, 3,
+ 700, 250, 116, 0, 0, 204, 3
+ },
+
+ /* Region 141 */
+ {
+ 0x000d, 48, 48, 0, 255, 187, 20,
+ 10, 247, 128, 0, 0, 204, 3,
+ -130, 249, 88, 0, 0, 252, 3,
+ 3068, 255, 182, 0, 0, 188, 3,
+ 800, 250, 116, 0, 0, 204, 3
+ },
+
+ /* Region 142 */
+ {
+ 0x000d, 49, 49, 160, 255, 215, 20,
+ 3986, 18, 6, 8, 0, 252, 2,
+ 0, 247, 70, 1, 0, 240, 2,
+ 5354, 242, 48, 0, 252, 216, 2,
+ 3868, 193, 48, 0, 212, 208, 2
+ },
+
+ /* Region 143 */
+ {
+ 0x000d, 50, 50, 0, 255, 201, 30,
+ 200, 247, 128, 0, 0, 208, 3,
+ 20, 249, 88, 0, 0, 252, 3,
+ 3368, 255, 182, 0, 0, 200, 3,
+ 1100, 250, 116, 0, 0, 204, 3
+ },
+
+ /* Region 144 */
+ {
+ 0x000d, 51, 51, 160, 255, 97, -20,
+ 3831, 240, 39, 0, 232, 224, 3,
+ 1258, 246, 102, 0, 0, 232, 3,
+ 4323, 242, 32, 0, 0, 216, 3,
+ 868, 243, 64, 0, 0, 204, 3
+ },
+
+ /* Region 145 */
+ {
+ 0x000d, 52, 52, 112, 128, 234, -20,
+ 725, 228, 32, 0, 0, 208, 1,
+ 400, 248, 86, 0, 0, 248, 3,
+ 2003, 53, 32, 0, 0, 236, 3,
+ 100, 209, 32, 0, 0, 212, 1
+ },
+
+ /* Region 146 */
+ {
+ 0x000d, 53, 53, 160, 255, 97, -20,
+ 3831, 240, 39, 0, 232, 224, 3,
+ 1258, 246, 102, 0, 0, 232, 3,
+ 4323, 242, 32, 0, 0, 224, 3,
+ 868, 243, 64, 0, 0, 196, 3
+ },
+
+ /* Region 147 */
+ {
+ 0x001d, 54, 54, 240, 240, 242, 10,
+ -1, 245, 71, 1, 24, 236, 0,
+ 1200, 218, 102, 1, 0, 236, 2,
+ 1354, 255, 48, 0, 0, 208, 2,
+ 5868, 209, 48, 0, 160, 212, 0
+ },
+
+ /* Region 148 */
+ {
+ 0x000d, 55, 55, 48, 32, 234, -10,
+ 725, 228, 32, 0, 0, 208, 3,
+ 900, 249, 86, 0, 0, 240, 3,
+ 2303, 69, 32, 0, 0, 236, 1,
+ 400, 177, 32, 0, 0, 212, 3
+ },
+
+ /* Region 149 */
+ {
+ 0x000d, 56, 56, 0, 255, 149, 20,
+ 414, 254, 123, 48, 0, 204, 3,
+ 1986, 252, 118, 48, 0, 244, 3,
+ 4383, 242, 67, 48, 0, 200, 3,
+ 4205, 243, 81, 48, 0, 204, 3
+ },
+
+ /* Region 150 */
+ {
+ 0x000d, 57, 57, 48, 32, 234, -20,
+ 526, 210, 32, 0, 0, 200, 3,
+ 719, 246, 86, 0, 0, 240, 3,
+ 1303, 48, 32, 0, 0, 236, 1,
+ 202, 98, 32, 0, 0, 212, 3
+ },
+
+ /* Region 151 */
+ {
+ 0x001d, 58, 58, 240, 240, 204, -40,
+ 5650, 247, 16, 0, 84, 220, 1,
+ 3800, 248, 32, 0, 0, 248, 3,
+ 1780, 252, 16, 0, 0, 152, 3,
+ 6825, 245, 32, 0, 0, 208, 1
+ },
+
+ /* Region 152 */
+ {
+ 0x000d, 59, 59, 144, 0, 108, -20,
+ 3531, 240, 103, 0, 232, 220, 3,
+ 1058, 246, 102, 0, 0, 232, 3,
+ 5331, 242, 64, 0, 0, 220, 3,
+ 1968, 243, 64, 0, 0, 204, 1
+ },
+
+ /* Region 153 */
+ {
+ 0x000d, 60, 60, 192, 64, 155, 40,
+ 700, 214, 84, 0, 0, 208, 1,
+ 950, 253, 76, 0, 0, 248, 3,
+ 2803, 255, 127, 0, 0, 200, 3,
+ 750, 255, 89, 0, 0, 204, 3
+ },
+
+ /* Region 154 */
+ {
+ 0x000d, 61, 61, 224, 48, 91, 40,
+ 400, 229, 68, 0, 0, 204, 1,
+ 700, 251, 76, 0, 0, 248, 3,
+ 1803, 255, 95, 0, 0, 196, 3,
+ 450, 255, 89, 0, 0, 208, 3
+ },
+
+ /* Region 155 */
+ {
+ 0x000d, 62, 62, 240, 32, 191, 25,
+ 214, 237, 69, 0, 0, 204, 1,
+ 400, 252, 78, 0, 0, 248, 3,
+ 2830, 255, 95, 0, 0, 208, 3,
+ 2500, 255, 25, 0, 0, 192, 3
+ },
+
+ /* Region 156 */
+ {
+ 0x000d, 63, 63, 240, 32, 91, 25,
+ 400, 229, 68, 0, 0, 188, 1,
+ -100, 250, 76, 0, 0, 248, 3,
+ 1803, 254, 95, 0, 0, 200, 3,
+ 450, 238, 89, 0, 0, 200, 3
+ },
+
+ /* Region 157 */
+ {
+ 0x000d, 64, 64, 240, 16, 91, 20,
+ 300, 210, 68, 0, 0, 196, 1,
+ -400, 250, 76, 0, 0, 248, 3,
+ 1803, 254, 95, 0, 0, 200, 3,
+ 550, 238, 89, 0, 0, 200, 3
+ },
+
+ /* Region 158 */
+ {
+ 0x001c, 65, 65, 240, 128, 223, 20,
+ 1780, 234, 16, 0, 112, 208, 3,
+ 800, 251, 32, 0, 0, 248, 3,
+ 5501, 231, 48, 0, 48, 200, 3,
+ 2751, 232, 48, 0, 0, 220, 3
+ },
+
+ /* Region 159 */
+ {
+ 0x001c, 66, 66, 240, 128, 223, 20,
+ 1580, 234, 16, 0, 112, 208, 3,
+ 600, 250, 32, 0, 0, 248, 3,
+ 5201, 231, 48, 0, 48, 200, 3,
+ 2510, 232, 48, 0, 0, 220, 3
+ },
+
+ /* Region 160 */
+ {
+ 0x000d, 67, 67, 0, 255, 0, -35,
+ 1514, 255, 63, 51, 0, 184, 3,
+ 4830, 251, 73, 51, 0, 252, 3,
+ 4349, 245, 67, 51, 0, 212, 3,
+ 5267, 246, 65, 51, 0, 200, 3
+ },
+
+ /* Region 161 */
+ {
+ 0x000d, 68, 68, 0, 255, 0, -35,
+ 1514, 255, 63, 51, 0, 196, 3,
+ 4905, 251, 73, 51, 0, 252, 3,
+ 4349, 245, 67, 51, 0, 196, 3,
+ 5214, 246, 65, 51, 0, 208, 3
+ },
+
+ /* Region 162 */
+ {
+ 0x000a, 69, 69, 240, 240, 243, -35,
+ 10000, 160, 68, 0, 0, 200, 3,
+ 7000, 156, 140, 0, 0, 228, 3,
+ 1586, 176, 16, 0, 0, 228, 7,
+ 8000, 140, 80, 0, 0, 236, 3
+ },
+
+ /* Region 163 */
+ {
+ 0x001a, 70, 70, 240, 240, 227, -38,
+ 500, 240, 52, 0, 0, 220, 1,
+ 8000, 188, 124, 0, 0, 228, 3,
+ 1586, 240, 16, 0, 0, 224, 7,
+ 8000, 203, 80, 0, 0, 228, 3
+ },
+
+ /* Region 164 */
+ {
+ 0x0004, 71, 71, 226, 240, 181, 35,
+ 7253, 224, 32, 48, 0, 184, 3,
+ 3594, 224, 79, 48, 0, 248, 1,
+ 220, 97, 19, 48, 156, 152, 3,
+ 5243, 172, 16, 48, 92, 204, 1
+ },
+
+ /* Region 165 */
+ {
+ 0x0004, 72, 72, 240, 241, 181, 35,
+ 6253, 134, 32, 48, 0, 184, 3,
+ 3994, 176, 76, 48, 160, 248, 1,
+ 22, 183, 19, 48, 156, 172, 3,
+ 1243, 160, 16, 48, 240, 188, 3
+ },
+
+ /* Region 166 */
+ {
+ 0x001a, 73, 73, 240, 224, 155, 30,
+ -2145, 240, 70, 0, 0, 252, 3,
+ 600, 109, 111, 0, 0, 240, 3,
+ -1800, 240, 71, 0, 0, 248, 3,
+ 200, 173, 111, 0, 0, 240, 3
+ },
+
+ /* Region 167 */
+ {
+ 0x0012, 74, 74, 240, 224, 119, 30,
+ -2545, 240, 70, 0, 252, 252, 3,
+ 0, 153, 111, 0, 0, 240, 3,
+ -2400, 240, 71, 0, 252, 252, 3,
+ 100, 137, 111, 0, 0, 240, 3
+ },
+
+ /* Region 168 */
+ {
+ 0x001a, 75, 75, 240, 128, 240, 20,
+ 3780, 255, 16, 0, 252, 188, 2,
+ 800, 255, 64, 0, 0, 248, 2,
+ 2501, 255, 48, 0, 252, 208, 0,
+ 751, 255, 48, 0, 0, 236, 2
+ },
+
+ /* Region 169 */
+ {
+ 0x000d, 76, 76, 0, 255, 68, 35,
+ 1100, 239, 69, 0, 0, 184, 3,
+ 2600, 255, 76, 0, 0, 252, 3,
+ 5000, 255, 111, 0, 0, 204, 3,
+ 3400, 254, 73, 0, 0, 184, 3
+ },
+
+ /* Region 170 */
+ {
+ 0x000d, 77, 77, 0, 255, 68, 35,
+ 914, 239, 69, 0, 0, 180, 3,
+ 1801, 254, 76, 0, 0, 252, 3,
+ 4800, 255, 111, 0, 0, 192, 3,
+ 3200, 254, 73, 0, 0, 192, 3
+ },
+
+ /* Region 171 */
+ {
+ 0x000d, 78, 78, 240, 32, 197, -20,
+ 1200, 216, 86, 0, 0, 180, 1,
+ 1800, 189, 127, 0, 0, 244, 3,
+ 2700, 156, 102, 0, 0, 196, 1,
+ 700, 109, 104, 0, 0, 196, 1
+ },
+
+ /* Region 172 */
+ {
+ 0x000d, 79, 79, 240, 32, 197, -20,
+ 1200, 216, 86, 0, 0, 196, 1,
+ 2200, 171, 127, 0, 0, 244, 3,
+ 2700, 145, 102, 0, 0, 192, 1,
+ 700, 106, 104, 0, 0, 192, 1
+ },
+
+ /* Region 173 */
+ {
+ 0x000d, 80, 80, 0, 255, 0, -40,
+ 3514, 254, 79, 51, 0, 196, 3,
+ 5905, 252, 73, 51, 0, 248, 3,
+ 6348, 245, 35, 51, 0, 176, 3,
+ 2203, 244, 33, 51, 0, 216, 3
+ },
+
+ /* Region 174 */
+ {
+ 0x800d, 81, 81, 0, 255, 0, -40,
+ 3514, 255, 79, 51, 0, 192, 3,
+ 5905, 246, 73, 51, 0, 252, 3,
+ 6348, 241, 35, 51, 0, 180, 3,
+ 2203, 242, 33, 51, 0, 212, 3
+ }
+};
+
+
+/*----------------------------------------------------------------------------
+ * Programs
+ *----------------------------------------------------------------------------
+*/
+const S_PROGRAM programs[] =
+{
+ { 7864320, 128 } /* program 0 */
+}; /* end Programs */
+
+/*----------------------------------------------------------------------------
+ * Banks
+ *----------------------------------------------------------------------------
+*/
+const S_BANK banks[] =
+{
+ { /* bank 0 */
+ 30976,
+ {
+ 0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87,
+ 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 101, 102, 103,
+ 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119,
+ 120, 121, 122, 123, 124, 125, 126, 127
+ }
+ }
+}; /* end Banks */
+
+/*----------------------------------------------------------------------------
+ * S_EAS
+ *----------------------------------------------------------------------------
+*/
+const S_EAS easSoundLib =
+{
+ 0x01534145,
+ 0x00105622,
+
+ banks,
+ programs,
+
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+
+ regions,
+
+ 1,
+ 1,
+
+ 0,
+ 0,
+ 0,
+
+ 175
+}; /* end S_EAS */
+/* end sound library */
diff --git a/arm-fm-22k/lib_src/eas_fmsynth.c b/arm-fm-22k/lib_src/eas_fmsynth.c
new file mode 100644
index 0000000..83f0087
--- /dev/null
+++ b/arm-fm-22k/lib_src/eas_fmsynth.c
@@ -0,0 +1,910 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * fmsynth.c
+ *
+ * Contents and purpose:
+ * Implements the high-level FM synthesizer functions.
+ *
+ * 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: 795 $
+ * $Date: 2007-08-01 00:14:45 -0700 (Wed, 01 Aug 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+// includes
+#include "eas_host.h"
+#include "eas_report.h"
+
+#include "eas_data.h"
+#include "eas_synth_protos.h"
+#include "eas_audioconst.h"
+#include "eas_fmengine.h"
+#include "eas_math.h"
+
+/* option sanity check */
+#ifdef _REVERB
+#error "No reverb for FM synthesizer"
+#endif
+#ifdef _CHORUS
+#error "No chorus for FM synthesizer"
+#endif
+
+/*
+ * WARNING: These macros can cause unwanted side effects. Use them
+ * with care. For example, min(x++,y++) will cause either x or y to be
+ * incremented twice.
+ */
+#define min(a,b) ((a) < (b) ? (a) : (b))
+#define max(a,b) ((a) > (b) ? (a) : (b))
+
+/* pivot point for keyboard scalars */
+#define EG_SCALE_PIVOT_POINT 64
+#define KEY_SCALE_PIVOT_POINT 36
+
+/* This number is the negative of the frequency of the note (in cents) of
+ * the sine wave played at unity. The number can be calculated as follows:
+ *
+ * MAGIC_NUMBER = 1200 * log(base2) (SINE_TABLE_SIZE * 8.175798916 / SAMPLE_RATE)
+ *
+ * 8.17578 is a reference to the frequency of MIDI note 0
+ */
+#if defined (_SAMPLE_RATE_8000)
+#define MAGIC_NUMBER 1279
+#elif defined (_SAMPLE_RATE_16000)
+#define MAGIC_NUMBER 79
+#elif defined (_SAMPLE_RATE_20000)
+#define MAGIC_NUMBER -308
+#elif defined (_SAMPLE_RATE_22050)
+#define MAGIC_NUMBER -477
+#elif defined (_SAMPLE_RATE_24000)
+#define MAGIC_NUMBER -623
+#elif defined (_SAMPLE_RATE_32000)
+#define MAGIC_NUMBER -1121
+#elif defined (_SAMPLE_RATE_44100)
+#define MAGIC_NUMBER -1677
+#elif defined (_SAMPLE_RATE_48000)
+#define MAGIC_NUMBER -1823
+#endif
+
+/* externs */
+extern const EAS_I16 fmControlTable[128];
+extern const EAS_U16 fmRateTable[256];
+extern const EAS_U16 fmAttackTable[16];
+extern const EAS_U8 fmDecayTable[16];
+extern const EAS_U8 fmReleaseTable[16];
+extern const EAS_U8 fmScaleTable[16];
+
+/* local prototypes */
+/*lint -esym(715, pVoiceMgr) standard synthesizer interface - pVoiceMgr not used */
+static EAS_RESULT FM_Initialize (S_VOICE_MGR *pVoiceMgr) { return EAS_SUCCESS; }
+static EAS_RESULT FM_StartVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_U16 regionIndex);
+static EAS_BOOL FM_UpdateVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_I32 *pMixBuffer, EAS_I32 numSamples);
+static void FM_ReleaseVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum);
+static void FM_MuteVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum);
+static void FM_SustainPedal (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, S_SYNTH_CHANNEL *pChannel, EAS_I32 voiceNum);
+static void FM_UpdateChannel (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel);
+
+
+/*----------------------------------------------------------------------------
+ * Synthesizer interface
+ *----------------------------------------------------------------------------
+*/
+const S_SYNTH_INTERFACE fmSynth =
+{
+ FM_Initialize,
+ FM_StartVoice,
+ FM_UpdateVoice,
+ FM_ReleaseVoice,
+ FM_MuteVoice,
+ FM_SustainPedal,
+ FM_UpdateChannel
+};
+
+#ifdef FM_OFFBOARD
+const S_FRAME_INTERFACE fmFrameInterface =
+{
+ FM_StartFrame,
+ FM_EndFrame
+};
+#endif
+
+/*----------------------------------------------------------------------------
+ * inline functions
+ *----------------------------------------------------------------------------
+ */
+EAS_INLINE S_FM_VOICE *GetFMVoicePtr (S_VOICE_MGR *pVoiceMgr, EAS_INT voiceNum)
+{
+ return &pVoiceMgr->fmVoices[voiceNum];
+}
+EAS_INLINE S_SYNTH_CHANNEL *GetChannelPtr (S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice)
+{
+ return &pSynth->channels[pVoice->channel & 15];
+}
+EAS_INLINE const S_FM_REGION *GetFMRegionPtr (S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice)
+{
+#ifdef _SECONDARY_SYNTH
+ return &pSynth->pEAS->pFMRegions[pVoice->regionIndex & REGION_INDEX_MASK];
+#else
+ return &pSynth->pEAS->pFMRegions[pVoice->regionIndex];
+#endif
+}
+
+/*----------------------------------------------------------------------------
+ * FM_SynthIsOutputOperator
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Returns true if the operator is a direct output and not muted
+ *
+ * Inputs:
+ *
+ * Outputs:
+ * Returns boolean
+ *----------------------------------------------------------------------------
+*/
+static EAS_BOOL FM_SynthIsOutputOperator (const S_FM_REGION *pRegion, EAS_INT operIndex)
+{
+
+ /* see if voice is muted */
+ if ((pRegion->oper[operIndex].gain & 0xfc) == 0)
+ return 0;
+
+ /* check based on mode */
+ switch (pRegion->region.keyGroupAndFlags & 7)
+ {
+
+ /* mode 0 - all operators are external */
+ case 0:
+ return EAS_TRUE;
+
+ /* mode 1 - operators 1-3 are external */
+ case 1:
+ if (operIndex != 0)
+ return EAS_TRUE;
+ break;
+
+ /* mode 2 - operators 1 & 3 are external */
+ case 2:
+ if ((operIndex == 1) || (operIndex == 3))
+ return EAS_TRUE;
+ break;
+
+ /* mode 2 - operators 1 & 2 are external */
+ case 3:
+ if ((operIndex == 1) || (operIndex == 2))
+ return EAS_TRUE;
+ break;
+
+ /* modes 4 & 5 - operator 1 is external */
+ case 4:
+ case 5:
+ if (operIndex == 1)
+ return EAS_TRUE;
+ break;
+
+ default:
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL,"Invalid voice mode: %d",
+ pRegion->region.keyGroupAndFlags & 7); */ }
+ }
+
+ return EAS_FALSE;
+}
+
+/*----------------------------------------------------------------------------
+ * FM_CalcEGRate()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ * Inputs:
+ * nKeyNumber - MIDI note
+ * nLogRate - logarithmic scale rate from patch data
+ * nKeyScale - key scaling factor for this EG
+ *
+ * Outputs:
+ * 16-bit linear multiplier
+ *----------------------------------------------------------------------------
+*/
+
+static EAS_U16 FM_CalcEGRate (EAS_U8 nKeyNumber, EAS_U8 nLogRate, EAS_U8 nEGScale)
+{
+ EAS_I32 temp;
+
+ /* incorporate key scaling on release rate */
+ temp = (EAS_I32) nLogRate << 7;
+ temp += ((EAS_I32) nKeyNumber - EG_SCALE_PIVOT_POINT) * (EAS_I32) nEGScale;
+
+ /* saturate */
+ temp = max(temp, 0);
+ temp = min(temp, 32767);
+
+ /* look up in rate table */
+ /*lint -e{704} use shift for performance */
+ return fmRateTable[temp >> 8];
+}
+
+/*----------------------------------------------------------------------------
+ * FM_ReleaseVoice()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * The selected voice is being released.
+ *
+ * Inputs:
+ * psEASData - pointer to S_EAS_DATA
+ * pVoice - pointer to voice to release
+ *
+ * Outputs:
+ * None
+ *----------------------------------------------------------------------------
+*/
+static void FM_ReleaseVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum)
+{
+ EAS_INT operIndex;
+ const S_FM_REGION *pRegion;
+ S_FM_VOICE *pFMVoice;
+
+ /* check to see if voice responds to NOTE-OFF's */
+ pRegion = GetFMRegionPtr(pSynth, pVoice);
+ if (pRegion->region.keyGroupAndFlags & REGION_FLAG_ONE_SHOT)
+ return;
+
+ /* set all envelopes to release state */
+ pFMVoice = GetFMVoicePtr(pVoiceMgr, voiceNum);
+ for (operIndex = 0; operIndex < 4; operIndex++)
+ {
+ pFMVoice->oper[operIndex].envState = eFMEnvelopeStateRelease;
+
+ /* incorporate key scaling on release rate */
+ pFMVoice->oper[operIndex].envRate = FM_CalcEGRate(
+ pVoice->note,
+ fmReleaseTable[pRegion->oper[operIndex].velocityRelease & 0x0f],
+ fmScaleTable[pRegion->oper[operIndex].egKeyScale >> 4]);
+ } /* end for (operIndex = 0; operIndex < 4; operIndex++) */
+}
+
+/*----------------------------------------------------------------------------
+ * FM_MuteVoice()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * The selected voice is being muted.
+ *
+ * Inputs:
+ * pVoice - pointer to voice to release
+ *
+ * Outputs:
+ * None
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pSynth) standard interface, pVoiceMgr not used */
+static void FM_MuteVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum)
+{
+ S_FM_VOICE *pFMVoice;
+
+ /* clear deferred action flags */
+ pVoice->voiceFlags &=
+ ~(VOICE_FLAG_DEFER_MIDI_NOTE_OFF |
+ VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF |
+ VOICE_FLAG_DEFER_MUTE);
+
+ /* set all envelopes to muted state */
+ pFMVoice = GetFMVoicePtr(pVoiceMgr, voiceNum);
+ pFMVoice->oper[0].envState = eFMEnvelopeStateMuted;
+ pFMVoice->oper[1].envState = eFMEnvelopeStateMuted;
+ pFMVoice->oper[2].envState = eFMEnvelopeStateMuted;
+ pFMVoice->oper[3].envState = eFMEnvelopeStateMuted;
+}
+
+/*----------------------------------------------------------------------------
+ * FM_SustainPedal()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * The selected voice is held due to sustain pedal
+ *
+ * Inputs:
+ * pVoice - pointer to voice to sustain
+ *
+ * Outputs:
+ * None
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pChannel) standard interface, pVoiceMgr not used */
+static void FM_SustainPedal (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, S_SYNTH_CHANNEL *pChannel, EAS_I32 voiceNum)
+{
+ const S_FM_REGION *pRegion;
+ S_FM_VOICE *pFMVoice;
+ EAS_INT operIndex;
+
+ pRegion = GetFMRegionPtr(pSynth, pVoice);
+ pFMVoice = GetFMVoicePtr(pVoiceMgr, voiceNum);
+
+ /* check to see if any envelopes are above the sustain level */
+ for (operIndex = 0; operIndex < 4; operIndex++)
+ {
+
+ /* if level control or envelope gain is zero, skip this envelope */
+ if (((pRegion->oper[operIndex].gain & 0xfc) == 0) ||
+ (pFMVoice->oper[operIndex].envGain == 0))
+ {
+ continue;
+ }
+
+ /* if the envelope gain is above the sustain level, we need to catch this voice */
+ if (pFMVoice->oper[operIndex].envGain >= ((EAS_U16) (pRegion->oper[operIndex].sustain & 0xfc) << 7))
+ {
+
+ /* reset envelope to decay state */
+ pFMVoice->oper[operIndex].envState = eFMEnvelopeStateDecay;
+
+ pFMVoice->oper[operIndex].envRate = FM_CalcEGRate(
+ pVoice->note,
+ fmDecayTable[pRegion->oper[operIndex].attackDecay & 0x0f],
+ fmScaleTable[pRegion->oper[operIndex].egKeyScale >> 4]);
+
+ /* set voice to decay state */
+ pVoice->voiceState = eVoiceStatePlay;
+
+ /* set sustain flag */
+ pVoice->voiceFlags |= VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF;
+ }
+ } /* end for (operIndex = 0; operIndex < 4; operIndex++) */
+}
+
+/*----------------------------------------------------------------------------
+ * FM_StartVoice()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Assign the region for the given instrument using the midi key number
+ * and the RPN2 (coarse tuning) value. By using RPN2 as part of the
+ * region selection process, we reduce the amount a given sample has
+ * to be transposed by selecting the closest recorded root instead.
+ *
+ * This routine is the second half of SynthAssignRegion().
+ * If the region was successfully found by SynthFindRegionIndex(),
+ * then assign the region's parameters to the voice.
+ *
+ * Setup and initialize the following voice parameters:
+ * m_nRegionIndex
+ *
+ * Inputs:
+ * pVoice - ptr to the voice we have assigned for this channel
+ * nRegionIndex - index of the region
+ * psEASData - pointer to overall EAS data structure
+ *
+ * Outputs:
+ * success - could find and assign the region for this voice's note otherwise
+ * failure - could not find nor assign the region for this voice's note
+ *
+ * Side Effects:
+ * psSynthObject->m_sVoice[].m_nRegionIndex is assigned
+ * psSynthObject->m_sVoice[] parameters are assigned
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT FM_StartVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_U16 regionIndex)
+{
+ S_FM_VOICE *pFMVoice;
+ S_SYNTH_CHANNEL *pChannel;
+ const S_FM_REGION *pRegion;
+ EAS_I32 temp;
+ EAS_INT operIndex;
+
+ /* establish pointers to data */
+ pVoice->regionIndex = regionIndex;
+ pFMVoice = GetFMVoicePtr(pVoiceMgr, voiceNum);
+ pChannel = GetChannelPtr(pSynth, pVoice);
+ pRegion = GetFMRegionPtr(pSynth, pVoice);
+
+ /* update static channel parameters */
+ if (pChannel->channelFlags & CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS)
+ FM_UpdateChannel(pVoiceMgr, pSynth, pVoice->channel & 15);
+
+ /* init the LFO */
+ pFMVoice->lfoValue = 0;
+ pFMVoice->lfoPhase = 0;
+ pFMVoice->lfoDelay = (EAS_U16) (fmScaleTable[pRegion->lfoFreqDelay & 0x0f] >> 1);
+
+#if (NUM_OUTPUT_CHANNELS == 2)
+ /* calculate pan gain values only if stereo output */
+ /* set up panning only at note start */
+ temp = (EAS_I32) pChannel->pan - 64;
+ temp += (EAS_I32) pRegion->pan;
+ if (temp < -64)
+ temp = -64;
+ if (temp > 64)
+ temp = 64;
+ pFMVoice->pan = (EAS_I8) temp;
+#endif /* #if (NUM_OUTPUT_CHANNELS == 2) */
+
+ /* no samples have been synthesized for this note yet */
+ pVoice->voiceFlags = VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET;
+
+ /* initialize gain value for anti-zipper filter */
+ pFMVoice->voiceGain = (EAS_I16) EAS_LogToLinear16(pChannel->staticGain);
+ pFMVoice->voiceGain = (EAS_I16) FMUL_15x15(pFMVoice->voiceGain, pSynth->masterVolume);
+
+ /* initialize the operators */
+ for (operIndex = 0; operIndex < 4; operIndex++)
+ {
+
+ /* establish operator output gain level */
+ /*lint -e{701} <use shift for performance> */
+ pFMVoice->oper[operIndex].outputGain = EAS_LogToLinear16(((EAS_I16) (pRegion->oper[operIndex].gain & 0xfc) - 0xfc) << 7);
+
+ /* check for linear velocity flag */
+ /*lint -e{703} <use shift for performance> */
+ if (pRegion->oper[operIndex].flags & FM_OPER_FLAG_LINEAR_VELOCITY)
+ temp = (EAS_I32) (pVoice->velocity - 127) << 5;
+ else
+ temp = (EAS_I32) fmControlTable[pVoice->velocity];
+
+ /* scale velocity */
+ /*lint -e{704} use shift for performance */
+ temp = (temp * (EAS_I32)(pRegion->oper[operIndex].velocityRelease & 0xf0)) >> 7;
+
+ /* include key scalar */
+ temp -= ((EAS_I32) pVoice->note - KEY_SCALE_PIVOT_POINT) * (EAS_I32) fmScaleTable[pRegion->oper[operIndex].egKeyScale & 0x0f];
+
+ /* saturate */
+ temp = min(temp, 0);
+ temp = max(temp, -32768);
+
+ /* save static gain parameters */
+ pFMVoice->oper[operIndex].baseGain = (EAS_I16) EAS_LogToLinear16(temp);
+
+ /* incorporate key scaling on decay rate */
+ pFMVoice->oper[operIndex].envRate = FM_CalcEGRate(
+ pVoice->note,
+ fmDecayTable[pRegion->oper[operIndex].attackDecay & 0x0f],
+ fmScaleTable[pRegion->oper[operIndex].egKeyScale >> 4]);
+
+ /* if zero attack time, max out envelope and jump to decay state */
+ if ((pRegion->oper[operIndex].attackDecay & 0xf0) == 0xf0)
+ {
+
+ /* start out envelope at max */
+ pFMVoice->oper[operIndex].envGain = 0x7fff;
+
+ /* set envelope to decay state */
+ pFMVoice->oper[operIndex].envState = eFMEnvelopeStateDecay;
+ }
+
+ /* start envelope at zero and start in attack state */
+ else
+ {
+ pFMVoice->oper[operIndex].envGain = 0;
+ pFMVoice->oper[operIndex].envState = eFMEnvelopeStateAttack;
+ }
+ }
+
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * FM_UpdateChannel()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Calculate and assign static channel parameters
+ * These values only need to be updated if one of the controller values
+ * for this channel changes.
+ * Called when CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS flag is set.
+ *
+ * Inputs:
+ * nChannel - channel to update
+ * psEASData - pointer to overall EAS data structure
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ * - the given channel's static gain and static pitch are updated
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pVoiceMgr) standard interface, pVoiceMgr not used */
+static void FM_UpdateChannel (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel)
+{
+ S_SYNTH_CHANNEL *pChannel;
+ EAS_I32 temp;
+
+ pChannel = &pSynth->channels[channel];
+
+ /* convert CC7 volume controller to log scale */
+ temp = fmControlTable[pChannel->volume];
+
+ /* incorporate CC11 expression controller */
+ temp += fmControlTable[pChannel->expression];
+
+ /* saturate */
+ pChannel->staticGain = (EAS_I16) max(temp,-32768);
+
+ /* calculate pitch bend */
+ /*lint -e{703} <avoid multiply for performance>*/
+ temp = (((EAS_I32)(pChannel->pitchBend) << 2) - 32768);
+
+ temp = FMUL_15x15(temp, pChannel->pitchBendSensitivity);
+
+ /* include "magic number" compensation for sample rate and lookup table size */
+ temp += MAGIC_NUMBER;
+
+ /* if this is not a drum channel, then add in the per-channel tuning */
+ if (!(pChannel->channelFlags & CHANNEL_FLAG_RHYTHM_CHANNEL))
+ temp += (pChannel->finePitch + (pChannel->coarsePitch * 100));
+
+ /* save static pitch */
+ pChannel->staticPitch = temp;
+
+ /* Calculate LFO modulation depth */
+ /* mod wheel to LFO depth */
+ temp = FMUL_15x15(DEFAULT_LFO_MOD_WHEEL_TO_PITCH_CENTS,
+ pChannel->modWheel << (NUM_EG1_FRAC_BITS -7));
+
+ /* channel pressure to LFO depth */
+ pChannel->lfoAmt = (EAS_I16) (temp +
+ FMUL_15x15(DEFAULT_LFO_CHANNEL_PRESSURE_TO_PITCH_CENTS,
+ pChannel->channelPressure << (NUM_EG1_FRAC_BITS -7)));
+
+ /* clear update flag */
+ pChannel->channelFlags &= ~CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS;
+ return;
+}
+
+/*----------------------------------------------------------------------------
+ * FM_UpdateLFO()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Calculate the LFO for the given voice
+ *
+ * Inputs:
+ * pVoice - ptr to the voice whose LFO we want to update
+ * psEASData - pointer to overall EAS data structure - used for debug only
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ * - updates LFO values for the given voice
+ *----------------------------------------------------------------------------
+*/
+static void FM_UpdateLFO (S_FM_VOICE *pFMVoice, const S_FM_REGION *pRegion)
+{
+
+ /* increment the LFO phase if the delay time has elapsed */
+ if (!pFMVoice->lfoDelay)
+ {
+ /*lint -e{701} <use shift for performance> */
+ pFMVoice->lfoPhase = pFMVoice->lfoPhase + (EAS_U16) (-fmControlTable[((15 - (pRegion->lfoFreqDelay >> 4)) << 3) + 4]);
+
+ /* square wave LFO? */
+ if (pRegion->region.keyGroupAndFlags & REGION_FLAG_SQUARE_WAVE)
+ pFMVoice->lfoValue = (EAS_I16)(pFMVoice->lfoPhase & 0x8000 ? -32767 : 32767);
+
+ /* trick to get a triangle wave out of a sawtooth */
+ else
+ {
+ pFMVoice->lfoValue = (EAS_I16) (pFMVoice->lfoPhase << 1);
+ /*lint -e{502} <shortcut to turn sawtooth into sine wave> */
+ if ((pFMVoice->lfoPhase > 0x3fff) && (pFMVoice->lfoPhase < 0xC000))
+ pFMVoice->lfoValue = ~pFMVoice->lfoValue;
+ }
+ }
+
+ /* still in delay */
+ else
+ pFMVoice->lfoDelay--;
+
+ return;
+}
+
+/*----------------------------------------------------------------------------
+ * FM_UpdateEG()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Calculate the synthesis parameters for an operator to be used during
+ * the next buffer
+ *
+ * Inputs:
+ * pVoice - pointer to the voice being updated
+ * psEASData - pointer to overall EAS data structure
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_BOOL FM_UpdateEG (S_SYNTH_VOICE *pVoice, S_OPERATOR *pOper, const S_FM_OPER *pOperData, EAS_BOOL oneShot)
+{
+ EAS_U32 temp;
+ EAS_BOOL done;
+
+ /* set flag assuming the envelope is not done */
+ done = EAS_FALSE;
+
+ /* take appropriate action based on state */
+ switch (pOper->envState)
+ {
+
+ case eFMEnvelopeStateAttack:
+
+ /* the envelope is linear during the attack, so add the value */
+ temp = pOper->envGain + fmAttackTable[pOperData->attackDecay >> 4];
+
+ /* check for end of attack */
+ if (temp >= 0x7fff)
+ {
+ pOper->envGain = 0x7fff;
+ pOper->envState = eFMEnvelopeStateDecay;
+ }
+ else
+ pOper->envGain = (EAS_U16) temp;
+ break;
+
+ case eFMEnvelopeStateDecay:
+
+ /* decay is exponential, multiply by decay rate */
+ pOper->envGain = (EAS_U16) FMUL_15x15(pOper->envGain, pOper->envRate);
+
+ /* check for sustain level reached */
+ temp = (EAS_U32) (pOperData->sustain & 0xfc) << 7;
+ if (pOper->envGain <= (EAS_U16) temp)
+ {
+ /* if this is a one-shot patch, go directly to release phase */
+ if (oneShot)
+ {
+ pOper->envRate = FM_CalcEGRate(
+ pVoice->note,
+ fmReleaseTable[pOperData->velocityRelease & 0x0f],
+ fmScaleTable[pOperData->egKeyScale >> 4]);
+ pOper->envState = eFMEnvelopeStateRelease;
+ }
+
+ /* normal sustaining type */
+ else
+ {
+ pOper->envGain = (EAS_U16) temp;
+ pOper->envState = eFMEnvelopeStateSustain;
+ }
+ }
+ break;
+
+ case eFMEnvelopeStateSustain:
+ pOper->envGain = (EAS_U16)((EAS_U16)(pOperData->sustain & 0xfc) << 7);
+ break;
+
+ case eFMEnvelopeStateRelease:
+
+ /* release is exponential, multiply by release rate */
+ pOper->envGain = (EAS_U16) FMUL_15x15(pOper->envGain, pOper->envRate);
+
+ /* fully released */
+ if (pOper->envGain == 0)
+ {
+ pOper->envGain = 0;
+ pOper->envState = eFMEnvelopeStateMuted;
+ done = EAS_TRUE;
+ }
+ break;
+
+ case eFMEnvelopeStateMuted:
+ pOper->envGain = 0;
+ done = EAS_TRUE;
+ break;
+ default:
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL,"Invalid operator state: %d", pOper->envState); */ }
+ } /* end switch (pOper->m_eState) */
+
+ return done;
+}
+
+/*----------------------------------------------------------------------------
+ * FM_UpdateDynamic()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Calculate the synthesis parameters for this voice that will be used to
+ * synthesize the next buffer
+ *
+ * Inputs:
+ * pVoice - pointer to the voice being updated
+ * psEASData - pointer to overall EAS data structure
+ *
+ * Outputs:
+ * Returns EAS_TRUE if voice will be fully ramped to zero at the end of
+ * the next synthesized buffer.
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_BOOL FM_UpdateDynamic (S_SYNTH_VOICE *pVoice, S_FM_VOICE *pFMVoice, const S_FM_REGION *pRegion, S_SYNTH_CHANNEL *pChannel)
+{
+ EAS_I32 temp;
+ EAS_I32 pitch;
+ EAS_I32 lfoPitch;
+ EAS_INT operIndex;
+ EAS_BOOL done;
+
+ /* increment LFO phase */
+ FM_UpdateLFO(pFMVoice, pRegion);
+
+ /* base pitch in cents */
+ pitch = pVoice->note * 100;
+
+ /* LFO amount includes LFO depth from programming + channel dynamics */
+ temp = (fmScaleTable[pRegion->vibTrem >> 4] >> 1) + pChannel->lfoAmt;
+
+ /* multiply by LFO output to get final pitch modulation */
+ lfoPitch = FMUL_15x15(pFMVoice->lfoValue, temp);
+
+ /* flag to indicate this voice is done */
+ done = EAS_TRUE;
+
+ /* iterate through operators to establish parameters */
+ for (operIndex = 0; operIndex < 4; operIndex++)
+ {
+ EAS_BOOL bTemp;
+
+ /* set base phase increment for each operator */
+ temp = pRegion->oper[operIndex].tuning +
+ pChannel->staticPitch;
+
+ /* add vibrato effect unless it is disabled for this operator */
+ if ((pRegion->oper[operIndex].flags & FM_OPER_FLAG_NO_VIBRATO) == 0)
+ temp += lfoPitch;
+
+ /* if note is monotonic, bias to MIDI note 60 */
+ if (pRegion->oper[operIndex].flags & FM_OPER_FLAG_MONOTONE)
+ temp += 6000;
+ else
+ temp += pitch;
+ pFMVoice->oper[operIndex].pitch = (EAS_I16) temp;
+
+ /* calculate envelope, returns true if done */
+ bTemp = FM_UpdateEG(pVoice, &pFMVoice->oper[operIndex], &pRegion->oper[operIndex], pRegion->region.keyGroupAndFlags & REGION_FLAG_ONE_SHOT);
+
+ /* check if all output envelopes have completed */
+ if (FM_SynthIsOutputOperator(pRegion, operIndex))
+ done = done && bTemp;
+ }
+
+ return done;
+}
+
+/*----------------------------------------------------------------------------
+ * FM_UpdateVoice()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Synthesize a block of samples for the given voice.
+ *
+ * Inputs:
+ * psEASData - pointer to overall EAS data structure
+ *
+ * Outputs:
+ * number of samples actually written to buffer
+ *
+ * Side Effects:
+ * - samples are added to the presently free buffer
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_BOOL FM_UpdateVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_I32 *pMixBuffer, EAS_I32 numSamples)
+{
+ S_SYNTH_CHANNEL *pChannel;
+ const S_FM_REGION *pRegion;
+ S_FM_VOICE *pFMVoice;
+ S_FM_VOICE_CONFIG vCfg;
+ S_FM_VOICE_FRAME vFrame;
+ EAS_I32 temp;
+ EAS_INT oper;
+ EAS_U16 voiceGainTarget;
+ EAS_BOOL done;
+
+ /* setup some pointers */
+ pChannel = GetChannelPtr(pSynth, pVoice);
+ pRegion = GetFMRegionPtr(pSynth, pVoice);
+ pFMVoice = GetFMVoicePtr(pVoiceMgr, voiceNum);
+
+ /* if the voice is just starting, get the voice configuration data */
+ if (pVoice->voiceFlags & VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET)
+ {
+
+ /* split architecture may limit the number of voice starts */
+#ifdef MAX_VOICE_STARTS
+ if (pVoiceMgr->numVoiceStarts == MAX_VOICE_STARTS)
+ return EAS_FALSE;
+ pVoiceMgr->numVoiceStarts++;
+#endif
+
+ /* get initial parameters */
+ vCfg.feedback = pRegion->feedback;
+ vCfg.voiceGain = (EAS_U16) pFMVoice->voiceGain;
+
+#if (NUM_OUTPUT_CHANNELS == 2)
+ vCfg.pan = pFMVoice->pan;
+#endif
+
+ /* get voice mode */
+ vCfg.flags = pRegion->region.keyGroupAndFlags & 7;
+
+ /* get operator parameters */
+ for (oper = 0; oper < 4; oper++)
+ {
+ /* calculate initial gain */
+ vCfg.gain[oper] = (EAS_U16) FMUL_15x15(pFMVoice->oper[oper].baseGain, pFMVoice->oper[oper].envGain);
+ vCfg.outputGain[oper] = pFMVoice->oper[oper].outputGain;
+
+ /* copy noise waveform flag */
+ if (pRegion->oper[oper].flags & FM_OPER_FLAG_NOISE)
+ vCfg.flags |= (EAS_U8) (FLAG_FM_ENG_VOICE_OP1_NOISE << oper);
+ }
+
+#ifdef FM_OFFBOARD
+ FM_ConfigVoice(voiceNum, &vCfg, pVoiceMgr->pFrameBuffer);
+#else
+ FM_ConfigVoice(voiceNum, &vCfg, NULL);
+#endif
+
+ /* clear startup flag */
+ pVoice->voiceFlags &= ~VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET;
+ }
+
+ /* calculate new synthesis parameters */
+ done = FM_UpdateDynamic(pVoice, pFMVoice, pRegion, pChannel);
+
+ /* calculate LFO gain modulation */
+ /*lint -e{702} <use shift for performance> */
+ temp = ((fmScaleTable[pRegion->vibTrem & 0x0f] >> 1) * pFMVoice->lfoValue) >> FM_LFO_GAIN_SHIFT;
+
+ /* include channel gain */
+ temp += pChannel->staticGain;
+
+ /* -32768 or lower is infinite attenuation */
+ if (temp < -32767)
+ voiceGainTarget = 0;
+
+ /* translate to linear gain multiplier */
+ else
+ voiceGainTarget = EAS_LogToLinear16(temp);
+
+ /* include synth master volume */
+ voiceGainTarget = (EAS_U16) FMUL_15x15(voiceGainTarget, pSynth->masterVolume);
+
+ /* save target values for this frame */
+ vFrame.voiceGain = voiceGainTarget;
+
+ /* assume voice output is zero */
+ pVoice->gain = 0;
+
+ /* save operator targets for this frame */
+ for (oper = 0; oper < 4; oper++)
+ {
+ vFrame.gain[oper] = (EAS_U16) FMUL_15x15(pFMVoice->oper[oper].baseGain, pFMVoice->oper[oper].envGain);
+ vFrame.pitch[oper] = pFMVoice->oper[oper].pitch;
+
+ /* use the highest output envelope level as the gain for the voice stealing algorithm */
+ if (FM_SynthIsOutputOperator(pRegion, oper))
+ pVoice->gain = max(pVoice->gain, (EAS_I16) vFrame.gain[oper]);
+ }
+
+ /* consider voice gain multiplier in calculating gain for stealing algorithm */
+ pVoice->gain = (EAS_I16) FMUL_15x15(voiceGainTarget, pVoice->gain);
+
+ /* synthesize samples */
+#ifdef FM_OFFBOARD
+ FM_ProcessVoice(voiceNum, &vFrame, numSamples, pVoiceMgr->operMixBuffer, pVoiceMgr->voiceBuffer, pMixBuffer, pVoiceMgr->pFrameBuffer);
+#else
+ FM_ProcessVoice(voiceNum, &vFrame, numSamples, pVoiceMgr->operMixBuffer, pVoiceMgr->voiceBuffer, pMixBuffer, NULL);
+#endif
+
+ return done;
+}
+
diff --git a/arm-fm-22k/lib_src/eas_fmsynth.h b/arm-fm-22k/lib_src/eas_fmsynth.h
new file mode 100644
index 0000000..76f8adc
--- /dev/null
+++ b/arm-fm-22k/lib_src/eas_fmsynth.h
@@ -0,0 +1,81 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_fmsynth.h
+ *
+ * Contents and purpose:
+ * Implements the FM synthesizer functions.
+ *
+ * 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: 90 $
+ * $Date: 2006-07-11 20:18:13 -0700 (Tue, 11 Jul 2006) $
+ *----------------------------------------------------------------------------
+*/
+
+#ifndef fmsynthH
+#define fmsynthH
+
+#include "eas_data.h"
+
+#if defined (_FM_SYNTH)
+
+/* FM envelope state */
+typedef enum {
+ eFMEnvelopeStateAttack = 0,
+ eFMEnvelopeStateDecay,
+ eFMEnvelopeStateSustain,
+ eFMEnvelopeStateRelease,
+ eFMEnvelopeStateMuted,
+ eFMEnvelopeStateInvalid /* should never be in this state! */
+} E_FM_ENVELOPE_STATE;
+
+/*------------------------------------
+ * S_OPERATOR data structure
+ *------------------------------------
+*/
+typedef struct s_operator_tag
+{
+ EAS_I16 pitch; /* operator pitch in cents */
+ EAS_U16 envGain; /* envelope target */
+ EAS_I16 baseGain; /* patch gain (inc. vel & key scale) */
+ EAS_U16 outputGain; /* current output gain */
+ EAS_U16 envRate; /* calculated envelope rate */
+ EAS_U8 envState; /* envelope state */
+ EAS_U8 pad; /* pad to 16-bits */
+} S_OPERATOR;
+#endif
+
+typedef struct s_fm_voice_tag
+{
+ S_OPERATOR oper[4]; /* operator data */
+ EAS_I16 voiceGain; /* LFO + channel parameters */
+ EAS_U16 lfoPhase; /* LFO current phase */
+ EAS_I16 lfoValue; /* LFO current value */
+ EAS_U16 lfoDelay; /* keeps track of elapsed delay time */
+ EAS_I8 pan; /* stereo pan value (-64 to +64) */
+ EAS_I8 pad; /* reserved to maintain alignment */
+} S_FM_VOICE;
+
+#ifdef _FM_EDITOR
+extern S_FM_REGION newPatch;
+extern S_FM_REGION OriginalPatch;
+#endif
+
+extern EAS_U32 freqTable[];
+
+#endif
diff --git a/arm-fm-22k/lib_src/eas_fmtables.c b/arm-fm-22k/lib_src/eas_fmtables.c
new file mode 100644
index 0000000..25c6961
--- /dev/null
+++ b/arm-fm-22k/lib_src/eas_fmtables.c
@@ -0,0 +1,368 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_fmtables.c
+ *
+ * Contents and purpose:
+ * Contains lookup tables for the FM synthesizer
+ *
+ *
+ * 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_types.h"
+
+/* this table is needed by the DSP and the main processor */
+const EAS_U8 fmScaleTable[16] =
+{
+ 0,8,16,24,32,40,48,56,64,72,80,96,128,160,192,255
+};
+
+/* these tables are needed on the main processor */
+#ifndef _DSP_CODE
+const EAS_I16 fmControlTable[128] =
+{
+ -32768,-14313,-12265,-11067,-10217,-9558,-9019,-8563,
+ -8169,-7821,-7510,-7228,-6971,-6734,-6515,-6312,
+ -6121,-5942,-5773,-5613,-5462,-5317,-5180,-5049,
+ -4923,-4802,-4686,-4575,-4467,-4364,-4264,-4167,
+ -4073,-3982,-3894,-3808,-3725,-3644,-3565,-3488,
+ -3414,-3341,-3269,-3200,-3132,-3066,-3001,-2937,
+ -2875,-2814,-2754,-2696,-2638,-2582,-2527,-2473,
+ -2419,-2367,-2316,-2265,-2216,-2167,-2119,-2071,
+ -2025,-1979,-1934,-1889,-1846,-1803,-1760,-1718,
+ -1677,-1636,-1596,-1556,-1517,-1478,-1440,-1403,
+ -1366,-1329,-1293,-1257,-1221,-1186,-1152,-1118,
+ -1084,-1051,-1018,-985,-953,-921,-889,-858,
+ -827,-796,-766,-736,-706,-677,-648,-619,
+ -590,-562,-534,-506,-479,-452,-425,-398,
+ -371,-345,-319,-293,-268,-242,-217,-192,
+ -168,-143,-119,-95,-71,-47,-23,0
+};
+
+const EAS_U16 fmRateTable[128] =
+{
+ 32767,32764,32758,32747,32731,32712,32688,32659,
+ 32627,32590,32548,32503,32453,32398,32340,32277,
+ 32211,32140,32065,31985,31902,31815,31724,31628,
+ 31529,31426,31319,31208,31094,30976,30854,30728,
+ 30599,30466,30330,30191,30048,29902,29752,29599,
+ 29443,29285,29123,28958,28790,28619,28445,28269,
+ 28090,27909,27725,27538,27349,27158,26964,26769,
+ 26571,26371,26169,25965,25760,25552,25343,25132,
+ 24920,24706,24490,24274,24056,23836,23616,23394,
+ 23172,22948,22724,22499,22273,22046,21819,21591,
+ 21363,21135,20906,20676,20447,20217,19987,19758,
+ 19528,19298,19069,18840,18610,18382,18153,17926,
+ 17698,17471,17245,17020,16795,16571,16347,16125,
+ 15903,15683,15463,15245,15027,14811,14596,14382,
+ 14169,13957,13747,13538,13331,13125,12920,12717,
+ 12516,12316,12117,11921,11725,11532,11340,0
+};
+
+const EAS_U16 fmAttackTable[15] =
+{
+ 27,54,109,327,655,1310,2730,4095,
+ 4681,5461,6553,8191,10922,16383,32767
+};
+
+const EAS_U8 fmDecayTable[16] =
+{
+ 4,7,10,15,20,25,30,35,40,50,60,70,80,90,100,127
+};
+
+const EAS_U8 fmReleaseTable[16] =
+{
+ 10,15,20,25,30,35,40,45,50,60,70,80,90,100,113,127
+};
+#endif
+
+/* this table is needed only on the DSP */
+#if defined(_DSP_CODE) || !defined(_SPLIT_ARCHITECTURE)
+//---------------------------------------------------------------------
+// sineTable
+//
+// Contains sine lookup table
+//---------------------------------------------------------------------
+
+const EAS_I16 sineTable[2048] =
+{
+ 0,101,201,302,402,503,603,704,
+ 804,905,1005,1106,1206,1307,1407,1507,
+ 1608,1708,1809,1909,2009,2110,2210,2310,
+ 2410,2511,2611,2711,2811,2911,3012,3112,
+ 3212,3312,3412,3512,3612,3712,3811,3911,
+ 4011,4111,4210,4310,4410,4509,4609,4708,
+ 4808,4907,5007,5106,5205,5305,5404,5503,
+ 5602,5701,5800,5899,5998,6096,6195,6294,
+ 6393,6491,6590,6688,6786,6885,6983,7081,
+ 7179,7277,7375,7473,7571,7669,7767,7864,
+ 7962,8059,8157,8254,8351,8448,8545,8642,
+ 8739,8836,8933,9030,9126,9223,9319,9416,
+ 9512,9608,9704,9800,9896,9992,10087,10183,
+ 10278,10374,10469,10564,10659,10754,10849,10944,
+ 11039,11133,11228,11322,11417,11511,11605,11699,
+ 11793,11886,11980,12074,12167,12260,12353,12446,
+ 12539,12632,12725,12817,12910,13002,13094,13187,
+ 13279,13370,13462,13554,13645,13736,13828,13919,
+ 14010,14101,14191,14282,14372,14462,14553,14643,
+ 14732,14822,14912,15001,15090,15180,15269,15358,
+ 15446,15535,15623,15712,15800,15888,15976,16063,
+ 16151,16238,16325,16413,16499,16586,16673,16759,
+ 16846,16932,17018,17104,17189,17275,17360,17445,
+ 17530,17615,17700,17784,17869,17953,18037,18121,
+ 18204,18288,18371,18454,18537,18620,18703,18785,
+ 18868,18950,19032,19113,19195,19276,19357,19438,
+ 19519,19600,19680,19761,19841,19921,20000,20080,
+ 20159,20238,20317,20396,20475,20553,20631,20709,
+ 20787,20865,20942,21019,21096,21173,21250,21326,
+ 21403,21479,21554,21630,21705,21781,21856,21930,
+ 22005,22079,22154,22227,22301,22375,22448,22521,
+ 22594,22667,22739,22812,22884,22956,23027,23099,
+ 23170,23241,23311,23382,23452,23522,23592,23662,
+ 23731,23801,23870,23938,24007,24075,24143,24211,
+ 24279,24346,24413,24480,24547,24613,24680,24746,
+ 24811,24877,24942,25007,25072,25137,25201,25265,
+ 25329,25393,25456,25519,25582,25645,25708,25770,
+ 25832,25893,25955,26016,26077,26138,26198,26259,
+ 26319,26378,26438,26497,26556,26615,26674,26732,
+ 26790,26848,26905,26962,27019,27076,27133,27189,
+ 27245,27300,27356,27411,27466,27521,27575,27629,
+ 27683,27737,27790,27843,27896,27949,28001,28053,
+ 28105,28157,28208,28259,28310,28360,28411,28460,
+ 28510,28560,28609,28658,28706,28755,28803,28850,
+ 28898,28945,28992,29039,29085,29131,29177,29223,
+ 29268,29313,29358,29403,29447,29491,29534,29578,
+ 29621,29664,29706,29749,29791,29832,29874,29915,
+ 29956,29997,30037,30077,30117,30156,30195,30234,
+ 30273,30311,30349,30387,30424,30462,30498,30535,
+ 30571,30607,30643,30679,30714,30749,30783,30818,
+ 30852,30885,30919,30952,30985,31017,31050,31082,
+ 31113,31145,31176,31206,31237,31267,31297,31327,
+ 31356,31385,31414,31442,31470,31498,31526,31553,
+ 31580,31607,31633,31659,31685,31710,31736,31760,
+ 31785,31809,31833,31857,31880,31903,31926,31949,
+ 31971,31993,32014,32036,32057,32077,32098,32118,
+ 32137,32157,32176,32195,32213,32232,32250,32267,
+ 32285,32302,32318,32335,32351,32367,32382,32397,
+ 32412,32427,32441,32455,32469,32482,32495,32508,
+ 32521,32533,32545,32556,32567,32578,32589,32599,
+ 32609,32619,32628,32637,32646,32655,32663,32671,
+ 32678,32685,32692,32699,32705,32711,32717,32722,
+ 32728,32732,32737,32741,32745,32748,32752,32755,
+ 32757,32759,32761,32763,32765,32766,32766,32767,
+ 32767,32767,32766,32766,32765,32763,32761,32759,
+ 32757,32755,32752,32748,32745,32741,32737,32732,
+ 32728,32722,32717,32711,32705,32699,32692,32685,
+ 32678,32671,32663,32655,32646,32637,32628,32619,
+ 32609,32599,32589,32578,32567,32556,32545,32533,
+ 32521,32508,32495,32482,32469,32455,32441,32427,
+ 32412,32397,32382,32367,32351,32335,32318,32302,
+ 32285,32267,32250,32232,32213,32195,32176,32157,
+ 32137,32118,32098,32077,32057,32036,32014,31993,
+ 31971,31949,31926,31903,31880,31857,31833,31809,
+ 31785,31760,31736,31710,31685,31659,31633,31607,
+ 31580,31553,31526,31498,31470,31442,31414,31385,
+ 31356,31327,31297,31267,31237,31206,31176,31145,
+ 31113,31082,31050,31017,30985,30952,30919,30885,
+ 30852,30818,30783,30749,30714,30679,30643,30607,
+ 30571,30535,30498,30462,30424,30387,30349,30311,
+ 30273,30234,30195,30156,30117,30077,30037,29997,
+ 29956,29915,29874,29832,29791,29749,29706,29664,
+ 29621,29578,29534,29491,29447,29403,29358,29313,
+ 29268,29223,29177,29131,29085,29039,28992,28945,
+ 28898,28850,28803,28755,28706,28658,28609,28560,
+ 28510,28460,28411,28360,28310,28259,28208,28157,
+ 28105,28053,28001,27949,27896,27843,27790,27737,
+ 27683,27629,27575,27521,27466,27411,27356,27300,
+ 27245,27189,27133,27076,27019,26962,26905,26848,
+ 26790,26732,26674,26615,26556,26497,26438,26378,
+ 26319,26259,26198,26138,26077,26016,25955,25893,
+ 25832,25770,25708,25645,25582,25519,25456,25393,
+ 25329,25265,25201,25137,25072,25007,24942,24877,
+ 24811,24746,24680,24613,24547,24480,24413,24346,
+ 24279,24211,24143,24075,24007,23938,23870,23801,
+ 23731,23662,23592,23522,23452,23382,23311,23241,
+ 23170,23099,23027,22956,22884,22812,22739,22667,
+ 22594,22521,22448,22375,22301,22227,22154,22079,
+ 22005,21930,21856,21781,21705,21630,21554,21479,
+ 21403,21326,21250,21173,21096,21019,20942,20865,
+ 20787,20709,20631,20553,20475,20396,20317,20238,
+ 20159,20080,20000,19921,19841,19761,19680,19600,
+ 19519,19438,19357,19276,19195,19113,19032,18950,
+ 18868,18785,18703,18620,18537,18454,18371,18288,
+ 18204,18121,18037,17953,17869,17784,17700,17615,
+ 17530,17445,17360,17275,17189,17104,17018,16932,
+ 16846,16759,16673,16586,16499,16413,16325,16238,
+ 16151,16063,15976,15888,15800,15712,15623,15535,
+ 15446,15358,15269,15180,15090,15001,14912,14822,
+ 14732,14643,14553,14462,14372,14282,14191,14101,
+ 14010,13919,13828,13736,13645,13554,13462,13370,
+ 13279,13187,13094,13002,12910,12817,12725,12632,
+ 12539,12446,12353,12260,12167,12074,11980,11886,
+ 11793,11699,11605,11511,11417,11322,11228,11133,
+ 11039,10944,10849,10754,10659,10564,10469,10374,
+ 10278,10183,10087,9992,9896,9800,9704,9608,
+ 9512,9416,9319,9223,9126,9030,8933,8836,
+ 8739,8642,8545,8448,8351,8254,8157,8059,
+ 7962,7864,7767,7669,7571,7473,7375,7277,
+ 7179,7081,6983,6885,6786,6688,6590,6491,
+ 6393,6294,6195,6096,5998,5899,5800,5701,
+ 5602,5503,5404,5305,5205,5106,5007,4907,
+ 4808,4708,4609,4509,4410,4310,4210,4111,
+ 4011,3911,3811,3712,3612,3512,3412,3312,
+ 3212,3112,3012,2911,2811,2711,2611,2511,
+ 2410,2310,2210,2110,2009,1909,1809,1708,
+ 1608,1507,1407,1307,1206,1106,1005,905,
+ 804,704,603,503,402,302,201,101,
+ 0,-101,-201,-302,-402,-503,-603,-704,
+ -804,-905,-1005,-1106,-1206,-1307,-1407,-1507,
+ -1608,-1708,-1809,-1909,-2009,-2110,-2210,-2310,
+ -2410,-2511,-2611,-2711,-2811,-2911,-3012,-3112,
+ -3212,-3312,-3412,-3512,-3612,-3712,-3811,-3911,
+ -4011,-4111,-4210,-4310,-4410,-4509,-4609,-4708,
+ -4808,-4907,-5007,-5106,-5205,-5305,-5404,-5503,
+ -5602,-5701,-5800,-5899,-5998,-6096,-6195,-6294,
+ -6393,-6491,-6590,-6688,-6786,-6885,-6983,-7081,
+ -7179,-7277,-7375,-7473,-7571,-7669,-7767,-7864,
+ -7962,-8059,-8157,-8254,-8351,-8448,-8545,-8642,
+ -8739,-8836,-8933,-9030,-9126,-9223,-9319,-9416,
+ -9512,-9608,-9704,-9800,-9896,-9992,-10087,-10183,
+ -10278,-10374,-10469,-10564,-10659,-10754,-10849,-10944,
+ -11039,-11133,-11228,-11322,-11417,-11511,-11605,-11699,
+ -11793,-11886,-11980,-12074,-12167,-12260,-12353,-12446,
+ -12539,-12632,-12725,-12817,-12910,-13002,-13094,-13187,
+ -13279,-13370,-13462,-13554,-13645,-13736,-13828,-13919,
+ -14010,-14101,-14191,-14282,-14372,-14462,-14553,-14643,
+ -14732,-14822,-14912,-15001,-15090,-15180,-15269,-15358,
+ -15446,-15535,-15623,-15712,-15800,-15888,-15976,-16063,
+ -16151,-16238,-16325,-16413,-16499,-16586,-16673,-16759,
+ -16846,-16932,-17018,-17104,-17189,-17275,-17360,-17445,
+ -17530,-17615,-17700,-17784,-17869,-17953,-18037,-18121,
+ -18204,-18288,-18371,-18454,-18537,-18620,-18703,-18785,
+ -18868,-18950,-19032,-19113,-19195,-19276,-19357,-19438,
+ -19519,-19600,-19680,-19761,-19841,-19921,-20000,-20080,
+ -20159,-20238,-20317,-20396,-20475,-20553,-20631,-20709,
+ -20787,-20865,-20942,-21019,-21096,-21173,-21250,-21326,
+ -21403,-21479,-21554,-21630,-21705,-21781,-21856,-21930,
+ -22005,-22079,-22154,-22227,-22301,-22375,-22448,-22521,
+ -22594,-22667,-22739,-22812,-22884,-22956,-23027,-23099,
+ -23170,-23241,-23311,-23382,-23452,-23522,-23592,-23662,
+ -23731,-23801,-23870,-23938,-24007,-24075,-24143,-24211,
+ -24279,-24346,-24413,-24480,-24547,-24613,-24680,-24746,
+ -24811,-24877,-24942,-25007,-25072,-25137,-25201,-25265,
+ -25329,-25393,-25456,-25519,-25582,-25645,-25708,-25770,
+ -25832,-25893,-25955,-26016,-26077,-26138,-26198,-26259,
+ -26319,-26378,-26438,-26497,-26556,-26615,-26674,-26732,
+ -26790,-26848,-26905,-26962,-27019,-27076,-27133,-27189,
+ -27245,-27300,-27356,-27411,-27466,-27521,-27575,-27629,
+ -27683,-27737,-27790,-27843,-27896,-27949,-28001,-28053,
+ -28105,-28157,-28208,-28259,-28310,-28360,-28411,-28460,
+ -28510,-28560,-28609,-28658,-28706,-28755,-28803,-28850,
+ -28898,-28945,-28992,-29039,-29085,-29131,-29177,-29223,
+ -29268,-29313,-29358,-29403,-29447,-29491,-29534,-29578,
+ -29621,-29664,-29706,-29749,-29791,-29832,-29874,-29915,
+ -29956,-29997,-30037,-30077,-30117,-30156,-30195,-30234,
+ -30273,-30311,-30349,-30387,-30424,-30462,-30498,-30535,
+ -30571,-30607,-30643,-30679,-30714,-30749,-30783,-30818,
+ -30852,-30885,-30919,-30952,-30985,-31017,-31050,-31082,
+ -31113,-31145,-31176,-31206,-31237,-31267,-31297,-31327,
+ -31356,-31385,-31414,-31442,-31470,-31498,-31526,-31553,
+ -31580,-31607,-31633,-31659,-31685,-31710,-31736,-31760,
+ -31785,-31809,-31833,-31857,-31880,-31903,-31926,-31949,
+ -31971,-31993,-32014,-32036,-32057,-32077,-32098,-32118,
+ -32137,-32157,-32176,-32195,-32213,-32232,-32250,-32267,
+ -32285,-32302,-32318,-32335,-32351,-32367,-32382,-32397,
+ -32412,-32427,-32441,-32455,-32469,-32482,-32495,-32508,
+ -32521,-32533,-32545,-32556,-32567,-32578,-32589,-32599,
+ -32609,-32619,-32628,-32637,-32646,-32655,-32663,-32671,
+ -32678,-32685,-32692,-32699,-32705,-32711,-32717,-32722,
+ -32728,-32732,-32737,-32741,-32745,-32748,-32752,-32755,
+ -32757,-32759,-32761,-32763,-32765,-32766,-32766,-32767,
+ -32767,-32767,-32766,-32766,-32765,-32763,-32761,-32759,
+ -32757,-32755,-32752,-32748,-32745,-32741,-32737,-32732,
+ -32728,-32722,-32717,-32711,-32705,-32699,-32692,-32685,
+ -32678,-32671,-32663,-32655,-32646,-32637,-32628,-32619,
+ -32609,-32599,-32589,-32578,-32567,-32556,-32545,-32533,
+ -32521,-32508,-32495,-32482,-32469,-32455,-32441,-32427,
+ -32412,-32397,-32382,-32367,-32351,-32335,-32318,-32302,
+ -32285,-32267,-32250,-32232,-32213,-32195,-32176,-32157,
+ -32137,-32118,-32098,-32077,-32057,-32036,-32014,-31993,
+ -31971,-31949,-31926,-31903,-31880,-31857,-31833,-31809,
+ -31785,-31760,-31736,-31710,-31685,-31659,-31633,-31607,
+ -31580,-31553,-31526,-31498,-31470,-31442,-31414,-31385,
+ -31356,-31327,-31297,-31267,-31237,-31206,-31176,-31145,
+ -31113,-31082,-31050,-31017,-30985,-30952,-30919,-30885,
+ -30852,-30818,-30783,-30749,-30714,-30679,-30643,-30607,
+ -30571,-30535,-30498,-30462,-30424,-30387,-30349,-30311,
+ -30273,-30234,-30195,-30156,-30117,-30077,-30037,-29997,
+ -29956,-29915,-29874,-29832,-29791,-29749,-29706,-29664,
+ -29621,-29578,-29534,-29491,-29447,-29403,-29358,-29313,
+ -29268,-29223,-29177,-29131,-29085,-29039,-28992,-28945,
+ -28898,-28850,-28803,-28755,-28706,-28658,-28609,-28560,
+ -28510,-28460,-28411,-28360,-28310,-28259,-28208,-28157,
+ -28105,-28053,-28001,-27949,-27896,-27843,-27790,-27737,
+ -27683,-27629,-27575,-27521,-27466,-27411,-27356,-27300,
+ -27245,-27189,-27133,-27076,-27019,-26962,-26905,-26848,
+ -26790,-26732,-26674,-26615,-26556,-26497,-26438,-26378,
+ -26319,-26259,-26198,-26138,-26077,-26016,-25955,-25893,
+ -25832,-25770,-25708,-25645,-25582,-25519,-25456,-25393,
+ -25329,-25265,-25201,-25137,-25072,-25007,-24942,-24877,
+ -24811,-24746,-24680,-24613,-24547,-24480,-24413,-24346,
+ -24279,-24211,-24143,-24075,-24007,-23938,-23870,-23801,
+ -23731,-23662,-23592,-23522,-23452,-23382,-23311,-23241,
+ -23170,-23099,-23027,-22956,-22884,-22812,-22739,-22667,
+ -22594,-22521,-22448,-22375,-22301,-22227,-22154,-22079,
+ -22005,-21930,-21856,-21781,-21705,-21630,-21554,-21479,
+ -21403,-21326,-21250,-21173,-21096,-21019,-20942,-20865,
+ -20787,-20709,-20631,-20553,-20475,-20396,-20317,-20238,
+ -20159,-20080,-20000,-19921,-19841,-19761,-19680,-19600,
+ -19519,-19438,-19357,-19276,-19195,-19113,-19032,-18950,
+ -18868,-18785,-18703,-18620,-18537,-18454,-18371,-18288,
+ -18204,-18121,-18037,-17953,-17869,-17784,-17700,-17615,
+ -17530,-17445,-17360,-17275,-17189,-17104,-17018,-16932,
+ -16846,-16759,-16673,-16586,-16499,-16413,-16325,-16238,
+ -16151,-16063,-15976,-15888,-15800,-15712,-15623,-15535,
+ -15446,-15358,-15269,-15180,-15090,-15001,-14912,-14822,
+ -14732,-14643,-14553,-14462,-14372,-14282,-14191,-14101,
+ -14010,-13919,-13828,-13736,-13645,-13554,-13462,-13370,
+ -13279,-13187,-13094,-13002,-12910,-12817,-12725,-12632,
+ -12539,-12446,-12353,-12260,-12167,-12074,-11980,-11886,
+ -11793,-11699,-11605,-11511,-11417,-11322,-11228,-11133,
+ -11039,-10944,-10849,-10754,-10659,-10564,-10469,-10374,
+ -10278,-10183,-10087,-9992,-9896,-9800,-9704,-9608,
+ -9512,-9416,-9319,-9223,-9126,-9030,-8933,-8836,
+ -8739,-8642,-8545,-8448,-8351,-8254,-8157,-8059,
+ -7962,-7864,-7767,-7669,-7571,-7473,-7375,-7277,
+ -7179,-7081,-6983,-6885,-6786,-6688,-6590,-6491,
+ -6393,-6294,-6195,-6096,-5998,-5899,-5800,-5701,
+ -5602,-5503,-5404,-5305,-5205,-5106,-5007,-4907,
+ -4808,-4708,-4609,-4509,-4410,-4310,-4210,-4111,
+ -4011,-3911,-3811,-3712,-3612,-3512,-3412,-3312,
+ -3212,-3112,-3012,-2911,-2811,-2711,-2611,-2511,
+ -2410,-2310,-2210,-2110,-2009,-1909,-1809,-1708,
+ -1608,-1507,-1407,-1307,-1206,-1106,-1005,-905,
+ -804,-704,-603,-503,-402,-302,-201,-101
+};
+#endif
+
diff --git a/arm-fm-22k/lib_src/eas_ima_tables.c b/arm-fm-22k/lib_src/eas_ima_tables.c
new file mode 100644
index 0000000..56bd1eb
--- /dev/null
+++ b/arm-fm-22k/lib_src/eas_ima_tables.c
@@ -0,0 +1,54 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_ima_tables.c
+ *
+ * Contents and purpose:
+ * Contains the constant tables for IMA encode/decode
+ *
+ * Copyright (c) 2005 Sonic Network Inc.
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 760 $
+ * $Date: 2007-07-17 23:09:36 -0700 (Tue, 17 Jul 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+#include "eas_types.h"
+
+/*----------------------------------------------------------------------------
+ * ADPCM decode tables
+ *----------------------------------------------------------------------------
+*/
+const EAS_I16 imaIndexTable[16] =
+{
+ -1, -1, -1, -1, 2, 4, 6, 8,
+ -1, -1, -1, -1, 2, 4, 6, 8
+};
+
+const EAS_I16 imaStepSizeTable[89] =
+{
+ 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
+ 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
+ 50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
+ 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
+ 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
+ 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
+ 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
+ 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
+ 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
+};
+
diff --git a/arm-fm-22k/lib_src/eas_imaadpcm.c b/arm-fm-22k/lib_src/eas_imaadpcm.c
new file mode 100644
index 0000000..68bf257
--- /dev/null
+++ b/arm-fm-22k/lib_src/eas_imaadpcm.c
@@ -0,0 +1,368 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_imaadpcm.c
+ *
+ * Contents and purpose:
+ * Implements the IMA ADPCM decoder
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 847 $
+ * $Date: 2007-08-27 21:30:08 -0700 (Mon, 27 Aug 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+#include "eas_data.h"
+#include "eas_host.h"
+#include "eas_pcm.h"
+#include "eas_math.h"
+#include "eas_report.h"
+
+// #define _DEBUG_IMA_ADPCM_LOCATE
+
+/*----------------------------------------------------------------------------
+ * externs
+ *----------------------------------------------------------------------------
+*/
+extern const EAS_I16 imaIndexTable[];
+extern const EAS_I16 imaStepSizeTable[];
+
+/*----------------------------------------------------------------------------
+ * prototypes
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT IMADecoderInit (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState);
+static EAS_RESULT IMADecoderSample (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState);
+static void IMADecoderADPCM (S_DECODER_STATE *pState, EAS_U8 nibble);
+static EAS_RESULT IMADecoderLocate (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState, EAS_I32 time);
+
+/*----------------------------------------------------------------------------
+ * IMA ADPCM Decoder interface
+ *----------------------------------------------------------------------------
+*/
+const S_DECODER_INTERFACE IMADecoder =
+{
+ IMADecoderInit,
+ IMADecoderSample,
+ IMADecoderLocate
+};
+
+/*----------------------------------------------------------------------------
+ * IMADecoderInit()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Initializes the IMA ADPCM decoder
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pEASData) common decoder interface - pEASData not used */
+static EAS_RESULT IMADecoderInit (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState)
+{
+ pState->decoderL.step = 0;
+ pState->decoderR.step = 0;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * IMADecoderSample()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Decodes an IMA ADPCM sample
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT IMADecoderSample (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState)
+{
+ EAS_RESULT result;
+ EAS_I16 sTemp;
+
+ /* if high nibble, decode */
+ if (pState->hiNibble)
+ {
+ IMADecoderADPCM(&pState->decoderL, (EAS_U8)(pState->srcByte >> 4));
+ pState->hiNibble = EAS_FALSE;
+ }
+
+ /* low nibble, need to fetch another byte */
+ else
+ {
+ /* check for loop */
+ if ((pState->bytesLeft == 0) && (pState->loopSamples != 0))
+ {
+ /* seek to start of loop */
+ if ((result = EAS_HWFileSeek(pEASData->hwInstData, pState->fileHandle, (EAS_I32) (pState->startPos + pState->loopLocation))) != EAS_SUCCESS)
+ return result;
+ pState->bytesLeft = pState->byteCount = (EAS_I32) pState->bytesLeftLoop;
+ pState->blockCount = 0;
+ pState->flags &= ~PCM_FLAGS_EMPTY;
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMADecoderSample: Rewind file to %d, bytesLeft = %d\n", pState->startPos, pState->bytesLeft); */ }
+ }
+
+ /* if start of block, fetch new predictor and step index */
+ if ((pState->blockSize != 0) && (pState->blockCount == 0) && (pState->bytesLeft != 0))
+ {
+
+ /* get predicted sample for left channel */
+ if ((result = EAS_HWGetWord(pEASData->hwInstData, pState->fileHandle, &sTemp, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+#ifdef _DEBUG_IMA_ADPCM
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Predictor: Was %d, now %d\n", pState->decoderL.acc, sTemp); */ }
+#endif
+ pState->decoderL.acc = pState->decoderL.x1 = sTemp;
+
+ /* get step index for left channel - upper 8 bits are reserved */
+ if ((result = EAS_HWGetWord(pEASData->hwInstData, pState->fileHandle, &sTemp, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+#ifdef _DEBUG_IMA_ADPCM
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Step: Was %d, now %d\n", pState->decoderL.step, sTemp); */ }
+#endif
+ pState->decoderL.step = sTemp & 0xff;
+
+ if (pState->flags & PCM_FLAGS_STEREO)
+ {
+ /* get predicted sample for right channel */
+ if ((result = EAS_HWGetWord(pEASData->hwInstData, pState->fileHandle, &sTemp, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+ pState->decoderR.acc = pState->decoderR.x1 = sTemp;
+
+ /* get step index for right channel - upper 8 bits are reserved */
+ if ((result = EAS_HWGetWord(pEASData->hwInstData, pState->fileHandle, &sTemp, EAS_FALSE)) != EAS_SUCCESS)
+ return result;
+#ifdef _DEBUG_IMA_ADPCM
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Step: Was %d, now %d\n", pState->decoderR.step, sTemp); */ }
+#endif
+ pState->decoderR.step = sTemp & 0xff;
+
+ pState->blockCount = pState->blockSize - 8;
+ pState->bytesLeft -= 8;
+ }
+ else
+ {
+ pState->blockCount = pState->blockSize - 4;
+ pState->bytesLeft -= 4;
+ }
+ }
+ else
+ {
+
+ /* get another ADPCM data pair */
+ if (pState->bytesLeft)
+ {
+
+ if ((result = EAS_HWGetByte(pEASData->hwInstData, pState->fileHandle, &pState->srcByte)) != EAS_SUCCESS)
+ return result;
+
+ /* decode the low nibble */
+ pState->bytesLeft--;
+ pState->blockCount--;
+ IMADecoderADPCM(&pState->decoderL, (EAS_U8)(pState->srcByte & 0x0f));
+
+ if (pState->flags & PCM_FLAGS_STEREO)
+ IMADecoderADPCM(&pState->decoderR, (EAS_U8)(pState->srcByte >> 4));
+ else
+ pState->hiNibble = EAS_TRUE;
+ }
+
+ /* out of ADPCM data, generate enough samples to fill buffer */
+ else
+ {
+ pState->decoderL.x1 = pState->decoderL.x0;
+ pState->decoderR.x1 = pState->decoderR.x0;
+ }
+ }
+ }
+
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * IMADecoderADPCM()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Decodes an IMA ADPCM sample
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static void IMADecoderADPCM (S_DECODER_STATE *pState, EAS_U8 nibble)
+{
+ EAS_INT delta;
+ EAS_INT stepSize;
+
+ /* get stepsize from table */
+ stepSize = imaStepSizeTable[pState->step];
+
+ /* delta = (abs(delta) + 0.5) * step / 4 */
+ delta = 0;
+ if (nibble & 4)
+ delta += stepSize;
+
+ if (nibble & 2)
+ /*lint -e{702} use shift for performance */
+ delta += stepSize >> 1;
+
+ if (nibble & 1)
+ /*lint -e{702} use shift for performance */
+ delta += stepSize >> 2;
+
+ /*lint -e{702} use shift for performance */
+ delta += stepSize >> 3;
+
+ /* integrate the delta */
+ if (nibble & 8)
+ pState->acc -= delta;
+ else
+ pState->acc += delta;
+
+ /* saturate */
+ if (pState->acc > 32767)
+ pState->acc = 32767;
+ if (pState->acc < -32768)
+ pState->acc = -32768;
+ pState->x1 = (EAS_PCM) pState->acc;
+
+ /* compute new step size */
+ pState->step += imaIndexTable[nibble];
+ if (pState->step < 0)
+ pState->step = 0;
+ if (pState->step > 88)
+ pState->step = 88;
+
+#ifdef _DEBUG_IMA_ADPCM
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "In=%u, Pred=%d, Step=%d\n", nibble, pState->acc, imaStepSizeTable[pState->step]); */ }
+#endif
+}
+
+/*----------------------------------------------------------------------------
+ * IMADecoderLocate()
+ *----------------------------------------------------------------------------
+ * Locate in an IMA ADPCM stream
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT IMADecoderLocate (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState, EAS_I32 time)
+{
+ EAS_RESULT result;
+ EAS_I32 temp;
+ EAS_I32 samplesPerBlock;
+ EAS_I32 secs, msecs;
+
+ /* no need to calculate if time is zero */
+ if (time == 0)
+ temp = 0;
+
+ /* not zero */
+ else
+ {
+
+ /* can't seek if not a blocked file */
+ if (pState->blockSize == 0)
+ return EAS_ERROR_FEATURE_NOT_AVAILABLE;
+
+ /* calculate number of samples per block */
+ if (pState->flags & PCM_FLAGS_STEREO)
+ samplesPerBlock = pState->blockSize - 7;
+ else
+ samplesPerBlock = (pState->blockSize << 1) - 7;
+
+ /* break down into secs and msecs */
+ secs = time / 1000;
+ msecs = time - (secs * 1000);
+
+ /* calculate sample number fraction from msecs */
+ temp = (msecs * pState->sampleRate);
+ temp = (temp >> 10) + ((temp * 49) >> 21);
+
+ /* add integer sample count */
+ temp += secs * pState->sampleRate;
+
+#ifdef _DEBUG_IMA_ADPCM_LOCATE
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x2380b977, 0x00000006 , time, temp);
+#endif
+
+ /* for looped samples, calculate position in the loop */
+ if ((temp > pState->byteCount) && (pState->loopSamples != 0))
+ {
+ EAS_I32 numBlocks;
+ EAS_I32 samplesPerLoop;
+ EAS_I32 samplesInLastBlock;
+
+ numBlocks = (EAS_I32) (pState->loopStart / pState->blockSize);
+ samplesInLastBlock = (EAS_I32) pState->loopStart - (numBlocks * pState->blockSize);
+ if (samplesInLastBlock)
+ {
+ if (pState->flags & PCM_FLAGS_STEREO)
+ samplesInLastBlock = samplesInLastBlock - 7;
+ else
+ /*lint -e{703} use shift for performance */
+ samplesInLastBlock = (samplesInLastBlock << 1) - 7;
+ }
+ samplesPerLoop = numBlocks * samplesPerBlock + samplesInLastBlock;
+ temp = temp % samplesPerLoop;
+#ifdef _DEBUG_IMA_ADPCM_LOCATE
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x2380b977, 0x00000007 , numBlocks, samplesPerLoop, samplesInLastBlock, temp);
+#endif
+ }
+
+ /* find start of block for requested sample */
+ temp = (temp / samplesPerBlock) * pState->blockSize;
+#ifdef _DEBUG_IMA_ADPCM_LOCATE
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x2380b977, 0x00000008 , temp);
+#endif
+
+ }
+
+ /* seek to new location */
+ if ((result = EAS_PESeek(pEASData, pState, &temp)) != EAS_SUCCESS)
+ return result;
+
+#ifdef _DEBUG_IMA_ADPCM_LOCATE
+ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x2380b977, 0x00000009 , pState->bytesLeft);
+#endif
+
+ /* reset state */
+ pState->blockCount = 0;
+ pState->hiNibble = EAS_FALSE;
+ if ((pState->state != EAS_STATE_PAUSING) && (pState->state != EAS_STATE_PAUSED))
+ pState->state = EAS_STATE_READY;
+
+ return EAS_SUCCESS;
+}
+
diff --git a/arm-fm-22k/lib_src/eas_imelody.c b/arm-fm-22k/lib_src/eas_imelody.c
new file mode 100644
index 0000000..9f4d541
--- /dev/null
+++ b/arm-fm-22k/lib_src/eas_imelody.c
@@ -0,0 +1,1738 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_imelody.c
+ *
+ * Contents and purpose:
+ * iMelody parser
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 797 $
+ * $Date: 2007-08-01 00:15:56 -0700 (Wed, 01 Aug 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+/* lint doesn't like the way some string.h files look */
+#ifdef _lint
+#include "lint_stdlib.h"
+#else
+#include <string.h>
+#endif
+
+#include "eas_data.h"
+#include "eas_miditypes.h"
+#include "eas_parser.h"
+#include "eas_report.h"
+#include "eas_host.h"
+#include "eas_midi.h"
+#include "eas_config.h"
+#include "eas_vm_protos.h"
+#include "eas_imelodydata.h"
+#include "eas_ctype.h"
+
+// #define _DEBUG_IMELODY
+
+/* increase gain for mono ringtones */
+#define IMELODY_GAIN_OFFSET 8
+
+/* length of 32nd note in 1/256ths of a msec for 120 BPM tempo */
+#define DEFAULT_TICK_CONV 16000
+#define TICK_CONVERT 1920000
+
+/* default channel and program for iMelody playback */
+#define IMELODY_CHANNEL 0
+#define IMELODY_PROGRAM 80
+#define IMELODY_VEL_MUL 4
+#define IMELODY_VEL_OFS 67
+
+/* multiplier for fixed point triplet conversion */
+#define TRIPLET_MULTIPLIER 683
+#define TRIPLET_SHIFT 10
+
+static const char* const tokens[] =
+{
+ "BEGIN:IMELODY",
+ "VERSION:",
+ "FORMAT:CLASS",
+ "NAME:",
+ "COMPOSER:",
+ "BEAT:",
+ "STYLE:",
+ "VOLUME:",
+ "MELODY:",
+ "END:IMELODY"
+};
+
+/* ledon or ledoff */
+static const char ledStr[] = "edo";
+
+/* vibeon or vibeoff */
+static const char vibeStr[] = "ibeo";
+
+/* backon or backoff */
+static const char backStr[] = "cko";
+
+typedef enum
+{
+ TOKEN_BEGIN,
+ TOKEN_VERSION,
+ TOKEN_FORMAT,
+ TOKEN_NAME,
+ TOKEN_COMPOSER,
+ TOKEN_BEAT,
+ TOKEN_STYLE,
+ TOKEN_VOLUME,
+ TOKEN_MELODY,
+ TOKEN_END,
+ TOKEN_INVALID
+} ENUM_IMELODY_TOKENS;
+
+/* lookup table for note values */
+static const EAS_I8 noteTable[] = { 9, 11, 0, 2, 4, 5, 7 };
+
+/* inline functions */
+#ifdef _DEBUG_IMELODY
+static void PutBackChar (S_IMELODY_DATA *pData)
+{
+ if (pData->index)
+ pData->index--;
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "PutBackChar '%c'\n", pData->buffer[pData->index]); */ }
+}
+#else
+EAS_INLINE void PutBackChar (S_IMELODY_DATA *pData) { if (pData->index) pData->index--; }
+#endif
+
+
+/* local prototypes */
+static EAS_RESULT IMY_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset);
+static EAS_RESULT IMY_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
+static EAS_RESULT IMY_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime);
+static EAS_RESULT IMY_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode);
+static EAS_RESULT IMY_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState);
+static EAS_RESULT IMY_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
+static EAS_RESULT IMY_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
+static EAS_RESULT IMY_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
+static EAS_RESULT IMY_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
+static EAS_RESULT IMY_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value);
+static EAS_RESULT IMY_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue);
+static EAS_BOOL IMY_PlayNote (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData, EAS_I8 note, EAS_INT parserMode);
+static EAS_BOOL IMY_PlayRest (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData);
+static EAS_BOOL IMY_GetDuration (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_I32 *pDuration);
+static EAS_BOOL IMY_GetLEDState (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData);
+static EAS_BOOL IMY_GetVibeState (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData);
+static EAS_BOOL IMY_GetBackState (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData);
+static EAS_BOOL IMY_GetVolume (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_BOOL inHeader);
+static EAS_BOOL IMY_GetNumber (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_INT *temp, EAS_BOOL inHeader);
+static EAS_RESULT IMY_ParseHeader (S_EAS_DATA *pEASData, S_IMELODY_DATA* pData);
+static EAS_I8 IMY_GetNextChar (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_BOOL inHeader);
+static EAS_RESULT IMY_ReadLine (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_I8 *buffer, EAS_I32 *pStartLine);
+static EAS_INT IMY_ParseLine (EAS_I8 *buffer, EAS_U8 *pIndex);
+
+
+/*----------------------------------------------------------------------------
+ *
+ * EAS_iMelody_Parser
+ *
+ * This structure contains the functional interface for the iMelody parser
+ *----------------------------------------------------------------------------
+*/
+const S_FILE_PARSER_INTERFACE EAS_iMelody_Parser =
+{
+ IMY_CheckFileType,
+ IMY_Prepare,
+ IMY_Time,
+ IMY_Event,
+ IMY_State,
+ IMY_Close,
+ IMY_Reset,
+ IMY_Pause,
+ IMY_Resume,
+ NULL,
+ IMY_SetData,
+ IMY_GetData,
+ NULL
+};
+
+/*----------------------------------------------------------------------------
+ * IMY_CheckFileType()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Check the file type to see if we can parse it
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT IMY_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset)
+{
+ S_IMELODY_DATA* pData;
+ EAS_I8 buffer[MAX_LINE_SIZE+1];
+ EAS_U8 index;
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_CheckFileType\n"); */ }
+#endif
+
+ /* read the first line of the file */
+ *ppHandle = NULL;
+ if (IMY_ReadLine(pEASData->hwInstData, fileHandle, buffer, NULL) != EAS_SUCCESS)
+ return EAS_SUCCESS;
+
+ /* check for header string */
+ if (IMY_ParseLine(buffer, &index) == TOKEN_BEGIN)
+ {
+
+ /* check for static memory allocation */
+ if (pEASData->staticMemoryModel)
+ pData = EAS_CMEnumData(EAS_CM_IMELODY_DATA);
+ else
+ pData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_IMELODY_DATA));
+ if (!pData)
+ return EAS_ERROR_MALLOC_FAILED;
+ EAS_HWMemSet(pData, 0, sizeof(S_IMELODY_DATA));
+
+ /* initialize */
+ pData->fileHandle = fileHandle;
+ pData->fileOffset = offset;
+ pData->state = EAS_STATE_ERROR;
+ pData->state = EAS_STATE_OPEN;
+
+ /* return a pointer to the instance data */
+ *ppHandle = pData;
+ }
+
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_Prepare()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Prepare to parse the file. Allocates instance data (or uses static allocation for
+ * static memory model).
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT IMY_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
+{
+ S_IMELODY_DATA* pData;
+ EAS_RESULT result;
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_Prepare\n"); */ }
+#endif
+
+ /* check for valid state */
+ pData = (S_IMELODY_DATA*) pInstData;
+ if (pData->state != EAS_STATE_OPEN)
+ return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
+
+ /* instantiate a synthesizer */
+ if ((result = VMInitMIDI(pEASData, &pData->pSynth)) != EAS_SUCCESS)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMInitMIDI returned %d\n", result); */ }
+ return result;
+ }
+
+ /* parse the header */
+ if ((result = IMY_ParseHeader(pEASData, pData)) != EAS_SUCCESS)
+ return result;
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Prepare: state set to EAS_STATE_READY\n"); */ }
+#endif
+
+ pData ->state = EAS_STATE_READY;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_Time()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Returns the time of the next event in msecs
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ * pTime - pointer to variable to hold time of next event (in msecs)
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pEASData) common decoder interface - pEASData not used */
+static EAS_RESULT IMY_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime)
+{
+ S_IMELODY_DATA *pData;
+
+ pData = (S_IMELODY_DATA*) pInstData;
+
+ /* return time in milliseconds */
+ /*lint -e{704} use shift instead of division */
+ *pTime = pData->time >> 8;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_Event()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Parse the next event in the file
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT IMY_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode)
+{
+ S_IMELODY_DATA* pData;
+ EAS_RESULT result;
+ EAS_I8 c;
+ EAS_BOOL eof;
+ EAS_INT temp;
+
+ pData = (S_IMELODY_DATA*) pInstData;
+ if (pData->state >= EAS_STATE_OPEN)
+ return EAS_SUCCESS;
+
+ /* initialize MIDI channel when the track starts playing */
+ if (pData->time == 0)
+ {
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Event: Reset\n"); */ }
+#endif
+ /* set program to square lead */
+ VMProgramChange(pEASData->pVoiceMgr, pData->pSynth, IMELODY_CHANNEL, IMELODY_PROGRAM);
+
+ /* set channel volume to max */
+ VMControlChange(pEASData->pVoiceMgr, pData->pSynth, IMELODY_CHANNEL, 7, 127);
+ }
+
+ /* check for end of note */
+ if (pData->note)
+ {
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Stopping note %d\n", pData->note); */ }
+#endif
+ /* stop the note */
+ VMStopNote(pEASData->pVoiceMgr, pData->pSynth, IMELODY_CHANNEL, pData->note, 0);
+ pData->note = 0;
+
+ /* check for rest between notes */
+ if (pData->restTicks)
+ {
+ pData->time += pData->restTicks;
+ pData->restTicks = 0;
+ return EAS_SUCCESS;
+ }
+ }
+
+ /* parse the next event */
+ eof = EAS_FALSE;
+ while (!eof)
+ {
+
+ /* get next character */
+ c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_FALSE);
+
+ switch (c)
+ {
+ /* start repeat */
+ case '(':
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter repeat section\n", c); */ }
+#endif
+
+ if (pData->repeatOffset < 0)
+ {
+ pData->repeatOffset = pData->startLine + (EAS_I32) pData->index;
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Repeat offset = %d\n", pData->repeatOffset); */ }
+#endif
+ }
+ else
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Ignoring nested repeat section\n"); */ }
+ break;
+
+ /* end repeat */
+ case ')':
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "End repeat section, repeat offset = %d\n", pData->repeatOffset); */ }
+#endif
+ /* ignore invalid repeats */
+ if (pData->repeatCount >= 0)
+ {
+
+ /* decrement repeat count (repeatCount == 0 means infinite loop) */
+ if (pData->repeatCount > 0)
+ {
+ if (--pData->repeatCount == 0)
+ {
+ pData->repeatCount = -1;
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Repeat loop complete\n"); */ }
+#endif
+ }
+ }
+
+//2 TEMPORARY FIX: If locating, don't do infinite loops.
+//3 We need a different mode for metadata parsing where we don't loop at all
+ if ((parserMode == eParserModePlay) || (pData->repeatCount != 0))
+ {
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Rewinding file for repeat\n"); */ }
+#endif
+ /* rewind to start of loop */
+ if ((result = EAS_HWFileSeek(pEASData->hwInstData, pData->fileHandle, pData->repeatOffset)) != EAS_SUCCESS)
+ return result;
+ IMY_ReadLine(pEASData->hwInstData, pData->fileHandle, pData->buffer, &pData->startLine);
+ pData->index = 0;
+
+ /* if last loop, prevent future loops */
+ if (pData->repeatCount == -1)
+ pData->repeatOffset = -1;
+ }
+ }
+ break;
+
+ /* repeat count */
+ case '@':
+ if (!IMY_GetNumber(pEASData->hwInstData, pData, &temp, EAS_FALSE))
+ eof = EAS_TRUE;
+ else if (pData->repeatOffset > 0)
+ {
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Repeat count = %dt", pData->repeatCount); */ }
+#endif
+ if (pData->repeatCount < 0)
+ pData->repeatCount = (EAS_I16) temp;
+ }
+ break;
+
+ /* volume */
+ case 'V':
+ if (!IMY_GetVolume(pEASData->hwInstData, pData, EAS_FALSE))
+ eof = EAS_TRUE;
+ break;
+
+ /* flat */
+ case '&':
+ pData->noteModifier = -1;
+ break;
+
+ /* sharp */
+ case '#':
+ pData->noteModifier = +1;
+ break;
+
+ /* octave */
+ case '*':
+ c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_FALSE);
+ if (IsDigit(c))
+ pData->octave = (EAS_U8) ((c - '0' + 1) * 12);
+ else if (!c)
+ eof = EAS_TRUE;
+ break;
+
+ /* ledon or ledoff */
+ case 'l':
+ if (!IMY_GetLEDState(pEASData, pData))
+ eof = EAS_TRUE;
+ break;
+
+ /* vibeon or vibeoff */
+ case 'v':
+ if (!IMY_GetVibeState(pEASData, pData))
+ eof = EAS_TRUE;
+ break;
+
+ /* either a B note or backon or backoff */
+ case 'b':
+ if (IMY_GetNextChar(pEASData->hwInstData, pData, EAS_FALSE) == 'a')
+ {
+ if (!IMY_GetBackState(pEASData, pData))
+ eof = EAS_TRUE;
+ }
+ else
+ {
+ PutBackChar(pData);
+ if (IMY_PlayNote(pEASData, pData, c, parserMode))
+ return EAS_SUCCESS;
+ eof = EAS_TRUE;
+ }
+ break;
+
+ /* rest */
+ case 'r':
+ case 'R':
+ if (IMY_PlayRest(pEASData, pData))
+ return EAS_SUCCESS;
+ eof = EAS_TRUE;
+ break;
+
+ /* EOF */
+ case 0:
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Event: end of iMelody file detected\n"); */ }
+#endif
+ eof = EAS_TRUE;
+ break;
+
+ /* must be a note */
+ default:
+ c = ToLower(c);
+ if ((c >= 'a') && (c <= 'g'))
+ {
+ if (IMY_PlayNote(pEASData, pData, c, parserMode))
+ return EAS_SUCCESS;
+ eof = EAS_TRUE;
+ }
+ else
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Ignoring unexpected character '%c' [0x%02x]\n", c, c); */ }
+ break;
+ }
+ }
+
+ /* handle EOF */
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Event: state set to EAS_STATE_STOPPING\n"); */ }
+#endif
+ pData->state = EAS_STATE_STOPPING;
+ VMReleaseAllVoices(pEASData->pVoiceMgr, pData->pSynth);
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_State()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Returns the current state of the stream
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ * pState - pointer to variable to store state
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pEASData) common decoder interface - pEASData not used */
+static EAS_RESULT IMY_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pState)
+{
+ S_IMELODY_DATA* pData;
+
+ /* establish pointer to instance data */
+ pData = (S_IMELODY_DATA*) pInstData;
+
+ /* if stopping, check to see if synth voices are active */
+ if (pData->state == EAS_STATE_STOPPING)
+ {
+ if (VMActiveVoices(pData->pSynth) == 0)
+ {
+ pData->state = EAS_STATE_STOPPED;
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_State: state set to EAS_STATE_STOPPED\n"); */ }
+#endif
+ }
+ }
+
+ if (pData->state == EAS_STATE_PAUSING)
+ {
+ if (VMActiveVoices(pData->pSynth) == 0)
+ {
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_State: state set to EAS_STATE_PAUSED\n"); */ }
+#endif
+ pData->state = EAS_STATE_PAUSED;
+ }
+ }
+
+ /* return current state */
+ *pState = pData->state;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_Close()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Close the file and clean up
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT IMY_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
+{
+ S_IMELODY_DATA* pData;
+ EAS_RESULT result;
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Close: close file\n"); */ }
+#endif
+
+ pData = (S_IMELODY_DATA*) pInstData;
+
+ /* close the file */
+ if ((result = EAS_HWCloseFile(pEASData->hwInstData, pData->fileHandle)) != EAS_SUCCESS)
+ return result;
+
+ /* free the synth */
+ if (pData->pSynth != NULL)
+ VMMIDIShutdown(pEASData, pData->pSynth);
+
+ /* if using dynamic memory, free it */
+ if (!pEASData->staticMemoryModel)
+ EAS_HWFree(pEASData->hwInstData, pData);
+
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_Reset()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Reset the sequencer. Used for locating backwards in the file.
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT IMY_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
+{
+ S_IMELODY_DATA* pData;
+ EAS_RESULT result;
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Reset: reset file\n"); */ }
+#endif
+ pData = (S_IMELODY_DATA*) pInstData;
+
+ /* reset the synth */
+ VMReset(pEASData->pVoiceMgr, pData->pSynth, EAS_TRUE);
+
+ /* reset time to zero */
+ pData->time = 0;
+ pData->note = 0;
+
+ /* reset file position and re-parse header */
+ pData->state = EAS_STATE_ERROR;
+ if ((result = EAS_HWFileSeek(pEASData->hwInstData, pData->fileHandle, pData->fileOffset)) != EAS_SUCCESS)
+ return result;
+ if ((result = IMY_ParseHeader (pEASData, pData)) != EAS_SUCCESS)
+ return result;
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Reset: state set to EAS_STATE_ERROR\n"); */ }
+#endif
+
+ pData->state = EAS_STATE_READY;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_Pause()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Pauses the sequencer. Mutes all voices and sets state to pause.
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT IMY_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
+{
+ S_IMELODY_DATA *pData;
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Pause: pause file\n"); */ }
+#endif
+
+ /* can't pause a stopped stream */
+ pData = (S_IMELODY_DATA*) pInstData;
+ if (pData->state == EAS_STATE_STOPPED)
+ return EAS_ERROR_ALREADY_STOPPED;
+
+ /* mute the synthesizer */
+ VMMuteAllVoices(pEASData->pVoiceMgr, pData->pSynth);
+ pData->state = EAS_STATE_PAUSING;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_Resume()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Resume playing after a pause, sets state back to playing.
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pEASData) common decoder interface - pEASData not used */
+static EAS_RESULT IMY_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
+{
+ S_IMELODY_DATA *pData;
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Resume: resume file\n"); */ }
+#endif
+
+ /* can't resume a stopped stream */
+ pData = (S_IMELODY_DATA*) pInstData;
+ if (pData->state == EAS_STATE_STOPPED)
+ return EAS_ERROR_ALREADY_STOPPED;
+
+ /* nothing to do but resume playback */
+ pData->state = EAS_STATE_PLAY;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_SetData()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Adjust tempo relative to song tempo
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * pInstData - pointer to iMelody instance data
+ * rate - rate (28-bit fractional amount)
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pEASData) common decoder interface - pEASData not used */
+static EAS_RESULT IMY_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value)
+{
+ S_IMELODY_DATA *pData;
+
+ pData = (S_IMELODY_DATA*) pInstData;
+ switch (param)
+ {
+
+ /* set metadata callback */
+ case PARSER_DATA_METADATA_CB:
+ EAS_HWMemCpy(&pData->metadata, (void*) value, sizeof(S_METADATA_CB));
+ break;
+
+ default:
+ return EAS_ERROR_INVALID_PARAMETER;
+ }
+
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_GetData()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Return the file type
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * pInstData - pointer to iMelody instance data
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pEASData) common decoder interface - pEASData not used */
+static EAS_RESULT IMY_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue)
+{
+ S_IMELODY_DATA *pData;
+
+ pData = (S_IMELODY_DATA*) pInstData;
+
+ switch (param)
+ {
+ /* return file type as iMelody */
+ case PARSER_DATA_FILE_TYPE:
+ *pValue = EAS_FILE_IMELODY;
+ break;
+
+ case PARSER_DATA_SYNTH_HANDLE:
+ *pValue = (EAS_I32) pData->pSynth;
+ break;
+
+ case PARSER_DATA_GAIN_OFFSET:
+ *pValue = IMELODY_GAIN_OFFSET;
+ break;
+
+ default:
+ return EAS_ERROR_INVALID_PARAMETER;
+ }
+
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_PlayNote()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_BOOL IMY_PlayNote (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData, EAS_I8 note, EAS_INT parserMode)
+{
+ EAS_I32 duration;
+ EAS_U8 velocity;
+
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_PlayNote: start note %d\n", note); */ }
+#endif
+
+ /* get the duration */
+ if (!IMY_GetDuration(pEASData->hwInstData, pData, &duration))
+ return EAS_FALSE;
+
+ /* save note value */
+ pData->note = (EAS_U8) (pData->octave + noteTable[note - 'a'] + pData->noteModifier);
+ velocity = (EAS_U8) (pData->volume ? pData->volume * IMELODY_VEL_MUL + IMELODY_VEL_OFS : 0);
+
+ /* start note only if in play mode */
+ if (parserMode == eParserModePlay)
+ VMStartNote(pEASData->pVoiceMgr, pData->pSynth, IMELODY_CHANNEL, pData->note, velocity);
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_PlayNote: Start note %d, duration %d\n", pData->note, duration); */ }
+#endif
+
+ /* determine note length */
+ switch (pData->style)
+ {
+ case 0:
+ /*lint -e{704} shift for performance */
+ pData->restTicks = duration >> 4;
+ break;
+ case 1:
+ pData->restTicks = 0;
+ break;
+ case 2:
+ /*lint -e{704} shift for performance */
+ pData->restTicks = duration >> 1;
+ break;
+ default:
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "IMY_PlayNote: Note style out of range: %d\n", pData->style); */ }
+ /*lint -e{704} shift for performance */
+ pData->restTicks = duration >> 4;
+ break;
+ }
+
+ /* next event is at end of this note */
+ pData->time += duration - pData->restTicks;
+
+ /* reset the flat/sharp modifier */
+ pData->noteModifier = 0;
+
+ return EAS_TRUE;
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_PlayRest()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_BOOL IMY_PlayRest (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData)
+{
+ EAS_I32 duration;
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_PlayRest]n"); */ }
+#endif
+
+ /* get the duration */
+ if (!IMY_GetDuration(pEASData->hwInstData, pData, &duration))
+ return EAS_FALSE;
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_PlayRest: note duration %d\n", duration); */ }
+#endif
+
+ /* next event is at end of this note */
+ pData->time += duration;
+ return EAS_TRUE;
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_GetDuration()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+
+static EAS_BOOL IMY_GetDuration (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_I32 *pDuration)
+{
+ EAS_I32 duration;
+ EAS_I8 c;
+
+ /* get the duration */
+ *pDuration = 0;
+ c = IMY_GetNextChar(hwInstData, pData, EAS_FALSE);
+ if (!c)
+ return EAS_FALSE;
+ if ((c < '0') || (c > '5'))
+ {
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetDuration: error in duration '%c'\n", c); */ }
+#endif
+ return EAS_FALSE;
+ }
+
+ /* calculate total length of note */
+ duration = pData->tick * (1 << ('5' - c));
+
+ /* check for duration modifier */
+ c = IMY_GetNextChar(hwInstData, pData, EAS_FALSE);
+ if (c)
+ {
+ if (c == '.')
+ /*lint -e{704} shift for performance */
+ duration += duration >> 1;
+ else if (c == ':')
+ /*lint -e{704} shift for performance */
+ duration += (duration >> 1) + (duration >> 2);
+ else if (c == ';')
+ /*lint -e{704} shift for performance */
+ duration = (duration * TRIPLET_MULTIPLIER) >> TRIPLET_SHIFT;
+ else
+ PutBackChar(pData);
+ }
+
+ *pDuration = duration;
+ return EAS_TRUE;
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_GetLEDState()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_BOOL IMY_GetLEDState (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData)
+{
+ EAS_I8 c;
+ EAS_INT i;
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_GetLEDState\n"); */ }
+#endif
+
+ for (i = 0; i < 5; i++)
+ {
+ c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_FALSE);
+ if (!c)
+ return EAS_FALSE;
+ switch (i)
+ {
+ case 3:
+ if (c == 'n')
+ {
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetLEDState: LED on\n"); */ }
+#endif
+ EAS_HWLED(pEASData->hwInstData, EAS_TRUE);
+ return EAS_TRUE;
+ }
+ else if (c != 'f')
+ return EAS_FALSE;
+ break;
+
+ case 4:
+ if (c == 'f')
+ {
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetLEDState: LED off\n"); */ }
+#endif
+ EAS_HWLED(pEASData->hwInstData, EAS_FALSE);
+ return EAS_TRUE;
+ }
+ return EAS_FALSE;
+
+ default:
+ if (c != ledStr[i])
+ return EAS_FALSE;
+ break;
+ }
+ }
+ return EAS_FALSE;
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_GetVibeState()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_BOOL IMY_GetVibeState (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData)
+{
+ EAS_I8 c;
+ EAS_INT i;
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_GetVibeState\n"); */ }
+#endif
+
+ for (i = 0; i < 6; i++)
+ {
+ c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_FALSE);
+ if (!c)
+ return EAS_FALSE;
+ switch (i)
+ {
+ case 4:
+ if (c == 'n')
+ {
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetVibeState: vibrate on\n"); */ }
+#endif
+ EAS_HWVibrate(pEASData->hwInstData, EAS_TRUE);
+ return EAS_TRUE;
+ }
+ else if (c != 'f')
+ return EAS_FALSE;
+ break;
+
+ case 5:
+ if (c == 'f')
+ {
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetVibeState: vibrate off\n"); */ }
+#endif
+ EAS_HWVibrate(pEASData->hwInstData, EAS_FALSE);
+ return EAS_TRUE;
+ }
+ return EAS_FALSE;
+
+ default:
+ if (c != vibeStr[i])
+ return EAS_FALSE;
+ break;
+ }
+ }
+ return EAS_FALSE;
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_GetBackState()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_BOOL IMY_GetBackState (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData)
+{
+ EAS_I8 c;
+ EAS_INT i;
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_GetBackState\n"); */ }
+#endif
+
+ for (i = 0; i < 5; i++)
+ {
+ c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_FALSE);
+ if (!c)
+ return EAS_FALSE;
+ switch (i)
+ {
+ case 3:
+ if (c == 'n')
+ {
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetBackState: backlight on\n"); */ }
+#endif
+ EAS_HWBackLight(pEASData->hwInstData, EAS_TRUE);
+ return EAS_TRUE;
+ }
+ else if (c != 'f')
+ return EAS_FALSE;
+ break;
+
+ case 4:
+ if (c == 'f')
+ {
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetBackState: backlight off\n"); */ }
+#endif
+ EAS_HWBackLight(pEASData->hwInstData, EAS_FALSE);
+ return EAS_TRUE;
+ }
+ return EAS_FALSE;
+
+ default:
+ if (c != backStr[i])
+ return EAS_FALSE;
+ break;
+ }
+ }
+ return EAS_FALSE;
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_GetVolume()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_BOOL IMY_GetVolume (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_BOOL inHeader)
+{
+ EAS_INT temp;
+ EAS_I8 c;
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_GetVolume\n"); */ }
+#endif
+
+ c = IMY_GetNextChar(hwInstData, pData, inHeader);
+ if (c == '+')
+ {
+ if (pData->volume < 15)
+ pData->volume++;
+ return EAS_TRUE;
+ }
+ else if (c == '-')
+ {
+ if (pData->volume > 0)
+ pData->volume--;
+ return EAS_TRUE;
+ }
+ else if (IsDigit(c))
+ temp = c - '0';
+ else
+ return EAS_FALSE;
+
+ c = IMY_GetNextChar(hwInstData, pData, inHeader);
+ if (IsDigit(c))
+ temp = temp * 10 + c - '0';
+ else if (c)
+ PutBackChar(pData);
+ if ((temp >= 0) && (temp <= 15))
+ {
+ if (inHeader && (temp == 0))
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Ignoring V0 encountered in header\n"); */ }
+ else
+ pData->volume = (EAS_U8) temp;
+ }
+ return EAS_TRUE;
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_GetNumber()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_BOOL IMY_GetNumber (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_INT *temp, EAS_BOOL inHeader)
+{
+ EAS_BOOL ok;
+ EAS_I8 c;
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_GetNumber\n"); */ }
+#endif
+
+ *temp = 0;
+ ok = EAS_FALSE;
+ for (;;)
+ {
+ c = IMY_GetNextChar(hwInstData, pData, inHeader);
+ if (IsDigit(c))
+ {
+ *temp = *temp * 10 + c - '0';
+ ok = EAS_TRUE;
+ }
+ else
+ {
+ if (c)
+ PutBackChar(pData);
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetNumber: value %d\n", *temp); */ }
+#endif
+
+ return ok;
+ }
+ }
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_GetVersion()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_BOOL IMY_GetVersion (S_IMELODY_DATA *pData, EAS_INT *pVersion)
+{
+ EAS_I8 c;
+ EAS_INT temp;
+ EAS_INT version;
+
+ version = temp = 0;
+ for (;;)
+ {
+ c = pData->buffer[pData->index++];
+ if ((c == 0) || (c == '.'))
+ {
+ /*lint -e{701} use shift for performance */
+ version = (version << 8) + temp;
+ if (c == 0)
+ {
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetVersion: version 0x%04x\n", version); */ }
+#endif
+
+ *pVersion = version;
+ return EAS_TRUE;
+ }
+ temp = 0;
+ }
+ else if (IsDigit(c))
+ temp = (temp * 10) + c - '0';
+ }
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_MetaData()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Prepare to parse the file. Allocates instance data (or uses static allocation for
+ * static memory model).
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static void IMY_MetaData (S_IMELODY_DATA *pData, E_EAS_METADATA_TYPE metaType, EAS_I8 *buffer)
+{
+ EAS_I32 len;
+
+ /* check for callback */
+ if (!pData->metadata.callback)
+ return;
+
+ /* copy data to host buffer */
+ len = (EAS_I32) strlen((char*) buffer);
+ if (len >pData->metadata.bufferSize)
+ len = pData->metadata.bufferSize;
+ strncpy((char*) pData->metadata.buffer, (char*) buffer, (size_t) len);
+ pData->metadata.buffer[len] = 0;
+
+ /* callback to host */
+ pData->metadata.callback(metaType, pData->metadata.buffer, pData->metadata.pUserData);
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_ParseHeader()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Prepare to parse the file. Allocates instance data (or uses static allocation for
+ * static memory model).
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT IMY_ParseHeader (S_EAS_DATA *pEASData, S_IMELODY_DATA* pData)
+{
+ EAS_RESULT result;
+ EAS_INT token;
+ EAS_INT temp;
+ EAS_I8 c;
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_ParseHeader\n"); */ }
+#endif
+
+ /* initialize some defaults */
+ pData->time = 0;
+ pData->tick = DEFAULT_TICK_CONV;
+ pData->note = 0;
+ pData->noteModifier = 0;
+ pData ->restTicks = 0;
+ pData->volume = 7;
+ pData->octave = 60;
+ pData->repeatOffset = -1;
+ pData->repeatCount = -1;
+ pData->style = 0;
+
+ /* force the read of the first line */
+ pData->index = 1;
+
+ /* read data until we get to melody */
+ for (;;)
+ {
+ /* read a line from the file and parse the token */
+ if (pData->index != 0)
+ {
+ if ((result = IMY_ReadLine(pEASData->hwInstData, pData->fileHandle, pData->buffer, &pData->startLine)) != EAS_SUCCESS)
+ {
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_ParseHeader: IMY_ReadLine returned %d\n", result); */ }
+#endif
+ return result;
+ }
+ }
+ token = IMY_ParseLine(pData->buffer, &pData->index);
+
+ switch (token)
+ {
+ /* ignore these valid tokens */
+ case TOKEN_BEGIN:
+ break;
+
+ case TOKEN_FORMAT:
+ if (!IMY_GetVersion(pData, &temp))
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Invalid FORMAT field '%s'\n", pData->buffer); */ }
+ return EAS_ERROR_FILE_FORMAT;
+ }
+ if ((temp != 0x0100) && (temp != 0x0200))
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Unsupported FORMAT %02x\n", temp); */ }
+ return EAS_ERROR_UNRECOGNIZED_FORMAT;
+ }
+ break;
+
+ case TOKEN_VERSION:
+ if (!IMY_GetVersion(pData, &temp))
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Invalid VERSION field '%s'\n", pData->buffer); */ }
+ return EAS_ERROR_FILE_FORMAT;
+ }
+ if ((temp != 0x0100) && (temp != 0x0102))
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Unsupported VERSION %02x\n", temp); */ }
+ return EAS_ERROR_UNRECOGNIZED_FORMAT;
+ }
+ break;
+
+ case TOKEN_NAME:
+ IMY_MetaData(pData, EAS_METADATA_TITLE, pData->buffer + pData->index);
+ break;
+
+ case TOKEN_COMPOSER:
+ IMY_MetaData(pData, EAS_METADATA_AUTHOR, pData->buffer + pData->index);
+ break;
+
+ /* handle beat */
+ case TOKEN_BEAT:
+ IMY_GetNumber(pEASData->hwInstData, pData, &temp, EAS_TRUE);
+ if ((temp >= 25) && (temp <= 900))
+ pData->tick = TICK_CONVERT / temp;
+ break;
+
+ /* handle style */
+ case TOKEN_STYLE:
+ c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_TRUE);
+ if (c == 'S')
+ c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_TRUE);
+ if ((c >= '0') && (c <= '2'))
+ pData->style = (EAS_U8) (c - '0');
+ else
+ {
+ PutBackChar(pData);
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Error in style command: %s\n", pData->buffer); */ }
+ }
+ break;
+
+ /* handle volume */
+ case TOKEN_VOLUME:
+ c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_TRUE);
+ if (c != 'V')
+ {
+ PutBackChar(pData);
+ if (!IsDigit(c))
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Error in volume command: %s\n", pData->buffer); */ }
+ break;
+ }
+ }
+ IMY_GetVolume(pEASData->hwInstData, pData, EAS_TRUE);
+ break;
+
+ case TOKEN_MELODY:
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Header successfully parsed\n"); */ }
+#endif
+ return EAS_SUCCESS;
+
+ case TOKEN_END:
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Unexpected END:IMELODY encountered\n"); */ }
+ return EAS_ERROR_FILE_FORMAT;
+
+ default:
+ /* force a read of the next line */
+ pData->index = 1;
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Ignoring unrecognized token in iMelody file: %s\n", pData->buffer); */ }
+ break;
+ }
+ }
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_GetNextChar()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_I8 IMY_GetNextChar (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_BOOL inHeader)
+{
+ EAS_I8 c;
+ EAS_U8 index;
+
+ for (;;)
+ {
+ /* get next character */
+ c = pData->buffer[pData->index++];
+
+ /* buffer empty, read more */
+ if (!c)
+ {
+ /* don't read the next line in the header */
+ if (inHeader)
+ return 0;
+
+ pData->index = 0;
+ pData->buffer[0] = 0;
+ if (IMY_ReadLine(hwInstData, pData->fileHandle, pData->buffer, &pData->startLine) != EAS_SUCCESS)
+ {
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetNextChar: EOF\n"); */ }
+#endif
+ return 0;
+ }
+
+ /* check for END:IMELODY token */
+ if (IMY_ParseLine(pData->buffer, &index) == TOKEN_END)
+ {
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetNextChar: found END:IMELODY\n"); */ }
+#endif
+ pData->buffer[0] = 0;
+ return 0;
+ }
+ continue;
+ }
+
+ /* ignore white space */
+ if (!IsSpace(c))
+ {
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetNextChar returned '%c'\n", c); */ }
+#endif
+ return c;
+ }
+ }
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_ReadLine()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Reads a line of input from the file, discarding the CR/LF
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT IMY_ReadLine (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_I8 *buffer, EAS_I32 *pStartLine)
+{
+ EAS_RESULT result;
+ EAS_INT i;
+ EAS_I8 c;
+
+ /* fetch current file position and save it */
+ if (pStartLine != NULL)
+ {
+ if ((result = EAS_HWFilePos(hwInstData, fileHandle, pStartLine)) != EAS_SUCCESS)
+ {
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_ParseHeader: EAS_HWFilePos returned %d\n", result); */ }
+#endif
+ return result;
+ }
+ }
+
+ buffer[0] = 0;
+ for (i = 0; i < MAX_LINE_SIZE; )
+ {
+ if ((result = EAS_HWGetByte(hwInstData, fileHandle, &c)) != EAS_SUCCESS)
+ {
+ if ((result == EAS_EOF) && (i > 0))
+ break;
+ return result;
+ }
+
+ /* return on LF or end of data */
+ if (c == '\n')
+ break;
+
+ /* store characters in buffer */
+ if (c != '\r')
+ buffer[i++] = c;
+ }
+ buffer[i] = 0;
+
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_ReadLine read %s\n", buffer); */ }
+#endif
+
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * IMY_ParseLine()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_INT IMY_ParseLine (EAS_I8 *buffer, EAS_U8 *pIndex)
+{
+ EAS_INT i;
+ EAS_INT j;
+
+ /* there's no strnicmp() in stdlib, so we have to roll our own */
+ for (i = 0; i < TOKEN_INVALID; i++)
+ {
+ for (j = 0; ; j++)
+ {
+ /* end of token, must be a match */
+ if (tokens[i][j] == 0)
+ {
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_ParseLine found token %d\n", i); */ }
+#endif
+ *pIndex = (EAS_U8) j;
+ return i;
+ }
+ if (tokens[i][j] != ToUpper(buffer[j]))
+ break;
+ }
+ }
+#ifdef _DEBUG_IMELODY
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_ParseLine: no token found\n"); */ }
+#endif
+ return TOKEN_INVALID;
+}
+
diff --git a/arm-fm-22k/lib_src/eas_imelodydata.c b/arm-fm-22k/lib_src/eas_imelodydata.c
new file mode 100644
index 0000000..e72dc0b
--- /dev/null
+++ b/arm-fm-22k/lib_src/eas_imelodydata.c
@@ -0,0 +1,43 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_imelodydata.c
+ *
+ * Contents and purpose:
+ * SMF File Parser
+ *
+ * This file contains data definitions for the SMF parser.
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 547 $
+ * $Date: 2007-01-31 16:30:17 -0800 (Wed, 31 Jan 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+#include "eas_types.h"
+#include "eas_imelodydata.h"
+
+/*----------------------------------------------------------------------------
+ *
+ * eas_iMelodyData
+ *
+ * Static memory allocation for iMelody parser
+ *----------------------------------------------------------------------------
+*/
+S_IMELODY_DATA eas_iMelodyData;
+
diff --git a/arm-fm-22k/lib_src/eas_imelodydata.h b/arm-fm-22k/lib_src/eas_imelodydata.h
new file mode 100644
index 0000000..303b8f6
--- /dev/null
+++ b/arm-fm-22k/lib_src/eas_imelodydata.h
@@ -0,0 +1,73 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_imelodydata.h
+ *
+ * Contents and purpose:
+ * SMF File Parser
+ *
+ * This file contains data declarations for the iMelody parser.
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 778 $
+ * $Date: 2007-07-23 16:45:17 -0700 (Mon, 23 Jul 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+#ifndef EAS_IMELODYDATA_H
+#define EAS_IMELODYDATA_H
+
+#include "eas_data.h"
+
+/* maximum line size as specified in iMelody V1.2 spec */
+#define MAX_LINE_SIZE 75
+
+/*----------------------------------------------------------------------------
+ *
+ * S_IMELODY_DATA
+ *
+ * This structure contains the state data for the iMelody parser
+ *----------------------------------------------------------------------------
+*/
+
+typedef struct
+{
+ EAS_FILE_HANDLE fileHandle; /* file handle */
+ S_SYNTH *pSynth; /* pointer to synth */
+ EAS_I32 fileOffset; /* offset to start of data */
+ EAS_I32 time; /* current time in 256ths of a msec */
+ EAS_I32 tickBase; /* basline length of 32nd note in 256th of a msec */
+ EAS_I32 tick; /* actual length of 32nd note in 256th of a msec */
+ EAS_I32 restTicks; /* ticks to rest after current note */
+ EAS_I32 startLine; /* file offset at start of line (for repeats) */
+ EAS_I32 repeatOffset; /* file offset to start of repeat section */
+ S_METADATA_CB metadata; /* metadata callback */
+ EAS_I16 repeatCount; /* repeat counter */
+ EAS_U8 state; /* current state EAS_STATE_XXXX */
+ EAS_U8 style; /* from STYLE */
+ EAS_U8 index; /* index into buffer */
+ EAS_U8 octave; /* octave prefix */
+ EAS_U8 volume; /* current volume */
+ EAS_U8 note; /* MIDI note number */
+ EAS_I8 noteModifier; /* sharp or flat */
+ EAS_I8 buffer[MAX_LINE_SIZE+1]; /* buffer for ASCII data */
+} S_IMELODY_DATA;
+
+#endif
+
+
diff --git a/arm-fm-22k/lib_src/eas_math.c b/arm-fm-22k/lib_src/eas_math.c
new file mode 100644
index 0000000..12d788e
--- /dev/null
+++ b/arm-fm-22k/lib_src/eas_math.c
@@ -0,0 +1,168 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_math.c
+ *
+ * Contents and purpose:
+ * Contains common math routines for the various audio engines.
+ *
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 586 $
+ * $Date: 2007-03-08 20:33:04 -0800 (Thu, 08 Mar 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+#include "eas.h"
+#include "eas_math.h"
+
+/* anything less than this converts to a fraction too small to represent in 32-bits */
+#define MIN_CENTS -18000
+
+/*----------------------------------------------------------------------------
+ * EAS_Calculate2toX()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Calculate 2^x
+ *
+ * Inputs:
+ * nCents - measured in cents
+ * psEASData - pointer to overall EAS data structure
+ *
+ * Outputs:
+ * nResult - int.frac result (where frac has NUM_DENTS_FRAC_BITS)
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_I32 EAS_Calculate2toX (EAS_I32 nCents)
+{
+ EAS_I32 nDents;
+ EAS_I32 nExponentInt, nExponentFrac;
+ EAS_I32 nTemp1, nTemp2;
+ EAS_I32 nResult;
+
+ /* check for minimum value */
+ if (nCents < MIN_CENTS)
+ return 0;
+
+ /* for the time being, convert cents to dents */
+ nDents = FMUL_15x15(nCents, CENTS_TO_DENTS);
+
+ nExponentInt = GET_DENTS_INT_PART(nDents);
+ nExponentFrac = GET_DENTS_FRAC_PART(nDents);
+
+ /*
+ implement 2^(fracPart) as a power series
+ */
+ nTemp1 = GN2_TO_X2 + MULT_DENTS_COEF(nExponentFrac, GN2_TO_X3);
+ nTemp2 = GN2_TO_X1 + MULT_DENTS_COEF(nExponentFrac, nTemp1);
+ nTemp1 = GN2_TO_X0 + MULT_DENTS_COEF(nExponentFrac, nTemp2);
+
+ /*
+ implement 2^(intPart) as
+ a left shift for intPart >= 0 or
+ a left shift for intPart < 0
+ */
+ if (nExponentInt >= 0)
+ {
+ /* left shift for positive exponents */
+ /*lint -e{703} <avoid multiply for performance>*/
+ nResult = nTemp1 << nExponentInt;
+ }
+ else
+ {
+ /* right shift for negative exponents */
+ nExponentInt = -nExponentInt;
+ nResult = nTemp1 >> nExponentInt;
+ }
+
+ return nResult;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_LogToLinear16()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Transform log value to linear gain multiplier using piece-wise linear
+ * approximation
+ *
+ * Inputs:
+ * nGain - log scale value in 20.10 format. Even though gain is normally
+ * stored in 6.10 (16-bit) format we use 32-bit numbers here to eliminate
+ * the need for saturation checking when combining gain values.
+ *
+ * Outputs:
+ * Returns a 16-bit linear value approximately equal to 2^(nGain/1024)
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_U16 EAS_LogToLinear16 (EAS_I32 nGain)
+{
+ EAS_INT nExp;
+ EAS_U16 nTemp;
+
+ /* bias to positive */
+ nGain += 32767;
+
+ /* check for infinite attenuation */
+ if (nGain < 0)
+ return 0;
+
+ /* extract the exponent */
+ nExp = 31 - (nGain >> 10);
+
+ /* check for maximum output */
+ if (nExp < 0)
+ return 0x7fff;
+
+ /* extract mantissa and restore implied 1 bit */
+ nTemp = (EAS_U16)((((nGain & 0x3ff) << 4) | 0x4000) >> nExp);
+
+ /* use shift to approximate power-of-2 operation */
+ return nTemp;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_VolumeToGain()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Transform volume control in 1dB increments to gain multiplier
+ *
+ * Inputs:
+ * volume - 100 = 0dB, 99 = -1dB, 0 = -inf
+ *
+ * Outputs:
+ * Returns a 16-bit linear value
+ *----------------------------------------------------------------------------
+*/
+EAS_I16 EAS_VolumeToGain (EAS_INT volume)
+{
+ /* check for limits */
+ if (volume <= 0)
+ return 0;
+ if (volume >= 100)
+ return 0x7fff;
+
+ /*lint -e{702} use shift instead of division */
+ return (EAS_I16) EAS_Calculate2toX((((volume - EAS_MAX_VOLUME) * 204099) >> 10) - 1);
+}
+
diff --git a/arm-fm-22k/lib_src/eas_math.h b/arm-fm-22k/lib_src/eas_math.h
new file mode 100644
index 0000000..719270b
--- /dev/null
+++ b/arm-fm-22k/lib_src/eas_math.h
@@ -0,0 +1,412 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_math.h
+ *
+ * Contents and purpose:
+ * Contains common math routines for the various audio engines.
+ *
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 584 $
+ * $Date: 2007-03-08 09:49:24 -0800 (Thu, 08 Mar 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+#ifndef _EAS_MATH_H
+#define _EAS_MATH_H
+
+
+/** coefs for pan, generates sin, cos */
+#define COEFF_PAN_G2 -27146 /* -0.82842712474619 = 2 - 4/sqrt(2) */
+#define COEFF_PAN_G0 23170 /* 0.707106781186547 = 1/sqrt(2) */
+
+/*
+coefficients for approximating
+2^x = gn2toX0 + gn2toX1*x + gn2toX2*x^2 + gn2toX3*x^3
+where x is a int.frac number representing number of octaves.
+Actually, we approximate only the 2^(frac) using the power series
+and implement the 2^(int) as a shift, so that
+2^x == 2^(int.frac) == 2^(int) * 2^(fract)
+ == (gn2toX0 + gn2toX1*x + gn2toX2*x^2 + gn2toX3*x^3) << (int)
+
+The gn2toX.. were generated using a best fit for a 3rd
+order polynomial, instead of taking the coefficients from
+a truncated Taylor (or Maclaurin?) series.
+*/
+
+#define GN2_TO_X0 32768 /* 1 */
+#define GN2_TO_X1 22833 /* 0.696807861328125 */
+#define GN2_TO_X2 7344 /* 0.22412109375 */
+#define GN2_TO_X3 2588 /* 0.0789794921875 */
+
+/*----------------------------------------------------------------------------
+ * Fixed Point Math
+ *----------------------------------------------------------------------------
+ * These macros are used for fixed point multiplies. If the processor
+ * supports fixed point multiplies, replace these macros with inline
+ * assembly code to improve performance.
+ *----------------------------------------------------------------------------
+*/
+
+/* Fixed point multiply 0.15 x 0.15 = 0.15 returned as 32-bits */
+#define FMUL_15x15(a,b) \
+ /*lint -e(704) <avoid multiply for performance>*/ \
+ (((EAS_I32)(a) * (EAS_I32)(b)) >> 15)
+
+/* Fixed point multiply 0.7 x 0.7 = 0.15 returned as 32-bits */
+#define FMUL_7x7(a,b) \
+ /*lint -e(704) <avoid multiply for performance>*/ \
+ (((EAS_I32)(a) * (EAS_I32)(b) ) << 1)
+
+/* Fixed point multiply 0.8 x 0.8 = 0.15 returned as 32-bits */
+#define FMUL_8x8(a,b) \
+ /*lint -e(704) <avoid multiply for performance>*/ \
+ (((EAS_I32)(a) * (EAS_I32)(b) ) >> 1)
+
+/* Fixed point multiply 0.8 x 1.15 = 0.15 returned as 32-bits */
+#define FMUL_8x15(a,b) \
+ /*lint -e(704) <avoid divide for performance>*/ \
+ (((EAS_I32)((a) << 7) * (EAS_I32)(b)) >> 15)
+
+/* macros for fractional phase accumulator */
+/*
+Note: changed the _U32 to _I32 on 03/14/02. This should not
+affect the phase calculations, and should allow us to reuse these
+macros for other audio sample related math.
+*/
+#define HARDWARE_BIT_WIDTH 32
+
+#define NUM_PHASE_INT_BITS 1
+#define NUM_PHASE_FRAC_BITS 15
+
+#define PHASE_FRAC_MASK (EAS_U32) ((0x1L << NUM_PHASE_FRAC_BITS) -1)
+
+#define GET_PHASE_INT_PART(x) (EAS_U32)((EAS_U32)(x) >> NUM_PHASE_FRAC_BITS)
+#define GET_PHASE_FRAC_PART(x) (EAS_U32)((EAS_U32)(x) & PHASE_FRAC_MASK)
+
+#define DEFAULT_PHASE_FRAC 0
+#define DEFAULT_PHASE_INT 0
+
+/*
+Linear interpolation calculates:
+output = (1-frac) * sample[n] + (frac) * sample[n+1]
+
+where conceptually 0 <= frac < 1
+
+For a fixed point implementation, frac is actually an integer value
+with an implied binary point one position to the left. The value of
+one (unity) is given by PHASE_ONE
+one half and one quarter are useful for 4-point linear interp.
+*/
+#define PHASE_ONE (EAS_I32) (0x1L << NUM_PHASE_FRAC_BITS)
+
+/*
+ Multiply the signed audio sample by the unsigned fraction.
+- a is the signed audio sample
+- b is the unsigned fraction (cast to signed int as long as coef
+ uses (n-1) or less bits, where n == hardware bit width)
+*/
+#define MULT_AUDIO_COEF(audio,coef) /*lint -e704 <avoid divide for performance>*/ \
+ (EAS_I32)( \
+ ( \
+ ((EAS_I32)(audio)) * ((EAS_I32)(coef)) \
+ ) \
+ >> NUM_PHASE_FRAC_BITS \
+ ) \
+ /* lint +704 <restore checking>*/
+
+/* wet / dry calculation macros */
+#define NUM_WET_DRY_FRAC_BITS 7 // 15
+#define NUM_WET_DRY_INT_BITS 9 // 1
+
+/* define a 1.0 */
+#define WET_DRY_ONE (EAS_I32) ((0x1L << NUM_WET_DRY_FRAC_BITS))
+#define WET_DRY_MINUS_ONE (EAS_I32) (~WET_DRY_ONE)
+#define WET_DRY_FULL_SCALE (EAS_I32) (WET_DRY_ONE - 1)
+
+#define MULT_AUDIO_WET_DRY_COEF(audio,coef) /*lint -e(702) <avoid divide for performance>*/ \
+ (EAS_I32)( \
+ ( \
+ ((EAS_I32)(audio)) * ((EAS_I32)(coef)) \
+ ) \
+ >> NUM_WET_DRY_FRAC_BITS \
+ )
+
+/* Envelope 1 (EG1) calculation macros */
+#define NUM_EG1_INT_BITS 1
+#define NUM_EG1_FRAC_BITS 15
+
+/* the max positive gain used in the synth for EG1 */
+/* SYNTH_FULL_SCALE_EG1_GAIN must match the value in the dls2eas
+converter, otherwise, the values we read from the .eas file are bogus. */
+#define SYNTH_FULL_SCALE_EG1_GAIN (EAS_I32) ((0x1L << NUM_EG1_FRAC_BITS) -1)
+
+/* define a 1.0 */
+#define EG1_ONE (EAS_I32) ((0x1L << NUM_EG1_FRAC_BITS))
+#define EG1_MINUS_ONE (EAS_I32) (~SYNTH_FULL_SCALE_EG1_GAIN)
+
+#define EG1_HALF (EAS_I32) (EG1_ONE/2)
+#define EG1_MINUS_HALF (EAS_I32) (EG1_MINUS_ONE/2)
+
+/*
+We implement the EG1 using a linear gain value, which means that the
+attack segment is handled by incrementing (adding) the linear gain.
+However, EG1 treats the Decay, Sustain, and Release differently than
+the Attack portion. For Decay, Sustain, and Release, the gain is
+linear on dB scale, which is equivalent to exponential damping on
+a linear scale. Because we use a linear gain for EG1, we implement
+the Decay and Release as multiplication (instead of incrementing
+as we did for the attack segment).
+Therefore, we need the following macro to implement the multiplication
+(i.e., exponential damping) during the Decay and Release segments of
+the EG1
+*/
+#define MULT_EG1_EG1(gain,damping) /*lint -e(704) <avoid divide for performance>*/ \
+ (EAS_I32)( \
+ ( \
+ ((EAS_I32)(gain)) * ((EAS_I32)(damping)) \
+ ) \
+ >> NUM_EG1_FRAC_BITS \
+ )
+
+// Use the following macro specifically for the filter, when multiplying
+// the b1 coefficient. The 0 <= |b1| < 2, which therefore might overflow
+// in certain conditions because we store b1 as a 1.15 value.
+// Instead, we could store b1 as b1p (b1' == b1 "prime") where
+// b1p == b1/2, thus ensuring no potential overflow for b1p because
+// 0 <= |b1p| < 1
+// However, during the filter calculation, we must account for the fact
+// that we are using b1p instead of b1, and thereby multiply by
+// an extra factor of 2. Rather than multiply by an extra factor of 2,
+// we can instead shift the result right by one less, hence the
+// modified shift right value of (NUM_EG1_FRAC_BITS -1)
+#define MULT_EG1_EG1_X2(gain,damping) /*lint -e(702) <avoid divide for performance>*/ \
+ (EAS_I32)( \
+ ( \
+ ((EAS_I32)(gain)) * ((EAS_I32)(damping)) \
+ ) \
+ >> (NUM_EG1_FRAC_BITS -1) \
+ )
+
+#define SATURATE_EG1(x) /*lint -e{734} saturation operation */ \
+ ((EAS_I32)(x) > SYNTH_FULL_SCALE_EG1_GAIN) ? (SYNTH_FULL_SCALE_EG1_GAIN) : \
+ ((EAS_I32)(x) < EG1_MINUS_ONE) ? (EG1_MINUS_ONE) : (x);
+
+
+/* use "digital cents" == "dents" instead of cents */
+/* we coudl re-use the phase frac macros, but if we do,
+we must change the phase macros to cast to _I32 instead of _U32,
+because using a _U32 cast causes problems when shifting the exponent
+for the 2^x calculation, because right shift a negative values MUST
+be sign extended, or else the 2^x calculation is wrong */
+
+/* use "digital cents" == "dents" instead of cents */
+#define NUM_DENTS_FRAC_BITS 12
+#define NUM_DENTS_INT_BITS (HARDWARE_BIT_WIDTH - NUM_DENTS_FRAC_BITS)
+
+#define DENTS_FRAC_MASK (EAS_I32) ((0x1L << NUM_DENTS_FRAC_BITS) -1)
+
+#define GET_DENTS_INT_PART(x) /*lint -e(704) <avoid divide for performance>*/ \
+ (EAS_I32)((EAS_I32)(x) >> NUM_DENTS_FRAC_BITS)
+
+#define GET_DENTS_FRAC_PART(x) (EAS_I32)((EAS_I32)(x) & DENTS_FRAC_MASK)
+
+#define DENTS_ONE (EAS_I32) (0x1L << NUM_DENTS_FRAC_BITS)
+
+/* use CENTS_TO_DENTS to convert a value in cents to dents */
+#define CENTS_TO_DENTS (EAS_I32) (DENTS_ONE * (0x1L << NUM_EG1_FRAC_BITS) / 1200L) \
+
+
+/*
+For gain, the LFO generates a value that modulates in terms
+of dB. However, we use a linear gain value, so we must convert
+the LFO value in dB to a linear gain. Normally, we would use
+linear gain = 10^x, where x = LFO value in dB / 20.
+Instead, we implement 10^x using our 2^x approximation.
+because
+
+ 10^x = 2^(log2(10^x)) = 2^(x * log2(10))
+
+so we need to multiply by log2(10) which is just a constant.
+Ah, but just wait -- our 2^x actually doesn't exactly implement
+2^x, but it actually assumes that the input is in cents, and within
+the 2^x approximation converts its input from cents to octaves
+by dividing its input by 1200.
+
+So, in order to convert the LFO gain value in dB to something
+that our existing 2^x approximation can use, multiply the LFO gain
+by log2(10) * 1200 / 20
+
+The divide by 20 helps convert dB to linear gain, and we might
+as well incorporate that operation into this conversion.
+Of course, we need to keep some fractional bits, so multiply
+the constant by NUM_EG1_FRAC_BITS
+*/
+
+/* use LFO_GAIN_TO_CENTS to convert the LFO gain value to cents */
+#if 0
+#define DOUBLE_LOG2_10 (double) (3.32192809488736) /* log2(10) */
+
+#define DOUBLE_LFO_GAIN_TO_CENTS (double) \
+ ( \
+ (DOUBLE_LOG2_10) * \
+ 1200.0 / \
+ 20.0 \
+ )
+
+#define LFO_GAIN_TO_CENTS (EAS_I32) \
+ ( \
+ DOUBLE_LFO_GAIN_TO_CENTS * \
+ (0x1L << NUM_EG1_FRAC_BITS) \
+ )
+#endif
+
+#define LFO_GAIN_TO_CENTS (EAS_I32) (1671981156L >> (23 - NUM_EG1_FRAC_BITS))
+
+
+#define MULT_DENTS_COEF(dents,coef) /*lint -e704 <avoid divide for performance>*/ \
+ (EAS_I32)( \
+ ( \
+ ((EAS_I32)(dents)) * ((EAS_I32)(coef)) \
+ ) \
+ >> NUM_DENTS_FRAC_BITS \
+ ) \
+ /* lint +e704 <restore checking>*/
+
+/* we use 16-bits in the PC per audio sample */
+#define BITS_PER_AUDIO_SAMPLE 16
+
+/* we define 1 as 1.0 - 1 LSbit */
+#define DISTORTION_ONE (EAS_I32)((0x1L << (BITS_PER_AUDIO_SAMPLE-1)) -1)
+#define DISTORTION_MINUS_ONE (EAS_I32)(~DISTORTION_ONE)
+
+/* drive coef is given as int.frac */
+#define NUM_DRIVE_COEF_INT_BITS 1
+#define NUM_DRIVE_COEF_FRAC_BITS 4
+
+#define MULT_AUDIO_DRIVE(audio,drive) /*lint -e(702) <avoid divide for performance>*/ \
+ (EAS_I32) ( \
+ ( \
+ ((EAS_I32)(audio)) * ((EAS_I32)(drive)) \
+ ) \
+ >> NUM_DRIVE_COEF_FRAC_BITS \
+ )
+
+#define MULT_AUDIO_AUDIO(audio1,audio2) /*lint -e(702) <avoid divide for performance>*/ \
+ (EAS_I32) ( \
+ ( \
+ ((EAS_I32)(audio1)) * ((EAS_I32)(audio2)) \
+ ) \
+ >> (BITS_PER_AUDIO_SAMPLE-1) \
+ )
+
+#define SATURATE(x) \
+ ((((EAS_I32)(x)) > DISTORTION_ONE) ? (DISTORTION_ONE) : \
+ (((EAS_I32)(x)) < DISTORTION_MINUS_ONE) ? (DISTORTION_MINUS_ONE) : ((EAS_I32)(x)));
+
+
+
+/*----------------------------------------------------------------------------
+ * EAS_Calculate2toX()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Calculate 2^x
+ *
+ * Inputs:
+ * nCents - measured in cents
+ *
+ * Outputs:
+ * nResult - int.frac result (where frac has NUM_DENTS_FRAC_BITS)
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_I32 EAS_Calculate2toX (EAS_I32 nCents);
+
+/*----------------------------------------------------------------------------
+ * EAS_LogToLinear16()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Transform log value to linear gain multiplier using piece-wise linear
+ * approximation
+ *
+ * Inputs:
+ * nGain - log scale value in 20.10 format. Even though gain is normally
+ * stored in 6.10 (16-bit) format we use 32-bit numbers here to eliminate
+ * the need for saturation checking when combining gain values.
+ *
+ * Outputs:
+ * Returns a 16-bit linear value approximately equal to 2^(nGain/1024)
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_U16 EAS_LogToLinear16 (EAS_I32 nGain);
+
+/*----------------------------------------------------------------------------
+ * EAS_VolumeToGain()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Transform volume control in 1dB increments to gain multiplier
+ *
+ * Inputs:
+ * volume - 100 = 0dB, 99 = -1dB, 0 = -inf
+ *
+ * Outputs:
+ * Returns a 16-bit linear value
+ *----------------------------------------------------------------------------
+*/
+EAS_I16 EAS_VolumeToGain (EAS_INT volume);
+
+/*----------------------------------------------------------------------------
+ * EAS_fsqrt()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Calculates the square root of a 32-bit fixed point value
+ *
+ * Inputs:
+ * n = value of interest
+ *
+ * Outputs:
+ * returns the square root of n
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_U16 EAS_fsqrt (EAS_U32 n);
+
+/*----------------------------------------------------------------------------
+ * EAS_flog2()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Calculates the log2 of a 32-bit fixed point value
+ *
+ * Inputs:
+ * n = value of interest
+ *
+ * Outputs:
+ * returns the log2 of n
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_I32 EAS_flog2 (EAS_U32 n);
+
+#endif
+
diff --git a/arm-fm-22k/lib_src/eas_midi.c b/arm-fm-22k/lib_src/eas_midi.c
new file mode 100644
index 0000000..08aed72
--- /dev/null
+++ b/arm-fm-22k/lib_src/eas_midi.c
@@ -0,0 +1,569 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_midi.c
+ *
+ * Contents and purpose:
+ * This file implements the MIDI stream parser. It is called by eas_smf.c to parse MIDI messages
+ * that are streamed out of the file. It can also parse live MIDI streams.
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 794 $
+ * $Date: 2007-08-01 00:08:48 -0700 (Wed, 01 Aug 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+#include "eas_data.h"
+#include "eas_report.h"
+#include "eas_miditypes.h"
+#include "eas_midi.h"
+#include "eas_vm_protos.h"
+#include "eas_parser.h"
+
+#ifdef JET_INTERFACE
+#include "jet_data.h"
+#endif
+
+
+/* state enumerations for ProcessSysExMessage */
+typedef enum
+{
+ eSysEx,
+ eSysExUnivNonRealTime,
+ eSysExUnivNrtTargetID,
+ eSysExGMControl,
+ eSysExUnivRealTime,
+ eSysExUnivRtTargetID,
+ eSysExDeviceControl,
+ eSysExMasterVolume,
+ eSysExMasterVolLSB,
+ eSysExSPMIDI,
+ eSysExSPMIDIchan,
+ eSysExSPMIDIMIP,
+ eSysExMfgID1,
+ eSysExMfgID2,
+ eSysExMfgID3,
+ eSysExEnhancer,
+ eSysExEnhancerSubID,
+ eSysExEnhancerFeedback1,
+ eSysExEnhancerFeedback2,
+ eSysExEnhancerDrive,
+ eSysExEnhancerWet,
+ eSysExEOX,
+ eSysExIgnore
+} E_SYSEX_STATES;
+
+/* local prototypes */
+static EAS_RESULT ProcessMIDIMessage (S_EAS_DATA *pEASData, S_SYNTH *pSynth, S_MIDI_STREAM *pMIDIStream, EAS_INT parserMode);
+static EAS_RESULT ProcessSysExMessage (S_EAS_DATA *pEASData, S_SYNTH *pSynth, S_MIDI_STREAM *pMIDIStream, EAS_U8 c, EAS_INT parserMode);
+
+/*----------------------------------------------------------------------------
+ * EAS_InitMIDIStream()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Initializes the MIDI stream state for parsing.
+ *
+ * Inputs:
+ *
+ * Outputs:
+ * returns EAS_RESULT (EAS_SUCCESS is OK)
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+void EAS_InitMIDIStream (S_MIDI_STREAM *pMIDIStream)
+{
+ pMIDIStream->byte3 = EAS_FALSE;
+ pMIDIStream->pending = EAS_FALSE;
+ pMIDIStream->runningStatus = 0;
+ pMIDIStream->status = 0;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_ParseMIDIStream()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Parses a MIDI input stream character by character. Characters are pushed (rather than pulled)
+ * so the interface works equally well for both file and stream I/O.
+ *
+ * Inputs:
+ * c - character from MIDI stream
+ *
+ * Outputs:
+ * returns EAS_RESULT (EAS_SUCCESS is OK)
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_ParseMIDIStream (S_EAS_DATA *pEASData, S_SYNTH *pSynth, S_MIDI_STREAM *pMIDIStream, EAS_U8 c, EAS_INT parserMode)
+{
+
+ /* check for new status byte */
+ if (c & 0x80)
+ {
+ /* save new running status */
+ if (c < 0xf8)
+ {
+ pMIDIStream->runningStatus = c;
+ pMIDIStream->byte3 = EAS_FALSE;
+
+ /* deal with SysEx */
+ if ((c == 0xf7) || (c == 0xf0))
+ {
+ if (parserMode == eParserModeMetaData)
+ return EAS_SUCCESS;
+ return ProcessSysExMessage(pEASData, pSynth, pMIDIStream, c, parserMode);
+ }
+
+ /* inform the file parser that we're in the middle of a message */
+ if ((c < 0xf4) || (c > 0xf6))
+ pMIDIStream->pending = EAS_TRUE;
+ }
+
+ /* real-time message - ignore it */
+ return EAS_SUCCESS;
+ }
+
+ /* 3rd byte of a 3-byte message? */
+ if (pMIDIStream->byte3)
+ {
+ pMIDIStream->d2 = c;
+ pMIDIStream->byte3 = EAS_FALSE;
+ pMIDIStream->pending = EAS_FALSE;
+ if (parserMode == eParserModeMetaData)
+ return EAS_SUCCESS;
+ return ProcessMIDIMessage(pEASData, pSynth, pMIDIStream, parserMode);
+ }
+
+ /* check for status received */
+ if (pMIDIStream->runningStatus)
+ {
+
+ /* save new status and data byte */
+ pMIDIStream->status = pMIDIStream->runningStatus;
+
+ /* check for 3-byte messages */
+ if (pMIDIStream->status < 0xc0)
+ {
+ pMIDIStream->d1 = c;
+ pMIDIStream->pending = EAS_TRUE;
+ pMIDIStream->byte3 = EAS_TRUE;
+ return EAS_SUCCESS;
+ }
+
+ /* check for 2-byte messages */
+ if (pMIDIStream->status < 0xe0)
+ {
+ pMIDIStream->d1 = c;
+ pMIDIStream->pending = EAS_FALSE;
+ if (parserMode == eParserModeMetaData)
+ return EAS_SUCCESS;
+ return ProcessMIDIMessage(pEASData, pSynth, pMIDIStream, parserMode);
+ }
+
+ /* check for more 3-bytes message */
+ if (pMIDIStream->status < 0xf0)
+ {
+ pMIDIStream->d1 = c;
+ pMIDIStream->pending = EAS_TRUE;
+ pMIDIStream->byte3 = EAS_TRUE;
+ return EAS_SUCCESS;
+ }
+
+ /* SysEx message? */
+ if (pMIDIStream->status == 0xF0)
+ {
+ if (parserMode == eParserModeMetaData)
+ return EAS_SUCCESS;
+ return ProcessSysExMessage(pEASData, pSynth, pMIDIStream, c, parserMode);
+ }
+
+ /* remaining messages all clear running status */
+ pMIDIStream->runningStatus = 0;
+
+ /* F2 is 3-byte message */
+ if (pMIDIStream->status == 0xf2)
+ {
+ pMIDIStream->byte3 = EAS_TRUE;
+ return EAS_SUCCESS;
+ }
+ }
+
+ /* no status byte received, provide a warning, but we should be able to recover */
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Received MIDI data without a valid status byte: %d\n",c); */ }
+ pMIDIStream->pending = EAS_FALSE;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * ProcessMIDIMessage()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * This function processes a typical MIDI message. All of the data has been received, just need
+ * to take appropriate action.
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT ProcessMIDIMessage (S_EAS_DATA *pEASData, S_SYNTH *pSynth, S_MIDI_STREAM *pMIDIStream, EAS_INT parserMode)
+{
+ EAS_U8 channel;
+
+ channel = pMIDIStream->status & 0x0f;
+ switch (pMIDIStream->status & 0xf0)
+ {
+ case 0x80:
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"NoteOff: %02x %02x %02x\n",
+ pMIDIStream->status, pMIDIStream->d1, pMIDIStream->d2); */ }
+ if (parserMode < eParserModeMute)
+ VMStopNote(pEASData->pVoiceMgr, pSynth, channel, pMIDIStream->d1, pMIDIStream->d2);
+ break;
+
+ case 0x90:
+ if (pMIDIStream->d2)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"NoteOn: %02x %02x %02x\n",
+ pMIDIStream->status, pMIDIStream->d1, pMIDIStream->d2); */ }
+ pMIDIStream->flags |= MIDI_FLAG_FIRST_NOTE;
+ if (parserMode == eParserModePlay)
+ VMStartNote(pEASData->pVoiceMgr, pSynth, channel, pMIDIStream->d1, pMIDIStream->d2);
+ }
+ else
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"NoteOff: %02x %02x %02x\n",
+ pMIDIStream->status, pMIDIStream->d1, pMIDIStream->d2); */ }
+ if (parserMode < eParserModeMute)
+ VMStopNote(pEASData->pVoiceMgr, pSynth, channel, pMIDIStream->d1, pMIDIStream->d2);
+ }
+ break;
+
+ case 0xa0:
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"PolyPres: %02x %02x %02x\n",
+ pMIDIStream->status, pMIDIStream->d1, pMIDIStream->d2); */ }
+ break;
+
+ case 0xb0:
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"Control: %02x %02x %02x\n",
+ pMIDIStream->status, pMIDIStream->d1, pMIDIStream->d2); */ }
+ if (parserMode < eParserModeMute)
+ VMControlChange(pEASData->pVoiceMgr, pSynth, channel, pMIDIStream->d1, pMIDIStream->d2);
+#ifdef JET_INTERFACE
+ if (pMIDIStream->jetData & MIDI_FLAGS_JET_CB)
+ {
+ JET_Event(pEASData, pMIDIStream->jetData & (JET_EVENT_SEG_MASK | JET_EVENT_TRACK_MASK),
+ channel, pMIDIStream->d1, pMIDIStream->d2);
+ }
+#endif
+ break;
+
+ case 0xc0:
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"Program: %02x %02x\n",
+ pMIDIStream->status, pMIDIStream->d1); */ }
+ if (parserMode < eParserModeMute)
+ VMProgramChange(pEASData->pVoiceMgr, pSynth, channel, pMIDIStream->d1);
+ break;
+
+ case 0xd0:
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"ChanPres: %02x %02x\n",
+ pMIDIStream->status, pMIDIStream->d1); */ }
+ if (parserMode < eParserModeMute)
+ VMChannelPressure(pSynth, channel, pMIDIStream->d1);
+ break;
+
+ case 0xe0:
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"PBend: %02x %02x %02x\n",
+ pMIDIStream->status, pMIDIStream->d1, pMIDIStream->d2); */ }
+ if (parserMode < eParserModeMute)
+ VMPitchBend(pSynth, channel, pMIDIStream->d1, pMIDIStream->d2);
+ break;
+
+ default:
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"Unknown: %02x %02x %02x\n",
+ pMIDIStream->status, pMIDIStream->d1, pMIDIStream->d2); */ }
+ }
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * ProcessSysExMessage()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Process a SysEx character byte from the MIDI stream. Since we cannot
+ * simply wait for the next character to arrive, we are forced to save
+ * state after each character. It would be easier to parse at the file
+ * level, but then we lose the nice feature of being able to support
+ * these messages in a real-time MIDI stream.
+ *
+ * Inputs:
+ * pEASData - pointer to synthesizer instance data
+ * c - character to be processed
+ * locating - if true, the sequencer is relocating to a new position
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ * Notes:
+ * These are the SysEx messages we can receive:
+ *
+ * SysEx messages
+ * { f0 7e 7f 09 01 f7 } GM 1 On
+ * { f0 7e 7f 09 02 f7 } GM 1/2 Off
+ * { f0 7e 7f 09 03 f7 } GM 2 On
+ * { f0 7f 7f 04 01 lsb msb } Master Volume
+ * { f0 7f 7f 0b 01 ch mip [ch mip ...] f7 } SP-MIDI
+ * { f0 00 01 3a 04 01 fdbk1 fdbk2 drive wet dry f7 } Enhancer
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT ProcessSysExMessage (S_EAS_DATA *pEASData, S_SYNTH *pSynth, S_MIDI_STREAM *pMIDIStream, EAS_U8 c, EAS_INT parserMode)
+{
+
+ /* check for start byte */
+ if (c == 0xf0)
+ {
+ pMIDIStream->sysExState = eSysEx;
+ }
+ /* check for end byte */
+ else if (c == 0xf7)
+ {
+ /* if this was a MIP message, update the MIP table */
+ if ((pMIDIStream->sysExState == eSysExSPMIDIchan) && (parserMode != eParserModeMetaData))
+ VMUpdateMIPTable(pEASData->pVoiceMgr, pSynth);
+ pMIDIStream->sysExState = eSysExIgnore;
+ }
+
+ /* process SysEx message */
+ else
+ {
+ switch (pMIDIStream->sysExState)
+ {
+ case eSysEx:
+
+ /* first byte, determine message class */
+ switch (c)
+ {
+ case 0x7e:
+ pMIDIStream->sysExState = eSysExUnivNonRealTime;
+ break;
+ case 0x7f:
+ pMIDIStream->sysExState = eSysExUnivRealTime;
+ break;
+ case 0x00:
+ pMIDIStream->sysExState = eSysExMfgID1;
+ break;
+ default:
+ pMIDIStream->sysExState = eSysExIgnore;
+ break;
+ }
+ break;
+
+ /* process GM message */
+ case eSysExUnivNonRealTime:
+ if (c == 0x7f)
+ pMIDIStream->sysExState = eSysExUnivNrtTargetID;
+ else
+ pMIDIStream->sysExState = eSysExIgnore;
+ break;
+
+ case eSysExUnivNrtTargetID:
+ if (c == 0x09)
+ pMIDIStream->sysExState = eSysExGMControl;
+ else
+ pMIDIStream->sysExState = eSysExIgnore;
+ break;
+
+ case eSysExGMControl:
+ if ((c == 1) || (c == 3))
+ {
+ /* GM 1 or GM2 On, reset synth */
+ if (parserMode != eParserModeMetaData)
+ {
+ pMIDIStream->flags |= MIDI_FLAG_GM_ON;
+ VMReset(pEASData->pVoiceMgr, pSynth, EAS_FALSE);
+ VMInitMIPTable(pSynth);
+ }
+ pMIDIStream->sysExState = eSysExEOX;
+ }
+ else
+ pMIDIStream->sysExState = eSysExIgnore;
+ break;
+
+ /* Process Master Volume and SP-MIDI */
+ case eSysExUnivRealTime:
+ if (c == 0x7f)
+ pMIDIStream->sysExState = eSysExUnivRtTargetID;
+ else
+ pMIDIStream->sysExState = eSysExIgnore;
+ break;
+
+ case eSysExUnivRtTargetID:
+ if (c == 0x04)
+ pMIDIStream->sysExState = eSysExDeviceControl;
+ else if (c == 0x0b)
+ pMIDIStream->sysExState = eSysExSPMIDI;
+ else
+ pMIDIStream->sysExState = eSysExIgnore;
+ break;
+
+ /* process master volume */
+ case eSysExDeviceControl:
+ if (c == 0x01)
+ pMIDIStream->sysExState = eSysExMasterVolume;
+ else
+ pMIDIStream->sysExState = eSysExIgnore;
+ break;
+
+ case eSysExMasterVolume:
+ /* save LSB */
+ pMIDIStream->d1 = c;
+ pMIDIStream->sysExState = eSysExMasterVolLSB;
+ break;
+
+ case eSysExMasterVolLSB:
+ if (parserMode != eParserModeMetaData)
+ {
+ EAS_I32 gain = ((EAS_I32) c << 8) | ((EAS_I32) pMIDIStream->d1 << 1);
+ gain = (gain * gain) >> 15;
+ VMSetVolume(pSynth, (EAS_U16) gain);
+ }
+ pMIDIStream->sysExState = eSysExEOX;
+ break;
+
+ /* process SP-MIDI MIP message */
+ case eSysExSPMIDI:
+ if (c == 0x01)
+ {
+ /* assume all channels are muted */
+ if (parserMode != eParserModeMetaData)
+ VMInitMIPTable(pSynth);
+ pMIDIStream->d1 = 0;
+ pMIDIStream->sysExState = eSysExSPMIDIchan;
+ }
+ else
+ pMIDIStream->sysExState = eSysExIgnore;
+ break;
+
+ case eSysExSPMIDIchan:
+ if (c < NUM_SYNTH_CHANNELS)
+ {
+ pMIDIStream->d2 = c;
+ pMIDIStream->sysExState = eSysExSPMIDIMIP;
+ }
+ else
+ {
+ /* bad MIP message - unmute channels */
+ if (parserMode != eParserModeMetaData)
+ VMInitMIPTable(pSynth);
+ pMIDIStream->sysExState = eSysExIgnore;
+ }
+ break;
+
+ case eSysExSPMIDIMIP:
+ /* process MIP entry here */
+ if (parserMode != eParserModeMetaData)
+ VMSetMIPEntry(pEASData->pVoiceMgr, pSynth, pMIDIStream->d2, pMIDIStream->d1, c);
+ pMIDIStream->sysExState = eSysExSPMIDIchan;
+
+ /* if 16 channels received, update MIP table */
+ if (++pMIDIStream->d1 == NUM_SYNTH_CHANNELS)
+ {
+ if (parserMode != eParserModeMetaData)
+ VMUpdateMIPTable(pEASData->pVoiceMgr, pSynth);
+ pMIDIStream->sysExState = eSysExEOX;
+ }
+ break;
+
+ /* process Enhancer */
+ case eSysExMfgID1:
+ if (c == 0x01)
+ pMIDIStream->sysExState = eSysExMfgID1;
+ else
+ pMIDIStream->sysExState = eSysExIgnore;
+ break;
+
+ case eSysExMfgID2:
+ if (c == 0x3a)
+ pMIDIStream->sysExState = eSysExMfgID1;
+ else
+ pMIDIStream->sysExState = eSysExIgnore;
+ break;
+
+ case eSysExMfgID3:
+ if (c == 0x04)
+ pMIDIStream->sysExState = eSysExEnhancer;
+ else
+ pMIDIStream->sysExState = eSysExIgnore;
+ break;
+
+ case eSysExEnhancer:
+ if (c == 0x01)
+ pMIDIStream->sysExState = eSysExEnhancerSubID;
+ else
+ pMIDIStream->sysExState = eSysExIgnore;
+ break;
+
+ case eSysExEnhancerSubID:
+ pMIDIStream->sysExState = eSysExEnhancerFeedback1;
+ break;
+
+ case eSysExEnhancerFeedback1:
+ pMIDIStream->sysExState = eSysExEnhancerFeedback2;
+ break;
+
+ case eSysExEnhancerFeedback2:
+ pMIDIStream->sysExState = eSysExEnhancerDrive;
+ break;
+
+ case eSysExEnhancerDrive:
+ pMIDIStream->sysExState = eSysExEnhancerWet;
+ break;
+
+ case eSysExEnhancerWet:
+ pMIDIStream->sysExState = eSysExEOX;
+ break;
+
+ case eSysExEOX:
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Expected F7, received %02x\n", c); */ }
+ pMIDIStream->sysExState = eSysExIgnore;
+ break;
+
+ case eSysExIgnore:
+ break;
+
+ default:
+ pMIDIStream->sysExState = eSysExIgnore;
+ break;
+ }
+ }
+
+ if (pMIDIStream->sysExState == eSysExIgnore)
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Ignoring SysEx byte %02x\n", c); */ }
+ return EAS_SUCCESS;
+} /* end ProcessSysExMessage */
+
diff --git a/arm-fm-22k/lib_src/eas_midi.h b/arm-fm-22k/lib_src/eas_midi.h
new file mode 100644
index 0000000..37a03ee
--- /dev/null
+++ b/arm-fm-22k/lib_src/eas_midi.h
@@ -0,0 +1,71 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_midi.h
+ *
+ * Contents and purpose:
+ * Prototypes for MIDI stream parsing functions
+ *
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 82 $
+ * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $
+ *----------------------------------------------------------------------------
+*/
+
+#ifndef _EAS_MIDI_H
+#define _EAS_MIDI_H
+
+/*----------------------------------------------------------------------------
+ * EAS_InitMIDIStream()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Initializes the MIDI stream state for parsing.
+ *
+ * Inputs:
+ *
+ * Outputs:
+ * returns EAS_RESULT (EAS_SUCCESS is OK)
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+void EAS_InitMIDIStream (S_MIDI_STREAM *pMIDIStream);
+
+/*----------------------------------------------------------------------------
+ * EAS_ParseMIDIStream()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Parses a MIDI input stream character by character. Characters are pushed (rather than pulled)
+ * so the interface works equally well for both file and stream I/O.
+ *
+ * Inputs:
+ * c - character from MIDI stream
+ *
+ * Outputs:
+ * returns EAS_RESULT (EAS_SUCCESS is OK)
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_ParseMIDIStream (S_EAS_DATA *pEASData, S_SYNTH *pSynth, S_MIDI_STREAM *pMIDIStream, EAS_U8 c, EAS_INT parserMode);
+
+#endif /* #define _EAS_MIDI_H */
+
diff --git a/arm-fm-22k/lib_src/eas_midictrl.h b/arm-fm-22k/lib_src/eas_midictrl.h
new file mode 100644
index 0000000..0c4217d
--- /dev/null
+++ b/arm-fm-22k/lib_src/eas_midictrl.h
@@ -0,0 +1,64 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_midictrl.h
+ *
+ * Contents and purpose:
+ * MIDI controller definitions
+ *
+ * This header only contains declarations that are specific
+ * to this implementation.
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 82 $
+ * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $
+ *----------------------------------------------------------------------------
+*/
+
+#ifndef _EAS_MIDICTRL_H
+#define _EAS_MIDICTRL_H
+
+/* define controller types */
+/*
+ Note that these controller types are specified in base 10 (decimal)
+ and not in hexadecimal. The above midi messages are specified
+ in hexadecimal.
+*/
+#define MIDI_CONTROLLER_BANK_SELECT 0
+#define MIDI_CONTROLLER_BANK_SELECT_MSB 0
+#define MIDI_CONTROLLER_MOD_WHEEL 1
+#define MIDI_CONTROLLER_ENTER_DATA_MSB 6
+#define MIDI_CONTROLLER_VOLUME 7
+#define MIDI_CONTROLLER_PAN 10
+#define MIDI_CONTROLLER_EXPRESSION 11
+#define MIDI_CONTROLLER_BANK_SELECT_LSB 32
+#define MIDI_CONTROLLER_ENTER_DATA_LSB 38 /* 0x26 */
+#define MIDI_CONTROLLER_SUSTAIN_PEDAL 64
+#define MIDI_CONTROLLER_SELECT_NRPN_LSB 98
+#define MIDI_CONTROLLER_SELECT_NRPN_MSB 99
+#define MIDI_CONTROLLER_SELECT_RPN_LSB 100 /* 0x64 */
+#define MIDI_CONTROLLER_SELECT_RPN_MSB 101 /* 0x65 */
+#define MIDI_CONTROLLER_ALL_SOUND_OFF 120
+#define MIDI_CONTROLLER_RESET_CONTROLLERS 121
+#define MIDI_CONTROLLER_ALL_NOTES_OFF 123
+#define MIDI_CONTROLLER_OMNI_OFF 124
+#define MIDI_CONTROLLER_OMNI_ON 125
+#define MIDI_CONTROLLER_MONO_ON_POLY_OFF 126
+#define MIDI_CONTROLLER_POLY_ON_MONO_OFF 127
+
+#endif /* #ifndef _EAS_MIDICTRL_H */
diff --git a/arm-fm-22k/lib_src/eas_mididata.c b/arm-fm-22k/lib_src/eas_mididata.c
new file mode 100644
index 0000000..2ee907e
--- /dev/null
+++ b/arm-fm-22k/lib_src/eas_mididata.c
@@ -0,0 +1,34 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_mididata.c
+ *
+ * Contents and purpose:
+ * Data module for MIDI stream interface
+ *
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 547 $
+ * $Date: 2007-01-31 16:30:17 -0800 (Wed, 31 Jan 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+#include "eas_miditypes.h"
+
+S_INTERACTIVE_MIDI eas_MIDIData;
+
diff --git a/arm-fm-22k/lib_src/eas_miditypes.h b/arm-fm-22k/lib_src/eas_miditypes.h
new file mode 100644
index 0000000..0b7f96e
--- /dev/null
+++ b/arm-fm-22k/lib_src/eas_miditypes.h
@@ -0,0 +1,138 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_miditypes.h
+ *
+ * Contents and purpose:
+ * Contains declarations for the MIDI stream parser.
+ *
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 778 $
+ * $Date: 2007-07-23 16:45:17 -0700 (Mon, 23 Jul 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+#ifndef _EAS_MIDITYPES_H
+#define _EAS_MIDITYPES_H
+
+#include "eas_data.h"
+#include "eas_parser.h"
+
+/*----------------------------------------------------------------------------
+ * S_MIDI_STREAM
+ *
+ * Maintains parser state for the MIDI stream parser
+ *
+ *----------------------------------------------------------------------------
+*/
+
+typedef struct s_midi_stream_tag
+{
+ EAS_BOOL8 byte3; /* flag indicates 3rd byte expected */
+ EAS_BOOL8 pending; /* flag indicates more data expected */
+ EAS_U8 sysExState; /* maintains the SysEx state */
+ EAS_U8 runningStatus; /* last running status received */
+ EAS_U8 status; /* status byte */
+ EAS_U8 d1; /* first data byte */
+ EAS_U8 d2; /* second data byte */
+ EAS_U8 flags; /* flags - see below for definition */
+#ifdef JET_INTERFACE
+ EAS_U32 jetData; /* JET data */
+#endif
+} S_MIDI_STREAM;
+
+/* flags for S_MIDI_STREAM.flags */
+#define MIDI_FLAG_GM_ON 0x01 /* GM System On message received */
+#define MIDI_FLAG_FIRST_NOTE 0x02 /* first note received */
+
+/* flags for S_MIDI_STREAM.jetFlags */
+#define MIDI_FLAGS_JET_MUTE 0x00000001 /* track is muted */
+#define MIDI_FLAGS_JET_CB 0x00000002 /* JET callback enabled */
+
+/*----------------------------------------------------------------------------
+ *
+ * S_SMF_STREAM
+ *
+ * This structure contains data required to parse an SMF stream. For SMF0 files, there
+ * will be a single instance of this per file. For SMF1 files, there will be multiple instance,
+ * one for each separate stream in the file.
+ *
+ *----------------------------------------------------------------------------
+*/
+
+typedef struct s_smf_stream_tag
+{
+ EAS_FILE_HANDLE fileHandle; /* host wrapper file handle */
+ EAS_U32 ticks; /* time of next event in stream */
+ EAS_I32 startFilePos; /* start location of track within file */
+ S_MIDI_STREAM midiStream; /* MIDI stream state */
+} S_SMF_STREAM;
+
+/*----------------------------------------------------------------------------
+ *
+ * S_SMF_DATA
+ *
+ * This structure contains the instance data required to parse an SMF stream.
+ *
+ *----------------------------------------------------------------------------
+*/
+
+typedef struct s_smf_data_tag
+{
+#ifdef _CHECKED_BUILD
+ EAS_U32 handleCheck; /* signature check for checked build */
+#endif
+ S_SMF_STREAM *streams; /* pointer to individual streams in file */
+ S_SMF_STREAM *nextStream; /* pointer to next stream with event */
+ S_SYNTH *pSynth; /* pointer to synth */
+ EAS_FILE_HANDLE fileHandle; /* file handle */
+ S_METADATA_CB metadata; /* metadata callback */
+ EAS_I32 fileOffset; /* for embedded files */
+ EAS_I32 time; /* current time in milliseconds/256 */
+ EAS_U16 numStreams; /* actual number of streams */
+ EAS_U16 tickConv; /* current MIDI tick to msec conversion */
+ EAS_U16 ppqn; /* ticks per quarter note */
+ EAS_U8 state; /* current state EAS_STATE_XXXX */
+ EAS_U8 flags; /* flags - see definitions below */
+} S_SMF_DATA;
+
+#define SMF_FLAGS_CHASE_MODE 0x01 /* chase mode - skip to first note */
+#define SMF_FLAGS_HAS_TIME_SIG 0x02 /* time signature encountered at time 0 */
+#define SMF_FLAGS_HAS_TEMPO 0x04 /* tempo encountered at time 0 */
+#define SMF_FLAGS_HAS_GM_ON 0x08 /* GM System On encountered at time 0 */
+#define SMF_FLAGS_JET_STREAM 0x80 /* JET in use - keep strict timing */
+
+/* combo flags indicate setup bar */
+#define SMF_FLAGS_SETUP_BAR (SMF_FLAGS_HAS_TIME_SIG | SMF_FLAGS_HAS_TEMPO | SMF_FLAGS_HAS_GM_ON)
+
+/*----------------------------------------------------------------------------
+ * Interactive MIDI structure
+ *----------------------------------------------------------------------------
+*/
+typedef struct s_interactive_midi_tag
+{
+#ifdef _CHECKED_BUILD
+ EAS_U32 handleCheck; /* signature check for checked build */
+#endif
+ S_SYNTH *pSynth; /* pointer to synth */
+ S_MIDI_STREAM stream; /* stream data */
+} S_INTERACTIVE_MIDI;
+
+#endif /* #ifndef _EAS_MIDITYPES_H */
+
diff --git a/arm-fm-22k/lib_src/eas_mixbuf.c b/arm-fm-22k/lib_src/eas_mixbuf.c
new file mode 100644
index 0000000..73e969a
--- /dev/null
+++ b/arm-fm-22k/lib_src/eas_mixbuf.c
@@ -0,0 +1,36 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_mixbuf.c
+ *
+ * Contents and purpose:
+ * Contains a data allocation for synthesizer
+ *
+ * Copyright Sonic Network Inc. 2004
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 82 $
+ * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $
+ *----------------------------------------------------------------------------
+*/
+
+// includes
+#include "eas_data.h"
+#include "eas_mixer.h"
+
+// globals
+EAS_I32 eas_MixBuffer[BUFFER_SIZE_IN_MONO_SAMPLES * NUM_OUTPUT_CHANNELS];
+
diff --git a/arm-fm-22k/lib_src/eas_mixer.c b/arm-fm-22k/lib_src/eas_mixer.c
new file mode 100644
index 0000000..c4a2f9f
--- /dev/null
+++ b/arm-fm-22k/lib_src/eas_mixer.c
@@ -0,0 +1,464 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_mixer.c
+ *
+ * Contents and purpose:
+ * This file contains the critical components of the mix engine that
+ * must be optimized for best performance.
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 706 $
+ * $Date: 2007-05-31 17:22:51 -0700 (Thu, 31 May 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+//3 dls: This module is in the midst of being converted from a synth
+//3 specific module to a general purpose mix engine
+
+/*------------------------------------
+ * includes
+ *------------------------------------
+*/
+#include "eas_data.h"
+#include "eas_host.h"
+#include "eas_math.h"
+#include "eas_mixer.h"
+#include "eas_config.h"
+#include "eas_report.h"
+
+#ifdef _MAXIMIZER_ENABLED
+EAS_I32 MaximizerProcess (EAS_VOID_PTR pInstData, EAS_I32 *pSrc, EAS_I32 *pDst, EAS_I32 numSamples);
+#endif
+
+/*------------------------------------
+ * defines
+ *------------------------------------
+*/
+
+/* need to boost stereo by ~3dB to compensate for the panner */
+#define STEREO_3DB_GAIN_BOOST 512
+
+/*----------------------------------------------------------------------------
+ * EAS_MixEngineInit()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Prepares the mix engine for work, allocates buffers, locates effects modules, etc.
+ *
+ * Inputs:
+ * pEASData - instance data
+ * pInstData - pointer to variable to receive instance data handle
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_MixEngineInit (S_EAS_DATA *pEASData)
+{
+
+ /* check Configuration Module for mix buffer allocation */
+ if (pEASData->staticMemoryModel)
+ pEASData->pMixBuffer = EAS_CMEnumData(EAS_CM_MIX_BUFFER);
+ else
+ pEASData->pMixBuffer = EAS_HWMalloc(pEASData->hwInstData, BUFFER_SIZE_IN_MONO_SAMPLES * NUM_OUTPUT_CHANNELS * sizeof(EAS_I32));
+ if (pEASData->pMixBuffer == NULL)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate mix buffer memory\n"); */ }
+ return EAS_ERROR_MALLOC_FAILED;
+ }
+ EAS_HWMemSet((void *)(pEASData->pMixBuffer), 0, BUFFER_SIZE_IN_MONO_SAMPLES * NUM_OUTPUT_CHANNELS * sizeof(EAS_I32));
+
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_MixEnginePrep()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Performs prep before synthesize a buffer of audio, such as clearing
+ * audio buffers, etc.
+ *
+ * Inputs:
+ * psEASData - pointer to overall EAS data structure
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+void EAS_MixEnginePrep (S_EAS_DATA *pEASData, EAS_I32 numSamples)
+{
+
+ /* clear the mix buffer */
+#if (NUM_OUTPUT_CHANNELS == 2)
+ EAS_HWMemSet(pEASData->pMixBuffer, 0, numSamples * (EAS_I32) sizeof(long) * 2);
+#else
+ EAS_HWMemSet(pEASData->pMixBuffer, 0, (EAS_I32) numSamples * (EAS_I32) sizeof(long));
+#endif
+
+ /* need to clear other side-chain effect buffers (chorus & reverb) */
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_MixEnginePost
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * This routine does the post-processing after all voices have been
+ * synthesized. It calls any sweeteners and does the final mixdown to
+ * the output buffer.
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ * Notes:
+ *----------------------------------------------------------------------------
+*/
+void EAS_MixEnginePost (S_EAS_DATA *pEASData, EAS_I32 numSamples)
+{
+ EAS_U16 gain;
+
+//3 dls: Need to restore the mix engine metrics
+
+ /* calculate the gain multiplier */
+#ifdef _MAXIMIZER_ENABLED
+ if (pEASData->effectsModules[EAS_MODULE_MAXIMIZER].effect)
+ {
+ EAS_I32 temp;
+ temp = MaximizerProcess(pEASData->effectsModules[EAS_MODULE_MAXIMIZER].effectData, pEASData->pMixBuffer, pEASData->pMixBuffer, numSamples);
+ temp = (temp * pEASData->masterGain) >> 15;
+ if (temp > 32767)
+ gain = 32767;
+ else
+ gain = (EAS_U16) temp;
+ }
+ else
+ gain = (EAS_U16) pEASData->masterGain;
+#else
+ gain = (EAS_U16) pEASData->masterGain;
+#endif
+
+ /* Not using all the gain bits for now
+ * Reduce the input to the compressor by 6dB to prevent saturation
+ */
+#ifdef _COMPRESSOR_ENABLED
+ if (pEASData->effectsModules[EAS_MODULE_COMPRESSOR].effectData)
+ gain = gain >> 5;
+ else
+ gain = gain >> 4;
+#else
+ gain = gain >> 4;
+#endif
+
+ /* convert 32-bit mix buffer to 16-bit output format */
+#if (NUM_OUTPUT_CHANNELS == 2)
+ SynthMasterGain(pEASData->pMixBuffer, pEASData->pOutputAudioBuffer, gain, (EAS_U16) ((EAS_U16) numSamples * 2));
+#else
+ SynthMasterGain(pEASData->pMixBuffer, pEASData->pOutputAudioBuffer, gain, (EAS_U16) numSamples);
+#endif
+
+#ifdef _ENHANCER_ENABLED
+ /* enhancer effect */
+ if (pEASData->effectsModules[EAS_MODULE_ENHANCER].effectData)
+ (*pEASData->effectsModules[EAS_MODULE_ENHANCER].effect->pfProcess)
+ (pEASData->effectsModules[EAS_MODULE_ENHANCER].effectData,
+ pEASData->pOutputAudioBuffer,
+ pEASData->pOutputAudioBuffer,
+ numSamples);
+#endif
+
+#ifdef _GRAPHIC_EQ_ENABLED
+ /* graphic EQ effect */
+ if (pEASData->effectsModules[EAS_MODULE_GRAPHIC_EQ].effectData)
+ (*pEASData->effectsModules[EAS_MODULE_GRAPHIC_EQ].effect->pfProcess)
+ (pEASData->effectsModules[EAS_MODULE_GRAPHIC_EQ].effectData,
+ pEASData->pOutputAudioBuffer,
+ pEASData->pOutputAudioBuffer,
+ numSamples);
+#endif
+
+#ifdef _COMPRESSOR_ENABLED
+ /* compressor effect */
+ if (pEASData->effectsModules[EAS_MODULE_COMPRESSOR].effectData)
+ (*pEASData->effectsModules[EAS_MODULE_COMPRESSOR].effect->pfProcess)
+ (pEASData->effectsModules[EAS_MODULE_COMPRESSOR].effectData,
+ pEASData->pOutputAudioBuffer,
+ pEASData->pOutputAudioBuffer,
+ numSamples);
+#endif
+
+#ifdef _WOW_ENABLED
+ /* WOW requires a 32-bit buffer, borrow the mix buffer and
+ * pass it as the destination buffer
+ */
+ /*lint -e{740} temporarily passing a parameter through an existing I/F */
+ if (pEASData->effectsModules[EAS_MODULE_WOW].effectData)
+ (*pEASData->effectsModules[EAS_MODULE_WOW].effect->pfProcess)
+ (pEASData->effectsModules[EAS_MODULE_WOW].effectData,
+ pEASData->pOutputAudioBuffer,
+ (EAS_PCM*) pEASData->pMixBuffer,
+ numSamples);
+#endif
+
+#ifdef _TONECONTROLEQ_ENABLED
+ /* ToneControlEQ effect */
+ if (pEASData->effectsModules[EAS_MODULE_TONECONTROLEQ].effectData)
+ (*pEASData->effectsModules[EAS_MODULE_TONECONTROLEQ].effect->pfProcess)
+ (pEASData->effectsModules[EAS_MODULE_TONECONTROLEQ].effectData,
+ pEASData->pOutputAudioBuffer,
+ pEASData->pOutputAudioBuffer,
+ numSamples);
+#endif
+
+#ifdef _REVERB_ENABLED
+ /* Reverb effect */
+ if (pEASData->effectsModules[EAS_MODULE_REVERB].effectData)
+ (*pEASData->effectsModules[EAS_MODULE_REVERB].effect->pfProcess)
+ (pEASData->effectsModules[EAS_MODULE_REVERB].effectData,
+ pEASData->pOutputAudioBuffer,
+ pEASData->pOutputAudioBuffer,
+ numSamples);
+#endif
+
+#ifdef _CHORUS_ENABLED
+ /* Chorus effect */
+ if (pEASData->effectsModules[EAS_MODULE_CHORUS].effectData)
+ (*pEASData->effectsModules[EAS_MODULE_CHORUS].effect->pfProcess)
+ (pEASData->effectsModules[EAS_MODULE_CHORUS].effectData,
+ pEASData->pOutputAudioBuffer,
+ pEASData->pOutputAudioBuffer,
+ numSamples);
+#endif
+
+}
+
+#ifndef NATIVE_EAS_KERNEL
+/*----------------------------------------------------------------------------
+ * SynthMasterGain
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Mixes down audio from 32-bit to 16-bit target buffer
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ *----------------------------------------------------------------------------
+*/
+void SynthMasterGain (long *pInputBuffer, EAS_PCM *pOutputBuffer, EAS_U16 nGain, EAS_U16 numSamples) {
+
+ /* loop through the buffer */
+ while (numSamples--) {
+ long s;
+
+ /* read a sample from the input buffer and add some guard bits */
+ s = *pInputBuffer++;
+
+ /* add some guard bits */
+ /*lint -e{704} <avoid divide for performance>*/
+ s = s >> 7;
+
+ /* apply master gain */
+ s *= (long) nGain;
+
+ /* shift to lower 16-bits */
+ /*lint -e{704} <avoid divide for performance>*/
+ s = s >> 9;
+
+ /* saturate */
+ s = SATURATE(s);
+
+ *pOutputBuffer++ = (EAS_PCM)s;
+ }
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ * EAS_MixEngineShutdown()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Shuts down effects modules and deallocates memory
+ *
+ * Inputs:
+ * pEASData - instance data
+ * pInstData - instance data handle
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_MixEngineShutdown (S_EAS_DATA *pEASData)
+{
+
+ /* check Configuration Module for static memory allocation */
+ if (!pEASData->staticMemoryModel && (pEASData->pMixBuffer != NULL))
+ EAS_HWFree(pEASData->hwInstData, pEASData->pMixBuffer);
+
+ return EAS_SUCCESS;
+}
+
+#ifdef UNIFIED_MIXER
+#ifndef NATIVE_MIX_STREAM
+/*----------------------------------------------------------------------------
+ * EAS_MixStream
+ *----------------------------------------------------------------------------
+ * Mix a 16-bit stream into a 32-bit buffer
+ *
+ * pInputBuffer 16-bit input buffer
+ * pMixBuffer 32-bit mix buffer
+ * numSamples number of samples to mix
+ * gainLeft initial gain left or mono
+ * gainRight initial gain right
+ * gainLeft left gain increment per sample
+ * gainRight right gain increment per sample
+ * flags bit 0 = stereo source
+ * bit 1 = stereo output
+ *----------------------------------------------------------------------------
+*/
+void EAS_MixStream (EAS_PCM *pInputBuffer, EAS_I32 *pMixBuffer, EAS_I32 numSamples, EAS_I32 gainLeft, EAS_I32 gainRight, EAS_I32 gainIncLeft, EAS_I32 gainIncRight, EAS_I32 flags)
+{
+ EAS_I32 temp;
+ EAS_INT src, dest;
+
+ /* NOTE: There are a lot of optimizations that can be done
+ * in the native implementations based on register
+ * availability, etc. For example, it may make sense to
+ * break this down into 8 separate routines:
+ *
+ * 1. Mono source to mono output
+ * 2. Mono source to stereo output
+ * 3. Stereo source to mono output
+ * 4. Stereo source to stereo output
+ * 5. Mono source to mono output - no gain change
+ * 6. Mono source to stereo output - no gain change
+ * 7. Stereo source to mono output - no gain change
+ * 8. Stereo source to stereo output - no gain change
+ *
+ * Other possibilities include loop unrolling, skipping
+ * a gain calculation every 2 or 4 samples, etc.
+ */
+
+ /* no gain change, use fast loops */
+ if ((gainIncLeft == 0) && (gainIncRight == 0))
+ {
+ switch (flags & (MIX_FLAGS_STEREO_SOURCE | MIX_FLAGS_STEREO_OUTPUT))
+ {
+ /* mono to mono */
+ case 0:
+ gainLeft >>= 15;
+ for (src = dest = 0; src < numSamples; src++, dest++)
+ {
+
+ pMixBuffer[dest] += (pInputBuffer[src] * gainLeft) >> NUM_MIXER_GUARD_BITS;
+ }
+ break;
+
+ /* mono to stereo */
+ case MIX_FLAGS_STEREO_OUTPUT:
+ gainLeft >>= 15;
+ gainRight >>= 15;
+ for (src = dest = 0; src < numSamples; src++, dest+=2)
+ {
+ pMixBuffer[dest] += (pInputBuffer[src] * gainLeft) >> NUM_MIXER_GUARD_BITS;
+ pMixBuffer[dest+1] += (pInputBuffer[src] * gainRight) >> NUM_MIXER_GUARD_BITS;
+ }
+ break;
+
+ /* stereo to mono */
+ case MIX_FLAGS_STEREO_SOURCE:
+ gainLeft >>= 15;
+ gainRight >>= 15;
+ for (src = dest = 0; src < numSamples; src+=2, dest++)
+ {
+ temp = (pInputBuffer[src] * gainLeft) >> NUM_MIXER_GUARD_BITS;
+ temp += ((pInputBuffer[src+1] * gainRight) >> NUM_MIXER_GUARD_BITS);
+ pMixBuffer[dest] += temp;
+ }
+ break;
+
+ /* stereo to stereo */
+ case MIX_FLAGS_STEREO_SOURCE | MIX_FLAGS_STEREO_OUTPUT:
+ gainLeft >>= 15;
+ gainRight >>= 15;
+ for (src = dest = 0; src < numSamples; src+=2, dest+=2)
+ {
+ pMixBuffer[dest] += (pInputBuffer[src] * gainLeft) >> NUM_MIXER_GUARD_BITS;
+ pMixBuffer[dest+1] += (pInputBuffer[src+1] * gainRight) >> NUM_MIXER_GUARD_BITS;
+ }
+ break;
+ }
+ }
+
+ /* gain change - do gain increment */
+ else
+ {
+ switch (flags & (MIX_FLAGS_STEREO_SOURCE | MIX_FLAGS_STEREO_OUTPUT))
+ {
+ /* mono to mono */
+ case 0:
+ for (src = dest = 0; src < numSamples; src++, dest++)
+ {
+ gainLeft += gainIncLeft;
+ pMixBuffer[dest] += (pInputBuffer[src] * (gainLeft >> 15)) >> NUM_MIXER_GUARD_BITS;
+ }
+ break;
+
+ /* mono to stereo */
+ case MIX_FLAGS_STEREO_OUTPUT:
+ for (src = dest = 0; src < numSamples; src++, dest+=2)
+ {
+ gainLeft += gainIncLeft;
+ gainRight += gainIncRight;
+ pMixBuffer[dest] += (pInputBuffer[src] * (gainLeft >> 15)) >> NUM_MIXER_GUARD_BITS;
+ pMixBuffer[dest+1] += (pInputBuffer[src] * (gainRight >> 15)) >> NUM_MIXER_GUARD_BITS;
+ }
+ break;
+
+ /* stereo to mono */
+ case MIX_FLAGS_STEREO_SOURCE:
+ for (src = dest = 0; src < numSamples; src+=2, dest++)
+ {
+ gainLeft += gainIncLeft;
+ gainRight += gainIncRight;
+ temp = (pInputBuffer[src] * (gainLeft >> 15)) >> NUM_MIXER_GUARD_BITS;
+ temp += ((pInputBuffer[src+1] * (gainRight >> 15)) >> NUM_MIXER_GUARD_BITS);
+ pMixBuffer[dest] += temp;
+ }
+ break;
+
+ /* stereo to stereo */
+ case MIX_FLAGS_STEREO_SOURCE | MIX_FLAGS_STEREO_OUTPUT:
+ for (src = dest = 0; src < numSamples; src+=2, dest+=2)
+ {
+ gainLeft += gainIncLeft;
+ gainRight += gainIncRight;
+ pMixBuffer[dest] += (pInputBuffer[src] * (gainLeft >> 15)) >> NUM_MIXER_GUARD_BITS;
+ pMixBuffer[dest+1] += (pInputBuffer[src+1] * (gainRight >> 15)) >> NUM_MIXER_GUARD_BITS;
+ }
+ break;
+ }
+ }
+}
+#endif
+#endif
+
diff --git a/arm-fm-22k/lib_src/eas_mixer.h b/arm-fm-22k/lib_src/eas_mixer.h
new file mode 100644
index 0000000..2ba2d3d
--- /dev/null
+++ b/arm-fm-22k/lib_src/eas_mixer.h
@@ -0,0 +1,137 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_mixer.h
+ *
+ * Contents and purpose:
+ * This file contains the critical components of the mix engine that
+ * must be optimized for best performance.
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 706 $
+ * $Date: 2007-05-31 17:22:51 -0700 (Thu, 31 May 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+#ifndef _EAS_MIXER_H
+#define _EAS_MIXER_H
+
+//3 dls: This module is in the midst of being converted from a synth
+//3 specific module to a general purpose mix engine
+
+#define MIX_FLAGS_STEREO_SOURCE 1
+#define MIX_FLAGS_STEREO_OUTPUT 2
+#define NUM_MIXER_GUARD_BITS 4
+
+#include "eas_effects.h"
+
+extern void SynthMasterGain( long *pInputBuffer, EAS_PCM *pOutputBuffer, EAS_U16 nGain, EAS_U16 nNumLoopSamples);
+
+/*----------------------------------------------------------------------------
+ * EAS_MixEngineInit()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Prepares the mix engine for work, allocates buffers, locates effects modules, etc.
+ *
+ * Inputs:
+ * pEASData - instance data
+ * pInstData - pointer to variable to receive instance data handle
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_MixEngineInit (EAS_DATA_HANDLE pEASData);
+
+/*----------------------------------------------------------------------------
+ * EAS_MixEnginePrep()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Performs prep before synthesize a buffer of audio, such as clearing
+ * audio buffers, etc.
+ *
+ * Inputs:
+ * psEASData - pointer to overall EAS data structure
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+void EAS_MixEnginePrep (EAS_DATA_HANDLE pEASData, EAS_I32 nNumSamplesToAdd);
+
+/*----------------------------------------------------------------------------
+ * EAS_MixEnginePost
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * This routine does the post-processing after all voices have been
+ * synthesized. It calls any sweeteners and does the final mixdown to
+ * the output buffer.
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ * Notes:
+ *----------------------------------------------------------------------------
+*/
+void EAS_MixEnginePost (EAS_DATA_HANDLE pEASData, EAS_I32 nNumSamplesToAdd);
+
+/*----------------------------------------------------------------------------
+ * EAS_MixEngineShutdown()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Shuts down effects modules and deallocates memory
+ *
+ * Inputs:
+ * pEASData - instance data
+ * pInstData - instance data handle
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_MixEngineShutdown (EAS_DATA_HANDLE pEASData);
+
+#ifdef UNIFIED_MIXER
+/*----------------------------------------------------------------------------
+ * EAS_MixStream
+ *----------------------------------------------------------------------------
+ * Mix a 16-bit stream into a 32-bit buffer
+ *
+ * pInputBuffer 16-bit input buffer
+ * pMixBuffer 32-bit mix buffer
+ * numSamples number of samples to mix
+ * gainLeft initial gain left or mono
+ * gainRight initial gain right
+ * gainLeft left gain increment per sample
+ * gainRight right gain increment per sample
+ * flags bit 0 = stereo source
+ * bit 1 = stereo output
+ *----------------------------------------------------------------------------
+*/
+void EAS_MixStream (EAS_PCM *pInputBuffer, EAS_I32 *pMixBuffer, EAS_I32 numSamples, EAS_I32 gainLeft, EAS_I32 gainRight, EAS_I32 gainIncLeft, EAS_I32 gainIncRight, EAS_I32 flags);
+#endif
+
+#endif /* #ifndef _EAS_MIXER_H */
+
diff --git a/arm-fm-22k/lib_src/eas_ota.c b/arm-fm-22k/lib_src/eas_ota.c
new file mode 100644
index 0000000..fb81d62
--- /dev/null
+++ b/arm-fm-22k/lib_src/eas_ota.c
@@ -0,0 +1,1077 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_ota.c
+ *
+ * Contents and purpose:
+ * OTA parser
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 795 $
+ * $Date: 2007-08-01 00:14:45 -0700 (Wed, 01 Aug 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+#include "eas_data.h"
+#include "eas_miditypes.h"
+#include "eas_parser.h"
+#include "eas_report.h"
+#include "eas_host.h"
+#include "eas_midi.h"
+#include "eas_config.h"
+#include "eas_vm_protos.h"
+#include "eas_otadata.h"
+
+/* increase gain for mono ringtones */
+#define OTA_GAIN_OFFSET 8
+
+/* file definitions */
+#define OTA_RINGTONE 0x25
+#define OTA_SOUND 0x1d
+#define OTA_UNICODE 0x22
+
+/* song type definitions */
+#define OTA_BASIC_SONG_TYPE 0x01
+#define OTA_TEMPORARY_SONG_TYPE 0x02
+
+/* instruction ID coding */
+#define OTA_PATTERN_HEADER_ID 0x00
+#define OTA_NOTE_INST_ID 0x01
+#define OTA_SCALE_INST_ID 0x02
+#define OTA_STYLE_INST_ID 0x03
+#define OTA_TEMPO_INST_ID 0x04
+#define OTA_VOLUME_INST_ID 0x05
+
+/* note durations */
+#define OTA_NORMAL_DURATION 0x00
+#define OTA_DOTTED_NOTE 0x01
+#define OTA_DOUBLE_DOTTED_NOTE 0x02
+#define OTA_TRIPLET_NOTE 0x03
+
+/* loop count value for infinite loop */
+#define OTA_INFINITE_LOOP 0x0f
+
+/* length of 32nd note in 1/256ths of a msec for 63 BPM tempo */
+#define DEFAULT_TICK_CONV 30476
+
+/* default channel and program for OTA playback */
+#define OTA_CHANNEL 0
+#define OTA_PROGRAM 80
+#define OTA_VEL_MUL 4
+#define OTA_VEL_OFS 67
+#define OTA_VEL_DEFAULT 95
+
+/* multiplier for fixed point triplet conversion */
+#define TRIPLET_MULTIPLIER 683
+#define TRIPLET_SHIFT 10
+
+/* local prototypes */
+static EAS_RESULT OTA_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset);
+static EAS_RESULT OTA_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
+static EAS_RESULT OTA_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime);
+static EAS_RESULT OTA_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode);
+static EAS_RESULT OTA_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState);
+static EAS_RESULT OTA_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
+static EAS_RESULT OTA_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
+static EAS_RESULT OTA_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
+static EAS_RESULT OTA_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
+static EAS_RESULT OTA_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value);
+static EAS_RESULT OTA_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue);
+static EAS_RESULT OTA_ParseHeader (S_EAS_DATA *pEASData, S_OTA_DATA* pData);
+static EAS_RESULT OTA_FetchBitField (EAS_HW_DATA_HANDLE hwInstData, S_OTA_DATA *pData, EAS_I32 numBits, EAS_U8 *pValue);
+static EAS_RESULT OTA_SavePosition (EAS_HW_DATA_HANDLE hwInstData, S_OTA_DATA *pData, S_OTA_LOC *pLoc);
+static EAS_RESULT OTA_RestorePosition (EAS_HW_DATA_HANDLE hwInstData, S_OTA_DATA *pData, S_OTA_LOC *pLoc);
+
+
+/*----------------------------------------------------------------------------
+ *
+ * EAS_OTA_Parser
+ *
+ * This structure contains the functional interface for the OTA parser
+ *----------------------------------------------------------------------------
+*/
+const S_FILE_PARSER_INTERFACE EAS_OTA_Parser =
+{
+ OTA_CheckFileType,
+ OTA_Prepare,
+ OTA_Time,
+ OTA_Event,
+ OTA_State,
+ OTA_Close,
+ OTA_Reset,
+ OTA_Pause,
+ OTA_Resume,
+ NULL,
+ OTA_SetData,
+ OTA_GetData,
+ NULL
+};
+
+/*----------------------------------------------------------------------------
+ *
+ * bpmTable
+ *
+ * BPM conversion table. Converts bpm values to 256ths of a millisecond for a 32nd note
+ *----------------------------------------------------------------------------
+*/
+static const EAS_U32 bpmTable[32] =
+{
+ 76800, 68571, 61935, 54857,
+ 48000, 42667, 38400, 34286,
+ 30476, 27429, 24000, 21333,
+ 19200, 17143, 15360, 13714,
+ 12000, 10667, 9600, 8533,
+ 7680, 6737, 6000, 5408,
+ 4800, 4267, 3840, 3398,
+ 3024, 2685, 2400, 2133
+};
+
+/*----------------------------------------------------------------------------
+ * OTA_CheckFileType()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Check the file type to see if we can parse it
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT OTA_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset)
+{
+ S_OTA_DATA* pData;
+ EAS_RESULT result;
+ EAS_INT cmdLen;
+ EAS_INT state;
+ EAS_U8 temp;
+
+ /* read the first byte, should be command length */
+ *ppHandle = NULL;
+ if ((result = EAS_HWGetByte(pEASData->hwInstData, fileHandle, &temp)) != EAS_SUCCESS)
+ return result;
+
+ /* read all the commands */
+ cmdLen = temp;
+ state = 0;
+ while (cmdLen--)
+ {
+
+ /* read the command, upper 7 bits */
+ if ((result = EAS_HWGetByte(pEASData->hwInstData, fileHandle, &temp)) != EAS_SUCCESS)
+ return result;
+ temp = temp >> 1;
+
+ if (state == 0)
+ {
+ if (temp != OTA_RINGTONE)
+ break;
+ state++;
+ }
+ else
+ {
+
+ if (temp == OTA_SOUND)
+ {
+
+ /* check for static memory allocation */
+ if (pEASData->staticMemoryModel)
+ pData = EAS_CMEnumData(EAS_CM_OTA_DATA);
+ else
+ pData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_OTA_DATA));
+ if (!pData)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Malloc failed in OTA_Prepare\n"); */ }
+ return EAS_ERROR_MALLOC_FAILED;
+ }
+ EAS_HWMemSet(pData, 0, sizeof(S_OTA_DATA));
+
+ /* return a pointer to the instance data */
+ pData->fileHandle = fileHandle;
+ pData->fileOffset = offset;
+ pData->state = EAS_STATE_OPEN;
+ *ppHandle = pData;
+ break;
+ }
+
+ if (temp != OTA_UNICODE)
+ break;
+ }
+ }
+
+ /* not recognized */
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * OTA_Prepare()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Prepare to parse the file. Allocates instance data (or uses static allocation for
+ * static memory model).
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT OTA_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
+{
+ S_OTA_DATA* pData;
+ EAS_RESULT result;
+
+ /* check for valid state */
+ pData = (S_OTA_DATA*) pInstData;
+ if (pData->state != EAS_STATE_OPEN)
+ return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
+
+ /* instantiate a synthesizer */
+ if ((result = VMInitMIDI(pEASData, &pData->pSynth)) != EAS_SUCCESS)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMInitMIDI returned %d\n", result); */ }
+ return result;
+ }
+
+ pData->state = EAS_STATE_ERROR;
+ if ((result = OTA_ParseHeader(pEASData, pData)) != EAS_SUCCESS)
+ return result;
+
+ pData->state = EAS_STATE_READY;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * OTA_Time()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Returns the time of the next event in msecs
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ * pTime - pointer to variable to hold time of next event (in msecs)
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pEASData) common decoder interface - pEASData not used */
+static EAS_RESULT OTA_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime)
+{
+ S_OTA_DATA *pData;
+
+ pData = (S_OTA_DATA*) pInstData;
+
+ /* return time in milliseconds */
+ /*lint -e{704} use shift instead of division */
+ *pTime = pData->time >> 8;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * OTA_Event()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Parse the next event in the file
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT OTA_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode)
+{
+ S_OTA_DATA* pData;
+ EAS_RESULT result;
+ EAS_U32 duration;
+ EAS_U8 temp;
+
+ pData = (S_OTA_DATA*) pInstData;
+ if (pData->state >= EAS_STATE_OPEN)
+ return EAS_SUCCESS;
+
+ /* initialize MIDI channel when the track starts playing */
+ if (pData->time == 0)
+ {
+ /* set program to square lead */
+ if (parserMode != eParserModeMetaData)
+ VMProgramChange(pEASData->pVoiceMgr, pData->pSynth, OTA_CHANNEL, OTA_PROGRAM);
+
+ /* set channel volume to max */
+ if (parserMode != eParserModeMetaData)
+ VMControlChange(pEASData->pVoiceMgr, pData->pSynth, OTA_CHANNEL, 7, 127);
+ }
+
+ /* check for end of note */
+ if (pData->note)
+ {
+ /* stop the note */
+ VMStopNote(pEASData->pVoiceMgr, pData->pSynth, OTA_CHANNEL, pData->note, 0);
+ pData->note = 0;
+
+ /* check for rest between notes */
+ if (pData->restTicks)
+ {
+ pData->time += (EAS_I32) pData->restTicks;
+ pData->restTicks = 0;
+ return EAS_SUCCESS;
+ }
+ }
+
+ /* if not in a pattern, read the pattern header */
+ while (pData->current.patternLen == 0)
+ {
+
+ /* check for loop - don't do infinite loops when locating */
+ if (pData->loopCount && ((parserMode == eParserModePlay) || (pData->loopCount != OTA_INFINITE_LOOP)))
+ {
+ /* if not infinite loop, decrement loop count */
+ if (pData->loopCount != OTA_INFINITE_LOOP)
+ pData->loopCount--;
+
+ /* back to start of pattern*/
+ if ((result = OTA_RestorePosition(pEASData->hwInstData, pData, &pData->patterns[pData->currentPattern])) != EAS_SUCCESS)
+ return result;
+ }
+
+ /* if no previous position to restore, continue forward */
+ else if (pData->restore.fileOffset < 0)
+ {
+
+ /* check for end of song */
+ if (pData->numPatterns == 0)
+ {
+ pData->state = EAS_STATE_STOPPING;
+ VMReleaseAllVoices(pEASData->pVoiceMgr, pData->pSynth);
+ return EAS_SUCCESS;
+ }
+
+ /* read the next pattern header */
+ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 3, &temp)) != EAS_SUCCESS)
+ return result;
+ if (temp != OTA_PATTERN_HEADER_ID)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Expected OTA pattern header\n"); */ }
+ return EAS_ERROR_FILE_FORMAT;
+ }
+
+ /* get the pattern ID */
+ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 2, &pData->currentPattern)) != EAS_SUCCESS)
+ return result;
+
+ /* get the loop count */
+ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 4, &pData->loopCount)) != EAS_SUCCESS)
+ return result;
+
+ /* get the pattern length */
+ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 8, &pData->current.patternLen)) != EAS_SUCCESS)
+ return result;
+
+ /* if pattern definition, save the current position */
+ if (pData->current.patternLen)
+ {
+ if ((result = OTA_SavePosition(pEASData->hwInstData, pData, &pData->patterns[pData->currentPattern])) != EAS_SUCCESS)
+ return result;
+ }
+
+ /* if pattern length is zero, repeat a previous pattern */
+ else
+ {
+ /* make sure it's a valid pattern */
+ if (pData->patterns[pData->currentPattern].fileOffset < 0)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "OTA pattern error, invalid pattern specified\n"); */ }
+ return EAS_ERROR_FILE_FORMAT;
+ }
+
+ /* save current position and data */
+ if ((result = OTA_SavePosition(pEASData->hwInstData, pData, &pData->restore)) != EAS_SUCCESS)
+ return result;
+
+ /* seek to the pattern in the file */
+ if ((result = OTA_RestorePosition(pEASData->hwInstData, pData, &pData->patterns[pData->currentPattern])) != EAS_SUCCESS)
+ return result;
+ }
+
+ /* decrement pattern count */
+ pData->numPatterns--;
+ }
+
+ /* restore previous position */
+ else
+ {
+ if ((result = OTA_RestorePosition(pEASData->hwInstData, pData, &pData->restore)) != EAS_SUCCESS)
+ return result;
+ }
+ }
+
+ /* get the next event */
+ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 3, &temp)) != EAS_SUCCESS)
+ return result;
+
+ switch (temp)
+ {
+ case OTA_NOTE_INST_ID:
+ /* fetch note value */
+ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 4, &pData->note)) != EAS_SUCCESS)
+ return result;
+
+ /* fetch note duration */
+ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 3, &temp)) != EAS_SUCCESS)
+ return result;
+ duration = pData->tick * (0x20 >> temp);
+
+ /* fetch note duration modifier */
+ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 2, &temp)) != EAS_SUCCESS)
+ return result;
+ switch (temp)
+ {
+ case OTA_NORMAL_DURATION:
+ break;
+
+ case OTA_DOTTED_NOTE:
+ duration += duration >> 1;
+ break;
+
+ case OTA_DOUBLE_DOTTED_NOTE:
+ duration += (duration >> 1) + (duration >> 2);
+ break;
+
+ case OTA_TRIPLET_NOTE:
+ duration = (duration * TRIPLET_MULTIPLIER) >> TRIPLET_SHIFT;
+ break;
+
+ default:
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Unrecognized note duration ignored\n"); */ }
+ break;
+ }
+
+ /* check for note */
+ if (pData->note)
+ {
+
+ /* determine note length based on style */
+ switch (pData->style)
+ {
+ case 0:
+ pData->restTicks = duration >> 4;
+ break;
+ case 1:
+ pData->restTicks = 0;
+ break;
+ case 2:
+ pData->restTicks = duration >> 1;
+ break;
+ default:
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Unrecognized note style ignored\n"); */ }
+ }
+
+ /* add octave */
+ pData->note += pData->octave;
+ if (parserMode == eParserModePlay)
+ VMStartNote(pEASData->pVoiceMgr, pData->pSynth, OTA_CHANNEL, pData->note, pData->velocity);
+ pData->time += (EAS_I32) duration - (EAS_I32) pData->restTicks;
+ }
+
+ /* this is a rest */
+ else
+ pData->time += (EAS_I32) duration;
+ break;
+
+ case OTA_SCALE_INST_ID:
+ /* fetch octave */
+ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 2, &temp)) != EAS_SUCCESS)
+ return result;
+ pData->octave = (EAS_U8) (temp * 12 + 59);
+ break;
+
+ case OTA_STYLE_INST_ID:
+ /* fetch note style */
+ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 2, &pData->style)) != EAS_SUCCESS)
+ return result;
+ break;
+
+ case OTA_TEMPO_INST_ID:
+ /* fetch tempo */
+ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 5, &temp)) != EAS_SUCCESS)
+ return result;
+ pData->tick = bpmTable[temp];
+ break;
+
+ case OTA_VOLUME_INST_ID:
+ /* fetch volume */
+ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 4, &temp)) != EAS_SUCCESS)
+ return result;
+ pData->velocity = temp ? (EAS_U8) (temp * OTA_VEL_MUL + OTA_VEL_OFS) : 0;
+ break;
+
+ default:
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unexpected instruction ID in OTA stream\n"); */ }
+ return EAS_ERROR_FILE_FORMAT;
+ }
+
+ /* decrement pattern length */
+ pData->current.patternLen--;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * OTA_State()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Returns the current state of the stream
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ * pState - pointer to variable to store state
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pEASData) common decoder interface - pEASData not used */
+static EAS_RESULT OTA_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pState)
+{
+ S_OTA_DATA* pData;
+
+ /* establish pointer to instance data */
+ pData = (S_OTA_DATA*) pInstData;
+
+ /* if stopping, check to see if synth voices are active */
+ if (pData->state == EAS_STATE_STOPPING)
+ {
+ if (VMActiveVoices(pData->pSynth) == 0)
+ pData->state = EAS_STATE_STOPPED;
+ }
+
+ if (pData->state == EAS_STATE_PAUSING)
+ {
+ if (VMActiveVoices(pData->pSynth) == 0)
+ pData->state = EAS_STATE_PAUSED;
+ }
+
+ /* return current state */
+ *pState = pData->state;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * OTA_Close()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Close the file and clean up
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT OTA_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
+{
+ S_OTA_DATA* pData;
+ EAS_RESULT result;
+
+ pData = (S_OTA_DATA*) pInstData;
+
+ /* close the file */
+ if ((result = EAS_HWCloseFile(pEASData->hwInstData, pData->fileHandle)) != EAS_SUCCESS)
+ return result;
+
+ /* free the synth */
+ if (pData->pSynth != NULL)
+ VMMIDIShutdown(pEASData, pData->pSynth);
+
+ /* if using dynamic memory, free it */
+ if (!pEASData->staticMemoryModel)
+ EAS_HWFree(pEASData->hwInstData, pData);
+
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * OTA_Reset()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Reset the sequencer. Used for locating backwards in the file.
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT OTA_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
+{
+ S_OTA_DATA* pData;
+ EAS_RESULT result;
+
+ pData = (S_OTA_DATA*) pInstData;
+
+ /* reset the synth */
+ VMReset(pEASData->pVoiceMgr, pData->pSynth, EAS_TRUE);
+ pData->note = 0;
+
+ /* reset file position and re-parse header */
+ pData->state = EAS_STATE_ERROR;
+ if ((result = OTA_ParseHeader (pEASData, pData)) != EAS_SUCCESS)
+ return result;
+
+ pData->state = EAS_STATE_READY;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * OTA_Pause()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Pauses the sequencer. Mutes all voices and sets state to pause.
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT OTA_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
+{
+ S_OTA_DATA *pData;
+
+ /* can't pause a stopped stream */
+ pData = (S_OTA_DATA*) pInstData;
+ if (pData->state == EAS_STATE_STOPPED)
+ return EAS_ERROR_ALREADY_STOPPED;
+
+ /* mute the synthesizer */
+ VMMuteAllVoices(pEASData->pVoiceMgr, pData->pSynth);
+ pData->state = EAS_STATE_PAUSING;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * OTA_Resume()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Resume playing after a pause, sets state back to playing.
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pEASData) common decoder interface - pEASData not used */
+static EAS_RESULT OTA_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
+{
+ S_OTA_DATA *pData;
+
+ /* can't resume a stopped stream */
+ pData = (S_OTA_DATA*) pInstData;
+ if (pData->state == EAS_STATE_STOPPED)
+ return EAS_ERROR_ALREADY_STOPPED;
+
+ /* nothing to do but resume playback */
+ pData->state = EAS_STATE_PLAY;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * OTA_SetData()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Return file type
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pEASData) common decoder interface - pEASData not used */
+static EAS_RESULT OTA_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value)
+{
+ S_OTA_DATA *pData;
+
+ pData = (S_OTA_DATA *) pInstData;
+ switch (param)
+ {
+
+ /* set metadata callback */
+ case PARSER_DATA_METADATA_CB:
+ EAS_HWMemCpy(&pData->metadata, (void*) value, sizeof(S_METADATA_CB));
+ break;
+
+ default:
+ return EAS_ERROR_INVALID_PARAMETER;
+ }
+
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * OTA_GetData()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Return file type
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pEASData) common decoder interface - pEASData not used */
+static EAS_RESULT OTA_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue)
+{
+ S_OTA_DATA *pData;
+
+ pData = (S_OTA_DATA*) pInstData;
+ switch (param)
+ {
+ /* return file type as OTA */
+ case PARSER_DATA_FILE_TYPE:
+ *pValue = EAS_FILE_OTA;
+ break;
+
+#if 0
+ /* set transposition */
+ case PARSER_DATA_TRANSPOSITION:
+ *pValue = pData->transposition;
+ break;
+#endif
+
+ case PARSER_DATA_SYNTH_HANDLE:
+ *pValue = (EAS_I32) pData->pSynth;
+ break;
+
+ case PARSER_DATA_GAIN_OFFSET:
+ *pValue = OTA_GAIN_OFFSET;
+ break;
+
+ default:
+ return EAS_ERROR_INVALID_PARAMETER;
+ }
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * OTA_ParseHeader()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Prepare to parse the file. Allocates instance data (or uses static allocation for
+ * static memory model).
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT OTA_ParseHeader (S_EAS_DATA *pEASData, S_OTA_DATA* pData)
+{
+ EAS_RESULT result;
+ EAS_INT i;
+ EAS_INT state;
+ EAS_U8 temp;
+ EAS_U8 titleLen;
+
+ /* initialize some data */
+ pData->flags = 0;
+ pData->time = 0;
+ pData->tick = DEFAULT_TICK_CONV;
+ pData->patterns[0].fileOffset = pData->patterns[1].fileOffset =
+ pData->patterns[2].fileOffset = pData->patterns[3].fileOffset = -1;
+ pData->current.bitCount = 0;
+ pData->current.patternLen = 0;
+ pData->loopCount = 0;
+ pData->restore.fileOffset = -1;
+ pData->note = 0;
+ pData->restTicks = 0;
+ pData->velocity = OTA_VEL_DEFAULT;
+ pData->style = 0;
+ pData->octave = 59;
+
+ /* seek to start of data */
+ if ((result = EAS_HWFileSeek(pEASData->hwInstData, pData->fileHandle, pData->fileOffset)) != EAS_SUCCESS)
+ return result;
+
+ /* read the first byte, should be command length */
+ if ((result = EAS_HWGetByte(pEASData->hwInstData, pData->fileHandle, &temp)) != EAS_SUCCESS)
+ return result;
+
+ /* read all the commands */
+ i = temp;
+ state = 0;
+ while (i--)
+ {
+
+ /* fetch command, always starts on byte boundary */
+ pData->current.bitCount = 0;
+ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 7, &temp)) != EAS_SUCCESS)
+ return result;
+
+ if (state == 0)
+ {
+ if (temp != OTA_RINGTONE)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Expected OTA Ring Tone Programming type\n"); */ }
+ return EAS_ERROR_FILE_FORMAT;
+ }
+ state++;
+ }
+ else
+ {
+
+ if (temp == OTA_SOUND)
+ break;
+
+ if (temp == OTA_UNICODE)
+ pData->flags |= OTA_FLAGS_UNICODE;
+ else
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Expected OTA Sound or Unicode type\n"); */ }
+ return EAS_ERROR_FILE_FORMAT;
+ }
+ }
+ }
+
+ /* get song type */
+ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 3, &temp)) != EAS_SUCCESS)
+ return result;
+
+ /* check for basic song type */
+ if (temp == OTA_BASIC_SONG_TYPE)
+ {
+ /* fetch title length */
+ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 4, &titleLen)) != EAS_SUCCESS)
+ return result;
+
+ /* if unicode, double the length */
+ if (pData->flags & OTA_FLAGS_UNICODE)
+ titleLen = (EAS_U8) (titleLen << 1);
+
+ /* zero the metadata buffer */
+ if (pData->metadata.buffer)
+ EAS_HWMemSet(pData->metadata.buffer, 0, pData->metadata.bufferSize);
+
+ /* read the song title */
+ for (i = 0; i < titleLen; i++)
+ {
+ /* fetch character */
+ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 8, &temp)) != EAS_SUCCESS)
+ return result;
+
+ /* check for metadata callback */
+ if (pData->metadata.callback)
+ {
+ if (i < (pData->metadata.bufferSize - 1))
+ pData->metadata.buffer[i] = (char) temp;
+ }
+ }
+
+ /* if host has registered callback, call it now */
+ if (pData->metadata.callback)
+ (*pData->metadata.callback)(EAS_METADATA_TITLE, pData->metadata.buffer, pData->metadata.pUserData);
+ }
+
+ /* must be temporary song */
+ else if (temp != OTA_TEMPORARY_SONG_TYPE)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Expected OTA basic or temporary song type\n"); */ }
+ return EAS_ERROR_FILE_FORMAT;
+ }
+
+ /* get the song length */
+ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 8, &pData->numPatterns)) != EAS_SUCCESS)
+ return result;
+
+ /* sanity check */
+ if (pData->numPatterns == 0)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "OTA number of patterns is zero\n"); */ }
+ return EAS_ERROR_FILE_FORMAT;
+ }
+
+ /* at start of first pattern */
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * OTA_FetchBitField()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Fetch a specified number of bits from the input stream
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT OTA_FetchBitField (EAS_HW_DATA_HANDLE hwInstData, S_OTA_DATA *pData, EAS_I32 numBits, EAS_U8 *pValue)
+{
+ EAS_RESULT result;
+ EAS_I32 bitsLeft;
+ EAS_U8 value;
+
+ value = 0;
+
+ /* do we have enough bits? */
+ bitsLeft = pData->current.bitCount - numBits;
+
+ /* not enough bits, assemble them from 2 characters */
+ if (bitsLeft < 0)
+ {
+ /* grab the remaining bits from the previous byte */
+ if (pData->current.bitCount)
+ /*lint -e{504,734} this is a legitimate shift operation */
+ value = pData->current.dataByte << -bitsLeft;
+
+ /* read the next byte */
+ if ((result = EAS_HWGetByte(hwInstData, pData->fileHandle, &pData->current.dataByte)) != EAS_SUCCESS)
+ return result;
+ bitsLeft += 8;
+ }
+
+ /* more bits than needed? */
+ if (bitsLeft > 0)
+ {
+ value |= pData->current.dataByte >> bitsLeft;
+ pData->current.bitCount = (EAS_U8) bitsLeft;
+ pData->current.dataByte = pData->current.dataByte & (0xff >> (8 - bitsLeft));
+ }
+
+ /* exactly the right number of bits */
+ else
+ {
+ value |= pData->current.dataByte;
+ pData->current.bitCount = 0;
+ }
+
+ *pValue = value;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * OTA_SavePosition()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT OTA_SavePosition (EAS_HW_DATA_HANDLE hwInstData, S_OTA_DATA *pData, S_OTA_LOC *pLoc)
+{
+ EAS_HWMemCpy(pLoc, &pData->current, sizeof(S_OTA_LOC));
+ return EAS_HWFilePos(hwInstData, pData->fileHandle, &pLoc->fileOffset);
+}
+
+/*----------------------------------------------------------------------------
+ * OTA_RestorePosition()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT OTA_RestorePosition (EAS_HW_DATA_HANDLE hwInstData, S_OTA_DATA *pData, S_OTA_LOC *pLoc)
+{
+ EAS_HWMemCpy(&pData->current, pLoc, sizeof(S_OTA_LOC));
+ pData->restore.fileOffset = -1;
+ return EAS_HWFileSeek(hwInstData, pData->fileHandle, pLoc->fileOffset);
+}
+
diff --git a/arm-fm-22k/lib_src/eas_otadata.c b/arm-fm-22k/lib_src/eas_otadata.c
new file mode 100644
index 0000000..237f832
--- /dev/null
+++ b/arm-fm-22k/lib_src/eas_otadata.c
@@ -0,0 +1,41 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_otadata..c
+ *
+ * Contents and purpose:
+ * OTA Stream Parser data module for static memory model
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 547 $
+ * $Date: 2007-01-31 16:30:17 -0800 (Wed, 31 Jan 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+#include "eas_types.h"
+#include "eas_otadata.h"
+
+/*----------------------------------------------------------------------------
+ *
+ * eas_OTAData
+ *
+ * Static memory allocation for OTA parser
+ *----------------------------------------------------------------------------
+*/
+S_OTA_DATA eas_OTAData;
+
diff --git a/arm-fm-22k/lib_src/eas_otadata.h b/arm-fm-22k/lib_src/eas_otadata.h
new file mode 100644
index 0000000..63e963f
--- /dev/null
+++ b/arm-fm-22k/lib_src/eas_otadata.h
@@ -0,0 +1,81 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_otadata.h
+ *
+ * Contents and purpose:
+ * OTA File Parser
+ *
+ * This file contains data declarations for the OTA parser.
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 82 $
+ * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $
+ *----------------------------------------------------------------------------
+*/
+
+#ifndef EAS_OTADATA_H
+#define EAS_OTADATA_H
+
+#include "eas_data.h"
+
+/* definition for state flags */
+#define OTA_FLAGS_UNICODE 0x01 /* unicode text */
+
+/*----------------------------------------------------------------------------
+ *
+ * S_OTA_DATA
+ *
+ * This structure contains the state data for the OTA parser
+ *----------------------------------------------------------------------------
+*/
+
+typedef struct
+{
+ EAS_I32 fileOffset; /* offset to location in file */
+ EAS_U8 patternLen; /* length of current pattern */
+ EAS_U8 dataByte; /* previous char from file */
+ EAS_U8 bitCount; /* bit count in char */
+} S_OTA_LOC;
+
+typedef struct
+{
+ EAS_FILE_HANDLE fileHandle; /* file handle */
+ S_SYNTH *pSynth; /* synth handle */
+ EAS_I32 fileOffset; /* offset to start of data */
+ EAS_I32 time; /* current time in 256ths of a msec */
+ EAS_U32 tick; /* length of 32nd note in 256th of a msec */
+ EAS_U32 restTicks; /* ticks to rest after current note */
+ S_OTA_LOC patterns[4]; /* pattern locations */
+ S_OTA_LOC current; /* current location */
+ S_OTA_LOC restore; /* previous location */
+ S_METADATA_CB metadata; /* metadata callback */
+ EAS_U8 flags; /* bit flags */
+ EAS_U8 numPatterns; /* number of patterns left in song */
+ EAS_U8 currentPattern; /* current pattern for loop */
+ EAS_U8 note; /* MIDI note number */
+ EAS_U8 octave; /* octave modifier */
+ EAS_U8 style; /* from STYLE */
+ EAS_U8 velocity; /* current volume */
+ EAS_U8 state; /* current state EAS_STATE_XXXX */
+ EAS_U8 loopCount; /* loop count for pattern */
+} S_OTA_DATA;
+
+#endif
+
+
diff --git a/arm-fm-22k/lib_src/eas_pan.c b/arm-fm-22k/lib_src/eas_pan.c
new file mode 100644
index 0000000..373d90e
--- /dev/null
+++ b/arm-fm-22k/lib_src/eas_pan.c
@@ -0,0 +1,98 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_pan.c
+ *
+ * Contents and purpose:
+ * Calculates left and right gain multipliers based on a pan value from -63 to +63
+ *
+ * NOTES:
+ * The _CMX_PARSER and _MFI_PARSER preprocessor symbols determine
+ * whether the parser works for those particular file formats.
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 82 $
+ * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $
+ *----------------------------------------------------------------------------
+*/
+
+#include "eas_pan.h"
+#include "eas_math.h"
+
+/*----------------------------------------------------------------------------
+ * EAS_CalcPanControl()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Assign the left and right gain values corresponding to the given pan value.
+ *
+ * This routine uses sin/cos approximations for an equal power curve:
+ *
+ * sin(x) = (2-4*c)*x^2 + c + x
+ * cos(x) = (2-4*c)*x^2 + c - x
+ *
+ * where c = 1/sqrt(2)
+ * using the a0 + x*(a1 + x*a2) approach
+ *
+ * Inputs:
+ * pan - pan value (-63 to + 63)
+ *
+ * Outputs:
+ * pGainLeft linear gain multiplier for left channel (15-bit fraction)
+ * pGainRight linear gain multiplier for left channel (15-bit fraction)
+ *
+ * Side Effects:
+ *----------------------------------------------------------------------------
+*/
+void EAS_CalcPanControl (EAS_INT pan, EAS_I16 *pGainLeft, EAS_I16 *pGainRight)
+{
+ EAS_INT temp;
+ EAS_INT netAngle;
+
+ /* impose hard limit */
+ if (pan < -63)
+ netAngle = -63;
+ else if (pan > 63)
+ netAngle = 63;
+ else
+ netAngle = pan;
+
+ /*lint -e{701} <avoid multiply for performance reasons>*/
+ netAngle = netAngle << 8;
+
+ /* calculate sin */
+ temp = EG1_ONE + FMUL_15x15(COEFF_PAN_G2, netAngle);
+ temp = COEFF_PAN_G0 + FMUL_15x15(temp, netAngle);
+
+ if (temp > SYNTH_FULL_SCALE_EG1_GAIN)
+ temp = SYNTH_FULL_SCALE_EG1_GAIN;
+ else if (temp < 0)
+ temp = 0;
+
+ *pGainRight = (EAS_I16) temp;
+
+ /* calculate cos */
+ temp = -EG1_ONE + FMUL_15x15(COEFF_PAN_G2, netAngle);
+ temp = COEFF_PAN_G0 + FMUL_15x15(temp, netAngle);
+ if (temp > SYNTH_FULL_SCALE_EG1_GAIN)
+ temp = SYNTH_FULL_SCALE_EG1_GAIN;
+ else if (temp < 0)
+ temp = 0;
+
+ *pGainLeft = (EAS_I16) temp;
+}
+
diff --git a/arm-fm-22k/lib_src/eas_pan.h b/arm-fm-22k/lib_src/eas_pan.h
new file mode 100644
index 0000000..cefa650
--- /dev/null
+++ b/arm-fm-22k/lib_src/eas_pan.h
@@ -0,0 +1,66 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_pan.h
+ *
+ * Contents and purpose:
+ * Calculates left and right gain multipliers based on a pan value from -63 to +63
+ *
+ * NOTES:
+ * The _CMX_PARSER and _MFI_PARSER preprocessor symbols determine
+ * whether the parser works for those particular file formats.
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 82 $
+ * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $
+ *----------------------------------------------------------------------------
+*/
+
+#ifndef EAS_PAN_H
+#define _EAS_PAN_H
+
+#include "eas_types.h"
+
+/*----------------------------------------------------------------------------
+ * EAS_CalcPanControl()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Assign the left and right gain values corresponding to the given pan value.
+ *
+ * This routine uses sin/cos approximations for an equal power curve:
+ *
+ * sin(x) = (2-4*c)*x^2 + c + x
+ * cos(x) = (2-4*c)*x^2 + c - x
+ *
+ * where c = 1/sqrt(2)
+ * using the a0 + x*(a1 + x*a2) approach
+ *
+ * Inputs:
+ * pan - pan value (-63 to + 63)
+ *
+ * Outputs:
+ * pGainLeft linear gain multiplier for left channel (15-bit fraction)
+ * pGainRight linear gain multiplier for left channel (15-bit fraction)
+ *
+ * Side Effects:
+ *----------------------------------------------------------------------------
+*/
+void EAS_CalcPanControl (EAS_INT pan, EAS_I16 *pGainLeft, EAS_I16 *pGainRight);
+
+#endif
+
diff --git a/arm-fm-22k/lib_src/eas_parser.h b/arm-fm-22k/lib_src/eas_parser.h
new file mode 100644
index 0000000..5512c82
--- /dev/null
+++ b/arm-fm-22k/lib_src/eas_parser.h
@@ -0,0 +1,98 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_parser.h
+ *
+ * Contents and purpose:
+ * Interface declarations for the generic parser interface
+ *
+ * This header only contains declarations that are specific
+ * to this implementation.
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 767 $
+ * $Date: 2007-07-19 13:47:31 -0700 (Thu, 19 Jul 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+#ifndef _EAS_PARSER_H
+#define _EAS_PARSER_H
+
+#include "eas_types.h"
+
+
+/* metadata callback */
+typedef struct s_metadata_cb_tag
+{
+ EAS_METADATA_CBFUNC callback;
+ char *buffer;
+ EAS_VOID_PTR pUserData;
+ EAS_I32 bufferSize;
+} S_METADATA_CB;
+
+/* generic parser interface */
+typedef struct
+{
+ EAS_RESULT (* EAS_CONST pfCheckFileType)(struct s_eas_data_tag *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset);
+ EAS_RESULT (* EAS_CONST pfPrepare)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData);
+ EAS_RESULT (* EAS_CONST pfTime)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime);
+ EAS_RESULT (* EAS_CONST pfEvent)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData, EAS_INT parseMode);
+ EAS_RESULT (* EAS_CONST pfState)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState);
+ EAS_RESULT (* EAS_CONST pfClose)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData);
+ EAS_RESULT (* EAS_CONST pfReset)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData);
+ EAS_RESULT (* EAS_CONST pfPause)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData);
+ EAS_RESULT (* EAS_CONST pfResume)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData);
+ EAS_RESULT (* EAS_CONST pfLocate)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData, EAS_I32 time, EAS_BOOL *pParserLocate);
+ EAS_RESULT (* EAS_CONST pfSetData)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value);
+ EAS_RESULT (* EAS_CONST pfGetData)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue);
+ EAS_RESULT (* EAS_CONST pfGetMetaData)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pMediaLength);
+} S_FILE_PARSER_INTERFACE;
+
+typedef enum
+{
+ eParserModePlay,
+ eParserModeLocate,
+ eParserModeMute,
+ eParserModeMetaData
+} E_PARSE_MODE;
+
+typedef enum
+{
+ PARSER_DATA_FILE_TYPE,
+ PARSER_DATA_PLAYBACK_RATE,
+ PARSER_DATA_TRANSPOSITION,
+ PARSER_DATA_VOLUME,
+ PARSER_DATA_SYNTH_HANDLE,
+ PARSER_DATA_METADATA_CB,
+ PARSER_DATA_DLS_COLLECTION,
+ PARSER_DATA_EAS_LIBRARY,
+ PARSER_DATA_POLYPHONY,
+ PARSER_DATA_PRIORITY,
+ PARSER_DATA_FORMAT,
+ PARSER_DATA_MEDIA_LENGTH,
+ PARSER_DATA_JET_CB,
+ PARSER_DATA_MUTE_FLAGS,
+ PARSER_DATA_SET_MUTE,
+ PARSER_DATA_CLEAR_MUTE,
+ PARSER_DATA_NOTE_COUNT,
+ PARSER_DATA_MAX_PCM_STREAMS,
+ PARSER_DATA_GAIN_OFFSET,
+ PARSER_DATA_PLAY_MODE
+} E_PARSER_DATA;
+
+#endif /* #ifndef _EAS_PARSER_H */
diff --git a/arm-fm-22k/lib_src/eas_pcm.c b/arm-fm-22k/lib_src/eas_pcm.c
new file mode 100644
index 0000000..64b8f71
--- /dev/null
+++ b/arm-fm-22k/lib_src/eas_pcm.c
@@ -0,0 +1,1482 @@
+/*----------------------------------------------------------------------------
+ *
+ * File:
+ * eas_pcm.c
+ *
+ * Contents and purpose:
+ * Implements the PCM engine including ADPCM decode for SMAF and CMX audio playback.
+ *
+ * Copyright Sonic Network Inc. 2005
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *----------------------------------------------------------------------------
+ * Revision Control:
+ * $Revision: 849 $
+ * $Date: 2007-08-28 08:59:11 -0700 (Tue, 28 Aug 2007) $
+ *----------------------------------------------------------------------------
+*/
+
+#include "eas_data.h"
+#include "eas_report.h"
+#include "eas_host.h"
+#include "eas_config.h"
+#include "eas_parser.h"
+#include "eas_pcm.h"
+#include "eas_math.h"
+#include "eas_mixer.h"
+
+#define PCM_MIXER_GUARD_BITS (NUM_MIXER_GUARD_BITS + 1)
+
+/*----------------------------------------------------------------------------
+ * Decoder interfaces
+ *----------------------------------------------------------------------------
+*/
+
+static EAS_RESULT LinearPCMDecode (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState);
+static EAS_RESULT LinearPCMLocate (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState, EAS_I32 time);
+
+static const S_DECODER_INTERFACE PCMDecoder =
+{
+ NULL,
+ LinearPCMDecode,
+ LinearPCMLocate,
+};
+
+/* SMAF ADPCM decoder */
+#ifdef _SMAF_PARSER
+extern S_DECODER_INTERFACE SmafDecoder;
+#define SMAF_DECODER &SmafDecoder
+extern S_DECODER_INTERFACE Smaf7BitDecoder;
+#define SMAF_7BIT_DECODER &Smaf7BitDecoder
+#else
+#define SMAF_DECODER NULL
+#define SMAF_7BIT_DECODER NULL
+#endif
+
+/* IMA ADPCM decoder */
+#ifdef _IMA_DECODER
+extern S_DECODER_INTERFACE IMADecoder;
+#define IMA_DECODER &IMADecoder
+#else
+#define IMA_DECODER NULL
+#endif
+
+static const S_DECODER_INTERFACE * const decoders[] =
+{
+ &PCMDecoder,
+ SMAF_DECODER,
+ IMA_DECODER,
+ SMAF_7BIT_DECODER
+};
+
+/*----------------------------------------------------------------------------
+ * Sample rate conversion
+ *----------------------------------------------------------------------------
+*/
+
+#define SRC_RATE_MULTIPLER (0x40000000 / _OUTPUT_SAMPLE_RATE)
+
+#ifdef _LOOKUP_SAMPLE_RATE
+static const EAS_U32 srcConvRate[][2] =
+{
+ 4000L, (4000L << 15) / _OUTPUT_SAMPLE_RATE,
+ 8000L, (8000L << 15) / _OUTPUT_SAMPLE_RATE,
+ 11025L, (11025L << 15) / _OUTPUT_SAMPLE_RATE,
+ 12000L, (12000L << 15) / _OUTPUT_SAMPLE_RATE,
+ 16000L, (16000L << 15) / _OUTPUT_SAMPLE_RATE,
+ 22050L, (22050L << 15) / _OUTPUT_SAMPLE_RATE,
+ 24000L, (24000L << 15) / _OUTPUT_SAMPLE_RATE,
+ 32000L, (32000L << 15) / _OUTPUT_SAMPLE_RATE
+};
+static EAS_U32 CalcBaseFreq (EAS_U32 sampleRate);
+#define SRC_CONV_RATE_ENTRIES (sizeof(srcConvRate)/sizeof(EAS_U32)/2)
+#endif
+
+
+/* interface prototypes */
+static EAS_RESULT RenderPCMStream (S_EAS_DATA *pEASData, S_PCM_STATE *pState, EAS_I32 numSamples);
+
+
+/* local prototypes */
+static S_PCM_STATE *FindSlot (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_PCM_CALLBACK pCallbackFunc, EAS_VOID_PTR cbInstData);
+static EAS_RESULT InitPCMStream (S_EAS_DATA *pEASData, S_PCM_STATE *pState);
+
+/*----------------------------------------------------------------------------
+ * EAS_PEInit()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Initializes the PCM engine
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_PEInit (S_EAS_DATA *pEASData)
+{
+ S_PCM_STATE *pState;
+ EAS_INT i;
+
+ /* check for static memory allocation */
+ if (pEASData->staticMemoryModel)
+ pEASData->pPCMStreams = EAS_CMEnumData(EAS_CM_PCM_DATA);
+ /* allocate dynamic memory */
+ else
+ pEASData->pPCMStreams = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_PCM_STATE) * MAX_PCM_STREAMS);
+
+ if (!pEASData->pPCMStreams)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate memory for PCM streams\n"); */ }
+ return EAS_ERROR_MALLOC_FAILED;
+ }
+
+ //zero the memory to insure complete initialization
+ EAS_HWMemSet((void *)(pEASData->pPCMStreams),0, sizeof(S_PCM_STATE) * MAX_PCM_STREAMS);
+
+ /* initialize the state data */
+ for (i = 0, pState = pEASData->pPCMStreams; i < MAX_PCM_STREAMS; i++, pState++)
+ pState->fileHandle = NULL;
+
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_PEShutdown()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Shuts down the PCM engine
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_PEShutdown (S_EAS_DATA *pEASData)
+{
+
+ /* free any dynamic memory */
+ if (!pEASData->staticMemoryModel)
+ {
+ if (pEASData->pPCMStreams)
+ {
+ EAS_HWFree(pEASData->hwInstData, pEASData->pPCMStreams);
+ pEASData->pPCMStreams = NULL;
+ }
+ }
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_PERender()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Render a buffer of PCM audio
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_PERender (S_EAS_DATA* pEASData, EAS_I32 numSamples)
+{
+ S_PCM_STATE *pState;
+ EAS_RESULT result;
+ EAS_INT i;
+
+ /* render all the active streams */
+ for (i = 0, pState = pEASData->pPCMStreams; i < MAX_PCM_STREAMS; i++, pState++)
+ {
+ if ((pState->fileHandle) && (pState->state != EAS_STATE_STOPPED) && (pState->state != EAS_STATE_PAUSED))
+ if ((result = RenderPCMStream(pEASData, pState, numSamples)) != EAS_SUCCESS)
+ return result;
+ }
+ return EAS_SUCCESS;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EAS_PEState()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Returns the current state of the stream
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ * pState - pointer to variable to store state
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ * Notes:
+ * This interface is also exposed in the internal library for use by the other modules.
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pEASData) reserved for future use */
+EAS_RESULT EAS_PEState (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pInstData, EAS_STATE *pState)
+{
+ /* return current state */
+ *pState = pInstData->state;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_PEClose()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Close the file and clean up
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_PEClose (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState)
+{
+ EAS_RESULT result;
+
+ if ((result = EAS_HWCloseFile(pEASData->hwInstData, pState->fileHandle)) != EAS_SUCCESS)
+ return result;
+
+ pState->fileHandle = NULL;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * PCM_Reset()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Reset the sequencer. Used for locating backwards in the file.
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * handle - pointer to file handle
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_PEReset (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState)
+{
+ EAS_RESULT result;
+
+ /* reset file position to first byte of data in the stream */
+ if ((result = EAS_HWFileSeek(pEASData->hwInstData, pState->fileHandle, pState->startPos)) != EAS_SUCCESS)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %d seeking to start of PCM file\n", result); */ }
+ return result;
+ }
+
+ /* re-initialize stream */
+ return InitPCMStream(pEASData, pState);
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_PEOpenStream()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Starts up a PCM playback
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_PEOpenStream (S_EAS_DATA *pEASData, S_PCM_OPEN_PARAMS *pParams, EAS_PCM_HANDLE *pHandle)
+{
+ EAS_RESULT result;
+ S_PCM_STATE *pState;
+ EAS_I32 filePos;
+
+ /* make sure we support this decoder */
+ if (pParams->decoder >= NUM_DECODER_MODULES)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Decoder selector out of range\n"); */ }
+ return EAS_ERROR_PARAMETER_RANGE;
+ }
+ if (decoders[pParams->decoder] == NULL)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Decoder module not available\n"); */ }
+ return EAS_ERROR_FEATURE_NOT_AVAILABLE;
+ }
+
+ /* find a slot for the new stream */
+ if ((pState = FindSlot(pEASData, pParams->fileHandle, pParams->pCallbackFunc, pParams->cbInstData)) == NULL)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unable to open ADPCM stream, too many streams open\n"); */ }
+ return EAS_ERROR_MAX_PCM_STREAMS;
+ }
+
+ /* get the current file position */
+ if ((result = EAS_HWFilePos(pEASData->hwInstData, pState->fileHandle, &filePos)) != EAS_SUCCESS)
+ {
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_HWFilePos returned %ld\n",result); */ }
+ pState->fileHandle = NULL;
+ return result;
+ }
+
+ pState->pDecoder = decoders[pParams->decoder];
+ pState->startPos = filePos;
+ pState->bytesLeftLoop = pState->byteCount = pParams->size;
+ pState->loopStart = pParams->loopStart;
+ pState->samplesTilLoop = (EAS_I32) pState->loopStart;
+ pState->loopSamples = pParams->loopSamples;
+ pState->samplesInLoop = 0;
+ pState->blockSize = (EAS_U16) pParams->blockSize;
+ pState->flags = pParams->flags;
+ pState->envData = pParams->envData;
+ pState->volume = pParams->volume;
+ pState->sampleRate = (EAS_U16) pParams->sampleRate;
+
+ /* set the base frequency */
+ pState->basefreq = (SRC_RATE_MULTIPLER * (EAS_U32) pParams->sampleRate) >> 15;
+
+ /* calculate shift for frequencies > 1.0 */
+ pState->rateShift = 0;
+ while (pState->basefreq > 32767)
+ {
+ pState->basefreq = pState->basefreq >> 1;
+ pState->rateShift++;
+ }
+
+ /* initialize */
+ if ((result = InitPCMStream(pEASData, pState)) != EAS_SUCCESS)
+ return result;
+
+ *pHandle = pState;
+
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "EAS_PEOpenStream: StartPos=%d, byteCount = %d, loopSamples=%d\n",
+ pState->startPos, pState->byteCount, pState->loopSamples); */ }
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_PEContinueStream()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Continues a PCM stream
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -e{715} reserved for future use */
+EAS_RESULT EAS_PEContinueStream (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState, EAS_I32 size)
+{
+
+ /* add new samples to count */
+ pState->bytesLeft += size;
+ if (pState->bytesLeft > 0)
+ pState->flags &= ~PCM_FLAGS_EMPTY;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_PEGetFileHandle()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Returns the file handle of a stream
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pEASData) reserved for future use */
+EAS_RESULT EAS_PEGetFileHandle (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState, EAS_FILE_HANDLE *pFileHandle)
+{
+ *pFileHandle = pState->fileHandle;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_PEUpdateParams()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Update the pitch and volume parameters for a PCM stream
+ *
+ * Inputs:
+ * pEASData - pointer to EAS library instance data
+ * handle - pointer to S_PCM_STATE for this stream
+ * gainLeft - linear gain multipler in 1.15 fraction format
+ * gainRight - linear gain multipler in 1.15 fraction format
+ * pitch - pitch shift in cents
+ * initial - initial settings, set current gain
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ * Notes
+ * In mono mode, leftGain controls the output gain and rightGain is ignored
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pEASData) reserved for future use */
+/*lint -esym(715, gainRight) used only in 2-channel version */
+EAS_RESULT EAS_PEUpdateParams (S_EAS_DATA* pEASData, EAS_PCM_HANDLE pState, EAS_I16 pitch, EAS_I16 gainLeft, EAS_I16 gainRight)
+{
+
+ pState->gainLeft = gainLeft;
+
+#if (NUM_OUTPUT_CHANNELS == 2)
+ pState->gainRight = gainRight;
+#endif
+
+ pState->pitch = pitch;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_PELocate()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * This function seeks to the requested place in the file. Accuracy
+ * is dependent on the sample rate and block size.
+ *
+ * Inputs:
+ * pEASData - pointer to overall EAS data structure
+ * pState - stream handle
+ * time - media time in milliseconds
+ *----------------------------------------------------------------------------
+*/
+EAS_RESULT EAS_PELocate (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState, EAS_I32 time)
+{
+ if (pState->pDecoder->pfLocate == NULL)
+ return EAS_ERROR_FEATURE_NOT_AVAILABLE;
+
+ return pState->pDecoder->pfLocate(pEASData, pState, time);
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_PEUpdateVolume()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Update the volume parameters for a PCM stream
+ *
+ * Inputs:
+ * pEASData - pointer to EAS library instance data
+ * handle - pointer to S_PCM_STATE for this stream
+ * gainLeft - linear gain multipler in 1.15 fraction format
+ * gainRight - linear gain multipler in 1.15 fraction format
+ * initial - initial settings, set current gain
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ * Notes
+ * In mono mode, leftGain controls the output gain and rightGain is ignored
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pEASData) reserved for future use */
+EAS_RESULT EAS_PEUpdateVolume (S_EAS_DATA* pEASData, EAS_PCM_HANDLE pState, EAS_I16 volume)
+{
+ pState->volume = volume;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_PEUpdatePitch()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Update the pitch parameter for a PCM stream
+ *
+ * Inputs:
+ * pEASData - pointer to EAS library instance data
+ * pState - pointer to S_PCM_STATE for this stream
+ * pitch - new pitch value in pitch cents
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pEASData) reserved for future use */
+EAS_RESULT EAS_PEUpdatePitch (S_EAS_DATA* pEASData, EAS_PCM_HANDLE pState, EAS_I16 pitch)
+{
+ pState->pitch = pitch;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_PEPause()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Mute and stop rendering a PCM stream. Sets the gain target to zero and stops the playback
+ * at the end of the next audio frame.
+ *
+ * Inputs:
+ * pEASData - pointer to EAS library instance data
+ * handle - pointer to S_PCM_STATE for this stream
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pEASData) reserved for future use */
+EAS_RESULT EAS_PEPause (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState)
+{
+ /* set state to stopping */
+ pState->state = EAS_STATE_PAUSING;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_PEResume()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Resume rendering a PCM stream. Sets the gain target back to its
+ * previous setting and restarts playback at the end of the next audio
+ * frame.
+ *
+ * Inputs:
+ * pEASData - pointer to EAS library instance data
+ * handle - pointer to S_PCM_STATE for this stream
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pEASData) reserved for future use */
+EAS_RESULT EAS_PEResume (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState)
+{
+ /* set state to stopping */
+ pState->state = EAS_STATE_PLAY;
+ return EAS_SUCCESS;
+}
+
+EAS_U32 getDecayScale(EAS_U32 index)
+{
+ EAS_U32 utemp;
+
+ //envelope decay segment
+ switch (index)
+ {
+ case 0: //no decay
+ utemp = 512;//32768;
+ break;
+ case 1: //.0156 dB per update
+ utemp = 511;//32709;
+ break;
+ case 2: //.03125
+ utemp = 510;//32649;
+ break;
+ case 3: //.0625
+ utemp = 508;//32532;
+ break;
+ case 4: //.125
+ utemp = 505;//32298;
+ break;
+ case 5: //.25
+ utemp = 497;//31835;
+ break;
+ case 6: //.5
+ utemp = 483;//30929;
+ break;
+ case 7: //1.0
+ utemp = 456;//29193;
+ break;
+ case 8: //2.0
+ utemp = 406;//26008;
+ break;
+ case 9: //4.0
+ utemp = 323;//20642;
+ break;
+ case 10: //8.0
+ utemp = 203;//13004;
+ break;
+ case 11: //16.0
+ utemp = 81;//5160;
+ break;
+ case 12: //32.0
+ utemp = 13;//813;
+ break;
+ case 13: //64.0
+ utemp = 0;//20;
+ break;
+ case 14: //128.0
+ utemp = 0;
+ break;
+ case 15: //256.0
+ default:
+ utemp = 0;
+ break;
+ }
+ //printf("getdecayscale returned %d\n",utemp);
+ return utemp;
+}
+
+EAS_U32 getAttackIncrement(EAS_U32 index)
+{
+ EAS_U32 utemp;
+
+ //envelope decay segment
+ switch (index)
+ {
+ case 0:
+ utemp = 32;
+ break;
+ case 1:
+ utemp = 64;
+ break;
+ case 2:
+ utemp = 128;
+ break;
+ case 3:
+ utemp = 256;
+ break;
+ case 4:
+ utemp = 512;
+ break;
+ case 5:
+ utemp = 1024;
+ break;
+ case 6:
+ utemp = 2048;
+ break;
+ case 7:
+ utemp = 4096;
+ break;
+ case 8:
+ utemp = 8192;
+ break;
+ case 9:
+ utemp = 16384;
+ break;
+ case 10:
+ utemp = 32768;
+ break;
+ case 11:
+ utemp = 65536;
+ break;
+ case 12:
+ utemp = 65536;
+ break;
+ case 13:
+ utemp = 65536;
+ break;
+ case 14:
+ utemp = 65535;
+ break;
+ case 15:
+ default:
+ utemp = 0;
+ break;
+ }
+ //printf("getattackincrement returned %d\n",utemp);
+ return utemp;
+}
+
+/*----------------------------------------------------------------------------
+ * EAS_PERelease()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Put the PCM stream envelope into release.
+ *
+ * Inputs:
+ * pEASData - pointer to EAS library instance data
+ * handle - pointer to S_PCM_STATE for this stream
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+/*lint -esym(715, pEASData) reserved for future use */
+EAS_RESULT EAS_PERelease (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState)
+{
+ EAS_U32 utemp;
+
+ //printf("handling note-off part of envelope\n");
+ /*if the note is not ignore release or sustained*/
+ if (((pState->envData >> 24) & 0x0F)==0)
+ {
+ /* set envelope state to release */
+ pState->envState = PCM_ENV_RELEASE;
+ utemp = ((pState->envData >> 20) & 0x0F);
+ pState->envScale = getDecayScale(utemp); //getReleaseScale(utemp);
+ }
+ else
+ {
+ /*else change envelope state to sustain */
+ pState->envState = PCM_ENV_SUSTAIN;
+ utemp = ((pState->envData >> 28) & 0x0F);
+ pState->envScale = getDecayScale(utemp); //getSustainScale(utemp);
+ }
+ //since we are in release, don't let anything hang around too long
+ //printf("checking env scale, val = %d\n",((S_PCM_STATE*) handle)->envScale);
+ if (pState->envScale > 505)
+ pState->envScale = 505;
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * FindSlot()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Locates an empty stream slot and assigns the file handle
+ *
+ * Inputs:
+ * pEASData - pointer to EAS library instance data
+ * fileHandle - file handle
+ * pCallbackFunc - function to be called back upon EAS_STATE_STOPPED
+ *
+ * Outputs:
+ * returns handle to slot or NULL if all slots are used
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static S_PCM_STATE *FindSlot (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_PCM_CALLBACK pCallbackFunc, EAS_VOID_PTR cbInstData)
+{
+ EAS_INT i;
+ S_PCM_STATE *pState;
+
+#ifndef NO_PCM_STEAL
+ S_PCM_STATE *foundState = NULL;
+ EAS_INT count = 0;
+ EAS_U32 startOrder = 0xFFFFFFFF;
+ S_PCM_STATE *stealState = NULL;
+ EAS_U32 youngest = 0;
+
+ /* find an empty slot, count total in use, and find oldest in use (lowest start order) */
+ for (i = 0, pState = pEASData->pPCMStreams; i < MAX_PCM_STREAMS; i++, pState++)
+ {
+ /* if this one is available */
+ if (pState->fileHandle == NULL)
+ {
+ foundState = pState;
+ }
+ /* else this one is in use, so see if it is the oldest, and count total in use */
+ /* also find youngest */
+ else
+ {
+ /*one more voice in use*/
+ count++;
+ /* is this the oldest? (lowest start order) */
+ if ((pState->state != EAS_STATE_STOPPING) && (pState->startOrder < startOrder))
+ {
+ /* remember this one */
+ stealState = pState;
+ /* remember the oldest so far */
+ startOrder = pState->startOrder;
+ }
+ /* is this the youngest? (highest start order) */
+ if (pState->startOrder >= youngest)
+ {
+ youngest = pState->startOrder;
+ }
+ }
+ }
+
+ /* if there are too many voices active, stop the oldest one */
+ if (count > PCM_STREAM_THRESHOLD)
+ {
+ //printf("stealing!!!\n");
+ /* make sure we got one, although we should always have one at this point */
+ if (stealState != NULL)
+ {
+ //flag this as stopping, so it will get shut off
+ stealState->state = EAS_STATE_STOPPING;
+ }
+ }
+
+ /* if there are no available open streams (we won't likely see this, due to stealing) */
+ if (foundState == NULL)
+ return NULL;
+
+ /* save info */
+ foundState->startOrder = youngest + 1;
+ foundState->fileHandle = fileHandle;
+ foundState->pCallback = pCallbackFunc;
+ foundState->cbInstData = cbInstData;
+ return foundState;
+#else
+ /* find an empty slot*/
+ for (i = 0; i < MAX_PCM_STREAMS; i++)
+ {
+ pState = &pEASData->pPCMStreams[i];
+ if (pState->fileHandle != NULL)
+ continue;
+
+ pState->fileHandle = fileHandle;
+ pState->pCallback = pCallbackFunc;
+ pState->cbInstData = cbInstData;
+ return pState;
+ }
+ return NULL;
+#endif
+}
+
+#ifdef _LOOKUP_SAMPLE_RATE
+/*----------------------------------------------------------------------------
+ * CalcBaseFreq()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Calculates the fractional phase increment for the sample rate converter
+ *
+ * Inputs:
+ * sampleRate - sample rate in samples/sec
+ *
+ * Outputs:
+ * Returns fractional sample rate with a 15-bit fraction
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_U32 CalcBaseFreq (EAS_U32 sampleRate)
+{
+ EAS_INT i;
+
+ /* look up the conversion rate */
+ for (i = 0; i < (EAS_INT)(SRC_CONV_RATE_ENTRIES); i ++)
+ {
+ if (srcConvRate[i][0] == sampleRate)
+ return srcConvRate[i][1];
+ }
+
+ /* if not found in table, do it the long way */
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Sample rate %u not in table, calculating by division\n", sampleRate); */ }
+
+ return (SRC_RATE_MULTIPLER * (EAS_U32) sampleRate) >> 15;
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ * InitPCMStream()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Start an ADPCM stream playback. Decodes the header, preps the engine.
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT InitPCMStream (S_EAS_DATA *pEASData, S_PCM_STATE *pState)
+{
+
+ /* initialize the data structure */
+ pState->bytesLeft = pState->byteCount;
+ pState->phase = 0;
+ pState->srcByte = 0;
+ pState->decoderL.acc = 0;
+ pState->decoderL.output = 0;
+ pState->decoderL.x0 = pState->decoderL.x1 = 0;
+ pState->decoderL.step = 0;
+ pState->decoderR.acc = 0;
+ pState->decoderR.output = 0;
+ pState->decoderR.x0 = pState->decoderR.x1 = 0;
+ pState->decoderR.step = 0;
+ pState->hiNibble = EAS_FALSE;
+ pState->pitch = 0;
+ pState->blockCount = 0;
+ pState->gainLeft = PCM_DEFAULT_GAIN_SETTING;
+// pState->currentGainLeft = PCM_DEFAULT_GAIN_SETTING;
+ pState->envValue = 0;
+ pState->envState = PCM_ENV_START;
+
+#if (NUM_OUTPUT_CHANNELS == 2)
+ pState->gainRight = PCM_DEFAULT_GAIN_SETTING;
+// pState->currentGainRight = PCM_DEFAULT_GAIN_SETTING;
+#endif
+ pState->state = EAS_STATE_READY;
+
+ /* initialize the decoder */
+ if (pState->pDecoder->pfInit)
+ return (*pState->pDecoder->pfInit)(pEASData, pState);
+ return EAS_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ * RenderPCMStream()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Decodes a buffer of ADPCM data.
+ *
+ * Inputs:
+ *
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static EAS_RESULT RenderPCMStream (S_EAS_DATA *pEASData, S_PCM_STATE *pState, EAS_I32 numSamples)
+{
+ EAS_RESULT result;
+ EAS_U32 phaseInc;
+ EAS_I32 gainLeft, gainIncLeft;
+ EAS_I32 *pOut;
+ EAS_I32 temp;
+ EAS_U32 utemp;
+
+#if (NUM_OUTPUT_CHANNELS == 2)
+ EAS_I32 gainRight, gainIncRight;
+#endif
+
+#if 0
+ printf("env data: AR = %d, DR = %d, SL = %d, SR = %d, RR = %d\n",
+ ((pState->envData >> 12) & 0x0F),
+ ((pState->envData >> 16) & 0x0F),
+ ((pState->envData >> 8) & 0x0F),
+ ((pState->envData >> 28) & 0x0F),
+ ((pState->envData >> 20) & 0x0F));
+#endif
+
+ if (pState->envState == PCM_ENV_START)
+ {
+ //printf("env start\n");
+ utemp = ((pState->envData >> 12) & 0x0F);
+ //if fastest rate, attack is already completed
+ //do the same for slowest rate, since that allows zero to be passed for default envelope
+ if (utemp == 0x0F || utemp == 0x00)
+ {
+ //start envelope at full
+ pState->envValue = (32768<<7);
+ //jump right into decay
+ utemp = ((pState->envData >> 16) & 0x0F);
+ pState->envScale = getDecayScale(utemp);
+ pState->envState = PCM_ENV_DECAY;
+ pState->currentGainLeft = (EAS_I16) FMUL_15x15(pState->gainLeft, pState->volume);
+ pState->currentGainRight = (EAS_I16) FMUL_15x15(pState->gainRight, pState->volume);
+ }
+ //else attack has a ramp
+ else
+ {
+ //start the envelope very low
+ pState->envValue = (2<<7);
+ pState->currentGainLeft = 0;
+ pState->currentGainRight = 0;
+ //get envelope attack scaling value
+ pState->envScale = getAttackIncrement(utemp);
+ //go to attack state
+ pState->envState = PCM_ENV_ATTACK;
+ }
+ }
+ if (pState->envState == PCM_ENV_ATTACK)
+ {
+ //printf("env attack, env value = %d, env scale = %d\n",pState->envValue>>7,pState->envScale);
+ //update envelope value
+ pState->envValue = pState->envValue + (pState->envScale << 7);
+ //check envelope level and update state if needed
+ if (pState->envValue >= (32768<<7))
+ {
+ pState->envValue = (32768<<7);
+ utemp = ((pState->envData >> 16) & 0x0F);
+ pState->envScale = getDecayScale(utemp);
+ pState->envState = PCM_ENV_DECAY;
+ }
+ }
+ else if (pState->envState == PCM_ENV_DECAY)
+ {
+ //printf("env decay, env value = %d, env scale = %d\n",pState->envValue>>7,pState->envScale);
+ //update envelope value
+ pState->envValue = (pState->envValue * pState->envScale)>>9;
+ //check envelope level against sustain level and update state if needed
+ utemp = ((pState->envData >> 8) & 0x0F);
+ if (utemp == (EAS_U32)0x0F)
+ utemp = (2<<7);
+ else
+ {
+ utemp = ((32769<<7) >> (utemp>>1));
+ }
+ if (pState->envValue <= utemp)
+ {
+ utemp = ((pState->envData >> 28) & 0x0F);
+ pState->envScale = getDecayScale(utemp); //getSustainScale(utemp);
+ pState->envState = PCM_ENV_SUSTAIN;
+ }
+ }
+ else if (pState->envState == PCM_ENV_SUSTAIN)
+ {
+ //printf("env sustain, env value = %d, env scale = %d\n",pState->envValue>>7,pState->envScale);
+ //update envelope value
+ pState->envValue = (pState->envValue * pState->envScale)>>9;
+ //check envelope level against bottom level and update state if needed
+ if (pState->envValue <= (2<<7))
+ {
+ //no more decay
+ pState->envScale = 512;
+ pState->envState = PCM_ENV_END;
+ }
+ }
+ else if (pState->envState == PCM_ENV_RELEASE)
+ {
+ //printf("env release, env value = %d, env scale = %d\n",pState->envValue>>7,pState->envScale);
+ //update envelope value
+ pState->envValue = (pState->envValue * pState->envScale)>>9;
+ //check envelope level against bottom level and update state if needed
+ if (pState->envValue <= (2<<7))
+ {
+ //no more decay
+ pState->envScale = 512;
+ pState->envState = PCM_ENV_END;
+ }
+ }
+ else if (pState->envState == PCM_ENV_END)
+ {
+ //printf("env end\n");
+ /* set state to stopping, already ramped down */
+ pState->state = EAS_STATE_STOPPING;
+ }
+
+ //pState->gainLeft = (EAS_U16)((pState->gainLeft * (pState->envValue>>7))>>15);
+ //pState->gainRight = (EAS_U16)((pState->gainRight * (pState->envValue>>7))>>15);
+
+ /* gain to 32-bits to increase resolution on anti-zipper filter */
+ /*lint -e{703} use shift for performance */
+ gainLeft = (EAS_I32) pState->currentGainLeft << SYNTH_UPDATE_PERIOD_IN_BITS;
+#if (NUM_OUTPUT_CHANNELS == 2)
+ /*lint -e{703} use shift for performance */
+ gainRight = (EAS_I32) pState->currentGainRight << SYNTH_UPDATE_PERIOD_IN_BITS;
+#endif
+
+ /* calculate a new gain increment, gain target is zero if pausing */
+ if ((pState->state == EAS_STATE_PAUSING) || (pState->state == EAS_STATE_PAUSED))
+ {
+ gainIncLeft = -pState->currentGainLeft;
+#if (NUM_OUTPUT_CHANNELS == 2)
+ gainIncRight= -pState->currentGainRight;
+#endif
+ }
+ else
+ {
+ EAS_I32 gain = FMUL_15x15(pState->envValue >> 7, pState->volume);
+ gainIncLeft = FMUL_15x15(pState->gainLeft, gain) - pState->currentGainLeft;
+#if (NUM_OUTPUT_CHANNELS == 2)
+ gainIncRight = FMUL_15x15(pState->gainRight, gain) - pState->currentGainRight;
+#endif
+ }
+
+ /* calculate phase increment */
+ phaseInc = pState->basefreq;
+
+ /* convert pitch cents to linear multiplier */
+ if (pState->pitch)
+ {
+ temp = EAS_Calculate2toX(pState->pitch);
+ phaseInc = FMUL_15x15(phaseInc, temp);
+ }
+ phaseInc = phaseInc << pState->rateShift;
+
+ /* pointer to mix buffer */
+ pOut = pEASData->pMixBuffer;
+
+ /* render a buffer of samples */
+ while (numSamples--)
+ {
+
+ /* interpolate an output sample */
+ pState->decoderL.output = pState->decoderL.x0 + FMUL_15x15((pState->decoderL.x1 - pState->decoderL.x0), pState->phase & PHASE_FRAC_MASK);
+
+ /* stereo output */
+#if (NUM_OUTPUT_CHANNELS == 2)
+
+ /* stereo stream? */
+ if (pState->flags & PCM_FLAGS_STEREO)
+ pState->decoderR.output = pState->decoderR.x0 + FMUL_15x15((pState->decoderR.x1 - pState->decoderR.x0), pState->phase & PHASE_FRAC_MASK);
+
+ /* gain scale and mix */
+ /*lint -e{704} use shift instead of division */
+ *pOut++ += (pState->decoderL.output * (gainLeft >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS;
+ gainLeft += gainIncLeft;
+
+ /*lint -e{704} use shift instead of division */
+ if (pState->flags & PCM_FLAGS_STEREO)
+ *pOut++ += (pState->decoderR.output * (gainRight >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS;
+ else
+ *pOut++ += (pState->decoderL.output * (gainRight >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS;
+
+ gainRight += gainIncRight;
+
+ /* mono output */
+#else
+ /* if stereo stream, decode right channel and mix to mono */
+ if (pState->flags & PCM_FLAGS_STEREO)
+ {
+ pState->decoderR.output= pState->decoderR.x0 + FMUL_15x15((pState->decoderR.x1 - pState->decoderR.x0), pState->phase & PHASE_FRAC_MASK);
+
+ /* for mono, sum stereo ADPCM to mono */
+ /*lint -e{704} use shift instead of division */
+ *pOut++ += ((pState->decoderL.output + pState->decoderR.output) * (gainLeft >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS;
+ }
+ else
+ /*lint -e{704} use shift instead of division */
+ *pOut++ += (pState->decoderL.output * (gainLeft >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS;
+
+ gainLeft += gainIncLeft;
+#endif
+
+ /* advance phase accumulator */
+ pState->phase += phaseInc;
+
+ /* if integer part of phase accumulator is non-zero, advance to next sample */
+ while (pState->phase & ~PHASE_FRAC_MASK)
+ {
+ pState->decoderL.x0 = pState->decoderL.x1;
+ pState->decoderR.x0 = pState->decoderR.x1;
+
+ /* give the source a chance to continue the stream */
+ if (!pState->bytesLeft && pState->pCallback && ((pState->flags & PCM_FLAGS_EMPTY) == 0))
+ {
+ pState->flags |= PCM_FLAGS_EMPTY;
+ (*pState->pCallback)(pEASData, pState->cbInstData, pState, EAS_STATE_EMPTY);
+ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "RenderPCMStream: After empty callback, bytesLeft = %d\n", pState->bytesLeft); */ }
+ }
+
+ /* decode the next sample */
+ if ((result = (*pState->pDecoder->pfDecodeSample)(pEASData, pState)) != EAS_SUCCESS)
+ return result;
+
+ /* adjust phase by one sample */
+ pState->phase -= (1L << NUM_PHASE_FRAC_BITS);
+ }
+
+ }
+
+ /* save new gain */
+ /*lint -e{704} use shift instead of division */
+ pState->currentGainLeft = (EAS_I16) (gainLeft >> SYNTH_UPDATE_PERIOD_IN_BITS);
+
+#if (NUM_OUTPUT_CHANNELS == 2)
+ /*lint -e{704} use shift instead of division */
+ pState->currentGainRight = (EAS_I16) (gainRight >> SYNTH_UPDATE_PERIOD_IN_BITS);
+#endif
+
+ /* if pausing, set new state and notify */
+ if (pState->state == EAS_STATE_PAUSING)
+ {