xref: /aosp_15_r20/external/sonivox/arm-wt-22k/lib_src/eas_smf.c (revision f81fb7c475c4b71ff83bdcc517de2a8c174e4e5c)
1*f81fb7c4SAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
2*f81fb7c4SAndroid Build Coastguard Worker  *
3*f81fb7c4SAndroid Build Coastguard Worker  * File:
4*f81fb7c4SAndroid Build Coastguard Worker  * eas_smf.c
5*f81fb7c4SAndroid Build Coastguard Worker  *
6*f81fb7c4SAndroid Build Coastguard Worker  * Contents and purpose:
7*f81fb7c4SAndroid Build Coastguard Worker  * SMF Type 0 and 1 File Parser
8*f81fb7c4SAndroid Build Coastguard Worker  *
9*f81fb7c4SAndroid Build Coastguard Worker  * For SMF timebase analysis, see "MIDI Sequencer Analysis.xls".
10*f81fb7c4SAndroid Build Coastguard Worker  *
11*f81fb7c4SAndroid Build Coastguard Worker  * Copyright Sonic Network Inc. 2005
12*f81fb7c4SAndroid Build Coastguard Worker 
13*f81fb7c4SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
14*f81fb7c4SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
15*f81fb7c4SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
16*f81fb7c4SAndroid Build Coastguard Worker  *
17*f81fb7c4SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
18*f81fb7c4SAndroid Build Coastguard Worker  *
19*f81fb7c4SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
20*f81fb7c4SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
21*f81fb7c4SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22*f81fb7c4SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
23*f81fb7c4SAndroid Build Coastguard Worker  * limitations under the License.
24*f81fb7c4SAndroid Build Coastguard Worker  *
25*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
26*f81fb7c4SAndroid Build Coastguard Worker  * Revision Control:
27*f81fb7c4SAndroid Build Coastguard Worker  *   $Revision: 803 $
28*f81fb7c4SAndroid Build Coastguard Worker  *   $Date: 2007-08-01 09:57:00 -0700 (Wed, 01 Aug 2007) $
29*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
30*f81fb7c4SAndroid Build Coastguard Worker */
31*f81fb7c4SAndroid Build Coastguard Worker 
32*f81fb7c4SAndroid Build Coastguard Worker #define LOG_TAG "Sonivox"
33*f81fb7c4SAndroid Build Coastguard Worker #include "log/log.h"
34*f81fb7c4SAndroid Build Coastguard Worker 
35*f81fb7c4SAndroid Build Coastguard Worker #include "eas_data.h"
36*f81fb7c4SAndroid Build Coastguard Worker #include "eas_miditypes.h"
37*f81fb7c4SAndroid Build Coastguard Worker #include "eas_parser.h"
38*f81fb7c4SAndroid Build Coastguard Worker #include "eas_report.h"
39*f81fb7c4SAndroid Build Coastguard Worker #include "eas_host.h"
40*f81fb7c4SAndroid Build Coastguard Worker #include "eas_midi.h"
41*f81fb7c4SAndroid Build Coastguard Worker #include "eas_config.h"
42*f81fb7c4SAndroid Build Coastguard Worker #include "eas_vm_protos.h"
43*f81fb7c4SAndroid Build Coastguard Worker #include "eas_smfdata.h"
44*f81fb7c4SAndroid Build Coastguard Worker #include "eas_smf.h"
45*f81fb7c4SAndroid Build Coastguard Worker 
46*f81fb7c4SAndroid Build Coastguard Worker #ifdef JET_INTERFACE
47*f81fb7c4SAndroid Build Coastguard Worker #include "jet_data.h"
48*f81fb7c4SAndroid Build Coastguard Worker #endif
49*f81fb7c4SAndroid Build Coastguard Worker 
50*f81fb7c4SAndroid Build Coastguard Worker //3 dls: The timebase for this module is adequate to keep MIDI and
51*f81fb7c4SAndroid Build Coastguard Worker //3 digital audio synchronized for only a few minutes. It should be
52*f81fb7c4SAndroid Build Coastguard Worker //3 sufficient for most mobile applications. If better accuracy is
53*f81fb7c4SAndroid Build Coastguard Worker //3 required, more fractional bits should be added to the timebase.
54*f81fb7c4SAndroid Build Coastguard Worker 
55*f81fb7c4SAndroid Build Coastguard Worker static const EAS_U8 smfHeader[] = { 'M', 'T', 'h', 'd' };
56*f81fb7c4SAndroid Build Coastguard Worker 
57*f81fb7c4SAndroid Build Coastguard Worker /* local prototypes */
58*f81fb7c4SAndroid Build Coastguard Worker static EAS_RESULT SMF_GetVarLenData (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_U32 *pData);
59*f81fb7c4SAndroid Build Coastguard Worker static EAS_RESULT SMF_ParseMetaEvent (S_EAS_DATA *pEASData, S_SMF_DATA *pSMFData, S_SMF_STREAM *pSMFStream);
60*f81fb7c4SAndroid Build Coastguard Worker static EAS_RESULT SMF_ParseSysEx (S_EAS_DATA *pEASData, S_SMF_DATA *pSMFData, S_SMF_STREAM *pSMFStream, EAS_U8 f0, EAS_INT parserMode);
61*f81fb7c4SAndroid Build Coastguard Worker static EAS_RESULT SMF_ParseEvent (S_EAS_DATA *pEASData, S_SMF_DATA *pSMFData, S_SMF_STREAM *pSMFStream, EAS_INT parserMode);
62*f81fb7c4SAndroid Build Coastguard Worker static EAS_RESULT SMF_GetDeltaTime (EAS_HW_DATA_HANDLE hwInstData, S_SMF_STREAM *pSMFStream);
63*f81fb7c4SAndroid Build Coastguard Worker static void SMF_UpdateTime (S_SMF_DATA *pSMFData, EAS_U32 ticks);
64*f81fb7c4SAndroid Build Coastguard Worker 
65*f81fb7c4SAndroid Build Coastguard Worker 
66*f81fb7c4SAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
67*f81fb7c4SAndroid Build Coastguard Worker  *
68*f81fb7c4SAndroid Build Coastguard Worker  * SMF_Parser
69*f81fb7c4SAndroid Build Coastguard Worker  *
70*f81fb7c4SAndroid Build Coastguard Worker  * This structure contains the functional interface for the SMF parser
71*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
72*f81fb7c4SAndroid Build Coastguard Worker */
73*f81fb7c4SAndroid Build Coastguard Worker const S_FILE_PARSER_INTERFACE EAS_SMF_Parser =
74*f81fb7c4SAndroid Build Coastguard Worker {
75*f81fb7c4SAndroid Build Coastguard Worker     SMF_CheckFileType,
76*f81fb7c4SAndroid Build Coastguard Worker     SMF_Prepare,
77*f81fb7c4SAndroid Build Coastguard Worker     SMF_Time,
78*f81fb7c4SAndroid Build Coastguard Worker     SMF_Event,
79*f81fb7c4SAndroid Build Coastguard Worker     SMF_State,
80*f81fb7c4SAndroid Build Coastguard Worker     SMF_Close,
81*f81fb7c4SAndroid Build Coastguard Worker     SMF_Reset,
82*f81fb7c4SAndroid Build Coastguard Worker #ifdef JET_INTERFACE
83*f81fb7c4SAndroid Build Coastguard Worker     SMF_Pause,
84*f81fb7c4SAndroid Build Coastguard Worker     SMF_Resume,
85*f81fb7c4SAndroid Build Coastguard Worker #else
86*f81fb7c4SAndroid Build Coastguard Worker     NULL,
87*f81fb7c4SAndroid Build Coastguard Worker     NULL,
88*f81fb7c4SAndroid Build Coastguard Worker #endif
89*f81fb7c4SAndroid Build Coastguard Worker     NULL,
90*f81fb7c4SAndroid Build Coastguard Worker     SMF_SetData,
91*f81fb7c4SAndroid Build Coastguard Worker     SMF_GetData,
92*f81fb7c4SAndroid Build Coastguard Worker     NULL
93*f81fb7c4SAndroid Build Coastguard Worker };
94*f81fb7c4SAndroid Build Coastguard Worker 
95*f81fb7c4SAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
96*f81fb7c4SAndroid Build Coastguard Worker  * SMF_CheckFileType()
97*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
98*f81fb7c4SAndroid Build Coastguard Worker  * Purpose:
99*f81fb7c4SAndroid Build Coastguard Worker  * Check the file type to see if we can parse it
100*f81fb7c4SAndroid Build Coastguard Worker  *
101*f81fb7c4SAndroid Build Coastguard Worker  * Inputs:
102*f81fb7c4SAndroid Build Coastguard Worker  * pEASData         - pointer to overall EAS data structure
103*f81fb7c4SAndroid Build Coastguard Worker  * handle           - pointer to file handle
104*f81fb7c4SAndroid Build Coastguard Worker  *
105*f81fb7c4SAndroid Build Coastguard Worker  * Outputs:
106*f81fb7c4SAndroid Build Coastguard Worker  *
107*f81fb7c4SAndroid Build Coastguard Worker  *
108*f81fb7c4SAndroid Build Coastguard Worker  * Side Effects:
109*f81fb7c4SAndroid Build Coastguard Worker  *
110*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
111*f81fb7c4SAndroid Build Coastguard Worker */
SMF_CheckFileType(S_EAS_DATA * pEASData,EAS_FILE_HANDLE fileHandle,EAS_VOID_PTR * ppHandle,EAS_I32 offset)112*f81fb7c4SAndroid Build Coastguard Worker EAS_RESULT SMF_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset)
113*f81fb7c4SAndroid Build Coastguard Worker {
114*f81fb7c4SAndroid Build Coastguard Worker     S_SMF_DATA* pSMFData;
115*f81fb7c4SAndroid Build Coastguard Worker     EAS_RESULT result;
116*f81fb7c4SAndroid Build Coastguard Worker 
117*f81fb7c4SAndroid Build Coastguard Worker     /* seek to starting offset - usually 0 */
118*f81fb7c4SAndroid Build Coastguard Worker     *ppHandle = NULL;
119*f81fb7c4SAndroid Build Coastguard Worker     if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, offset)) != EAS_SUCCESS)
120*f81fb7c4SAndroid Build Coastguard Worker         return result;
121*f81fb7c4SAndroid Build Coastguard Worker 
122*f81fb7c4SAndroid Build Coastguard Worker #ifdef FILE_HEADER_SEARCH
123*f81fb7c4SAndroid Build Coastguard Worker     /* search through file for header - slow method */
124*f81fb7c4SAndroid Build Coastguard Worker     if (pEASData->searchHeaderFlag)
125*f81fb7c4SAndroid Build Coastguard Worker     {
126*f81fb7c4SAndroid Build Coastguard Worker         result = EAS_SearchFile(pEASData, fileHandle, smfHeader, sizeof(smfHeader), &offset);
127*f81fb7c4SAndroid Build Coastguard Worker         if (result != EAS_SUCCESS)
128*f81fb7c4SAndroid Build Coastguard Worker             return (result == EAS_EOF) ? EAS_SUCCESS : result;
129*f81fb7c4SAndroid Build Coastguard Worker     }
130*f81fb7c4SAndroid Build Coastguard Worker 
131*f81fb7c4SAndroid Build Coastguard Worker     /* read the first 4 bytes of the file - quick method */
132*f81fb7c4SAndroid Build Coastguard Worker     else
133*f81fb7c4SAndroid Build Coastguard Worker #endif
134*f81fb7c4SAndroid Build Coastguard Worker     {
135*f81fb7c4SAndroid Build Coastguard Worker         EAS_U8 header[4];
136*f81fb7c4SAndroid Build Coastguard Worker         EAS_I32 count;
137*f81fb7c4SAndroid Build Coastguard Worker         if ((result = EAS_HWReadFile(pEASData->hwInstData, fileHandle, header, sizeof(header), &count)) != EAS_SUCCESS)
138*f81fb7c4SAndroid Build Coastguard Worker             return result;
139*f81fb7c4SAndroid Build Coastguard Worker 
140*f81fb7c4SAndroid Build Coastguard Worker         /* check for 'MThd' - If no match then return SUCCESS with NULL handle
141*f81fb7c4SAndroid Build Coastguard Worker          * to indicate not an SMF file. */
142*f81fb7c4SAndroid Build Coastguard Worker         if ((header[0] != 'M') || (header[1] != 'T') || (header[2] != 'h') || (header[3] != 'd'))
143*f81fb7c4SAndroid Build Coastguard Worker             return EAS_SUCCESS;
144*f81fb7c4SAndroid Build Coastguard Worker     }
145*f81fb7c4SAndroid Build Coastguard Worker 
146*f81fb7c4SAndroid Build Coastguard Worker     /* check for static memory allocation */
147*f81fb7c4SAndroid Build Coastguard Worker     if (pEASData->staticMemoryModel)
148*f81fb7c4SAndroid Build Coastguard Worker         pSMFData = EAS_CMEnumData(EAS_CM_SMF_DATA);
149*f81fb7c4SAndroid Build Coastguard Worker     else
150*f81fb7c4SAndroid Build Coastguard Worker     {
151*f81fb7c4SAndroid Build Coastguard Worker         pSMFData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_SMF_DATA));
152*f81fb7c4SAndroid Build Coastguard Worker         EAS_HWMemSet((void *)pSMFData,0, sizeof(S_SMF_DATA));
153*f81fb7c4SAndroid Build Coastguard Worker     }
154*f81fb7c4SAndroid Build Coastguard Worker     if (!pSMFData)
155*f81fb7c4SAndroid Build Coastguard Worker         return EAS_ERROR_MALLOC_FAILED;
156*f81fb7c4SAndroid Build Coastguard Worker 
157*f81fb7c4SAndroid Build Coastguard Worker     /* initialize some critical data */
158*f81fb7c4SAndroid Build Coastguard Worker     pSMFData->fileHandle = fileHandle;
159*f81fb7c4SAndroid Build Coastguard Worker     pSMFData->fileOffset = offset;
160*f81fb7c4SAndroid Build Coastguard Worker     pSMFData->pSynth = NULL;
161*f81fb7c4SAndroid Build Coastguard Worker     pSMFData->time = 0;
162*f81fb7c4SAndroid Build Coastguard Worker     pSMFData->state = EAS_STATE_OPEN;
163*f81fb7c4SAndroid Build Coastguard Worker     *ppHandle = pSMFData;
164*f81fb7c4SAndroid Build Coastguard Worker 
165*f81fb7c4SAndroid Build Coastguard Worker     return EAS_SUCCESS;
166*f81fb7c4SAndroid Build Coastguard Worker }
167*f81fb7c4SAndroid Build Coastguard Worker 
168*f81fb7c4SAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
169*f81fb7c4SAndroid Build Coastguard Worker  * SMF_Prepare()
170*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
171*f81fb7c4SAndroid Build Coastguard Worker  * Purpose:
172*f81fb7c4SAndroid Build Coastguard Worker  * Prepare to parse the file. Allocates instance data (or uses static allocation for
173*f81fb7c4SAndroid Build Coastguard Worker  * static memory model).
174*f81fb7c4SAndroid Build Coastguard Worker  *
175*f81fb7c4SAndroid Build Coastguard Worker  * Inputs:
176*f81fb7c4SAndroid Build Coastguard Worker  * pEASData         - pointer to overall EAS data structure
177*f81fb7c4SAndroid Build Coastguard Worker  * handle           - pointer to file handle
178*f81fb7c4SAndroid Build Coastguard Worker  *
179*f81fb7c4SAndroid Build Coastguard Worker  * Outputs:
180*f81fb7c4SAndroid Build Coastguard Worker  *
181*f81fb7c4SAndroid Build Coastguard Worker  *
182*f81fb7c4SAndroid Build Coastguard Worker  * Side Effects:
183*f81fb7c4SAndroid Build Coastguard Worker  *
184*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
185*f81fb7c4SAndroid Build Coastguard Worker */
SMF_Prepare(S_EAS_DATA * pEASData,EAS_VOID_PTR pInstData)186*f81fb7c4SAndroid Build Coastguard Worker EAS_RESULT SMF_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
187*f81fb7c4SAndroid Build Coastguard Worker {
188*f81fb7c4SAndroid Build Coastguard Worker     S_SMF_DATA* pSMFData;
189*f81fb7c4SAndroid Build Coastguard Worker     EAS_RESULT result;
190*f81fb7c4SAndroid Build Coastguard Worker 
191*f81fb7c4SAndroid Build Coastguard Worker     /* check for valid state */
192*f81fb7c4SAndroid Build Coastguard Worker     pSMFData = (S_SMF_DATA *) pInstData;
193*f81fb7c4SAndroid Build Coastguard Worker     if (pSMFData->state != EAS_STATE_OPEN)
194*f81fb7c4SAndroid Build Coastguard Worker         return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
195*f81fb7c4SAndroid Build Coastguard Worker 
196*f81fb7c4SAndroid Build Coastguard Worker     /* instantiate a synthesizer */
197*f81fb7c4SAndroid Build Coastguard Worker     if ((result = VMInitMIDI(pEASData, &pSMFData->pSynth)) != EAS_SUCCESS)
198*f81fb7c4SAndroid Build Coastguard Worker     {
199*f81fb7c4SAndroid Build Coastguard Worker         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMInitMIDI returned %d\n", result); */ }
200*f81fb7c4SAndroid Build Coastguard Worker         return result;
201*f81fb7c4SAndroid Build Coastguard Worker     }
202*f81fb7c4SAndroid Build Coastguard Worker 
203*f81fb7c4SAndroid Build Coastguard Worker     /* parse the file header and setup the individual stream parsers */
204*f81fb7c4SAndroid Build Coastguard Worker     if ((result = SMF_ParseHeader(pEASData->hwInstData, pSMFData)) != EAS_SUCCESS)
205*f81fb7c4SAndroid Build Coastguard Worker         return result;
206*f81fb7c4SAndroid Build Coastguard Worker 
207*f81fb7c4SAndroid Build Coastguard Worker     /* ready to play */
208*f81fb7c4SAndroid Build Coastguard Worker     pSMFData->state = EAS_STATE_READY;
209*f81fb7c4SAndroid Build Coastguard Worker     return EAS_SUCCESS;
210*f81fb7c4SAndroid Build Coastguard Worker }
211*f81fb7c4SAndroid Build Coastguard Worker 
212*f81fb7c4SAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
213*f81fb7c4SAndroid Build Coastguard Worker  * SMF_Time()
214*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
215*f81fb7c4SAndroid Build Coastguard Worker  * Purpose:
216*f81fb7c4SAndroid Build Coastguard Worker  * Returns the time of the next event in msecs
217*f81fb7c4SAndroid Build Coastguard Worker  *
218*f81fb7c4SAndroid Build Coastguard Worker  * Inputs:
219*f81fb7c4SAndroid Build Coastguard Worker  * pEASData         - pointer to overall EAS data structure
220*f81fb7c4SAndroid Build Coastguard Worker  * handle           - pointer to file handle
221*f81fb7c4SAndroid Build Coastguard Worker  * pTime            - pointer to variable to hold time of next event (in msecs)
222*f81fb7c4SAndroid Build Coastguard Worker  *
223*f81fb7c4SAndroid Build Coastguard Worker  * Outputs:
224*f81fb7c4SAndroid Build Coastguard Worker  *
225*f81fb7c4SAndroid Build Coastguard Worker  *
226*f81fb7c4SAndroid Build Coastguard Worker  * Side Effects:
227*f81fb7c4SAndroid Build Coastguard Worker  *
228*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
229*f81fb7c4SAndroid Build Coastguard Worker */
230*f81fb7c4SAndroid Build Coastguard Worker /*lint -esym(715, pEASData) reserved for future use */
SMF_Time(S_EAS_DATA * pEASData,EAS_VOID_PTR pInstData,EAS_U32 * pTime)231*f81fb7c4SAndroid Build Coastguard Worker EAS_RESULT SMF_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime)
232*f81fb7c4SAndroid Build Coastguard Worker {
233*f81fb7c4SAndroid Build Coastguard Worker     S_SMF_DATA *pSMFData;
234*f81fb7c4SAndroid Build Coastguard Worker 
235*f81fb7c4SAndroid Build Coastguard Worker     pSMFData = (S_SMF_DATA*) pInstData;
236*f81fb7c4SAndroid Build Coastguard Worker 
237*f81fb7c4SAndroid Build Coastguard Worker     /* sanity check */
238*f81fb7c4SAndroid Build Coastguard Worker #ifdef _CHECKED_BUILD
239*f81fb7c4SAndroid Build Coastguard Worker     if (pSMFData->state == EAS_STATE_STOPPED)
240*f81fb7c4SAndroid Build Coastguard Worker     {
241*f81fb7c4SAndroid Build Coastguard Worker         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Can't ask for time on a stopped stream\n"); */ }
242*f81fb7c4SAndroid Build Coastguard Worker     }
243*f81fb7c4SAndroid Build Coastguard Worker 
244*f81fb7c4SAndroid Build Coastguard Worker     if (pSMFData->nextStream == NULL)
245*f81fb7c4SAndroid Build Coastguard Worker     {
246*f81fb7c4SAndroid Build Coastguard Worker         { /* dpp: EAS_ReportEx( _EAS_SEVERITY_ERROR, "no is NULL\n"); */ }
247*f81fb7c4SAndroid Build Coastguard Worker     }
248*f81fb7c4SAndroid Build Coastguard Worker #endif
249*f81fb7c4SAndroid Build Coastguard Worker 
250*f81fb7c4SAndroid Build Coastguard Worker #if 0
251*f81fb7c4SAndroid Build Coastguard Worker     /* return time in milliseconds */
252*f81fb7c4SAndroid Build Coastguard Worker     /* if chase mode, lie about time */
253*f81fb7c4SAndroid Build Coastguard Worker     if (pSMFData->flags & SMF_FLAGS_CHASE_MODE)
254*f81fb7c4SAndroid Build Coastguard Worker         *pTime = 0;
255*f81fb7c4SAndroid Build Coastguard Worker 
256*f81fb7c4SAndroid Build Coastguard Worker     else
257*f81fb7c4SAndroid Build Coastguard Worker #endif
258*f81fb7c4SAndroid Build Coastguard Worker 
259*f81fb7c4SAndroid Build Coastguard Worker         /*lint -e{704} use shift instead of division */
260*f81fb7c4SAndroid Build Coastguard Worker         *pTime = pSMFData->time >> 8;
261*f81fb7c4SAndroid Build Coastguard Worker 
262*f81fb7c4SAndroid Build Coastguard Worker     *pTime = pSMFData->time >> 8;
263*f81fb7c4SAndroid Build Coastguard Worker     return EAS_SUCCESS;
264*f81fb7c4SAndroid Build Coastguard Worker }
265*f81fb7c4SAndroid Build Coastguard Worker 
266*f81fb7c4SAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
267*f81fb7c4SAndroid Build Coastguard Worker  * SMF_Event()
268*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
269*f81fb7c4SAndroid Build Coastguard Worker  * Purpose:
270*f81fb7c4SAndroid Build Coastguard Worker  * Parse the next event in the file
271*f81fb7c4SAndroid Build Coastguard Worker  *
272*f81fb7c4SAndroid Build Coastguard Worker  * Inputs:
273*f81fb7c4SAndroid Build Coastguard Worker  * pEASData         - pointer to overall EAS data structure
274*f81fb7c4SAndroid Build Coastguard Worker  * handle           - pointer to file handle
275*f81fb7c4SAndroid Build Coastguard Worker  *
276*f81fb7c4SAndroid Build Coastguard Worker  * Outputs:
277*f81fb7c4SAndroid Build Coastguard Worker  *
278*f81fb7c4SAndroid Build Coastguard Worker  *
279*f81fb7c4SAndroid Build Coastguard Worker  * Side Effects:
280*f81fb7c4SAndroid Build Coastguard Worker  *
281*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
282*f81fb7c4SAndroid Build Coastguard Worker */
SMF_Event(S_EAS_DATA * pEASData,EAS_VOID_PTR pInstData,EAS_INT parserMode)283*f81fb7c4SAndroid Build Coastguard Worker EAS_RESULT SMF_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode)
284*f81fb7c4SAndroid Build Coastguard Worker {
285*f81fb7c4SAndroid Build Coastguard Worker     S_SMF_DATA* pSMFData;
286*f81fb7c4SAndroid Build Coastguard Worker     EAS_RESULT result;
287*f81fb7c4SAndroid Build Coastguard Worker     EAS_I32 i;
288*f81fb7c4SAndroid Build Coastguard Worker     EAS_U32 ticks;
289*f81fb7c4SAndroid Build Coastguard Worker     EAS_U32 temp;
290*f81fb7c4SAndroid Build Coastguard Worker 
291*f81fb7c4SAndroid Build Coastguard Worker     /* establish pointer to instance data */
292*f81fb7c4SAndroid Build Coastguard Worker     pSMFData = (S_SMF_DATA*) pInstData;
293*f81fb7c4SAndroid Build Coastguard Worker     if (pSMFData->state >= EAS_STATE_OPEN)
294*f81fb7c4SAndroid Build Coastguard Worker         return EAS_SUCCESS;
295*f81fb7c4SAndroid Build Coastguard Worker 
296*f81fb7c4SAndroid Build Coastguard Worker     if (!pSMFData->nextStream) {
297*f81fb7c4SAndroid Build Coastguard Worker         return EAS_ERROR_FILE_FORMAT;
298*f81fb7c4SAndroid Build Coastguard Worker     }
299*f81fb7c4SAndroid Build Coastguard Worker 
300*f81fb7c4SAndroid Build Coastguard Worker 
301*f81fb7c4SAndroid Build Coastguard Worker     /* get current ticks */
302*f81fb7c4SAndroid Build Coastguard Worker     ticks = pSMFData->nextStream->ticks;
303*f81fb7c4SAndroid Build Coastguard Worker 
304*f81fb7c4SAndroid Build Coastguard Worker     /* assume that an error occurred */
305*f81fb7c4SAndroid Build Coastguard Worker     pSMFData->state = EAS_STATE_ERROR;
306*f81fb7c4SAndroid Build Coastguard Worker 
307*f81fb7c4SAndroid Build Coastguard Worker #ifdef JET_INTERFACE
308*f81fb7c4SAndroid Build Coastguard Worker     /* if JET has track muted, set parser mode to mute */
309*f81fb7c4SAndroid Build Coastguard Worker     if (pSMFData->nextStream->midiStream.jetData & MIDI_FLAGS_JET_MUTE)
310*f81fb7c4SAndroid Build Coastguard Worker         parserMode = eParserModeMute;
311*f81fb7c4SAndroid Build Coastguard Worker #endif
312*f81fb7c4SAndroid Build Coastguard Worker 
313*f81fb7c4SAndroid Build Coastguard Worker     /* parse the next event from all the streams */
314*f81fb7c4SAndroid Build Coastguard Worker     if ((result = SMF_ParseEvent(pEASData, pSMFData, pSMFData->nextStream, parserMode)) != EAS_SUCCESS)
315*f81fb7c4SAndroid Build Coastguard Worker     {
316*f81fb7c4SAndroid Build Coastguard Worker         /* check for unexpected end-of-file */
317*f81fb7c4SAndroid Build Coastguard Worker         if (result != EAS_EOF)
318*f81fb7c4SAndroid Build Coastguard Worker             return result;
319*f81fb7c4SAndroid Build Coastguard Worker 
320*f81fb7c4SAndroid Build Coastguard Worker         /* indicate end of track for this stream */
321*f81fb7c4SAndroid Build Coastguard Worker         pSMFData->nextStream->ticks = SMF_END_OF_TRACK;
322*f81fb7c4SAndroid Build Coastguard Worker     }
323*f81fb7c4SAndroid Build Coastguard Worker 
324*f81fb7c4SAndroid Build Coastguard Worker     /* get next delta time, unless already at end of track */
325*f81fb7c4SAndroid Build Coastguard Worker     else if (pSMFData->nextStream->ticks != SMF_END_OF_TRACK)
326*f81fb7c4SAndroid Build Coastguard Worker     {
327*f81fb7c4SAndroid Build Coastguard Worker         if ((result = SMF_GetDeltaTime(pEASData->hwInstData, pSMFData->nextStream)) != EAS_SUCCESS)
328*f81fb7c4SAndroid Build Coastguard Worker         {
329*f81fb7c4SAndroid Build Coastguard Worker             /* check for unexpected end-of-file */
330*f81fb7c4SAndroid Build Coastguard Worker             if (result != EAS_EOF)
331*f81fb7c4SAndroid Build Coastguard Worker                 return result;
332*f81fb7c4SAndroid Build Coastguard Worker 
333*f81fb7c4SAndroid Build Coastguard Worker             /* indicate end of track for this stream */
334*f81fb7c4SAndroid Build Coastguard Worker             pSMFData->nextStream->ticks = SMF_END_OF_TRACK;
335*f81fb7c4SAndroid Build Coastguard Worker         }
336*f81fb7c4SAndroid Build Coastguard Worker 
337*f81fb7c4SAndroid Build Coastguard Worker         /* if zero delta to next event, stay with this stream */
338*f81fb7c4SAndroid Build Coastguard Worker         else if (pSMFData->nextStream->ticks == ticks)
339*f81fb7c4SAndroid Build Coastguard Worker         {
340*f81fb7c4SAndroid Build Coastguard Worker             pSMFData->state = EAS_STATE_PLAY;
341*f81fb7c4SAndroid Build Coastguard Worker             return EAS_SUCCESS;
342*f81fb7c4SAndroid Build Coastguard Worker         }
343*f81fb7c4SAndroid Build Coastguard Worker     }
344*f81fb7c4SAndroid Build Coastguard Worker 
345*f81fb7c4SAndroid Build Coastguard Worker     /* find next event in all streams */
346*f81fb7c4SAndroid Build Coastguard Worker     temp = 0x7ffffff;
347*f81fb7c4SAndroid Build Coastguard Worker     pSMFData->nextStream = NULL;
348*f81fb7c4SAndroid Build Coastguard Worker     for (i = 0; i < pSMFData->numStreams; i++)
349*f81fb7c4SAndroid Build Coastguard Worker     {
350*f81fb7c4SAndroid Build Coastguard Worker         if (pSMFData->streams[i].ticks < temp)
351*f81fb7c4SAndroid Build Coastguard Worker         {
352*f81fb7c4SAndroid Build Coastguard Worker             temp = pSMFData->streams[i].ticks;
353*f81fb7c4SAndroid Build Coastguard Worker             pSMFData->nextStream = &pSMFData->streams[i];
354*f81fb7c4SAndroid Build Coastguard Worker         }
355*f81fb7c4SAndroid Build Coastguard Worker     }
356*f81fb7c4SAndroid Build Coastguard Worker 
357*f81fb7c4SAndroid Build Coastguard Worker     /* are there any more events to parse? */
358*f81fb7c4SAndroid Build Coastguard Worker     if (pSMFData->nextStream)
359*f81fb7c4SAndroid Build Coastguard Worker     {
360*f81fb7c4SAndroid Build Coastguard Worker         pSMFData->state = EAS_STATE_PLAY;
361*f81fb7c4SAndroid Build Coastguard Worker 
362*f81fb7c4SAndroid Build Coastguard Worker         /* update the time of the next event */
363*f81fb7c4SAndroid Build Coastguard Worker         SMF_UpdateTime(pSMFData, pSMFData->nextStream->ticks - ticks);
364*f81fb7c4SAndroid Build Coastguard Worker     }
365*f81fb7c4SAndroid Build Coastguard Worker     else
366*f81fb7c4SAndroid Build Coastguard Worker     {
367*f81fb7c4SAndroid Build Coastguard Worker         pSMFData->state = EAS_STATE_STOPPING;
368*f81fb7c4SAndroid Build Coastguard Worker         VMReleaseAllVoices(pEASData->pVoiceMgr, pSMFData->pSynth);
369*f81fb7c4SAndroid Build Coastguard Worker     }
370*f81fb7c4SAndroid Build Coastguard Worker 
371*f81fb7c4SAndroid Build Coastguard Worker     return EAS_SUCCESS;
372*f81fb7c4SAndroid Build Coastguard Worker }
373*f81fb7c4SAndroid Build Coastguard Worker 
374*f81fb7c4SAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
375*f81fb7c4SAndroid Build Coastguard Worker  * SMF_State()
376*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
377*f81fb7c4SAndroid Build Coastguard Worker  * Purpose:
378*f81fb7c4SAndroid Build Coastguard Worker  * Returns the current state of the stream
379*f81fb7c4SAndroid Build Coastguard Worker  *
380*f81fb7c4SAndroid Build Coastguard Worker  * Inputs:
381*f81fb7c4SAndroid Build Coastguard Worker  * pEASData         - pointer to overall EAS data structure
382*f81fb7c4SAndroid Build Coastguard Worker  * handle           - pointer to file handle
383*f81fb7c4SAndroid Build Coastguard Worker  * pState           - pointer to variable to store state
384*f81fb7c4SAndroid Build Coastguard Worker  *
385*f81fb7c4SAndroid Build Coastguard Worker  * Outputs:
386*f81fb7c4SAndroid Build Coastguard Worker  *
387*f81fb7c4SAndroid Build Coastguard Worker  *
388*f81fb7c4SAndroid Build Coastguard Worker  * Side Effects:
389*f81fb7c4SAndroid Build Coastguard Worker  *
390*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
391*f81fb7c4SAndroid Build Coastguard Worker */
392*f81fb7c4SAndroid Build Coastguard Worker /*lint -esym(715, pEASData) reserved for future use */
SMF_State(S_EAS_DATA * pEASData,EAS_VOID_PTR pInstData,EAS_I32 * pState)393*f81fb7c4SAndroid Build Coastguard Worker EAS_RESULT SMF_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pState)
394*f81fb7c4SAndroid Build Coastguard Worker {
395*f81fb7c4SAndroid Build Coastguard Worker     S_SMF_DATA* pSMFData;
396*f81fb7c4SAndroid Build Coastguard Worker 
397*f81fb7c4SAndroid Build Coastguard Worker     /* establish pointer to instance data */
398*f81fb7c4SAndroid Build Coastguard Worker     pSMFData = (S_SMF_DATA*) pInstData;
399*f81fb7c4SAndroid Build Coastguard Worker 
400*f81fb7c4SAndroid Build Coastguard Worker     /* if stopping, check to see if synth voices are active */
401*f81fb7c4SAndroid Build Coastguard Worker     if (pSMFData->state == EAS_STATE_STOPPING)
402*f81fb7c4SAndroid Build Coastguard Worker     {
403*f81fb7c4SAndroid Build Coastguard Worker         if (VMActiveVoices(pSMFData->pSynth) == 0)
404*f81fb7c4SAndroid Build Coastguard Worker             pSMFData->state = EAS_STATE_STOPPED;
405*f81fb7c4SAndroid Build Coastguard Worker     }
406*f81fb7c4SAndroid Build Coastguard Worker 
407*f81fb7c4SAndroid Build Coastguard Worker     if (pSMFData->state == EAS_STATE_PAUSING)
408*f81fb7c4SAndroid Build Coastguard Worker     {
409*f81fb7c4SAndroid Build Coastguard Worker         if (VMActiveVoices(pSMFData->pSynth) == 0)
410*f81fb7c4SAndroid Build Coastguard Worker             pSMFData->state = EAS_STATE_PAUSED;
411*f81fb7c4SAndroid Build Coastguard Worker     }
412*f81fb7c4SAndroid Build Coastguard Worker 
413*f81fb7c4SAndroid Build Coastguard Worker     /* return current state */
414*f81fb7c4SAndroid Build Coastguard Worker     *pState = pSMFData->state;
415*f81fb7c4SAndroid Build Coastguard Worker     return EAS_SUCCESS;
416*f81fb7c4SAndroid Build Coastguard Worker }
417*f81fb7c4SAndroid Build Coastguard Worker 
418*f81fb7c4SAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
419*f81fb7c4SAndroid Build Coastguard Worker  * SMF_Close()
420*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
421*f81fb7c4SAndroid Build Coastguard Worker  * Purpose:
422*f81fb7c4SAndroid Build Coastguard Worker  * Close the file and clean up
423*f81fb7c4SAndroid Build Coastguard Worker  *
424*f81fb7c4SAndroid Build Coastguard Worker  * Inputs:
425*f81fb7c4SAndroid Build Coastguard Worker  * pEASData         - pointer to overall EAS data structure
426*f81fb7c4SAndroid Build Coastguard Worker  * handle           - pointer to file handle
427*f81fb7c4SAndroid Build Coastguard Worker  *
428*f81fb7c4SAndroid Build Coastguard Worker  * Outputs:
429*f81fb7c4SAndroid Build Coastguard Worker  *
430*f81fb7c4SAndroid Build Coastguard Worker  *
431*f81fb7c4SAndroid Build Coastguard Worker  * Side Effects:
432*f81fb7c4SAndroid Build Coastguard Worker  *
433*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
434*f81fb7c4SAndroid Build Coastguard Worker */
SMF_Close(S_EAS_DATA * pEASData,EAS_VOID_PTR pInstData)435*f81fb7c4SAndroid Build Coastguard Worker EAS_RESULT SMF_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
436*f81fb7c4SAndroid Build Coastguard Worker {
437*f81fb7c4SAndroid Build Coastguard Worker     S_SMF_DATA* pSMFData;
438*f81fb7c4SAndroid Build Coastguard Worker     EAS_I32 i;
439*f81fb7c4SAndroid Build Coastguard Worker     EAS_RESULT result;
440*f81fb7c4SAndroid Build Coastguard Worker 
441*f81fb7c4SAndroid Build Coastguard Worker     pSMFData = (S_SMF_DATA*) pInstData;
442*f81fb7c4SAndroid Build Coastguard Worker 
443*f81fb7c4SAndroid Build Coastguard Worker     /* close all the streams */
444*f81fb7c4SAndroid Build Coastguard Worker     for (i = 0; i < pSMFData->numStreams; i++)
445*f81fb7c4SAndroid Build Coastguard Worker     {
446*f81fb7c4SAndroid Build Coastguard Worker         if (pSMFData->streams[i].fileHandle != NULL)
447*f81fb7c4SAndroid Build Coastguard Worker         {
448*f81fb7c4SAndroid Build Coastguard Worker             if ((result = EAS_HWCloseFile(pEASData->hwInstData, pSMFData->streams[i].fileHandle)) != EAS_SUCCESS)
449*f81fb7c4SAndroid Build Coastguard Worker                 return result;
450*f81fb7c4SAndroid Build Coastguard Worker         }
451*f81fb7c4SAndroid Build Coastguard Worker     }
452*f81fb7c4SAndroid Build Coastguard Worker     if (pSMFData->fileHandle != NULL)
453*f81fb7c4SAndroid Build Coastguard Worker         if ((result = EAS_HWCloseFile(pEASData->hwInstData, pSMFData->fileHandle)) != EAS_SUCCESS)
454*f81fb7c4SAndroid Build Coastguard Worker             return result;
455*f81fb7c4SAndroid Build Coastguard Worker 
456*f81fb7c4SAndroid Build Coastguard Worker     /* free the synth */
457*f81fb7c4SAndroid Build Coastguard Worker     if (pSMFData->pSynth != NULL)
458*f81fb7c4SAndroid Build Coastguard Worker         VMMIDIShutdown(pEASData, pSMFData->pSynth);
459*f81fb7c4SAndroid Build Coastguard Worker 
460*f81fb7c4SAndroid Build Coastguard Worker     /* if using dynamic memory, free it */
461*f81fb7c4SAndroid Build Coastguard Worker     if (!pEASData->staticMemoryModel)
462*f81fb7c4SAndroid Build Coastguard Worker     {
463*f81fb7c4SAndroid Build Coastguard Worker         if (pSMFData->streams)
464*f81fb7c4SAndroid Build Coastguard Worker             EAS_HWFree(pEASData->hwInstData, pSMFData->streams);
465*f81fb7c4SAndroid Build Coastguard Worker 
466*f81fb7c4SAndroid Build Coastguard Worker         /* free the instance data */
467*f81fb7c4SAndroid Build Coastguard Worker         EAS_HWFree(pEASData->hwInstData, pSMFData);
468*f81fb7c4SAndroid Build Coastguard Worker     }
469*f81fb7c4SAndroid Build Coastguard Worker 
470*f81fb7c4SAndroid Build Coastguard Worker     return EAS_SUCCESS;
471*f81fb7c4SAndroid Build Coastguard Worker }
472*f81fb7c4SAndroid Build Coastguard Worker 
473*f81fb7c4SAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
474*f81fb7c4SAndroid Build Coastguard Worker  * SMF_Reset()
475*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
476*f81fb7c4SAndroid Build Coastguard Worker  * Purpose:
477*f81fb7c4SAndroid Build Coastguard Worker  * Reset the sequencer. Used for locating backwards in the file.
478*f81fb7c4SAndroid Build Coastguard Worker  *
479*f81fb7c4SAndroid Build Coastguard Worker  * Inputs:
480*f81fb7c4SAndroid Build Coastguard Worker  * pEASData         - pointer to overall EAS data structure
481*f81fb7c4SAndroid Build Coastguard Worker  * handle           - pointer to file handle
482*f81fb7c4SAndroid Build Coastguard Worker  *
483*f81fb7c4SAndroid Build Coastguard Worker  * Outputs:
484*f81fb7c4SAndroid Build Coastguard Worker  *
485*f81fb7c4SAndroid Build Coastguard Worker  *
486*f81fb7c4SAndroid Build Coastguard Worker  * Side Effects:
487*f81fb7c4SAndroid Build Coastguard Worker  *
488*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
489*f81fb7c4SAndroid Build Coastguard Worker */
SMF_Reset(S_EAS_DATA * pEASData,EAS_VOID_PTR pInstData)490*f81fb7c4SAndroid Build Coastguard Worker EAS_RESULT SMF_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
491*f81fb7c4SAndroid Build Coastguard Worker {
492*f81fb7c4SAndroid Build Coastguard Worker     S_SMF_DATA* pSMFData;
493*f81fb7c4SAndroid Build Coastguard Worker     EAS_I32 i;
494*f81fb7c4SAndroid Build Coastguard Worker     EAS_RESULT result;
495*f81fb7c4SAndroid Build Coastguard Worker     EAS_U32 ticks;
496*f81fb7c4SAndroid Build Coastguard Worker 
497*f81fb7c4SAndroid Build Coastguard Worker     pSMFData = (S_SMF_DATA*) pInstData;
498*f81fb7c4SAndroid Build Coastguard Worker 
499*f81fb7c4SAndroid Build Coastguard Worker     /* reset time to zero */
500*f81fb7c4SAndroid Build Coastguard Worker     pSMFData->time = 0;
501*f81fb7c4SAndroid Build Coastguard Worker 
502*f81fb7c4SAndroid Build Coastguard Worker     /* reset the synth */
503*f81fb7c4SAndroid Build Coastguard Worker     VMReset(pEASData->pVoiceMgr, pSMFData->pSynth, EAS_TRUE);
504*f81fb7c4SAndroid Build Coastguard Worker 
505*f81fb7c4SAndroid Build Coastguard Worker     /* find the start of each track */
506*f81fb7c4SAndroid Build Coastguard Worker     ticks = 0x7fffffffL;
507*f81fb7c4SAndroid Build Coastguard Worker     pSMFData->nextStream = NULL;
508*f81fb7c4SAndroid Build Coastguard Worker     for (i = 0; i < pSMFData->numStreams; i++)
509*f81fb7c4SAndroid Build Coastguard Worker     {
510*f81fb7c4SAndroid Build Coastguard Worker 
511*f81fb7c4SAndroid Build Coastguard Worker         /* reset file position to first byte of data in track */
512*f81fb7c4SAndroid Build Coastguard Worker         if ((result = EAS_HWFileSeek(pEASData->hwInstData, pSMFData->streams[i].fileHandle, pSMFData->streams[i].startFilePos)) != EAS_SUCCESS)
513*f81fb7c4SAndroid Build Coastguard Worker             return result;
514*f81fb7c4SAndroid Build Coastguard Worker 
515*f81fb7c4SAndroid Build Coastguard Worker         /* initalize some data */
516*f81fb7c4SAndroid Build Coastguard Worker         pSMFData->streams[i].ticks = 0;
517*f81fb7c4SAndroid Build Coastguard Worker 
518*f81fb7c4SAndroid Build Coastguard Worker         /* initalize the MIDI parser data */
519*f81fb7c4SAndroid Build Coastguard Worker         EAS_InitMIDIStream(&pSMFData->streams[i].midiStream);
520*f81fb7c4SAndroid Build Coastguard Worker 
521*f81fb7c4SAndroid Build Coastguard Worker         /* parse the first delta time in each stream */
522*f81fb7c4SAndroid Build Coastguard Worker         if ((result = SMF_GetDeltaTime(pEASData->hwInstData,&pSMFData->streams[i])) != EAS_SUCCESS)
523*f81fb7c4SAndroid Build Coastguard Worker             return result;
524*f81fb7c4SAndroid Build Coastguard Worker         if (pSMFData->streams[i].ticks < ticks)
525*f81fb7c4SAndroid Build Coastguard Worker         {
526*f81fb7c4SAndroid Build Coastguard Worker             ticks = pSMFData->streams[i].ticks;
527*f81fb7c4SAndroid Build Coastguard Worker             pSMFData->nextStream = &pSMFData->streams[i];
528*f81fb7c4SAndroid Build Coastguard Worker         }
529*f81fb7c4SAndroid Build Coastguard Worker     }
530*f81fb7c4SAndroid Build Coastguard Worker 
531*f81fb7c4SAndroid Build Coastguard Worker 
532*f81fb7c4SAndroid Build Coastguard Worker     pSMFData->state = EAS_STATE_READY;
533*f81fb7c4SAndroid Build Coastguard Worker     return EAS_SUCCESS;
534*f81fb7c4SAndroid Build Coastguard Worker }
535*f81fb7c4SAndroid Build Coastguard Worker 
536*f81fb7c4SAndroid Build Coastguard Worker #ifdef JET_INTERFACE
537*f81fb7c4SAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
538*f81fb7c4SAndroid Build Coastguard Worker  * SMF_Pause()
539*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
540*f81fb7c4SAndroid Build Coastguard Worker  * Purpose:
541*f81fb7c4SAndroid Build Coastguard Worker  * Pauses the sequencer. Mutes all voices and sets state to pause.
542*f81fb7c4SAndroid Build Coastguard Worker  *
543*f81fb7c4SAndroid Build Coastguard Worker  * Inputs:
544*f81fb7c4SAndroid Build Coastguard Worker  * pEASData         - pointer to overall EAS data structure
545*f81fb7c4SAndroid Build Coastguard Worker  * handle           - pointer to file handle
546*f81fb7c4SAndroid Build Coastguard Worker  *
547*f81fb7c4SAndroid Build Coastguard Worker  * Outputs:
548*f81fb7c4SAndroid Build Coastguard Worker  *
549*f81fb7c4SAndroid Build Coastguard Worker  *
550*f81fb7c4SAndroid Build Coastguard Worker  * Side Effects:
551*f81fb7c4SAndroid Build Coastguard Worker  *
552*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
553*f81fb7c4SAndroid Build Coastguard Worker */
SMF_Pause(S_EAS_DATA * pEASData,EAS_VOID_PTR pInstData)554*f81fb7c4SAndroid Build Coastguard Worker EAS_RESULT SMF_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
555*f81fb7c4SAndroid Build Coastguard Worker {
556*f81fb7c4SAndroid Build Coastguard Worker     S_SMF_DATA *pSMFData;
557*f81fb7c4SAndroid Build Coastguard Worker 
558*f81fb7c4SAndroid Build Coastguard Worker     /* can't pause a stopped stream */
559*f81fb7c4SAndroid Build Coastguard Worker     pSMFData = (S_SMF_DATA*) pInstData;
560*f81fb7c4SAndroid Build Coastguard Worker     if (pSMFData->state == EAS_STATE_STOPPED)
561*f81fb7c4SAndroid Build Coastguard Worker         return EAS_ERROR_ALREADY_STOPPED;
562*f81fb7c4SAndroid Build Coastguard Worker 
563*f81fb7c4SAndroid Build Coastguard Worker     /* mute the synthesizer */
564*f81fb7c4SAndroid Build Coastguard Worker     VMMuteAllVoices(pEASData->pVoiceMgr, pSMFData->pSynth);
565*f81fb7c4SAndroid Build Coastguard Worker     pSMFData->state = EAS_STATE_PAUSING;
566*f81fb7c4SAndroid Build Coastguard Worker     return EAS_SUCCESS;
567*f81fb7c4SAndroid Build Coastguard Worker }
568*f81fb7c4SAndroid Build Coastguard Worker 
569*f81fb7c4SAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
570*f81fb7c4SAndroid Build Coastguard Worker  * SMF_Resume()
571*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
572*f81fb7c4SAndroid Build Coastguard Worker  * Purpose:
573*f81fb7c4SAndroid Build Coastguard Worker  * Resume playing after a pause, sets state back to playing.
574*f81fb7c4SAndroid Build Coastguard Worker  *
575*f81fb7c4SAndroid Build Coastguard Worker  * Inputs:
576*f81fb7c4SAndroid Build Coastguard Worker  * pEASData         - pointer to overall EAS data structure
577*f81fb7c4SAndroid Build Coastguard Worker  * handle           - pointer to file handle
578*f81fb7c4SAndroid Build Coastguard Worker  *
579*f81fb7c4SAndroid Build Coastguard Worker  * Outputs:
580*f81fb7c4SAndroid Build Coastguard Worker  *
581*f81fb7c4SAndroid Build Coastguard Worker  *
582*f81fb7c4SAndroid Build Coastguard Worker  * Side Effects:
583*f81fb7c4SAndroid Build Coastguard Worker  *
584*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
585*f81fb7c4SAndroid Build Coastguard Worker */
586*f81fb7c4SAndroid Build Coastguard Worker /*lint -esym(715, pEASData) reserved for future use */
SMF_Resume(S_EAS_DATA * pEASData,EAS_VOID_PTR pInstData)587*f81fb7c4SAndroid Build Coastguard Worker EAS_RESULT SMF_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
588*f81fb7c4SAndroid Build Coastguard Worker {
589*f81fb7c4SAndroid Build Coastguard Worker     S_SMF_DATA *pSMFData;
590*f81fb7c4SAndroid Build Coastguard Worker 
591*f81fb7c4SAndroid Build Coastguard Worker     /* can't resume a stopped stream */
592*f81fb7c4SAndroid Build Coastguard Worker     pSMFData = (S_SMF_DATA*) pInstData;
593*f81fb7c4SAndroid Build Coastguard Worker     if (pSMFData->state == EAS_STATE_STOPPED)
594*f81fb7c4SAndroid Build Coastguard Worker         return EAS_ERROR_ALREADY_STOPPED;
595*f81fb7c4SAndroid Build Coastguard Worker 
596*f81fb7c4SAndroid Build Coastguard Worker     /* nothing to do but resume playback */
597*f81fb7c4SAndroid Build Coastguard Worker     pSMFData->state = EAS_STATE_PLAY;
598*f81fb7c4SAndroid Build Coastguard Worker     return EAS_SUCCESS;
599*f81fb7c4SAndroid Build Coastguard Worker }
600*f81fb7c4SAndroid Build Coastguard Worker #endif
601*f81fb7c4SAndroid Build Coastguard Worker 
602*f81fb7c4SAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
603*f81fb7c4SAndroid Build Coastguard Worker  * SMF_SetData()
604*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
605*f81fb7c4SAndroid Build Coastguard Worker  * Purpose:
606*f81fb7c4SAndroid Build Coastguard Worker  * Sets parser parameters
607*f81fb7c4SAndroid Build Coastguard Worker  *
608*f81fb7c4SAndroid Build Coastguard Worker  * Inputs:
609*f81fb7c4SAndroid Build Coastguard Worker  * pEASData         - pointer to overall EAS data structure
610*f81fb7c4SAndroid Build Coastguard Worker  * handle           - pointer to file handle
611*f81fb7c4SAndroid Build Coastguard Worker  *
612*f81fb7c4SAndroid Build Coastguard Worker  * Outputs:
613*f81fb7c4SAndroid Build Coastguard Worker  *
614*f81fb7c4SAndroid Build Coastguard Worker  *
615*f81fb7c4SAndroid Build Coastguard Worker  * Side Effects:
616*f81fb7c4SAndroid Build Coastguard Worker  *
617*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
618*f81fb7c4SAndroid Build Coastguard Worker */
619*f81fb7c4SAndroid Build Coastguard Worker /*lint -esym(715, pEASData) reserved for future use */
SMF_SetData(S_EAS_DATA * pEASData,EAS_VOID_PTR pInstData,EAS_I32 param,EAS_I32 value)620*f81fb7c4SAndroid Build Coastguard Worker EAS_RESULT SMF_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value)
621*f81fb7c4SAndroid Build Coastguard Worker {
622*f81fb7c4SAndroid Build Coastguard Worker     S_SMF_DATA *pSMFData;
623*f81fb7c4SAndroid Build Coastguard Worker 
624*f81fb7c4SAndroid Build Coastguard Worker     pSMFData = (S_SMF_DATA*) pInstData;
625*f81fb7c4SAndroid Build Coastguard Worker     switch (param)
626*f81fb7c4SAndroid Build Coastguard Worker     {
627*f81fb7c4SAndroid Build Coastguard Worker 
628*f81fb7c4SAndroid Build Coastguard Worker         /* set metadata callback */
629*f81fb7c4SAndroid Build Coastguard Worker         case PARSER_DATA_METADATA_CB:
630*f81fb7c4SAndroid Build Coastguard Worker             EAS_HWMemCpy(&pSMFData->metadata, (void*) value, sizeof(S_METADATA_CB));
631*f81fb7c4SAndroid Build Coastguard Worker             break;
632*f81fb7c4SAndroid Build Coastguard Worker 
633*f81fb7c4SAndroid Build Coastguard Worker #ifdef JET_INTERFACE
634*f81fb7c4SAndroid Build Coastguard Worker         /* set jet segment and track ID of all tracks for callback function */
635*f81fb7c4SAndroid Build Coastguard Worker         case PARSER_DATA_JET_CB:
636*f81fb7c4SAndroid Build Coastguard Worker             {
637*f81fb7c4SAndroid Build Coastguard Worker                 EAS_U32 i;
638*f81fb7c4SAndroid Build Coastguard Worker                 EAS_U32 bit = (EAS_U32) value;
639*f81fb7c4SAndroid Build Coastguard Worker                 bit = (bit << JET_EVENT_SEG_SHIFT) & JET_EVENT_SEG_MASK;
640*f81fb7c4SAndroid Build Coastguard Worker                 for (i = 0; i < pSMFData->numStreams; i++)
641*f81fb7c4SAndroid Build Coastguard Worker                     pSMFData->streams[i].midiStream.jetData =
642*f81fb7c4SAndroid Build Coastguard Worker                         (pSMFData->streams[i].midiStream.jetData &
643*f81fb7c4SAndroid Build Coastguard Worker                         ~(JET_EVENT_TRACK_MASK | JET_EVENT_SEG_MASK)) |
644*f81fb7c4SAndroid Build Coastguard Worker                         i << JET_EVENT_TRACK_SHIFT | bit | MIDI_FLAGS_JET_CB;
645*f81fb7c4SAndroid Build Coastguard Worker                 pSMFData->flags |= SMF_FLAGS_JET_STREAM;
646*f81fb7c4SAndroid Build Coastguard Worker             }
647*f81fb7c4SAndroid Build Coastguard Worker             break;
648*f81fb7c4SAndroid Build Coastguard Worker 
649*f81fb7c4SAndroid Build Coastguard Worker         /* set state of all mute flags at once */
650*f81fb7c4SAndroid Build Coastguard Worker         case PARSER_DATA_MUTE_FLAGS:
651*f81fb7c4SAndroid Build Coastguard Worker             {
652*f81fb7c4SAndroid Build Coastguard Worker                 EAS_INT i;
653*f81fb7c4SAndroid Build Coastguard Worker                 EAS_U32 bit = (EAS_U32) value;
654*f81fb7c4SAndroid Build Coastguard Worker                 for (i = 0; i < pSMFData->numStreams; i++)
655*f81fb7c4SAndroid Build Coastguard Worker                 {
656*f81fb7c4SAndroid Build Coastguard Worker                     if (bit & 1)
657*f81fb7c4SAndroid Build Coastguard Worker                         pSMFData->streams[i].midiStream.jetData |= MIDI_FLAGS_JET_MUTE;
658*f81fb7c4SAndroid Build Coastguard Worker                     else
659*f81fb7c4SAndroid Build Coastguard Worker                         pSMFData->streams[i].midiStream.jetData &= ~MIDI_FLAGS_JET_MUTE;
660*f81fb7c4SAndroid Build Coastguard Worker                     bit >>= 1;
661*f81fb7c4SAndroid Build Coastguard Worker                 }
662*f81fb7c4SAndroid Build Coastguard Worker             }
663*f81fb7c4SAndroid Build Coastguard Worker             break;
664*f81fb7c4SAndroid Build Coastguard Worker 
665*f81fb7c4SAndroid Build Coastguard Worker         /* set track mute */
666*f81fb7c4SAndroid Build Coastguard Worker         case PARSER_DATA_SET_MUTE:
667*f81fb7c4SAndroid Build Coastguard Worker             if (value < pSMFData->numStreams)
668*f81fb7c4SAndroid Build Coastguard Worker                 pSMFData->streams[value].midiStream.jetData |= MIDI_FLAGS_JET_MUTE;
669*f81fb7c4SAndroid Build Coastguard Worker             else
670*f81fb7c4SAndroid Build Coastguard Worker                 return EAS_ERROR_PARAMETER_RANGE;
671*f81fb7c4SAndroid Build Coastguard Worker             break;
672*f81fb7c4SAndroid Build Coastguard Worker 
673*f81fb7c4SAndroid Build Coastguard Worker         /* clear track mute */
674*f81fb7c4SAndroid Build Coastguard Worker         case PARSER_DATA_CLEAR_MUTE:
675*f81fb7c4SAndroid Build Coastguard Worker             if (value < pSMFData->numStreams)
676*f81fb7c4SAndroid Build Coastguard Worker                 pSMFData->streams[value].midiStream.jetData &= ~MIDI_FLAGS_JET_MUTE;
677*f81fb7c4SAndroid Build Coastguard Worker             else
678*f81fb7c4SAndroid Build Coastguard Worker                 return EAS_ERROR_PARAMETER_RANGE;
679*f81fb7c4SAndroid Build Coastguard Worker             break;
680*f81fb7c4SAndroid Build Coastguard Worker #endif
681*f81fb7c4SAndroid Build Coastguard Worker 
682*f81fb7c4SAndroid Build Coastguard Worker         default:
683*f81fb7c4SAndroid Build Coastguard Worker             return EAS_ERROR_INVALID_PARAMETER;
684*f81fb7c4SAndroid Build Coastguard Worker     }
685*f81fb7c4SAndroid Build Coastguard Worker 
686*f81fb7c4SAndroid Build Coastguard Worker     return EAS_SUCCESS;
687*f81fb7c4SAndroid Build Coastguard Worker }
688*f81fb7c4SAndroid Build Coastguard Worker 
689*f81fb7c4SAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
690*f81fb7c4SAndroid Build Coastguard Worker  * SMF_GetData()
691*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
692*f81fb7c4SAndroid Build Coastguard Worker  * Purpose:
693*f81fb7c4SAndroid Build Coastguard Worker  * Retrieves parser parameters
694*f81fb7c4SAndroid Build Coastguard Worker  *
695*f81fb7c4SAndroid Build Coastguard Worker  * Inputs:
696*f81fb7c4SAndroid Build Coastguard Worker  * pEASData         - pointer to overall EAS data structure
697*f81fb7c4SAndroid Build Coastguard Worker  * handle           - pointer to file handle
698*f81fb7c4SAndroid Build Coastguard Worker  *
699*f81fb7c4SAndroid Build Coastguard Worker  * Outputs:
700*f81fb7c4SAndroid Build Coastguard Worker  *
701*f81fb7c4SAndroid Build Coastguard Worker  *
702*f81fb7c4SAndroid Build Coastguard Worker  * Side Effects:
703*f81fb7c4SAndroid Build Coastguard Worker  *
704*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
705*f81fb7c4SAndroid Build Coastguard Worker */
706*f81fb7c4SAndroid Build Coastguard Worker /*lint -esym(715, pEASData) reserved for future use */
SMF_GetData(S_EAS_DATA * pEASData,EAS_VOID_PTR pInstData,EAS_I32 param,EAS_I32 * pValue)707*f81fb7c4SAndroid Build Coastguard Worker EAS_RESULT SMF_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue)
708*f81fb7c4SAndroid Build Coastguard Worker {
709*f81fb7c4SAndroid Build Coastguard Worker     S_SMF_DATA *pSMFData;
710*f81fb7c4SAndroid Build Coastguard Worker 
711*f81fb7c4SAndroid Build Coastguard Worker     pSMFData = (S_SMF_DATA*) pInstData;
712*f81fb7c4SAndroid Build Coastguard Worker     switch (param)
713*f81fb7c4SAndroid Build Coastguard Worker     {
714*f81fb7c4SAndroid Build Coastguard Worker         /* return file type */
715*f81fb7c4SAndroid Build Coastguard Worker         case PARSER_DATA_FILE_TYPE:
716*f81fb7c4SAndroid Build Coastguard Worker             if (pSMFData->numStreams == 1)
717*f81fb7c4SAndroid Build Coastguard Worker                 *pValue = EAS_FILE_SMF0;
718*f81fb7c4SAndroid Build Coastguard Worker             else
719*f81fb7c4SAndroid Build Coastguard Worker                 *pValue = EAS_FILE_SMF1;
720*f81fb7c4SAndroid Build Coastguard Worker             break;
721*f81fb7c4SAndroid Build Coastguard Worker 
722*f81fb7c4SAndroid Build Coastguard Worker /* now handled in eas_public.c */
723*f81fb7c4SAndroid Build Coastguard Worker #if 0
724*f81fb7c4SAndroid Build Coastguard Worker         case PARSER_DATA_POLYPHONY:
725*f81fb7c4SAndroid Build Coastguard Worker             if (pSMFData->pSynth)
726*f81fb7c4SAndroid Build Coastguard Worker                 VMGetPolyphony(pEASData->pVoiceMgr, pSMFData->pSynth, pValue);
727*f81fb7c4SAndroid Build Coastguard Worker             else
728*f81fb7c4SAndroid Build Coastguard Worker                 return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
729*f81fb7c4SAndroid Build Coastguard Worker             break;
730*f81fb7c4SAndroid Build Coastguard Worker 
731*f81fb7c4SAndroid Build Coastguard Worker         case PARSER_DATA_PRIORITY:
732*f81fb7c4SAndroid Build Coastguard Worker             if (pSMFData->pSynth)
733*f81fb7c4SAndroid Build Coastguard Worker                 VMGetPriority(pEASData->pVoiceMgr, pSMFData->pSynth, pValue);
734*f81fb7c4SAndroid Build Coastguard Worker             break;
735*f81fb7c4SAndroid Build Coastguard Worker 
736*f81fb7c4SAndroid Build Coastguard Worker         /* set transposition */
737*f81fb7c4SAndroid Build Coastguard Worker         case PARSER_DATA_TRANSPOSITION:
738*f81fb7c4SAndroid Build Coastguard Worker             *pValue = pSMFData->transposition;
739*f81fb7c4SAndroid Build Coastguard Worker             break;
740*f81fb7c4SAndroid Build Coastguard Worker #endif
741*f81fb7c4SAndroid Build Coastguard Worker 
742*f81fb7c4SAndroid Build Coastguard Worker         case PARSER_DATA_SYNTH_HANDLE:
743*f81fb7c4SAndroid Build Coastguard Worker             *pValue = (EAS_I32) pSMFData->pSynth;
744*f81fb7c4SAndroid Build Coastguard Worker             break;
745*f81fb7c4SAndroid Build Coastguard Worker 
746*f81fb7c4SAndroid Build Coastguard Worker         default:
747*f81fb7c4SAndroid Build Coastguard Worker             return EAS_ERROR_INVALID_PARAMETER;
748*f81fb7c4SAndroid Build Coastguard Worker     }
749*f81fb7c4SAndroid Build Coastguard Worker 
750*f81fb7c4SAndroid Build Coastguard Worker     return EAS_SUCCESS;
751*f81fb7c4SAndroid Build Coastguard Worker }
752*f81fb7c4SAndroid Build Coastguard Worker 
753*f81fb7c4SAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
754*f81fb7c4SAndroid Build Coastguard Worker  * SMF_GetVarLenData()
755*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
756*f81fb7c4SAndroid Build Coastguard Worker  * Purpose:
757*f81fb7c4SAndroid Build Coastguard Worker  * Reads a varible length quantity from an SMF file
758*f81fb7c4SAndroid Build Coastguard Worker  *
759*f81fb7c4SAndroid Build Coastguard Worker  * Inputs:
760*f81fb7c4SAndroid Build Coastguard Worker  *
761*f81fb7c4SAndroid Build Coastguard Worker  *
762*f81fb7c4SAndroid Build Coastguard Worker  * Outputs:
763*f81fb7c4SAndroid Build Coastguard Worker  *
764*f81fb7c4SAndroid Build Coastguard Worker  *
765*f81fb7c4SAndroid Build Coastguard Worker  * Side Effects:
766*f81fb7c4SAndroid Build Coastguard Worker  *
767*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
768*f81fb7c4SAndroid Build Coastguard Worker */
SMF_GetVarLenData(EAS_HW_DATA_HANDLE hwInstData,EAS_FILE_HANDLE fileHandle,EAS_U32 * pData)769*f81fb7c4SAndroid Build Coastguard Worker static EAS_RESULT SMF_GetVarLenData (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_U32 *pData)
770*f81fb7c4SAndroid Build Coastguard Worker {
771*f81fb7c4SAndroid Build Coastguard Worker     EAS_RESULT result;
772*f81fb7c4SAndroid Build Coastguard Worker     EAS_U32 data;
773*f81fb7c4SAndroid Build Coastguard Worker     EAS_U8 c;
774*f81fb7c4SAndroid Build Coastguard Worker 
775*f81fb7c4SAndroid Build Coastguard Worker     /* read until bit 7 is zero */
776*f81fb7c4SAndroid Build Coastguard Worker     data = 0;
777*f81fb7c4SAndroid Build Coastguard Worker     do
778*f81fb7c4SAndroid Build Coastguard Worker     {
779*f81fb7c4SAndroid Build Coastguard Worker         if ((result = EAS_HWGetByte(hwInstData, fileHandle,&c)) != EAS_SUCCESS)
780*f81fb7c4SAndroid Build Coastguard Worker             return result;
781*f81fb7c4SAndroid Build Coastguard Worker         data = (data << 7) | (c & 0x7f);
782*f81fb7c4SAndroid Build Coastguard Worker     } while (c & 0x80);
783*f81fb7c4SAndroid Build Coastguard Worker     *pData = data;
784*f81fb7c4SAndroid Build Coastguard Worker     return EAS_SUCCESS;
785*f81fb7c4SAndroid Build Coastguard Worker }
786*f81fb7c4SAndroid Build Coastguard Worker 
787*f81fb7c4SAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
788*f81fb7c4SAndroid Build Coastguard Worker  * SMF_GetDeltaTime()
789*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
790*f81fb7c4SAndroid Build Coastguard Worker  * Purpose:
791*f81fb7c4SAndroid Build Coastguard Worker  * Reads a varible length quantity from an SMF file
792*f81fb7c4SAndroid Build Coastguard Worker  *
793*f81fb7c4SAndroid Build Coastguard Worker  * Inputs:
794*f81fb7c4SAndroid Build Coastguard Worker  *
795*f81fb7c4SAndroid Build Coastguard Worker  *
796*f81fb7c4SAndroid Build Coastguard Worker  * Outputs:
797*f81fb7c4SAndroid Build Coastguard Worker  *
798*f81fb7c4SAndroid Build Coastguard Worker  *
799*f81fb7c4SAndroid Build Coastguard Worker  * Side Effects:
800*f81fb7c4SAndroid Build Coastguard Worker  *
801*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
802*f81fb7c4SAndroid Build Coastguard Worker */
SMF_GetDeltaTime(EAS_HW_DATA_HANDLE hwInstData,S_SMF_STREAM * pSMFStream)803*f81fb7c4SAndroid Build Coastguard Worker static EAS_RESULT SMF_GetDeltaTime (EAS_HW_DATA_HANDLE hwInstData, S_SMF_STREAM *pSMFStream)
804*f81fb7c4SAndroid Build Coastguard Worker {
805*f81fb7c4SAndroid Build Coastguard Worker     EAS_RESULT result;
806*f81fb7c4SAndroid Build Coastguard Worker     EAS_U32 ticks;
807*f81fb7c4SAndroid Build Coastguard Worker 
808*f81fb7c4SAndroid Build Coastguard Worker     if ((result = SMF_GetVarLenData(hwInstData, pSMFStream->fileHandle, &ticks)) != EAS_SUCCESS)
809*f81fb7c4SAndroid Build Coastguard Worker         return result;
810*f81fb7c4SAndroid Build Coastguard Worker 
811*f81fb7c4SAndroid Build Coastguard Worker     /* number of ticks must not exceed 32-bits */
812*f81fb7c4SAndroid Build Coastguard Worker     if (ticks > (UINT32_MAX - pSMFStream->ticks))
813*f81fb7c4SAndroid Build Coastguard Worker         return EAS_ERROR_FILE_FORMAT;
814*f81fb7c4SAndroid Build Coastguard Worker 
815*f81fb7c4SAndroid Build Coastguard Worker     pSMFStream->ticks += ticks;
816*f81fb7c4SAndroid Build Coastguard Worker     return EAS_SUCCESS;
817*f81fb7c4SAndroid Build Coastguard Worker }
818*f81fb7c4SAndroid Build Coastguard Worker 
819*f81fb7c4SAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
820*f81fb7c4SAndroid Build Coastguard Worker  * SMF_ParseMetaEvent()
821*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
822*f81fb7c4SAndroid Build Coastguard Worker  * Purpose:
823*f81fb7c4SAndroid Build Coastguard Worker  * Reads a varible length quantity from an SMF file
824*f81fb7c4SAndroid Build Coastguard Worker  *
825*f81fb7c4SAndroid Build Coastguard Worker  * Inputs:
826*f81fb7c4SAndroid Build Coastguard Worker  *
827*f81fb7c4SAndroid Build Coastguard Worker  *
828*f81fb7c4SAndroid Build Coastguard Worker  * Outputs:
829*f81fb7c4SAndroid Build Coastguard Worker  *
830*f81fb7c4SAndroid Build Coastguard Worker  *
831*f81fb7c4SAndroid Build Coastguard Worker  * Side Effects:
832*f81fb7c4SAndroid Build Coastguard Worker  *
833*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
834*f81fb7c4SAndroid Build Coastguard Worker */
SMF_ParseMetaEvent(S_EAS_DATA * pEASData,S_SMF_DATA * pSMFData,S_SMF_STREAM * pSMFStream)835*f81fb7c4SAndroid Build Coastguard Worker static EAS_RESULT SMF_ParseMetaEvent (S_EAS_DATA *pEASData, S_SMF_DATA *pSMFData, S_SMF_STREAM *pSMFStream)
836*f81fb7c4SAndroid Build Coastguard Worker {
837*f81fb7c4SAndroid Build Coastguard Worker     EAS_RESULT result;
838*f81fb7c4SAndroid Build Coastguard Worker     EAS_U32 len;
839*f81fb7c4SAndroid Build Coastguard Worker     EAS_I32 pos;
840*f81fb7c4SAndroid Build Coastguard Worker     EAS_U32 temp;
841*f81fb7c4SAndroid Build Coastguard Worker     EAS_U8 c;
842*f81fb7c4SAndroid Build Coastguard Worker 
843*f81fb7c4SAndroid Build Coastguard Worker     /* get the meta-event type */
844*f81fb7c4SAndroid Build Coastguard Worker     if ((result = EAS_HWGetByte(pEASData->hwInstData, pSMFStream->fileHandle, &c)) != EAS_SUCCESS)
845*f81fb7c4SAndroid Build Coastguard Worker         return result;
846*f81fb7c4SAndroid Build Coastguard Worker 
847*f81fb7c4SAndroid Build Coastguard Worker     /* get the length */
848*f81fb7c4SAndroid Build Coastguard Worker     if ((result = SMF_GetVarLenData(pEASData->hwInstData, pSMFStream->fileHandle, &len)) != EAS_SUCCESS)
849*f81fb7c4SAndroid Build Coastguard Worker         return result;
850*f81fb7c4SAndroid Build Coastguard Worker 
851*f81fb7c4SAndroid Build Coastguard Worker     /* get the current file position so we can skip the event */
852*f81fb7c4SAndroid Build Coastguard Worker     if ((result = EAS_HWFilePos(pEASData->hwInstData, pSMFStream->fileHandle, &pos)) != EAS_SUCCESS)
853*f81fb7c4SAndroid Build Coastguard Worker         return result;
854*f81fb7c4SAndroid Build Coastguard Worker 
855*f81fb7c4SAndroid Build Coastguard Worker     /* prevent a large unsigned length from being treated as a negative length */
856*f81fb7c4SAndroid Build Coastguard Worker     if ((EAS_I32) len < 0) {
857*f81fb7c4SAndroid Build Coastguard Worker         /* note that EAS_I32 is a long, which can be 64-bits on some computers */
858*f81fb7c4SAndroid Build Coastguard Worker         ALOGE("%s() negative len = %ld", __func__, (long) len);
859*f81fb7c4SAndroid Build Coastguard Worker         android_errorWriteLog(0x534e4554, "68953854");
860*f81fb7c4SAndroid Build Coastguard Worker         return EAS_ERROR_FILE_FORMAT;
861*f81fb7c4SAndroid Build Coastguard Worker     }
862*f81fb7c4SAndroid Build Coastguard Worker     /* prevent numeric overflow caused by a very large len, assume pos > 0 */
863*f81fb7c4SAndroid Build Coastguard Worker     const EAS_I32 EAS_I32_MAX = 0x7FFFFFFF;
864*f81fb7c4SAndroid Build Coastguard Worker     if ((EAS_I32) len > (EAS_I32_MAX - pos)) {
865*f81fb7c4SAndroid Build Coastguard Worker         ALOGE("%s() too large len = %ld", __func__, (long) len);
866*f81fb7c4SAndroid Build Coastguard Worker         android_errorWriteLog(0x534e4554, "68953854");
867*f81fb7c4SAndroid Build Coastguard Worker         return EAS_ERROR_FILE_FORMAT;
868*f81fb7c4SAndroid Build Coastguard Worker     }
869*f81fb7c4SAndroid Build Coastguard Worker 
870*f81fb7c4SAndroid Build Coastguard Worker     pos += (EAS_I32) len;
871*f81fb7c4SAndroid Build Coastguard Worker 
872*f81fb7c4SAndroid Build Coastguard Worker     /* end of track? */
873*f81fb7c4SAndroid Build Coastguard Worker     if (c == SMF_META_END_OF_TRACK)
874*f81fb7c4SAndroid Build Coastguard Worker     {
875*f81fb7c4SAndroid Build Coastguard Worker         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Meta-event: end of track\n", c, len); */ }
876*f81fb7c4SAndroid Build Coastguard Worker         pSMFStream->ticks = SMF_END_OF_TRACK;
877*f81fb7c4SAndroid Build Coastguard Worker     }
878*f81fb7c4SAndroid Build Coastguard Worker 
879*f81fb7c4SAndroid Build Coastguard Worker     /* tempo event? */
880*f81fb7c4SAndroid Build Coastguard Worker     else if (c == SMF_META_TEMPO)
881*f81fb7c4SAndroid Build Coastguard Worker     {
882*f81fb7c4SAndroid Build Coastguard Worker         /* read the 3-byte timebase value */
883*f81fb7c4SAndroid Build Coastguard Worker         temp = 0;
884*f81fb7c4SAndroid Build Coastguard Worker         while (len)
885*f81fb7c4SAndroid Build Coastguard Worker         {
886*f81fb7c4SAndroid Build Coastguard Worker             len--;
887*f81fb7c4SAndroid Build Coastguard Worker             if ((result = EAS_HWGetByte(pEASData->hwInstData, pSMFStream->fileHandle, &c)) != EAS_SUCCESS)
888*f81fb7c4SAndroid Build Coastguard Worker                 return result;
889*f81fb7c4SAndroid Build Coastguard Worker             temp = (temp << 8) | c;
890*f81fb7c4SAndroid Build Coastguard Worker         }
891*f81fb7c4SAndroid Build Coastguard Worker         {
892*f81fb7c4SAndroid Build Coastguard Worker             // pSMFData->tickConv = (EAS_U16) (((temp * 1024) / pSMFData->ppqn + 500) / 1000);
893*f81fb7c4SAndroid Build Coastguard Worker             uint64_t temp64;
894*f81fb7c4SAndroid Build Coastguard Worker             if (__builtin_mul_overflow(temp, 1024u, &temp64) ||
895*f81fb7c4SAndroid Build Coastguard Worker                     pSMFData->ppqn == 0 ||
896*f81fb7c4SAndroid Build Coastguard Worker                     (temp64 /= pSMFData->ppqn, false) ||
897*f81fb7c4SAndroid Build Coastguard Worker                     __builtin_add_overflow(temp64, 500, &temp64) ||
898*f81fb7c4SAndroid Build Coastguard Worker                     (temp64 /= 1000, false) ||
899*f81fb7c4SAndroid Build Coastguard Worker                     temp64 > 65535) {
900*f81fb7c4SAndroid Build Coastguard Worker                 pSMFData->tickConv = 65535;
901*f81fb7c4SAndroid Build Coastguard Worker             } else {
902*f81fb7c4SAndroid Build Coastguard Worker                 pSMFData->tickConv = (EAS_U16) temp64;
903*f81fb7c4SAndroid Build Coastguard Worker             }
904*f81fb7c4SAndroid Build Coastguard Worker         }
905*f81fb7c4SAndroid Build Coastguard Worker         pSMFData->flags |= SMF_FLAGS_HAS_TEMPO;
906*f81fb7c4SAndroid Build Coastguard Worker     }
907*f81fb7c4SAndroid Build Coastguard Worker 
908*f81fb7c4SAndroid Build Coastguard Worker     /* check for time signature - see iMelody spec V1.4 section 4.1.2.2.3.6 */
909*f81fb7c4SAndroid Build Coastguard Worker     else if (c == SMF_META_TIME_SIGNATURE)
910*f81fb7c4SAndroid Build Coastguard Worker     {
911*f81fb7c4SAndroid Build Coastguard Worker         pSMFData->flags |= SMF_FLAGS_HAS_TIME_SIG;
912*f81fb7c4SAndroid Build Coastguard Worker     }
913*f81fb7c4SAndroid Build Coastguard Worker 
914*f81fb7c4SAndroid Build Coastguard Worker     /* if the host has registered a metadata callback return the metadata */
915*f81fb7c4SAndroid Build Coastguard Worker     else if (pSMFData->metadata.callback)
916*f81fb7c4SAndroid Build Coastguard Worker     {
917*f81fb7c4SAndroid Build Coastguard Worker         EAS_I32 readLen;
918*f81fb7c4SAndroid Build Coastguard Worker         E_EAS_METADATA_TYPE metaType;
919*f81fb7c4SAndroid Build Coastguard Worker 
920*f81fb7c4SAndroid Build Coastguard Worker         metaType = EAS_METADATA_UNKNOWN;
921*f81fb7c4SAndroid Build Coastguard Worker 
922*f81fb7c4SAndroid Build Coastguard Worker         /* only process title on the first track */
923*f81fb7c4SAndroid Build Coastguard Worker         if (c == SMF_META_SEQTRK_NAME)
924*f81fb7c4SAndroid Build Coastguard Worker             metaType = EAS_METADATA_TITLE;
925*f81fb7c4SAndroid Build Coastguard Worker         else if (c == SMF_META_TEXT)
926*f81fb7c4SAndroid Build Coastguard Worker             metaType = EAS_METADATA_TEXT;
927*f81fb7c4SAndroid Build Coastguard Worker         else if (c == SMF_META_COPYRIGHT)
928*f81fb7c4SAndroid Build Coastguard Worker             metaType = EAS_METADATA_COPYRIGHT;
929*f81fb7c4SAndroid Build Coastguard Worker         else if (c == SMF_META_LYRIC)
930*f81fb7c4SAndroid Build Coastguard Worker             metaType = EAS_METADATA_LYRIC;
931*f81fb7c4SAndroid Build Coastguard Worker 
932*f81fb7c4SAndroid Build Coastguard Worker         if (metaType != EAS_METADATA_UNKNOWN)
933*f81fb7c4SAndroid Build Coastguard Worker         {
934*f81fb7c4SAndroid Build Coastguard Worker             readLen = pSMFData->metadata.bufferSize - 1;
935*f81fb7c4SAndroid Build Coastguard Worker             if ((EAS_I32) len < readLen)
936*f81fb7c4SAndroid Build Coastguard Worker                 readLen = (EAS_I32) len;
937*f81fb7c4SAndroid Build Coastguard Worker             if ((result = EAS_HWReadFile(pEASData->hwInstData, pSMFStream->fileHandle, pSMFData->metadata.buffer, readLen, &readLen)) != EAS_SUCCESS)
938*f81fb7c4SAndroid Build Coastguard Worker                 return result;
939*f81fb7c4SAndroid Build Coastguard Worker             pSMFData->metadata.buffer[readLen] = 0;
940*f81fb7c4SAndroid Build Coastguard Worker             pSMFData->metadata.callback(metaType, pSMFData->metadata.buffer, pSMFData->metadata.pUserData);
941*f81fb7c4SAndroid Build Coastguard Worker         }
942*f81fb7c4SAndroid Build Coastguard Worker     }
943*f81fb7c4SAndroid Build Coastguard Worker 
944*f81fb7c4SAndroid Build Coastguard Worker     /* position file to next event - in case we ignored all or part of the meta-event */
945*f81fb7c4SAndroid Build Coastguard Worker     if ((result = EAS_HWFileSeek(pEASData->hwInstData, pSMFStream->fileHandle, pos)) != EAS_SUCCESS)
946*f81fb7c4SAndroid Build Coastguard Worker         return result;
947*f81fb7c4SAndroid Build Coastguard Worker 
948*f81fb7c4SAndroid Build Coastguard Worker     { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Meta-event: type=%02x, len=%d\n", c, len); */ }
949*f81fb7c4SAndroid Build Coastguard Worker     return EAS_SUCCESS;
950*f81fb7c4SAndroid Build Coastguard Worker }
951*f81fb7c4SAndroid Build Coastguard Worker 
952*f81fb7c4SAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
953*f81fb7c4SAndroid Build Coastguard Worker  * SMF_ParseSysEx()
954*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
955*f81fb7c4SAndroid Build Coastguard Worker  * Purpose:
956*f81fb7c4SAndroid Build Coastguard Worker  * Reads a varible length quantity from an SMF file
957*f81fb7c4SAndroid Build Coastguard Worker  *
958*f81fb7c4SAndroid Build Coastguard Worker  * Inputs:
959*f81fb7c4SAndroid Build Coastguard Worker  *
960*f81fb7c4SAndroid Build Coastguard Worker  *
961*f81fb7c4SAndroid Build Coastguard Worker  * Outputs:
962*f81fb7c4SAndroid Build Coastguard Worker  *
963*f81fb7c4SAndroid Build Coastguard Worker  *
964*f81fb7c4SAndroid Build Coastguard Worker  * Side Effects:
965*f81fb7c4SAndroid Build Coastguard Worker  *
966*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
967*f81fb7c4SAndroid Build Coastguard Worker */
SMF_ParseSysEx(S_EAS_DATA * pEASData,S_SMF_DATA * pSMFData,S_SMF_STREAM * pSMFStream,EAS_U8 f0,EAS_INT parserMode)968*f81fb7c4SAndroid Build Coastguard Worker static EAS_RESULT SMF_ParseSysEx (S_EAS_DATA *pEASData, S_SMF_DATA *pSMFData, S_SMF_STREAM *pSMFStream, EAS_U8 f0, EAS_INT parserMode)
969*f81fb7c4SAndroid Build Coastguard Worker {
970*f81fb7c4SAndroid Build Coastguard Worker     EAS_RESULT result;
971*f81fb7c4SAndroid Build Coastguard Worker     EAS_U32 len;
972*f81fb7c4SAndroid Build Coastguard Worker     EAS_U8 c;
973*f81fb7c4SAndroid Build Coastguard Worker 
974*f81fb7c4SAndroid Build Coastguard Worker     /* get the length */
975*f81fb7c4SAndroid Build Coastguard Worker     if ((result = SMF_GetVarLenData(pEASData->hwInstData, pSMFStream->fileHandle, &len)) != EAS_SUCCESS)
976*f81fb7c4SAndroid Build Coastguard Worker         return result;
977*f81fb7c4SAndroid Build Coastguard Worker 
978*f81fb7c4SAndroid Build Coastguard Worker     /* start of SysEx message? */
979*f81fb7c4SAndroid Build Coastguard Worker     if (f0 == 0xf0)
980*f81fb7c4SAndroid Build Coastguard Worker     {
981*f81fb7c4SAndroid Build Coastguard Worker         if ((result = EAS_ParseMIDIStream(pEASData, pSMFData->pSynth, &pSMFStream->midiStream, f0, parserMode)) != EAS_SUCCESS)
982*f81fb7c4SAndroid Build Coastguard Worker             return result;
983*f81fb7c4SAndroid Build Coastguard Worker     }
984*f81fb7c4SAndroid Build Coastguard Worker 
985*f81fb7c4SAndroid Build Coastguard Worker     /* feed the SysEx to the stream parser */
986*f81fb7c4SAndroid Build Coastguard Worker     while (len)
987*f81fb7c4SAndroid Build Coastguard Worker     {
988*f81fb7c4SAndroid Build Coastguard Worker         len--;
989*f81fb7c4SAndroid Build Coastguard Worker         if ((result = EAS_HWGetByte(pEASData->hwInstData, pSMFStream->fileHandle, &c)) != EAS_SUCCESS)
990*f81fb7c4SAndroid Build Coastguard Worker             return result;
991*f81fb7c4SAndroid Build Coastguard Worker         if ((result = EAS_ParseMIDIStream(pEASData, pSMFData->pSynth, &pSMFStream->midiStream, c, parserMode)) != EAS_SUCCESS)
992*f81fb7c4SAndroid Build Coastguard Worker             return result;
993*f81fb7c4SAndroid Build Coastguard Worker 
994*f81fb7c4SAndroid Build Coastguard Worker         /* check for GM system ON */
995*f81fb7c4SAndroid Build Coastguard Worker         if (pSMFStream->midiStream.flags & MIDI_FLAG_GM_ON)
996*f81fb7c4SAndroid Build Coastguard Worker             pSMFData->flags |= SMF_FLAGS_HAS_GM_ON;
997*f81fb7c4SAndroid Build Coastguard Worker     }
998*f81fb7c4SAndroid Build Coastguard Worker 
999*f81fb7c4SAndroid Build Coastguard Worker     return EAS_SUCCESS;
1000*f81fb7c4SAndroid Build Coastguard Worker }
1001*f81fb7c4SAndroid Build Coastguard Worker 
1002*f81fb7c4SAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
1003*f81fb7c4SAndroid Build Coastguard Worker  * SMF_ParseEvent()
1004*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
1005*f81fb7c4SAndroid Build Coastguard Worker  * Purpose:
1006*f81fb7c4SAndroid Build Coastguard Worker  * Reads a varible length quantity from an SMF file
1007*f81fb7c4SAndroid Build Coastguard Worker  *
1008*f81fb7c4SAndroid Build Coastguard Worker  * Inputs:
1009*f81fb7c4SAndroid Build Coastguard Worker  *
1010*f81fb7c4SAndroid Build Coastguard Worker  *
1011*f81fb7c4SAndroid Build Coastguard Worker  * Outputs:
1012*f81fb7c4SAndroid Build Coastguard Worker  *
1013*f81fb7c4SAndroid Build Coastguard Worker  *
1014*f81fb7c4SAndroid Build Coastguard Worker  * Side Effects:
1015*f81fb7c4SAndroid Build Coastguard Worker  *
1016*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
1017*f81fb7c4SAndroid Build Coastguard Worker */
SMF_ParseEvent(S_EAS_DATA * pEASData,S_SMF_DATA * pSMFData,S_SMF_STREAM * pSMFStream,EAS_INT parserMode)1018*f81fb7c4SAndroid Build Coastguard Worker static EAS_RESULT SMF_ParseEvent (S_EAS_DATA *pEASData, S_SMF_DATA *pSMFData, S_SMF_STREAM *pSMFStream, EAS_INT parserMode)
1019*f81fb7c4SAndroid Build Coastguard Worker {
1020*f81fb7c4SAndroid Build Coastguard Worker     EAS_RESULT result;
1021*f81fb7c4SAndroid Build Coastguard Worker     EAS_U8 c;
1022*f81fb7c4SAndroid Build Coastguard Worker 
1023*f81fb7c4SAndroid Build Coastguard Worker     /* get the event type */
1024*f81fb7c4SAndroid Build Coastguard Worker     if ((result = EAS_HWGetByte(pEASData->hwInstData, pSMFStream->fileHandle, &c)) != EAS_SUCCESS)
1025*f81fb7c4SAndroid Build Coastguard Worker         return result;
1026*f81fb7c4SAndroid Build Coastguard Worker 
1027*f81fb7c4SAndroid Build Coastguard Worker     /* parse meta-event */
1028*f81fb7c4SAndroid Build Coastguard Worker     if (c == 0xff)
1029*f81fb7c4SAndroid Build Coastguard Worker     {
1030*f81fb7c4SAndroid Build Coastguard Worker         if ((result = SMF_ParseMetaEvent(pEASData, pSMFData, pSMFStream)) != EAS_SUCCESS)
1031*f81fb7c4SAndroid Build Coastguard Worker             return result;
1032*f81fb7c4SAndroid Build Coastguard Worker     }
1033*f81fb7c4SAndroid Build Coastguard Worker 
1034*f81fb7c4SAndroid Build Coastguard Worker     /* parse SysEx */
1035*f81fb7c4SAndroid Build Coastguard Worker     else if ((c == 0xf0) || (c == 0xf7))
1036*f81fb7c4SAndroid Build Coastguard Worker     {
1037*f81fb7c4SAndroid Build Coastguard Worker         if ((result = SMF_ParseSysEx(pEASData, pSMFData, pSMFStream, c, parserMode)) != EAS_SUCCESS)
1038*f81fb7c4SAndroid Build Coastguard Worker             return result;
1039*f81fb7c4SAndroid Build Coastguard Worker     }
1040*f81fb7c4SAndroid Build Coastguard Worker 
1041*f81fb7c4SAndroid Build Coastguard Worker     /* parse MIDI message */
1042*f81fb7c4SAndroid Build Coastguard Worker     else
1043*f81fb7c4SAndroid Build Coastguard Worker     {
1044*f81fb7c4SAndroid Build Coastguard Worker         if ((result = EAS_ParseMIDIStream(pEASData, pSMFData->pSynth, &pSMFStream->midiStream, c, parserMode)) != EAS_SUCCESS)
1045*f81fb7c4SAndroid Build Coastguard Worker             return result;
1046*f81fb7c4SAndroid Build Coastguard Worker 
1047*f81fb7c4SAndroid Build Coastguard Worker         /* keep streaming data to the MIDI parser until the message is complete */
1048*f81fb7c4SAndroid Build Coastguard Worker         while (pSMFStream->midiStream.pending)
1049*f81fb7c4SAndroid Build Coastguard Worker         {
1050*f81fb7c4SAndroid Build Coastguard Worker             if ((result = EAS_HWGetByte(pEASData->hwInstData, pSMFStream->fileHandle, &c)) != EAS_SUCCESS)
1051*f81fb7c4SAndroid Build Coastguard Worker                 return result;
1052*f81fb7c4SAndroid Build Coastguard Worker             if ((result = EAS_ParseMIDIStream(pEASData, pSMFData->pSynth, &pSMFStream->midiStream, c, parserMode)) != EAS_SUCCESS)
1053*f81fb7c4SAndroid Build Coastguard Worker                 return result;
1054*f81fb7c4SAndroid Build Coastguard Worker         }
1055*f81fb7c4SAndroid Build Coastguard Worker 
1056*f81fb7c4SAndroid Build Coastguard Worker     }
1057*f81fb7c4SAndroid Build Coastguard Worker 
1058*f81fb7c4SAndroid Build Coastguard Worker     /* chase mode logic */
1059*f81fb7c4SAndroid Build Coastguard Worker     if (pSMFData->time == 0)
1060*f81fb7c4SAndroid Build Coastguard Worker     {
1061*f81fb7c4SAndroid Build Coastguard Worker         if (pSMFData->flags & SMF_FLAGS_CHASE_MODE)
1062*f81fb7c4SAndroid Build Coastguard Worker         {
1063*f81fb7c4SAndroid Build Coastguard Worker             if (pSMFStream->midiStream.flags & MIDI_FLAG_FIRST_NOTE)
1064*f81fb7c4SAndroid Build Coastguard Worker                 pSMFData->flags &= ~SMF_FLAGS_CHASE_MODE;
1065*f81fb7c4SAndroid Build Coastguard Worker         }
1066*f81fb7c4SAndroid Build Coastguard Worker         else if ((pSMFData->flags & SMF_FLAGS_SETUP_BAR) == SMF_FLAGS_SETUP_BAR)
1067*f81fb7c4SAndroid Build Coastguard Worker             pSMFData->flags = (pSMFData->flags & ~SMF_FLAGS_SETUP_BAR) | SMF_FLAGS_CHASE_MODE;
1068*f81fb7c4SAndroid Build Coastguard Worker     }
1069*f81fb7c4SAndroid Build Coastguard Worker 
1070*f81fb7c4SAndroid Build Coastguard Worker     return EAS_SUCCESS;
1071*f81fb7c4SAndroid Build Coastguard Worker }
1072*f81fb7c4SAndroid Build Coastguard Worker 
1073*f81fb7c4SAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
1074*f81fb7c4SAndroid Build Coastguard Worker  * SMF_ParseHeader()
1075*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
1076*f81fb7c4SAndroid Build Coastguard Worker  * Purpose:
1077*f81fb7c4SAndroid Build Coastguard Worker  * Parses the header of an SMF file, allocates memory the stream parsers and initializes the
1078*f81fb7c4SAndroid Build Coastguard Worker  * stream parsers.
1079*f81fb7c4SAndroid Build Coastguard Worker  *
1080*f81fb7c4SAndroid Build Coastguard Worker  * Inputs:
1081*f81fb7c4SAndroid Build Coastguard Worker  * pEASData         - pointer to overall EAS data structure
1082*f81fb7c4SAndroid Build Coastguard Worker  * pSMFData         - pointer to parser instance data
1083*f81fb7c4SAndroid Build Coastguard Worker  * fileHandle       - file handle
1084*f81fb7c4SAndroid Build Coastguard Worker  * fileOffset       - offset in the file where the header data starts, usually 0
1085*f81fb7c4SAndroid Build Coastguard Worker  *
1086*f81fb7c4SAndroid Build Coastguard Worker  *
1087*f81fb7c4SAndroid Build Coastguard Worker  * Outputs:
1088*f81fb7c4SAndroid Build Coastguard Worker  *
1089*f81fb7c4SAndroid Build Coastguard Worker  *
1090*f81fb7c4SAndroid Build Coastguard Worker  * Side Effects:
1091*f81fb7c4SAndroid Build Coastguard Worker  *
1092*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
1093*f81fb7c4SAndroid Build Coastguard Worker */
1094*f81fb7c4SAndroid Build Coastguard Worker /*lint -e{801} we know that 'goto' is deprecated - but it's cleaner in this case */
SMF_ParseHeader(EAS_HW_DATA_HANDLE hwInstData,S_SMF_DATA * pSMFData)1095*f81fb7c4SAndroid Build Coastguard Worker EAS_RESULT SMF_ParseHeader (EAS_HW_DATA_HANDLE hwInstData, S_SMF_DATA *pSMFData)
1096*f81fb7c4SAndroid Build Coastguard Worker {
1097*f81fb7c4SAndroid Build Coastguard Worker     EAS_RESULT result;
1098*f81fb7c4SAndroid Build Coastguard Worker     EAS_I32 i;
1099*f81fb7c4SAndroid Build Coastguard Worker     EAS_U16 division;
1100*f81fb7c4SAndroid Build Coastguard Worker     EAS_U16 numStreams;
1101*f81fb7c4SAndroid Build Coastguard Worker     EAS_U32 chunkSize;
1102*f81fb7c4SAndroid Build Coastguard Worker     EAS_U32 chunkStart;
1103*f81fb7c4SAndroid Build Coastguard Worker     EAS_U32 temp;
1104*f81fb7c4SAndroid Build Coastguard Worker     EAS_U32 ticks;
1105*f81fb7c4SAndroid Build Coastguard Worker 
1106*f81fb7c4SAndroid Build Coastguard Worker     /* explicitly set numStreams to 0. It will later be used by SMF_Close to
1107*f81fb7c4SAndroid Build Coastguard Worker      * determine whether we have valid streams or not. */
1108*f81fb7c4SAndroid Build Coastguard Worker     pSMFData->numStreams = 0;
1109*f81fb7c4SAndroid Build Coastguard Worker 
1110*f81fb7c4SAndroid Build Coastguard Worker     /* rewind the file and find the end of the header chunk */
1111*f81fb7c4SAndroid Build Coastguard Worker     if ((result = EAS_HWFileSeek(hwInstData, pSMFData->fileHandle, pSMFData->fileOffset + SMF_OFS_HEADER_SIZE)) != EAS_SUCCESS)
1112*f81fb7c4SAndroid Build Coastguard Worker         goto ReadError;
1113*f81fb7c4SAndroid Build Coastguard Worker     if ((result = EAS_HWGetDWord(hwInstData, pSMFData->fileHandle, &chunkSize, EAS_TRUE)) != EAS_SUCCESS)
1114*f81fb7c4SAndroid Build Coastguard Worker         goto ReadError;
1115*f81fb7c4SAndroid Build Coastguard Worker 
1116*f81fb7c4SAndroid Build Coastguard Worker     /* determine the number of tracks */
1117*f81fb7c4SAndroid Build Coastguard Worker     if ((result = EAS_HWFileSeek(hwInstData, pSMFData->fileHandle, pSMFData->fileOffset + SMF_OFS_NUM_TRACKS)) != EAS_SUCCESS)
1118*f81fb7c4SAndroid Build Coastguard Worker         goto ReadError;
1119*f81fb7c4SAndroid Build Coastguard Worker     if ((result = EAS_HWGetWord(hwInstData, pSMFData->fileHandle, &numStreams, EAS_TRUE)) != EAS_SUCCESS)
1120*f81fb7c4SAndroid Build Coastguard Worker         goto ReadError;
1121*f81fb7c4SAndroid Build Coastguard Worker 
1122*f81fb7c4SAndroid Build Coastguard Worker     /* limit the number of tracks */
1123*f81fb7c4SAndroid Build Coastguard Worker     if (numStreams > MAX_SMF_STREAMS)
1124*f81fb7c4SAndroid Build Coastguard Worker     {
1125*f81fb7c4SAndroid Build Coastguard Worker         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "SMF file contains %u tracks, playing %d tracks\n", numStreams, MAX_SMF_STREAMS); */ }
1126*f81fb7c4SAndroid Build Coastguard Worker         numStreams = MAX_SMF_STREAMS;
1127*f81fb7c4SAndroid Build Coastguard Worker     } else if (numStreams == 0)
1128*f81fb7c4SAndroid Build Coastguard Worker     {
1129*f81fb7c4SAndroid Build Coastguard Worker         /* avoid 0 sized allocation */
1130*f81fb7c4SAndroid Build Coastguard Worker         return EAS_ERROR_PARAMETER_RANGE;
1131*f81fb7c4SAndroid Build Coastguard Worker     }
1132*f81fb7c4SAndroid Build Coastguard Worker 
1133*f81fb7c4SAndroid Build Coastguard Worker     /* get the time division */
1134*f81fb7c4SAndroid Build Coastguard Worker     if ((result = EAS_HWGetWord(hwInstData, pSMFData->fileHandle, &division, EAS_TRUE)) != EAS_SUCCESS)
1135*f81fb7c4SAndroid Build Coastguard Worker         goto ReadError;
1136*f81fb7c4SAndroid Build Coastguard Worker 
1137*f81fb7c4SAndroid Build Coastguard Worker     /* setup default timebase for 120 bpm */
1138*f81fb7c4SAndroid Build Coastguard Worker     pSMFData->ppqn = 192;
1139*f81fb7c4SAndroid Build Coastguard Worker     if (!division || division & 0x8000)
1140*f81fb7c4SAndroid Build Coastguard Worker         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING,"No support for SMPTE code timebase\n"); */ }
1141*f81fb7c4SAndroid Build Coastguard Worker     else
1142*f81fb7c4SAndroid Build Coastguard Worker         pSMFData->ppqn = (division & 0x7fff);
1143*f81fb7c4SAndroid Build Coastguard Worker     pSMFData->tickConv = (EAS_U16) (((SMF_DEFAULT_TIMEBASE * 1024) / pSMFData->ppqn + 500) / 1000);
1144*f81fb7c4SAndroid Build Coastguard Worker 
1145*f81fb7c4SAndroid Build Coastguard Worker     /* dynamic memory allocation, allocate memory for streams */
1146*f81fb7c4SAndroid Build Coastguard Worker     if (pSMFData->streams == NULL)
1147*f81fb7c4SAndroid Build Coastguard Worker     {
1148*f81fb7c4SAndroid Build Coastguard Worker         pSMFData->streams = EAS_HWMalloc(hwInstData,sizeof(S_SMF_STREAM) * numStreams);
1149*f81fb7c4SAndroid Build Coastguard Worker         if (pSMFData->streams == NULL)
1150*f81fb7c4SAndroid Build Coastguard Worker             return EAS_ERROR_MALLOC_FAILED;
1151*f81fb7c4SAndroid Build Coastguard Worker 
1152*f81fb7c4SAndroid Build Coastguard Worker         /* zero the memory to insure complete initialization */
1153*f81fb7c4SAndroid Build Coastguard Worker         EAS_HWMemSet((void *)(pSMFData->streams), 0, sizeof(S_SMF_STREAM) * numStreams);
1154*f81fb7c4SAndroid Build Coastguard Worker     }
1155*f81fb7c4SAndroid Build Coastguard Worker     pSMFData->numStreams = numStreams;
1156*f81fb7c4SAndroid Build Coastguard Worker 
1157*f81fb7c4SAndroid Build Coastguard Worker     /* find the start of each track */
1158*f81fb7c4SAndroid Build Coastguard Worker     chunkStart = (EAS_U32) pSMFData->fileOffset;
1159*f81fb7c4SAndroid Build Coastguard Worker     ticks = 0x7fffffffL;
1160*f81fb7c4SAndroid Build Coastguard Worker     pSMFData->nextStream = NULL;
1161*f81fb7c4SAndroid Build Coastguard Worker     for (i = 0; i < pSMFData->numStreams; i++)
1162*f81fb7c4SAndroid Build Coastguard Worker     {
1163*f81fb7c4SAndroid Build Coastguard Worker 
1164*f81fb7c4SAndroid Build Coastguard Worker         for (;;)
1165*f81fb7c4SAndroid Build Coastguard Worker         {
1166*f81fb7c4SAndroid Build Coastguard Worker 
1167*f81fb7c4SAndroid Build Coastguard Worker             /* calculate start of next chunk - checking for errors */
1168*f81fb7c4SAndroid Build Coastguard Worker             temp = chunkStart + SMF_CHUNK_INFO_SIZE + chunkSize;
1169*f81fb7c4SAndroid Build Coastguard Worker             if (temp <= chunkStart)
1170*f81fb7c4SAndroid Build Coastguard Worker             {
1171*f81fb7c4SAndroid Build Coastguard Worker                 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING,"Error in chunk size at offset %d\n", chunkStart); */ }
1172*f81fb7c4SAndroid Build Coastguard Worker                 return EAS_ERROR_FILE_FORMAT;
1173*f81fb7c4SAndroid Build Coastguard Worker             }
1174*f81fb7c4SAndroid Build Coastguard Worker             chunkStart = temp;
1175*f81fb7c4SAndroid Build Coastguard Worker 
1176*f81fb7c4SAndroid Build Coastguard Worker             /* seek to the start of the next chunk */
1177*f81fb7c4SAndroid Build Coastguard Worker             if ((result = EAS_HWFileSeek(hwInstData, pSMFData->fileHandle, (EAS_I32) chunkStart)) != EAS_SUCCESS)
1178*f81fb7c4SAndroid Build Coastguard Worker                 goto ReadError;
1179*f81fb7c4SAndroid Build Coastguard Worker 
1180*f81fb7c4SAndroid Build Coastguard Worker             /* read the chunk identifier */
1181*f81fb7c4SAndroid Build Coastguard Worker             if ((result = EAS_HWGetDWord(hwInstData, pSMFData->fileHandle, &temp, EAS_TRUE)) != EAS_SUCCESS)
1182*f81fb7c4SAndroid Build Coastguard Worker                 goto ReadError;
1183*f81fb7c4SAndroid Build Coastguard Worker 
1184*f81fb7c4SAndroid Build Coastguard Worker             /* read the chunk size */
1185*f81fb7c4SAndroid Build Coastguard Worker             if ((result = EAS_HWGetDWord(hwInstData, pSMFData->fileHandle, &chunkSize, EAS_TRUE)) != EAS_SUCCESS)
1186*f81fb7c4SAndroid Build Coastguard Worker                 goto ReadError;
1187*f81fb7c4SAndroid Build Coastguard Worker 
1188*f81fb7c4SAndroid Build Coastguard Worker             /* make sure this is an 'MTrk' chunk */
1189*f81fb7c4SAndroid Build Coastguard Worker             if (temp == SMF_CHUNK_TYPE_TRACK)
1190*f81fb7c4SAndroid Build Coastguard Worker                 break;
1191*f81fb7c4SAndroid Build Coastguard Worker 
1192*f81fb7c4SAndroid Build Coastguard Worker             { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING,"Unexpected chunk type: 0x%08x\n", temp); */ }
1193*f81fb7c4SAndroid Build Coastguard Worker         }
1194*f81fb7c4SAndroid Build Coastguard Worker 
1195*f81fb7c4SAndroid Build Coastguard Worker         /* initalize some data */
1196*f81fb7c4SAndroid Build Coastguard Worker         pSMFData->streams[i].ticks = 0;
1197*f81fb7c4SAndroid Build Coastguard Worker         pSMFData->streams[i].fileHandle = pSMFData->fileHandle;
1198*f81fb7c4SAndroid Build Coastguard Worker 
1199*f81fb7c4SAndroid Build Coastguard Worker         /* NULL the file handle so we don't try to close it twice */
1200*f81fb7c4SAndroid Build Coastguard Worker         pSMFData->fileHandle = NULL;
1201*f81fb7c4SAndroid Build Coastguard Worker 
1202*f81fb7c4SAndroid Build Coastguard Worker         /* save this file position as the start of the track */
1203*f81fb7c4SAndroid Build Coastguard Worker         pSMFData->streams[i].startFilePos = (EAS_I32) chunkStart + SMF_CHUNK_INFO_SIZE;
1204*f81fb7c4SAndroid Build Coastguard Worker 
1205*f81fb7c4SAndroid Build Coastguard Worker         /* initalize the MIDI parser data */
1206*f81fb7c4SAndroid Build Coastguard Worker         EAS_InitMIDIStream(&pSMFData->streams[i].midiStream);
1207*f81fb7c4SAndroid Build Coastguard Worker 
1208*f81fb7c4SAndroid Build Coastguard Worker         /* parse the first delta time in each stream */
1209*f81fb7c4SAndroid Build Coastguard Worker         if ((result = SMF_GetDeltaTime(hwInstData, &pSMFData->streams[i])) != EAS_SUCCESS)
1210*f81fb7c4SAndroid Build Coastguard Worker                 goto ReadError;
1211*f81fb7c4SAndroid Build Coastguard Worker 
1212*f81fb7c4SAndroid Build Coastguard Worker         if (pSMFData->streams[i].ticks < ticks)
1213*f81fb7c4SAndroid Build Coastguard Worker         {
1214*f81fb7c4SAndroid Build Coastguard Worker             ticks = pSMFData->streams[i].ticks;
1215*f81fb7c4SAndroid Build Coastguard Worker             pSMFData->nextStream = &pSMFData->streams[i];
1216*f81fb7c4SAndroid Build Coastguard Worker         }
1217*f81fb7c4SAndroid Build Coastguard Worker 
1218*f81fb7c4SAndroid Build Coastguard Worker         /* more tracks to do, create a duplicate file handle */
1219*f81fb7c4SAndroid Build Coastguard Worker         if (i < (pSMFData->numStreams - 1))
1220*f81fb7c4SAndroid Build Coastguard Worker         {
1221*f81fb7c4SAndroid Build Coastguard Worker             if ((result = EAS_HWDupHandle(hwInstData, pSMFData->streams[i].fileHandle, &pSMFData->fileHandle)) != EAS_SUCCESS)
1222*f81fb7c4SAndroid Build Coastguard Worker                 goto ReadError;
1223*f81fb7c4SAndroid Build Coastguard Worker         }
1224*f81fb7c4SAndroid Build Coastguard Worker     }
1225*f81fb7c4SAndroid Build Coastguard Worker 
1226*f81fb7c4SAndroid Build Coastguard Worker     /* update the time of the next event */
1227*f81fb7c4SAndroid Build Coastguard Worker     if (pSMFData->nextStream)
1228*f81fb7c4SAndroid Build Coastguard Worker         SMF_UpdateTime(pSMFData, pSMFData->nextStream->ticks);
1229*f81fb7c4SAndroid Build Coastguard Worker 
1230*f81fb7c4SAndroid Build Coastguard Worker     return EAS_SUCCESS;
1231*f81fb7c4SAndroid Build Coastguard Worker 
1232*f81fb7c4SAndroid Build Coastguard Worker     /* ugly goto: but simpler than structured */
1233*f81fb7c4SAndroid Build Coastguard Worker     ReadError:
1234*f81fb7c4SAndroid Build Coastguard Worker         if (result == EAS_EOF)
1235*f81fb7c4SAndroid Build Coastguard Worker             return EAS_ERROR_FILE_FORMAT;
1236*f81fb7c4SAndroid Build Coastguard Worker         return result;
1237*f81fb7c4SAndroid Build Coastguard Worker }
1238*f81fb7c4SAndroid Build Coastguard Worker 
1239*f81fb7c4SAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
1240*f81fb7c4SAndroid Build Coastguard Worker  * SMF_UpdateTime()
1241*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
1242*f81fb7c4SAndroid Build Coastguard Worker  * Purpose:
1243*f81fb7c4SAndroid Build Coastguard Worker  * Update the millisecond time base by converting the ticks into millieconds
1244*f81fb7c4SAndroid Build Coastguard Worker  *
1245*f81fb7c4SAndroid Build Coastguard Worker  * Inputs:
1246*f81fb7c4SAndroid Build Coastguard Worker  *
1247*f81fb7c4SAndroid Build Coastguard Worker  *
1248*f81fb7c4SAndroid Build Coastguard Worker  * Outputs:
1249*f81fb7c4SAndroid Build Coastguard Worker  *
1250*f81fb7c4SAndroid Build Coastguard Worker  *
1251*f81fb7c4SAndroid Build Coastguard Worker  * Side Effects:
1252*f81fb7c4SAndroid Build Coastguard Worker  *
1253*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
1254*f81fb7c4SAndroid Build Coastguard Worker */
SMF_UpdateTime(S_SMF_DATA * pSMFData,EAS_U32 ticks)1255*f81fb7c4SAndroid Build Coastguard Worker static void SMF_UpdateTime (S_SMF_DATA *pSMFData, EAS_U32 ticks)
1256*f81fb7c4SAndroid Build Coastguard Worker {
1257*f81fb7c4SAndroid Build Coastguard Worker     EAS_U32 temp1, temp2;
1258*f81fb7c4SAndroid Build Coastguard Worker 
1259*f81fb7c4SAndroid Build Coastguard Worker     if (pSMFData->flags & SMF_FLAGS_CHASE_MODE)
1260*f81fb7c4SAndroid Build Coastguard Worker         return;
1261*f81fb7c4SAndroid Build Coastguard Worker 
1262*f81fb7c4SAndroid Build Coastguard Worker     temp1 = (ticks >> 10) * pSMFData->tickConv;
1263*f81fb7c4SAndroid Build Coastguard Worker     temp2 = (ticks & 0x3ff) * pSMFData->tickConv;
1264*f81fb7c4SAndroid Build Coastguard Worker     pSMFData->time += (EAS_I32)((temp1 << 8) + (temp2 >> 2));
1265*f81fb7c4SAndroid Build Coastguard Worker }
1266*f81fb7c4SAndroid Build Coastguard Worker 
1267