Mercurial > SDL_sound_CoreAudio
annotate decoders/flac.c @ 562:7e08477b0fc1
MP3 decoder upgrade work.
Ripped out SMPEG and mpglib support, replaced it with "mpg123.c" and libmpg123.
libmpg123 is a much better version of mpglib, so it should solve all the
problems about MP3's not seeking, or most modern MP3's not playing at all,
etc. Since you no longer have to make a tradeoff with SMPEG for features, and
SMPEG is basically rotting, I removed it from the project.
There is still work to be done with libmpg123...there are MMX, 3DNow, SSE,
Altivec, etc decoders which we don't have enabled at the moment, and the
build system could use some work to make this compile more cleanly, etc.
Still: huge win.
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Fri, 30 Jan 2009 02:44:47 -0500 |
parents | 2e8907ff98e9 |
children |
rev | line source |
---|---|
155 | 1 /* |
2 * SDL_sound -- An abstract sound format decoding API. | |
3 * Copyright (C) 2001 Ryan C. Gordon. | |
4 * | |
5 * This library is free software; you can redistribute it and/or | |
6 * modify it under the terms of the GNU Lesser General Public | |
7 * License as published by the Free Software Foundation; either | |
8 * version 2.1 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 * Lesser General Public License for more details. | |
14 * | |
15 * You should have received a copy of the GNU Lesser General Public | |
16 * License along with this library; if not, write to the Free Software | |
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 */ | |
19 | |
20 /* | |
21 * FLAC decoder for SDL_sound. | |
22 * | |
23 * This driver handles FLAC audio, that is to say the Free Lossless Audio | |
24 * Codec. It depends on libFLAC for decoding, which can be grabbed from: | |
25 * http://flac.sourceforge.net | |
26 * | |
552
2e8907ff98e9
Replaced references to COPYING with references to LICENSE.txt ...
Ryan C. Gordon <icculus@icculus.org>
parents:
536
diff
changeset
|
27 * Please see the file LICENSE.txt in the source's root directory. |
155 | 28 * |
536
8a814bbbedfa
Merged r544:545 from branches/stable-1.0: converted to UTF-8 encoding.
Ryan C. Gordon <icculus@icculus.org>
parents:
516
diff
changeset
|
29 * This file written by Torbjörn Andersson. (d91tan@Update.UU.SE) |
155 | 30 */ |
31 | |
32 #if HAVE_CONFIG_H | |
33 # include <config.h> | |
34 #endif | |
35 | |
36 #ifdef SOUND_SUPPORTS_FLAC | |
37 | |
38 #include <stdio.h> | |
39 #include <stdlib.h> | |
40 #include <string.h> | |
41 | |
42 #include "SDL_sound.h" | |
43 | |
44 #define __SDL_SOUND_INTERNAL__ | |
45 #include "SDL_sound_internal.h" | |
46 | |
516
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
47 #include <FLAC/export.h> |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
48 |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
49 /* FLAC 1.1.3 has FLAC_API_VERSION_CURRENT == 8 */ |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
50 #if !defined(FLAC_API_VERSION_CURRENT) || FLAC_API_VERSION_CURRENT < 8 |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
51 #define LEGACY_FLAC |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
52 #else |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
53 #undef LEGACY_FLAC |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
54 #endif |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
55 |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
56 #ifdef LEGACY_FLAC |
443 | 57 #include <FLAC/seekable_stream_decoder.h> |
312 | 58 |
59 #define D_END_OF_STREAM FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM | |
60 | |
61 #define d_new() FLAC__seekable_stream_decoder_new() | |
62 #define d_init(x) FLAC__seekable_stream_decoder_init(x) | |
422
5b06e23d934e
Removed backwards compatible API nastiness from FLAC decoder.
Ryan C. Gordon <icculus@icculus.org>
parents:
400
diff
changeset
|
63 #define d_process_metadata(x) FLAC__seekable_stream_decoder_process_until_end_of_metadata(x) |
5b06e23d934e
Removed backwards compatible API nastiness from FLAC decoder.
Ryan C. Gordon <icculus@icculus.org>
parents:
400
diff
changeset
|
64 #define d_process_one_frame(x) FLAC__seekable_stream_decoder_process_single(x) |
312 | 65 #define d_get_state(x) FLAC__seekable_stream_decoder_get_state(x) |
66 #define d_finish(x) FLAC__seekable_stream_decoder_finish(x) | |
67 #define d_delete(x) FLAC__seekable_stream_decoder_delete(x) | |
68 #define d_set_read_callback(x, y) FLAC__seekable_stream_decoder_set_read_callback(x, y) | |
69 #define d_set_write_callback(x, y) FLAC__seekable_stream_decoder_set_write_callback(x, y) | |
70 #define d_set_metadata_callback(x, y) FLAC__seekable_stream_decoder_set_metadata_callback(x, y) | |
71 #define d_set_error_callback(x, y) FLAC__seekable_stream_decoder_set_error_callback(x, y) | |
72 #define d_set_client_data(x, y) FLAC__seekable_stream_decoder_set_client_data(x, y) | |
73 | |
74 typedef FLAC__SeekableStreamDecoder decoder_t; | |
75 typedef FLAC__SeekableStreamDecoderReadStatus d_read_status_t; | |
76 | |
77 #define D_SEEK_STATUS_OK FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK | |
78 #define D_SEEK_STATUS_ERROR FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR | |
79 #define D_TELL_STATUS_OK FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK | |
80 #define D_TELL_STATUS_ERROR FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR | |
81 #define D_LENGTH_STATUS_OK FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK | |
82 #define D_LENGTH_STATUS_ERROR FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR | |
83 | |
84 #define d_set_seek_callback(x, y) FLAC__seekable_stream_decoder_set_seek_callback(x, y) | |
85 #define d_set_tell_callback(x, y) FLAC__seekable_stream_decoder_set_tell_callback(x, y) | |
86 #define d_set_length_callback(x, y) FLAC__seekable_stream_decoder_set_length_callback(x, y) | |
87 #define d_set_eof_callback(x, y) FLAC__seekable_stream_decoder_set_eof_callback(x, y) | |
88 #define d_seek_absolute(x, y) FLAC__seekable_stream_decoder_seek_absolute(x, y) | |
89 | |
90 typedef FLAC__SeekableStreamDecoderSeekStatus d_seek_status_t; | |
91 typedef FLAC__SeekableStreamDecoderTellStatus d_tell_status_t; | |
92 typedef FLAC__SeekableStreamDecoderLengthStatus d_length_status_t; | |
516
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
93 #else |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
94 #include <FLAC/stream_decoder.h> |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
95 |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
96 #define D_END_OF_STREAM FLAC__STREAM_DECODER_END_OF_STREAM |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
97 |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
98 #define d_new() FLAC__stream_decoder_new() |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
99 #define d_process_metadata(x) FLAC__stream_decoder_process_until_end_of_metadata(x) |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
100 #define d_process_one_frame(x) FLAC__stream_decoder_process_single(x) |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
101 #define d_get_state(x) FLAC__stream_decoder_get_state(x) |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
102 #define d_finish(x) FLAC__stream_decoder_finish(x) |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
103 #define d_delete(x) FLAC__stream_decoder_delete(x) |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
104 |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
105 typedef FLAC__StreamDecoder decoder_t; |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
106 typedef FLAC__StreamDecoderReadStatus d_read_status_t; |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
107 |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
108 #define D_SEEK_STATUS_OK FLAC__STREAM_DECODER_SEEK_STATUS_OK |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
109 #define D_SEEK_STATUS_ERROR FLAC__STREAM_DECODER_SEEK_STATUS_ERROR |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
110 #define D_TELL_STATUS_OK FLAC__STREAM_DECODER_TELL_STATUS_OK |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
111 #define D_TELL_STATUS_ERROR FLAC__STREAM_DECODER_TELL_STATUS_ERROR |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
112 #define D_LENGTH_STATUS_OK FLAC__STREAM_DECODER_LENGTH_STATUS_OK |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
113 #define D_LENGTH_STATUS_ERROR FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
114 |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
115 #define d_seek_absolute(x, y) FLAC__stream_decoder_seek_absolute(x, y) |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
116 |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
117 typedef FLAC__StreamDecoderSeekStatus d_seek_status_t; |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
118 typedef FLAC__StreamDecoderTellStatus d_tell_status_t; |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
119 typedef FLAC__StreamDecoderLengthStatus d_length_status_t; |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
120 #endif |
312 | 121 |
393
b12c4483815e
Handles all versions of libFLAC up to version 1.0.3, now.
Ryan C. Gordon <icculus@icculus.org>
parents:
387
diff
changeset
|
122 #define D_WRITE_CONTINUE FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE |
b12c4483815e
Handles all versions of libFLAC up to version 1.0.3, now.
Ryan C. Gordon <icculus@icculus.org>
parents:
387
diff
changeset
|
123 #define D_READ_END_OF_STREAM FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM |
b12c4483815e
Handles all versions of libFLAC up to version 1.0.3, now.
Ryan C. Gordon <icculus@icculus.org>
parents:
387
diff
changeset
|
124 #define D_READ_ABORT FLAC__STREAM_DECODER_READ_STATUS_ABORT |
b12c4483815e
Handles all versions of libFLAC up to version 1.0.3, now.
Ryan C. Gordon <icculus@icculus.org>
parents:
387
diff
changeset
|
125 #define D_READ_CONTINUE FLAC__STREAM_DECODER_READ_STATUS_CONTINUE |
312 | 126 |
127 #define d_error_status_string FLAC__StreamDecoderErrorStatusString | |
128 | |
393
b12c4483815e
Handles all versions of libFLAC up to version 1.0.3, now.
Ryan C. Gordon <icculus@icculus.org>
parents:
387
diff
changeset
|
129 typedef FLAC__StreamDecoderErrorStatus d_error_status_t; |
b12c4483815e
Handles all versions of libFLAC up to version 1.0.3, now.
Ryan C. Gordon <icculus@icculus.org>
parents:
387
diff
changeset
|
130 typedef FLAC__StreamMetadata d_metadata_t; |
312 | 131 typedef FLAC__StreamDecoderWriteStatus d_write_status_t; |
132 | |
155 | 133 |
134 static int FLAC_init(void); | |
135 static void FLAC_quit(void); | |
136 static int FLAC_open(Sound_Sample *sample, const char *ext); | |
137 static void FLAC_close(Sound_Sample *sample); | |
138 static Uint32 FLAC_read(Sound_Sample *sample); | |
221
c9772a9f5271
Initial implementation or stubs for rewind method. Other cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
184
diff
changeset
|
139 static int FLAC_rewind(Sound_Sample *sample); |
306
c97be6e1bd27
Added framework for Sound_Seek() support.
Ryan C. Gordon <icculus@icculus.org>
parents:
231
diff
changeset
|
140 static int FLAC_seek(Sound_Sample *sample, Uint32 ms); |
155 | 141 |
142 static const char *extensions_flac[] = { "FLAC", "FLA", NULL }; | |
143 | |
144 const Sound_DecoderFunctions __Sound_DecoderFunctions_FLAC = | |
145 { | |
146 { | |
147 extensions_flac, | |
148 "Free Lossless Audio Codec", | |
536
8a814bbbedfa
Merged r544:545 from branches/stable-1.0: converted to UTF-8 encoding.
Ryan C. Gordon <icculus@icculus.org>
parents:
516
diff
changeset
|
149 "Torbjörn Andersson <d91tan@Update.UU.SE>", |
155 | 150 "http://flac.sourceforge.net/" |
151 }, | |
152 | |
221
c9772a9f5271
Initial implementation or stubs for rewind method. Other cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
184
diff
changeset
|
153 FLAC_init, /* init() method */ |
c9772a9f5271
Initial implementation or stubs for rewind method. Other cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
184
diff
changeset
|
154 FLAC_quit, /* quit() method */ |
c9772a9f5271
Initial implementation or stubs for rewind method. Other cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
184
diff
changeset
|
155 FLAC_open, /* open() method */ |
c9772a9f5271
Initial implementation or stubs for rewind method. Other cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
184
diff
changeset
|
156 FLAC_close, /* close() method */ |
c9772a9f5271
Initial implementation or stubs for rewind method. Other cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
184
diff
changeset
|
157 FLAC_read, /* read() method */ |
306
c97be6e1bd27
Added framework for Sound_Seek() support.
Ryan C. Gordon <icculus@icculus.org>
parents:
231
diff
changeset
|
158 FLAC_rewind, /* rewind() method */ |
c97be6e1bd27
Added framework for Sound_Seek() support.
Ryan C. Gordon <icculus@icculus.org>
parents:
231
diff
changeset
|
159 FLAC_seek /* seek() method */ |
155 | 160 }; |
161 | |
162 /* This is what we store in our internal->decoder_private field. */ | |
163 typedef struct | |
164 { | |
312 | 165 decoder_t *decoder; |
155 | 166 SDL_RWops *rw; |
167 Sound_Sample *sample; | |
168 Uint32 frame_size; | |
166
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
169 Uint8 is_flac; |
312 | 170 Uint32 stream_length; |
155 | 171 } flac_t; |
172 | |
173 | |
166
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
174 static void free_flac(flac_t *f) |
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
175 { |
312 | 176 d_finish(f->decoder); |
177 d_delete(f->decoder); | |
166
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
178 free(f); |
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
179 } /* free_flac */ |
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
180 |
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
181 |
516
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
182 #ifdef LEGACY_FLAC |
312 | 183 static d_read_status_t read_callback( |
184 const decoder_t *decoder, FLAC__byte buffer[], | |
155 | 185 unsigned int *bytes, void *client_data) |
516
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
186 #else |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
187 static d_read_status_t read_callback( |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
188 const decoder_t *decoder, FLAC__byte buffer[], |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
189 size_t *bytes, void *client_data) |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
190 #endif |
155 | 191 { |
192 flac_t *f = (flac_t *) client_data; | |
193 Uint32 retval; | |
194 | |
195 retval = SDL_RWread(f->rw, (Uint8 *) buffer, 1, *bytes); | |
196 | |
197 if (retval == 0) | |
198 { | |
199 *bytes = 0; | |
200 f->sample->flags |= SOUND_SAMPLEFLAG_EOF; | |
312 | 201 return(D_READ_END_OF_STREAM); |
155 | 202 } /* if */ |
203 | |
204 if (retval == -1) | |
205 { | |
206 *bytes = 0; | |
207 f->sample->flags |= SOUND_SAMPLEFLAG_ERROR; | |
312 | 208 return(D_READ_ABORT); |
155 | 209 } /* if */ |
210 | |
211 if (retval < *bytes) | |
212 { | |
213 *bytes = retval; | |
214 f->sample->flags |= SOUND_SAMPLEFLAG_EAGAIN; | |
215 } /* if */ | |
216 | |
312 | 217 return(D_READ_CONTINUE); |
218 } /* read_callback */ | |
155 | 219 |
220 | |
312 | 221 static d_write_status_t write_callback( |
222 const decoder_t *decoder, const FLAC__Frame *frame, | |
393
b12c4483815e
Handles all versions of libFLAC up to version 1.0.3, now.
Ryan C. Gordon <icculus@icculus.org>
parents:
387
diff
changeset
|
223 const FLAC__int32 * const buffer[], |
b12c4483815e
Handles all versions of libFLAC up to version 1.0.3, now.
Ryan C. Gordon <icculus@icculus.org>
parents:
387
diff
changeset
|
224 void *client_data) |
155 | 225 { |
226 flac_t *f = (flac_t *) client_data; | |
227 Uint32 i, j; | |
166
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
228 Uint32 sample; |
155 | 229 Uint8 *dst; |
230 | |
231 f->frame_size = frame->header.channels * frame->header.blocksize | |
232 * frame->header.bits_per_sample / 8; | |
233 | |
234 if (f->frame_size > f->sample->buffer_size) | |
235 Sound_SetBufferSize(f->sample, f->frame_size); | |
236 | |
237 dst = f->sample->buffer; | |
238 | |
166
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
239 /* If the sample is neither exactly 8-bit nor 16-bit, it will have to |
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
240 * be converted. Unfortunately the buffer is read-only, so we either |
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
241 * have to check for each sample, or make a copy of the buffer. I'm |
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
242 * not sure which way is best, so I've arbitrarily picked the former. |
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
243 */ |
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
244 if (f->sample->actual.format == AUDIO_S8) |
155 | 245 { |
246 for (i = 0; i < frame->header.blocksize; i++) | |
247 for (j = 0; j < frame->header.channels; j++) | |
166
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
248 { |
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
249 sample = buffer[j][i]; |
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
250 if (frame->header.bits_per_sample < 8) |
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
251 sample <<= (8 - frame->header.bits_per_sample); |
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
252 *dst++ = sample & 0x00ff; |
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
253 } /* for */ |
155 | 254 } /* if */ |
255 else | |
256 { | |
257 for (i = 0; i < frame->header.blocksize; i++) | |
258 for (j = 0; j < frame->header.channels; j++) | |
259 { | |
166
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
260 sample = buffer[j][i]; |
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
261 if (frame->header.bits_per_sample < 16) |
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
262 sample <<= (16 - frame->header.bits_per_sample); |
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
263 else if (frame->header.bits_per_sample > 16) |
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
264 sample >>= (frame->header.bits_per_sample - 16); |
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
265 *dst++ = (sample & 0xff00) >> 8; |
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
266 *dst++ = sample & 0x00ff; |
155 | 267 } /* for */ |
268 } /* else */ | |
269 | |
312 | 270 return(D_WRITE_CONTINUE); |
271 } /* write_callback */ | |
155 | 272 |
273 | |
312 | 274 static void metadata_callback( |
275 const decoder_t *decoder, | |
276 const d_metadata_t *metadata, | |
155 | 277 void *client_data) |
278 { | |
279 flac_t *f = (flac_t *) client_data; | |
477
3e705c9180e5
Fixed binary compatibility, added Sound_GetDuration().
Ryan C. Gordon <icculus@icculus.org>
parents:
474
diff
changeset
|
280 Sound_Sample *sample = f->sample; |
3e705c9180e5
Fixed binary compatibility, added Sound_GetDuration().
Ryan C. Gordon <icculus@icculus.org>
parents:
474
diff
changeset
|
281 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; |
312 | 282 |
155 | 283 SNDDBG(("FLAC: Metadata callback.\n")); |
284 | |
166
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
285 /* There are several kinds of metadata, but STREAMINFO is the only |
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
286 * one that always has to be there. |
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
287 */ |
155 | 288 if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO) |
289 { | |
290 SNDDBG(("FLAC: Metadata is streaminfo.\n")); | |
166
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
291 |
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
292 f->is_flac = 1; |
477
3e705c9180e5
Fixed binary compatibility, added Sound_GetDuration().
Ryan C. Gordon <icculus@icculus.org>
parents:
474
diff
changeset
|
293 sample->actual.channels = metadata->data.stream_info.channels; |
3e705c9180e5
Fixed binary compatibility, added Sound_GetDuration().
Ryan C. Gordon <icculus@icculus.org>
parents:
474
diff
changeset
|
294 sample->actual.rate = metadata->data.stream_info.sample_rate; |
155 | 295 |
477
3e705c9180e5
Fixed binary compatibility, added Sound_GetDuration().
Ryan C. Gordon <icculus@icculus.org>
parents:
474
diff
changeset
|
296 if (metadata->data.stream_info.sample_rate == 0 || |
474
c66080364dff
Most decoders now report total sample play time, now. Technically, this
Ryan C. Gordon <icculus@icculus.org>
parents:
443
diff
changeset
|
297 metadata->data.stream_info.total_samples == 0) |
477
3e705c9180e5
Fixed binary compatibility, added Sound_GetDuration().
Ryan C. Gordon <icculus@icculus.org>
parents:
474
diff
changeset
|
298 { |
3e705c9180e5
Fixed binary compatibility, added Sound_GetDuration().
Ryan C. Gordon <icculus@icculus.org>
parents:
474
diff
changeset
|
299 internal->total_time = -1; |
3e705c9180e5
Fixed binary compatibility, added Sound_GetDuration().
Ryan C. Gordon <icculus@icculus.org>
parents:
474
diff
changeset
|
300 } /* if */ |
3e705c9180e5
Fixed binary compatibility, added Sound_GetDuration().
Ryan C. Gordon <icculus@icculus.org>
parents:
474
diff
changeset
|
301 else |
3e705c9180e5
Fixed binary compatibility, added Sound_GetDuration().
Ryan C. Gordon <icculus@icculus.org>
parents:
474
diff
changeset
|
302 { |
3e705c9180e5
Fixed binary compatibility, added Sound_GetDuration().
Ryan C. Gordon <icculus@icculus.org>
parents:
474
diff
changeset
|
303 internal->total_time = (metadata->data.stream_info.total_samples) |
474
c66080364dff
Most decoders now report total sample play time, now. Technically, this
Ryan C. Gordon <icculus@icculus.org>
parents:
443
diff
changeset
|
304 / metadata->data.stream_info.sample_rate * 1000; |
477
3e705c9180e5
Fixed binary compatibility, added Sound_GetDuration().
Ryan C. Gordon <icculus@icculus.org>
parents:
474
diff
changeset
|
305 internal->total_time += (metadata->data.stream_info.total_samples |
474
c66080364dff
Most decoders now report total sample play time, now. Technically, this
Ryan C. Gordon <icculus@icculus.org>
parents:
443
diff
changeset
|
306 % metadata->data.stream_info.sample_rate) * 1000 |
c66080364dff
Most decoders now report total sample play time, now. Technically, this
Ryan C. Gordon <icculus@icculus.org>
parents:
443
diff
changeset
|
307 / metadata->data.stream_info.sample_rate; |
477
3e705c9180e5
Fixed binary compatibility, added Sound_GetDuration().
Ryan C. Gordon <icculus@icculus.org>
parents:
474
diff
changeset
|
308 } /* else */ |
474
c66080364dff
Most decoders now report total sample play time, now. Technically, this
Ryan C. Gordon <icculus@icculus.org>
parents:
443
diff
changeset
|
309 |
166
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
310 if (metadata->data.stream_info.bits_per_sample > 8) |
477
3e705c9180e5
Fixed binary compatibility, added Sound_GetDuration().
Ryan C. Gordon <icculus@icculus.org>
parents:
474
diff
changeset
|
311 sample->actual.format = AUDIO_S16MSB; |
166
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
312 else |
477
3e705c9180e5
Fixed binary compatibility, added Sound_GetDuration().
Ryan C. Gordon <icculus@icculus.org>
parents:
474
diff
changeset
|
313 sample->actual.format = AUDIO_S8; |
155 | 314 } /* if */ |
312 | 315 } /* metadata_callback */ |
155 | 316 |
317 | |
312 | 318 static void error_callback( |
319 const decoder_t *decoder, | |
320 d_error_status_t status, | |
155 | 321 void *client_data) |
322 { | |
323 flac_t *f = (flac_t *) client_data; | |
164
77482005beb6
Now includes FLAC/stream_decoder.h instead of FLAC/all.h. More robust
Ryan C. Gordon <icculus@icculus.org>
parents:
155
diff
changeset
|
324 |
387
fb519e6028e3
Changed all the Sound_SetError() calls to __Sound_SetError (or BAIL*_MACRO)
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
325 __Sound_SetError(d_error_status_string[status]); |
155 | 326 f->sample->flags |= SOUND_SAMPLEFLAG_ERROR; |
312 | 327 } /* error_callback */ |
328 | |
329 | |
330 static d_seek_status_t seek_callback( | |
331 const decoder_t *decoder, | |
332 FLAC__uint64 absolute_byte_offset, | |
333 void *client_data) | |
334 { | |
335 flac_t *f = (flac_t *) client_data; | |
336 | |
337 if (SDL_RWseek(f->rw, absolute_byte_offset, SEEK_SET) >= 0) | |
338 { | |
339 return(D_SEEK_STATUS_OK); | |
340 } /* if */ | |
341 | |
342 return(D_SEEK_STATUS_ERROR); | |
343 } /* seek_callback*/ | |
344 | |
345 | |
346 static d_tell_status_t tell_callback( | |
347 const decoder_t *decoder, | |
348 FLAC__uint64 *absolute_byte_offset, | |
349 void *client_data) | |
350 { | |
351 flac_t *f = (flac_t *) client_data; | |
400 | 352 int pos; |
312 | 353 |
354 pos = SDL_RWtell(f->rw); | |
355 | |
356 if (pos < 0) | |
357 { | |
358 return(D_TELL_STATUS_ERROR); | |
359 } /* if */ | |
155 | 360 |
312 | 361 *absolute_byte_offset = pos; |
362 return(D_TELL_STATUS_OK); | |
363 } /* tell_callback */ | |
364 | |
365 | |
366 static d_length_status_t length_callback( | |
367 const decoder_t *decoder, | |
368 FLAC__uint64 *stream_length, | |
369 void *client_data) | |
370 { | |
371 flac_t *f = (flac_t *) client_data; | |
372 | |
373 if (f->sample->flags & SOUND_SAMPLEFLAG_CANSEEK) | |
374 { | |
375 *stream_length = f->stream_length; | |
376 return(D_LENGTH_STATUS_OK); | |
377 } /* if */ | |
378 | |
379 return(D_LENGTH_STATUS_ERROR); | |
380 } /* length_callback */ | |
381 | |
382 | |
383 static FLAC__bool eof_callback( | |
384 const decoder_t *decoder, | |
385 void *client_data) | |
386 { | |
387 flac_t *f = (flac_t *) client_data; | |
400 | 388 int pos; |
312 | 389 |
390 /* Maybe we could check for SOUND_SAMPLEFLAG_EOF here instead? */ | |
391 pos = SDL_RWtell(f->rw); | |
392 | |
393 if (pos >= 0 && pos >= f->stream_length) | |
394 { | |
395 return(true); | |
396 } /* if */ | |
397 | |
398 return(false); | |
399 } /* eof_callback */ | |
400 | |
155 | 401 |
402 static int FLAC_init(void) | |
403 { | |
404 return(1); /* always succeeds. */ | |
405 } /* FLAC_init */ | |
406 | |
407 | |
408 static void FLAC_quit(void) | |
409 { | |
410 /* it's a no-op. */ | |
411 } /* FLAC_quit */ | |
412 | |
413 | |
182
3849438b735e
Checks magic number again, unless the file extension is recognized.
Ryan C. Gordon <icculus@icculus.org>
parents:
166
diff
changeset
|
414 #define FLAC_MAGIC 0x43614C66 /* "fLaC" in ASCII. */ |
3849438b735e
Checks magic number again, unless the file extension is recognized.
Ryan C. Gordon <icculus@icculus.org>
parents:
166
diff
changeset
|
415 |
155 | 416 static int FLAC_open(Sound_Sample *sample, const char *ext) |
417 { | |
418 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; | |
419 SDL_RWops *rw = internal->rw; | |
312 | 420 decoder_t *decoder; |
155 | 421 flac_t *f; |
166
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
422 int i; |
182
3849438b735e
Checks magic number again, unless the file extension is recognized.
Ryan C. Gordon <icculus@icculus.org>
parents:
166
diff
changeset
|
423 int has_extension = 0; |
312 | 424 Uint32 pos; |
182
3849438b735e
Checks magic number again, unless the file extension is recognized.
Ryan C. Gordon <icculus@icculus.org>
parents:
166
diff
changeset
|
425 |
3849438b735e
Checks magic number again, unless the file extension is recognized.
Ryan C. Gordon <icculus@icculus.org>
parents:
166
diff
changeset
|
426 /* |
3849438b735e
Checks magic number again, unless the file extension is recognized.
Ryan C. Gordon <icculus@icculus.org>
parents:
166
diff
changeset
|
427 * If the extension is "flac", we'll believe that this is really meant |
3849438b735e
Checks magic number again, unless the file extension is recognized.
Ryan C. Gordon <icculus@icculus.org>
parents:
166
diff
changeset
|
428 * to be a FLAC stream, and will try to grok it from existing metadata. |
3849438b735e
Checks magic number again, unless the file extension is recognized.
Ryan C. Gordon <icculus@icculus.org>
parents:
166
diff
changeset
|
429 * metadata searching can be a very expensive operation, however, so |
3849438b735e
Checks magic number again, unless the file extension is recognized.
Ryan C. Gordon <icculus@icculus.org>
parents:
166
diff
changeset
|
430 * unless the user swears that it is a FLAC stream through the extension, |
3849438b735e
Checks magic number again, unless the file extension is recognized.
Ryan C. Gordon <icculus@icculus.org>
parents:
166
diff
changeset
|
431 * we decide what to do based on the existance of a 32-bit magic number. |
3849438b735e
Checks magic number again, unless the file extension is recognized.
Ryan C. Gordon <icculus@icculus.org>
parents:
166
diff
changeset
|
432 */ |
3849438b735e
Checks magic number again, unless the file extension is recognized.
Ryan C. Gordon <icculus@icculus.org>
parents:
166
diff
changeset
|
433 for (i = 0; extensions_flac[i] != NULL; i++) |
3849438b735e
Checks magic number again, unless the file extension is recognized.
Ryan C. Gordon <icculus@icculus.org>
parents:
166
diff
changeset
|
434 { |
3849438b735e
Checks magic number again, unless the file extension is recognized.
Ryan C. Gordon <icculus@icculus.org>
parents:
166
diff
changeset
|
435 if (__Sound_strcasecmp(ext, extensions_flac[i]) == 0) |
3849438b735e
Checks magic number again, unless the file extension is recognized.
Ryan C. Gordon <icculus@icculus.org>
parents:
166
diff
changeset
|
436 { |
3849438b735e
Checks magic number again, unless the file extension is recognized.
Ryan C. Gordon <icculus@icculus.org>
parents:
166
diff
changeset
|
437 has_extension = 1; |
3849438b735e
Checks magic number again, unless the file extension is recognized.
Ryan C. Gordon <icculus@icculus.org>
parents:
166
diff
changeset
|
438 break; |
3849438b735e
Checks magic number again, unless the file extension is recognized.
Ryan C. Gordon <icculus@icculus.org>
parents:
166
diff
changeset
|
439 } /* if */ |
3849438b735e
Checks magic number again, unless the file extension is recognized.
Ryan C. Gordon <icculus@icculus.org>
parents:
166
diff
changeset
|
440 } /* for */ |
3849438b735e
Checks magic number again, unless the file extension is recognized.
Ryan C. Gordon <icculus@icculus.org>
parents:
166
diff
changeset
|
441 |
3849438b735e
Checks magic number again, unless the file extension is recognized.
Ryan C. Gordon <icculus@icculus.org>
parents:
166
diff
changeset
|
442 if (!has_extension) |
3849438b735e
Checks magic number again, unless the file extension is recognized.
Ryan C. Gordon <icculus@icculus.org>
parents:
166
diff
changeset
|
443 { |
3849438b735e
Checks magic number again, unless the file extension is recognized.
Ryan C. Gordon <icculus@icculus.org>
parents:
166
diff
changeset
|
444 int rc; |
3849438b735e
Checks magic number again, unless the file extension is recognized.
Ryan C. Gordon <icculus@icculus.org>
parents:
166
diff
changeset
|
445 Uint32 flac_magic = SDL_ReadLE32(rw); |
3849438b735e
Checks magic number again, unless the file extension is recognized.
Ryan C. Gordon <icculus@icculus.org>
parents:
166
diff
changeset
|
446 BAIL_IF_MACRO(flac_magic != FLAC_MAGIC, "FLAC: Not a FLAC stream.", 0); |
3849438b735e
Checks magic number again, unless the file extension is recognized.
Ryan C. Gordon <icculus@icculus.org>
parents:
166
diff
changeset
|
447 |
3849438b735e
Checks magic number again, unless the file extension is recognized.
Ryan C. Gordon <icculus@icculus.org>
parents:
166
diff
changeset
|
448 /* move back over magic number for metadata scan... */ |
3849438b735e
Checks magic number again, unless the file extension is recognized.
Ryan C. Gordon <icculus@icculus.org>
parents:
166
diff
changeset
|
449 rc = SDL_RWseek(internal->rw, -sizeof (flac_magic), SEEK_CUR); |
3849438b735e
Checks magic number again, unless the file extension is recognized.
Ryan C. Gordon <icculus@icculus.org>
parents:
166
diff
changeset
|
450 BAIL_IF_MACRO(rc < 0, ERR_IO_ERROR, 0); |
3849438b735e
Checks magic number again, unless the file extension is recognized.
Ryan C. Gordon <icculus@icculus.org>
parents:
166
diff
changeset
|
451 } /* if */ |
155 | 452 |
453 f = (flac_t *) malloc(sizeof (flac_t)); | |
454 BAIL_IF_MACRO(f == NULL, ERR_OUT_OF_MEMORY, 0); | |
455 | |
312 | 456 decoder = d_new(); |
155 | 457 if (decoder == NULL) |
458 { | |
459 free(f); | |
387
fb519e6028e3
Changed all the Sound_SetError() calls to __Sound_SetError (or BAIL*_MACRO)
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
460 BAIL_MACRO(ERR_OUT_OF_MEMORY, 0); |
155 | 461 } /* if */ |
462 | |
516
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
463 #ifdef LEGACY_FLAC |
312 | 464 d_set_read_callback(decoder, read_callback); |
465 d_set_write_callback(decoder, write_callback); | |
466 d_set_metadata_callback(decoder, metadata_callback); | |
467 d_set_error_callback(decoder, error_callback); | |
468 d_set_seek_callback(decoder, seek_callback); | |
469 d_set_tell_callback(decoder, tell_callback); | |
470 d_set_length_callback(decoder, length_callback); | |
471 d_set_eof_callback(decoder, eof_callback); | |
422
5b06e23d934e
Removed backwards compatible API nastiness from FLAC decoder.
Ryan C. Gordon <icculus@icculus.org>
parents:
400
diff
changeset
|
472 |
312 | 473 d_set_client_data(decoder, f); |
516
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
474 #endif |
155 | 475 |
476 f->rw = internal->rw; | |
477 f->sample = sample; | |
478 f->decoder = decoder; | |
164
77482005beb6
Now includes FLAC/stream_decoder.h instead of FLAC/all.h. More robust
Ryan C. Gordon <icculus@icculus.org>
parents:
155
diff
changeset
|
479 f->sample->actual.format = 0; |
182
3849438b735e
Checks magic number again, unless the file extension is recognized.
Ryan C. Gordon <icculus@icculus.org>
parents:
166
diff
changeset
|
480 f->is_flac = 0 /* !!! FIXME: should be "has_extension", not "0". */; |
166
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
481 |
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
482 internal->decoder_private = f; |
516
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
483 /* really should check the init return value here: */ |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
484 #ifdef LEGACY_FLAC |
312 | 485 d_init(decoder); |
516
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
486 #else |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
487 FLAC__stream_decoder_init_stream(decoder, read_callback, seek_callback, |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
488 tell_callback, length_callback, |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
489 eof_callback, write_callback, |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
490 metadata_callback, error_callback, f); |
46d5f399cb35
Patch from stable-1.0 branch r528:529.
Ryan C. Gordon <icculus@icculus.org>
parents:
477
diff
changeset
|
491 #endif |
166
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
492 |
400 | 493 sample->flags = SOUND_SAMPLEFLAG_NONE; |
494 | |
495 pos = SDL_RWtell(f->rw); | |
496 if (SDL_RWseek(f->rw, 0, SEEK_END) > 0) | |
497 { | |
498 f->stream_length = SDL_RWtell(f->rw); | |
499 if (SDL_RWseek(f->rw, pos, SEEK_SET) == -1) | |
500 { | |
501 free_flac(f); | |
502 BAIL_MACRO(ERR_IO_ERROR, 0); | |
503 } /* if */ | |
504 sample->flags = SOUND_SAMPLEFLAG_CANSEEK; | |
505 } /* if */ | |
506 | |
231
d3dc34315ac7
Rewind method implemented by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
221
diff
changeset
|
507 /* |
182
3849438b735e
Checks magic number again, unless the file extension is recognized.
Ryan C. Gordon <icculus@icculus.org>
parents:
166
diff
changeset
|
508 * If we are not sure this is a FLAC stream, check for the STREAMINFO |
166
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
509 * metadata block. If not, we'd have to peek at the first audio frame |
182
3849438b735e
Checks magic number again, unless the file extension is recognized.
Ryan C. Gordon <icculus@icculus.org>
parents:
166
diff
changeset
|
510 * and get the sound format from there, but that is not yet |
3849438b735e
Checks magic number again, unless the file extension is recognized.
Ryan C. Gordon <icculus@icculus.org>
parents:
166
diff
changeset
|
511 * implemented. |
166
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
512 */ |
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
513 if (!f->is_flac) |
155 | 514 { |
312 | 515 d_process_metadata(decoder); |
166
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
516 |
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
517 /* Still not FLAC? Give up. */ |
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
518 if (!f->is_flac) |
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
519 { |
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
520 free_flac(f); |
387
fb519e6028e3
Changed all the Sound_SetError() calls to __Sound_SetError (or BAIL*_MACRO)
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
521 BAIL_MACRO("FLAC: No metadata found. Not a FLAC stream?", 0); |
166
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
522 } /* if */ |
155 | 523 } /* if */ |
524 | |
164
77482005beb6
Now includes FLAC/stream_decoder.h instead of FLAC/all.h. More robust
Ryan C. Gordon <icculus@icculus.org>
parents:
155
diff
changeset
|
525 SNDDBG(("FLAC: Accepting data stream.\n")); |
155 | 526 return(1); |
527 } /* FLAC_open */ | |
528 | |
529 | |
530 static void FLAC_close(Sound_Sample *sample) | |
531 { | |
532 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; | |
533 flac_t *f = (flac_t *) internal->decoder_private; | |
534 | |
166
d8904267d23c
Cleanups, fixes and enhancements by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
164
diff
changeset
|
535 free_flac(f); |
155 | 536 } /* FLAC_close */ |
537 | |
538 | |
539 static Uint32 FLAC_read(Sound_Sample *sample) | |
540 { | |
541 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; | |
542 flac_t *f = (flac_t *) internal->decoder_private; | |
543 Uint32 len; | |
544 | |
312 | 545 if (!d_process_one_frame(f->decoder)) |
155 | 546 { |
547 sample->flags |= SOUND_SAMPLEFLAG_ERROR; | |
387
fb519e6028e3
Changed all the Sound_SetError() calls to __Sound_SetError (or BAIL*_MACRO)
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
548 BAIL_MACRO("FLAC: Couldn't decode frame.", 0); |
155 | 549 } /* if */ |
550 | |
312 | 551 if (d_get_state(f->decoder) == D_END_OF_STREAM) |
231
d3dc34315ac7
Rewind method implemented by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
221
diff
changeset
|
552 { |
d3dc34315ac7
Rewind method implemented by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
221
diff
changeset
|
553 sample->flags |= SOUND_SAMPLEFLAG_EOF; |
d3dc34315ac7
Rewind method implemented by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
221
diff
changeset
|
554 return(0); |
d3dc34315ac7
Rewind method implemented by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
221
diff
changeset
|
555 } /* if */ |
d3dc34315ac7
Rewind method implemented by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
221
diff
changeset
|
556 |
164
77482005beb6
Now includes FLAC/stream_decoder.h instead of FLAC/all.h. More robust
Ryan C. Gordon <icculus@icculus.org>
parents:
155
diff
changeset
|
557 /* An error may have been signalled through the error callback. */ |
77482005beb6
Now includes FLAC/stream_decoder.h instead of FLAC/all.h. More robust
Ryan C. Gordon <icculus@icculus.org>
parents:
155
diff
changeset
|
558 if (sample->flags & SOUND_SAMPLEFLAG_ERROR) |
77482005beb6
Now includes FLAC/stream_decoder.h instead of FLAC/all.h. More robust
Ryan C. Gordon <icculus@icculus.org>
parents:
155
diff
changeset
|
559 return(0); |
231
d3dc34315ac7
Rewind method implemented by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
221
diff
changeset
|
560 |
155 | 561 return(f->frame_size); |
562 } /* FLAC_read */ | |
563 | |
221
c9772a9f5271
Initial implementation or stubs for rewind method. Other cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
184
diff
changeset
|
564 |
c9772a9f5271
Initial implementation or stubs for rewind method. Other cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
184
diff
changeset
|
565 static int FLAC_rewind(Sound_Sample *sample) |
c9772a9f5271
Initial implementation or stubs for rewind method. Other cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
184
diff
changeset
|
566 { |
312 | 567 return FLAC_seek(sample, 0); |
221
c9772a9f5271
Initial implementation or stubs for rewind method. Other cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
184
diff
changeset
|
568 } /* FLAC_rewind */ |
c9772a9f5271
Initial implementation or stubs for rewind method. Other cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
184
diff
changeset
|
569 |
306
c97be6e1bd27
Added framework for Sound_Seek() support.
Ryan C. Gordon <icculus@icculus.org>
parents:
231
diff
changeset
|
570 |
c97be6e1bd27
Added framework for Sound_Seek() support.
Ryan C. Gordon <icculus@icculus.org>
parents:
231
diff
changeset
|
571 static int FLAC_seek(Sound_Sample *sample, Uint32 ms) |
c97be6e1bd27
Added framework for Sound_Seek() support.
Ryan C. Gordon <icculus@icculus.org>
parents:
231
diff
changeset
|
572 { |
312 | 573 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; |
574 flac_t *f = (flac_t *) internal->decoder_private; | |
575 | |
576 d_seek_absolute(f->decoder, (ms * sample->actual.rate) / 1000); | |
577 return(1); | |
306
c97be6e1bd27
Added framework for Sound_Seek() support.
Ryan C. Gordon <icculus@icculus.org>
parents:
231
diff
changeset
|
578 } /* FLAC_seek */ |
c97be6e1bd27
Added framework for Sound_Seek() support.
Ryan C. Gordon <icculus@icculus.org>
parents:
231
diff
changeset
|
579 |
155 | 580 #endif /* SOUND_SUPPORTS_FLAC */ |
581 | |
582 /* end of flac.c ... */ |