Remove the source's public update method
[alure.git] / src / decoders / flac.cpp
blob0947bb771ea8e307bda40536b6715e7082733288
2 #include "flac.hpp"
4 #include <stdexcept>
5 #include <iostream>
6 #include <cstring>
8 #include "FLAC/all.h"
11 namespace alure
14 class FlacDecoder : public Decoder {
15 UniquePtr<std::istream> mFile;
17 FLAC__StreamDecoder *mFlacFile;
18 ChannelConfig mChannelConfig;
19 SampleType mSampleType;
20 ALuint mFrequency;
21 ALuint mFrameSize;
22 uint64_t mSamplePos;
24 Vector<ALubyte> mData;
26 ALubyte *mOutBytes;
27 ALuint mOutMax;
28 ALuint mOutLen;
30 void CopySamples(ALubyte *output, ALuint todo, const FLAC__Frame *frame, const FLAC__int32 *const buffer[], ALuint offset)
32 if(mSampleType == SampleType::UInt8)
34 int shift = 8 - frame->header.bits_per_sample;
35 ALubyte *samples = output;
36 for(ALuint c = 0;c < frame->header.channels;c++)
38 for(ALuint i = 0;i < todo;i++)
39 samples[i*frame->header.channels + c] = ALubyte((buffer[c][offset+i]<<shift) + 0x80);
42 else if(mSampleType == SampleType::Int16)
44 int shift = 16 - frame->header.bits_per_sample;
45 ALshort *samples = reinterpret_cast<ALshort*>(output);
46 if(shift >= 0)
48 for(ALuint c = 0;c < frame->header.channels;c++)
50 for(ALuint i = 0;i < todo;i++)
51 samples[i*frame->header.channels + c] = buffer[c][offset+i] << shift;
54 else
56 shift = -shift;
57 for(ALuint c = 0;c < frame->header.channels;c++)
59 for(ALuint i = 0;i < todo;i++)
60 samples[i*frame->header.channels + c] = buffer[c][offset+i] >> shift;
64 else
66 ALfloat scale = 1.0f / (float)(1<<(frame->header.bits_per_sample-1));
67 ALfloat *samples = reinterpret_cast<ALfloat*>(output);
68 for(ALuint c = 0;c < frame->header.channels;c++)
70 for(ALuint i = 0;i < todo;i++)
71 samples[i*frame->header.channels + c] = (ALfloat)buffer[c][offset+i] * scale;
76 static FLAC__StreamDecoderWriteStatus WriteCallback(const FLAC__StreamDecoder*, const FLAC__Frame *frame, const FLAC__int32 *const buffer[], void *client_data)
78 FlacDecoder *self = static_cast<FlacDecoder*>(client_data);
80 if(self->mFrequency == 0)
82 if(frame->header.channels == 1)
83 self->mChannelConfig = ChannelConfig::Mono;
84 else if(frame->header.channels == 2)
85 self->mChannelConfig = ChannelConfig::Stereo;
86 else
87 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
89 ALuint bps = frame->header.bits_per_sample;
90 if(bps > 16 && Context::GetCurrent().isSupported(self->mChannelConfig, SampleType::Float32))
92 self->mSampleType = SampleType::Float32;
93 bps = 32;
95 else if(bps > 8)
97 self->mSampleType = SampleType::Int16;
98 bps = 16;
100 else
102 self->mSampleType = SampleType::UInt8;
103 bps = 8;
106 self->mFrameSize = frame->header.channels * bps/8;
107 self->mFrequency = frame->header.sample_rate;
110 ALubyte *data = self->mOutBytes + self->mOutLen;
111 ALuint todo = std::min<ALuint>((self->mOutMax-self->mOutLen) / self->mFrameSize,
112 frame->header.blocksize);
113 self->CopySamples(data, todo, frame, buffer, 0);
114 self->mOutLen += self->mFrameSize * todo;
116 if(todo < frame->header.blocksize)
118 ALuint offset = todo;
119 todo = frame->header.blocksize - todo;
121 ALuint blocklen = todo * self->mFrameSize;
122 ALuint start = self->mData.size();
124 self->mData.resize(start+blocklen);
125 data = &self->mData[start];
127 self->CopySamples(data, todo, frame, buffer, offset);
130 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
132 static void MetadataCallback(const FLAC__StreamDecoder*,const FLAC__StreamMetadata*,void*)
135 static void ErrorCallback(const FLAC__StreamDecoder*,FLAC__StreamDecoderErrorStatus,void*)
139 static FLAC__StreamDecoderReadStatus ReadCallback(const FLAC__StreamDecoder*, FLAC__byte buffer[], size_t *bytes, void *client_data)
141 std::istream *stream = static_cast<FlacDecoder*>(client_data)->mFile.get();
142 stream->clear();
144 if(*bytes <= 0)
145 return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
147 stream->read(reinterpret_cast<char*>(buffer), *bytes);
148 *bytes = stream->gcount();
149 if(*bytes == 0 && stream->eof())
150 return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
152 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
154 static FLAC__StreamDecoderSeekStatus SeekCallback(const FLAC__StreamDecoder*, FLAC__uint64 absolute_byte_offset, void *client_data)
156 std::istream *stream = static_cast<FlacDecoder*>(client_data)->mFile.get();
157 stream->clear();
159 if(!stream->seekg(absolute_byte_offset))
160 return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
161 return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
163 static FLAC__StreamDecoderTellStatus TellCallback(const FLAC__StreamDecoder*, FLAC__uint64 *absolute_byte_offset, void *client_data)
165 std::istream *stream = static_cast<FlacDecoder*>(client_data)->mFile.get();
166 stream->clear();
168 *absolute_byte_offset = stream->tellg();
169 return FLAC__STREAM_DECODER_TELL_STATUS_OK;
171 static FLAC__StreamDecoderLengthStatus LengthCallback(const FLAC__StreamDecoder*, FLAC__uint64 *stream_length, void *client_data)
173 std::istream *stream = static_cast<FlacDecoder*>(client_data)->mFile.get();
174 stream->clear();
176 std::streampos pos = stream->tellg();
177 if(stream->seekg(0, std::ios_base::end))
179 *stream_length = stream->tellg();
180 stream->seekg(pos);
183 if(!stream->good())
184 return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR;
185 return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
187 static FLAC__bool EofCallback(const FLAC__StreamDecoder*, void *client_data)
189 std::istream *stream = static_cast<FlacDecoder*>(client_data)->mFile.get();
190 return stream->eof() ? true : false;
193 public:
194 FlacDecoder()
195 : mFlacFile(nullptr), mChannelConfig(ChannelConfig::Mono), mSampleType(SampleType::Int16)
196 , mFrequency(0), mFrameSize(0), mSamplePos(0), mOutBytes(nullptr), mOutMax(0), mOutLen(0)
198 ~FlacDecoder() override final;
200 bool open(UniquePtr<std::istream> &file);
202 ALuint getFrequency() const override final;
203 ChannelConfig getChannelConfig() const override final;
204 SampleType getSampleType() const override final;
206 uint64_t getLength() const override final;
207 uint64_t getPosition() const override final;
208 bool seek(uint64_t pos) override final;
210 std::pair<uint64_t,uint64_t> getLoopPoints() const override final;
212 ALuint read(ALvoid *ptr, ALuint count) override final;
215 FlacDecoder::~FlacDecoder()
217 if(mFlacFile)
219 FLAC__stream_decoder_finish(mFlacFile);
220 FLAC__stream_decoder_delete(mFlacFile);
221 mFlacFile = nullptr;
226 bool FlacDecoder::open(UniquePtr<std::istream> &file)
228 mFlacFile = FLAC__stream_decoder_new();
229 if(mFlacFile)
231 mFile = std::move(file);
232 if(FLAC__stream_decoder_init_stream(mFlacFile, ReadCallback, SeekCallback, TellCallback, LengthCallback, EofCallback, WriteCallback, MetadataCallback, ErrorCallback, this) == FLAC__STREAM_DECODER_INIT_STATUS_OK)
234 while(mData.empty())
236 if(FLAC__stream_decoder_process_single(mFlacFile) == false ||
237 FLAC__stream_decoder_get_state(mFlacFile) == FLAC__STREAM_DECODER_END_OF_STREAM)
238 break;
240 if(!mData.empty())
241 return true;
243 FLAC__stream_decoder_finish(mFlacFile);
245 FLAC__stream_decoder_delete(mFlacFile);
246 mFlacFile = nullptr;
248 file = std::move(mFile);
251 return false;
255 ALuint FlacDecoder::getFrequency() const
257 return mFrequency;
260 ChannelConfig FlacDecoder::getChannelConfig() const
262 return mChannelConfig;
265 SampleType FlacDecoder::getSampleType() const
267 return mSampleType;
271 uint64_t FlacDecoder::getLength() const
273 return FLAC__stream_decoder_get_total_samples(mFlacFile);
276 uint64_t FlacDecoder::getPosition() const
278 return mSamplePos;
281 bool FlacDecoder::seek(uint64_t pos)
283 if(!FLAC__stream_decoder_seek_absolute(mFlacFile, pos))
284 return false;
285 mSamplePos = pos;
286 return true;
289 std::pair<uint64_t,uint64_t> FlacDecoder::getLoopPoints() const
291 return std::make_pair(0, 0);
294 ALuint FlacDecoder::read(ALvoid *ptr, ALuint count)
296 mOutBytes = reinterpret_cast<ALubyte*>(ptr);
297 mOutLen = 0;
298 mOutMax = count * mFrameSize;
300 if(mData.size() > 0)
302 size_t rem = std::min(mData.size(), (size_t)mOutMax);
303 memcpy(ptr, &mData[0], rem);
304 mOutLen += rem;
305 mData.erase(mData.begin(), mData.begin()+rem);
308 while(mOutLen < mOutMax)
310 if(FLAC__stream_decoder_process_single(mFlacFile) == false ||
311 FLAC__stream_decoder_get_state(mFlacFile) == FLAC__STREAM_DECODER_END_OF_STREAM)
312 break;
314 ALuint ret = mOutLen / mFrameSize;
316 mSamplePos += ret;
318 return ret;
322 SharedPtr<Decoder> FlacDecoderFactory::createDecoder(UniquePtr<std::istream> &file)
324 auto decoder = MakeShared<FlacDecoder>();
325 if(!decoder->open(file)) decoder.reset();
326 return decoder;