1 /*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15 */
16
17 /* Sound file decoder for .wav, .mod, .ogg (to be used with OpenAL)
18 * API is heavily influenced by SDL_sound.
19 */
20
21 #include <string.h>
22 #include <stdlib.h>
23 #include "port.h"
24 #include "libs/memlib.h"
25 #include "libs/file.h"
26 #include "libs/log.h"
27 #include "decoder.h"
28 #include "wav.h"
29 #include "dukaud.h"
30 #include "modaud.h"
31 #ifndef OVCODEC_NONE
32 # include "oggaud.h"
33 #endif /* OVCODEC_NONE */
34 #include "aiffaud.h"
35
36
37 #define MAX_REG_DECODERS 31
38
39 #define THIS_PTR TFB_SoundDecoder*
40
41 static const char* bufa_GetName (void);
42 static bool bufa_InitModule (int flags, const TFB_DecoderFormats*);
43 static void bufa_TermModule (void);
44 static uint32 bufa_GetStructSize (void);
45 static int bufa_GetError (THIS_PTR);
46 static bool bufa_Init (THIS_PTR);
47 static void bufa_Term (THIS_PTR);
48 static bool bufa_Open (THIS_PTR, uio_DirHandle *dir, const char *filename);
49 static void bufa_Close (THIS_PTR);
50 static int bufa_Decode (THIS_PTR, void* buf, sint32 bufsize);
51 static uint32 bufa_Seek (THIS_PTR, uint32 pcm_pos);
52 static uint32 bufa_GetFrame (THIS_PTR);
53
54 TFB_SoundDecoderFuncs bufa_DecoderVtbl =
55 {
56 bufa_GetName,
57 bufa_InitModule,
58 bufa_TermModule,
59 bufa_GetStructSize,
60 bufa_GetError,
61 bufa_Init,
62 bufa_Term,
63 bufa_Open,
64 bufa_Close,
65 bufa_Decode,
66 bufa_Seek,
67 bufa_GetFrame,
68 };
69
70 typedef struct tfb_bufsounddecoder
71 {
72 // always the first member
73 TFB_SoundDecoder decoder;
74
75 // private
76 void* data;
77 uint32 max_pcm;
78 uint32 cur_pcm;
79
80 } TFB_BufSoundDecoder;
81
82 #define SD_MIN_SIZE (sizeof (TFB_BufSoundDecoder))
83
84 static const char* nula_GetName (void);
85 static bool nula_InitModule (int flags, const TFB_DecoderFormats*);
86 static void nula_TermModule (void);
87 static uint32 nula_GetStructSize (void);
88 static int nula_GetError (THIS_PTR);
89 static bool nula_Init (THIS_PTR);
90 static void nula_Term (THIS_PTR);
91 static bool nula_Open (THIS_PTR, uio_DirHandle *dir, const char *filename);
92 static void nula_Close (THIS_PTR);
93 static int nula_Decode (THIS_PTR, void* buf, sint32 bufsize);
94 static uint32 nula_Seek (THIS_PTR, uint32 pcm_pos);
95 static uint32 nula_GetFrame (THIS_PTR);
96
97 TFB_SoundDecoderFuncs nula_DecoderVtbl =
98 {
99 nula_GetName,
100 nula_InitModule,
101 nula_TermModule,
102 nula_GetStructSize,
103 nula_GetError,
104 nula_Init,
105 nula_Term,
106 nula_Open,
107 nula_Close,
108 nula_Decode,
109 nula_Seek,
110 nula_GetFrame,
111 };
112
113 typedef struct tfb_nullsounddecoder
114 {
115 // always the first member
116 TFB_SoundDecoder decoder;
117
118 // private
119 uint32 cur_pcm;
120
121 } TFB_NullSoundDecoder;
122
123 #undef THIS_PTR
124
125
126 struct TFB_RegSoundDecoder
127 {
128 bool builtin;
129 bool used; // ever used indicator
130 const char* ext;
131 const TFB_SoundDecoderFuncs* funcs;
132 };
133 static TFB_RegSoundDecoder sd_decoders[MAX_REG_DECODERS + 1] =
134 {
135 {true, true, "wav", &wava_DecoderVtbl},
136 {true, true, "mod", &moda_DecoderVtbl},
137 #ifndef OVCODEC_NONE
138 {true, true, "ogg", &ova_DecoderVtbl},
139 #endif /* OVCODEC_NONE */
140 {true, true, "duk", &duka_DecoderVtbl},
141 {true, true, "aif", &aifa_DecoderVtbl},
142 {false, false, NULL, NULL}, // null term
143 };
144
145 static TFB_DecoderFormats decoder_formats;
146 static int sd_flags = 0;
147
148 /* change endianness of 16bit words
149 * Only works optimal when 'data' is aligned on a 32 bits boundary.
150 */
151 void
SoundDecoder_SwapWords(uint16 * data,uint32 size)152 SoundDecoder_SwapWords (uint16* data, uint32 size)
153 {
154 uint32 fsize = size & (~3U);
155
156 size -= fsize;
157 fsize >>= 2;
158 for (; fsize; fsize--, data += 2)
159 {
160 uint32 v = *(uint32*)data;
161 *(uint32*)data = ((v & 0x00ff00ff) << 8)
162 | ((v & 0xff00ff00) >> 8);
163 }
164 if (size)
165 {
166 /* leftover word */
167 *data = ((*data & 0x00ff) << 8) | ((*data & 0xff00) >> 8);
168 }
169 }
170
171 const char*
SoundDecoder_GetName(TFB_SoundDecoder * decoder)172 SoundDecoder_GetName (TFB_SoundDecoder *decoder)
173 {
174 if (!decoder || !decoder->funcs)
175 return "(Null)";
176 return decoder->funcs->GetName ();
177 }
178
179 sint32
SoundDecoder_Init(int flags,TFB_DecoderFormats * formats)180 SoundDecoder_Init (int flags, TFB_DecoderFormats *formats)
181 {
182 TFB_RegSoundDecoder* info;
183 sint32 ret = 0;
184
185 if (!formats)
186 {
187 log_add (log_Error, "SoundDecoder_Init(): missing decoder formats");
188 return 1;
189 }
190 decoder_formats = *formats;
191
192 // init built-in decoders
193 for (info = sd_decoders; info->ext; info++)
194 {
195 if (!info->funcs->InitModule (flags, &decoder_formats))
196 {
197 log_add (log_Error, "SoundDecoder_Init(): "
198 "%s audio decoder init failed",
199 info->funcs->GetName ());
200 ret = 1;
201 }
202 }
203
204 sd_flags = flags;
205
206 return ret;
207 }
208
209 void
SoundDecoder_Uninit(void)210 SoundDecoder_Uninit (void)
211 {
212 TFB_RegSoundDecoder* info;
213
214 // uninit all decoders
215 // and unregister loaded decoders
216 for (info = sd_decoders; info->used; info++)
217 {
218 if (info->ext) // check if present
219 info->funcs->TermModule ();
220
221 if (!info->builtin)
222 {
223 info->used = false;
224 info->ext = NULL;
225 }
226 }
227 }
228
229 TFB_RegSoundDecoder*
SoundDecoder_Register(const char * fileext,TFB_SoundDecoderFuncs * decvtbl)230 SoundDecoder_Register (const char* fileext, TFB_SoundDecoderFuncs* decvtbl)
231 {
232 TFB_RegSoundDecoder* info;
233 TFB_RegSoundDecoder* newslot = NULL;
234
235 if (!decvtbl)
236 {
237 log_add (log_Warning, "SoundDecoder_Register(): Null decoder table");
238 return NULL;
239 }
240 if (!fileext)
241 {
242 log_add (log_Warning, "SoundDecoder_Register(): Bad file type for %s",
243 decvtbl->GetName ());
244 return NULL;
245 }
246
247 // check if extension already registered
248 for (info = sd_decoders; info->used &&
249 (!info->ext || strcmp (info->ext, fileext) != 0);
250 ++info)
251 {
252 // and pick up an empty slot (where available)
253 if (!newslot && !info->ext)
254 newslot = info;
255 }
256
257 if (info >= sd_decoders + MAX_REG_DECODERS)
258 {
259 log_add (log_Warning, "SoundDecoder_Register(): Decoders limit reached");
260 return NULL;
261 }
262 else if (info->ext)
263 {
264 log_add (log_Warning, "SoundDecoder_Register(): "
265 "'%s' decoder already registered (%s denied)",
266 fileext, decvtbl->GetName ());
267 return NULL;
268 }
269
270 if (!decvtbl->InitModule (sd_flags, &decoder_formats))
271 {
272 log_add (log_Warning, "SoundDecoder_Register(): %s decoder init failed",
273 decvtbl->GetName ());
274 return NULL;
275 }
276
277 if (!newslot)
278 {
279 newslot = info;
280 newslot->used = true;
281 // make next one a term
282 info[1].builtin = false;
283 info[1].used = false;
284 info[1].ext = NULL;
285 }
286
287 newslot->ext = fileext;
288 newslot->funcs = decvtbl;
289
290 return newslot;
291 }
292
293 void
SoundDecoder_Unregister(TFB_RegSoundDecoder * regdec)294 SoundDecoder_Unregister (TFB_RegSoundDecoder* regdec)
295 {
296 if (regdec < sd_decoders || regdec >= sd_decoders + MAX_REG_DECODERS ||
297 !regdec->ext || !regdec->funcs)
298 {
299 log_add (log_Warning, "SoundDecoder_Unregister(): "
300 "Invalid or expired decoder passed");
301 return;
302 }
303
304 regdec->funcs->TermModule ();
305 regdec->ext = NULL;
306 regdec->funcs = NULL;
307 }
308
309 const TFB_SoundDecoderFuncs*
SoundDecoder_Lookup(const char * fileext)310 SoundDecoder_Lookup (const char* fileext)
311 {
312 TFB_RegSoundDecoder* info;
313
314 for (info = sd_decoders; info->used &&
315 (!info->ext || strcmp (info->ext, fileext) != 0);
316 ++info)
317 ;
318 return info->ext ? info->funcs : NULL;
319 }
320
321 TFB_SoundDecoder*
SoundDecoder_Load(uio_DirHandle * dir,char * filename,uint32 buffer_size,uint32 startTime,sint32 runTime)322 SoundDecoder_Load (uio_DirHandle *dir, char *filename,
323 uint32 buffer_size, uint32 startTime, sint32 runTime)
324 // runTime < 0 specifies a default length for a nul decoder
325 {
326 const char* pext;
327 TFB_RegSoundDecoder* info;
328 const TFB_SoundDecoderFuncs* funcs;
329 TFB_SoundDecoder* decoder;
330 uint32 struct_size;
331
332 pext = strrchr (filename, '.');
333 if (!pext)
334 {
335 log_add (log_Warning, "SoundDecoder_Load(): Unknown file type (%s)",
336 filename);
337 return NULL;
338 }
339 ++pext;
340
341 for (info = sd_decoders; info->used &&
342 (!info->ext || strcmp (info->ext, pext) != 0);
343 ++info)
344 ;
345 if (!info->ext)
346 {
347 log_add (log_Warning, "SoundDecoder_Load(): Unsupported file type (%s)",
348 filename);
349
350 if (runTime)
351 {
352 runTime = abs (runTime);
353 startTime = 0;
354 funcs = &nula_DecoderVtbl;
355 }
356 else
357 {
358 return NULL;
359 }
360 }
361 else
362 {
363 funcs = info->funcs;
364 }
365
366 if (!fileExists2 (dir, filename))
367 {
368 if (runTime)
369 {
370 runTime = abs (runTime);
371 startTime = 0;
372 funcs = &nula_DecoderVtbl;
373 }
374 else
375 {
376 log_add (log_Warning, "SoundDecoder_Load(): %s does not exist",
377 filename);
378 return NULL;
379 }
380 }
381
382 struct_size = funcs->GetStructSize ();
383 if (struct_size < SD_MIN_SIZE)
384 struct_size = SD_MIN_SIZE;
385
386 decoder = (TFB_SoundDecoder*) HCalloc (struct_size);
387 decoder->funcs = funcs;
388 if (!decoder->funcs->Init (decoder))
389 {
390 log_add (log_Warning, "SoundDecoder_Load(): "
391 "%s decoder instance failed init",
392 decoder->funcs->GetName ());
393 HFree (decoder);
394 return NULL;
395 }
396
397 if (!decoder->funcs->Open (decoder, dir, filename))
398 {
399 log_add (log_Warning, "SoundDecoder_Load(): "
400 "%s decoder could not load %s",
401 decoder->funcs->GetName (), filename);
402 decoder->funcs->Term (decoder);
403 HFree (decoder);
404 return NULL;
405 }
406
407 decoder->buffer = HMalloc (buffer_size);
408 decoder->buffer_size = buffer_size;
409 decoder->looping = false;
410 decoder->error = SOUNDDECODER_OK;
411 decoder->dir = dir;
412 decoder->filename = (char *) HMalloc (strlen (filename) + 1);
413 strcpy (decoder->filename, filename);
414
415 if (decoder->is_null)
416 { // fake decoder, keeps voiceovers and etc. going
417 decoder->length = (float) (runTime / 1000.0);
418 }
419
420 decoder->length -= startTime / 1000.0f;
421 if (decoder->length < 0)
422 decoder->length = 0;
423 else if (runTime > 0 && runTime / 1000.0 < decoder->length)
424 decoder->length = (float)(runTime / 1000.0);
425
426 decoder->start_sample = (uint32)(startTime / 1000.0f * decoder->frequency);
427 decoder->end_sample = decoder->start_sample +
428 (unsigned long)(decoder->length * decoder->frequency);
429 if (decoder->start_sample != 0)
430 decoder->funcs->Seek (decoder, decoder->start_sample);
431
432 if (decoder->format == decoder_formats.mono8)
433 decoder->bytes_per_samp = 1;
434 else if (decoder->format == decoder_formats.mono16)
435 decoder->bytes_per_samp = 2;
436 else if (decoder->format == decoder_formats.stereo8)
437 decoder->bytes_per_samp = 2;
438 else if (decoder->format == decoder_formats.stereo16)
439 decoder->bytes_per_samp = 4;
440
441 decoder->pos = decoder->start_sample * decoder->bytes_per_samp;
442
443 return decoder;
444 }
445
446 uint32
SoundDecoder_Decode(TFB_SoundDecoder * decoder)447 SoundDecoder_Decode (TFB_SoundDecoder *decoder)
448 {
449 long decoded_bytes;
450 long rc;
451 long buffer_size;
452 uint32 max_bytes = UINT32_MAX;
453 uint8 *buffer;
454
455 if (!decoder || !decoder->funcs)
456 {
457 log_add (log_Warning, "SoundDecoder_Decode(): null or bad decoder");
458 return 0;
459 }
460
461 buffer = (uint8*) decoder->buffer;
462 buffer_size = decoder->buffer_size;
463 if (!decoder->looping && decoder->end_sample > 0)
464 {
465 max_bytes = decoder->end_sample * decoder->bytes_per_samp;
466 if (max_bytes - decoder->pos < decoder->buffer_size)
467 buffer_size = max_bytes - decoder->pos;
468 }
469
470 if (buffer_size == 0)
471 { // nothing more to decode
472 decoder->error = SOUNDDECODER_EOF;
473 return 0;
474 }
475
476 for (decoded_bytes = 0, rc = 1; rc > 0 && decoded_bytes < buffer_size; )
477 {
478 rc = decoder->funcs->Decode (decoder, buffer + decoded_bytes,
479 buffer_size - decoded_bytes);
480 if (rc < 0)
481 {
482 log_add (log_Warning, "SoundDecoder_Decode(): "
483 "error decoding %s, code %ld",
484 decoder->filename, rc);
485 }
486 else if (rc == 0)
487 { // probably EOF
488 if (decoder->looping)
489 {
490 SoundDecoder_Rewind (decoder);
491 if (decoder->error)
492 {
493 log_add (log_Warning, "SoundDecoder_Decode(): "
494 "tried to loop %s but couldn't rewind, "
495 "error code %d",
496 decoder->filename, decoder->error);
497 }
498 else
499 {
500 log_add (log_Info, "SoundDecoder_Decode(): "
501 "looping %s", decoder->filename);
502 rc = 1; // prime the loop again
503 }
504 }
505 else
506 {
507 log_add (log_Info, "SoundDecoder_Decode(): eof for %s",
508 decoder->filename);
509 }
510 }
511 else
512 { // some bytes decoded
513 decoded_bytes += rc;
514 }
515 }
516 decoder->pos += decoded_bytes;
517 if (rc < 0)
518 decoder->error = SOUNDDECODER_ERROR;
519 else if (rc == 0 || decoder->pos >= max_bytes)
520 decoder->error = SOUNDDECODER_EOF;
521 else
522 decoder->error = SOUNDDECODER_OK;
523
524 if (decoder->need_swap && decoded_bytes > 0 &&
525 (decoder->format == decoder_formats.stereo16 ||
526 decoder->format == decoder_formats.mono16))
527 {
528 SoundDecoder_SwapWords (
529 decoder->buffer, decoded_bytes);
530 }
531
532 return decoded_bytes;
533 }
534
535 uint32
SoundDecoder_DecodeAll(TFB_SoundDecoder * decoder)536 SoundDecoder_DecodeAll (TFB_SoundDecoder *decoder)
537 {
538 uint32 decoded_bytes;
539 long rc;
540 uint32 reqbufsize;
541
542 if (!decoder || !decoder->funcs)
543 {
544 log_add (log_Warning, "SoundDecoder_DecodeAll(): null or bad decoder");
545 return 0;
546 }
547
548 reqbufsize = decoder->buffer_size;
549
550 if (decoder->looping)
551 {
552 log_add (log_Warning, "SoundDecoder_DecodeAll(): "
553 "called for %s with looping", decoder->filename);
554 return 0;
555 }
556
557 if (reqbufsize < 4096)
558 reqbufsize = 4096;
559
560 for (decoded_bytes = 0, rc = 1; rc > 0; )
561 {
562 if (decoded_bytes >= decoder->buffer_size)
563 { // need to grow buffer
564 decoder->buffer_size += reqbufsize;
565 decoder->buffer = HRealloc (
566 decoder->buffer, decoder->buffer_size);
567 }
568
569 rc = decoder->funcs->Decode (decoder,
570 (uint8*) decoder->buffer + decoded_bytes,
571 decoder->buffer_size - decoded_bytes);
572
573 if (rc > 0)
574 decoded_bytes += rc;
575 }
576 decoder->buffer_size = decoded_bytes;
577 decoder->pos += decoded_bytes;
578 // Free up some unused memory
579 decoder->buffer = HRealloc (decoder->buffer, decoded_bytes);
580
581 if (decoder->need_swap && decoded_bytes > 0 &&
582 (decoder->format == decoder_formats.stereo16 ||
583 decoder->format == decoder_formats.mono16))
584 {
585 SoundDecoder_SwapWords (
586 decoder->buffer, decoded_bytes);
587 }
588
589 if (rc < 0)
590 {
591 decoder->error = SOUNDDECODER_ERROR;
592 log_add (log_Warning, "SoundDecoder_DecodeAll(): "
593 "error decoding %s, code %ld",
594 decoder->filename, rc);
595 return decoded_bytes;
596 }
597
598 // switch to Buffer decoder
599 decoder->funcs->Close (decoder);
600 decoder->funcs->Term (decoder);
601
602 decoder->funcs = &bufa_DecoderVtbl;
603 decoder->funcs->Init (decoder);
604 decoder->pos = 0;
605 decoder->start_sample = 0;
606 decoder->error = SOUNDDECODER_OK;
607
608 return decoded_bytes;
609 }
610
611 void
SoundDecoder_Rewind(TFB_SoundDecoder * decoder)612 SoundDecoder_Rewind (TFB_SoundDecoder *decoder)
613 {
614 SoundDecoder_Seek (decoder, 0);
615 }
616
617 // seekTime is specified in mili-seconds
618 void
SoundDecoder_Seek(TFB_SoundDecoder * decoder,uint32 seekTime)619 SoundDecoder_Seek (TFB_SoundDecoder *decoder, uint32 seekTime)
620 {
621 uint32 pcm_pos;
622
623 if (!decoder)
624 return;
625 if (!decoder->funcs)
626 {
627 log_add (log_Warning, "SoundDecoder_Seek(): bad decoder passed");
628 return;
629 }
630
631 pcm_pos = (uint32) (seekTime / 1000.0f * decoder->frequency);
632 pcm_pos = decoder->funcs->Seek (decoder,
633 decoder->start_sample + pcm_pos);
634 decoder->pos = pcm_pos * decoder->bytes_per_samp;
635 decoder->error = SOUNDDECODER_OK;
636 }
637
638 void
SoundDecoder_Free(TFB_SoundDecoder * decoder)639 SoundDecoder_Free (TFB_SoundDecoder *decoder)
640 {
641 if (!decoder)
642 return;
643 if (!decoder->funcs)
644 {
645 log_add (log_Warning, "SoundDecoder_Free(): bad decoder passed");
646 return;
647 }
648
649 decoder->funcs->Close (decoder);
650 decoder->funcs->Term (decoder);
651
652 HFree (decoder->buffer);
653 HFree (decoder->filename);
654 HFree (decoder);
655 }
656
657 float
SoundDecoder_GetTime(TFB_SoundDecoder * decoder)658 SoundDecoder_GetTime (TFB_SoundDecoder *decoder)
659 {
660 if (!decoder)
661 return 0.0f;
662 if (!decoder->funcs)
663 {
664 log_add (log_Warning, "SoundDecoder_GetTime(): bad decoder passed");
665 return 0.0f;
666 }
667
668 return (float)
669 ((decoder->pos / decoder->bytes_per_samp)
670 - decoder->start_sample
671 ) / decoder->frequency;
672 }
673
674 uint32
SoundDecoder_GetFrame(TFB_SoundDecoder * decoder)675 SoundDecoder_GetFrame (TFB_SoundDecoder *decoder)
676 {
677 if (!decoder)
678 return 0;
679 if (!decoder->funcs)
680 {
681 log_add (log_Warning, "SoundDecoder_GetFrame(): bad decoder passed");
682 return 0;
683 }
684
685 return decoder->funcs->GetFrame (decoder);
686 }
687
688
689 #define THIS_PTR TFB_SoundDecoder* This
690
691 static const char*
bufa_GetName(void)692 bufa_GetName (void)
693 {
694 return "Buffer";
695 }
696
697 static bool
bufa_InitModule(int flags,const TFB_DecoderFormats * fmts)698 bufa_InitModule (int flags, const TFB_DecoderFormats* fmts)
699 {
700 // this should never be called
701 log_add (log_Debug, "bufa_InitModule(): dead function called");
702 return false;
703
704 (void)flags; (void)fmts; // laugh at compiler warning
705 }
706
707 static void
bufa_TermModule(void)708 bufa_TermModule (void)
709 {
710 // this should never be called
711 log_add (log_Debug, "bufa_TermModule(): dead function called");
712 }
713
714 static uint32
bufa_GetStructSize(void)715 bufa_GetStructSize (void)
716 {
717 return sizeof (TFB_BufSoundDecoder);
718 }
719
720 static int
bufa_GetError(THIS_PTR)721 bufa_GetError (THIS_PTR)
722 {
723 return 0; // error? what error?!
724
725 (void)This; // laugh at compiler warning
726 }
727
728 static bool
bufa_Init(THIS_PTR)729 bufa_Init (THIS_PTR)
730 {
731 TFB_BufSoundDecoder* bufa = (TFB_BufSoundDecoder*) This;
732
733 This->need_swap = false;
734 // hijack the buffer
735 bufa->data = This->buffer;
736 bufa->max_pcm = This->buffer_size / This->bytes_per_samp;
737 bufa->cur_pcm = bufa->max_pcm;
738
739 return true;
740 }
741
742 static void
bufa_Term(THIS_PTR)743 bufa_Term (THIS_PTR)
744 {
745 //TFB_BufSoundDecoder* bufa = (TFB_BufSoundDecoder*) This;
746 bufa_Close (This); // ensure cleanup
747 }
748
749 static bool
bufa_Open(THIS_PTR,uio_DirHandle * dir,const char * filename)750 bufa_Open (THIS_PTR, uio_DirHandle *dir, const char *filename)
751 {
752 // this should never be called
753 log_add (log_Debug, "bufa_Open(): dead function called");
754 return false;
755
756 // laugh at compiler warnings
757 (void)This; (void)dir; (void)filename;
758 }
759
760 static void
bufa_Close(THIS_PTR)761 bufa_Close (THIS_PTR)
762 {
763 TFB_BufSoundDecoder* bufa = (TFB_BufSoundDecoder*) This;
764
765 // restore the status quo
766 if (bufa->data)
767 {
768 This->buffer = bufa->data;
769 bufa->data = NULL;
770 }
771 bufa->cur_pcm = 0;
772 }
773
774 static int
bufa_Decode(THIS_PTR,void * buf,sint32 bufsize)775 bufa_Decode (THIS_PTR, void* buf, sint32 bufsize)
776 {
777 TFB_BufSoundDecoder* bufa = (TFB_BufSoundDecoder*) This;
778 uint32 dec_pcm;
779 uint32 dec_bytes;
780
781 dec_pcm = bufsize / This->bytes_per_samp;
782 if (dec_pcm > bufa->max_pcm - bufa->cur_pcm)
783 dec_pcm = bufa->max_pcm - bufa->cur_pcm;
784 dec_bytes = dec_pcm * This->bytes_per_samp;
785
786 // Buffer decode is a hack
787 This->buffer = (uint8*) bufa->data
788 + bufa->cur_pcm * This->bytes_per_samp;
789
790 if (dec_pcm > 0)
791 bufa->cur_pcm += dec_pcm;
792
793 return dec_bytes;
794
795 (void)buf; // laugh at compiler warning
796 }
797
798 static uint32
bufa_Seek(THIS_PTR,uint32 pcm_pos)799 bufa_Seek (THIS_PTR, uint32 pcm_pos)
800 {
801 TFB_BufSoundDecoder* bufa = (TFB_BufSoundDecoder*) This;
802
803 if (pcm_pos > bufa->max_pcm)
804 pcm_pos = bufa->max_pcm;
805 bufa->cur_pcm = pcm_pos;
806
807 return pcm_pos;
808 }
809
810 static uint32
bufa_GetFrame(THIS_PTR)811 bufa_GetFrame (THIS_PTR)
812 {
813 return 0; // only 1 frame
814
815 (void)This; // laugh at compiler warning
816 }
817
818
819 static const char*
nula_GetName(void)820 nula_GetName (void)
821 {
822 return "Null";
823 }
824
825 static bool
nula_InitModule(int flags,const TFB_DecoderFormats * fmts)826 nula_InitModule (int flags, const TFB_DecoderFormats* fmts)
827 {
828 // this should never be called
829 log_add (log_Debug, "nula_InitModule(): dead function called");
830 return false;
831
832 (void)flags; (void)fmts; // laugh at compiler warning
833 }
834
835 static void
nula_TermModule(void)836 nula_TermModule (void)
837 {
838 // this should never be called
839 log_add (log_Debug, "nula_TermModule(): dead function called");
840 }
841
842 static uint32
nula_GetStructSize(void)843 nula_GetStructSize (void)
844 {
845 return sizeof (TFB_NullSoundDecoder);
846 }
847
848 static int
nula_GetError(THIS_PTR)849 nula_GetError (THIS_PTR)
850 {
851 return 0; // error? what error?!
852
853 (void)This; // laugh at compiler warning
854 }
855
856 static bool
nula_Init(THIS_PTR)857 nula_Init (THIS_PTR)
858 {
859 TFB_NullSoundDecoder* nula = (TFB_NullSoundDecoder*) This;
860
861 This->need_swap = false;
862 nula->cur_pcm = 0;
863 return true;
864 }
865
866 static void
nula_Term(THIS_PTR)867 nula_Term (THIS_PTR)
868 {
869 //TFB_NullSoundDecoder* nula = (TFB_NullSoundDecoder*) This;
870 nula_Close (This); // ensure cleanup
871 }
872
873 static bool
nula_Open(THIS_PTR,uio_DirHandle * dir,const char * filename)874 nula_Open (THIS_PTR, uio_DirHandle *dir, const char *filename)
875 {
876 This->frequency = 11025;
877 This->format = decoder_formats.mono16;
878 This->is_null = true;
879 return true;
880
881 // laugh at compiler warnings
882 (void)dir; (void)filename;
883 }
884
885 static void
nula_Close(THIS_PTR)886 nula_Close (THIS_PTR)
887 {
888 TFB_NullSoundDecoder* nula = (TFB_NullSoundDecoder*) This;
889
890 nula->cur_pcm = 0;
891 }
892
893 static int
nula_Decode(THIS_PTR,void * buf,sint32 bufsize)894 nula_Decode (THIS_PTR, void* buf, sint32 bufsize)
895 {
896 TFB_NullSoundDecoder* nula = (TFB_NullSoundDecoder*) This;
897 uint32 max_pcm;
898 uint32 dec_pcm;
899 uint32 dec_bytes;
900
901 max_pcm = (uint32) (This->length * This->frequency);
902 dec_pcm = bufsize / This->bytes_per_samp;
903 if (dec_pcm > max_pcm - nula->cur_pcm)
904 dec_pcm = max_pcm - nula->cur_pcm;
905 dec_bytes = dec_pcm * This->bytes_per_samp;
906
907 if (dec_pcm > 0)
908 {
909 memset (buf, 0, dec_bytes);
910 nula->cur_pcm += dec_pcm;
911 }
912
913 return dec_bytes;
914 }
915
916 static uint32
nula_Seek(THIS_PTR,uint32 pcm_pos)917 nula_Seek (THIS_PTR, uint32 pcm_pos)
918 {
919 TFB_NullSoundDecoder* nula = (TFB_NullSoundDecoder*) This;
920 uint32 max_pcm;
921
922 max_pcm = (uint32) (This->length * This->frequency);
923 if (pcm_pos > max_pcm)
924 pcm_pos = max_pcm;
925 nula->cur_pcm = pcm_pos;
926
927 return pcm_pos;
928 }
929
930 static uint32
nula_GetFrame(THIS_PTR)931 nula_GetFrame (THIS_PTR)
932 {
933 return 0; // only 1 frame
934
935 (void)This; // laugh at compiler warning
936 }
937