1 /*--------------------------------------------------------------------------*
2 Project: Revolution Audio sound file converter
3 File: output.c
4
5 Copyright (C)1998-2006 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: output.c,v $
14 Revision 1.2 02/09/2006 06:26:26 aka
15 Changed copyright.
16
17
18 *--------------------------------------------------------------------------*/
19 #include <stdio.h>
20 #include <memory.h>
21 #include <string.h>
22 #include "soundconv.h"
23 #include "endian.h"
24 #include "types.h"
25
26
27 /*--------------------------------------------------------------------------*
28 exports for dsptool.dll
29 *--------------------------------------------------------------------------*/
30 typedef int (*FUNCTION3)(int);
31 extern FUNCTION3 getNibbleAddress;
32
33
34 /*--------------------------------------------------------------------------*
35 local variables
36 *--------------------------------------------------------------------------*/
37 u32 soundEntries;
38 u32 soundAdpcmEntries;
39 u32 soundByteOffset;
40
41 SNDCONVDATA soundConvdata[0xFFFF];
42 ADPCMINFO soundAdpcminfo[0xFFFF];
43
44 FILE *outputHeader;
45 FILE *outputTable;
46 FILE *outputSamples;
47
48 /*--------------------------------------------------------------------------*
49 add an entry
50 *--------------------------------------------------------------------------*/
soundOutputAddEntry(u32 format,u32 dataBytes,void * buffer,u32 samples,u32 sampleRate,u32 loopStart,u32 loopEnd,ADPCMINFO * adpcminfo,char * headerId)51 void soundOutputAddEntry(
52 u32 format,
53 u32 dataBytes,
54 void *buffer,
55 u32 samples,
56 u32 sampleRate,
57 u32 loopStart,
58 u32 loopEnd,
59 ADPCMINFO *adpcminfo,
60 char *headerId
61 )
62 {
63 SNDCONVDATA *sndconvdata = &soundConvdata[soundEntries];
64
65 switch (format)
66 {
67 case SOUND_FORMAT_ADPCM:
68
69 // 8 byte-aligned ADPCM buffers
70 while (soundByteOffset % 8)
71 {
72 char ch = 0;
73 fwrite(&ch, 1, 1, outputSamples);
74 soundByteOffset++;
75 }
76
77 // looped sound
78 if (loopEnd)
79 {
80 sndconvdata->type = SP_TYPE_ADPCM_LOOPED;
81 sndconvdata->sampleRate = sampleRate;
82 sndconvdata->loopAddr = (soundByteOffset << 1) + getNibbleAddress(loopStart);
83 sndconvdata->loopEndAddr = (soundByteOffset << 1) + getNibbleAddress(loopEnd);
84 sndconvdata->endAddr = (soundByteOffset << 1) + getNibbleAddress(samples - 1);
85 sndconvdata->currentAddr = (soundByteOffset << 1) + getNibbleAddress(0);
86 sndconvdata->adpcm = 0;
87 }
88 else
89 {
90 sndconvdata->type = SP_TYPE_ADPCM_ONESHOT;
91 sndconvdata->sampleRate = sampleRate;
92 sndconvdata->loopAddr = 0;
93 sndconvdata->loopEndAddr = 0;
94 sndconvdata->endAddr = (soundByteOffset << 1) + getNibbleAddress(samples - 1);
95 sndconvdata->currentAddr = (soundByteOffset << 1) + getNibbleAddress(0);
96 sndconvdata->adpcm = 0;
97 }
98
99 // write the buffer to data file
100 fwrite(buffer, 1, dataBytes, outputSamples);
101 soundByteOffset += dataBytes;
102
103 // store the ADPCMINFO
104 memcpy(
105 &soundAdpcminfo[soundAdpcmEntries],
106 adpcminfo,
107 sizeof(ADPCMINFO)
108 );
109
110 soundAdpcmEntries++;
111
112 break;
113
114 case SOUND_FORMAT_PCM8:
115
116 // looped sound
117 if (loopEnd)
118 {
119 sndconvdata->type = SP_TYPE_PCM8_LOOPED;
120 sndconvdata->sampleRate = sampleRate;
121 sndconvdata->loopAddr = soundByteOffset + loopStart;
122 sndconvdata->loopEndAddr = soundByteOffset + loopEnd;
123 sndconvdata->endAddr = soundByteOffset + samples - 1;
124 sndconvdata->currentAddr = soundByteOffset;
125 sndconvdata->adpcm = 0;
126 }
127 else
128 {
129 sndconvdata->type = SP_TYPE_PCM8_ONESHOT;
130 sndconvdata->sampleRate = sampleRate;
131 sndconvdata->loopAddr = 0;
132 sndconvdata->loopEndAddr = 0;
133 sndconvdata->endAddr = soundByteOffset + samples - 1;
134 sndconvdata->currentAddr = soundByteOffset;
135 sndconvdata->adpcm = 0;
136 }
137
138 // write the buffer to data file
139 fwrite(buffer, 1, dataBytes, outputSamples);
140 soundByteOffset += dataBytes;
141
142 break;
143
144 case SOUND_FORMAT_PCM16:
145
146 // 16 bit-aligned the data
147 if (soundByteOffset & 1)
148 {
149 char ch = 0;
150 fwrite(&ch, 1, 1, outputSamples);
151 soundByteOffset++;
152 }
153
154 // looped sound
155 if (loopEnd)
156 {
157 sndconvdata->type = SP_TYPE_PCM16_LOOPED;
158 sndconvdata->sampleRate = sampleRate;
159 sndconvdata->loopAddr = (soundByteOffset >> 1) + loopStart;
160 sndconvdata->loopEndAddr = (soundByteOffset >> 1) + loopEnd;
161 sndconvdata->endAddr = (soundByteOffset >> 1) + samples - 1;
162 sndconvdata->currentAddr = soundByteOffset >> 1;
163 sndconvdata->adpcm = 0;
164 }
165 else
166 {
167 sndconvdata->type = SP_TYPE_PCM16_ONESHOT;
168 sndconvdata->sampleRate = sampleRate;
169 sndconvdata->loopAddr = 0;
170 sndconvdata->loopEndAddr = 0;
171 sndconvdata->endAddr = (soundByteOffset >> 1) + samples - 1;
172 sndconvdata->currentAddr = soundByteOffset >> 1;
173 sndconvdata->adpcm = 0;
174 }
175
176 // reverse the endian then write the buffer to data file
177 reverse_buffer_16(buffer, samples);
178 fwrite(buffer, 1, dataBytes, outputSamples);
179 soundByteOffset += dataBytes;
180
181 break;
182 }
183
184 if (outputHeader)
185 fprintf(outputHeader, "#define %s\t\t%d\n", headerId, soundEntries);
186
187 soundEntries++;
188 }
189
190
191 /*--------------------------------------------------------------------------*
192 print the table file ... call this once at end of program
193 *--------------------------------------------------------------------------*/
soundOutputWriteTable(void)194 void soundOutputWriteTable(void)
195 {
196 if (outputTable)
197 {
198 u32 data;
199 SNDCONVDATA *sndconvdata;
200 ADPCMINFO *adpcminfo;
201
202 // write number of entries
203 data = reverse_endian_32(soundEntries);
204 fwrite(&data, 1, sizeof(u32), outputTable);
205
206 // write sound entries
207 sndconvdata = soundConvdata;
208 while (soundEntries)
209 {
210 sndconvdata->type = reverse_endian_32(sndconvdata->type);
211 sndconvdata->sampleRate = reverse_endian_32(sndconvdata->sampleRate);
212 sndconvdata->loopAddr = reverse_endian_32(sndconvdata->loopAddr);
213 sndconvdata->loopEndAddr = reverse_endian_32(sndconvdata->loopEndAddr);
214 sndconvdata->endAddr = reverse_endian_32(sndconvdata->endAddr);
215 sndconvdata->currentAddr = reverse_endian_32(sndconvdata->currentAddr);
216 sndconvdata->adpcm = 0;
217
218 fwrite(sndconvdata, 1, sizeof(SNDCONVDATA), outputTable);
219
220 sndconvdata++;
221 soundEntries--;
222 }
223
224 // write apdcm entries
225 adpcminfo = soundAdpcminfo;
226 while (soundAdpcmEntries)
227 {
228 u16 *p;
229 int i;
230
231 p = (u16*)adpcminfo;
232
233 for (i = 0; i < sizeof(ADPCMINFO) / 2; i++)
234 {
235 *p = reverse_endian_16(*p);
236 p++;
237 }
238
239 fwrite(adpcminfo, 1, sizeof(ADPCMINFO), outputTable);
240
241 adpcminfo++;
242 soundAdpcmEntries--;
243 }
244 }
245 }
246
247
248 /*--------------------------------------------------------------------------*
249 print comment to header file
250 *--------------------------------------------------------------------------*/
soundOutputComment(char * ch)251 void soundOutputComment(char *ch)
252 {
253 if (outputHeader)
254 fwrite(ch, strlen(ch), 1, outputHeader);
255 }
256
257
258 /*--------------------------------------------------------------------------*
259 quit code module
260 *--------------------------------------------------------------------------*/
soundOutputQuit(void)261 void soundOutputQuit(void)
262 {
263 soundOutputWriteTable();
264
265 if (outputHeader) fclose(outputHeader);
266 if (outputTable) fclose(outputTable);
267 if (outputSamples) fclose(outputSamples);
268 }
269
270
271 /*--------------------------------------------------------------------------*
272 init code module
273 *--------------------------------------------------------------------------*/
soundOutputInit(char * name)274 int soundOutputInit(char *name)
275 {
276 char ch[1024];
277
278 soundEntries = 0;
279 soundAdpcmEntries = 0;
280 soundByteOffset = 0;
281
282 sprintf(ch, "%s.h", name);
283 outputHeader = fopen(ch, "w");
284
285 sprintf(ch, "%s.spt", name);
286 outputTable = fopen(ch, "wb");
287
288 sprintf(ch, "%s.spd", name);
289 outputSamples = fopen(ch, "wb");
290
291 if (outputHeader && outputTable && outputSamples)
292 return STATUS_SUCCESS;
293
294 soundOutputQuit();
295
296 if (outputHeader == NULL)
297 {
298 printf("Error: Can't open %s.h\n", name);
299 }
300
301 if (outputTable == NULL)
302 {
303 printf("Error: Can't open %s.spt\n", name);
304 }
305
306 if (outputSamples == NULL)
307 {
308 printf("Error: Can't open %s.spd\n", name);
309 }
310
311 return STATUS_ERROR;
312 }
313