1 /*--------------------------------------------------------------------------*
2   Project:  Revolution SOUNDFILE dynamic link library
3   File:     soundfile.c
4 
5   Copyright (C)1998-2009 Nintendo  All Rights Reserved
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Log: soundfile.c,v $
14   Revision 1.4  2009/03/30 07:44:45  aka
15   Copied from SDK_3_2_DEV_BRANCH.
16 
17   Revision 1.3.4.1  2009/03/30 04:40:35  aka
18   Added supporting a wav file with loop information.
19 
20   Revision 1.3  2007/11/30 04:19:32  iwai_yuma
21   Related to Visual Studio 2005
22 
23   Revision 1.3  2007/11/22 21:57:56  iwai
24   Replaced unsecure function to secure one.
25 
26   Revision 1.2  2006/02/09 06:51:39  aka
27   Changed copyright.
28 
29  *--------------------------------------------------------------------------*/
30 
31 #include <windows.h>
32 #include <stdio.h>
33 #include "Types.h"
34 #include "soundfile.h"
35 #include "endian.h"
36 #include "aifffile.h"
37 #include "Wavfile.h"
38 
39 
40 #define SOUND_FILE_WAVE 0
41 #define SOUND_FILE_AIFF 1
42 
43 
44 /*---------------------------------------------------------------------------*
45   Name:         getAiffInfo
46 
47   Description:  get AIFF file information.
48 
49   Arguments:    path          path of an AIFF file.
50                 soundinfo     pointer of a SOUNDINFO structure.
51                 buffer        pointer of a samples buffer.
52 
53   Returns:      SOUND_FILE_SUCCESS       OK.
54                 SOUND_FILE_FOPEN_ERROR   can't open an AIFF file.
55  *---------------------------------------------------------------------------*/
56 
getAiffInfo(char * path,SOUNDINFO * soundinfo,void * buffer)57 int getAiffInfo(char *path, SOUNDINFO *soundinfo, void *buffer)
58 {
59     FILE        *file;
60     AIFFINFO    aiffinfo;
61     errno_t     err;
62 
63     if (( err = fopen_s( &file, path, "rb" ) ) != 0)
64     {
65         return SOUND_FILE_FOPEN_ERROR;
66     }
67 
68     aiffReadHeader(&aiffinfo, file);
69 
70     soundinfo->channels      = aiffGetChannels(&aiffinfo);
71     soundinfo->bitsPerSample = aiffGetBitsPerSample(&aiffinfo);
72     soundinfo->sampleRate    = aiffGetSampleRate(&aiffinfo);
73     soundinfo->samples       = aiffGetSamples(&aiffinfo);
74     soundinfo->loopStart     = aiffGetLoopStart(&aiffinfo);
75     soundinfo->loopEnd       = aiffGetLoopEnd(&aiffinfo);
76     soundinfo->bufferLength  = 0;
77 
78     switch (soundinfo->bitsPerSample)
79     {
80         case 8:
81 
82             soundinfo->bufferLength = soundinfo->samples * soundinfo->channels;
83 
84             break;
85 
86         case 16:
87 
88             soundinfo->bufferLength = soundinfo->samples * soundinfo->channels * 2;
89 
90             break;
91     }
92 
93     if (buffer)
94     {
95         fread(buffer, soundinfo->bufferLength, 1, file);
96 
97         if (soundinfo->bitsPerSample == 16)
98         {
99             reverse_buffer_16(buffer, soundinfo->bufferLength / 2);
100         }
101     }
102 
103     fclose(file);
104 
105     return SOUND_FILE_SUCCESS;
106 }
107 
108 
109 /*---------------------------------------------------------------------------*
110   Name:         getWaveInfo
111 
112   Description:  get Wave file information.
113 
114   Arguments:    path          path of a Wave file.
115                 soundinfo     pointer of a SOUNDINFO structure.
116                 buffer        pointer of a samples buffer.
117 
118   Returns:      SOUND_FILE_SUCCESS       OK.
119                 SOUND_FILE_FOPEN_ERROR   can't open a Wave file.
120  *---------------------------------------------------------------------------*/
121 
getWaveInfo(char * path,SOUNDINFO * soundinfo,void * buffer)122 int getWaveInfo(char *path, SOUNDINFO *soundinfo, void *buffer)
123 {
124     FILE        *file;
125     WAVECHUNK   wavechunk;
126     LOOPINFO    loopinfo;
127     errno_t     err;
128 
129     if (( err = fopen_s( &file, path, "rb" ) ) != 0)
130     {
131         return SOUND_FILE_FOPEN_ERROR;
132     }
133 
134     wavReadHeader(&wavechunk, &loopinfo, file);
135 
136     soundinfo->channels      = wavGetChannels(&wavechunk);
137     soundinfo->bitsPerSample = wavGetBitsPerSample(&wavechunk);
138     soundinfo->sampleRate    = wavGetSampleRate(&wavechunk);
139     soundinfo->samples       = wavGetSamples(&wavechunk);
140     soundinfo->loopStart     = loopinfo.start;
141     soundinfo->loopEnd       = loopinfo.end;
142     soundinfo->bufferLength  = 0;
143 
144     switch (soundinfo->bitsPerSample)
145     {
146         case 8:
147 
148             soundinfo->bufferLength = soundinfo->samples * soundinfo->channels;
149 
150             break;
151 
152         case 16:
153 
154             soundinfo->bufferLength = soundinfo->samples * soundinfo->channels * 2;
155 
156             break;
157     }
158 
159     if (buffer)
160     {
161         fread(buffer, soundinfo->bufferLength, 1, file);
162 
163         if (soundinfo->bitsPerSample == 8)
164         {
165             int i;
166             char *p;
167 
168             p = buffer;
169 
170             for (i = 0; i < soundinfo->bufferLength; i++)
171             {
172                 *p = *p + 0x80;
173                 p++;
174             }
175         }
176     }
177 
178     fclose(file);
179 
180     return SOUND_FILE_SUCCESS;
181 }
182 
183 
184 /*---------------------------------------------------------------------------*
185   Name:         getFileType
186 
187   Description:  check file type (AIFF or Wave) of an input file.
188 
189   Arguments:    path          path of an input file.
190                 soundinfo     pointer of a SOUNDINFO structure (not used).
191 
192   Returns:      SOUND_FILE_FORMAT_ERROR  neither AIFF nor Wave.
193                 SOUND_FILE_AIFF          AIFF.
194                 SOUND_FILE_WAVE          Wave.
195                 SOUND_FILE_FOPEN_ERROR   can't open an input file.
196  *---------------------------------------------------------------------------*/
197 
getFileType(char * path,SOUNDINFO * soundinfo)198 int getFileType(char *path, SOUNDINFO *soundinfo)
199 {
200     FILE        *file;
201     u32         data, result;
202     errno_t     err;
203 
204     if (( err = fopen_s( &file, path, "rb" ) ) != 0)
205     {
206         return SOUND_FILE_FOPEN_ERROR;
207     }
208     else
209     {
210         result = SOUND_FILE_FORMAT_ERROR;
211     }
212 
213     fread(&data, 1, sizeof(u32), file);
214 
215     switch (data)
216     {
217         case CHUNK_FORM:
218 
219             fread(&data, 1, sizeof(u32), file);
220             fread(&data, 1, sizeof(u32), file);
221 
222             if (data == CHUNK_AIFF)
223             {
224                 result = SOUND_FILE_AIFF;
225             }
226 
227             break;
228 
229         case CHUNK_RIFF:
230 
231             fread(&data, 1, sizeof(u32), file);
232             fread(&data, 1, sizeof(u32), file);
233 
234             if (data == CHUNK_WAVE)
235             {
236                 result = SOUND_FILE_WAVE;
237             }
238 
239             break;
240     }
241 
242     fclose(file);
243 
244     return result;
245 }
246 
247 
248 /*---------------------------------------------------------------------------*
249   Name:         getSoundInfo
250 
251   Description:  get information of an input sound file (AIFF or Wave).
252 
253   Arguments:    path          path of an input file.
254                 soundinfo     pointer of a SOUNDINFO structure.
255 
256   Returns:      SOUND_FILE_SUCCESS       OK.
257                 SOUND_FILE_FOPEN_ERROR   can't open an AIFF file.
258                 SOUND_FILE_FORMAT_ERROR  neither AIFF nor Wave.
259  *---------------------------------------------------------------------------*/
260 
getSoundInfo(char * path,SOUNDINFO * soundinfo)261 int getSoundInfo(char *path, SOUNDINFO *soundinfo)
262 {
263     u32 result = getFileType(path, soundinfo);
264 
265     switch (result)
266     {
267         case SOUND_FILE_AIFF:
268 
269             result = getAiffInfo(path, soundinfo, NULL);
270 
271             break;
272 
273         case SOUND_FILE_WAVE:
274 
275             result = getWaveInfo(path, soundinfo, NULL);
276 
277             break;
278     }
279 
280     return result;
281 }
282 
283 
284 /*---------------------------------------------------------------------------*
285   Name:         getSoundSamples
286 
287   Description:  get information and samples of an input sound file (AIFF or Wave).
288 
289   Arguments:    path          path of an input file.
290                 soundinfo     pointer of a SOUNDINFO structure.
291                 dest          pointer of a samples buffer.
292 
293   Returns:      SOUND_FILE_SUCCESS       OK.
294                 SOUND_FILE_FOPEN_ERROR   can't open an AIFF file.
295                 SOUND_FILE_FORMAT_ERROR  neither AIFF nor Wave.
296  *---------------------------------------------------------------------------*/
297 
getSoundSamples(char * path,SOUNDINFO * soundinfo,void * dest)298 int getSoundSamples(char *path, SOUNDINFO *soundinfo, void *dest)
299 {
300     u32 result = getFileType(path, soundinfo);
301 
302     switch (result)
303     {
304         case SOUND_FILE_AIFF:
305 
306             result = getAiffInfo(path, soundinfo, dest);
307 
308             break;
309 
310         case SOUND_FILE_WAVE:
311 
312             result = getWaveInfo(path, soundinfo, dest);
313 
314             break;
315     }
316 
317     return result;
318 }
319 
320 
321 /*---------------------------------------------------------------------------*
322   Name:         writeWaveFile
323 
324   Description:  create a Wave file.
325 
326   Arguments:    path          path of an output file.
327                 soundinfo     pointer of a SOUNDINFO structure.
328                 samples       pointer of a samples buffer.
329 
330   Returns:      SOUND_FILE_SUCCESS       OK.
331                 SOUND_FILE_FOPEN_ERROR   can't open an output file.
332  *---------------------------------------------------------------------------*/
333 
writeWaveFile(char * path,SOUNDINFO * info,void * samples)334 int writeWaveFile(char *path, SOUNDINFO *info, void *samples)
335 {
336     WAVECHUNK   wavechunk;
337     SMPLCHUNK   smpl;
338     SMPLLOOP    loop;
339     FILE        *file;
340     errno_t     err;
341 
342     if (( err = fopen_s( &file, path, "wb" ) ) != 0)
343     {
344         return SOUND_FILE_FOPEN_ERROR;
345     }
346 
347     wavCreateHeader(
348         &wavechunk,
349         info->channels,
350         info->samples,
351         info->bitsPerSample,
352         info->sampleRate,
353         info->loopEnd
354         );
355 
356     wavWriteHeader(
357         &wavechunk,
358         file
359         );
360 
361     fwrite(samples, info->bufferLength, sizeof(char), file);
362 
363     if (info->loopEnd)
364     {
365         wavCreateSmplChunk(&wavechunk, &smpl, &loop, info->loopStart, info->loopEnd);
366         wavWriteSmplChunk(&smpl, &loop, file);
367     }
368 
369     fclose(file);
370 
371     return SOUND_FILE_SUCCESS;
372 }
373 
374 
375 /*---------------------------------------------------------------------------*
376   Name:         writeAiffFile
377 
378   Description:  create an AIFF file.
379 
380   Arguments:    path          path of an output file.
381                 soundinfo     pointer of a SOUNDINFO structure.
382                 samples       pointer of a samples buffer.
383 
384   Returns:      SOUND_FILE_SUCCESS       OK.
385                 SOUND_FILE_FOPEN_ERROR   can't open an output file.
386  *---------------------------------------------------------------------------*/
387 
writeAiffFile(char * path,SOUNDINFO * info,void * samples)388 int writeAiffFile(char *path, SOUNDINFO *info, void *samples)
389 {
390     AIFFINFO    aiffinfo;
391     FILE        *file;
392     errno_t     err;
393 
394     if (( err = fopen_s( &file, path, "wb" ) ) != 0)
395     {
396         return SOUND_FILE_FOPEN_ERROR;
397     }
398 
399     aiffCreateHeader(
400         &aiffinfo,
401         info->channels,
402         info->samples,
403         info->bitsPerSample,
404         info->sampleRate
405         );
406 
407     aiffWriteHeader(
408         &aiffinfo,
409         file,
410         info->channels,
411         info->samples,
412         info->bitsPerSample,
413         info->loopEnd
414         );
415 
416     if (info->bitsPerSample == 16)
417     {
418         reverse_buffer_16(samples, info->bufferLength / 2);
419     }
420 
421     fwrite(samples, info->bufferLength, sizeof(char), file);
422 
423     if (info->loopEnd)
424     {
425         aiffCreateMark(&aiffinfo, info->loopStart, info->loopEnd);
426         aiffWriteMark(&aiffinfo, file);
427     }
428 
429     fclose(file);
430 
431     return SOUND_FILE_SUCCESS;
432 }
433