Update spec for changing license to MIT
[platform/upstream/alure.git] / src / codec_flac.cpp
1 /*
2  * ALURE  OpenAL utility library
3  * Copyright (c) 2009-2010 by Chris Robinson.
4  *
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:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
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
21  * IN THE SOFTWARE.
22  */
23
24 #include "config.h"
25
26 #include "main.h"
27
28 #include <string.h>
29 #include <assert.h>
30
31 #include <istream>
32
33 #include <FLAC/all.h>
34
35
36 #ifdef DYNLOAD
37 static void *flac_handle;
38 #define MAKE_FUNC(x) static typeof(x)* p##x
39 MAKE_FUNC(FLAC__stream_decoder_get_state);
40 MAKE_FUNC(FLAC__stream_decoder_finish);
41 MAKE_FUNC(FLAC__stream_decoder_new);
42 MAKE_FUNC(FLAC__stream_decoder_seek_absolute);
43 MAKE_FUNC(FLAC__stream_decoder_delete);
44 MAKE_FUNC(FLAC__stream_decoder_get_total_samples);
45 MAKE_FUNC(FLAC__stream_decoder_process_single);
46 MAKE_FUNC(FLAC__stream_decoder_init_stream);
47 #undef MAKE_FUNC
48
49 #define FLAC__stream_decoder_get_state pFLAC__stream_decoder_get_state
50 #define FLAC__stream_decoder_finish pFLAC__stream_decoder_finish
51 #define FLAC__stream_decoder_new pFLAC__stream_decoder_new
52 #define FLAC__stream_decoder_seek_absolute pFLAC__stream_decoder_seek_absolute
53 #define FLAC__stream_decoder_delete pFLAC__stream_decoder_delete
54 #define FLAC__stream_decoder_get_total_samples pFLAC__stream_decoder_get_total_samples
55 #define FLAC__stream_decoder_process_single pFLAC__stream_decoder_process_single
56 #define FLAC__stream_decoder_init_stream pFLAC__stream_decoder_init_stream
57 #else
58 #define flac_handle 1
59 #endif
60
61
62 struct flacStream : public alureStream {
63 private:
64     FLAC__StreamDecoder *flacFile;
65     ALenum format;
66     ALuint samplerate;
67     ALuint blockAlign;
68     ALboolean useFloat;
69
70     std::vector<ALubyte> initialData;
71
72     ALubyte *outBytes;
73     ALuint outMax;
74     ALuint outLen;
75
76 public:
77 #ifdef DYNLOAD
78     static void Init()
79     {
80 #ifdef _WIN32
81 #define FLAC_LIB "libFLAC.dll"
82 #elif defined(__APPLE__)
83 #define FLAC_LIB "libFLAC.8.dylib"
84 #else
85 #define FLAC_LIB "libFLAC.so.8"
86 #endif
87
88         flac_handle = OpenLib(FLAC_LIB);
89         if(!flac_handle) return;
90
91         LOAD_FUNC(flac_handle, FLAC__stream_decoder_get_state);
92         LOAD_FUNC(flac_handle, FLAC__stream_decoder_finish);
93         LOAD_FUNC(flac_handle, FLAC__stream_decoder_new);
94         LOAD_FUNC(flac_handle, FLAC__stream_decoder_seek_absolute);
95         LOAD_FUNC(flac_handle, FLAC__stream_decoder_delete);
96         LOAD_FUNC(flac_handle, FLAC__stream_decoder_get_total_samples);
97         LOAD_FUNC(flac_handle, FLAC__stream_decoder_process_single);
98         LOAD_FUNC(flac_handle, FLAC__stream_decoder_init_stream);
99     }
100     static void Deinit()
101     {
102         if(flac_handle)
103             CloseLib(flac_handle);
104         flac_handle = NULL;
105     }
106 #else
107     static void Init() { }
108     static void Deinit() { }
109 #endif
110
111     virtual bool IsValid()
112     { return flacFile != NULL; }
113
114     virtual bool GetFormat(ALenum *fmt, ALuint *frequency, ALuint *blockalign)
115     {
116         *fmt = format;
117         *frequency = samplerate;
118         *blockalign = blockAlign;
119         return true;
120     }
121
122     virtual ALuint GetData(ALubyte *data, ALuint bytes)
123     {
124         outBytes = data;
125         outLen = 0;
126         outMax = bytes;
127
128         if(initialData.size() > 0)
129         {
130             size_t rem = std::min(initialData.size(), (size_t)bytes);
131             memcpy(data, &initialData[0], rem);
132             outLen += rem;
133             initialData.erase(initialData.begin(), initialData.begin()+rem);
134         }
135
136         while(outLen < outMax)
137         {
138             if(FLAC__stream_decoder_process_single(flacFile) == false ||
139                FLAC__stream_decoder_get_state(flacFile) == FLAC__STREAM_DECODER_END_OF_STREAM)
140                 break;
141         }
142
143         return outLen;
144     }
145
146     virtual bool Rewind()
147     {
148         if(FLAC__stream_decoder_seek_absolute(flacFile, 0) != false)
149         {
150             initialData.clear();
151             return true;
152         }
153
154         SetError("Seek failed");
155         return false;
156     }
157
158     virtual alureInt64 GetLength()
159     {
160         return FLAC__stream_decoder_get_total_samples(flacFile);
161     }
162
163     flacStream(std::istream *_fstream)
164       : alureStream(_fstream), flacFile(NULL), format(AL_NONE), samplerate(0),
165         blockAlign(0), useFloat(AL_FALSE)
166     {
167         if(!flac_handle) return;
168
169         flacFile = FLAC__stream_decoder_new();
170         if(flacFile)
171         {
172             if(FLAC__stream_decoder_init_stream(flacFile, ReadCallback, SeekCallback, TellCallback, LengthCallback, EofCallback, WriteCallback, MetadataCallback, ErrorCallback, this) == FLAC__STREAM_DECODER_INIT_STATUS_OK)
173             {
174                 if(InitFlac())
175                 {
176                     // all ok
177                     return;
178                 }
179
180                 FLAC__stream_decoder_finish(flacFile);
181             }
182             FLAC__stream_decoder_delete(flacFile);
183             flacFile = NULL;
184         }
185     }
186
187     virtual ~flacStream()
188     {
189         if(flacFile)
190         {
191             FLAC__stream_decoder_finish(flacFile);
192             FLAC__stream_decoder_delete(flacFile);
193             flacFile = NULL;
194         }
195     }
196
197 private:
198     bool InitFlac()
199     {
200         // We need to decode some data to be able to get the channel count, bit
201         // depth, and sample rate. It also ensures the file has FLAC data, as
202         // the FLAC__stream_decoder_init_* functions can succeed on non-FLAC
203         // Ogg files.
204         outBytes = NULL;
205         outMax = 0;
206         outLen = 0;
207         while(initialData.size() == 0)
208         {
209             if(FLAC__stream_decoder_process_single(flacFile) == false ||
210                FLAC__stream_decoder_get_state(flacFile) == FLAC__STREAM_DECODER_END_OF_STREAM)
211                 break;
212         }
213
214         if(initialData.size() > 0)
215             return true;
216         return false;
217     }
218
219
220     template<ALuint shift, ALint offset, typename T>
221     static void CopySamples(T *data, const FLAC__int32 *const buffer[], ALuint off, ALuint todo, ALuint channels)
222     {
223         for(ALuint i = 0;i < todo;i++)
224         {
225             for(ALuint c = 0;c < channels;c++)
226                 *(data++) = (buffer[c][off+i]>>shift) + offset;
227         }
228     }
229
230     template<ALuint bits>
231     static void CopySamplesFloat(ALfloat *data, const FLAC__int32 *const buffer[], ALuint off, ALuint todo, ALuint channels)
232     {
233         for(ALuint i = 0;i < todo;i++)
234         {
235             for(ALuint c = 0;c < channels;c++)
236                 *(data++) = buffer[c][off+i] * (1./((1u<<(bits-1))-1));
237         }
238     }
239
240     static FLAC__StreamDecoderWriteStatus WriteCallback(const FLAC__StreamDecoder*, const FLAC__Frame *frame, const FLAC__int32 *const buffer[], void *client_data)
241     {
242         flacStream *self = static_cast<flacStream*>(client_data);
243
244         if(self->format == AL_NONE)
245         {
246             ALuint bps = frame->header.bits_per_sample;
247             if(bps == 24 || bps == 32)
248             {
249                 self->format = GetSampleFormat(frame->header.channels, 32, true);
250                 if(self->format != AL_NONE)
251                 {
252                     self->useFloat = AL_TRUE;
253                     bps = 32;
254                 }
255                 else bps = 16;
256             }
257             if(self->format == AL_NONE)
258                 self->format = GetSampleFormat(frame->header.channels, bps, false);
259             self->blockAlign = frame->header.channels * bps/8;
260             self->samplerate = frame->header.sample_rate;
261         }
262
263         ALubyte *data = self->outBytes + self->outLen;
264         ALuint todo = std::min<ALuint>((self->outMax-self->outLen) / self->blockAlign,
265                                        frame->header.blocksize);
266         if(frame->header.bits_per_sample == 8)
267             CopySamples<0,128>((ALubyte*)data, buffer, 0,
268                                todo, frame->header.channels);
269         else if(frame->header.bits_per_sample == 16)
270             CopySamples<0,0>((ALshort*)data, buffer, 0,
271                              todo, frame->header.channels);
272         else if(frame->header.bits_per_sample == 24)
273         {
274             if(self->useFloat)
275                 CopySamplesFloat<24>((ALfloat*)data, buffer, 0,
276                                      todo, frame->header.channels);
277             else
278                 CopySamples<8,0>((ALshort*)data, buffer, 0,
279                                  todo, frame->header.channels);
280         }
281         else if(frame->header.bits_per_sample == 32)
282         {
283             if(self->useFloat)
284                 CopySamplesFloat<32>((ALfloat*)data, buffer, 0,
285                                      todo, frame->header.channels);
286             else
287                 CopySamples<16,0>((ALshort*)data, buffer, 0,
288                                   todo, frame->header.channels);
289         }
290         self->outLen += self->blockAlign * todo;
291
292         if(todo < frame->header.blocksize)
293         {
294             ALuint offset = todo;
295             todo = frame->header.blocksize - todo;
296
297             ALuint blocklen = todo * self->blockAlign;
298             ALuint start = self->initialData.size();
299
300             self->initialData.resize(start+blocklen);
301             data = &self->initialData[start];
302
303             if(frame->header.bits_per_sample == 8)
304                 CopySamples<0,128>((ALubyte*)data, buffer, offset,
305                                    todo, frame->header.channels);
306             else if(frame->header.bits_per_sample == 16)
307                 CopySamples<0,0>((ALshort*)data, buffer, offset,
308                                  todo, frame->header.channels);
309             else if(frame->header.bits_per_sample == 24)
310             {
311                 if(self->useFloat)
312                     CopySamplesFloat<24>((ALfloat*)data, buffer, offset,
313                                          todo, frame->header.channels);
314                 else
315                     CopySamples<8,0>((ALshort*)data, buffer, offset,
316                                      todo, frame->header.channels);
317             }
318             else if(frame->header.bits_per_sample == 32)
319             {
320                 if(self->useFloat)
321                     CopySamplesFloat<32>((ALfloat*)data, buffer, offset,
322                                          todo, frame->header.channels);
323                 else
324                     CopySamples<16,0>((ALshort*)data, buffer, offset,
325                                       todo, frame->header.channels);
326             }
327         }
328
329         return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
330     }
331     static void MetadataCallback(const FLAC__StreamDecoder*,const FLAC__StreamMetadata*,void*)
332     {
333     }
334     static void ErrorCallback(const FLAC__StreamDecoder*,FLAC__StreamDecoderErrorStatus,void*)
335     {
336     }
337
338     static FLAC__StreamDecoderReadStatus ReadCallback(const FLAC__StreamDecoder*, FLAC__byte buffer[], size_t *bytes, void *client_data)
339     {
340         std::istream *stream = static_cast<flacStream*>(client_data)->fstream;
341         stream->clear();
342
343         if(*bytes <= 0)
344             return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
345
346         stream->read(reinterpret_cast<char*>(buffer), *bytes);
347         *bytes = stream->gcount();
348         if(*bytes == 0 && stream->eof())
349             return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
350
351         return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
352     }
353     static FLAC__StreamDecoderSeekStatus SeekCallback(const FLAC__StreamDecoder*, FLAC__uint64 absolute_byte_offset, void *client_data)
354     {
355         std::istream *stream = static_cast<flacStream*>(client_data)->fstream;
356         stream->clear();
357
358         if(!stream->seekg(absolute_byte_offset))
359             return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
360         return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
361     }
362     static FLAC__StreamDecoderTellStatus TellCallback(const FLAC__StreamDecoder*, FLAC__uint64 *absolute_byte_offset, void *client_data)
363     {
364         std::istream *stream = static_cast<flacStream*>(client_data)->fstream;
365         stream->clear();
366
367         *absolute_byte_offset = stream->tellg();
368         return FLAC__STREAM_DECODER_TELL_STATUS_OK;
369     }
370     static FLAC__StreamDecoderLengthStatus LengthCallback(const FLAC__StreamDecoder*, FLAC__uint64 *stream_length, void *client_data)
371     {
372         std::istream *stream = static_cast<flacStream*>(client_data)->fstream;
373         stream->clear();
374
375         std::streampos pos = stream->tellg();
376         if(stream->seekg(0, std::ios_base::end))
377         {
378             *stream_length = stream->tellg();
379             stream->seekg(pos);
380         }
381
382         if(!stream->good())
383             return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR;
384         return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
385     }
386     static FLAC__bool EofCallback(const FLAC__StreamDecoder*, void *client_data)
387     {
388         std::istream *stream = static_cast<flacStream*>(client_data)->fstream;
389         return (stream->eof()) ? true : false;
390     }
391 };
392 // Priority = 1, so it's preferred over libsndfile
393 static DecoderDecl<flacStream,1> flacStream_decoder;
394 Decoder &alure_init_flac(void)
395 { return flacStream_decoder; }