1 /*(LGPL)
2 ---------------------------------------------------------------------------
3 a_wave.c - Wava Data Manager
4 ---------------------------------------------------------------------------
5 * Copyright (C) 2001-2003, 2007 David Olofson
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation; either version 2.1 of the License, or (at
10 * your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this program; if not, write to the Free Software Foundation,
19 * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include <string.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25
26 #include "kobolog.h"
27 #include "a_globals.h"
28 #include "a_wave.h"
29 #include "a_struct.h"
30 #include "a_math.h"
31 #include "a_tools.h"
32 #include "a_agw.h"
33 #include "eel.h"
34
35 static int _was_init = 0;
36
audio_wave_open(void)37 void audio_wave_open(void)
38 {
39 if(_was_init)
40 return;
41
42 memset(wavetab, 0, sizeof(wavetab));
43 _was_init = 1;
44 }
45
audio_wave_close(void)46 void audio_wave_close(void)
47 {
48 if(!_was_init)
49 return;
50
51 audio_wave_free(-1);
52
53 _was_init = 0;
54 }
55
56 #define CHECKINIT if(!_was_init) audio_wave_open();
57
58
59 /*----------------------------------------------------------
60 Internal Tools
61 ----------------------------------------------------------*/
62
63 /*
64 * Fill in the loop/interpolation extension zone with the right
65 * data, depending on whether the waveform is looped or not.
66 *
67 * (This should probably be replaced with smarter mixers. Cheap
68 * sample players like the EMU8000 chips, have the same problem
69 * with interpolation over loop wraps, which causes various
70 * problems with anything but plain "loop forever" samples.)
71 */
_render_extension(int wid)72 static void _render_extension(int wid)
73 {
74 Sint8 *eos;
75 if(AF_MIDI == wavetab[wid].format)
76 return;
77
78 eos = wavetab[wid].data.si8 + wavetab[wid].size;
79 if(wavetab[wid].looped)
80 {
81 unsigned s, from = 0;
82 for(s = 0; s < wavetab[wid].xsize; ++s)
83 {
84 eos[s] = wavetab[wid].data.si8[from++];
85 if(from >= wavetab[wid].size)
86 from = 0;
87 }
88 }
89 else
90 memset(eos, 0, wavetab[wid].xsize);
91 }
92
93
_calc_info(int wid)94 static void _calc_info(int wid)
95 {
96 wavetab[wid].speed = (unsigned)((double)wavetab[wid].rate * 65536.0 /
97 (double)a_settings.samplerate);
98 switch(wavetab[wid].format)
99 {
100 case AF_MONO8:
101 wavetab[wid].samples = wavetab[wid].size;
102 break;
103 case AF_STEREO8:
104 case AF_MONO16:
105 wavetab[wid].samples = wavetab[wid].size / 2;
106 break;
107 case AF_STEREO16:
108 case AF_MONO32:
109 wavetab[wid].samples = wavetab[wid].size / 4;
110 break;
111 case AF_STEREO32:
112 wavetab[wid].samples = wavetab[wid].size / 8;
113 break;
114 case AF_MIDI:
115 wavetab[wid].samples = 1;
116 break;
117 }
118 }
119
120
audio_wave_prepare(int wid)121 void audio_wave_prepare(int wid)
122 {
123 int w, first, last;
124 if(wid < 0)
125 {
126 first = 0;
127 last = AUDIO_MAX_WAVES - 1;
128 }
129 else
130 first = last = wid;
131 for(w = first; w <= last; ++w)
132 {
133 if(!wavetab[w].allocated)
134 continue;
135 _calc_info(w);
136 _render_extension(w);
137 }
138 }
139
140
_get_free_wid(void)141 static int _get_free_wid(void)
142 {
143 int w;
144 for(w = 0; w < AUDIO_MAX_WAVES; ++w)
145 if(!wavetab[w].allocated)
146 return w;
147 return -1;
148 }
149
150
151 /*
152 * Flip back and forth between big and little endian,
153 * unless we're on big endian hardware.
154 */
flip_endian(Uint8 * data,Uint32 size,int format)155 static void flip_endian(Uint8 *data, Uint32 size, int format)
156 {
157 #if SDL_BYTEORDER == SDL_LITTLE_ENDIAN
158 int i, s;
159 switch(format)
160 {
161 case AF_MIDI:
162 case AF_MONO8:
163 case AF_STEREO8:
164 break;
165 case AF_MONO16:
166 case AF_STEREO16:
167 for(i = 0; i < size; i += 2)
168 {
169 s = data[i];
170 data[i] = data[i + 1];
171 data[i + 1] = s;
172 }
173 break;
174 case AF_MONO32:
175 case AF_STEREO32:
176 for(i = 0; i < size; i += 4)
177 {
178 s = data[i];
179 data[i] = data[i + 3];
180 data[i + 3] = s;
181 s = data[i + 1];
182 data[i + 1] = data[i + 2];
183 data[i + 2] = s;
184 }
185 break;
186 }
187 #endif
188 }
189
190
LoadRAW(const char * name,Uint8 ** data,Uint32 * size,int * format,int * rate,int * loop)191 static int LoadRAW(const char *name, Uint8 ** data, Uint32 * size,
192 int *format, int *rate, int *loop)
193 {
194 unsigned char header[8];
195 int startpos = 0;
196
197 FILE *f = fopen(name, "rb");
198 if(!f)
199 return -1;
200
201 if(fread(header, sizeof(header), 1, f) == 1)
202 {
203 if(strncmp("RAW", (char *)header, 3) == 0)
204 {
205 const char *fmt;
206 *format = (int)header[3] & 0x0f;
207 *loop = (header[3] & 0x80) != 0;
208 startpos = sizeof(header);
209 *rate = header[4];
210 *rate |= header[5] << 8;
211 *rate |= header[6] << 16;
212 *rate |= header[7] << 24;
213 switch (*format)
214 {
215 case AF_MONO8:
216 fmt = "MONO8";
217 break;
218 case AF_STEREO8:
219 fmt = "STEREO8";
220 break;
221 case AF_MONO16:
222 fmt = "MONO16";
223 break;
224 case AF_STEREO16:
225 fmt = "STEREO16";
226 break;
227 case AF_MONO32:
228 fmt = "MONO32";
229 break;
230 case AF_STEREO32:
231 fmt = "STEREO32";
232 break;
233 case AF_MIDI:
234 fmt = "MIDI (Huh!?)";
235 break;
236 default:
237 fmt = "Unknown";
238 break;
239 }
240 log_printf(DLOG, "LoadRAW: %s, %d Hz", fmt, *rate);
241 if(*loop)
242 log_printf(DLOG, ", looped\n");
243 else
244 log_printf(DLOG, ", one-shot\n");
245 }
246 else
247 fseek(f, 0, SEEK_SET);
248 }
249
250 if(fseek(f, 0, SEEK_END) == 0)
251 {
252 int s = (int)ftell(f) - startpos;
253 if(s <= 0)
254 {
255 fclose(f);
256 return -2;
257 }
258 *size = (Uint32) s;
259 if(fseek(f, startpos, SEEK_SET) == 0)
260 {
261 *data = malloc(*size);
262 if(*data)
263 {
264 if(fread(*data, *size, 1, f) == 1)
265 {
266 fclose(f);
267 flip_endian(*data, *size, *format);
268 return 0;
269 }
270 free(*data);
271 *data = NULL;
272 }
273 }
274 }
275 fclose(f);
276 return -3;
277 }
278
279
SaveRAW(const char * name,void * data,Uint32 size,int format,int rate,int loop)280 static int SaveRAW(const char *name, void *data, Uint32 size,
281 int format, int rate, int loop)
282 {
283 unsigned char header[8] = "RAW\0rate";
284 int result;
285 FILE *f = fopen(name, "wb");
286 if(!f)
287 return -1;
288 header[3] = (char)format;
289 if(loop)
290 header[3] |= 0x80;
291 header[4] = rate & 0xff;
292 header[5] = (rate >> 8) & 0xff;
293 header[6] = (rate >> 16) & 0xff;
294 header[7] = (rate >> 24) & 0xff;
295 if(fwrite(header, sizeof(header), 1, f) != 1)
296 return -2;
297 flip_endian(data, size, format);
298 result = fwrite(data, size, 1, f);
299 flip_endian(data, size, format);
300 if(result != 1)
301 return -3;
302 fclose(f);
303 return 0;
304 }
305
306
307 /*
308 * Calculate waveform memory needed, including the extra bytes
309 * needed for proper end-of-waveform handling. Will set the
310 * 'xsize' and 'play_samples' field.
311 *
312 * Must know sample format and original size!
313 *
314 * Also note that this is heavily dependent on the voice
315 * mixer - that's where the extra samples are needed.
316 FIXME: ...which means that this code probably belongs there,
317 FIXME: or that the voice mixer should set the parameters.
318 *
319 * Returns the total size required in bytes.
320 */
_calc_xsize(int wid)321 static unsigned _calc_xsize(int wid)
322 {
323 unsigned samples, fsamples;
324 unsigned bytes_sample = 1;
325 unsigned ssize = wavetab[wid].size;
326 switch(wavetab[wid].format)
327 {
328 case AF_MONO8:
329 bytes_sample = 1;
330 break;
331 case AF_STEREO8:
332 case AF_MONO16:
333 bytes_sample = 2;
334 ssize >>= 1;
335 break;
336 case AF_STEREO16:
337 case AF_MONO32:
338 bytes_sample = 4;
339 ssize >>= 2;
340 break;
341 case AF_STEREO32:
342 bytes_sample = 8;
343 ssize >>= 3;
344 break;
345 case AF_MIDI:
346 wavetab[wid].xsize = 0;
347 return 0;
348 }
349
350 /* Fixed part: */
351 /* Looping. */
352 samples = ssize;
353 while(samples < MIN_LOOP)
354 samples <<= 1;
355 wavetab[wid].play_samples = samples;
356 samples -= ssize;
357
358 /* Interpolation. */
359 samples += 3;
360
361 /* Freq. ratio dependent part: oversampling and looping */
362 fsamples = AUDIO_MAX_MIX_RATE / AUDIO_MIN_OUTPUT_RATE;
363 fsamples *= AUDIO_MAX_OVERSAMPLING;
364 ++fsamples;
365
366 wavetab[wid].xsize = bytes_sample * (samples + fsamples);
367 return wavetab[wid].size + wavetab[wid].xsize;
368 }
369
370
371 /*----------------------------------------------------------
372 Basic Wave API
373 ----------------------------------------------------------*/
374
audio_wave_alloc(int wid)375 int audio_wave_alloc(int wid)
376 {
377 CHECKINIT
378 if(wid >= AUDIO_MAX_WAVES)
379 return -1;
380 if(wid < 0)
381 wid = _get_free_wid();
382 if(wid < 0)
383 return -2;
384
385 audio_wave_free(wid);
386 wavetab[wid].allocated = 1;
387 return wid;
388 }
389
390
audio_wave_alloc_range(int first_wid,int last_wid)391 int audio_wave_alloc_range(int first_wid, int last_wid)
392 {
393 int w, res, last_done;
394 if(last_wid < first_wid)
395 return -1;
396 last_done = -1;
397 res = 0;
398 for(w = first_wid; w <= last_wid; ++w)
399 {
400 res = audio_wave_alloc(w);
401 if(res < 0)
402 break;
403 last_done = w;
404 }
405
406 if(res < 0)
407 {
408 if(last_done >= 0)
409 for(w = first_wid; w <= last_done; ++w)
410 audio_wave_free(w);
411 return -2;
412 }
413 else
414 return first_wid;
415 }
416
417
audio_wave_get(int wid)418 audio_wave_t *audio_wave_get(int wid)
419 {
420 if(wid < 0)
421 return NULL;
422 if(wid >= AUDIO_MAX_WAVES)
423 return NULL;
424 return &wavetab[wid];
425 }
426
427
audio_wave_format(int wid,audio_formats_t fmt,int fs)428 int audio_wave_format(int wid, audio_formats_t fmt, int fs)
429 {
430 unsigned old_xsize, new_size;
431 wid = audio_wave_alloc(wid);
432 if(wid < 0)
433 return wid;
434
435 old_xsize = wavetab[wid].xsize;
436 wavetab[wid].format = fmt;
437 wavetab[wid].rate = fs;
438 if(wavetab[wid].data.si8)
439 {
440 new_size = _calc_xsize(wid);
441 if(wavetab[wid].xsize != old_xsize)
442 {
443 void *ndata = realloc(wavetab[wid].data.si8, new_size);
444 if(!ndata)
445 return -3;
446 wavetab[wid].data.si8 = ndata;
447 _calc_info(wid);
448 }
449 }
450 return wid;
451 }
452
453
audio_wave_load_mem(int wid,void * data,unsigned size,int looped)454 int audio_wave_load_mem(int wid, void *data, unsigned size, int looped)
455 {
456 wid = audio_wave_alloc(wid);
457 if(wid < 0)
458 return wid;
459
460 wavetab[wid].size = size;
461 wavetab[wid].looped = looped;
462 wavetab[wid].data.si8 = (Sint8 *)malloc(_calc_xsize(wid));
463 wavetab[wid].howtofree = HTF_FREE;
464 if(!wavetab[wid].data.si8)
465 {
466 audio_wave_free(wid);
467 return -1;
468 }
469
470 if(data)
471 memcpy(wavetab[wid].data.si8, data, size);
472 else
473 memset(wavetab[wid].data.si8, 0, size);
474
475 #ifdef xDEBUG
476 {
477 int i;
478 int peak = 0;
479 double avg = 0;
480 double power = 0;
481 int iavg, ipower;
482 for(i = 0; i < size; ++i)
483 {
484 int s;
485 s = wavetab[wid].data.si8[i];
486 avg += s;
487 power += labs(s);
488 if(labs(s) > peak)
489 peak = labs(s);
490 }
491 avg /= size;
492 power /= size;
493 iavg = (int)avg;
494 ipower = (int)power;
495 log_printf(D3LOG, "audio_wave_load_mem(id=%d): size=%d peak=%d"
496 " average=%d power=%d\n",
497 wid, size, peak, iavg, ipower);
498 }
499 #endif
500 _calc_info(wid);
501 return wid;
502 }
503
504
audio_wave_blank(int wid,unsigned samples,int looped)505 int audio_wave_blank(int wid, unsigned samples, int looped)
506 {
507 int bps = 0;
508
509 wid = audio_wave_alloc(wid);
510 if(wid < 0)
511 return wid;
512
513 switch(wavetab[wid].format)
514 {
515 case AF_MONO8:
516 bps = 1;
517 break;
518 case AF_STEREO8:
519 case AF_MONO16:
520 bps = 2;
521 break;
522 case AF_STEREO16:
523 case AF_MONO32:
524 bps = 4;
525 break;
526 case AF_STEREO32:
527 bps = 8;
528 break;
529 case AF_MIDI:
530 return wid;
531 }
532 return audio_wave_load_mem(wid, NULL, samples * bps, looped);
533 }
534
535
audio_wave_convert(int wid,int new_wid,audio_formats_t fmt,int fs,audio_resample_t resamp)536 int audio_wave_convert(int wid, int new_wid, audio_formats_t fmt,
537 int fs, audio_resample_t resamp)
538 {
539 int inplace, private_pool = 0, i;
540 audio_voice_t resampler;
541 audio_quality_t old_quality;
542 int *bus;
543 Sint8 *out8;
544 Sint16 *out16;
545 float *out32;
546 unsigned newlen, j;
547
548 /* We need this to run the voice mixer... */
549 if(ptab_init(65536) < 0)
550 {
551 log_printf(ELOG, "audio_wave_convert(): ptab_init() failed!\n");
552 return -20;
553 }
554
555 if(AF_MIDI == fmt)
556 {
557 log_printf(ELOG, "audio_wave_convert(): Cannot convert to MIDI!\n");
558 return -10;
559 }
560
561 if(wid >= AUDIO_MAX_WAVES)
562 return -1;
563 if(wid < 0)
564 return -2;
565
566 if(AF_MIDI == wavetab[wid].format)
567 {
568 log_printf(ELOG, "audio_wave_convert(): Cannot convert from MIDI!\n");
569 return -11;
570 }
571
572 if(new_wid == wid)
573 {
574 inplace = 1;
575 new_wid = audio_wave_alloc(-1);
576 if(new_wid < 0)
577 return new_wid;
578 }
579 else
580 {
581 inplace = 0;
582 new_wid = audio_wave_alloc(new_wid);
583 if(new_wid < 0)
584 return new_wid;
585 }
586 audio_wave_format(new_wid, fmt, fs);
587 newlen = (unsigned)ceil((float)wavetab[wid].samples * (float)fs /
588 (float)wavetab[wid].rate);
589 audio_wave_blank(new_wid, newlen, wavetab[wid].looped);
590
591 /* Must prepare, as we're gonna use the wave mixer! */
592 audio_wave_prepare(wid);
593
594 memset(&resampler, 0, sizeof(resampler));
595
596 /* We need to tweak the 'speed' to get the output rate right! */
597 wavetab[wid].speed = (unsigned)((double)wavetab[wid].rate * 65536.0 /
598 (double)wavetab[new_wid].rate);
599
600 old_quality = a_settings.quality;
601 a_settings.quality = AQ_VERY_HIGH;
602
603 if(!aev_event_pool)
604 {
605 private_pool = 1;
606 aev_open(20);
607 }
608
609 switch(resamp)
610 {
611 case AR_WORST:
612 resamp = AR_NEAREST;
613 break;
614 case AR_MEDIUM:
615 resamp = AR_LINEAR_2X_R;
616 break;
617 case AR_BEST:
618 resamp = AR_CUBIC_R;
619 break;
620 default:
621 break;
622 }
623
624 aev_timer = 0;
625 (void)aev_send1(&resampler.port, 0, VE_START, wid);
626 (void)aev_sendi1(&resampler.port, 0, VE_SET, VC_PITCH, 60<<16);
627 (void)aev_sendi1(&resampler.port, 0, VE_SET, VC_RESAMPLE, resamp);
628 (void)aev_sendi1(&resampler.port, 0, VE_SET, VC_SEND_BUS, -1);
629 (void)aev_sendi2(&resampler.port, 0, VE_IRAMP, VIC_LVOL,
630 65536 >> (16-VOL_BITS), 0);
631 (void)aev_sendi2(&resampler.port, 0, VE_IRAMP, VIC_RVOL,
632 65536 >> (16-VOL_BITS), 0);
633 bus = malloc(256 * sizeof(int) * 2);
634 out8 = wavetab[new_wid].data.si8;
635 out16 = wavetab[new_wid].data.si16;
636 out32 = wavetab[new_wid].data.f32;
637 for(i = (int)wavetab[new_wid].samples; i > 0; i -= 256)
638 {
639 unsigned frames;
640 if(i > 256)
641 frames = 256;
642 else
643 frames = (unsigned)i;
644 s32clear(bus, frames);
645 voice_process_mix(&resampler, &bus, frames);
646 switch(wavetab[new_wid].format)
647 {
648 case AF_MONO8:
649 for(j = 0; j < frames; ++j)
650 *out8++ = (bus[j<<1] + bus[(j<<1)+1]) >> 9;
651 break;
652 case AF_STEREO8:
653 for(j = 0; j < frames; ++j)
654 {
655 *out8++ = bus[j<<1] >> 8;
656 *out8++ = bus[(j<<1)+1] >> 8;
657 }
658 break;
659 case AF_MONO16:
660 for(j = 0; j < frames; ++j)
661 *out16++ = (Sint16)(bus[j<<1] +
662 bus[(j<<1)+1]) >> 1;
663 break;
664 case AF_STEREO16:
665 for(j = 0; j < frames; ++j)
666 {
667 *out16++ = (Sint16)(bus[j<<1]);
668 *out16++ = (Sint16)(bus[(j<<1)+1]);
669 }
670 break;
671 case AF_MONO32:
672 for(j = 0; j < frames; ++j)
673 *out32++ = (float)(bus[j<<1] +
674 bus[(j<<1)+1]) * 0.5;
675 break;
676 case AF_STEREO32:
677 for(j = 0; j < frames; ++j)
678 {
679 *out32++ = (float)bus[j<<1];
680 *out32++ = (float)bus[(j<<1)+1];
681 }
682 break;
683 case AF_MIDI: /* whinestopper... */
684 break;
685 }
686 }
687 free(bus);
688 _calc_info(new_wid);
689
690 voice_kill(&resampler);
691 a_settings.quality = old_quality;
692
693 if(private_pool)
694 aev_close();
695
696 if(inplace)
697 {
698 audio_wave_free(wid);
699 memcpy(wavetab + wid, wavetab + new_wid, sizeof(audio_wave_t));
700 memset(wavetab + new_wid, 0, sizeof(audio_wave_t));
701 return wid;
702 }
703 else
704 {
705 _calc_info(wid); /* Restore after our tweaking */
706 return new_wid;
707 }
708 }
709
710
audio_wave_clone(int wid,int new_wid)711 int audio_wave_clone(int wid, int new_wid)
712 {
713 if(wid >= AUDIO_MAX_WAVES)
714 return -1;
715 if(wid < 0)
716 return -2;
717 new_wid = audio_wave_format(new_wid, wavetab[wid].format,
718 wavetab[wid].rate);
719 if(new_wid < 0)
720 return new_wid;
721 return audio_wave_load_mem(new_wid, wavetab[wid].data.si8,
722 wavetab[wid].size, wavetab[wid].looped);
723 }
724
725
726 /* We're simply using the same path for everything. */
audio_set_path(const char * path)727 void audio_set_path(const char *path)
728 {
729 eel_set_path(path);
730 }
731
732
audio_path(void)733 const char *audio_path(void)
734 {
735 return eel_path();
736 }
737
738
load_midi(int wid,const char * name)739 static int load_midi(int wid, const char *name)
740 {
741 midi_file_t *mf;
742
743 wid = audio_wave_alloc(wid);
744 if(wid < 0)
745 return wid;
746
747 mf = mf_open(name);
748 if(!mf)
749 {
750 log_printf(ELOG, "load_midi(): Failed to load file"
751 " \"%s\"! (Path = \"%s\")\n", name,
752 eel_path());
753 audio_wave_free(wid);
754 return -1;
755 }
756
757 wavetab[wid].data.midi = mf;
758
759 wavetab[wid].size = 1; /* Duration in ms or something? */
760 wavetab[wid].xsize = 0; /* N/A */
761 wavetab[wid].howtofree = HTF_FREE;
762
763 wavetab[wid].format = AF_MIDI;
764 wavetab[wid].rate = 120; /* PPQN? */
765 wavetab[wid].looped = 0; /* Not yet implemented */
766
767 wavetab[wid].speed = 120; /* ? */
768 wavetab[wid].samples = 1; /* Number of events? */
769
770 log_printf(DLOG, ".------------------------------------------------------\n");
771 log_printf(DLOG, "| MIDI File: %s\n", name);
772 log_printf(DLOG, "| Format: %u\n", mf->format);
773 log_printf(DLOG, "| Title: %s\n", mf->title);
774 log_printf(DLOG, "| Author: %s\n", mf->author);
775 log_printf(DLOG, "| Remarks: %s\n", mf->remarks);
776 log_printf(DLOG, "'------------------------------------------------------\n");
777
778 return wid;
779 }
780
781
audio_wave_load(int wid,const char * name,int looped)782 int audio_wave_load(int wid, const char *name, int looped)
783 {
784 char buf[1024];
785 SDL_AudioSpec spec;
786 Uint8 *data = NULL;
787 Uint32 size;
788 int format = -2;
789 int rate = 0; /* Warning suppressor */
790 int res;
791 int using_loadwav = 0;
792
793 /* Prepend path */
794 strncpy(buf, eel_path(), sizeof(buf));
795 #ifdef WIN32
796 strncat(buf, "\\", sizeof(buf));
797 #elif defined MACOS
798 strncat(buf, ":", sizeof(buf));
799 #else
800 strncat(buf, "/", sizeof(buf));
801 #endif
802 strncat(buf, name, sizeof(buf));
803
804 /* Check extension */
805 if(strstr(name, ".raw") || strstr(name, ".RAW"))
806 {
807 format = -1;
808 res = LoadRAW(buf, &data, &size, &format, &rate, &looped);
809 if(res < 0)
810 format = -1;
811 }
812 else if(strstr(name, ".agw") || strstr(name, ".AGW"))
813 return agw_load(wid, name); /* No full path here! */
814 else if(strstr(name, ".mid") || strstr(name, ".MID"))
815 return load_midi(wid, buf);
816 else
817 {
818 using_loadwav = 1;
819 res = SDL_LoadWAV(buf, &spec, &data, &size) ? 0 : -1;
820 }
821
822 wid = audio_wave_alloc(wid);
823 if(wid < 0)
824 return wid;
825
826 if(format >= 0)
827 {
828 wavetab[wid].format = format;
829 wavetab[wid].rate = rate;
830 }
831 else if(using_loadwav)
832 {
833 switch (spec.format)
834 {
835 case AUDIO_S8:
836 wavetab[wid].format = AF_MONO8;
837 break;
838 case AUDIO_S16SYS:
839 wavetab[wid].format = AF_MONO16;
840 break;
841 default:
842 log_printf(ELOG, "sound_load(): Unsupported wave format!\n");
843 SDL_FreeWAV((Uint8 *)(wavetab[wid].data.si8));
844 res = -1;
845 break;
846 }
847 if(spec.channels == 2)
848 ++wavetab[wid].format;
849 wavetab[wid].rate = spec.freq;
850 }
851
852 if(res < 0)
853 {
854 log_printf(ELOG, "audio_wave_load(): Failed to load file"
855 " \"%s\"! (Path = \"%s\")\n", name,
856 eel_path());
857 audio_wave_free(wid);
858 return -3;
859 }
860
861 if(data)
862 audio_wave_load_mem(wid, data, size, looped);
863
864 if(using_loadwav)
865 SDL_FreeWAV(data);
866 else
867 free(data);
868
869 return wid;
870 }
871
872
audio_wave_save(int wid,const char * name)873 int audio_wave_save(int wid, const char *name)
874 {
875 char buf[1024];
876 audio_wave_t *wave = audio_wave_get(wid);
877 if(!wave)
878 return -1;
879
880 /* Prepend path */
881 strncpy(buf, eel_path(), sizeof(buf));
882 #ifdef WIN32
883 strncat(buf, "\\", sizeof(buf));
884 #elif defined MACOS
885 strncat(buf, ":", sizeof(buf));
886 #else
887 strncat(buf, "/", sizeof(buf));
888 #endif
889 strncat(buf, name, sizeof(buf));
890 log_printf(DLOG, "Saving to \"%s\"\n", buf);
891 /* Check extension */
892 if(strstr(name, ".raw") || strstr(name, ".RAW"))
893 return SaveRAW(buf, wave->data.si8, wave->size,
894 (int)wave->format, wave->rate, wave->looped);
895 else
896 return -2;
897 }
898
899
audio_wave_free(int wid)900 void audio_wave_free(int wid)
901 {
902 int w, first, last;
903 CHECKINIT
904 if(wid < 0)
905 {
906 first = 0;
907 last = AUDIO_MAX_WAVES - 1;
908 }
909 else
910 first = last = wid;
911 for(w = first; w <= last; ++w)
912 {
913 if(!wavetab[w].data.si8)
914 continue;
915 if(HTF_FREE == wavetab[w].howtofree)
916 switch(wavetab[w].format)
917 {
918 case AF_MONO8:
919 case AF_STEREO8:
920 case AF_MONO16:
921 case AF_STEREO16:
922 case AF_MONO32:
923 case AF_STEREO32:
924 free(wavetab[w].data.si8);
925 break;
926 case AF_MIDI:
927 mf_close(wavetab[w].data.midi);
928 break;
929 }
930 wavetab[w].data.si8 = NULL;
931 wavetab[w].size = 0;
932 wavetab[w].xsize = 0;
933 wavetab[w].allocated = 0;
934 }
935 }
936
937
audio_wave_info(int wid)938 void audio_wave_info(int wid)
939 {
940 int w, first, last;
941 int count = 0;
942 int total_size = 0;
943 int total_time = 0;
944 if(wid < 0)
945 {
946 first = 0;
947 last = AUDIO_MAX_WAVES - 1;
948 }
949 else
950 first = last = wid;
951 log_printf(VLOG, "Waveform info:\n");
952 for(w = first; w <= last; ++w)
953 {
954 const char *f;
955 if(!wavetab[w].allocated)
956 continue;
957 switch(wavetab[w].format)
958 {
959 case AF_MONO8: f = "MONO8 "; break;
960 case AF_STEREO8: f = "STEREO8 "; break;
961 case AF_MONO16: f = "MONO16 "; break;
962 case AF_STEREO16: f = "STEREO16"; break;
963 case AF_MONO32: f = "MONO32 "; break;
964 case AF_STEREO32: f = "STEREO32"; break;
965 case AF_MIDI: f = "MIDI "; break;
966 default: f = "Unknown "; break;
967 }
968 if(wavetab[w].format == AF_MIDI)
969 log_printf(VLOG, " (%3d: %s %s, %d PPQN,\t%d events)\n",
970 w, f, wavetab[w].data.midi->title,
971 wavetab[w].rate, wavetab[w].size);
972 else
973 {
974 float d = (float)wavetab[w].samples / wavetab[w].rate;
975 log_printf(VLOG, " %3d: %s %s, %d Hz,\t%d bytes\t"
976 "(%.2f s)\n",
977 w, f, wavetab[w].looped ?
978 "LOOPED" : "ONESHOT",
979 wavetab[w].rate, wavetab[w].size, d);
980 total_size += wavetab[w].size;
981 total_time += d;
982 ++count;
983 }
984 }
985 log_printf(VLOG, " Total %d waveforms, total size: %d bytes, "
986 "total time: %d s\n", count, total_size, total_time);
987 }
988