2 * ALURE OpenAL utility library
3 * Copyright (c) 2009-2010 by Chris Robinson.
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to
7 * deal in the Software without restriction, including without limitation the
8 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9 * sell copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
37 #define FLAC_LIB "libFLAC.dll"
38 #elif defined(__APPLE__)
39 #define FLAC_LIB "libFLAC.8.dylib"
41 #define FLAC_LIB "libFLAC.so.8"
44 static void *flac_handle
;
45 #define MAKE_FUNC(x) static typeof(x)* p##x
46 MAKE_FUNC(FLAC__stream_decoder_get_state
);
47 MAKE_FUNC(FLAC__stream_decoder_finish
);
48 MAKE_FUNC(FLAC__stream_decoder_new
);
49 MAKE_FUNC(FLAC__stream_decoder_seek_absolute
);
50 MAKE_FUNC(FLAC__stream_decoder_delete
);
51 MAKE_FUNC(FLAC__stream_decoder_process_single
);
52 MAKE_FUNC(FLAC__stream_decoder_init_stream
);
56 struct flacStream
: public alureStream
{
58 FLAC__StreamDecoder
*flacFile
;
64 std::vector
<ALubyte
> initialData
;
73 flac_handle
= OpenLib(FLAC_LIB
);
74 if(!flac_handle
) return;
76 LOAD_FUNC(flac_handle
, FLAC__stream_decoder_get_state
);
77 LOAD_FUNC(flac_handle
, FLAC__stream_decoder_finish
);
78 LOAD_FUNC(flac_handle
, FLAC__stream_decoder_new
);
79 LOAD_FUNC(flac_handle
, FLAC__stream_decoder_seek_absolute
);
80 LOAD_FUNC(flac_handle
, FLAC__stream_decoder_delete
);
81 LOAD_FUNC(flac_handle
, FLAC__stream_decoder_process_single
);
82 LOAD_FUNC(flac_handle
, FLAC__stream_decoder_init_stream
);
87 CloseLib(flac_handle
);
91 virtual bool IsValid()
92 { return flacFile
!= NULL
; }
94 virtual bool GetFormat(ALenum
*fmt
, ALuint
*frequency
, ALuint
*blockalign
)
97 *frequency
= samplerate
;
98 *blockalign
= blockAlign
;
102 virtual ALuint
GetData(ALubyte
*data
, ALuint bytes
)
108 if(initialData
.size() > 0)
110 size_t rem
= std::min(initialData
.size(), (size_t)bytes
);
111 memcpy(data
, &initialData
[0], rem
);
113 initialData
.erase(initialData
.begin(), initialData
.begin()+rem
);
116 while(outTotal
< bytes
)
118 if(pFLAC__stream_decoder_process_single(flacFile
) == false ||
119 pFLAC__stream_decoder_get_state(flacFile
) == FLAC__STREAM_DECODER_END_OF_STREAM
)
126 virtual bool Rewind()
128 if(pFLAC__stream_decoder_seek_absolute(flacFile
, 0) != false)
134 SetError("Seek failed");
138 flacStream(std::istream
*_fstream
)
139 : alureStream(_fstream
), flacFile(NULL
), format(AL_NONE
), samplerate(0),
140 blockAlign(0), useFloat(AL_FALSE
)
142 if(!flac_handle
) return;
144 flacFile
= pFLAC__stream_decoder_new();
147 if(pFLAC__stream_decoder_init_stream(flacFile
, ReadCallback
, SeekCallback
, TellCallback
, LengthCallback
, EofCallback
, WriteCallback
, MetadataCallback
, ErrorCallback
, this) == FLAC__STREAM_DECODER_INIT_STATUS_OK
)
155 pFLAC__stream_decoder_finish(flacFile
);
157 pFLAC__stream_decoder_delete(flacFile
);
162 virtual ~flacStream()
166 pFLAC__stream_decoder_finish(flacFile
);
167 pFLAC__stream_decoder_delete(flacFile
);
175 // We need to decode some data to be able to get the channel count, bit
176 // depth, and sample rate. It also ensures the file has FLAC data, as
177 // the FLAC__stream_decoder_init_* functions can succeed on non-FLAC
181 while(initialData
.size() == 0)
183 if(pFLAC__stream_decoder_process_single(flacFile
) == false ||
184 pFLAC__stream_decoder_get_state(flacFile
) == FLAC__STREAM_DECODER_END_OF_STREAM
)
188 if(initialData
.size() > 0)
193 static FLAC__StreamDecoderWriteStatus
WriteCallback(const FLAC__StreamDecoder
*, const FLAC__Frame
*frame
, const FLAC__int32
*const buffer
[], void *client_data
)
195 flacStream
*self
= static_cast<flacStream
*>(client_data
);
196 ALubyte
*data
= self
->outBytes
+ self
->outTotal
;
199 if(self
->format
== AL_NONE
)
201 ALuint bps
= frame
->header
.bits_per_sample
;
202 if(bps
== 24 || bps
== 32)
204 self
->format
= GetSampleFormat(frame
->header
.channels
, 32, true);
205 if(self
->format
!= AL_NONE
)
207 self
->useFloat
= AL_TRUE
;
212 if(self
->format
== AL_NONE
)
213 self
->format
= GetSampleFormat(frame
->header
.channels
, bps
, false);
214 self
->blockAlign
= frame
->header
.channels
* bps
/8;
215 self
->samplerate
= frame
->header
.sample_rate
;
218 const ALboolean useFloat
= self
->useFloat
;
219 while(self
->outTotal
< self
->outLen
&& i
< frame
->header
.blocksize
)
221 for(ALuint c
= 0;c
< frame
->header
.channels
;c
++)
223 if(frame
->header
.bits_per_sample
== 8)
224 ((ALubyte
*)data
)[c
] = buffer
[c
][i
]+128;
225 else if(frame
->header
.bits_per_sample
== 16)
226 ((ALshort
*)data
)[c
] = buffer
[c
][i
];
227 else if(frame
->header
.bits_per_sample
== 24)
230 ((ALfloat
*)data
)[c
] = buffer
[c
][i
] * (1.0/8388607.0);
232 ((ALshort
*)data
)[c
] = buffer
[c
][i
]>>8;
234 else if(frame
->header
.bits_per_sample
== 32)
237 ((ALfloat
*)data
)[c
] = buffer
[c
][i
] * (1.0/2147483647.0);
239 ((ALshort
*)data
)[c
] = buffer
[c
][i
]>>16;
242 self
->outTotal
+= self
->blockAlign
;
243 data
+= self
->blockAlign
;
247 if(i
< frame
->header
.blocksize
)
249 ALuint blocklen
= (frame
->header
.blocksize
-i
) *
251 ALuint start
= self
->initialData
.size();
253 self
->initialData
.resize(start
+blocklen
);
254 data
= &self
->initialData
[start
];
257 for(ALuint c
= 0;c
< frame
->header
.channels
;c
++)
259 if(frame
->header
.bits_per_sample
== 8)
260 ((ALubyte
*)data
)[c
] = buffer
[c
][i
]+128;
261 else if(frame
->header
.bits_per_sample
== 16)
262 ((ALshort
*)data
)[c
] = buffer
[c
][i
];
263 else if(frame
->header
.bits_per_sample
== 24)
266 ((ALfloat
*)data
)[c
] = buffer
[c
][i
] * (1.0/8388607.0);
268 ((ALshort
*)data
)[c
] = buffer
[c
][i
]>>8;
270 else if(frame
->header
.bits_per_sample
== 32)
273 ((ALfloat
*)data
)[c
] = buffer
[c
][i
] * (1.0/2147483647.0);
275 ((ALshort
*)data
)[c
] = buffer
[c
][i
]>>16;
278 data
+= self
->blockAlign
;
280 } while(i
< frame
->header
.blocksize
);
283 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE
;
285 static void MetadataCallback(const FLAC__StreamDecoder
*,const FLAC__StreamMetadata
*,void*)
288 static void ErrorCallback(const FLAC__StreamDecoder
*,FLAC__StreamDecoderErrorStatus
,void*)
292 static FLAC__StreamDecoderReadStatus
ReadCallback(const FLAC__StreamDecoder
*, FLAC__byte buffer
[], size_t *bytes
, void *client_data
)
294 std::istream
*stream
= static_cast<flacStream
*>(client_data
)->fstream
;
298 return FLAC__STREAM_DECODER_READ_STATUS_ABORT
;
300 stream
->read(reinterpret_cast<char*>(buffer
), *bytes
);
301 *bytes
= stream
->gcount();
302 if(*bytes
== 0 && stream
->eof())
303 return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM
;
305 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE
;
307 static FLAC__StreamDecoderSeekStatus
SeekCallback(const FLAC__StreamDecoder
*, FLAC__uint64 absolute_byte_offset
, void *client_data
)
309 std::istream
*stream
= static_cast<flacStream
*>(client_data
)->fstream
;
312 if(!stream
->seekg(absolute_byte_offset
))
313 return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR
;
314 return FLAC__STREAM_DECODER_SEEK_STATUS_OK
;
316 static FLAC__StreamDecoderTellStatus
TellCallback(const FLAC__StreamDecoder
*, FLAC__uint64
*absolute_byte_offset
, void *client_data
)
318 std::istream
*stream
= static_cast<flacStream
*>(client_data
)->fstream
;
321 *absolute_byte_offset
= stream
->tellg();
322 return FLAC__STREAM_DECODER_TELL_STATUS_OK
;
324 static FLAC__StreamDecoderLengthStatus
LengthCallback(const FLAC__StreamDecoder
*, FLAC__uint64
*stream_length
, void *client_data
)
326 std::istream
*stream
= static_cast<flacStream
*>(client_data
)->fstream
;
329 std::streampos pos
= stream
->tellg();
330 if(stream
->seekg(0, std::ios_base::end
))
332 *stream_length
= stream
->tellg();
337 return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR
;
338 return FLAC__STREAM_DECODER_LENGTH_STATUS_OK
;
340 static FLAC__bool
EofCallback(const FLAC__StreamDecoder
*, void *client_data
)
342 std::istream
*stream
= static_cast<flacStream
*>(client_data
)->fstream
;
343 return (stream
->eof()) ? true : false;
346 // Priority = 1, so it's preferred over libsndfile
347 static DecoderDecl
<flacStream
,1> flacStream_decoder
;