dynamic_flac.c
author Sam Lantinga <slouken@libsdl.org>
Wed, 27 Feb 2008 07:31:03 +0000
changeset 382 50501e45c57b
child 386 695494546b3c
permissions -rw-r--r--
Austen Dicken - Tue Feb 26 23:28:27 PST 2008

Ok, here is the patch I made for FLAC support.

I have tested it relatively thoroughly and currently the patch allows:
1. Pre-loading FLAC files and playing them via LoadWAV
2. The patch allows for FLAC support in the LoadMUS setting as well as:
* Pause / Resume
* Volume control
* Seeking

I also did a little benchmarking by comparing memory/cpu usage of playmus to
that of mplayer, and the results were very good. playmus typically took about
half the RAM as mplayer, though that may be attributed to mplayer being a more
"bulky" program. As such I would say that the two are probably about equal in
efficiency.

Also, it is important to note that, similar to the OGG support currently
built-in, my FLAC patch only supports 16 bit stereo-encoded sound. Also, it
is only for Native FLAC (standard) and not the derivative, Ogg-FLAC.

I have tried to find a simple way to detect Ogg-FLAC files, as the only
difference between Ogg-FLAC and Native FLAC support is changing the init_
function call, but after digging a little deeper it seems that Ogg-FLAC is
basically FLAC wrapped in an Ogg transport layer, so it would be better to have
a way to read the Ogg transport layer which then reads the inner audio files
according to the proper codec.

But anyway, that's another job for another day! For now this should provide
Native FLAC support!
     1 /*
     2     SDL_mixer:  An audio mixer library based on the SDL library
     3     Copyright (C) 1997-2004 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Library General Public
     7     License as published by the Free Software Foundation; either
     8     version 2 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Library General Public License for more details.
    14 
    15     You should have received a copy of the GNU Library General Public
    16     License along with this library; if not, write to the Free
    17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 
    22 
    23     Implementation of the dynamic loading functionality for libFLAC.
    24     									~ Austen Dicken (admin@cvpcs.org)
    25 */
    26 
    27 #ifdef FLAC_MUSIC
    28 
    29 #include "SDL_loadso.h"
    30 
    31 #include "dynamic_flac.h"
    32 
    33 flac_loader flac = {
    34 	0, NULL
    35 };
    36 
    37 #ifdef FLAC_DYNAMIC
    38 
    39 int Mix_InitFLAC() {
    40 	if ( flac.loaded == 0 ) {
    41 		flac.handle = SDL_LoadObject(FLAC_DYNAMIC);
    42 		if ( flac.handle == NULL ) {
    43 			return -1;
    44 		}
    45 		flac.FLAC__stream_decoder_new =
    46 			(FLAC__StreamDecoder *(*)())
    47 			SDL_LoadFunction(flac.handle, "FLAC__stream_decoder_new");
    48 		if ( flac.FLAC__stream_decoder_new == NULL ) {
    49 			SDL_UnloadObject(flac.handle);
    50 			return -1;
    51 		}
    52 		flac.FLAC__stream_decoder_delete =
    53 			(void (*)(FLAC__StreamDecoder *))
    54 			SDL_LoadFunction(flac.handle, "FLAC__stream_decoder_delete");
    55 		if ( flac.FLAC__stream_decoder_delete == NULL ) {
    56 			SDL_UnloadObject(flac.handle);
    57 			return -1;
    58 		}
    59 		flac.FLAC__stream_decoder_init_stream =
    60 			(FLAC__StreamDecoderInitStatus (*)(
    61 						FLAC__StreamDecoder *,
    62 						FLAC__StreamDecoderReadCallback,
    63 						FLAC__StreamDecoderSeekCallback,
    64 						FLAC__StreamDecoderTellCallback,
    65 						FLAC__StreamDecoderLengthCallback,
    66 						FLAC__StreamDecoderEofCallback,
    67 						FLAC__StreamDecoderWriteCallback,
    68 						FLAC__StreamDecoderMetadataCallback,
    69 						FLAC__StreamDecoderErrorCallback,
    70 						void *))
    71 			SDL_LoadFunction(flac.handle, "FLAC__stream_decoder_init_stream");
    72 		if ( flac.FLAC__stream_decoder_init_stream == NULL ) {
    73 			SDL_UnloadObject(flac.handle);
    74 			return -1;
    75 		}
    76 		flac.FLAC__stream_decoder_finish =
    77 			(FLAC__bool (*)(FLAC__StreamDecoder *))
    78 			SDL_LoadFunction(flac.handle, "FLAC__stream_decoder_finish");
    79 		if ( flac.FLAC__stream_decoder_finish == NULL ) {
    80 			SDL_UnloadObject(flac.handle);
    81 			return -1;
    82 		}
    83 		flac.FLAC__stream_decoder_flush =
    84 			(FLAC__bool (*)(FLAC__StreamDecoder *))
    85 			SDL_LoadFunction(flac.handle, "FLAC__stream_decoder_flush");
    86 		if ( flac.FLAC__stream_decoder_flush == NULL ) {
    87 			SDL_UnloadObject(flac.handle);
    88 			return -1;
    89 		}
    90 		flac.FLAC__stream_decoder_process_single =
    91 			(FLAC__bool (*)(FLAC__StreamDecoder *))
    92 			SDL_LoadFunction(flac.handle,
    93 						"FLAC__stream_decoder_process_single");
    94 		if ( flac.FLAC__stream_decoder_process_single == NULL ) {
    95 			SDL_UnloadObject(flac.handle);
    96 			return -1;
    97 		}
    98 		flac.FLAC__stream_decoder_process_until_end_of_metadata =
    99 			(FLAC__bool (*)(FLAC__StreamDecoder *))
   100 			SDL_LoadFunction(flac.handle,
   101 						"FLAC__stream_decoder_process_until_end_of_metadata");
   102 		if ( flac.FLAC__stream_decoder_process_until_end_of_metadata == NULL ) {
   103 			SDL_UnloadObject(flac.handle);
   104 			return -1;
   105 		}
   106 		flac.FLAC__stream_decoder_process_until_end_of_stream =
   107 			(FLAC__bool (*)(FLAC__StreamDecoder *))
   108 			SDL_LoadFunction(flac.handle,
   109 						"FLAC__stream_decoder_process_until_end_of_stream");
   110 		if ( flac.FLAC__stream_decoder_process_until_end_of_stream == NULL ) {
   111 			SDL_UnloadObject(flac.handle);
   112 			return -1;
   113 		}
   114 		flac.FLAC__stream_decoder_seek_absolute =
   115 			(FLAC__bool (*)(FLAC__StreamDecoder *, FLAC__uint64))
   116 			SDL_LoadFunction(flac.handle, "FLAC__stream_decoder_seek_absolute");
   117 		if ( flac.FLAC__stream_decoder_seek_absolute == NULL ) {
   118 			SDL_UnloadObject(flac.handle);
   119 			return -1;
   120 		}
   121 		flac.FLAC__stream_decoder_get_state =
   122 			(FLAC__StreamDecoderState (*)(const FLAC__StreamDecoder *decoder))
   123 			SDL_LoadFunction(flac.handle, "FLAC__stream_decoder_get_state");
   124 		if ( flac.FLAC__stream_decoder_get_state == NULL ) {
   125 			SDL_UnloadObject(flac.handle);
   126 			return -1;
   127 		}
   128 	}
   129 	++flac.loaded;
   130 
   131 	return 0;
   132 }
   133 void Mix_QuitFLAC() {
   134 	if ( flac.loaded == 0 ) {
   135 		return;
   136 	}
   137 	if ( flac.loaded == 1 ) {
   138 		SDL_UnloadObject(flac.handle);
   139 	}
   140 	--flac.loaded;
   141 }
   142 #else
   143 int Mix_InitFLAC() {
   144 	if ( flac.loaded == 0 ) {
   145 		flac.FLAC__stream_decoder_new = FLAC__stream_decoder_new;
   146 		flac.FLAC__stream_decoder_delete = FLAC__stream_decoder_delete;
   147 		flac.FLAC__stream_decoder_init_stream =
   148 							FLAC__stream_decoder_init_stream;
   149 		flac.FLAC__stream_decoder_finish = FLAC__stream_decoder_finish;
   150 		flac.FLAC__stream_decoder_flush = FLAC__stream_decoder_flush;
   151 		flac.FLAC__stream_decoder_process_single =
   152 							FLAC__stream_decoder_process_single;
   153 		flac.FLAC__stream_decoder_process_until_end_of_metadata =
   154 							FLAC__stream_decoder_process_until_end_of_metadata;
   155 		flac.FLAC__stream_decoder_process_until_end_of_stream =
   156 							FLAC__stream_decoder_process_until_end_of_stream;
   157 		flac.FLAC__stream_decoder_seek_absolute =
   158 							FLAC__stream_decoder_seek_absolute;
   159 		flac.FLAC__stream_decoder_get_state =
   160 							FLAC__stream_decoder_get_state;
   161 	}
   162 	++flac.loaded;
   163 
   164 	return 0;
   165 }
   166 void Mix_QuitFLAC() {
   167 	if ( flac.loaded == 0 ) {
   168 		return;
   169 	}
   170 	if ( flac.loaded == 1 ) {
   171 	}
   172 	--flac.loaded;
   173 }
   174 #endif // FLAC_DYNAMIC
   175 
   176 #endif // FLAC_MUSIC