Home | History | Annotate | Download | only in host_src
      1 /*----------------------------------------------------------------------------
      2  *
      3  * File:
      4  * eas_main.c
      5  *
      6  * Contents and purpose:
      7  * The entry point and high-level functions for the EAS Synthesizer test
      8  * harness.
      9  *
     10  * Copyright Sonic Network Inc. 2004
     11 
     12  * Licensed under the Apache License, Version 2.0 (the "License");
     13  * you may not use this file except in compliance with the License.
     14  * You may obtain a copy of the License at
     15  *
     16  *      http://www.apache.org/licenses/LICENSE-2.0
     17  *
     18  * Unless required by applicable law or agreed to in writing, software
     19  * distributed under the License is distributed on an "AS IS" BASIS,
     20  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     21  * See the License for the specific language governing permissions and
     22  * limitations under the License.
     23  *
     24  *----------------------------------------------------------------------------
     25  * Revision Control:
     26  *   $Revision: 775 $
     27  *   $Date: 2007-07-20 10:11:11 -0700 (Fri, 20 Jul 2007) $
     28  *----------------------------------------------------------------------------
     29 */
     30 
     31 #ifdef _lint
     32 #include "lint_stdlib.h"
     33 #else
     34 #include <stdio.h>
     35 #include <string.h>
     36 #include <stdlib.h>
     37 #include <time.h>
     38 #endif
     39 
     40 #include "eas.h"
     41 #include "eas_wave.h"
     42 #include "eas_report.h"
     43 
     44 /* determines how many EAS buffers to fill a host buffer */
     45 #define NUM_BUFFERS         8
     46 
     47 /* default file to play if no filename is specified on the command line */
     48 static const char defaultTestFile[] = "test.mid";
     49 
     50 EAS_I32 polyphony;
     51 
     52 /* prototypes for helper functions */
     53 static void StrCopy(char *dest, const char *src, EAS_I32 size);
     54 static EAS_BOOL ChangeFileExt(char *str, const char *ext, EAS_I32 size);
     55 static EAS_RESULT PlayFile (EAS_DATA_HANDLE easData, const char* filename, const char* outputFile, const S_EAS_LIB_CONFIG *pLibConfig, void *buffer, EAS_I32 bufferSize);
     56 static EAS_BOOL EASLibraryCheck (const S_EAS_LIB_CONFIG *pLibConfig);
     57 
     58 /* main is defined after playfile to avoid the need for two passes through lint */
     59 
     60 /*----------------------------------------------------------------------------
     61  * PlayFile()
     62  *----------------------------------------------------------------------------
     63  * Purpose:
     64  * This function plays the file requested by filename
     65  *
     66  * Inputs:
     67  *
     68  * Outputs:
     69  *
     70  *----------------------------------------------------------------------------
     71 */
     72 
     73 static EAS_RESULT PlayFile (EAS_DATA_HANDLE easData, const char* filename, const char* outputFile, const S_EAS_LIB_CONFIG *pLibConfig, void *buffer, EAS_I32 bufferSize)
     74 {
     75     EAS_HANDLE handle;
     76     EAS_RESULT result, reportResult;
     77     EAS_I32 count;
     78     EAS_STATE state;
     79     EAS_I32 playTime;
     80     char waveFilename[256];
     81     WAVE_FILE *wFile;
     82     EAS_INT i;
     83     EAS_PCM *p;
     84     EAS_FILE file;
     85 
     86     /* determine the name of the output file */
     87     wFile = NULL;
     88     if (outputFile == NULL)
     89     {
     90         StrCopy(waveFilename, filename, sizeof(waveFilename));
     91         if (!ChangeFileExt(waveFilename, "wav", sizeof(waveFilename)))
     92         {
     93             { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error in output filename %s\n", waveFilename); */ }
     94             return EAS_FAILURE;
     95         }
     96         outputFile = waveFilename;
     97     }
     98 
     99     /* call EAS library to open file */
    100     file.path = filename;
    101     file.fd = 0;
    102     if ((reportResult = EAS_OpenFile(easData, &file, &handle)) != EAS_SUCCESS)
    103     {
    104         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_OpenFile returned %ld\n", reportResult); */ }
    105         return reportResult;
    106     }
    107 
    108     /* prepare to play the file */
    109     if ((result = EAS_Prepare(easData, handle)) != EAS_SUCCESS)
    110     {
    111         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_Prepare returned %ld\n", result); */ }
    112         reportResult = result;
    113     }
    114 
    115     /* get play length */
    116     if ((result = EAS_ParseMetaData(easData, handle, &playTime)) != EAS_SUCCESS)
    117     {
    118         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_ParseMetaData returned %ld\n", result); */ }
    119         return result;
    120     }
    121     EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0xe624f4d9, 0x00000005 , playTime / 1000, playTime % 1000);
    122 
    123     if (reportResult == EAS_SUCCESS)
    124     {
    125         /* create the output file */
    126         wFile = WaveFileCreate(outputFile, pLibConfig->numChannels, pLibConfig->sampleRate, sizeof(EAS_PCM) * 8);
    127         if (!wFile)
    128         {
    129             { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unable to create output file %s\n", waveFilename); */ }
    130             reportResult = EAS_FAILURE;
    131         }
    132     }
    133 
    134     /* rendering loop */
    135     while (reportResult == EAS_SUCCESS)
    136     {
    137 
    138         /* we may render several buffers here to fill one host buffer */
    139         for (i = 0, p = buffer; i < NUM_BUFFERS; i++, p+= pLibConfig->mixBufferSize * pLibConfig->numChannels)
    140         {
    141 
    142             /* get the current time */
    143             if ((result = EAS_GetLocation(easData, handle, &playTime)) != EAS_SUCCESS)
    144             {
    145                 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_GetLocation returned %d\n",result); */ }
    146                 if (reportResult == EAS_SUCCESS)
    147                     reportResult = result;
    148                 break;
    149             }
    150             { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Parser time: %d.%03d\n", playTime / 1000, playTime % 1000); */ }
    151 
    152             /* render a buffer of audio */
    153             if ((result = EAS_Render(easData, p, pLibConfig->mixBufferSize, &count)) != EAS_SUCCESS)
    154             {
    155                 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_Render returned %d\n",result); */ }
    156                 if (reportResult == EAS_SUCCESS)
    157                     reportResult = result;
    158             }
    159         }
    160 
    161         if (result == EAS_SUCCESS)
    162         {
    163             /* write it to the wave file */
    164             if (WaveFileWrite(wFile, buffer, bufferSize) != bufferSize)
    165             {
    166                 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "WaveFileWrite failed\n"); */ }
    167                 reportResult = EAS_FAILURE;
    168             }
    169         }
    170 
    171         if (reportResult == EAS_SUCCESS)
    172         {
    173             /* check stream state */
    174             if ((result = EAS_State(easData, handle, &state)) != EAS_SUCCESS)
    175             {
    176                 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_State returned %d\n", result); */ }
    177                 reportResult = result;
    178             }
    179 
    180             /* is playback complete */
    181             if ((state == EAS_STATE_STOPPED) || (state == EAS_STATE_ERROR))
    182                 break;
    183         }
    184     }
    185 
    186     /* close the output file */
    187     if (wFile)
    188     {
    189         if (!WaveFileClose(wFile))
    190         {
    191             { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error closing wave file %s\n", waveFilename); */ }
    192             if (reportResult == EAS_SUCCESS)
    193                 result = EAS_FAILURE;
    194         }
    195     }
    196 
    197     /* close the input file */
    198     if ((result = EAS_CloseFile(easData,handle)) != EAS_SUCCESS)
    199     {
    200         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_Close returned %ld\n", result); */ }
    201         if (reportResult == EAS_SUCCESS)
    202             result = EAS_FAILURE;
    203     }
    204 
    205     return reportResult;
    206 } /* end PlayFile */
    207 
    208 /*----------------------------------------------------------------------------
    209  * main()
    210  *----------------------------------------------------------------------------
    211  * Purpose: The entry point for the EAS sample application
    212  *
    213  * Inputs:
    214  *
    215  * Outputs:
    216  *
    217  *----------------------------------------------------------------------------
    218 */
    219 int main( int argc, char **argv )
    220 {
    221     EAS_DATA_HANDLE easData;
    222     const S_EAS_LIB_CONFIG *pLibConfig;
    223     void *buffer;
    224     EAS_RESULT result, playResult;
    225     EAS_I32 bufferSize;
    226     int i;
    227     int temp;
    228     FILE *debugFile;
    229     char *outputFile = NULL;
    230 
    231     /* set the error reporting level */
    232     EAS_SetDebugLevel(_EAS_SEVERITY_INFO);
    233     debugFile = NULL;
    234 
    235     /* process command-line arguments */
    236     for (i = 1; i < argc; i++)
    237     {
    238         /* check for switch */
    239         if (argv[i][0] == '-')
    240         {
    241             switch (argv[i][1])
    242             {
    243             case 'd':
    244                 temp = argv[i][2];
    245                 if ((temp >= '0') || (temp <= '9'))
    246                     EAS_SetDebugLevel(temp);
    247                 else
    248                     { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Invalid debug level %d\n", temp); */ }
    249                 break;
    250             case 'f':
    251                 if ((debugFile = fopen(&argv[i][2],"w")) == NULL)
    252                     { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Unable to create debug file %s\n", &argv[i][2]); */ }
    253                 else
    254                     EAS_SetDebugFile(debugFile, EAS_TRUE);
    255                 break;
    256             case 'o':
    257                 outputFile = &argv[i][2];
    258                 break;
    259             case 'p':
    260                 polyphony = atoi(&argv[i][2]);
    261                 if (polyphony < 1)
    262                     polyphony = 1;
    263                 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "Polyphony set to %d\n", polyphony); */ }
    264                 break;
    265             default:
    266                 break;
    267             }
    268             continue;
    269         }
    270     }
    271 
    272     /* assume success */
    273     playResult = EAS_SUCCESS;
    274 
    275     /* get the library configuration */
    276     pLibConfig = EAS_Config();
    277     if (!EASLibraryCheck(pLibConfig))
    278         return -1;
    279     if (polyphony > pLibConfig->maxVoices)
    280         polyphony = pLibConfig->maxVoices;
    281 
    282     /* calculate buffer size */
    283     bufferSize = pLibConfig->mixBufferSize * pLibConfig->numChannels * (EAS_I32)sizeof(EAS_PCM) * NUM_BUFFERS;
    284 
    285     /* allocate output buffer memory */
    286     buffer = malloc((EAS_U32)bufferSize);
    287     if (!buffer)
    288     {
    289         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Error allocating memory for audio buffer\n"); */ }
    290         return EAS_FAILURE;
    291     }
    292 
    293     /* initialize the EAS library */
    294     polyphony = pLibConfig->maxVoices;
    295     if ((result = EAS_Init(&easData)) != EAS_SUCCESS)
    296     {
    297         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "EAS_Init returned %ld - aborting!\n", result); */ }
    298         free(buffer);
    299         return result;
    300     }
    301 
    302     /*
    303      * Some debugging environments don't allow for passed parameters.
    304      * In this case, just play the default MIDI file "test.mid"
    305      */
    306     if (argc < 2)
    307     {
    308         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "Playing '%s'\n", defaultTestFile); */ }
    309         if ((playResult = PlayFile(easData, defaultTestFile, NULL, pLibConfig, buffer, bufferSize)) != EAS_SUCCESS)
    310         {
    311             { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %d playing file %s\n", playResult, defaultTestFile); */ }
    312         }
    313     }
    314     /* iterate through the list of files to be played */
    315     else
    316     {
    317         for (i = 1; i < argc; i++)
    318         {
    319             /* check for switch */
    320             if (argv[i][0] != '-')
    321             {
    322 
    323                 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "Playing '%s'\n", argv[i]); */ }
    324                 if ((playResult = PlayFile(easData, argv[i], outputFile, pLibConfig, buffer, bufferSize)) != EAS_SUCCESS)
    325                 {
    326                     { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %d playing file %s\n", playResult, argv[i]); */ }
    327                     break;
    328                 }
    329             }
    330         }
    331     }
    332 
    333     /* shutdown the EAS library */
    334     if ((result = EAS_Shutdown(easData)) != EAS_SUCCESS)
    335     {
    336         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "EAS_Shutdown returned %ld\n", result); */ }
    337     }
    338 
    339     /* free the output buffer */
    340     free(buffer);
    341 
    342     /* close the debug file */
    343     if (debugFile)
    344         fclose(debugFile);
    345 
    346     /* play errors take precedence over shutdown errors */
    347     if (playResult != EAS_SUCCESS)
    348         return playResult;
    349     return result;
    350 } /* end main */
    351 
    352 /*----------------------------------------------------------------------------
    353  * StrCopy()
    354  *----------------------------------------------------------------------------
    355  * Purpose:
    356  * Safe string copy
    357  *
    358  * Inputs:
    359  *
    360  * Outputs:
    361  *
    362  *----------------------------------------------------------------------------
    363 */
    364 static void StrCopy(char *dest, const char *src, EAS_I32 size)
    365 {
    366     int len;
    367 
    368     strncpy(dest, src, (size_t) size-1);
    369     len = (int) strlen(src);
    370     if (len < size)
    371         dest[len] = 0;
    372 } /* end StrCopy */
    373 
    374 /*----------------------------------------------------------------------------
    375  * ChangeFileExt()
    376  *----------------------------------------------------------------------------
    377  * Purpose:
    378  * Changes the file extension of a filename
    379  *
    380  * Inputs:
    381  *
    382  * Outputs:
    383  *
    384  *----------------------------------------------------------------------------
    385 */
    386 static EAS_BOOL ChangeFileExt(char *str, const char *ext, EAS_I32 size)
    387 {
    388     char *p;
    389 
    390     /* find the extension, if any */
    391     p = strrchr(str,'.');
    392     if (!p)
    393     {
    394         if ((EAS_I32)(strlen(str) + 5) > size)
    395             return EAS_FALSE;
    396         strcat(str,".");
    397         strcat(str,ext);
    398         return EAS_TRUE;
    399     }
    400 
    401     /* make sure there's room for the extension */
    402     p++;
    403     *p = 0;
    404     if ((EAS_I32)(strlen(str) + 4) > size)
    405         return EAS_FALSE;
    406     strcat(str,ext);
    407     return EAS_TRUE;
    408 } /* end ChangeFileExt */
    409 
    410 /*----------------------------------------------------------------------------
    411  * EASLibraryCheck()
    412  *----------------------------------------------------------------------------
    413  * Purpose:
    414  * Displays the library version and checks it against the header
    415  * file used to build this code.
    416  *
    417  * Inputs:
    418  * pLibConfig       - library configuration retrieved from the library
    419  *
    420  * Outputs:
    421  * returns EAS_TRUE if matched
    422  *
    423  * Side Effects:
    424  *
    425  *----------------------------------------------------------------------------
    426 */
    427 static EAS_BOOL EASLibraryCheck (const S_EAS_LIB_CONFIG *pLibConfig)
    428 {
    429 
    430     /* display the library version */
    431     { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "EAS Library Version %d.%d.%d.%d\n",
    432         pLibConfig->libVersion >> 24,
    433         (pLibConfig->libVersion >> 16) & 0x0f,
    434         (pLibConfig->libVersion >> 8) & 0x0f,
    435         pLibConfig->libVersion & 0x0f); */ }
    436 
    437     /* display some info about the library build */
    438     if (pLibConfig->checkedVersion)
    439         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tChecked library\n"); */ }
    440     { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tMaximum polyphony: %d\n", pLibConfig->maxVoices); */ }
    441     { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tNumber of channels: %d\n", pLibConfig->numChannels); */ }
    442     { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tSample rate: %d\n", pLibConfig->sampleRate); */ }
    443     { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tMix buffer size: %d\n", pLibConfig->mixBufferSize); */ }
    444     if (pLibConfig->filterEnabled)
    445         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tFilter enabled\n"); */ }
    446 #ifndef _WIN32_WCE
    447     { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tLibrary Build Timestamp: %s", ctime((time_t*)&pLibConfig->buildTimeStamp)); */ }
    448 #endif
    449     { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tLibrary Build ID: %s\n", pLibConfig->buildGUID); */ }
    450 
    451     /* check it against the header file used to build this code */
    452     /*lint -e{778} constant expression used for display purposes may evaluate to zero */
    453     if (LIB_VERSION != pLibConfig->libVersion)
    454     {
    455         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Library version does not match header files. EAS Header Version %d.%d.%d.%d\n",
    456             LIB_VERSION >> 24,
    457             (LIB_VERSION >> 16) & 0x0f,
    458             (LIB_VERSION >> 8) & 0x0f,
    459             LIB_VERSION & 0x0f); */ }
    460         return EAS_FALSE;
    461     }
    462     return EAS_TRUE;
    463 } /* end EASLibraryCheck */
    464 
    465