• 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 
85     /* determine the name of the output file */
86     wFile = NULL;
87     if (outputFile == NULL)
88     {
89         StrCopy(waveFilename, filename, sizeof(waveFilename));
90         if (!ChangeFileExt(waveFilename, "wav", sizeof(waveFilename)))
91         {
92             { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error in output filename %s\n", waveFilename); */ }
93             return EAS_FAILURE;
94         }
95         outputFile = waveFilename;
96     }
97 
98     /* call EAS library to open file */
99     if ((reportResult = EAS_OpenFile(easData, filename, &handle)) != EAS_SUCCESS)
100     {
101         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_OpenFile returned %ld\n", reportResult); */ }
102         return reportResult;
103     }
104 
105     /* prepare to play the file */
106     if ((result = EAS_Prepare(easData, handle)) != EAS_SUCCESS)
107     {
108         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_Prepare returned %ld\n", result); */ }
109         reportResult = result;
110     }
111 
112     /* get play length */
113     if ((result = EAS_ParseMetaData(easData, handle, &playTime)) != EAS_SUCCESS)
114     {
115         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_ParseMetaData returned %ld\n", result); */ }
116         return result;
117     }
118     EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0xe624f4d9, 0x00000005 , playTime / 1000, playTime % 1000);
119 
120     if (reportResult == EAS_SUCCESS)
121     {
122         /* create the output file */
123         wFile = WaveFileCreate(outputFile, pLibConfig->numChannels, pLibConfig->sampleRate, sizeof(EAS_PCM) * 8);
124         if (!wFile)
125         {
126             { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unable to create output file %s\n", waveFilename); */ }
127             reportResult = EAS_FAILURE;
128         }
129     }
130 
131     /* rendering loop */
132     while (reportResult == EAS_SUCCESS)
133     {
134 
135         /* we may render several buffers here to fill one host buffer */
136         for (i = 0, p = buffer; i < NUM_BUFFERS; i++, p+= pLibConfig->mixBufferSize * pLibConfig->numChannels)
137         {
138 
139             /* get the current time */
140             if ((result = EAS_GetLocation(easData, handle, &playTime)) != EAS_SUCCESS)
141             {
142                 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_GetLocation returned %d\n",result); */ }
143                 if (reportResult == EAS_SUCCESS)
144                     reportResult = result;
145                 break;
146             }
147             { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Parser time: %d.%03d\n", playTime / 1000, playTime % 1000); */ }
148 
149             /* render a buffer of audio */
150             if ((result = EAS_Render(easData, p, pLibConfig->mixBufferSize, &count)) != EAS_SUCCESS)
151             {
152                 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_Render returned %d\n",result); */ }
153                 if (reportResult == EAS_SUCCESS)
154                     reportResult = result;
155             }
156         }
157 
158         if (result == EAS_SUCCESS)
159         {
160             /* write it to the wave file */
161             if (WaveFileWrite(wFile, buffer, bufferSize) != bufferSize)
162             {
163                 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "WaveFileWrite failed\n"); */ }
164                 reportResult = EAS_FAILURE;
165             }
166         }
167 
168         if (reportResult == EAS_SUCCESS)
169         {
170             /* check stream state */
171             if ((result = EAS_State(easData, handle, &state)) != EAS_SUCCESS)
172             {
173                 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_State returned %d\n", result); */ }
174                 reportResult = result;
175             }
176 
177             /* is playback complete */
178             if ((state == EAS_STATE_STOPPED) || (state == EAS_STATE_ERROR))
179                 break;
180         }
181     }
182 
183     /* close the output file */
184     if (wFile)
185     {
186         if (!WaveFileClose(wFile))
187         {
188             { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error closing wave file %s\n", waveFilename); */ }
189             if (reportResult == EAS_SUCCESS)
190                 result = EAS_FAILURE;
191         }
192     }
193 
194     /* close the input file */
195     if ((result = EAS_CloseFile(easData,handle)) != EAS_SUCCESS)
196     {
197         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_Close returned %ld\n", result); */ }
198         if (reportResult == EAS_SUCCESS)
199             result = EAS_FAILURE;
200     }
201 
202     return reportResult;
203 } /* end PlayFile */
204 
205 /*----------------------------------------------------------------------------
206  * main()
207  *----------------------------------------------------------------------------
208  * Purpose: The entry point for the EAS sample application
209  *
210  * Inputs:
211  *
212  * Outputs:
213  *
214  *----------------------------------------------------------------------------
215 */
main(int argc,char ** argv)216 int main( int argc, char **argv )
217 {
218     EAS_DATA_HANDLE easData;
219     const S_EAS_LIB_CONFIG *pLibConfig;
220     void *buffer;
221     EAS_RESULT result, playResult;
222     EAS_I32 bufferSize;
223     int i;
224     int temp;
225     FILE *debugFile;
226     char *outputFile = NULL;
227 
228     /* set the error reporting level */
229     EAS_SetDebugLevel(_EAS_SEVERITY_INFO);
230     debugFile = NULL;
231 
232     /* process command-line arguments */
233     for (i = 1; i < argc; i++)
234     {
235         /* check for switch */
236         if (argv[i][0] == '-')
237         {
238             switch (argv[i][1])
239             {
240             case 'd':
241                 temp = argv[i][2];
242                 if ((temp >= '0') || (temp <= '9'))
243                     EAS_SetDebugLevel(temp);
244                 else
245                     { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Invalid debug level %d\n", temp); */ }
246                 break;
247             case 'f':
248                 if ((debugFile = fopen(&argv[i][2],"w")) == NULL)
249                     { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Unable to create debug file %s\n", &argv[i][2]); */ }
250                 else
251                     EAS_SetDebugFile(debugFile, EAS_TRUE);
252                 break;
253             case 'o':
254                 outputFile = &argv[i][2];
255                 break;
256             case 'p':
257                 polyphony = atoi(&argv[i][2]);
258                 if (polyphony < 1)
259                     polyphony = 1;
260                 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "Polyphony set to %d\n", polyphony); */ }
261                 break;
262             default:
263                 break;
264             }
265             continue;
266         }
267     }
268 
269     /* assume success */
270     playResult = EAS_SUCCESS;
271 
272     /* get the library configuration */
273     pLibConfig = EAS_Config();
274     if (!EASLibraryCheck(pLibConfig))
275         return -1;
276     if (polyphony > pLibConfig->maxVoices)
277         polyphony = pLibConfig->maxVoices;
278 
279     /* calculate buffer size */
280     bufferSize = pLibConfig->mixBufferSize * pLibConfig->numChannels * (EAS_I32)sizeof(EAS_PCM) * NUM_BUFFERS;
281 
282     /* allocate output buffer memory */
283     buffer = malloc((EAS_U32)bufferSize);
284     if (!buffer)
285     {
286         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Error allocating memory for audio buffer\n"); */ }
287         return EAS_FAILURE;
288     }
289 
290     /* initialize the EAS library */
291     polyphony = pLibConfig->maxVoices;
292     if ((result = EAS_Init(&easData)) != EAS_SUCCESS)
293     {
294         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "EAS_Init returned %ld - aborting!\n", result); */ }
295         free(buffer);
296         return result;
297     }
298 
299     /*
300      * Some debugging environments don't allow for passed parameters.
301      * In this case, just play the default MIDI file "test.mid"
302      */
303     if (argc < 2)
304     {
305         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "Playing '%s'\n", defaultTestFile); */ }
306         if ((playResult = PlayFile(easData, defaultTestFile, NULL, pLibConfig, buffer, bufferSize)) != EAS_SUCCESS)
307         {
308             { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %d playing file %s\n", playResult, defaultTestFile); */ }
309         }
310     }
311     /* iterate through the list of files to be played */
312     else
313     {
314         for (i = 1; i < argc; i++)
315         {
316             /* check for switch */
317             if (argv[i][0] != '-')
318             {
319 
320                 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "Playing '%s'\n", argv[i]); */ }
321                 if ((playResult = PlayFile(easData, argv[i], outputFile, pLibConfig, buffer, bufferSize)) != EAS_SUCCESS)
322                 {
323                     { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %d playing file %s\n", playResult, argv[i]); */ }
324                     break;
325                 }
326             }
327         }
328     }
329 
330     /* shutdown the EAS library */
331     if ((result = EAS_Shutdown(easData)) != EAS_SUCCESS)
332     {
333         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "EAS_Shutdown returned %ld\n", result); */ }
334     }
335 
336     /* free the output buffer */
337     free(buffer);
338 
339     /* close the debug file */
340     if (debugFile)
341         fclose(debugFile);
342 
343     /* play errors take precedence over shutdown errors */
344     if (playResult != EAS_SUCCESS)
345         return playResult;
346     return result;
347 } /* end main */
348 
349 /*----------------------------------------------------------------------------
350  * StrCopy()
351  *----------------------------------------------------------------------------
352  * Purpose:
353  * Safe string copy
354  *
355  * Inputs:
356  *
357  * Outputs:
358  *
359  *----------------------------------------------------------------------------
360 */
StrCopy(char * dest,const char * src,EAS_I32 size)361 static void StrCopy(char *dest, const char *src, EAS_I32 size)
362 {
363     int len;
364 
365     strncpy(dest, src, (size_t) size-1);
366     len = (int) strlen(src);
367     if (len < size)
368         dest[len] = 0;
369 } /* end StrCopy */
370 
371 /*----------------------------------------------------------------------------
372  * ChangeFileExt()
373  *----------------------------------------------------------------------------
374  * Purpose:
375  * Changes the file extension of a filename
376  *
377  * Inputs:
378  *
379  * Outputs:
380  *
381  *----------------------------------------------------------------------------
382 */
ChangeFileExt(char * str,const char * ext,EAS_I32 size)383 static EAS_BOOL ChangeFileExt(char *str, const char *ext, EAS_I32 size)
384 {
385     char *p;
386 
387     /* find the extension, if any */
388     p = strrchr(str,'.');
389     if (!p)
390     {
391         if ((EAS_I32)(strlen(str) + 5) > size)
392             return EAS_FALSE;
393         strcat(str,".");
394         strcat(str,ext);
395         return EAS_TRUE;
396     }
397 
398     /* make sure there's room for the extension */
399     p++;
400     *p = 0;
401     if ((EAS_I32)(strlen(str) + 4) > size)
402         return EAS_FALSE;
403     strcat(str,ext);
404     return EAS_TRUE;
405 } /* end ChangeFileExt */
406 
407 /*----------------------------------------------------------------------------
408  * EASLibraryCheck()
409  *----------------------------------------------------------------------------
410  * Purpose:
411  * Displays the library version and checks it against the header
412  * file used to build this code.
413  *
414  * Inputs:
415  * pLibConfig       - library configuration retrieved from the library
416  *
417  * Outputs:
418  * returns EAS_TRUE if matched
419  *
420  * Side Effects:
421  *
422  *----------------------------------------------------------------------------
423 */
EASLibraryCheck(const S_EAS_LIB_CONFIG * pLibConfig)424 static EAS_BOOL EASLibraryCheck (const S_EAS_LIB_CONFIG *pLibConfig)
425 {
426 
427     /* display the library version */
428     { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "EAS Library Version %d.%d.%d.%d\n",
429         pLibConfig->libVersion >> 24,
430         (pLibConfig->libVersion >> 16) & 0x0f,
431         (pLibConfig->libVersion >> 8) & 0x0f,
432         pLibConfig->libVersion & 0x0f); */ }
433 
434     /* display some info about the library build */
435     if (pLibConfig->checkedVersion)
436         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tChecked library\n"); */ }
437     { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tMaximum polyphony: %d\n", pLibConfig->maxVoices); */ }
438     { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tNumber of channels: %d\n", pLibConfig->numChannels); */ }
439     { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tSample rate: %d\n", pLibConfig->sampleRate); */ }
440     { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tMix buffer size: %d\n", pLibConfig->mixBufferSize); */ }
441     if (pLibConfig->filterEnabled)
442         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tFilter enabled\n"); */ }
443 #ifndef _WIN32_WCE
444     { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tLibrary Build Timestamp: %s", ctime((time_t*)&pLibConfig->buildTimeStamp)); */ }
445 #endif
446     { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tLibrary Build ID: %s\n", pLibConfig->buildGUID); */ }
447 
448     /* check it against the header file used to build this code */
449     /*lint -e{778} constant expression used for display purposes may evaluate to zero */
450     if (LIB_VERSION != pLibConfig->libVersion)
451     {
452         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Library version does not match header files. EAS Header Version %d.%d.%d.%d\n",
453             LIB_VERSION >> 24,
454             (LIB_VERSION >> 16) & 0x0f,
455             (LIB_VERSION >> 8) & 0x0f,
456             LIB_VERSION & 0x0f); */ }
457         return EAS_FALSE;
458     }
459     return EAS_TRUE;
460 } /* end EASLibraryCheck */
461 
462