1 /*----------------------------------------------------------------------------
2 *
3 * File:
4 * eas_ota.c
5 *
6 * Contents and purpose:
7 * OTA parser
8 *
9 * Copyright Sonic Network Inc. 2005
10
11 * Licensed under the Apache License, Version 2.0 (the "License");
12 * you may not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
14 *
15 * http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
22 *
23 *----------------------------------------------------------------------------
24 * Revision Control:
25 * $Revision: 795 $
26 * $Date: 2007-08-01 00:14:45 -0700 (Wed, 01 Aug 2007) $
27 *----------------------------------------------------------------------------
28 */
29
30 #define LOG_TAG "Sonivox"
31 #include <log/log.h>
32
33 #include "eas_data.h"
34 #include "eas_miditypes.h"
35 #include "eas_parser.h"
36 #include "eas_report.h"
37 #include "eas_host.h"
38 #include "eas_midi.h"
39 #include "eas_config.h"
40 #include "eas_vm_protos.h"
41 #include "eas_otadata.h"
42
43 /* increase gain for mono ringtones */
44 #define OTA_GAIN_OFFSET 8
45
46 /* file definitions */
47 #define OTA_RINGTONE 0x25
48 #define OTA_SOUND 0x1d
49 #define OTA_UNICODE 0x22
50
51 /* song type definitions */
52 #define OTA_BASIC_SONG_TYPE 0x01
53 #define OTA_TEMPORARY_SONG_TYPE 0x02
54
55 /* instruction ID coding */
56 #define OTA_PATTERN_HEADER_ID 0x00
57 #define OTA_NOTE_INST_ID 0x01
58 #define OTA_SCALE_INST_ID 0x02
59 #define OTA_STYLE_INST_ID 0x03
60 #define OTA_TEMPO_INST_ID 0x04
61 #define OTA_VOLUME_INST_ID 0x05
62
63 /* note durations */
64 #define OTA_NORMAL_DURATION 0x00
65 #define OTA_DOTTED_NOTE 0x01
66 #define OTA_DOUBLE_DOTTED_NOTE 0x02
67 #define OTA_TRIPLET_NOTE 0x03
68
69 /* loop count value for infinite loop */
70 #define OTA_INFINITE_LOOP 0x0f
71
72 /* length of 32nd note in 1/256ths of a msec for 63 BPM tempo */
73 #define DEFAULT_TICK_CONV 30476
74
75 /* default channel and program for OTA playback */
76 #define OTA_CHANNEL 0
77 #define OTA_PROGRAM 80
78 #define OTA_VEL_MUL 4
79 #define OTA_VEL_OFS 67
80 #define OTA_VEL_DEFAULT 95
81
82 /* multiplier for fixed point triplet conversion */
83 #define TRIPLET_MULTIPLIER 683
84 #define TRIPLET_SHIFT 10
85
86 /* local prototypes */
87 static EAS_RESULT OTA_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset);
88 static EAS_RESULT OTA_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
89 static EAS_RESULT OTA_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime);
90 static EAS_RESULT OTA_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode);
91 static EAS_RESULT OTA_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState);
92 static EAS_RESULT OTA_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
93 static EAS_RESULT OTA_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
94 static EAS_RESULT OTA_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
95 static EAS_RESULT OTA_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData);
96 static EAS_RESULT OTA_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value);
97 static EAS_RESULT OTA_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue);
98 static EAS_RESULT OTA_ParseHeader (S_EAS_DATA *pEASData, S_OTA_DATA* pData);
99 static EAS_RESULT OTA_FetchBitField (EAS_HW_DATA_HANDLE hwInstData, S_OTA_DATA *pData, EAS_I32 numBits, EAS_U8 *pValue);
100 static EAS_RESULT OTA_SavePosition (EAS_HW_DATA_HANDLE hwInstData, S_OTA_DATA *pData, S_OTA_LOC *pLoc);
101 static EAS_RESULT OTA_RestorePosition (EAS_HW_DATA_HANDLE hwInstData, S_OTA_DATA *pData, S_OTA_LOC *pLoc);
102
103
104 /*----------------------------------------------------------------------------
105 *
106 * EAS_OTA_Parser
107 *
108 * This structure contains the functional interface for the OTA parser
109 *----------------------------------------------------------------------------
110 */
111 const S_FILE_PARSER_INTERFACE EAS_OTA_Parser =
112 {
113 OTA_CheckFileType,
114 OTA_Prepare,
115 OTA_Time,
116 OTA_Event,
117 OTA_State,
118 OTA_Close,
119 OTA_Reset,
120 #ifdef JET_INTERFACE
121 OTA_Pause,
122 OTA_Resume,
123 #else
124 NULL,
125 NULL,
126 #endif
127 NULL,
128 OTA_SetData,
129 OTA_GetData,
130 NULL
131 };
132
133 /*----------------------------------------------------------------------------
134 *
135 * bpmTable
136 *
137 * BPM conversion table. Converts bpm values to 256ths of a millisecond for a 32nd note
138 *----------------------------------------------------------------------------
139 */
140 static const EAS_U32 bpmTable[32] =
141 {
142 76800, 68571, 61935, 54857,
143 48000, 42667, 38400, 34286,
144 30476, 27429, 24000, 21333,
145 19200, 17143, 15360, 13714,
146 12000, 10667, 9600, 8533,
147 7680, 6737, 6000, 5408,
148 4800, 4267, 3840, 3398,
149 3024, 2685, 2400, 2133
150 };
151
152 /*----------------------------------------------------------------------------
153 * OTA_CheckFileType()
154 *----------------------------------------------------------------------------
155 * Purpose:
156 * Check the file type to see if we can parse it
157 *
158 * Inputs:
159 * pEASData - pointer to overall EAS data structure
160 * handle - pointer to file handle
161 *
162 * Outputs:
163 *
164 *
165 * Side Effects:
166 *
167 *----------------------------------------------------------------------------
168 */
OTA_CheckFileType(S_EAS_DATA * pEASData,EAS_FILE_HANDLE fileHandle,EAS_VOID_PTR * ppHandle,EAS_I32 offset)169 static EAS_RESULT OTA_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset)
170 {
171 S_OTA_DATA* pData;
172 EAS_RESULT result;
173 EAS_INT cmdLen;
174 EAS_INT state;
175 EAS_U8 temp;
176
177 /* read the first byte, should be command length */
178 *ppHandle = NULL;
179 if ((result = EAS_HWGetByte(pEASData->hwInstData, fileHandle, &temp)) != EAS_SUCCESS)
180 return result;
181
182 /* read all the commands */
183 cmdLen = temp;
184 state = 0;
185 while (cmdLen--)
186 {
187
188 /* read the command, upper 7 bits */
189 if ((result = EAS_HWGetByte(pEASData->hwInstData, fileHandle, &temp)) != EAS_SUCCESS)
190 return result;
191 temp = temp >> 1;
192
193 if (state == 0)
194 {
195 if (temp != OTA_RINGTONE)
196 break;
197 state++;
198 }
199 else
200 {
201
202 if (temp == OTA_SOUND)
203 {
204
205 /* check for static memory allocation */
206 if (pEASData->staticMemoryModel)
207 pData = EAS_CMEnumData(EAS_CM_OTA_DATA);
208 else
209 pData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_OTA_DATA));
210 if (!pData)
211 {
212 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Malloc failed in OTA_Prepare\n"); */ }
213 return EAS_ERROR_MALLOC_FAILED;
214 }
215 EAS_HWMemSet(pData, 0, sizeof(S_OTA_DATA));
216
217 /* return a pointer to the instance data */
218 pData->fileHandle = fileHandle;
219 pData->fileOffset = offset;
220 pData->state = EAS_STATE_OPEN;
221 *ppHandle = pData;
222 ALOGD("%s() OTA file recognized", __func__);
223 break;
224 }
225
226 if (temp != OTA_UNICODE)
227 break;
228 }
229 }
230
231 /* not recognized */
232 return EAS_SUCCESS;
233 }
234
235 /*----------------------------------------------------------------------------
236 * OTA_Prepare()
237 *----------------------------------------------------------------------------
238 * Purpose:
239 * Prepare to parse the file. Allocates instance data (or uses static allocation for
240 * static memory model).
241 *
242 * Inputs:
243 * pEASData - pointer to overall EAS data structure
244 * handle - pointer to file handle
245 *
246 * Outputs:
247 *
248 *
249 * Side Effects:
250 *
251 *----------------------------------------------------------------------------
252 */
OTA_Prepare(S_EAS_DATA * pEASData,EAS_VOID_PTR pInstData)253 static EAS_RESULT OTA_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
254 {
255 S_OTA_DATA* pData;
256 EAS_RESULT result;
257
258 /* check for valid state */
259 pData = (S_OTA_DATA*) pInstData;
260 if (pData->state != EAS_STATE_OPEN)
261 return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
262
263 /* instantiate a synthesizer */
264 if ((result = VMInitMIDI(pEASData, &pData->pSynth)) != EAS_SUCCESS)
265 {
266 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMInitMIDI returned %d\n", result); */ }
267 return result;
268 }
269
270 pData->state = EAS_STATE_ERROR;
271 if ((result = OTA_ParseHeader(pEASData, pData)) != EAS_SUCCESS)
272 return result;
273
274 pData->state = EAS_STATE_READY;
275 return EAS_SUCCESS;
276 }
277
278 /*----------------------------------------------------------------------------
279 * OTA_Time()
280 *----------------------------------------------------------------------------
281 * Purpose:
282 * Returns the time of the next event in msecs
283 *
284 * Inputs:
285 * pEASData - pointer to overall EAS data structure
286 * handle - pointer to file handle
287 * pTime - pointer to variable to hold time of next event (in msecs)
288 *
289 * Outputs:
290 *
291 *
292 * Side Effects:
293 *
294 *----------------------------------------------------------------------------
295 */
296 /*lint -esym(715, pEASData) common decoder interface - pEASData not used */
OTA_Time(S_EAS_DATA * pEASData,EAS_VOID_PTR pInstData,EAS_U32 * pTime)297 static EAS_RESULT OTA_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime)
298 {
299 S_OTA_DATA *pData;
300
301 pData = (S_OTA_DATA*) pInstData;
302
303 /* return time in milliseconds */
304 /*lint -e{704} use shift instead of division */
305 *pTime = pData->time >> 8;
306 return EAS_SUCCESS;
307 }
308
309 /*----------------------------------------------------------------------------
310 * OTA_Event()
311 *----------------------------------------------------------------------------
312 * Purpose:
313 * Parse the next event in the file
314 *
315 * Inputs:
316 * pEASData - pointer to overall EAS data structure
317 * handle - pointer to file handle
318 *
319 * Outputs:
320 *
321 *
322 * Side Effects:
323 *
324 *----------------------------------------------------------------------------
325 */
OTA_Event(S_EAS_DATA * pEASData,EAS_VOID_PTR pInstData,EAS_INT parserMode)326 static EAS_RESULT OTA_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode)
327 {
328 S_OTA_DATA* pData;
329 EAS_RESULT result;
330 EAS_U32 duration;
331 EAS_U8 temp;
332
333 pData = (S_OTA_DATA*) pInstData;
334 if (pData->state >= EAS_STATE_OPEN)
335 return EAS_SUCCESS;
336
337 /* initialize MIDI channel when the track starts playing */
338 if (pData->time == 0)
339 {
340 /* set program to square lead */
341 if (parserMode != eParserModeMetaData)
342 VMProgramChange(pEASData->pVoiceMgr, pData->pSynth, OTA_CHANNEL, OTA_PROGRAM);
343
344 /* set channel volume to max */
345 if (parserMode != eParserModeMetaData)
346 VMControlChange(pEASData->pVoiceMgr, pData->pSynth, OTA_CHANNEL, 7, 127);
347 }
348
349 /* check for end of note */
350 if (pData->note)
351 {
352 /* stop the note */
353 VMStopNote(pEASData->pVoiceMgr, pData->pSynth, OTA_CHANNEL, pData->note, 0);
354 pData->note = 0;
355
356 /* check for rest between notes */
357 if (pData->restTicks)
358 {
359 pData->time += (EAS_I32) pData->restTicks;
360 pData->restTicks = 0;
361 return EAS_SUCCESS;
362 }
363 }
364
365 /* if not in a pattern, read the pattern header */
366 while (pData->current.patternLen == 0)
367 {
368
369 /* check for loop - don't do infinite loops when locating */
370 if (pData->loopCount && ((parserMode == eParserModePlay) || (pData->loopCount != OTA_INFINITE_LOOP)))
371 {
372 ALOGV("%s() loop backwards, loopCount = %d", __func__, pData->loopCount);
373 /* if not infinite loop, decrement loop count */
374 if (pData->loopCount != OTA_INFINITE_LOOP)
375 pData->loopCount--;
376
377 /* back to start of pattern*/
378 if ((result = OTA_RestorePosition(pEASData->hwInstData, pData, &pData->patterns[pData->currentPattern])) != EAS_SUCCESS)
379 return result;
380 }
381
382 /* if no previous position to restore, continue forward */
383 else if (pData->restore.fileOffset < 0)
384 {
385
386 /* check for end of song */
387 if (pData->numPatterns == 0)
388 {
389 pData->state = EAS_STATE_STOPPING;
390 VMReleaseAllVoices(pEASData->pVoiceMgr, pData->pSynth);
391 return EAS_SUCCESS;
392 }
393
394 /* read the next pattern header */
395 if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 3, &temp)) != EAS_SUCCESS)
396 return result;
397 if (temp != OTA_PATTERN_HEADER_ID)
398 {
399 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Expected OTA pattern header\n"); */ }
400 return EAS_ERROR_FILE_FORMAT;
401 }
402
403 /* get the pattern ID */
404 if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 2, &pData->currentPattern)) != EAS_SUCCESS)
405 return result;
406
407 /* get the loop count */
408 if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 4, &pData->loopCount)) != EAS_SUCCESS)
409 return result;
410
411 /* get the pattern length */
412 if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 8, &pData->current.patternLen)) != EAS_SUCCESS)
413 return result;
414
415 /* if pattern definition, save the current position */
416 if (pData->current.patternLen)
417 {
418 if ((result = OTA_SavePosition(pEASData->hwInstData, pData, &pData->patterns[pData->currentPattern])) != EAS_SUCCESS)
419 return result;
420 }
421
422 /* if pattern length is zero, repeat a previous pattern */
423 else
424 {
425 /* make sure it's a valid pattern */
426 if (pData->patterns[pData->currentPattern].fileOffset < 0)
427 {
428 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "OTA pattern error, invalid pattern specified\n"); */ }
429 return EAS_ERROR_FILE_FORMAT;
430 }
431
432 /* save current position and data */
433 if ((result = OTA_SavePosition(pEASData->hwInstData, pData, &pData->restore)) != EAS_SUCCESS)
434 return result;
435
436 /* seek to the pattern in the file */
437 if ((result = OTA_RestorePosition(pEASData->hwInstData, pData, &pData->patterns[pData->currentPattern])) != EAS_SUCCESS)
438 return result;
439 }
440
441 /* decrement pattern count */
442 pData->numPatterns--;
443 }
444
445 /* restore previous position */
446 else
447 {
448 if ((result = OTA_RestorePosition(pEASData->hwInstData, pData, &pData->restore)) != EAS_SUCCESS)
449 return result;
450 }
451 }
452
453 /* get the next event */
454 if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 3, &temp)) != EAS_SUCCESS)
455 return result;
456
457 switch (temp)
458 {
459 case OTA_NOTE_INST_ID:
460 /* fetch note value */
461 if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 4, &pData->note)) != EAS_SUCCESS)
462 return result;
463
464 /* fetch note duration */
465 if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 3, &temp)) != EAS_SUCCESS)
466 return result;
467 duration = pData->tick * (0x20 >> temp);
468
469 /* fetch note duration modifier */
470 if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 2, &temp)) != EAS_SUCCESS)
471 return result;
472 switch (temp)
473 {
474 case OTA_NORMAL_DURATION:
475 break;
476
477 case OTA_DOTTED_NOTE:
478 duration += duration >> 1;
479 break;
480
481 case OTA_DOUBLE_DOTTED_NOTE:
482 duration += (duration >> 1) + (duration >> 2);
483 break;
484
485 case OTA_TRIPLET_NOTE:
486 duration = (duration * TRIPLET_MULTIPLIER) >> TRIPLET_SHIFT;
487 break;
488
489 default:
490 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Unrecognized note duration ignored\n"); */ }
491 break;
492 }
493
494 /* check for note */
495 if (pData->note)
496 {
497
498 /* determine note length based on style */
499 switch (pData->style)
500 {
501 case 0:
502 pData->restTicks = duration >> 4;
503 break;
504 case 1:
505 pData->restTicks = 0;
506 break;
507 case 2:
508 pData->restTicks = duration >> 1;
509 break;
510 default:
511 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Unrecognized note style ignored\n"); */ }
512 }
513
514 /* add octave */
515 pData->note += pData->octave;
516 if (parserMode == eParserModePlay)
517 VMStartNote(pEASData->pVoiceMgr, pData->pSynth, OTA_CHANNEL, pData->note, pData->velocity);
518 pData->time += (EAS_I32) duration - (EAS_I32) pData->restTicks;
519 }
520
521 /* this is a rest */
522 else
523 pData->time += (EAS_I32) duration;
524 break;
525
526 case OTA_SCALE_INST_ID:
527 /* fetch octave */
528 if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 2, &temp)) != EAS_SUCCESS)
529 return result;
530 pData->octave = (EAS_U8) (temp * 12 + 59);
531 break;
532
533 case OTA_STYLE_INST_ID:
534 /* fetch note style */
535 if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 2, &pData->style)) != EAS_SUCCESS)
536 return result;
537 break;
538
539 case OTA_TEMPO_INST_ID:
540 /* fetch tempo */
541 if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 5, &temp)) != EAS_SUCCESS)
542 return result;
543 pData->tick = bpmTable[temp];
544 break;
545
546 case OTA_VOLUME_INST_ID:
547 /* fetch volume */
548 if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 4, &temp)) != EAS_SUCCESS)
549 return result;
550 pData->velocity = temp ? (EAS_U8) (temp * OTA_VEL_MUL + OTA_VEL_OFS) : 0;
551 break;
552
553 default:
554 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unexpected instruction ID in OTA stream\n"); */ }
555 return EAS_ERROR_FILE_FORMAT;
556 }
557
558 /* decrement pattern length */
559 pData->current.patternLen--;
560 return EAS_SUCCESS;
561 }
562
563 /*----------------------------------------------------------------------------
564 * OTA_State()
565 *----------------------------------------------------------------------------
566 * Purpose:
567 * Returns the current state of the stream
568 *
569 * Inputs:
570 * pEASData - pointer to overall EAS data structure
571 * handle - pointer to file handle
572 * pState - pointer to variable to store state
573 *
574 * Outputs:
575 *
576 *
577 * Side Effects:
578 *
579 *----------------------------------------------------------------------------
580 */
581 /*lint -esym(715, pEASData) common decoder interface - pEASData not used */
OTA_State(S_EAS_DATA * pEASData,EAS_VOID_PTR pInstData,EAS_I32 * pState)582 static EAS_RESULT OTA_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pState)
583 {
584 S_OTA_DATA* pData;
585
586 /* establish pointer to instance data */
587 pData = (S_OTA_DATA*) pInstData;
588
589 /* if stopping, check to see if synth voices are active */
590 if (pData->state == EAS_STATE_STOPPING)
591 {
592 if (VMActiveVoices(pData->pSynth) == 0)
593 pData->state = EAS_STATE_STOPPED;
594 }
595
596 if (pData->state == EAS_STATE_PAUSING)
597 {
598 if (VMActiveVoices(pData->pSynth) == 0)
599 pData->state = EAS_STATE_PAUSED;
600 }
601
602 /* return current state */
603 *pState = pData->state;
604 return EAS_SUCCESS;
605 }
606
607 /*----------------------------------------------------------------------------
608 * OTA_Close()
609 *----------------------------------------------------------------------------
610 * Purpose:
611 * Close the file and clean up
612 *
613 * Inputs:
614 * pEASData - pointer to overall EAS data structure
615 * handle - pointer to file handle
616 *
617 * Outputs:
618 *
619 *
620 * Side Effects:
621 *
622 *----------------------------------------------------------------------------
623 */
OTA_Close(S_EAS_DATA * pEASData,EAS_VOID_PTR pInstData)624 static EAS_RESULT OTA_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
625 {
626 S_OTA_DATA* pData;
627 EAS_RESULT result;
628
629 pData = (S_OTA_DATA*) pInstData;
630
631 /* close the file */
632 if ((result = EAS_HWCloseFile(pEASData->hwInstData, pData->fileHandle)) != EAS_SUCCESS)
633 return result;
634
635 /* free the synth */
636 if (pData->pSynth != NULL)
637 VMMIDIShutdown(pEASData, pData->pSynth);
638
639 /* if using dynamic memory, free it */
640 if (!pEASData->staticMemoryModel)
641 EAS_HWFree(pEASData->hwInstData, pData);
642
643 return EAS_SUCCESS;
644 }
645
646 /*----------------------------------------------------------------------------
647 * OTA_Reset()
648 *----------------------------------------------------------------------------
649 * Purpose:
650 * Reset the sequencer. Used for locating backwards in the file.
651 *
652 * Inputs:
653 * pEASData - pointer to overall EAS data structure
654 * handle - pointer to file handle
655 *
656 * Outputs:
657 *
658 *
659 * Side Effects:
660 *
661 *----------------------------------------------------------------------------
662 */
OTA_Reset(S_EAS_DATA * pEASData,EAS_VOID_PTR pInstData)663 static EAS_RESULT OTA_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
664 {
665 S_OTA_DATA* pData;
666 EAS_RESULT result;
667
668 pData = (S_OTA_DATA*) pInstData;
669
670 /* reset the synth */
671 VMReset(pEASData->pVoiceMgr, pData->pSynth, EAS_TRUE);
672 pData->note = 0;
673
674 /* reset file position and re-parse header */
675 pData->state = EAS_STATE_ERROR;
676 if ((result = OTA_ParseHeader (pEASData, pData)) != EAS_SUCCESS)
677 return result;
678
679 pData->state = EAS_STATE_READY;
680 return EAS_SUCCESS;
681 }
682
683 #ifdef JET_INTERFACE
684 /*----------------------------------------------------------------------------
685 * OTA_Pause()
686 *----------------------------------------------------------------------------
687 * Purpose:
688 * Pauses the sequencer. Mutes all voices and sets state to pause.
689 *
690 * Inputs:
691 * pEASData - pointer to overall EAS data structure
692 * handle - pointer to file handle
693 *
694 * Outputs:
695 *
696 *
697 * Side Effects:
698 *
699 *----------------------------------------------------------------------------
700 */
OTA_Pause(S_EAS_DATA * pEASData,EAS_VOID_PTR pInstData)701 static EAS_RESULT OTA_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
702 {
703 S_OTA_DATA *pData;
704
705 /* can't pause a stopped stream */
706 pData = (S_OTA_DATA*) pInstData;
707 if (pData->state == EAS_STATE_STOPPED)
708 return EAS_ERROR_ALREADY_STOPPED;
709
710 /* mute the synthesizer */
711 VMMuteAllVoices(pEASData->pVoiceMgr, pData->pSynth);
712 pData->state = EAS_STATE_PAUSING;
713 return EAS_SUCCESS;
714 }
715
716 /*----------------------------------------------------------------------------
717 * OTA_Resume()
718 *----------------------------------------------------------------------------
719 * Purpose:
720 * Resume playing after a pause, sets state back to playing.
721 *
722 * Inputs:
723 * pEASData - pointer to overall EAS data structure
724 * handle - pointer to file handle
725 *
726 * Outputs:
727 *
728 *
729 * Side Effects:
730 *
731 *----------------------------------------------------------------------------
732 */
733 /*lint -esym(715, pEASData) common decoder interface - pEASData not used */
OTA_Resume(S_EAS_DATA * pEASData,EAS_VOID_PTR pInstData)734 static EAS_RESULT OTA_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData)
735 {
736 S_OTA_DATA *pData;
737
738 /* can't resume a stopped stream */
739 pData = (S_OTA_DATA*) pInstData;
740 if (pData->state == EAS_STATE_STOPPED)
741 return EAS_ERROR_ALREADY_STOPPED;
742
743 /* nothing to do but resume playback */
744 pData->state = EAS_STATE_PLAY;
745 return EAS_SUCCESS;
746 }
747 #endif
748
749 /*----------------------------------------------------------------------------
750 * OTA_SetData()
751 *----------------------------------------------------------------------------
752 * Purpose:
753 * Return file type
754 *
755 * Inputs:
756 * pEASData - pointer to overall EAS data structure
757 * handle - pointer to file handle
758 *
759 * Outputs:
760 *
761 *
762 * Side Effects:
763 *
764 *----------------------------------------------------------------------------
765 */
766 /*lint -esym(715, pEASData) common decoder interface - pEASData not used */
OTA_SetData(S_EAS_DATA * pEASData,EAS_VOID_PTR pInstData,EAS_I32 param,EAS_I32 value)767 static EAS_RESULT OTA_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value)
768 {
769 S_OTA_DATA *pData;
770
771 pData = (S_OTA_DATA *) pInstData;
772 switch (param)
773 {
774
775 /* set metadata callback */
776 case PARSER_DATA_METADATA_CB:
777 EAS_HWMemCpy(&pData->metadata, (void*) value, sizeof(S_METADATA_CB));
778 break;
779
780 default:
781 return EAS_ERROR_INVALID_PARAMETER;
782 }
783
784 return EAS_SUCCESS;
785 }
786
787 /*----------------------------------------------------------------------------
788 * OTA_GetData()
789 *----------------------------------------------------------------------------
790 * Purpose:
791 * Return file type
792 *
793 * Inputs:
794 * pEASData - pointer to overall EAS data structure
795 * handle - pointer to file handle
796 *
797 * Outputs:
798 *
799 *
800 * Side Effects:
801 *
802 *----------------------------------------------------------------------------
803 */
804 /*lint -esym(715, pEASData) common decoder interface - pEASData not used */
OTA_GetData(S_EAS_DATA * pEASData,EAS_VOID_PTR pInstData,EAS_I32 param,EAS_I32 * pValue)805 static EAS_RESULT OTA_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue)
806 {
807 S_OTA_DATA *pData;
808
809 pData = (S_OTA_DATA*) pInstData;
810 switch (param)
811 {
812 /* return file type as OTA */
813 case PARSER_DATA_FILE_TYPE:
814 *pValue = EAS_FILE_OTA;
815 break;
816
817 #if 0
818 /* set transposition */
819 case PARSER_DATA_TRANSPOSITION:
820 *pValue = pData->transposition;
821 break;
822 #endif
823
824 case PARSER_DATA_SYNTH_HANDLE:
825 *pValue = (EAS_I32) pData->pSynth;
826 break;
827
828 case PARSER_DATA_GAIN_OFFSET:
829 *pValue = OTA_GAIN_OFFSET;
830 break;
831
832 default:
833 return EAS_ERROR_INVALID_PARAMETER;
834 }
835 return EAS_SUCCESS;
836 }
837
838 /*----------------------------------------------------------------------------
839 * OTA_ParseHeader()
840 *----------------------------------------------------------------------------
841 * Purpose:
842 * Prepare to parse the file. Allocates instance data (or uses static allocation for
843 * static memory model).
844 *
845 * Inputs:
846 * pEASData - pointer to overall EAS data structure
847 * handle - pointer to file handle
848 *
849 * Outputs:
850 *
851 *
852 * Side Effects:
853 *
854 *----------------------------------------------------------------------------
855 */
OTA_ParseHeader(S_EAS_DATA * pEASData,S_OTA_DATA * pData)856 static EAS_RESULT OTA_ParseHeader (S_EAS_DATA *pEASData, S_OTA_DATA* pData)
857 {
858 EAS_RESULT result;
859 EAS_INT i;
860 EAS_INT state;
861 EAS_U8 temp;
862 EAS_U8 titleLen;
863
864 /* initialize some data */
865 pData->flags = 0;
866 pData->time = 0;
867 pData->tick = DEFAULT_TICK_CONV;
868 pData->patterns[0].fileOffset = pData->patterns[1].fileOffset =
869 pData->patterns[2].fileOffset = pData->patterns[3].fileOffset = -1;
870 pData->current.bitCount = 0;
871 pData->current.patternLen = 0;
872 pData->loopCount = 0;
873 pData->restore.fileOffset = -1;
874 pData->note = 0;
875 pData->restTicks = 0;
876 pData->velocity = OTA_VEL_DEFAULT;
877 pData->style = 0;
878 pData->octave = 59;
879
880 /* seek to start of data */
881 if ((result = EAS_HWFileSeek(pEASData->hwInstData, pData->fileHandle, pData->fileOffset)) != EAS_SUCCESS)
882 return result;
883
884 /* read the first byte, should be command length */
885 if ((result = EAS_HWGetByte(pEASData->hwInstData, pData->fileHandle, &temp)) != EAS_SUCCESS)
886 return result;
887
888 /* read all the commands */
889 i = temp;
890 state = 0;
891 while (i--)
892 {
893
894 /* fetch command, always starts on byte boundary */
895 pData->current.bitCount = 0;
896 if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 7, &temp)) != EAS_SUCCESS)
897 return result;
898
899 if (state == 0)
900 {
901 if (temp != OTA_RINGTONE)
902 {
903 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Expected OTA Ring Tone Programming type\n"); */ }
904 return EAS_ERROR_FILE_FORMAT;
905 }
906 state++;
907 }
908 else
909 {
910
911 if (temp == OTA_SOUND)
912 break;
913
914 if (temp == OTA_UNICODE)
915 pData->flags |= OTA_FLAGS_UNICODE;
916 else
917 {
918 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Expected OTA Sound or Unicode type\n"); */ }
919 return EAS_ERROR_FILE_FORMAT;
920 }
921 }
922 }
923
924 /* get song type */
925 if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 3, &temp)) != EAS_SUCCESS)
926 return result;
927
928 /* check for basic song type */
929 if (temp == OTA_BASIC_SONG_TYPE)
930 {
931 /* fetch title length */
932 if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 4, &titleLen)) != EAS_SUCCESS)
933 return result;
934
935 /* if unicode, double the length */
936 if (pData->flags & OTA_FLAGS_UNICODE)
937 titleLen = (EAS_U8) (titleLen << 1);
938
939 /* zero the metadata buffer */
940 if (pData->metadata.buffer)
941 EAS_HWMemSet(pData->metadata.buffer, 0, pData->metadata.bufferSize);
942
943 /* read the song title */
944 for (i = 0; i < titleLen; i++)
945 {
946 /* fetch character */
947 if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 8, &temp)) != EAS_SUCCESS)
948 return result;
949
950 /* check for metadata callback */
951 if (pData->metadata.callback)
952 {
953 if (i < (pData->metadata.bufferSize - 1))
954 pData->metadata.buffer[i] = (char) temp;
955 }
956 }
957
958 /* if host has registered callback, call it now */
959 if (pData->metadata.callback)
960 (*pData->metadata.callback)(EAS_METADATA_TITLE, pData->metadata.buffer, pData->metadata.pUserData);
961 }
962
963 /* must be temporary song */
964 else if (temp != OTA_TEMPORARY_SONG_TYPE)
965 {
966 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Expected OTA basic or temporary song type\n"); */ }
967 return EAS_ERROR_FILE_FORMAT;
968 }
969
970 /* get the song length */
971 if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 8, &pData->numPatterns)) != EAS_SUCCESS)
972 return result;
973
974 /* sanity check */
975 if (pData->numPatterns == 0)
976 {
977 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "OTA number of patterns is zero\n"); */ }
978 return EAS_ERROR_FILE_FORMAT;
979 }
980
981 /* at start of first pattern */
982 return EAS_SUCCESS;
983 }
984
985 /*----------------------------------------------------------------------------
986 * OTA_FetchBitField()
987 *----------------------------------------------------------------------------
988 * Purpose:
989 * Fetch a specified number of bits from the input stream
990 *
991 * Inputs:
992 *
993 *
994 * Outputs:
995 *
996 *
997 * Side Effects:
998 *
999 *----------------------------------------------------------------------------
1000 */
OTA_FetchBitField(EAS_HW_DATA_HANDLE hwInstData,S_OTA_DATA * pData,EAS_I32 numBits,EAS_U8 * pValue)1001 static EAS_RESULT OTA_FetchBitField (EAS_HW_DATA_HANDLE hwInstData, S_OTA_DATA *pData, EAS_I32 numBits, EAS_U8 *pValue)
1002 {
1003 EAS_RESULT result;
1004 EAS_I32 bitsLeft;
1005 EAS_U8 value;
1006
1007 value = 0;
1008
1009 /* do we have enough bits? */
1010 bitsLeft = pData->current.bitCount - numBits;
1011
1012 /* not enough bits, assemble them from 2 characters */
1013 if (bitsLeft < 0)
1014 {
1015 /* grab the remaining bits from the previous byte */
1016 if (pData->current.bitCount)
1017 /*lint -e{504,734} this is a legitimate shift operation */
1018 value = pData->current.dataByte << -bitsLeft;
1019
1020 /* read the next byte */
1021 if ((result = EAS_HWGetByte(hwInstData, pData->fileHandle, &pData->current.dataByte)) != EAS_SUCCESS)
1022 return result;
1023 bitsLeft += 8;
1024 }
1025
1026 /* more bits than needed? */
1027 if (bitsLeft > 0)
1028 {
1029 value |= pData->current.dataByte >> bitsLeft;
1030 pData->current.bitCount = (EAS_U8) bitsLeft;
1031 pData->current.dataByte = pData->current.dataByte & (0xff >> (8 - bitsLeft));
1032 }
1033
1034 /* exactly the right number of bits */
1035 else
1036 {
1037 value |= pData->current.dataByte;
1038 pData->current.bitCount = 0;
1039 }
1040
1041 *pValue = value;
1042 return EAS_SUCCESS;
1043 }
1044
1045 /*----------------------------------------------------------------------------
1046 * OTA_SavePosition()
1047 *----------------------------------------------------------------------------
1048 * Purpose:
1049 *
1050 *
1051 * Inputs:
1052 *
1053 *
1054 * Outputs:
1055 *
1056 *
1057 * Side Effects:
1058 *
1059 *----------------------------------------------------------------------------
1060 */
OTA_SavePosition(EAS_HW_DATA_HANDLE hwInstData,S_OTA_DATA * pData,S_OTA_LOC * pLoc)1061 static EAS_RESULT OTA_SavePosition (EAS_HW_DATA_HANDLE hwInstData, S_OTA_DATA *pData, S_OTA_LOC *pLoc)
1062 {
1063 EAS_HWMemCpy(pLoc, &pData->current, sizeof(S_OTA_LOC));
1064 return EAS_HWFilePos(hwInstData, pData->fileHandle, &pLoc->fileOffset);
1065 }
1066
1067 /*----------------------------------------------------------------------------
1068 * OTA_RestorePosition()
1069 *----------------------------------------------------------------------------
1070 * Purpose:
1071 *
1072 *
1073 * Inputs:
1074 *
1075 *
1076 * Outputs:
1077 *
1078 *
1079 * Side Effects:
1080 *
1081 *----------------------------------------------------------------------------
1082 */
OTA_RestorePosition(EAS_HW_DATA_HANDLE hwInstData,S_OTA_DATA * pData,S_OTA_LOC * pLoc)1083 static EAS_RESULT OTA_RestorePosition (EAS_HW_DATA_HANDLE hwInstData, S_OTA_DATA *pData, S_OTA_LOC *pLoc)
1084 {
1085 EAS_HWMemCpy(&pData->current, pLoc, sizeof(S_OTA_LOC));
1086 pData->restore.fileOffset = -1;
1087 return EAS_HWFileSeek(hwInstData, pData->fileHandle, pLoc->fileOffset);
1088 }
1089
1090