From a8c89077d78769bf4840fa91609edc51fe2fa02d Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Queru Date: Thu, 12 Nov 2009 18:45:37 -0800 Subject: eclair snapshot --- arm-fm-22k/host_src/eas.h | 2100 +- arm-fm-22k/host_src/eas_build.h | 48 +- arm-fm-22k/host_src/eas_chorus.h | 80 +- arm-fm-22k/host_src/eas_config.c | 1214 +- arm-fm-22k/host_src/eas_config.h | 358 +- arm-fm-22k/host_src/eas_debugmsgs.h | 86 +- arm-fm-22k/host_src/eas_host.h | 142 +- arm-fm-22k/host_src/eas_hostmm.c | 1296 +- arm-fm-22k/host_src/eas_main.c | 898 +- arm-fm-22k/host_src/eas_report.c | 504 +- arm-fm-22k/host_src/eas_report.h | 130 +- arm-fm-22k/host_src/eas_reverb.h | 84 +- arm-fm-22k/host_src/eas_types.h | 512 +- arm-fm-22k/host_src/eas_wave.c | 822 +- arm-fm-22k/host_src/eas_wave.h | 124 +- arm-fm-22k/lib_src/eas_audioconst.h | 170 +- arm-fm-22k/lib_src/eas_chorus.c | 1184 +- arm-fm-22k/lib_src/eas_chorusdata.c | 44 +- arm-fm-22k/lib_src/eas_chorusdata.h | 296 +- arm-fm-22k/lib_src/eas_ctype.h | 58 +- arm-fm-22k/lib_src/eas_data.c | 50 +- arm-fm-22k/lib_src/eas_data.h | 238 +- arm-fm-22k/lib_src/eas_effects.h | 98 +- arm-fm-22k/lib_src/eas_fmengine.c | 1546 +- arm-fm-22k/lib_src/eas_fmengine.h | 218 +- arm-fm-22k/lib_src/eas_fmsndlib.c | 3324 +-- arm-fm-22k/lib_src/eas_fmsynth.c | 1796 +- arm-fm-22k/lib_src/eas_fmsynth.h | 138 +- arm-fm-22k/lib_src/eas_fmtables.c | 712 +- arm-fm-22k/lib_src/eas_ima_tables.c | 84 +- arm-fm-22k/lib_src/eas_imaadpcm.c | 712 +- arm-fm-22k/lib_src/eas_imelody.c | 3452 +-- arm-fm-22k/lib_src/eas_imelodydata.c | 62 +- arm-fm-22k/lib_src/eas_imelodydata.h | 122 +- arm-fm-22k/lib_src/eas_math.c | 312 +- arm-fm-22k/lib_src/eas_math.h | 800 +- arm-fm-22k/lib_src/eas_midi.c | 1114 +- arm-fm-22k/lib_src/eas_midi.h | 118 +- arm-fm-22k/lib_src/eas_midictrl.h | 104 +- arm-fm-22k/lib_src/eas_mididata.c | 44 +- arm-fm-22k/lib_src/eas_miditypes.h | 252 +- arm-fm-22k/lib_src/eas_mixbuf.c | 48 +- arm-fm-22k/lib_src/eas_mixer.c | 904 +- arm-fm-22k/lib_src/eas_mixer.h | 250 +- arm-fm-22k/lib_src/eas_ota.c | 2130 +- arm-fm-22k/lib_src/eas_otadata.c | 58 +- arm-fm-22k/lib_src/eas_otadata.h | 138 +- arm-fm-22k/lib_src/eas_pan.c | 172 +- arm-fm-22k/lib_src/eas_pan.h | 108 +- arm-fm-22k/lib_src/eas_parser.h | 172 +- arm-fm-22k/lib_src/eas_pcm.c | 2940 +- arm-fm-22k/lib_src/eas_pcm.h | 694 +- arm-fm-22k/lib_src/eas_pcmdata.c | 46 +- arm-fm-22k/lib_src/eas_pcmdata.h | 290 +- arm-fm-22k/lib_src/eas_public.c | 5170 ++-- arm-fm-22k/lib_src/eas_reverb.c | 2284 +- arm-fm-22k/lib_src/eas_reverbdata.c | 44 +- arm-fm-22k/lib_src/eas_reverbdata.h | 948 +- arm-fm-22k/lib_src/eas_rtttl.c | 2370 +- arm-fm-22k/lib_src/eas_rtttldata.c | 58 +- arm-fm-22k/lib_src/eas_rtttldata.h | 116 +- arm-fm-22k/lib_src/eas_smf.c | 2382 +- arm-fm-22k/lib_src/eas_smf.h | 74 +- arm-fm-22k/lib_src/eas_smfdata.c | 108 +- arm-fm-22k/lib_src/eas_smfdata.h | 108 +- arm-fm-22k/lib_src/eas_sndlib.h | 788 +- arm-fm-22k/lib_src/eas_synth.h | 766 +- arm-fm-22k/lib_src/eas_synth_protos.h | 96 +- arm-fm-22k/lib_src/eas_synthcfg.h | 116 +- arm-fm-22k/lib_src/eas_vm_protos.h | 2148 +- arm-fm-22k/lib_src/eas_voicemgt.c | 7918 ++--- arm-fm-22k/lib_src/eas_wavefile.c | 1710 +- arm-fm-22k/lib_src/eas_wavefile.h | 102 +- arm-fm-22k/lib_src/eas_wavefiledata.c | 42 +- arm-hybrid-22k/host_src/eas.h | 2100 +- arm-hybrid-22k/host_src/eas_build.h | 48 +- arm-hybrid-22k/host_src/eas_chorus.h | 80 +- arm-hybrid-22k/host_src/eas_config.c | 1214 +- arm-hybrid-22k/host_src/eas_config.h | 358 +- arm-hybrid-22k/host_src/eas_debugmsgs.h | 88 +- arm-hybrid-22k/host_src/eas_host.h | 142 +- arm-hybrid-22k/host_src/eas_hostmm.c | 1296 +- arm-hybrid-22k/host_src/eas_main.c | 898 +- arm-hybrid-22k/host_src/eas_report.c | 504 +- arm-hybrid-22k/host_src/eas_report.h | 130 +- arm-hybrid-22k/host_src/eas_reverb.h | 84 +- arm-hybrid-22k/host_src/eas_types.h | 512 +- arm-hybrid-22k/host_src/eas_wave.c | 822 +- arm-hybrid-22k/host_src/eas_wave.h | 124 +- arm-hybrid-22k/lib_src/ARM_synth_constants_gnu.inc | 306 +- arm-hybrid-22k/lib_src/eas_audioconst.h | 170 +- arm-hybrid-22k/lib_src/eas_chorus.c | 1184 +- arm-hybrid-22k/lib_src/eas_chorusdata.c | 44 +- arm-hybrid-22k/lib_src/eas_chorusdata.h | 296 +- arm-hybrid-22k/lib_src/eas_ctype.h | 58 +- arm-hybrid-22k/lib_src/eas_data.c | 50 +- arm-hybrid-22k/lib_src/eas_data.h | 238 +- arm-hybrid-22k/lib_src/eas_effects.h | 98 +- arm-hybrid-22k/lib_src/eas_fmengine.c | 1546 +- arm-hybrid-22k/lib_src/eas_fmengine.h | 218 +- arm-hybrid-22k/lib_src/eas_fmsynth.c | 1796 +- arm-hybrid-22k/lib_src/eas_fmsynth.h | 138 +- arm-hybrid-22k/lib_src/eas_fmtables.c | 712 +- arm-hybrid-22k/lib_src/eas_ima_tables.c | 84 +- arm-hybrid-22k/lib_src/eas_imaadpcm.c | 712 +- arm-hybrid-22k/lib_src/eas_imelody.c | 3452 +-- arm-hybrid-22k/lib_src/eas_imelodydata.c | 62 +- arm-hybrid-22k/lib_src/eas_imelodydata.h | 122 +- arm-hybrid-22k/lib_src/eas_math.c | 312 +- arm-hybrid-22k/lib_src/eas_math.h | 800 +- arm-hybrid-22k/lib_src/eas_midi.c | 1114 +- arm-hybrid-22k/lib_src/eas_midi.h | 118 +- arm-hybrid-22k/lib_src/eas_midictrl.h | 104 +- arm-hybrid-22k/lib_src/eas_mididata.c | 44 +- arm-hybrid-22k/lib_src/eas_miditypes.h | 252 +- arm-hybrid-22k/lib_src/eas_mixbuf.c | 48 +- arm-hybrid-22k/lib_src/eas_mixer.c | 904 +- arm-hybrid-22k/lib_src/eas_mixer.h | 250 +- arm-hybrid-22k/lib_src/eas_ota.c | 2130 +- arm-hybrid-22k/lib_src/eas_otadata.c | 58 +- arm-hybrid-22k/lib_src/eas_otadata.h | 138 +- arm-hybrid-22k/lib_src/eas_pan.c | 172 +- arm-hybrid-22k/lib_src/eas_pan.h | 108 +- arm-hybrid-22k/lib_src/eas_parser.h | 172 +- arm-hybrid-22k/lib_src/eas_pcm.c | 2940 +- arm-hybrid-22k/lib_src/eas_pcm.h | 694 +- arm-hybrid-22k/lib_src/eas_pcmdata.c | 46 +- arm-hybrid-22k/lib_src/eas_pcmdata.h | 290 +- arm-hybrid-22k/lib_src/eas_public.c | 5170 ++-- arm-hybrid-22k/lib_src/eas_reverb.c | 2284 +- arm-hybrid-22k/lib_src/eas_reverbdata.c | 44 +- arm-hybrid-22k/lib_src/eas_reverbdata.h | 948 +- arm-hybrid-22k/lib_src/eas_rtttl.c | 2370 +- arm-hybrid-22k/lib_src/eas_rtttldata.c | 58 +- arm-hybrid-22k/lib_src/eas_rtttldata.h | 116 +- arm-hybrid-22k/lib_src/eas_smf.c | 2382 +- arm-hybrid-22k/lib_src/eas_smf.h | 74 +- arm-hybrid-22k/lib_src/eas_smfdata.c | 108 +- arm-hybrid-22k/lib_src/eas_smfdata.h | 108 +- arm-hybrid-22k/lib_src/eas_sndlib.h | 788 +- arm-hybrid-22k/lib_src/eas_synth.h | 766 +- arm-hybrid-22k/lib_src/eas_synth_protos.h | 96 +- arm-hybrid-22k/lib_src/eas_synthcfg.h | 116 +- arm-hybrid-22k/lib_src/eas_vm_protos.h | 2148 +- arm-hybrid-22k/lib_src/eas_voicemgt.c | 7918 ++--- arm-hybrid-22k/lib_src/eas_wavefile.c | 1710 +- arm-hybrid-22k/lib_src/eas_wavefile.h | 102 +- arm-hybrid-22k/lib_src/eas_wavefiledata.c | 42 +- arm-hybrid-22k/lib_src/eas_wt_IPC_frame.h | 140 +- arm-hybrid-22k/lib_src/eas_wtengine.c | 1298 +- arm-hybrid-22k/lib_src/eas_wtengine.h | 318 +- arm-hybrid-22k/lib_src/eas_wtsynth.c | 2478 +- arm-hybrid-22k/lib_src/eas_wtsynth.h | 108 +- arm-hybrid-22k/lib_src/hybrid_22khz_mcu.c | 10274 +++---- arm-wt-22k/host_src/eas.h | 570 +- arm-wt-22k/host_src/eas_build.h | 48 +- arm-wt-22k/host_src/eas_chorus.h | 80 +- arm-wt-22k/host_src/eas_config.c | 1214 +- arm-wt-22k/host_src/eas_config.h | 358 +- arm-wt-22k/host_src/eas_host.h | 150 +- arm-wt-22k/host_src/eas_hostmm.c | 24 +- arm-wt-22k/host_src/eas_main.c | 674 +- arm-wt-22k/host_src/eas_report.c | 504 +- arm-wt-22k/host_src/eas_report.h | 130 +- arm-wt-22k/host_src/eas_reverb.h | 84 +- arm-wt-22k/host_src/eas_types.h | 522 +- arm-wt-22k/host_src/eas_wave.c | 822 +- arm-wt-22k/host_src/eas_wave.h | 124 +- arm-wt-22k/host_src/jet.h | 398 +- arm-wt-22k/jetcreator_lib_src/darwin-x86/EASLib.c | 3618 +-- arm-wt-22k/jetcreator_lib_src/darwin-x86/EASLib.h | 62 +- .../jetcreator_lib_src/darwin-x86/EASLibVst.c | 3008 +- .../jetcreator_lib_src/darwin-x86/eas_host_debug.h | 94 +- .../jetcreator_lib_src/darwin-x86/eastestv37.c | 1998 +- .../jetcreator_lib_src/darwin-x86/wt_44khz.c | 29446 +++++++++---------- arm-wt-22k/lib_src/ARM_synth_constants_gnu.inc | 306 +- arm-wt-22k/lib_src/dls.h | 536 +- arm-wt-22k/lib_src/dls2.h | 244 +- arm-wt-22k/lib_src/eas_audioconst.h | 170 +- arm-wt-22k/lib_src/eas_chorus.c | 1184 +- arm-wt-22k/lib_src/eas_chorusdata.c | 44 +- arm-wt-22k/lib_src/eas_chorusdata.h | 296 +- arm-wt-22k/lib_src/eas_ctype.h | 58 +- arm-wt-22k/lib_src/eas_data.c | 50 +- arm-wt-22k/lib_src/eas_data.h | 242 +- arm-wt-22k/lib_src/eas_dlssynth.c | 754 +- arm-wt-22k/lib_src/eas_dlssynth.h | 58 +- arm-wt-22k/lib_src/eas_effects.h | 98 +- arm-wt-22k/lib_src/eas_flog.c | 168 +- arm-wt-22k/lib_src/eas_ima_tables.c | 84 +- arm-wt-22k/lib_src/eas_imaadpcm.c | 712 +- arm-wt-22k/lib_src/eas_imelody.c | 3465 +-- arm-wt-22k/lib_src/eas_imelodydata.c | 62 +- arm-wt-22k/lib_src/eas_imelodydata.h | 123 +- arm-wt-22k/lib_src/eas_math.c | 312 +- arm-wt-22k/lib_src/eas_math.h | 800 +- arm-wt-22k/lib_src/eas_mdls.c | 3928 +-- arm-wt-22k/lib_src/eas_mdls.h | 566 +- arm-wt-22k/lib_src/eas_midi.c | 1114 +- arm-wt-22k/lib_src/eas_midi.h | 118 +- arm-wt-22k/lib_src/eas_midictrl.h | 104 +- arm-wt-22k/lib_src/eas_mididata.c | 44 +- arm-wt-22k/lib_src/eas_miditypes.h | 252 +- arm-wt-22k/lib_src/eas_mixbuf.c | 48 +- arm-wt-22k/lib_src/eas_mixer.c | 904 +- arm-wt-22k/lib_src/eas_mixer.h | 250 +- arm-wt-22k/lib_src/eas_ota.c | 2130 +- arm-wt-22k/lib_src/eas_otadata.c | 58 +- arm-wt-22k/lib_src/eas_otadata.h | 138 +- arm-wt-22k/lib_src/eas_pan.c | 172 +- arm-wt-22k/lib_src/eas_pan.h | 108 +- arm-wt-22k/lib_src/eas_parser.h | 172 +- arm-wt-22k/lib_src/eas_pcm.c | 2940 +- arm-wt-22k/lib_src/eas_pcm.h | 694 +- arm-wt-22k/lib_src/eas_pcmdata.c | 46 +- arm-wt-22k/lib_src/eas_pcmdata.h | 290 +- arm-wt-22k/lib_src/eas_public.c | 3092 +- arm-wt-22k/lib_src/eas_reverb.c | 2284 +- arm-wt-22k/lib_src/eas_reverbdata.c | 44 +- arm-wt-22k/lib_src/eas_reverbdata.h | 948 +- arm-wt-22k/lib_src/eas_rtttl.c | 2370 +- arm-wt-22k/lib_src/eas_rtttldata.c | 58 +- arm-wt-22k/lib_src/eas_rtttldata.h | 116 +- arm-wt-22k/lib_src/eas_smf.c | 1636 +- arm-wt-22k/lib_src/eas_smf.h | 74 +- arm-wt-22k/lib_src/eas_smfdata.c | 108 +- arm-wt-22k/lib_src/eas_smfdata.h | 108 +- arm-wt-22k/lib_src/eas_sndlib.h | 788 +- arm-wt-22k/lib_src/eas_synth.h | 766 +- arm-wt-22k/lib_src/eas_synth_protos.h | 96 +- arm-wt-22k/lib_src/eas_synthcfg.h | 116 +- arm-wt-22k/lib_src/eas_tcdata.c | 62 +- arm-wt-22k/lib_src/eas_tcdata.h | 106 +- arm-wt-22k/lib_src/eas_tonecontrol.c | 1858 +- arm-wt-22k/lib_src/eas_vm_protos.h | 2148 +- arm-wt-22k/lib_src/eas_voicemgt.c | 7918 ++--- arm-wt-22k/lib_src/eas_wavefile.c | 1710 +- arm-wt-22k/lib_src/eas_wavefile.h | 102 +- arm-wt-22k/lib_src/eas_wavefiledata.c | 42 +- arm-wt-22k/lib_src/eas_wt_IPC_frame.h | 140 +- arm-wt-22k/lib_src/eas_wtengine.c | 898 +- arm-wt-22k/lib_src/eas_wtengine.h | 318 +- arm-wt-22k/lib_src/eas_wtsynth.c | 1428 +- arm-wt-22k/lib_src/eas_wtsynth.h | 108 +- arm-wt-22k/lib_src/eas_xmf.c | 1676 +- arm-wt-22k/lib_src/eas_xmf.h | 96 +- arm-wt-22k/lib_src/eas_xmfdata.c | 64 +- arm-wt-22k/lib_src/eas_xmfdata.h | 86 +- arm-wt-22k/lib_src/jet.c | 2258 +- arm-wt-22k/lib_src/jet_data.h | 342 +- arm-wt-22k/lib_src/wt_22khz.c | 29280 +++++++++--------- arm-wt-22k/misc/eas_host.c | 1550 +- 252 files changed, 132829 insertions(+), 132823 deletions(-) mode change 100755 => 100644 arm-wt-22k/jetcreator_lib_src/darwin-x86/EASLib.c mode change 100755 => 100644 arm-wt-22k/jetcreator_lib_src/darwin-x86/EASLib.h mode change 100755 => 100644 arm-wt-22k/jetcreator_lib_src/darwin-x86/EASLibVst.c mode change 100755 => 100644 arm-wt-22k/jetcreator_lib_src/darwin-x86/eas_host_debug.h mode change 100755 => 100644 arm-wt-22k/jetcreator_lib_src/darwin-x86/eastestv37.c diff --git a/arm-fm-22k/host_src/eas.h b/arm-fm-22k/host_src/eas.h index 0bb04fe..c64af49 100644 --- a/arm-fm-22k/host_src/eas.h +++ b/arm-fm-22k/host_src/eas.h @@ -1,17 +1,17 @@ -/*---------------------------------------------------------------------------- - * - * 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 +/*---------------------------------------------------------------------------- + * + * 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. @@ -24,1039 +24,1039 @@ * 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 */ + * + *---------------------------------------------------------------------------- + * 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 index 64ccf5a..5b058e7 100644 --- a/arm-fm-22k/host_src/eas_build.h +++ b/arm-fm-22k/host_src/eas_build.h @@ -1,15 +1,15 @@ -/*---------------------------------------------------------------------------- - * - * 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 +/*---------------------------------------------------------------------------- + * + * 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. @@ -22,15 +22,15 @@ * 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_ */ + * + * 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 index 0e9057f..998a828 100644 --- a/arm-fm-22k/host_src/eas_chorus.h +++ b/arm-fm-22k/host_src/eas_chorus.h @@ -1,13 +1,13 @@ -/*---------------------------------------------------------------------------- - * - * File: - * eas_chorus.h - * - * Contents and purpose: - * Contains parameter enumerations for the Chorus effect - * - * - * Copyright Sonic Network Inc. 2006 +/*---------------------------------------------------------------------------- + * + * 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. @@ -20,34 +20,34 @@ * 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; - - + * + *---------------------------------------------------------------------------- + * 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 index c45fbb7..0b92357 100644 --- a/arm-fm-22k/host_src/eas_config.c +++ b/arm-fm-22k/host_src/eas_config.c @@ -1,22 +1,22 @@ -/*---------------------------------------------------------------------------- - * - * 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 +/*---------------------------------------------------------------------------- + * + * 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. @@ -29,591 +29,591 @@ * 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]; -} - - + * + *---------------------------------------------------------------------------- + * 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 index d16be4a..49c2ef2 100644 --- a/arm-fm-22k/host_src/eas_config.h +++ b/arm-fm-22k/host_src/eas_config.h @@ -1,22 +1,22 @@ -/*---------------------------------------------------------------------------- - * - * 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. +/*---------------------------------------------------------------------------- + * + * 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. @@ -29,163 +29,163 @@ * 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 */ + * + *---------------------------------------------------------------------------- + * 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 index 436875b..de60259 100644 --- a/arm-fm-22k/host_src/eas_debugmsgs.h +++ b/arm-fm-22k/host_src/eas_debugmsgs.h @@ -1,43 +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" }, +/* 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 index 0db0e30..b356982 100644 --- a/arm-fm-22k/host_src/eas_host.h +++ b/arm-fm-22k/host_src/eas_host.h @@ -1,16 +1,16 @@ -/*---------------------------------------------------------------------------- - * - * 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. +/*---------------------------------------------------------------------------- + * + * 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. @@ -23,61 +23,61 @@ * 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 */ + * + *---------------------------------------------------------------------------- + * 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 index 7e58838..df24cf2 100644 --- a/arm-fm-22k/host_src/eas_hostmm.c +++ b/arm-fm-22k/host_src/eas_hostmm.c @@ -1,33 +1,33 @@ -/*---------------------------------------------------------------------------- - * - * 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. +/*---------------------------------------------------------------------------- + * + * 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. @@ -40,621 +40,621 @@ * 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 -#include -#include -#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; -} - + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 795 $ + * $Date: 2007-08-01 00:14:45 -0700 (Wed, 01 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifdef _lint +#include "lint_stdlib.h" +#else +#include +#include +#include +#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 index 809a132..6ebb13e 100644 --- a/arm-fm-22k/host_src/eas_main.c +++ b/arm-fm-22k/host_src/eas_main.c @@ -1,13 +1,13 @@ -/*---------------------------------------------------------------------------- - * - * 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 +/*---------------------------------------------------------------------------- + * + * 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. @@ -20,442 +20,442 @@ * 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 -#include -#include -#include -#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 */ - + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 775 $ + * $Date: 2007-07-20 10:11:11 -0700 (Fri, 20 Jul 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifdef _lint +#include "lint_stdlib.h" +#else +#include +#include +#include +#include +#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 index d4dd22c..04a828c 100644 --- a/arm-fm-22k/host_src/eas_report.c +++ b/arm-fm-22k/host_src/eas_report.c @@ -1,13 +1,13 @@ -/*---------------------------------------------------------------------------- - * - * 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. +/*---------------------------------------------------------------------------- + * + * 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. @@ -20,245 +20,245 @@ * 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 -#include -#include -#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} */ - 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} */ - 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} */ - 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 */ - + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 659 $ + * $Date: 2007-04-24 13:36:35 -0700 (Tue, 24 Apr 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifdef _lint +#include "lint_stdlib.h" +#else +#include +#include +#include +#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} */ + 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} */ + 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} */ + 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 index 9d7c8e8..b603b12 100644 --- a/arm-fm-22k/host_src/eas_report.h +++ b/arm-fm-22k/host_src/eas_report.h @@ -1,15 +1,15 @@ -/*---------------------------------------------------------------------------- - * - * 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. +/*---------------------------------------------------------------------------- + * + * 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. @@ -22,56 +22,56 @@ * 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 + * + *---------------------------------------------------------------------------- + * 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 index a2535fb..559abed 100644 --- a/arm-fm-22k/host_src/eas_reverb.h +++ b/arm-fm-22k/host_src/eas_reverb.h @@ -1,13 +1,13 @@ -/*---------------------------------------------------------------------------- - * - * File: - * eas_reverb.h - * - * Contents and purpose: - * Contains parameter enumerations for the Reverb effect - * - * - * Copyright Sonic Network Inc. 2006 +/*---------------------------------------------------------------------------- + * + * 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. @@ -20,35 +20,35 @@ * 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 */ + * + *---------------------------------------------------------------------------- + * 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 index f0293ef..45fa4b2 100644 --- a/arm-fm-22k/host_src/eas_types.h +++ b/arm-fm-22k/host_src/eas_types.h @@ -1,17 +1,17 @@ -/*---------------------------------------------------------------------------- - * - * 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 +/*---------------------------------------------------------------------------- + * + * 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. @@ -24,245 +24,245 @@ * 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 */ + * + *---------------------------------------------------------------------------- + * 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 index 02fed6e..4f6ffbd 100644 --- a/arm-fm-22k/host_src/eas_wave.c +++ b/arm-fm-22k/host_src/eas_wave.c @@ -1,13 +1,13 @@ -/*---------------------------------------------------------------------------- - * - * File: - * eas_wave.c - * - * Contents and purpose: - * This module contains .WAV file functions for the EAS synthesizer - * test harness. - * - * Copyright Sonic Network Inc. 2005 +/*---------------------------------------------------------------------------- + * + * 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. @@ -20,404 +20,404 @@ * 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 -#include -#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 - - - + *---------------------------------------------------------------------------- + * 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 +#include +#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 index ca388f5..968782f 100644 --- a/arm-fm-22k/host_src/eas_wave.h +++ b/arm-fm-22k/host_src/eas_wave.h @@ -1,14 +1,14 @@ -/*---------------------------------------------------------------------------- - * - * File: - * eas_wave.h - * - * Contents and purpose: - * Writes output to a .WAV file - * - * DO NOT MODIFY THIS FILE! - * - * Copyright Sonic Network Inc. 2005 +/*---------------------------------------------------------------------------- + * + * 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. @@ -21,54 +21,54 @@ * 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 */ - - - + *---------------------------------------------------------------------------- + * 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_src/eas_audioconst.h b/arm-fm-22k/lib_src/eas_audioconst.h index 1cfa404..066148e 100644 --- a/arm-fm-22k/lib_src/eas_audioconst.h +++ b/arm-fm-22k/lib_src/eas_audioconst.h @@ -1,13 +1,13 @@ -/*---------------------------------------------------------------------------- - * - * File: - * eas_audioconst.h - * - * Contents and purpose: - * Defines audio constants related to the sample rate, bit size, etc. - * - * - * Copyright Sonic Network Inc. 2005 +/*---------------------------------------------------------------------------- + * + * 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. @@ -20,78 +20,78 @@ * 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 */ - + * + *---------------------------------------------------------------------------- + * 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 index bc42237..4a2c8d0 100644 --- a/arm-fm-22k/lib_src/eas_chorus.c +++ b/arm-fm-22k/lib_src/eas_chorus.c @@ -1,13 +1,13 @@ -/*---------------------------------------------------------------------------- - * - * File: - * eas_chorus.c - * - * Contents and purpose: - * Contains the implementation of the Chorus effect. - * - * - * Copyright Sonic Network Inc. 2006 +/*---------------------------------------------------------------------------- + * + * 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. @@ -20,585 +20,585 @@ * 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(valueEAS_CHORUS_RATE_MAX) - return EAS_ERROR_INVALID_PARAMETER; - p->m_nRate = (EAS_I16) value; - break; - case EAS_PARAM_CHORUS_DEPTH: - if(valueEAS_CHORUS_DEPTH_MAX) - return EAS_ERROR_INVALID_PARAMETER; - p->m_nDepth = (EAS_I16) value; - break; - case EAS_PARAM_CHORUS_LEVEL: - if(valueEAS_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 */ + * + *---------------------------------------------------------------------------- + * 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(valueEAS_CHORUS_RATE_MAX) + return EAS_ERROR_INVALID_PARAMETER; + p->m_nRate = (EAS_I16) value; + break; + case EAS_PARAM_CHORUS_DEPTH: + if(valueEAS_CHORUS_DEPTH_MAX) + return EAS_ERROR_INVALID_PARAMETER; + p->m_nDepth = (EAS_I16) value; + break; + case EAS_PARAM_CHORUS_LEVEL: + if(valueEAS_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 index caee1ed..ec71ff8 100644 --- a/arm-fm-22k/lib_src/eas_chorusdata.c +++ b/arm-fm-22k/lib_src/eas_chorusdata.c @@ -1,13 +1,13 @@ -/*---------------------------------------------------------------------------- - * - * File: - * eas_chorusdata.c - * - * Contents and purpose: - * Contains the static data allocation for the Chorus effect - * - * - * Copyright Sonic Network Inc. 2006 +/*---------------------------------------------------------------------------- + * + * 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. @@ -20,15 +20,15 @@ * 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; - + * + *---------------------------------------------------------------------------- + * 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 index 4420ddd..ec8daa4 100644 --- a/arm-fm-22k/lib_src/eas_chorusdata.h +++ b/arm-fm-22k/lib_src/eas_chorusdata.h @@ -1,13 +1,13 @@ -/*---------------------------------------------------------------------------- - * - * File: - * eas_chorusdata.h - * - * Contents and purpose: - * Contains the prototypes for the Chorus effect. - * - * - * Copyright Sonic Network Inc. 2006 +/*---------------------------------------------------------------------------- + * + * 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. @@ -20,141 +20,141 @@ * 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 */ - - + * + *---------------------------------------------------------------------------- + * 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 index 8503870..14fa96f 100644 --- a/arm-fm-22k/lib_src/eas_ctype.h +++ b/arm-fm-22k/lib_src/eas_ctype.h @@ -1,14 +1,14 @@ -/*---------------------------------------------------------------------------- - * - * 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. +/*---------------------------------------------------------------------------- + * + * 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. @@ -21,21 +21,21 @@ * 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 - + * + *---------------------------------------------------------------------------- + * 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 index bb60ef2..31a4e6a 100644 --- a/arm-fm-22k/lib_src/eas_data.c +++ b/arm-fm-22k/lib_src/eas_data.c @@ -1,12 +1,12 @@ -/*---------------------------------------------------------------------------- - * - * File: - * eas_data.c - * - * Contents and purpose: - * Contains a data allocation for synthesizer - * - * Copyright Sonic Network Inc. 2004 +/*---------------------------------------------------------------------------- + * + * 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. @@ -19,19 +19,19 @@ * 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; - + * + *---------------------------------------------------------------------------- + * 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 index 0a47d04..e2fcb1a 100644 --- a/arm-fm-22k/lib_src/eas_data.h +++ b/arm-fm-22k/lib_src/eas_data.h @@ -1,13 +1,13 @@ -/*---------------------------------------------------------------------------- - * - * 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. +/*---------------------------------------------------------------------------- + * + * 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. @@ -20,112 +20,112 @@ * 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 - + * + *---------------------------------------------------------------------------- + * 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 index 01e64c0..86dedac 100644 --- a/arm-fm-22k/lib_src/eas_effects.h +++ b/arm-fm-22k/lib_src/eas_effects.h @@ -1,12 +1,12 @@ -/*---------------------------------------------------------------------------- - * - * File: - * eas_effects.h - * - * Contents and purpose: - * Defines a generic effects interface. - * - * Copyright Sonic Network Inc. 2005 +/*---------------------------------------------------------------------------- + * + * 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. @@ -19,43 +19,43 @@ * 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 */ - + * + *---------------------------------------------------------------------------- + * 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 index 9c3da66..ea7f69c 100644 --- a/arm-fm-22k/lib_src/eas_fmengine.c +++ b/arm-fm-22k/lib_src/eas_fmengine.c @@ -1,12 +1,12 @@ -/*---------------------------------------------------------------------------- - * - * File: - * eas_fmengine.c - * - * Contents and purpose: - * Implements the low-level FM synthesizer functions. - * - * Copyright Sonic Network Inc. 2004, 2005 +/*---------------------------------------------------------------------------- + * + * 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. @@ -19,767 +19,767 @@ * 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} */ - 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} */ - 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} */ - 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} */ - nGain = (EAS_I32) p->voiceGain << 16; - - /* calculate gain increment */ - /*lint -e{703} */ - 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} */ - nTemp = ((EAS_I32) nTemp * (nGain >> 16)) >> FM_GAIN_SHIFT; - - /*lint -e{704} */ - { - 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} */ - 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; -} - + * + *---------------------------------------------------------------------------- + * 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} */ + 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} */ + 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} */ + 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} */ + nGain = (EAS_I32) p->voiceGain << 16; + + /* calculate gain increment */ + /*lint -e{703} */ + 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} */ + nTemp = ((EAS_I32) nTemp * (nGain >> 16)) >> FM_GAIN_SHIFT; + + /*lint -e{704} */ + { + 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} */ + 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 index 4ddc12b..dd248f8 100644 --- a/arm-fm-22k/lib_src/eas_fmengine.h +++ b/arm-fm-22k/lib_src/eas_fmengine.h @@ -1,12 +1,12 @@ -/*---------------------------------------------------------------------------- - * - * File: - * eas_fmengine.h - * - * Contents and purpose: - * Declarations, interfaces, and prototypes for FM synthesize low-level. - * - * Copyright Sonic Network Inc. 2004 +/*---------------------------------------------------------------------------- + * + * 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. @@ -19,103 +19,103 @@ * 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 */ - + * + *---------------------------------------------------------------------------- + * 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 index bdd063c..dcde967 100644 --- a/arm-fm-22k/lib_src/eas_fmsndlib.c +++ b/arm-fm-22k/lib_src/eas_fmsndlib.c @@ -1,8 +1,8 @@ -/******************************************************************** - * - * fmsndlib.c - * - * (c) Copyright 2005 Sonic Network, Inc. All Rights Reserved +/******************************************************************** + * + * 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. @@ -15,1660 +15,1660 @@ * 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 */ + * + * 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 index 83f0087..629506a 100644 --- a/arm-fm-22k/lib_src/eas_fmsynth.c +++ b/arm-fm-22k/lib_src/eas_fmsynth.c @@ -1,12 +1,12 @@ -/*---------------------------------------------------------------------------- - * - * File: - * fmsynth.c - * - * Contents and purpose: - * Implements the high-level FM synthesizer functions. - * - * Copyright Sonic Network Inc. 2004 +/*---------------------------------------------------------------------------- + * + * 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. @@ -19,892 +19,892 @@ * 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} */ - pFMVoice->oper[operIndex].outputGain = EAS_LogToLinear16(((EAS_I16) (pRegion->oper[operIndex].gain & 0xfc) - 0xfc) << 7); - - /* check for linear velocity flag */ - /*lint -e{703} */ - 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} */ - 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} */ - 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} */ - 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} */ - 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; -} - + * + *---------------------------------------------------------------------------- + * 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} */ + pFMVoice->oper[operIndex].outputGain = EAS_LogToLinear16(((EAS_I16) (pRegion->oper[operIndex].gain & 0xfc) - 0xfc) << 7); + + /* check for linear velocity flag */ + /*lint -e{703} */ + 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} */ + 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} */ + 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} */ + 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} */ + 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 index 76f8adc..8ceda46 100644 --- a/arm-fm-22k/lib_src/eas_fmsynth.h +++ b/arm-fm-22k/lib_src/eas_fmsynth.h @@ -1,12 +1,12 @@ -/*---------------------------------------------------------------------------- - * - * File: - * eas_fmsynth.h - * - * Contents and purpose: - * Implements the FM synthesizer functions. - * - * Copyright Sonic Network Inc. 2004 +/*---------------------------------------------------------------------------- + * + * 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. @@ -19,63 +19,63 @@ * 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 + * + *---------------------------------------------------------------------------- + * 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 index 25c6961..a8ff0a2 100644 --- a/arm-fm-22k/lib_src/eas_fmtables.c +++ b/arm-fm-22k/lib_src/eas_fmtables.c @@ -1,13 +1,13 @@ -/*---------------------------------------------------------------------------- - * - * File: - * eas_fmtables.c - * - * Contents and purpose: - * Contains lookup tables for the FM synthesizer - * - * - * Copyright Sonic Network Inc. 2005 +/*---------------------------------------------------------------------------- + * + * 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. @@ -20,349 +20,349 @@ * 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 - + * + *---------------------------------------------------------------------------- + * 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 index 56bd1eb..b03b4d4 100644 --- a/arm-fm-22k/lib_src/eas_ima_tables.c +++ b/arm-fm-22k/lib_src/eas_ima_tables.c @@ -1,12 +1,12 @@ -/*---------------------------------------------------------------------------- - * - * File: - * eas_ima_tables.c - * - * Contents and purpose: - * Contains the constant tables for IMA encode/decode - * - * Copyright (c) 2005 Sonic Network Inc. +/*---------------------------------------------------------------------------- + * + * 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. @@ -19,36 +19,36 @@ * 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 -}; - + * + *---------------------------------------------------------------------------- + * 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 index 68bf257..41280b5 100644 --- a/arm-fm-22k/lib_src/eas_imaadpcm.c +++ b/arm-fm-22k/lib_src/eas_imaadpcm.c @@ -1,12 +1,12 @@ -/*---------------------------------------------------------------------------- - * - * File: - * eas_imaadpcm.c - * - * Contents and purpose: - * Implements the IMA ADPCM decoder - * - * Copyright Sonic Network Inc. 2005 +/*---------------------------------------------------------------------------- + * + * 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. @@ -19,350 +19,350 @@ * 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; -} - + * + *---------------------------------------------------------------------------- + * 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 index 9f4d541..698c7df 100644 --- a/arm-fm-22k/lib_src/eas_imelody.c +++ b/arm-fm-22k/lib_src/eas_imelody.c @@ -1,12 +1,12 @@ -/*---------------------------------------------------------------------------- - * - * File: - * eas_imelody.c - * - * Contents and purpose: - * iMelody parser - * - * Copyright Sonic Network Inc. 2005 +/*---------------------------------------------------------------------------- + * + * 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. @@ -19,1720 +19,1720 @@ * 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 -#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; -} - + * + *---------------------------------------------------------------------------- + * 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 +#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 index e72dc0b..9437e08 100644 --- a/arm-fm-22k/lib_src/eas_imelodydata.c +++ b/arm-fm-22k/lib_src/eas_imelodydata.c @@ -1,14 +1,14 @@ -/*---------------------------------------------------------------------------- - * - * File: - * eas_imelodydata.c - * - * Contents and purpose: - * SMF File Parser - * - * This file contains data definitions for the SMF parser. - * - * Copyright Sonic Network Inc. 2005 +/*---------------------------------------------------------------------------- + * + * 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. @@ -21,23 +21,23 @@ * 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; - + * + *---------------------------------------------------------------------------- + * 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 index 303b8f6..57c1ed0 100644 --- a/arm-fm-22k/lib_src/eas_imelodydata.h +++ b/arm-fm-22k/lib_src/eas_imelodydata.h @@ -1,14 +1,14 @@ -/*---------------------------------------------------------------------------- - * - * File: - * eas_imelodydata.h - * - * Contents and purpose: - * SMF File Parser - * - * This file contains data declarations for the iMelody parser. - * - * Copyright Sonic Network Inc. 2005 +/*---------------------------------------------------------------------------- + * + * 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. @@ -21,53 +21,53 @@ * 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 - - + * + *---------------------------------------------------------------------------- + * 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 index 12d788e..dc85051 100644 --- a/arm-fm-22k/lib_src/eas_math.c +++ b/arm-fm-22k/lib_src/eas_math.c @@ -1,13 +1,13 @@ -/*---------------------------------------------------------------------------- - * - * File: - * eas_math.c - * - * Contents and purpose: - * Contains common math routines for the various audio engines. - * - * - * Copyright Sonic Network Inc. 2005 +/*---------------------------------------------------------------------------- + * + * 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. @@ -20,149 +20,149 @@ * 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} */ - 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); -} - + * + *---------------------------------------------------------------------------- + * 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} */ + 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 index 719270b..f240b51 100644 --- a/arm-fm-22k/lib_src/eas_math.h +++ b/arm-fm-22k/lib_src/eas_math.h @@ -1,13 +1,13 @@ -/*---------------------------------------------------------------------------- - * - * File: - * eas_math.h - * - * Contents and purpose: - * Contains common math routines for the various audio engines. - * - * - * Copyright Sonic Network Inc. 2005 +/*---------------------------------------------------------------------------- + * + * 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. @@ -20,393 +20,393 @@ * 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) */ \ - (((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) */ \ - (((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) */ \ - (((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) */ \ - (((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 */ \ - (EAS_I32)( \ - ( \ - ((EAS_I32)(audio)) * ((EAS_I32)(coef)) \ - ) \ - >> NUM_PHASE_FRAC_BITS \ - ) \ - /* lint +704 */ - -/* 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) */ \ - (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) */ \ - (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) */ \ - (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) */ \ - (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 */ \ - (EAS_I32)( \ - ( \ - ((EAS_I32)(dents)) * ((EAS_I32)(coef)) \ - ) \ - >> NUM_DENTS_FRAC_BITS \ - ) \ - /* lint +e704 */ - -/* 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) */ \ - (EAS_I32) ( \ - ( \ - ((EAS_I32)(audio)) * ((EAS_I32)(drive)) \ - ) \ - >> NUM_DRIVE_COEF_FRAC_BITS \ - ) - -#define MULT_AUDIO_AUDIO(audio1,audio2) /*lint -e(702) */ \ - (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 - + * + *---------------------------------------------------------------------------- + * 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) */ \ + (((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) */ \ + (((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) */ \ + (((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) */ \ + (((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 */ \ + (EAS_I32)( \ + ( \ + ((EAS_I32)(audio)) * ((EAS_I32)(coef)) \ + ) \ + >> NUM_PHASE_FRAC_BITS \ + ) \ + /* lint +704 */ + +/* 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) */ \ + (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) */ \ + (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) */ \ + (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) */ \ + (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 */ \ + (EAS_I32)( \ + ( \ + ((EAS_I32)(dents)) * ((EAS_I32)(coef)) \ + ) \ + >> NUM_DENTS_FRAC_BITS \ + ) \ + /* lint +e704 */ + +/* 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) */ \ + (EAS_I32) ( \ + ( \ + ((EAS_I32)(audio)) * ((EAS_I32)(drive)) \ + ) \ + >> NUM_DRIVE_COEF_FRAC_BITS \ + ) + +#define MULT_AUDIO_AUDIO(audio1,audio2) /*lint -e(702) */ \ + (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 index 08aed72..2c0c793 100644 --- a/arm-fm-22k/lib_src/eas_midi.c +++ b/arm-fm-22k/lib_src/eas_midi.c @@ -1,13 +1,13 @@ -/*---------------------------------------------------------------------------- - * - * 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 +/*---------------------------------------------------------------------------- + * + * 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. @@ -20,550 +20,550 @@ * 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 */ - + * + *---------------------------------------------------------------------------- + * 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 index 37a03ee..10649a0 100644 --- a/arm-fm-22k/lib_src/eas_midi.h +++ b/arm-fm-22k/lib_src/eas_midi.h @@ -1,13 +1,13 @@ -/*---------------------------------------------------------------------------- - * - * File: - * eas_midi.h - * - * Contents and purpose: - * Prototypes for MIDI stream parsing functions - * - * - * Copyright Sonic Network Inc. 2005 +/*---------------------------------------------------------------------------- + * + * 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. @@ -20,52 +20,52 @@ * 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 */ - + * + *---------------------------------------------------------------------------- + * 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 index 0c4217d..46fdc4f 100644 --- a/arm-fm-22k/lib_src/eas_midictrl.h +++ b/arm-fm-22k/lib_src/eas_midictrl.h @@ -1,15 +1,15 @@ -/*---------------------------------------------------------------------------- - * - * 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 +/*---------------------------------------------------------------------------- + * + * 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. @@ -22,43 +22,43 @@ * 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 */ + * + *---------------------------------------------------------------------------- + * 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 index 2ee907e..4463b7e 100644 --- a/arm-fm-22k/lib_src/eas_mididata.c +++ b/arm-fm-22k/lib_src/eas_mididata.c @@ -1,13 +1,13 @@ -/*---------------------------------------------------------------------------- - * - * File: - * eas_mididata.c - * - * Contents and purpose: - * Data module for MIDI stream interface - * - * - * Copyright Sonic Network Inc. 2005 +/*---------------------------------------------------------------------------- + * + * 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. @@ -20,15 +20,15 @@ * 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; - + * + *---------------------------------------------------------------------------- + * 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 index 0b7f96e..015f08b 100644 --- a/arm-fm-22k/lib_src/eas_miditypes.h +++ b/arm-fm-22k/lib_src/eas_miditypes.h @@ -1,13 +1,13 @@ -/*---------------------------------------------------------------------------- - * - * File: - * eas_miditypes.h - * - * Contents and purpose: - * Contains declarations for the MIDI stream parser. - * - * - * Copyright Sonic Network Inc. 2005 +/*---------------------------------------------------------------------------- + * + * 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. @@ -20,119 +20,119 @@ * 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 */ - + * + *---------------------------------------------------------------------------- + * 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 index 73e969a..db5bd02 100644 --- a/arm-fm-22k/lib_src/eas_mixbuf.c +++ b/arm-fm-22k/lib_src/eas_mixbuf.c @@ -1,12 +1,12 @@ -/*---------------------------------------------------------------------------- - * - * File: - * eas_mixbuf.c - * - * Contents and purpose: - * Contains a data allocation for synthesizer - * - * Copyright Sonic Network Inc. 2004 +/*---------------------------------------------------------------------------- + * + * 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. @@ -19,18 +19,18 @@ * 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]; - + * + *---------------------------------------------------------------------------- + * 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 index c4a2f9f..0a839a8 100644 --- a/arm-fm-22k/lib_src/eas_mixer.c +++ b/arm-fm-22k/lib_src/eas_mixer.c @@ -1,13 +1,13 @@ -/*---------------------------------------------------------------------------- - * - * 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 +/*---------------------------------------------------------------------------- + * + * 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. @@ -20,445 +20,445 @@ * 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} */ - s = s >> 7; - - /* apply master gain */ - s *= (long) nGain; - - /* shift to lower 16-bits */ - /*lint -e{704} */ - 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 - + * + *---------------------------------------------------------------------------- + * 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} */ + s = s >> 7; + + /* apply master gain */ + s *= (long) nGain; + + /* shift to lower 16-bits */ + /*lint -e{704} */ + 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 index 2ba2d3d..b2eb33b 100644 --- a/arm-fm-22k/lib_src/eas_mixer.h +++ b/arm-fm-22k/lib_src/eas_mixer.h @@ -1,13 +1,13 @@ -/*---------------------------------------------------------------------------- - * - * 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 +/*---------------------------------------------------------------------------- + * + * 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. @@ -20,118 +20,118 @@ * 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 */ - + * + *---------------------------------------------------------------------------- + * 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 index fb81d62..5bc9062 100644 --- a/arm-fm-22k/lib_src/eas_ota.c +++ b/arm-fm-22k/lib_src/eas_ota.c @@ -1,12 +1,12 @@ -/*---------------------------------------------------------------------------- - * - * File: - * eas_ota.c - * - * Contents and purpose: - * OTA parser - * - * Copyright Sonic Network Inc. 2005 +/*---------------------------------------------------------------------------- + * + * 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. @@ -19,1059 +19,1059 @@ * 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); -} - + * + *---------------------------------------------------------------------------- + * 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 index 237f832..7463a0c 100644 --- a/arm-fm-22k/lib_src/eas_otadata.c +++ b/arm-fm-22k/lib_src/eas_otadata.c @@ -1,12 +1,12 @@ -/*---------------------------------------------------------------------------- - * - * File: - * eas_otadata..c - * - * Contents and purpose: - * OTA Stream Parser data module for static memory model - * - * Copyright Sonic Network Inc. 2005 +/*---------------------------------------------------------------------------- + * + * 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. @@ -19,23 +19,23 @@ * 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; - + * + *---------------------------------------------------------------------------- + * 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 index 63e963f..c06e3d3 100644 --- a/arm-fm-22k/lib_src/eas_otadata.h +++ b/arm-fm-22k/lib_src/eas_otadata.h @@ -1,14 +1,14 @@ -/*---------------------------------------------------------------------------- - * - * File: - * eas_otadata.h - * - * Contents and purpose: - * OTA File Parser - * - * This file contains data declarations for the OTA parser. - * - * Copyright Sonic Network Inc. 2005 +/*---------------------------------------------------------------------------- + * + * 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. @@ -21,61 +21,61 @@ * 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 - - + * + *---------------------------------------------------------------------------- + * 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 index 373d90e..ae4c69d 100644 --- a/arm-fm-22k/lib_src/eas_pan.c +++ b/arm-fm-22k/lib_src/eas_pan.c @@ -1,16 +1,16 @@ -/*---------------------------------------------------------------------------- - * - * 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 +/*---------------------------------------------------------------------------- + * + * 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. @@ -23,76 +23,76 @@ * 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} */ - 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; -} - + * + *---------------------------------------------------------------------------- + * 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} */ + 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 index cefa650..cb0a90d 100644 --- a/arm-fm-22k/lib_src/eas_pan.h +++ b/arm-fm-22k/lib_src/eas_pan.h @@ -1,16 +1,16 @@ -/*---------------------------------------------------------------------------- - * - * 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 +/*---------------------------------------------------------------------------- + * + * 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. @@ -23,44 +23,44 @@ * 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 - + * + *---------------------------------------------------------------------------- + * 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 index 5512c82..96ec35b 100644 --- a/arm-fm-22k/lib_src/eas_parser.h +++ b/arm-fm-22k/lib_src/eas_parser.h @@ -1,15 +1,15 @@ -/*---------------------------------------------------------------------------- - * - * 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 +/*---------------------------------------------------------------------------- + * + * 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. @@ -22,77 +22,77 @@ * 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 */ + * + *---------------------------------------------------------------------------- + * 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 index 64b8f71..ff3f6f9 100644 --- a/arm-fm-22k/lib_src/eas_pcm.c +++ b/arm-fm-22k/lib_src/eas_pcm.c @@ -1,12 +1,12 @@ -/*---------------------------------------------------------------------------- - * - * 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 +/*---------------------------------------------------------------------------- + * + * 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. @@ -19,1464 +19,1464 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * - *---------------------------------------------------------------------------- - * Revision Control: - * $Revision: 849 $ - * $Date: 2007-08-28 08:59:11 -0700 (Tue, 28 Aug 2007) $ - *---------------------------------------------------------------------------- -*/ - -#include "eas_data.h" -#include "eas_report.h" -#include "eas_host.h" -#include "eas_config.h" -#include "eas_parser.h" -#include "eas_pcm.h" -#include "eas_math.h" -#include "eas_mixer.h" - -#define PCM_MIXER_GUARD_BITS (NUM_MIXER_GUARD_BITS + 1) - -/*---------------------------------------------------------------------------- - * Decoder interfaces - *---------------------------------------------------------------------------- -*/ - -static EAS_RESULT LinearPCMDecode (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState); -static EAS_RESULT LinearPCMLocate (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState, EAS_I32 time); - -static const S_DECODER_INTERFACE PCMDecoder = -{ - NULL, - LinearPCMDecode, - LinearPCMLocate, -}; - -/* SMAF ADPCM decoder */ -#ifdef _SMAF_PARSER -extern S_DECODER_INTERFACE SmafDecoder; -#define SMAF_DECODER &SmafDecoder -extern S_DECODER_INTERFACE Smaf7BitDecoder; -#define SMAF_7BIT_DECODER &Smaf7BitDecoder -#else -#define SMAF_DECODER NULL -#define SMAF_7BIT_DECODER NULL -#endif - -/* IMA ADPCM decoder */ -#ifdef _IMA_DECODER -extern S_DECODER_INTERFACE IMADecoder; -#define IMA_DECODER &IMADecoder -#else -#define IMA_DECODER NULL -#endif - -static const S_DECODER_INTERFACE * const decoders[] = -{ - &PCMDecoder, - SMAF_DECODER, - IMA_DECODER, - SMAF_7BIT_DECODER -}; - -/*---------------------------------------------------------------------------- - * Sample rate conversion - *---------------------------------------------------------------------------- -*/ - -#define SRC_RATE_MULTIPLER (0x40000000 / _OUTPUT_SAMPLE_RATE) - -#ifdef _LOOKUP_SAMPLE_RATE -static const EAS_U32 srcConvRate[][2] = -{ - 4000L, (4000L << 15) / _OUTPUT_SAMPLE_RATE, - 8000L, (8000L << 15) / _OUTPUT_SAMPLE_RATE, - 11025L, (11025L << 15) / _OUTPUT_SAMPLE_RATE, - 12000L, (12000L << 15) / _OUTPUT_SAMPLE_RATE, - 16000L, (16000L << 15) / _OUTPUT_SAMPLE_RATE, - 22050L, (22050L << 15) / _OUTPUT_SAMPLE_RATE, - 24000L, (24000L << 15) / _OUTPUT_SAMPLE_RATE, - 32000L, (32000L << 15) / _OUTPUT_SAMPLE_RATE -}; -static EAS_U32 CalcBaseFreq (EAS_U32 sampleRate); -#define SRC_CONV_RATE_ENTRIES (sizeof(srcConvRate)/sizeof(EAS_U32)/2) -#endif - - -/* interface prototypes */ -static EAS_RESULT RenderPCMStream (S_EAS_DATA *pEASData, S_PCM_STATE *pState, EAS_I32 numSamples); - - -/* local prototypes */ -static S_PCM_STATE *FindSlot (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_PCM_CALLBACK pCallbackFunc, EAS_VOID_PTR cbInstData); -static EAS_RESULT InitPCMStream (S_EAS_DATA *pEASData, S_PCM_STATE *pState); - -/*---------------------------------------------------------------------------- - * EAS_PEInit() - *---------------------------------------------------------------------------- - * Purpose: - * Initializes the PCM engine - * - * Inputs: - * - * - * Outputs: - * - * - * Side Effects: - * - *---------------------------------------------------------------------------- -*/ -EAS_RESULT EAS_PEInit (S_EAS_DATA *pEASData) -{ - S_PCM_STATE *pState; - EAS_INT i; - - /* check for static memory allocation */ - if (pEASData->staticMemoryModel) - pEASData->pPCMStreams = EAS_CMEnumData(EAS_CM_PCM_DATA); - /* allocate dynamic memory */ - else - pEASData->pPCMStreams = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_PCM_STATE) * MAX_PCM_STREAMS); - - if (!pEASData->pPCMStreams) - { - { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate memory for PCM streams\n"); */ } - return EAS_ERROR_MALLOC_FAILED; - } - - //zero the memory to insure complete initialization - EAS_HWMemSet((void *)(pEASData->pPCMStreams),0, sizeof(S_PCM_STATE) * MAX_PCM_STREAMS); - - /* initialize the state data */ - for (i = 0, pState = pEASData->pPCMStreams; i < MAX_PCM_STREAMS; i++, pState++) - pState->fileHandle = NULL; - - return EAS_SUCCESS; -} - -/*---------------------------------------------------------------------------- - * EAS_PEShutdown() - *---------------------------------------------------------------------------- - * Purpose: - * Shuts down the PCM engine - * - * Inputs: - * - * - * Outputs: - * - * - * Side Effects: - * - *---------------------------------------------------------------------------- -*/ -EAS_RESULT EAS_PEShutdown (S_EAS_DATA *pEASData) -{ - - /* free any dynamic memory */ - if (!pEASData->staticMemoryModel) - { - if (pEASData->pPCMStreams) - { - EAS_HWFree(pEASData->hwInstData, pEASData->pPCMStreams); - pEASData->pPCMStreams = NULL; - } - } - return EAS_SUCCESS; -} - -/*---------------------------------------------------------------------------- - * EAS_PERender() - *---------------------------------------------------------------------------- - * Purpose: - * Render a buffer of PCM audio - * - * Inputs: - * - * - * Outputs: - * - * - * Side Effects: - * - *---------------------------------------------------------------------------- -*/ -EAS_RESULT EAS_PERender (S_EAS_DATA* pEASData, EAS_I32 numSamples) -{ - S_PCM_STATE *pState; - EAS_RESULT result; - EAS_INT i; - - /* render all the active streams */ - for (i = 0, pState = pEASData->pPCMStreams; i < MAX_PCM_STREAMS; i++, pState++) - { - if ((pState->fileHandle) && (pState->state != EAS_STATE_STOPPED) && (pState->state != EAS_STATE_PAUSED)) - if ((result = RenderPCMStream(pEASData, pState, numSamples)) != EAS_SUCCESS) - return result; - } - return EAS_SUCCESS; -} - - -/*---------------------------------------------------------------------------- - * EAS_PEState() - *---------------------------------------------------------------------------- - * Purpose: - * Returns the current state of the stream - * - * Inputs: - * pEASData - pointer to overall EAS data structure - * handle - pointer to file handle - * pState - pointer to variable to store state - * - * Outputs: - * - * - * Side Effects: - * - * Notes: - * This interface is also exposed in the internal library for use by the other modules. - *---------------------------------------------------------------------------- -*/ -/*lint -esym(715, pEASData) reserved for future use */ -EAS_RESULT EAS_PEState (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pInstData, EAS_STATE *pState) -{ - /* return current state */ - *pState = pInstData->state; - return EAS_SUCCESS; -} - -/*---------------------------------------------------------------------------- - * EAS_PEClose() - *---------------------------------------------------------------------------- - * Purpose: - * Close the file and clean up - * - * Inputs: - * pEASData - pointer to overall EAS data structure - * handle - pointer to file handle - * - * Outputs: - * - * - * Side Effects: - * - *---------------------------------------------------------------------------- -*/ -EAS_RESULT EAS_PEClose (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState) -{ - EAS_RESULT result; - - if ((result = EAS_HWCloseFile(pEASData->hwInstData, pState->fileHandle)) != EAS_SUCCESS) - return result; - - pState->fileHandle = NULL; - return EAS_SUCCESS; -} - -/*---------------------------------------------------------------------------- - * PCM_Reset() - *---------------------------------------------------------------------------- - * Purpose: - * Reset the sequencer. Used for locating backwards in the file. - * - * Inputs: - * pEASData - pointer to overall EAS data structure - * handle - pointer to file handle - * - * Outputs: - * - * - * Side Effects: - * - *---------------------------------------------------------------------------- -*/ -EAS_RESULT EAS_PEReset (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState) -{ - EAS_RESULT result; - - /* reset file position to first byte of data in the stream */ - if ((result = EAS_HWFileSeek(pEASData->hwInstData, pState->fileHandle, pState->startPos)) != EAS_SUCCESS) - { - { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %d seeking to start of PCM file\n", result); */ } - return result; - } - - /* re-initialize stream */ - return InitPCMStream(pEASData, pState); -} - -/*---------------------------------------------------------------------------- - * EAS_PEOpenStream() - *---------------------------------------------------------------------------- - * Purpose: - * Starts up a PCM playback - * - * Inputs: - * - * - * Outputs: - * - * - * Side Effects: - * - *---------------------------------------------------------------------------- -*/ -EAS_RESULT EAS_PEOpenStream (S_EAS_DATA *pEASData, S_PCM_OPEN_PARAMS *pParams, EAS_PCM_HANDLE *pHandle) -{ - EAS_RESULT result; - S_PCM_STATE *pState; - EAS_I32 filePos; - - /* make sure we support this decoder */ - if (pParams->decoder >= NUM_DECODER_MODULES) - { - { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Decoder selector out of range\n"); */ } - return EAS_ERROR_PARAMETER_RANGE; - } - if (decoders[pParams->decoder] == NULL) - { - { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Decoder module not available\n"); */ } - return EAS_ERROR_FEATURE_NOT_AVAILABLE; - } - - /* find a slot for the new stream */ - if ((pState = FindSlot(pEASData, pParams->fileHandle, pParams->pCallbackFunc, pParams->cbInstData)) == NULL) - { - { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unable to open ADPCM stream, too many streams open\n"); */ } - return EAS_ERROR_MAX_PCM_STREAMS; - } - - /* get the current file position */ - if ((result = EAS_HWFilePos(pEASData->hwInstData, pState->fileHandle, &filePos)) != EAS_SUCCESS) - { - { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_HWFilePos returned %ld\n",result); */ } - pState->fileHandle = NULL; - return result; - } - - pState->pDecoder = decoders[pParams->decoder]; - pState->startPos = filePos; - pState->bytesLeftLoop = pState->byteCount = pParams->size; - pState->loopStart = pParams->loopStart; - pState->samplesTilLoop = (EAS_I32) pState->loopStart; - pState->loopSamples = pParams->loopSamples; - pState->samplesInLoop = 0; - pState->blockSize = (EAS_U16) pParams->blockSize; - pState->flags = pParams->flags; - pState->envData = pParams->envData; - pState->volume = pParams->volume; - pState->sampleRate = (EAS_U16) pParams->sampleRate; - - /* set the base frequency */ - pState->basefreq = (SRC_RATE_MULTIPLER * (EAS_U32) pParams->sampleRate) >> 15; - - /* calculate shift for frequencies > 1.0 */ - pState->rateShift = 0; - while (pState->basefreq > 32767) - { - pState->basefreq = pState->basefreq >> 1; - pState->rateShift++; - } - - /* initialize */ - if ((result = InitPCMStream(pEASData, pState)) != EAS_SUCCESS) - return result; - - *pHandle = pState; - - { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "EAS_PEOpenStream: StartPos=%d, byteCount = %d, loopSamples=%d\n", - pState->startPos, pState->byteCount, pState->loopSamples); */ } - return EAS_SUCCESS; -} - -/*---------------------------------------------------------------------------- - * EAS_PEContinueStream() - *---------------------------------------------------------------------------- - * Purpose: - * Continues a PCM stream - * - * Inputs: - * - * - * Outputs: - * - * - * Side Effects: - * - *---------------------------------------------------------------------------- -*/ -/*lint -e{715} reserved for future use */ -EAS_RESULT EAS_PEContinueStream (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState, EAS_I32 size) -{ - - /* add new samples to count */ - pState->bytesLeft += size; - if (pState->bytesLeft > 0) - pState->flags &= ~PCM_FLAGS_EMPTY; - return EAS_SUCCESS; -} - -/*---------------------------------------------------------------------------- - * EAS_PEGetFileHandle() - *---------------------------------------------------------------------------- - * Purpose: - * Returns the file handle of a stream - * - * Inputs: - * - * - * Outputs: - * - * - * Side Effects: - * - *---------------------------------------------------------------------------- -*/ -/*lint -esym(715, pEASData) reserved for future use */ -EAS_RESULT EAS_PEGetFileHandle (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState, EAS_FILE_HANDLE *pFileHandle) -{ - *pFileHandle = pState->fileHandle; - return EAS_SUCCESS; -} - -/*---------------------------------------------------------------------------- - * EAS_PEUpdateParams() - *---------------------------------------------------------------------------- - * Purpose: - * Update the pitch and volume parameters for a PCM stream - * - * Inputs: - * pEASData - pointer to EAS library instance data - * handle - pointer to S_PCM_STATE for this stream - * gainLeft - linear gain multipler in 1.15 fraction format - * gainRight - linear gain multipler in 1.15 fraction format - * pitch - pitch shift in cents - * initial - initial settings, set current gain - * - * Outputs: - * - * - * Side Effects: - * - * Notes - * In mono mode, leftGain controls the output gain and rightGain is ignored - *---------------------------------------------------------------------------- -*/ -/*lint -esym(715, pEASData) reserved for future use */ -/*lint -esym(715, gainRight) used only in 2-channel version */ -EAS_RESULT EAS_PEUpdateParams (S_EAS_DATA* pEASData, EAS_PCM_HANDLE pState, EAS_I16 pitch, EAS_I16 gainLeft, EAS_I16 gainRight) -{ - - pState->gainLeft = gainLeft; - -#if (NUM_OUTPUT_CHANNELS == 2) - pState->gainRight = gainRight; -#endif - - pState->pitch = pitch; - return EAS_SUCCESS; -} - -/*---------------------------------------------------------------------------- - * EAS_PELocate() - *---------------------------------------------------------------------------- - * Purpose: - * This function seeks to the requested place in the file. Accuracy - * is dependent on the sample rate and block size. - * - * Inputs: - * pEASData - pointer to overall EAS data structure - * pState - stream handle - * time - media time in milliseconds - *---------------------------------------------------------------------------- -*/ -EAS_RESULT EAS_PELocate (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState, EAS_I32 time) -{ - if (pState->pDecoder->pfLocate == NULL) - return EAS_ERROR_FEATURE_NOT_AVAILABLE; - - return pState->pDecoder->pfLocate(pEASData, pState, time); -} - -/*---------------------------------------------------------------------------- - * EAS_PEUpdateVolume() - *---------------------------------------------------------------------------- - * Purpose: - * Update the volume parameters for a PCM stream - * - * Inputs: - * pEASData - pointer to EAS library instance data - * handle - pointer to S_PCM_STATE for this stream - * gainLeft - linear gain multipler in 1.15 fraction format - * gainRight - linear gain multipler in 1.15 fraction format - * initial - initial settings, set current gain - * - * Outputs: - * - * - * Side Effects: - * - * Notes - * In mono mode, leftGain controls the output gain and rightGain is ignored - *---------------------------------------------------------------------------- -*/ -/*lint -esym(715, pEASData) reserved for future use */ -EAS_RESULT EAS_PEUpdateVolume (S_EAS_DATA* pEASData, EAS_PCM_HANDLE pState, EAS_I16 volume) -{ - pState->volume = volume; - return EAS_SUCCESS; -} - -/*---------------------------------------------------------------------------- - * EAS_PEUpdatePitch() - *---------------------------------------------------------------------------- - * Purpose: - * Update the pitch parameter for a PCM stream - * - * Inputs: - * pEASData - pointer to EAS library instance data - * pState - pointer to S_PCM_STATE for this stream - * pitch - new pitch value in pitch cents - *---------------------------------------------------------------------------- -*/ -/*lint -esym(715, pEASData) reserved for future use */ -EAS_RESULT EAS_PEUpdatePitch (S_EAS_DATA* pEASData, EAS_PCM_HANDLE pState, EAS_I16 pitch) -{ - pState->pitch = pitch; - return EAS_SUCCESS; -} - -/*---------------------------------------------------------------------------- - * EAS_PEPause() - *---------------------------------------------------------------------------- - * Purpose: - * Mute and stop rendering a PCM stream. Sets the gain target to zero and stops the playback - * at the end of the next audio frame. - * - * Inputs: - * pEASData - pointer to EAS library instance data - * handle - pointer to S_PCM_STATE for this stream - * - * Outputs: - * - * - * Side Effects: - * - *---------------------------------------------------------------------------- -*/ -/*lint -esym(715, pEASData) reserved for future use */ -EAS_RESULT EAS_PEPause (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState) -{ - /* set state to stopping */ - pState->state = EAS_STATE_PAUSING; - return EAS_SUCCESS; -} - -/*---------------------------------------------------------------------------- - * EAS_PEResume() - *---------------------------------------------------------------------------- - * Purpose: - * Resume rendering a PCM stream. Sets the gain target back to its - * previous setting and restarts playback at the end of the next audio - * frame. - * - * Inputs: - * pEASData - pointer to EAS library instance data - * handle - pointer to S_PCM_STATE for this stream - * - * Outputs: - * - * - * Side Effects: - * - *---------------------------------------------------------------------------- -*/ -/*lint -esym(715, pEASData) reserved for future use */ -EAS_RESULT EAS_PEResume (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState) -{ - /* set state to stopping */ - pState->state = EAS_STATE_PLAY; - return EAS_SUCCESS; -} - -EAS_U32 getDecayScale(EAS_U32 index) -{ - EAS_U32 utemp; - - //envelope decay segment - switch (index) - { - case 0: //no decay - utemp = 512;//32768; - break; - case 1: //.0156 dB per update - utemp = 511;//32709; - break; - case 2: //.03125 - utemp = 510;//32649; - break; - case 3: //.0625 - utemp = 508;//32532; - break; - case 4: //.125 - utemp = 505;//32298; - break; - case 5: //.25 - utemp = 497;//31835; - break; - case 6: //.5 - utemp = 483;//30929; - break; - case 7: //1.0 - utemp = 456;//29193; - break; - case 8: //2.0 - utemp = 406;//26008; - break; - case 9: //4.0 - utemp = 323;//20642; - break; - case 10: //8.0 - utemp = 203;//13004; - break; - case 11: //16.0 - utemp = 81;//5160; - break; - case 12: //32.0 - utemp = 13;//813; - break; - case 13: //64.0 - utemp = 0;//20; - break; - case 14: //128.0 - utemp = 0; - break; - case 15: //256.0 - default: - utemp = 0; - break; - } - //printf("getdecayscale returned %d\n",utemp); - return utemp; -} - -EAS_U32 getAttackIncrement(EAS_U32 index) -{ - EAS_U32 utemp; - - //envelope decay segment - switch (index) - { - case 0: - utemp = 32; - break; - case 1: - utemp = 64; - break; - case 2: - utemp = 128; - break; - case 3: - utemp = 256; - break; - case 4: - utemp = 512; - break; - case 5: - utemp = 1024; - break; - case 6: - utemp = 2048; - break; - case 7: - utemp = 4096; - break; - case 8: - utemp = 8192; - break; - case 9: - utemp = 16384; - break; - case 10: - utemp = 32768; - break; - case 11: - utemp = 65536; - break; - case 12: - utemp = 65536; - break; - case 13: - utemp = 65536; - break; - case 14: - utemp = 65535; - break; - case 15: - default: - utemp = 0; - break; - } - //printf("getattackincrement returned %d\n",utemp); - return utemp; -} - -/*---------------------------------------------------------------------------- - * EAS_PERelease() - *---------------------------------------------------------------------------- - * Purpose: - * Put the PCM stream envelope into release. - * - * Inputs: - * pEASData - pointer to EAS library instance data - * handle - pointer to S_PCM_STATE for this stream - * - * Outputs: - * - * - * Side Effects: - * - *---------------------------------------------------------------------------- -*/ -/*lint -esym(715, pEASData) reserved for future use */ -EAS_RESULT EAS_PERelease (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState) -{ - EAS_U32 utemp; - - //printf("handling note-off part of envelope\n"); - /*if the note is not ignore release or sustained*/ - if (((pState->envData >> 24) & 0x0F)==0) - { - /* set envelope state to release */ - pState->envState = PCM_ENV_RELEASE; - utemp = ((pState->envData >> 20) & 0x0F); - pState->envScale = getDecayScale(utemp); //getReleaseScale(utemp); - } - else - { - /*else change envelope state to sustain */ - pState->envState = PCM_ENV_SUSTAIN; - utemp = ((pState->envData >> 28) & 0x0F); - pState->envScale = getDecayScale(utemp); //getSustainScale(utemp); - } - //since we are in release, don't let anything hang around too long - //printf("checking env scale, val = %d\n",((S_PCM_STATE*) handle)->envScale); - if (pState->envScale > 505) - pState->envScale = 505; - return EAS_SUCCESS; -} - -/*---------------------------------------------------------------------------- - * FindSlot() - *---------------------------------------------------------------------------- - * Purpose: - * Locates an empty stream slot and assigns the file handle - * - * Inputs: - * pEASData - pointer to EAS library instance data - * fileHandle - file handle - * pCallbackFunc - function to be called back upon EAS_STATE_STOPPED - * - * Outputs: - * returns handle to slot or NULL if all slots are used - * - * Side Effects: - * - *---------------------------------------------------------------------------- -*/ -static S_PCM_STATE *FindSlot (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_PCM_CALLBACK pCallbackFunc, EAS_VOID_PTR cbInstData) -{ - EAS_INT i; - S_PCM_STATE *pState; - -#ifndef NO_PCM_STEAL - S_PCM_STATE *foundState = NULL; - EAS_INT count = 0; - EAS_U32 startOrder = 0xFFFFFFFF; - S_PCM_STATE *stealState = NULL; - EAS_U32 youngest = 0; - - /* find an empty slot, count total in use, and find oldest in use (lowest start order) */ - for (i = 0, pState = pEASData->pPCMStreams; i < MAX_PCM_STREAMS; i++, pState++) - { - /* if this one is available */ - if (pState->fileHandle == NULL) - { - foundState = pState; - } - /* else this one is in use, so see if it is the oldest, and count total in use */ - /* also find youngest */ - else - { - /*one more voice in use*/ - count++; - /* is this the oldest? (lowest start order) */ - if ((pState->state != EAS_STATE_STOPPING) && (pState->startOrder < startOrder)) - { - /* remember this one */ - stealState = pState; - /* remember the oldest so far */ - startOrder = pState->startOrder; - } - /* is this the youngest? (highest start order) */ - if (pState->startOrder >= youngest) - { - youngest = pState->startOrder; - } - } - } - - /* if there are too many voices active, stop the oldest one */ - if (count > PCM_STREAM_THRESHOLD) - { - //printf("stealing!!!\n"); - /* make sure we got one, although we should always have one at this point */ - if (stealState != NULL) - { - //flag this as stopping, so it will get shut off - stealState->state = EAS_STATE_STOPPING; - } - } - - /* if there are no available open streams (we won't likely see this, due to stealing) */ - if (foundState == NULL) - return NULL; - - /* save info */ - foundState->startOrder = youngest + 1; - foundState->fileHandle = fileHandle; - foundState->pCallback = pCallbackFunc; - foundState->cbInstData = cbInstData; - return foundState; -#else - /* find an empty slot*/ - for (i = 0; i < MAX_PCM_STREAMS; i++) - { - pState = &pEASData->pPCMStreams[i]; - if (pState->fileHandle != NULL) - continue; - - pState->fileHandle = fileHandle; - pState->pCallback = pCallbackFunc; - pState->cbInstData = cbInstData; - return pState; - } - return NULL; -#endif -} - -#ifdef _LOOKUP_SAMPLE_RATE -/*---------------------------------------------------------------------------- - * CalcBaseFreq() - *---------------------------------------------------------------------------- - * Purpose: - * Calculates the fractional phase increment for the sample rate converter - * - * Inputs: - * sampleRate - sample rate in samples/sec - * - * Outputs: - * Returns fractional sample rate with a 15-bit fraction - * - * Side Effects: - * - *---------------------------------------------------------------------------- -*/ -static EAS_U32 CalcBaseFreq (EAS_U32 sampleRate) -{ - EAS_INT i; - - /* look up the conversion rate */ - for (i = 0; i < (EAS_INT)(SRC_CONV_RATE_ENTRIES); i ++) - { - if (srcConvRate[i][0] == sampleRate) - return srcConvRate[i][1]; - } - - /* if not found in table, do it the long way */ - { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Sample rate %u not in table, calculating by division\n", sampleRate); */ } - - return (SRC_RATE_MULTIPLER * (EAS_U32) sampleRate) >> 15; -} -#endif - -/*---------------------------------------------------------------------------- - * InitPCMStream() - *---------------------------------------------------------------------------- - * Purpose: - * Start an ADPCM stream playback. Decodes the header, preps the engine. - * - * Inputs: - * - * - * Outputs: - * - * - * Side Effects: - * - *---------------------------------------------------------------------------- -*/ -static EAS_RESULT InitPCMStream (S_EAS_DATA *pEASData, S_PCM_STATE *pState) -{ - - /* initialize the data structure */ - pState->bytesLeft = pState->byteCount; - pState->phase = 0; - pState->srcByte = 0; - pState->decoderL.acc = 0; - pState->decoderL.output = 0; - pState->decoderL.x0 = pState->decoderL.x1 = 0; - pState->decoderL.step = 0; - pState->decoderR.acc = 0; - pState->decoderR.output = 0; - pState->decoderR.x0 = pState->decoderR.x1 = 0; - pState->decoderR.step = 0; - pState->hiNibble = EAS_FALSE; - pState->pitch = 0; - pState->blockCount = 0; - pState->gainLeft = PCM_DEFAULT_GAIN_SETTING; -// pState->currentGainLeft = PCM_DEFAULT_GAIN_SETTING; - pState->envValue = 0; - pState->envState = PCM_ENV_START; - -#if (NUM_OUTPUT_CHANNELS == 2) - pState->gainRight = PCM_DEFAULT_GAIN_SETTING; -// pState->currentGainRight = PCM_DEFAULT_GAIN_SETTING; -#endif - pState->state = EAS_STATE_READY; - - /* initialize the decoder */ - if (pState->pDecoder->pfInit) - return (*pState->pDecoder->pfInit)(pEASData, pState); - return EAS_SUCCESS; -} - -/*---------------------------------------------------------------------------- - * RenderPCMStream() - *---------------------------------------------------------------------------- - * Purpose: - * Decodes a buffer of ADPCM data. - * - * Inputs: - * - * - * Outputs: - * - * - * Side Effects: - * - *---------------------------------------------------------------------------- -*/ -static EAS_RESULT RenderPCMStream (S_EAS_DATA *pEASData, S_PCM_STATE *pState, EAS_I32 numSamples) -{ - EAS_RESULT result; - EAS_U32 phaseInc; - EAS_I32 gainLeft, gainIncLeft; - EAS_I32 *pOut; - EAS_I32 temp; - EAS_U32 utemp; - -#if (NUM_OUTPUT_CHANNELS == 2) - EAS_I32 gainRight, gainIncRight; -#endif - -#if 0 - printf("env data: AR = %d, DR = %d, SL = %d, SR = %d, RR = %d\n", - ((pState->envData >> 12) & 0x0F), - ((pState->envData >> 16) & 0x0F), - ((pState->envData >> 8) & 0x0F), - ((pState->envData >> 28) & 0x0F), - ((pState->envData >> 20) & 0x0F)); -#endif - - if (pState->envState == PCM_ENV_START) - { - //printf("env start\n"); - utemp = ((pState->envData >> 12) & 0x0F); - //if fastest rate, attack is already completed - //do the same for slowest rate, since that allows zero to be passed for default envelope - if (utemp == 0x0F || utemp == 0x00) - { - //start envelope at full - pState->envValue = (32768<<7); - //jump right into decay - utemp = ((pState->envData >> 16) & 0x0F); - pState->envScale = getDecayScale(utemp); - pState->envState = PCM_ENV_DECAY; - pState->currentGainLeft = (EAS_I16) FMUL_15x15(pState->gainLeft, pState->volume); - pState->currentGainRight = (EAS_I16) FMUL_15x15(pState->gainRight, pState->volume); - } - //else attack has a ramp - else - { - //start the envelope very low - pState->envValue = (2<<7); - pState->currentGainLeft = 0; - pState->currentGainRight = 0; - //get envelope attack scaling value - pState->envScale = getAttackIncrement(utemp); - //go to attack state - pState->envState = PCM_ENV_ATTACK; - } - } - if (pState->envState == PCM_ENV_ATTACK) - { - //printf("env attack, env value = %d, env scale = %d\n",pState->envValue>>7,pState->envScale); - //update envelope value - pState->envValue = pState->envValue + (pState->envScale << 7); - //check envelope level and update state if needed - if (pState->envValue >= (32768<<7)) - { - pState->envValue = (32768<<7); - utemp = ((pState->envData >> 16) & 0x0F); - pState->envScale = getDecayScale(utemp); - pState->envState = PCM_ENV_DECAY; - } - } - else if (pState->envState == PCM_ENV_DECAY) - { - //printf("env decay, env value = %d, env scale = %d\n",pState->envValue>>7,pState->envScale); - //update envelope value - pState->envValue = (pState->envValue * pState->envScale)>>9; - //check envelope level against sustain level and update state if needed - utemp = ((pState->envData >> 8) & 0x0F); - if (utemp == (EAS_U32)0x0F) - utemp = (2<<7); - else - { - utemp = ((32769<<7) >> (utemp>>1)); - } - if (pState->envValue <= utemp) - { - utemp = ((pState->envData >> 28) & 0x0F); - pState->envScale = getDecayScale(utemp); //getSustainScale(utemp); - pState->envState = PCM_ENV_SUSTAIN; - } - } - else if (pState->envState == PCM_ENV_SUSTAIN) - { - //printf("env sustain, env value = %d, env scale = %d\n",pState->envValue>>7,pState->envScale); - //update envelope value - pState->envValue = (pState->envValue * pState->envScale)>>9; - //check envelope level against bottom level and update state if needed - if (pState->envValue <= (2<<7)) - { - //no more decay - pState->envScale = 512; - pState->envState = PCM_ENV_END; - } - } - else if (pState->envState == PCM_ENV_RELEASE) - { - //printf("env release, env value = %d, env scale = %d\n",pState->envValue>>7,pState->envScale); - //update envelope value - pState->envValue = (pState->envValue * pState->envScale)>>9; - //check envelope level against bottom level and update state if needed - if (pState->envValue <= (2<<7)) - { - //no more decay - pState->envScale = 512; - pState->envState = PCM_ENV_END; - } - } - else if (pState->envState == PCM_ENV_END) - { - //printf("env end\n"); - /* set state to stopping, already ramped down */ - pState->state = EAS_STATE_STOPPING; - } - - //pState->gainLeft = (EAS_U16)((pState->gainLeft * (pState->envValue>>7))>>15); - //pState->gainRight = (EAS_U16)((pState->gainRight * (pState->envValue>>7))>>15); - - /* gain to 32-bits to increase resolution on anti-zipper filter */ - /*lint -e{703} use shift for performance */ - gainLeft = (EAS_I32) pState->currentGainLeft << SYNTH_UPDATE_PERIOD_IN_BITS; -#if (NUM_OUTPUT_CHANNELS == 2) - /*lint -e{703} use shift for performance */ - gainRight = (EAS_I32) pState->currentGainRight << SYNTH_UPDATE_PERIOD_IN_BITS; -#endif - - /* calculate a new gain increment, gain target is zero if pausing */ - if ((pState->state == EAS_STATE_PAUSING) || (pState->state == EAS_STATE_PAUSED)) - { - gainIncLeft = -pState->currentGainLeft; -#if (NUM_OUTPUT_CHANNELS == 2) - gainIncRight= -pState->currentGainRight; -#endif - } - else - { - EAS_I32 gain = FMUL_15x15(pState->envValue >> 7, pState->volume); - gainIncLeft = FMUL_15x15(pState->gainLeft, gain) - pState->currentGainLeft; -#if (NUM_OUTPUT_CHANNELS == 2) - gainIncRight = FMUL_15x15(pState->gainRight, gain) - pState->currentGainRight; -#endif - } - - /* calculate phase increment */ - phaseInc = pState->basefreq; - - /* convert pitch cents to linear multiplier */ - if (pState->pitch) - { - temp = EAS_Calculate2toX(pState->pitch); - phaseInc = FMUL_15x15(phaseInc, temp); - } - phaseInc = phaseInc << pState->rateShift; - - /* pointer to mix buffer */ - pOut = pEASData->pMixBuffer; - - /* render a buffer of samples */ - while (numSamples--) - { - - /* interpolate an output sample */ - pState->decoderL.output = pState->decoderL.x0 + FMUL_15x15((pState->decoderL.x1 - pState->decoderL.x0), pState->phase & PHASE_FRAC_MASK); - - /* stereo output */ -#if (NUM_OUTPUT_CHANNELS == 2) - - /* stereo stream? */ - if (pState->flags & PCM_FLAGS_STEREO) - pState->decoderR.output = pState->decoderR.x0 + FMUL_15x15((pState->decoderR.x1 - pState->decoderR.x0), pState->phase & PHASE_FRAC_MASK); - - /* gain scale and mix */ - /*lint -e{704} use shift instead of division */ - *pOut++ += (pState->decoderL.output * (gainLeft >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS; - gainLeft += gainIncLeft; - - /*lint -e{704} use shift instead of division */ - if (pState->flags & PCM_FLAGS_STEREO) - *pOut++ += (pState->decoderR.output * (gainRight >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS; - else - *pOut++ += (pState->decoderL.output * (gainRight >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS; - - gainRight += gainIncRight; - - /* mono output */ -#else - /* if stereo stream, decode right channel and mix to mono */ - if (pState->flags & PCM_FLAGS_STEREO) - { - pState->decoderR.output= pState->decoderR.x0 + FMUL_15x15((pState->decoderR.x1 - pState->decoderR.x0), pState->phase & PHASE_FRAC_MASK); - - /* for mono, sum stereo ADPCM to mono */ - /*lint -e{704} use shift instead of division */ - *pOut++ += ((pState->decoderL.output + pState->decoderR.output) * (gainLeft >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS; - } - else - /*lint -e{704} use shift instead of division */ - *pOut++ += (pState->decoderL.output * (gainLeft >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS; - - gainLeft += gainIncLeft; -#endif - - /* advance phase accumulator */ - pState->phase += phaseInc; - - /* if integer part of phase accumulator is non-zero, advance to next sample */ - while (pState->phase & ~PHASE_FRAC_MASK) - { - pState->decoderL.x0 = pState->decoderL.x1; - pState->decoderR.x0 = pState->decoderR.x1; - - /* give the source a chance to continue the stream */ - if (!pState->bytesLeft && pState->pCallback && ((pState->flags & PCM_FLAGS_EMPTY) == 0)) - { - pState->flags |= PCM_FLAGS_EMPTY; - (*pState->pCallback)(pEASData, pState->cbInstData, pState, EAS_STATE_EMPTY); - { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "RenderPCMStream: After empty callback, bytesLeft = %d\n", pState->bytesLeft); */ } - } - - /* decode the next sample */ - if ((result = (*pState->pDecoder->pfDecodeSample)(pEASData, pState)) != EAS_SUCCESS) - return result; - - /* adjust phase by one sample */ - pState->phase -= (1L << NUM_PHASE_FRAC_BITS); - } - - } - - /* save new gain */ - /*lint -e{704} use shift instead of division */ - pState->currentGainLeft = (EAS_I16) (gainLeft >> SYNTH_UPDATE_PERIOD_IN_BITS); - -#if (NUM_OUTPUT_CHANNELS == 2) - /*lint -e{704} use shift instead of division */ - pState->currentGainRight = (EAS_I16) (gainRight >> SYNTH_UPDATE_PERIOD_IN_BITS); -#endif - - /* if pausing, set new state and notify */ - if (pState->state == EAS_STATE_PAUSING) - { - pState->state = EAS_STATE_PAUSED; - if (pState->pCallback) - (*pState->pCallback)(pEASData, pState->cbInstData, pState, pState->state); - } - - /* if out of data, set stopped state and notify */ - if (pState->bytesLeft == 0 || pState->state == EAS_STATE_STOPPING) - { - pState->state = EAS_STATE_STOPPED; - - /* do callback unless the file has already been closed */ - if (pState->pCallback && pState->fileHandle) - (*pState->pCallback)(pEASData, pState->cbInstData, pState, pState->state); - } - - if (pState->state == EAS_STATE_READY) - pState->state = EAS_STATE_PLAY; - - return EAS_SUCCESS; -} - -/*---------------------------------------------------------------------------- - * LinearPCMDecode() - *---------------------------------------------------------------------------- - * Purpose: - * Decodes a PCM sample - * - * Inputs: - * - * - * Outputs: - * - * - * Side Effects: - * - *---------------------------------------------------------------------------- -*/ -static EAS_RESULT LinearPCMDecode (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState) -{ - EAS_RESULT result; - EAS_HW_DATA_HANDLE hwInstData; - - hwInstData = ((S_EAS_DATA*) pEASData)->hwInstData; - - /* if out of data, check for loop */ - if ((pState->bytesLeft == 0) && (pState->loopSamples != 0)) - { - if ((result = EAS_HWFileSeek(pEASData->hwInstData, pState->fileHandle, (EAS_I32) (pState->startPos + pState->loopLocation))) != EAS_SUCCESS) - return result; - pState->bytesLeft = pState->byteCount = (EAS_I32) pState->bytesLeftLoop; - pState->flags &= ~PCM_FLAGS_EMPTY; - { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "LinearPCMDecode: Rewind file to %d, bytesLeft = %d\n", pState->startPos, pState->bytesLeft); */ } - } - - if (pState->bytesLeft) - { - - /* check format byte for 8-bit samples */ - if (pState->flags & PCM_FLAGS_8_BIT) - { - /* fetch left or mono sample */ - if ((result = EAS_HWGetByte(hwInstData, pState->fileHandle, &pState->srcByte)) != EAS_SUCCESS) - return result; - - /* if unsigned */ - if (pState->flags & PCM_FLAGS_UNSIGNED) - { - /*lint -e{734} converting unsigned 8-bit to signed 16-bit */ - pState->decoderL.x1 = (EAS_PCM)(((EAS_PCM) pState->srcByte << 8) ^ 0x8000); - } - else - { - /*lint -e{734} converting signed 8-bit to signed 16-bit */ - pState->decoderL.x1 = (EAS_PCM)((EAS_PCM) pState->srcByte << 8); - } - pState->bytesLeft--; - - /* fetch right sample */ - if(pState->flags & PCM_FLAGS_STEREO) - { - if ((result = EAS_HWGetByte(hwInstData, pState->fileHandle, &pState->srcByte)) != EAS_SUCCESS) - return result; - - /* if unsigned */ - if (pState->flags & PCM_FLAGS_UNSIGNED) - { - /*lint -e{734} converting unsigned 8-bit to signed 16-bit */ - pState->decoderR.x1 = (EAS_PCM)(((EAS_PCM) pState->srcByte << 8) ^ 0x8000); - } - else - { - /*lint -e{734} converting signed 8-bit to signed 16-bit */ - pState->decoderR.x1 = (EAS_PCM)((EAS_PCM) pState->srcByte << 8); - } - pState->bytesLeft--; - } - } - - /* must be 16-bit samples */ - else - { - //unsigned 16 bit currently not supported - if (pState->flags & PCM_FLAGS_UNSIGNED) - { - return EAS_ERROR_INVALID_PCM_TYPE; - } - - /* fetch left or mono sample */ - if ((result = EAS_HWGetWord(hwInstData, pState->fileHandle, &pState->decoderL.x1, EAS_FALSE)) != EAS_SUCCESS) - return result; - pState->bytesLeft -= 2; - - /* fetch right sample */ - if(pState->flags & PCM_FLAGS_STEREO) - { - if ((result = EAS_HWGetWord(hwInstData, pState->fileHandle, &pState->decoderR.x1, EAS_FALSE)) != EAS_SUCCESS) - return result; - pState->bytesLeft -= 2; - } - } - } - - /* no more data, force zero samples */ - else - pState->decoderL.x1 = pState->decoderR.x1 = 0; - - return EAS_SUCCESS; -} - -/*---------------------------------------------------------------------------- - * LinearPCMLocate() - *---------------------------------------------------------------------------- - * Purpose: - * Locate in a linear PCM stream - *---------------------------------------------------------------------------- -*/ -static EAS_RESULT LinearPCMLocate (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState, EAS_I32 time) -{ - EAS_RESULT result; - EAS_I32 temp; - EAS_I32 secs, msecs; - EAS_INT shift; - - /* calculate size of sample frame */ - if (pState->flags & PCM_FLAGS_8_BIT) - shift = 0; - else - shift = 1; - if (pState->flags & PCM_FLAGS_STEREO) - shift++; - - /* break down into secs and msecs */ - secs = time / 1000; - msecs = time - (secs * 1000); - - /* calculate sample number fraction from msecs */ - temp = (msecs * pState->sampleRate); - temp = (temp >> 10) + ((temp * 49) >> 21); - - /* add integer sample count */ - temp += secs * pState->sampleRate; - - /* calculate the position based on sample frame size */ - /*lint -e{703} use shift for performance */ - temp <<= shift; - - /* past end of sample? */ - if (temp > (EAS_I32) pState->loopStart) - { - /* if not looped, flag error */ - if (pState->loopSamples == 0) - { - pState->bytesLeft = 0; - pState->flags |= PCM_FLAGS_EMPTY; - return EAS_ERROR_LOCATE_BEYOND_END; - } - - /* looped sample - calculate position in loop */ - while (temp > (EAS_I32) pState->loopStart) - temp -= (EAS_I32) pState->loopStart; - } - - /* seek to new position */ - if ((result = EAS_PESeek(pEASData, pState, &temp)) != EAS_SUCCESS) - return result; - - /* reset state */ - if ((pState->state != EAS_STATE_PAUSING) && (pState->state != EAS_STATE_PAUSED)) - pState->state = EAS_STATE_READY; - - return EAS_SUCCESS; -} - -/*---------------------------------------------------------------------------- - * EAS_PESeek - *---------------------------------------------------------------------------- - * Purpose: - * Locate to a particular byte in a PCM stream - *---------------------------------------------------------------------------- - * This bit is tricky because the chunks may not be contiguous, - * so we have to rely on the parser to position in the file. We - * do this by seeking to the end of each chunk and simulating an - * empty buffer condition until we get to where we want to go. - * - * A better solution would be a parser API for re-positioning, - * but there isn't time at the moment to re-factor all the - * parsers to support a new API. - *---------------------------------------------------------------------------- -*/ -EAS_RESULT EAS_PESeek (S_EAS_DATA *pEASData, S_PCM_STATE *pState, EAS_I32 *pLocation) -{ - EAS_RESULT result; - - /* seek to start of audio */ - if ((result = EAS_HWFileSeek(pEASData->hwInstData, pState->fileHandle, pState->startPos)) != EAS_SUCCESS) - { - pState->state = EAS_STATE_ERROR; - return result; - } - pState->bytesLeft = pState->bytesLeftLoop; - - /* skip through chunks until we find the right chunk */ - while (*pLocation > (EAS_I32) pState->bytesLeft) - { - /* seek to end of audio chunk */ - { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "EAS_PESeek: Seek to offset = %d\n", pState->bytesLeft); */ } - if ((result = EAS_HWFileSeekOfs(pEASData->hwInstData, pState->fileHandle, pState->bytesLeft)) != EAS_SUCCESS) - { - pState->state = EAS_STATE_ERROR; - return result; - } - *pLocation -= pState->bytesLeft; - pState->bytesLeft = 0; - pState->flags |= PCM_FLAGS_EMPTY; - - /* retrieve more data */ - if (pState->pCallback) - (*pState->pCallback)(pEASData, pState->cbInstData, pState, EAS_STATE_EMPTY); - - { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "EAS_PESeek: bytesLeft=%d, byte location = %d\n", pState->bytesLeft, *pLocation); */ } - - /* no more samples */ - if (pState->bytesLeft == 0) - return EAS_ERROR_LOCATE_BEYOND_END; - } - - /* seek to new offset in current chunk */ - if (*pLocation > 0) - { - { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "EAS_PESeek: Seek to offset = %d\n", *pLocation); */ } - if ((result = EAS_HWFileSeekOfs(pEASData->hwInstData, pState->fileHandle, *pLocation)) != EAS_SUCCESS) - { - pState->state = EAS_STATE_ERROR; - return result; - } - - /* if not streamed, calculate number of bytes left */ - if (pState->flags & PCM_FLAGS_STREAMING) - pState->bytesLeft = 0x7fffffff; - else - pState->bytesLeft -= *pLocation; - } - return EAS_SUCCESS; -} - + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 849 $ + * $Date: 2007-08-28 08:59:11 -0700 (Tue, 28 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_data.h" +#include "eas_report.h" +#include "eas_host.h" +#include "eas_config.h" +#include "eas_parser.h" +#include "eas_pcm.h" +#include "eas_math.h" +#include "eas_mixer.h" + +#define PCM_MIXER_GUARD_BITS (NUM_MIXER_GUARD_BITS + 1) + +/*---------------------------------------------------------------------------- + * Decoder interfaces + *---------------------------------------------------------------------------- +*/ + +static EAS_RESULT LinearPCMDecode (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState); +static EAS_RESULT LinearPCMLocate (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState, EAS_I32 time); + +static const S_DECODER_INTERFACE PCMDecoder = +{ + NULL, + LinearPCMDecode, + LinearPCMLocate, +}; + +/* SMAF ADPCM decoder */ +#ifdef _SMAF_PARSER +extern S_DECODER_INTERFACE SmafDecoder; +#define SMAF_DECODER &SmafDecoder +extern S_DECODER_INTERFACE Smaf7BitDecoder; +#define SMAF_7BIT_DECODER &Smaf7BitDecoder +#else +#define SMAF_DECODER NULL +#define SMAF_7BIT_DECODER NULL +#endif + +/* IMA ADPCM decoder */ +#ifdef _IMA_DECODER +extern S_DECODER_INTERFACE IMADecoder; +#define IMA_DECODER &IMADecoder +#else +#define IMA_DECODER NULL +#endif + +static const S_DECODER_INTERFACE * const decoders[] = +{ + &PCMDecoder, + SMAF_DECODER, + IMA_DECODER, + SMAF_7BIT_DECODER +}; + +/*---------------------------------------------------------------------------- + * Sample rate conversion + *---------------------------------------------------------------------------- +*/ + +#define SRC_RATE_MULTIPLER (0x40000000 / _OUTPUT_SAMPLE_RATE) + +#ifdef _LOOKUP_SAMPLE_RATE +static const EAS_U32 srcConvRate[][2] = +{ + 4000L, (4000L << 15) / _OUTPUT_SAMPLE_RATE, + 8000L, (8000L << 15) / _OUTPUT_SAMPLE_RATE, + 11025L, (11025L << 15) / _OUTPUT_SAMPLE_RATE, + 12000L, (12000L << 15) / _OUTPUT_SAMPLE_RATE, + 16000L, (16000L << 15) / _OUTPUT_SAMPLE_RATE, + 22050L, (22050L << 15) / _OUTPUT_SAMPLE_RATE, + 24000L, (24000L << 15) / _OUTPUT_SAMPLE_RATE, + 32000L, (32000L << 15) / _OUTPUT_SAMPLE_RATE +}; +static EAS_U32 CalcBaseFreq (EAS_U32 sampleRate); +#define SRC_CONV_RATE_ENTRIES (sizeof(srcConvRate)/sizeof(EAS_U32)/2) +#endif + + +/* interface prototypes */ +static EAS_RESULT RenderPCMStream (S_EAS_DATA *pEASData, S_PCM_STATE *pState, EAS_I32 numSamples); + + +/* local prototypes */ +static S_PCM_STATE *FindSlot (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_PCM_CALLBACK pCallbackFunc, EAS_VOID_PTR cbInstData); +static EAS_RESULT InitPCMStream (S_EAS_DATA *pEASData, S_PCM_STATE *pState); + +/*---------------------------------------------------------------------------- + * EAS_PEInit() + *---------------------------------------------------------------------------- + * Purpose: + * Initializes the PCM engine + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEInit (S_EAS_DATA *pEASData) +{ + S_PCM_STATE *pState; + EAS_INT i; + + /* check for static memory allocation */ + if (pEASData->staticMemoryModel) + pEASData->pPCMStreams = EAS_CMEnumData(EAS_CM_PCM_DATA); + /* allocate dynamic memory */ + else + pEASData->pPCMStreams = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_PCM_STATE) * MAX_PCM_STREAMS); + + if (!pEASData->pPCMStreams) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate memory for PCM streams\n"); */ } + return EAS_ERROR_MALLOC_FAILED; + } + + //zero the memory to insure complete initialization + EAS_HWMemSet((void *)(pEASData->pPCMStreams),0, sizeof(S_PCM_STATE) * MAX_PCM_STREAMS); + + /* initialize the state data */ + for (i = 0, pState = pEASData->pPCMStreams; i < MAX_PCM_STREAMS; i++, pState++) + pState->fileHandle = NULL; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_PEShutdown() + *---------------------------------------------------------------------------- + * Purpose: + * Shuts down the PCM engine + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEShutdown (S_EAS_DATA *pEASData) +{ + + /* free any dynamic memory */ + if (!pEASData->staticMemoryModel) + { + if (pEASData->pPCMStreams) + { + EAS_HWFree(pEASData->hwInstData, pEASData->pPCMStreams); + pEASData->pPCMStreams = NULL; + } + } + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_PERender() + *---------------------------------------------------------------------------- + * Purpose: + * Render a buffer of PCM audio + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PERender (S_EAS_DATA* pEASData, EAS_I32 numSamples) +{ + S_PCM_STATE *pState; + EAS_RESULT result; + EAS_INT i; + + /* render all the active streams */ + for (i = 0, pState = pEASData->pPCMStreams; i < MAX_PCM_STREAMS; i++, pState++) + { + if ((pState->fileHandle) && (pState->state != EAS_STATE_STOPPED) && (pState->state != EAS_STATE_PAUSED)) + if ((result = RenderPCMStream(pEASData, pState, numSamples)) != EAS_SUCCESS) + return result; + } + return EAS_SUCCESS; +} + + +/*---------------------------------------------------------------------------- + * EAS_PEState() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current state of the stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * pState - pointer to variable to store state + * + * Outputs: + * + * + * Side Effects: + * + * Notes: + * This interface is also exposed in the internal library for use by the other modules. + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT EAS_PEState (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pInstData, EAS_STATE *pState) +{ + /* return current state */ + *pState = pInstData->state; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_PEClose() + *---------------------------------------------------------------------------- + * Purpose: + * Close the file and clean up + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEClose (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState) +{ + EAS_RESULT result; + + if ((result = EAS_HWCloseFile(pEASData->hwInstData, pState->fileHandle)) != EAS_SUCCESS) + return result; + + pState->fileHandle = NULL; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * PCM_Reset() + *---------------------------------------------------------------------------- + * Purpose: + * Reset the sequencer. Used for locating backwards in the file. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEReset (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState) +{ + EAS_RESULT result; + + /* reset file position to first byte of data in the stream */ + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pState->fileHandle, pState->startPos)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %d seeking to start of PCM file\n", result); */ } + return result; + } + + /* re-initialize stream */ + return InitPCMStream(pEASData, pState); +} + +/*---------------------------------------------------------------------------- + * EAS_PEOpenStream() + *---------------------------------------------------------------------------- + * Purpose: + * Starts up a PCM playback + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEOpenStream (S_EAS_DATA *pEASData, S_PCM_OPEN_PARAMS *pParams, EAS_PCM_HANDLE *pHandle) +{ + EAS_RESULT result; + S_PCM_STATE *pState; + EAS_I32 filePos; + + /* make sure we support this decoder */ + if (pParams->decoder >= NUM_DECODER_MODULES) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Decoder selector out of range\n"); */ } + return EAS_ERROR_PARAMETER_RANGE; + } + if (decoders[pParams->decoder] == NULL) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Decoder module not available\n"); */ } + return EAS_ERROR_FEATURE_NOT_AVAILABLE; + } + + /* find a slot for the new stream */ + if ((pState = FindSlot(pEASData, pParams->fileHandle, pParams->pCallbackFunc, pParams->cbInstData)) == NULL) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unable to open ADPCM stream, too many streams open\n"); */ } + return EAS_ERROR_MAX_PCM_STREAMS; + } + + /* get the current file position */ + if ((result = EAS_HWFilePos(pEASData->hwInstData, pState->fileHandle, &filePos)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_HWFilePos returned %ld\n",result); */ } + pState->fileHandle = NULL; + return result; + } + + pState->pDecoder = decoders[pParams->decoder]; + pState->startPos = filePos; + pState->bytesLeftLoop = pState->byteCount = pParams->size; + pState->loopStart = pParams->loopStart; + pState->samplesTilLoop = (EAS_I32) pState->loopStart; + pState->loopSamples = pParams->loopSamples; + pState->samplesInLoop = 0; + pState->blockSize = (EAS_U16) pParams->blockSize; + pState->flags = pParams->flags; + pState->envData = pParams->envData; + pState->volume = pParams->volume; + pState->sampleRate = (EAS_U16) pParams->sampleRate; + + /* set the base frequency */ + pState->basefreq = (SRC_RATE_MULTIPLER * (EAS_U32) pParams->sampleRate) >> 15; + + /* calculate shift for frequencies > 1.0 */ + pState->rateShift = 0; + while (pState->basefreq > 32767) + { + pState->basefreq = pState->basefreq >> 1; + pState->rateShift++; + } + + /* initialize */ + if ((result = InitPCMStream(pEASData, pState)) != EAS_SUCCESS) + return result; + + *pHandle = pState; + + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "EAS_PEOpenStream: StartPos=%d, byteCount = %d, loopSamples=%d\n", + pState->startPos, pState->byteCount, pState->loopSamples); */ } + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_PEContinueStream() + *---------------------------------------------------------------------------- + * Purpose: + * Continues a PCM stream + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -e{715} reserved for future use */ +EAS_RESULT EAS_PEContinueStream (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState, EAS_I32 size) +{ + + /* add new samples to count */ + pState->bytesLeft += size; + if (pState->bytesLeft > 0) + pState->flags &= ~PCM_FLAGS_EMPTY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_PEGetFileHandle() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the file handle of a stream + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT EAS_PEGetFileHandle (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState, EAS_FILE_HANDLE *pFileHandle) +{ + *pFileHandle = pState->fileHandle; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_PEUpdateParams() + *---------------------------------------------------------------------------- + * Purpose: + * Update the pitch and volume parameters for a PCM stream + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_PCM_STATE for this stream + * gainLeft - linear gain multipler in 1.15 fraction format + * gainRight - linear gain multipler in 1.15 fraction format + * pitch - pitch shift in cents + * initial - initial settings, set current gain + * + * Outputs: + * + * + * Side Effects: + * + * Notes + * In mono mode, leftGain controls the output gain and rightGain is ignored + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +/*lint -esym(715, gainRight) used only in 2-channel version */ +EAS_RESULT EAS_PEUpdateParams (S_EAS_DATA* pEASData, EAS_PCM_HANDLE pState, EAS_I16 pitch, EAS_I16 gainLeft, EAS_I16 gainRight) +{ + + pState->gainLeft = gainLeft; + +#if (NUM_OUTPUT_CHANNELS == 2) + pState->gainRight = gainRight; +#endif + + pState->pitch = pitch; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_PELocate() + *---------------------------------------------------------------------------- + * Purpose: + * This function seeks to the requested place in the file. Accuracy + * is dependent on the sample rate and block size. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * pState - stream handle + * time - media time in milliseconds + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PELocate (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState, EAS_I32 time) +{ + if (pState->pDecoder->pfLocate == NULL) + return EAS_ERROR_FEATURE_NOT_AVAILABLE; + + return pState->pDecoder->pfLocate(pEASData, pState, time); +} + +/*---------------------------------------------------------------------------- + * EAS_PEUpdateVolume() + *---------------------------------------------------------------------------- + * Purpose: + * Update the volume parameters for a PCM stream + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_PCM_STATE for this stream + * gainLeft - linear gain multipler in 1.15 fraction format + * gainRight - linear gain multipler in 1.15 fraction format + * initial - initial settings, set current gain + * + * Outputs: + * + * + * Side Effects: + * + * Notes + * In mono mode, leftGain controls the output gain and rightGain is ignored + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT EAS_PEUpdateVolume (S_EAS_DATA* pEASData, EAS_PCM_HANDLE pState, EAS_I16 volume) +{ + pState->volume = volume; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_PEUpdatePitch() + *---------------------------------------------------------------------------- + * Purpose: + * Update the pitch parameter for a PCM stream + * + * Inputs: + * pEASData - pointer to EAS library instance data + * pState - pointer to S_PCM_STATE for this stream + * pitch - new pitch value in pitch cents + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT EAS_PEUpdatePitch (S_EAS_DATA* pEASData, EAS_PCM_HANDLE pState, EAS_I16 pitch) +{ + pState->pitch = pitch; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_PEPause() + *---------------------------------------------------------------------------- + * Purpose: + * Mute and stop rendering a PCM stream. Sets the gain target to zero and stops the playback + * at the end of the next audio frame. + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_PCM_STATE for this stream + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT EAS_PEPause (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState) +{ + /* set state to stopping */ + pState->state = EAS_STATE_PAUSING; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_PEResume() + *---------------------------------------------------------------------------- + * Purpose: + * Resume rendering a PCM stream. Sets the gain target back to its + * previous setting and restarts playback at the end of the next audio + * frame. + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_PCM_STATE for this stream + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT EAS_PEResume (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState) +{ + /* set state to stopping */ + pState->state = EAS_STATE_PLAY; + return EAS_SUCCESS; +} + +EAS_U32 getDecayScale(EAS_U32 index) +{ + EAS_U32 utemp; + + //envelope decay segment + switch (index) + { + case 0: //no decay + utemp = 512;//32768; + break; + case 1: //.0156 dB per update + utemp = 511;//32709; + break; + case 2: //.03125 + utemp = 510;//32649; + break; + case 3: //.0625 + utemp = 508;//32532; + break; + case 4: //.125 + utemp = 505;//32298; + break; + case 5: //.25 + utemp = 497;//31835; + break; + case 6: //.5 + utemp = 483;//30929; + break; + case 7: //1.0 + utemp = 456;//29193; + break; + case 8: //2.0 + utemp = 406;//26008; + break; + case 9: //4.0 + utemp = 323;//20642; + break; + case 10: //8.0 + utemp = 203;//13004; + break; + case 11: //16.0 + utemp = 81;//5160; + break; + case 12: //32.0 + utemp = 13;//813; + break; + case 13: //64.0 + utemp = 0;//20; + break; + case 14: //128.0 + utemp = 0; + break; + case 15: //256.0 + default: + utemp = 0; + break; + } + //printf("getdecayscale returned %d\n",utemp); + return utemp; +} + +EAS_U32 getAttackIncrement(EAS_U32 index) +{ + EAS_U32 utemp; + + //envelope decay segment + switch (index) + { + case 0: + utemp = 32; + break; + case 1: + utemp = 64; + break; + case 2: + utemp = 128; + break; + case 3: + utemp = 256; + break; + case 4: + utemp = 512; + break; + case 5: + utemp = 1024; + break; + case 6: + utemp = 2048; + break; + case 7: + utemp = 4096; + break; + case 8: + utemp = 8192; + break; + case 9: + utemp = 16384; + break; + case 10: + utemp = 32768; + break; + case 11: + utemp = 65536; + break; + case 12: + utemp = 65536; + break; + case 13: + utemp = 65536; + break; + case 14: + utemp = 65535; + break; + case 15: + default: + utemp = 0; + break; + } + //printf("getattackincrement returned %d\n",utemp); + return utemp; +} + +/*---------------------------------------------------------------------------- + * EAS_PERelease() + *---------------------------------------------------------------------------- + * Purpose: + * Put the PCM stream envelope into release. + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_PCM_STATE for this stream + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT EAS_PERelease (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState) +{ + EAS_U32 utemp; + + //printf("handling note-off part of envelope\n"); + /*if the note is not ignore release or sustained*/ + if (((pState->envData >> 24) & 0x0F)==0) + { + /* set envelope state to release */ + pState->envState = PCM_ENV_RELEASE; + utemp = ((pState->envData >> 20) & 0x0F); + pState->envScale = getDecayScale(utemp); //getReleaseScale(utemp); + } + else + { + /*else change envelope state to sustain */ + pState->envState = PCM_ENV_SUSTAIN; + utemp = ((pState->envData >> 28) & 0x0F); + pState->envScale = getDecayScale(utemp); //getSustainScale(utemp); + } + //since we are in release, don't let anything hang around too long + //printf("checking env scale, val = %d\n",((S_PCM_STATE*) handle)->envScale); + if (pState->envScale > 505) + pState->envScale = 505; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * FindSlot() + *---------------------------------------------------------------------------- + * Purpose: + * Locates an empty stream slot and assigns the file handle + * + * Inputs: + * pEASData - pointer to EAS library instance data + * fileHandle - file handle + * pCallbackFunc - function to be called back upon EAS_STATE_STOPPED + * + * Outputs: + * returns handle to slot or NULL if all slots are used + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static S_PCM_STATE *FindSlot (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_PCM_CALLBACK pCallbackFunc, EAS_VOID_PTR cbInstData) +{ + EAS_INT i; + S_PCM_STATE *pState; + +#ifndef NO_PCM_STEAL + S_PCM_STATE *foundState = NULL; + EAS_INT count = 0; + EAS_U32 startOrder = 0xFFFFFFFF; + S_PCM_STATE *stealState = NULL; + EAS_U32 youngest = 0; + + /* find an empty slot, count total in use, and find oldest in use (lowest start order) */ + for (i = 0, pState = pEASData->pPCMStreams; i < MAX_PCM_STREAMS; i++, pState++) + { + /* if this one is available */ + if (pState->fileHandle == NULL) + { + foundState = pState; + } + /* else this one is in use, so see if it is the oldest, and count total in use */ + /* also find youngest */ + else + { + /*one more voice in use*/ + count++; + /* is this the oldest? (lowest start order) */ + if ((pState->state != EAS_STATE_STOPPING) && (pState->startOrder < startOrder)) + { + /* remember this one */ + stealState = pState; + /* remember the oldest so far */ + startOrder = pState->startOrder; + } + /* is this the youngest? (highest start order) */ + if (pState->startOrder >= youngest) + { + youngest = pState->startOrder; + } + } + } + + /* if there are too many voices active, stop the oldest one */ + if (count > PCM_STREAM_THRESHOLD) + { + //printf("stealing!!!\n"); + /* make sure we got one, although we should always have one at this point */ + if (stealState != NULL) + { + //flag this as stopping, so it will get shut off + stealState->state = EAS_STATE_STOPPING; + } + } + + /* if there are no available open streams (we won't likely see this, due to stealing) */ + if (foundState == NULL) + return NULL; + + /* save info */ + foundState->startOrder = youngest + 1; + foundState->fileHandle = fileHandle; + foundState->pCallback = pCallbackFunc; + foundState->cbInstData = cbInstData; + return foundState; +#else + /* find an empty slot*/ + for (i = 0; i < MAX_PCM_STREAMS; i++) + { + pState = &pEASData->pPCMStreams[i]; + if (pState->fileHandle != NULL) + continue; + + pState->fileHandle = fileHandle; + pState->pCallback = pCallbackFunc; + pState->cbInstData = cbInstData; + return pState; + } + return NULL; +#endif +} + +#ifdef _LOOKUP_SAMPLE_RATE +/*---------------------------------------------------------------------------- + * CalcBaseFreq() + *---------------------------------------------------------------------------- + * Purpose: + * Calculates the fractional phase increment for the sample rate converter + * + * Inputs: + * sampleRate - sample rate in samples/sec + * + * Outputs: + * Returns fractional sample rate with a 15-bit fraction + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_U32 CalcBaseFreq (EAS_U32 sampleRate) +{ + EAS_INT i; + + /* look up the conversion rate */ + for (i = 0; i < (EAS_INT)(SRC_CONV_RATE_ENTRIES); i ++) + { + if (srcConvRate[i][0] == sampleRate) + return srcConvRate[i][1]; + } + + /* if not found in table, do it the long way */ + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Sample rate %u not in table, calculating by division\n", sampleRate); */ } + + return (SRC_RATE_MULTIPLER * (EAS_U32) sampleRate) >> 15; +} +#endif + +/*---------------------------------------------------------------------------- + * InitPCMStream() + *---------------------------------------------------------------------------- + * Purpose: + * Start an ADPCM stream playback. Decodes the header, preps the engine. + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT InitPCMStream (S_EAS_DATA *pEASData, S_PCM_STATE *pState) +{ + + /* initialize the data structure */ + pState->bytesLeft = pState->byteCount; + pState->phase = 0; + pState->srcByte = 0; + pState->decoderL.acc = 0; + pState->decoderL.output = 0; + pState->decoderL.x0 = pState->decoderL.x1 = 0; + pState->decoderL.step = 0; + pState->decoderR.acc = 0; + pState->decoderR.output = 0; + pState->decoderR.x0 = pState->decoderR.x1 = 0; + pState->decoderR.step = 0; + pState->hiNibble = EAS_FALSE; + pState->pitch = 0; + pState->blockCount = 0; + pState->gainLeft = PCM_DEFAULT_GAIN_SETTING; +// pState->currentGainLeft = PCM_DEFAULT_GAIN_SETTING; + pState->envValue = 0; + pState->envState = PCM_ENV_START; + +#if (NUM_OUTPUT_CHANNELS == 2) + pState->gainRight = PCM_DEFAULT_GAIN_SETTING; +// pState->currentGainRight = PCM_DEFAULT_GAIN_SETTING; +#endif + pState->state = EAS_STATE_READY; + + /* initialize the decoder */ + if (pState->pDecoder->pfInit) + return (*pState->pDecoder->pfInit)(pEASData, pState); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RenderPCMStream() + *---------------------------------------------------------------------------- + * Purpose: + * Decodes a buffer of ADPCM data. + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RenderPCMStream (S_EAS_DATA *pEASData, S_PCM_STATE *pState, EAS_I32 numSamples) +{ + EAS_RESULT result; + EAS_U32 phaseInc; + EAS_I32 gainLeft, gainIncLeft; + EAS_I32 *pOut; + EAS_I32 temp; + EAS_U32 utemp; + +#if (NUM_OUTPUT_CHANNELS == 2) + EAS_I32 gainRight, gainIncRight; +#endif + +#if 0 + printf("env data: AR = %d, DR = %d, SL = %d, SR = %d, RR = %d\n", + ((pState->envData >> 12) & 0x0F), + ((pState->envData >> 16) & 0x0F), + ((pState->envData >> 8) & 0x0F), + ((pState->envData >> 28) & 0x0F), + ((pState->envData >> 20) & 0x0F)); +#endif + + if (pState->envState == PCM_ENV_START) + { + //printf("env start\n"); + utemp = ((pState->envData >> 12) & 0x0F); + //if fastest rate, attack is already completed + //do the same for slowest rate, since that allows zero to be passed for default envelope + if (utemp == 0x0F || utemp == 0x00) + { + //start envelope at full + pState->envValue = (32768<<7); + //jump right into decay + utemp = ((pState->envData >> 16) & 0x0F); + pState->envScale = getDecayScale(utemp); + pState->envState = PCM_ENV_DECAY; + pState->currentGainLeft = (EAS_I16) FMUL_15x15(pState->gainLeft, pState->volume); + pState->currentGainRight = (EAS_I16) FMUL_15x15(pState->gainRight, pState->volume); + } + //else attack has a ramp + else + { + //start the envelope very low + pState->envValue = (2<<7); + pState->currentGainLeft = 0; + pState->currentGainRight = 0; + //get envelope attack scaling value + pState->envScale = getAttackIncrement(utemp); + //go to attack state + pState->envState = PCM_ENV_ATTACK; + } + } + if (pState->envState == PCM_ENV_ATTACK) + { + //printf("env attack, env value = %d, env scale = %d\n",pState->envValue>>7,pState->envScale); + //update envelope value + pState->envValue = pState->envValue + (pState->envScale << 7); + //check envelope level and update state if needed + if (pState->envValue >= (32768<<7)) + { + pState->envValue = (32768<<7); + utemp = ((pState->envData >> 16) & 0x0F); + pState->envScale = getDecayScale(utemp); + pState->envState = PCM_ENV_DECAY; + } + } + else if (pState->envState == PCM_ENV_DECAY) + { + //printf("env decay, env value = %d, env scale = %d\n",pState->envValue>>7,pState->envScale); + //update envelope value + pState->envValue = (pState->envValue * pState->envScale)>>9; + //check envelope level against sustain level and update state if needed + utemp = ((pState->envData >> 8) & 0x0F); + if (utemp == (EAS_U32)0x0F) + utemp = (2<<7); + else + { + utemp = ((32769<<7) >> (utemp>>1)); + } + if (pState->envValue <= utemp) + { + utemp = ((pState->envData >> 28) & 0x0F); + pState->envScale = getDecayScale(utemp); //getSustainScale(utemp); + pState->envState = PCM_ENV_SUSTAIN; + } + } + else if (pState->envState == PCM_ENV_SUSTAIN) + { + //printf("env sustain, env value = %d, env scale = %d\n",pState->envValue>>7,pState->envScale); + //update envelope value + pState->envValue = (pState->envValue * pState->envScale)>>9; + //check envelope level against bottom level and update state if needed + if (pState->envValue <= (2<<7)) + { + //no more decay + pState->envScale = 512; + pState->envState = PCM_ENV_END; + } + } + else if (pState->envState == PCM_ENV_RELEASE) + { + //printf("env release, env value = %d, env scale = %d\n",pState->envValue>>7,pState->envScale); + //update envelope value + pState->envValue = (pState->envValue * pState->envScale)>>9; + //check envelope level against bottom level and update state if needed + if (pState->envValue <= (2<<7)) + { + //no more decay + pState->envScale = 512; + pState->envState = PCM_ENV_END; + } + } + else if (pState->envState == PCM_ENV_END) + { + //printf("env end\n"); + /* set state to stopping, already ramped down */ + pState->state = EAS_STATE_STOPPING; + } + + //pState->gainLeft = (EAS_U16)((pState->gainLeft * (pState->envValue>>7))>>15); + //pState->gainRight = (EAS_U16)((pState->gainRight * (pState->envValue>>7))>>15); + + /* gain to 32-bits to increase resolution on anti-zipper filter */ + /*lint -e{703} use shift for performance */ + gainLeft = (EAS_I32) pState->currentGainLeft << SYNTH_UPDATE_PERIOD_IN_BITS; +#if (NUM_OUTPUT_CHANNELS == 2) + /*lint -e{703} use shift for performance */ + gainRight = (EAS_I32) pState->currentGainRight << SYNTH_UPDATE_PERIOD_IN_BITS; +#endif + + /* calculate a new gain increment, gain target is zero if pausing */ + if ((pState->state == EAS_STATE_PAUSING) || (pState->state == EAS_STATE_PAUSED)) + { + gainIncLeft = -pState->currentGainLeft; +#if (NUM_OUTPUT_CHANNELS == 2) + gainIncRight= -pState->currentGainRight; +#endif + } + else + { + EAS_I32 gain = FMUL_15x15(pState->envValue >> 7, pState->volume); + gainIncLeft = FMUL_15x15(pState->gainLeft, gain) - pState->currentGainLeft; +#if (NUM_OUTPUT_CHANNELS == 2) + gainIncRight = FMUL_15x15(pState->gainRight, gain) - pState->currentGainRight; +#endif + } + + /* calculate phase increment */ + phaseInc = pState->basefreq; + + /* convert pitch cents to linear multiplier */ + if (pState->pitch) + { + temp = EAS_Calculate2toX(pState->pitch); + phaseInc = FMUL_15x15(phaseInc, temp); + } + phaseInc = phaseInc << pState->rateShift; + + /* pointer to mix buffer */ + pOut = pEASData->pMixBuffer; + + /* render a buffer of samples */ + while (numSamples--) + { + + /* interpolate an output sample */ + pState->decoderL.output = pState->decoderL.x0 + FMUL_15x15((pState->decoderL.x1 - pState->decoderL.x0), pState->phase & PHASE_FRAC_MASK); + + /* stereo output */ +#if (NUM_OUTPUT_CHANNELS == 2) + + /* stereo stream? */ + if (pState->flags & PCM_FLAGS_STEREO) + pState->decoderR.output = pState->decoderR.x0 + FMUL_15x15((pState->decoderR.x1 - pState->decoderR.x0), pState->phase & PHASE_FRAC_MASK); + + /* gain scale and mix */ + /*lint -e{704} use shift instead of division */ + *pOut++ += (pState->decoderL.output * (gainLeft >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS; + gainLeft += gainIncLeft; + + /*lint -e{704} use shift instead of division */ + if (pState->flags & PCM_FLAGS_STEREO) + *pOut++ += (pState->decoderR.output * (gainRight >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS; + else + *pOut++ += (pState->decoderL.output * (gainRight >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS; + + gainRight += gainIncRight; + + /* mono output */ +#else + /* if stereo stream, decode right channel and mix to mono */ + if (pState->flags & PCM_FLAGS_STEREO) + { + pState->decoderR.output= pState->decoderR.x0 + FMUL_15x15((pState->decoderR.x1 - pState->decoderR.x0), pState->phase & PHASE_FRAC_MASK); + + /* for mono, sum stereo ADPCM to mono */ + /*lint -e{704} use shift instead of division */ + *pOut++ += ((pState->decoderL.output + pState->decoderR.output) * (gainLeft >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS; + } + else + /*lint -e{704} use shift instead of division */ + *pOut++ += (pState->decoderL.output * (gainLeft >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS; + + gainLeft += gainIncLeft; +#endif + + /* advance phase accumulator */ + pState->phase += phaseInc; + + /* if integer part of phase accumulator is non-zero, advance to next sample */ + while (pState->phase & ~PHASE_FRAC_MASK) + { + pState->decoderL.x0 = pState->decoderL.x1; + pState->decoderR.x0 = pState->decoderR.x1; + + /* give the source a chance to continue the stream */ + if (!pState->bytesLeft && pState->pCallback && ((pState->flags & PCM_FLAGS_EMPTY) == 0)) + { + pState->flags |= PCM_FLAGS_EMPTY; + (*pState->pCallback)(pEASData, pState->cbInstData, pState, EAS_STATE_EMPTY); + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "RenderPCMStream: After empty callback, bytesLeft = %d\n", pState->bytesLeft); */ } + } + + /* decode the next sample */ + if ((result = (*pState->pDecoder->pfDecodeSample)(pEASData, pState)) != EAS_SUCCESS) + return result; + + /* adjust phase by one sample */ + pState->phase -= (1L << NUM_PHASE_FRAC_BITS); + } + + } + + /* save new gain */ + /*lint -e{704} use shift instead of division */ + pState->currentGainLeft = (EAS_I16) (gainLeft >> SYNTH_UPDATE_PERIOD_IN_BITS); + +#if (NUM_OUTPUT_CHANNELS == 2) + /*lint -e{704} use shift instead of division */ + pState->currentGainRight = (EAS_I16) (gainRight >> SYNTH_UPDATE_PERIOD_IN_BITS); +#endif + + /* if pausing, set new state and notify */ + if (pState->state == EAS_STATE_PAUSING) + { + pState->state = EAS_STATE_PAUSED; + if (pState->pCallback) + (*pState->pCallback)(pEASData, pState->cbInstData, pState, pState->state); + } + + /* if out of data, set stopped state and notify */ + if (pState->bytesLeft == 0 || pState->state == EAS_STATE_STOPPING) + { + pState->state = EAS_STATE_STOPPED; + + /* do callback unless the file has already been closed */ + if (pState->pCallback && pState->fileHandle) + (*pState->pCallback)(pEASData, pState->cbInstData, pState, pState->state); + } + + if (pState->state == EAS_STATE_READY) + pState->state = EAS_STATE_PLAY; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * LinearPCMDecode() + *---------------------------------------------------------------------------- + * Purpose: + * Decodes a PCM sample + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT LinearPCMDecode (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState) +{ + EAS_RESULT result; + EAS_HW_DATA_HANDLE hwInstData; + + hwInstData = ((S_EAS_DATA*) pEASData)->hwInstData; + + /* if out of data, check for loop */ + if ((pState->bytesLeft == 0) && (pState->loopSamples != 0)) + { + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pState->fileHandle, (EAS_I32) (pState->startPos + pState->loopLocation))) != EAS_SUCCESS) + return result; + pState->bytesLeft = pState->byteCount = (EAS_I32) pState->bytesLeftLoop; + pState->flags &= ~PCM_FLAGS_EMPTY; + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "LinearPCMDecode: Rewind file to %d, bytesLeft = %d\n", pState->startPos, pState->bytesLeft); */ } + } + + if (pState->bytesLeft) + { + + /* check format byte for 8-bit samples */ + if (pState->flags & PCM_FLAGS_8_BIT) + { + /* fetch left or mono sample */ + if ((result = EAS_HWGetByte(hwInstData, pState->fileHandle, &pState->srcByte)) != EAS_SUCCESS) + return result; + + /* if unsigned */ + if (pState->flags & PCM_FLAGS_UNSIGNED) + { + /*lint -e{734} converting unsigned 8-bit to signed 16-bit */ + pState->decoderL.x1 = (EAS_PCM)(((EAS_PCM) pState->srcByte << 8) ^ 0x8000); + } + else + { + /*lint -e{734} converting signed 8-bit to signed 16-bit */ + pState->decoderL.x1 = (EAS_PCM)((EAS_PCM) pState->srcByte << 8); + } + pState->bytesLeft--; + + /* fetch right sample */ + if(pState->flags & PCM_FLAGS_STEREO) + { + if ((result = EAS_HWGetByte(hwInstData, pState->fileHandle, &pState->srcByte)) != EAS_SUCCESS) + return result; + + /* if unsigned */ + if (pState->flags & PCM_FLAGS_UNSIGNED) + { + /*lint -e{734} converting unsigned 8-bit to signed 16-bit */ + pState->decoderR.x1 = (EAS_PCM)(((EAS_PCM) pState->srcByte << 8) ^ 0x8000); + } + else + { + /*lint -e{734} converting signed 8-bit to signed 16-bit */ + pState->decoderR.x1 = (EAS_PCM)((EAS_PCM) pState->srcByte << 8); + } + pState->bytesLeft--; + } + } + + /* must be 16-bit samples */ + else + { + //unsigned 16 bit currently not supported + if (pState->flags & PCM_FLAGS_UNSIGNED) + { + return EAS_ERROR_INVALID_PCM_TYPE; + } + + /* fetch left or mono sample */ + if ((result = EAS_HWGetWord(hwInstData, pState->fileHandle, &pState->decoderL.x1, EAS_FALSE)) != EAS_SUCCESS) + return result; + pState->bytesLeft -= 2; + + /* fetch right sample */ + if(pState->flags & PCM_FLAGS_STEREO) + { + if ((result = EAS_HWGetWord(hwInstData, pState->fileHandle, &pState->decoderR.x1, EAS_FALSE)) != EAS_SUCCESS) + return result; + pState->bytesLeft -= 2; + } + } + } + + /* no more data, force zero samples */ + else + pState->decoderL.x1 = pState->decoderR.x1 = 0; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * LinearPCMLocate() + *---------------------------------------------------------------------------- + * Purpose: + * Locate in a linear PCM stream + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT LinearPCMLocate (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState, EAS_I32 time) +{ + EAS_RESULT result; + EAS_I32 temp; + EAS_I32 secs, msecs; + EAS_INT shift; + + /* calculate size of sample frame */ + if (pState->flags & PCM_FLAGS_8_BIT) + shift = 0; + else + shift = 1; + if (pState->flags & PCM_FLAGS_STEREO) + shift++; + + /* break down into secs and msecs */ + secs = time / 1000; + msecs = time - (secs * 1000); + + /* calculate sample number fraction from msecs */ + temp = (msecs * pState->sampleRate); + temp = (temp >> 10) + ((temp * 49) >> 21); + + /* add integer sample count */ + temp += secs * pState->sampleRate; + + /* calculate the position based on sample frame size */ + /*lint -e{703} use shif