Properly mark classes as final
[alure.git] / src / decoders / flac.cpp
blob58ba64d6363db4b1951919e891ec961dfdb4500d
2 #include "flac.hpp"
4 #include <stdexcept>
5 #include <iostream>
6 #include <cstring>
8 #include "FLAC/all.h"
11 namespace alure
14 class FlacDecoder final : public Decoder {
15 UniquePtr<std::istream> mFile;
17 FLAC__StreamDecoder *mFlacFile;
18 ChannelConfig mChannelConfig;
19 SampleType mSampleType;
20 ALuint mFrequency;
21 ALuint mFrameSize;
23 Vector<ALubyte> mData;
25 ALubyte *mOutBytes;
26 ALuint mOutMax;
27 ALuint mOutLen;
29 void CopySamples(ALubyte *output, ALuint todo, const FLAC__Frame *frame, const FLAC__int32 *const buffer[], ALuint offset)
31 if(mSampleType == SampleType::UInt8)
33 int shift = 8 - frame->header.bits_per_sample;
34 ALubyte *samples = output;
35 for(ALuint c = 0;c < frame->header.channels;c++)
37 for(ALuint i = 0;i < todo;i++)
38 samples[i*frame->header.channels + c] = ALubyte((buffer[c][offset+i]<<shift) + 0x80);
41 else if(mSampleType == SampleType::Int16)
43 int shift = 16 - frame->header.bits_per_sample;
44 ALshort *samples = reinterpret_cast<ALshort*>(output);
45 if(shift >= 0)
47 for(ALuint c = 0;c < frame->header.channels;c++)
49 for(ALuint i = 0;i < todo;i++)
50 samples[i*frame->header.channels + c] = buffer[c][offset+i] << shift;
53 else
55 shift = -shift;
56 for(ALuint c = 0;c < frame->header.channels;c++)
58 for(ALuint i = 0;i < todo;i++)
59 samples[i*frame->header.channels + c] = buffer[c][offset+i] >> shift;
63 else
65 ALfloat scale = 1.0f / (float)(1<<(frame->header.bits_per_sample-1));
66 ALfloat *samples = reinterpret_cast<ALfloat*>(output);
67 for(ALuint c = 0;c < frame->header.channels;c++)
69 for(ALuint i = 0;i < todo;i++)
70 samples[i*frame->header.channels + c] = (ALfloat)buffer[c][offset+i] * scale;
75 static FLAC__StreamDecoderWriteStatus WriteCallback(const FLAC__StreamDecoder*, const FLAC__Frame *frame, const FLAC__int32 *const buffer[], void *client_data)
77 FlacDecoder *self = static_cast<FlacDecoder*>(client_data);
79 if(self->mFrequency == 0)
81 if(frame->header.channels == 1)
82 self->mChannelConfig = ChannelConfig::Mono;
83 else if(frame->header.channels == 2)
84 self->mChannelConfig = ChannelConfig::Stereo;
85 else
86 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
88 ALuint bps = frame->header.bits_per_sample;
89 if(bps > 16 && Context::GetCurrent().isSupported(self->mChannelConfig, SampleType::Float32))
91 self->mSampleType = SampleType::Float32;
92 bps = 32;
94 else if(bps > 8)
96 self->mSampleType = SampleType::Int16;
97 bps = 16;
99 else
101 self->mSampleType = SampleType::UInt8;
102 bps = 8;
105 self->mFrameSize = frame->header.channels * bps/8;
106 self->mFrequency = frame->header.sample_rate;
109 ALubyte *data = self->mOutBytes + self->mOutLen;
110 ALuint todo = std::min<ALuint>((self->mOutMax-self->mOutLen) / self->mFrameSize,
111 frame->header.blocksize);
112 self->CopySamples(data, todo, frame, buffer, 0);
113 self->mOutLen += self->mFrameSize * todo;
115 if(todo < frame->header.blocksize)
117 ALuint offset = todo;
118 todo = frame->header.blocksize - todo;
120 ALuint blocklen = todo * self->mFrameSize;
121 ALuint start = self->mData.size();
123 self->mData.resize(start+blocklen);
124 data = &self->mData[start];
126 self->CopySamples(data, todo, frame, buffer, offset);
129 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
131 static void MetadataCallback(const FLAC__StreamDecoder*,const FLAC__StreamMetadata*,void*)
134 static void ErrorCallback(const FLAC__StreamDecoder*,FLAC__StreamDecoderErrorStatus,void*)
138 static FLAC__StreamDecoderReadStatus ReadCallback(const FLAC__StreamDecoder*, FLAC__byte buffer[], size_t *bytes, void *client_data)
140 std::istream *stream = static_cast<FlacDecoder*>(client_data)->mFile.get();
141 stream->clear();
143 if(*bytes <= 0)
144 return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
146 stream->read(reinterpret_cast<char*>(buffer), *bytes);
147 *bytes = stream->gcount();
148 if(*bytes == 0 && stream->eof())
149 return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
151 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
153 static FLAC__StreamDecoderSeekStatus SeekCallback(const FLAC__StreamDecoder*, FLAC__uint64 absolute_byte_offset, void *client_data)
155 std::istream *stream = static_cast<FlacDecoder*>(client_data)->mFile.get();
156 stream->clear();
158 if(!stream->seekg(absolute_byte_offset))
159 return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
160 return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
162 static FLAC__StreamDecoderTellStatus TellCallback(const FLAC__StreamDecoder*, FLAC__uint64 *absolute_byte_offset, void *client_data)
164 std::istream *stream = static_cast<FlacDecoder*>(client_data)->mFile.get();
165 stream->clear();
167 *absolute_byte_offset = stream->tellg();
168 return FLAC__STREAM_DECODER_TELL_STATUS_OK;
170 static FLAC__StreamDecoderLengthStatus LengthCallback(const FLAC__StreamDecoder*, FLAC__uint64 *stream_length, void *client_data)
172 std::istream *stream = static_cast<FlacDecoder*>(client_data)->mFile.get();
173 stream->clear();
175 std::streampos pos = stream->tellg();
176 if(stream->seekg(0, std::ios_base::end))
178 *stream_length = stream->tellg();
179 stream->seekg(pos);
182 if(!stream->good())
183 return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR;
184 return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
186 static FLAC__bool EofCallback(const FLAC__StreamDecoder*, void *client_data)
188 std::istream *stream = static_cast<FlacDecoder*>(client_data)->mFile.get();
189 return stream->eof() ? true : false;
192 public:
193 FlacDecoder()
194 : mFlacFile(nullptr), mChannelConfig(ChannelConfig::Mono), mSampleType(SampleType::Int16)
195 , mFrequency(0), mFrameSize(0), mOutBytes(nullptr), mOutMax(0), mOutLen(0)
197 ~FlacDecoder() override;
199 bool open(UniquePtr<std::istream> &file);
201 ALuint getFrequency() const override;
202 ChannelConfig getChannelConfig() const override;
203 SampleType getSampleType() const override;
205 uint64_t getLength() const override;
206 bool seek(uint64_t pos) override;
208 std::pair<uint64_t,uint64_t> getLoopPoints() const override;
210 ALuint read(ALvoid *ptr, ALuint count) override;
213 FlacDecoder::~FlacDecoder()
215 if(mFlacFile)
217 FLAC__stream_decoder_finish(mFlacFile);
218 FLAC__stream_decoder_delete(mFlacFile);
219 mFlacFile = nullptr;
224 bool FlacDecoder::open(UniquePtr<std::istream> &file)
226 mFlacFile = FLAC__stream_decoder_new();
227 if(mFlacFile)
229 mFile = std::move(file);
230 if(FLAC__stream_decoder_init_stream(mFlacFile, ReadCallback, SeekCallback, TellCallback, LengthCallback, EofCallback, WriteCallback, MetadataCallback, ErrorCallback, this) == FLAC__STREAM_DECODER_INIT_STATUS_OK)
232 while(mData.empty())
234 if(FLAC__stream_decoder_process_single(mFlacFile) == false ||
235 FLAC__stream_decoder_get_state(mFlacFile) == FLAC__STREAM_DECODER_END_OF_STREAM)
236 break;
238 if(!mData.empty())
239 return true;
241 FLAC__stream_decoder_finish(mFlacFile);
243 FLAC__stream_decoder_delete(mFlacFile);
244 mFlacFile = nullptr;
246 file = std::move(mFile);
249 return false;
253 ALuint FlacDecoder::getFrequency() const
255 return mFrequency;
258 ChannelConfig FlacDecoder::getChannelConfig() const
260 return mChannelConfig;
263 SampleType FlacDecoder::getSampleType() const
265 return mSampleType;
269 uint64_t FlacDecoder::getLength() const
271 return FLAC__stream_decoder_get_total_samples(mFlacFile);
274 bool FlacDecoder::seek(uint64_t pos)
276 if(!FLAC__stream_decoder_seek_absolute(mFlacFile, pos))
277 return false;
278 return true;
281 std::pair<uint64_t,uint64_t> FlacDecoder::getLoopPoints() const
283 return std::make_pair(0, 0);
286 ALuint FlacDecoder::read(ALvoid *ptr, ALuint count)
288 mOutBytes = reinterpret_cast<ALubyte*>(ptr);
289 mOutLen = 0;
290 mOutMax = count * mFrameSize;
292 if(mData.size() > 0)
294 size_t rem = std::min(mData.size(), (size_t)mOutMax);
295 memcpy(ptr, mData.data(), rem);
296 mOutLen += rem;
297 mData.erase(mData.begin(), mData.begin()+rem);
300 while(mOutLen < mOutMax)
302 if(FLAC__stream_decoder_process_single(mFlacFile) == false ||
303 FLAC__stream_decoder_get_state(mFlacFile) == FLAC__STREAM_DECODER_END_OF_STREAM)
304 break;
306 return mOutLen / mFrameSize;
310 SharedPtr<Decoder> FlacDecoderFactory::createDecoder(UniquePtr<std::istream> &file)
312 auto decoder = MakeShared<FlacDecoder>();
313 if(!decoder->open(file)) decoder.reset();
314 return decoder;