Ticket #8112: simon2mp3.c

File simon2mp3.c, 11.9 KB (added by SF/olki, 18 years ago)

program to covert simon(2).voc/wav and effects.voc to mp3

Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <sys/stat.h>
5
6#ifndef WIN32
7#include <unistd.h>
8#endif
9
10/* These are the defaults parameters for the Lame invocation */
11#define minBitrDef 24
12#define maxBitrDef 64
13#define abrDef 0
14#define vbrDef 1
15#define algqualDef 2
16#define vbrqualDef 4
17
18/* The default for oggenc invocation is to use the --quality option only */
19#define oggqualDef 3
20
21FILE *input, *output_idx, *output_snd;
22
23unsigned int offsets[32768];
24
25char infile_base[256];
26char fbuf_temp[1024];
27char buf[256];
28char tmp[256];
29
30struct lameparams {
31 unsigned int minBitr;
32 unsigned int maxBitr;
33 unsigned int abr;
34 unsigned int vbr;
35 unsigned int algqual;
36 unsigned int vbrqual;
37 unsigned int silent;
38} encparms = { minBitrDef, maxBitrDef, abrDef, vbrDef, algqualDef, vbrqualDef, 0 };
39
40struct oggencparams {
41 int nominalBitr;
42 int minBitr;
43 int maxBitr;
44 int quality;
45 int silent;
46} oggparms = { -1, -1, -1, oggqualDef, 0 };
47
48int oggmode = 0;
49
50void end(void)
51{
52 int size;
53 char buf[2048];
54
55 fclose(output_snd);
56 fclose(output_idx);
57 fclose(input);
58
59 sprintf(tmp, "%s%s", infile_base, oggmode ? "ogg" : "mp3");
60 output_idx = fopen(tmp, "wb");
61
62 sprintf(tmp, "%sidx", infile_base);
63 input = fopen(tmp, "rb");
64 while ((size = fread(buf, 1, 2048, input)) > 0) {
65 fwrite(buf, 1, size, output_idx);
66 }
67 fclose(input);
68 sprintf(tmp, "%sdat", infile_base);
69 input = fopen(tmp, "rb");
70 while ((size = fread(buf, 1, 2048, input)) > 0) {
71 fwrite(buf, 1, size, output_idx);
72 }
73 fclose(input);
74 fclose(output_idx);
75
76 /* And some clean-up :-) */
77 sprintf(tmp, "%sidx", infile_base);
78 unlink(tmp);
79 sprintf(tmp, "%sdat", infile_base);
80 unlink(tmp);
81 unlink("tempfile.raw");
82 unlink(oggmode ? "tempfile.ogg" : "tempfile.mp3");
83
84 exit(0);
85}
86
87void get_string(int size)
88{
89 int i = 0;
90 while (i < size) {
91 int c = fgetc(input);
92 buf[i++] = c;
93 }
94 buf[i] = '\0';
95}
96
97unsigned int get_int(void)
98{
99 int i;
100 unsigned int ret = 0;
101 unsigned int c;
102 for (i = 0; i < 4; i++) {
103 c = fgetc(input);
104 ret |= c << i*8;
105 }
106 return ret;
107}
108
109void put_int(unsigned int val)
110{
111 int i;
112 for (i = 3; i >= 0; i--) {
113 fputc((val << i*8) >> 24, output_idx);
114 }
115}
116
117int get_offsets(void)
118{
119 int i;
120
121 for (i = 0;; i++) {
122 get_string(8);
123 if (!strncmp(buf, "Creative", 8) || !strncmp(buf, "RIFF", 4)) {
124 return(i);
125 }
126 fseek(input, -8, SEEK_CUR);
127
128 offsets[i] = get_int();
129 }
130}
131
132void get_voc(void);
133void get_wav(void);
134
135unsigned int get_sound(int sound)
136{
137 FILE *f;
138 unsigned int tot_size;
139 char mp3name[256];
140 int size;
141 char fbuf[2048];
142
143 fseek(input, offsets[sound], SEEK_SET);
144
145 get_string(8);
146 if (!strncmp(buf, "Creative", 8)) {
147 printf("VOC found (pos = %d) :\n", offsets[sound]);
148 get_voc();
149 } else if (!strncmp(buf, "RIFF", 4)) {
150 printf("WAV found (pos = %d) :\n", offsets[sound]);
151 get_wav();
152 } else {
153 printf("Unexpected data at offset: %i\n", offsets[sound]);
154 exit(-1);
155 }
156
157 sprintf(mp3name, oggmode ? "tempfile.ogg" : "tempfile.mp3");
158 f = fopen(mp3name, "rb");
159 tot_size = 0;
160 while ((size = fread(fbuf, 1, 2048, f)) > 0) {
161 tot_size += size;
162 fwrite(fbuf, 1, size, output_snd);
163 }
164 fclose(f);
165
166 return(tot_size);
167}
168
169void get_wav(void) {
170 int length;
171 int i;
172 FILE *f;
173 char fbuf[2048];
174 char fbuf_o[4096];
175 int size;
176 char wavname[256];
177 char mp3name[256];
178
179 fseek(input, -4, SEEK_CUR);
180 length = get_int();
181 length += 8;
182
183 sprintf(wavname, "tempfile.wav");
184 sprintf(mp3name, oggmode ? "tempfile.ogg" : "tempfile.mp3");
185
186 f = fopen(wavname, "wb");
187 while (length > 0) {
188 size = fread(fbuf, 1, length > 2048 ? 2048 : length, input);
189 if (size <= 0)
190 break;
191 length -= size;
192 for (i = 0; i < size; i++) {
193 fbuf_o[2 * i] = fbuf[i] ^ 0x80;
194 fbuf_o[2 * i + 1] = 0;
195 }
196 fwrite(fbuf_o, 1, 2 * size, f);
197 }
198 fclose(f);
199
200 if (oggmode) {
201 sprintf(fbuf, "oggenc ");
202 if (oggparms.nominalBitr != -1) {
203 sprintf(fbuf_temp, "-b %i ", oggparms.nominalBitr);
204 strcat(fbuf, fbuf_temp);
205 }
206 if (oggparms.minBitr != -1) {
207 sprintf(fbuf_temp, "-m %i ", oggparms.minBitr);
208 strcat(fbuf, fbuf_temp);
209 }
210 if (oggparms.maxBitr != -1) {
211 sprintf(fbuf_temp, "-M %i ", oggparms.maxBitr);
212 strcat(fbuf, fbuf_temp);
213 }
214 if (oggparms.silent) {
215 strcat(fbuf, "--quiet ");
216 }
217 sprintf(fbuf_temp, "-q %i --resample 22050 %s -o %s",
218 oggparms.quality, wavname, mp3name);
219 strcat(fbuf, fbuf_temp);
220 system(fbuf);
221 } else {
222 if (encparms.abr == 1)
223 sprintf(fbuf_temp,"--abr %i",encparms.minBitr);
224 else
225 sprintf(fbuf_temp,"--vbr-new -b %i",encparms.minBitr);
226 if (encparms.silent == 1)
227 strcat(fbuf_temp," --silent");
228 sprintf(fbuf,
229 "lame -t -q %i %s -V %i -B %i --resample 22.05 -m m %s %s",
230 encparms.algqual, fbuf_temp, encparms.vbrqual,
231 encparms.maxBitr, wavname, mp3name);
232 system(fbuf);
233 }
234}
235
236void get_voc(void)
237{
238 int blocktype;
239
240 get_string(18);
241
242 blocktype = fgetc(input);
243 switch (blocktype) {
244 case 0x01:{
245 int length = 0;
246 int i;
247 int sample_rate;
248 int comp;
249 FILE *f;
250 char fbuf[2048];
251 char fbuf_o[4096];
252 int size;
253 char rawname[256];
254 char mp3name[256];
255 int real_samplerate;
256
257 /* Sound Data */
258 printf(" Sound Data\n");
259 for (i = 0; i < 3; i++)
260 length = length | (fgetc(input) << (i * 8));
261 length -= 2;
262 printf(" - length = %d\n", length);
263 sample_rate = fgetc(input);
264 comp = fgetc(input);
265 real_samplerate = 1000000 / (256 - sample_rate);
266 printf(" - sample rate = %d (%02x)\n", 1000000 / (256 - sample_rate), sample_rate);
267 printf(" - compression = %s (%02x)\n",
268 (comp == 0 ? "8bits" :
269 (comp == 1 ? "4bits" :
270 (comp == 2 ? "2.6bits" :
271 (comp == 3 ? "2bits" :
272 "Multi")))), comp);
273
274 if (comp != 0) {
275 printf("Cannot handle compression\n");
276 exit(-1);
277 }
278 sprintf(rawname, "tempfile.raw");
279 sprintf(mp3name, oggmode ? "tempfile.ogg" : "tempfile.mp3");
280
281 f = fopen(rawname, "wb");
282 while (length > 0) {
283 size = fread(fbuf, 1, length > 2048 ? 2048 : length, input);
284 if (size <= 0)
285 break;
286 length -= size;
287 for (i = 0; i < size; i++) {
288 fbuf_o[2 * i] = fbuf[i] ^ 0x80;
289 fbuf_o[2 * i + 1] = 0;
290 }
291 fwrite(fbuf_o, 1, 2 * size, f);
292 }
293 fclose(f);
294
295 if (oggmode) {
296 sprintf(fbuf, "oggenc ");
297 if (oggparms.nominalBitr != -1) {
298 sprintf(fbuf_temp, "-b %i ", oggparms.nominalBitr);
299 strcat(fbuf, fbuf_temp);
300 }
301 if (oggparms.minBitr != -1) {
302 sprintf(fbuf_temp, "-m %i ", oggparms.minBitr);
303 strcat(fbuf, fbuf_temp);
304 }
305 if (oggparms.maxBitr != -1) {
306 sprintf(fbuf_temp, "-M %i ", oggparms.maxBitr);
307 strcat(fbuf, fbuf_temp);
308 }
309 if (oggparms.silent) {
310 strcat(fbuf, "--quiet ");
311 }
312 sprintf(fbuf_temp, "-q %i -r -C 1 --raw-endianness=1 -R %i --resample 22050 %s -o %s",
313 oggparms.quality, real_samplerate,
314 rawname, mp3name);
315 strcat(fbuf, fbuf_temp);
316 system(fbuf);
317 }
318 else {
319 if (encparms.abr == 1)
320 sprintf(fbuf_temp,"--abr %i",encparms.minBitr);
321 else
322 sprintf(fbuf_temp,"--vbr-new -b %i",encparms.minBitr);
323 if (encparms.silent == 1)
324 strcat(fbuf_temp," --silent");
325 sprintf(fbuf,
326 "lame -t -q %i %s -V %i -B %i --resample 22.05 -m m -r -s %d %s %s",
327 encparms.algqual, fbuf_temp, encparms.vbrqual,
328 encparms.maxBitr, real_samplerate, rawname, mp3name);
329 system(fbuf);
330 }
331 break;
332 }
333
334 default:
335 printf("Unknown chunk : %02x\n", blocktype);
336 exit(-1);
337 break;
338 }
339}
340
341void showhelp(char *exename)
342{
343 printf("\nUsage: %s <params> file\n", exename);
344 printf("\nParams:\n");
345 printf("--mp3 encode to MP3 format (default)\n");
346 printf("--vorbis encode to Vorbis format (not yet implemented)\n");
347 printf("(If one of these is specified, it must be the first parameter.)\n");
348 printf("\nMP3 mode params:\n");
349 printf("-b <rate> <rate> is the target bitrate(ABR)/minimal bitrate(VBR) (default:%i)\n", minBitrDef);
350 printf("-B <rate> <rate> is the maximum VBR/ABR bitrate (default:%i)\n", maxBitrDef);
351 printf("--vbr LAME uses the VBR mode (default)\n");
352 printf("--abr LAME uses the ABR mode\n");
353 printf("-V <value> specifies the value (0 - 9) of VBR quality (0=best) (default:%i)\n", vbrqualDef);
354 printf("-q <value> specifies the MPEG algorithm quality (0-9; 0=best) (default:%i)\n", algqualDef);
355 printf("--silent the output of LAME is hidden (default:disabled)\n");
356 printf("\nVorbis mode params:\n");
357 printf("-b <rate> <rate> is the nominal bitrate (default:unset)\n");
358 printf("-m <rate> <rate> is the minimum bitrate (default:unset)\n");
359 printf("-M <rate> <rate> is the maximum bitrate (default:unset)\n");
360 printf("-q <value> specifies the value (0 - 10) of VBR quality (10=best) (default:%i)\n", oggqualDef);
361 printf("--silent the output of oggenc is hidden (default:disabled)\n");
362 printf("\n--help this help message\n");
363 printf("\n\nIf a parameter is not given the default value is used\n");
364 printf("If using VBR mode for MP3 -b and -B must be multiples of 8; the maximum is 160!\n");
365 exit(2);
366}
367
368void process_mp3_parms(int argc, char *argv[], int i) {
369 for(; i < argc; i++) {
370 if (strcmp(argv[i], "--vbr") == 0) {
371 encparms.vbr=1;
372 encparms.abr=0;
373 } else if (strcmp(argv[i], "--abr") == 0) {
374 encparms.vbr=0;
375 encparms.abr=1;
376 } else if (strcmp(argv[i], "-b") == 0) {
377 encparms.minBitr = atoi(argv[i + 1]);
378 if ((encparms.minBitr % 8) != 0)
379 encparms.minBitr -= encparms.minBitr % 8;
380 if (encparms.minBitr >160)
381 encparms.minBitr = 160;
382 if (encparms.minBitr < 8)
383 encparms.minBitr=8;
384 i++;
385 } else if (strcmp(argv[i], "-B") == 0) {
386 encparms.maxBitr = atoi(argv[i + 1]);
387 if ((encparms.maxBitr % 8) != 0)
388 encparms.maxBitr -= encparms.maxBitr % 8;
389 if (encparms.maxBitr > 160)
390 encparms.maxBitr = 160;
391 if (encparms.maxBitr < 8)
392 encparms.maxBitr = 8;
393 i++;
394 } else if (strcmp(argv[i], "-V") == 0) {
395 encparms.vbrqual = atoi(argv[i + 1]);
396 if(encparms.vbrqual < 0)
397 encparms.vbrqual = 0;
398 if(encparms.vbrqual > 9)
399 encparms.vbrqual = 9;
400 i++;
401 } else if (strcmp(argv[i], "-q") == 0) {
402 encparms.algqual = atoi(argv[i + 1]);
403 if (encparms.algqual < 0)
404 encparms.algqual = 0;
405 if (encparms.algqual > 9)
406 encparms.algqual = 9;
407 i++;
408 } else if (strcmp(argv[i], "--silent") == 0) {
409 encparms.silent = 1;
410 } else if (strcmp(argv[i], "--help") == 0) {
411 showhelp(argv[0]);
412 } else if (argv[i][0] == '-') {
413 showhelp(argv[0]);
414 } else {
415 break;
416 }
417 }
418 if (i != (argc - 1)) {
419 showhelp(argv[0]);
420 }
421}
422
423void process_ogg_parms(int argc, char *argv[], int i) {
424 for (; i < argc; i++) {
425 if (strcmp(argv[i], "-b") == 0) {
426 oggparms.nominalBitr = atoi(argv[i + 1]);
427 i++;
428 }
429 else if (strcmp(argv[i], "-m") == 0) {
430 oggparms.minBitr = atoi(argv[i + 1]);
431 i++;
432 }
433 else if (strcmp(argv[i], "-M") == 0) {
434 oggparms.maxBitr = atoi(argv[i + 1]);
435 i++;
436 }
437 else if (strcmp(argv[i], "-q") == 0) {
438 oggparms.quality = atoi(argv[i + 1]);
439 i++;
440 }
441 else if (strcmp(argv[i], "--silent") == 0) {
442 oggparms.silent = 1;
443 }
444 else if (strcmp(argv[i], "--help") == 0) {
445 showhelp(argv[0]);
446 }
447 else if (argv[i][0] == '-') {
448 showhelp(argv[0]);
449 }
450 else
451 break;
452 }
453 if (i != argc - 1)
454 showhelp(argv[0]);
455}
456
457int main(int argc, char *argv[])
458{
459 int i, n, size, num;
460
461 if (argc < 2)
462 showhelp(argv[0]);
463 i = 1;
464 if (strcmp(argv[1], "--mp3") == 0) {
465 oggmode = 0;
466 i++;
467 }
468 else if (strcmp(argv[1], "--vorbis") == 0) {
469 oggmode = 1;
470 i++;
471 }
472
473 if (oggmode)
474 process_ogg_parms(argc, argv, i);
475 else
476 process_mp3_parms(argc, argv, i);
477
478 i = argc - 1;
479
480 n = strlen(argv[i]);
481 strncpy(infile_base, argv[i], n - 3);
482
483 input = fopen(argv[i], "rb");
484 if (!input) {
485 printf("Cannot open file: %s\n", argv[i]);
486 exit(-1);
487 }
488
489 sprintf(tmp, "%sidx", infile_base);
490 output_idx = fopen(tmp, "wb");
491
492 sprintf(tmp, "%sdat", infile_base);
493 output_snd = fopen(tmp, "wb");
494
495 num = get_offsets();
496
497 if (!num) {
498 printf("This does not seem to be a valid file\n");
499 exit(-1);
500 }
501 size = num*4;
502
503 put_int(0);
504 put_int(size);
505
506 for (i = 1; i < num; i++) {
507 if (offsets[i] == offsets[i+1]) {
508 put_int(size);
509 continue;
510 }
511
512 size += get_sound(i);
513 if (i < num - 1)
514 put_int(size);
515 }
516
517 end();
518
519 return(0);
520}