• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
PlayFile(EAS_DATA_HANDLE easData,const char * filename,const char * outputFile,const S_EAS_LIB_CONFIG * pLibConfig,void * buffer,EAS_I32 bufferSize)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 */
main(int argc,char ** argv)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 */
StrCopy(char * dest,const char * src,EAS_I32 size)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 */
ChangeFileExt(char * str,const char * ext,EAS_I32 size)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 */
EASLibraryCheck(const S_EAS_LIB_CONFIG * pLibConfig)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