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