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