14 class FlacDecoder
: public Decoder
{
15 SharedPtr
<std::istream
> mFile
;
17 FLAC__StreamDecoder
*mFlacFile
;
18 SampleConfig mSampleConfig
;
19 SampleType mSampleType
;
24 std::vector
<ALubyte
> mData
;
30 void CopySamples(ALubyte
*output
, ALuint todo
, const FLAC__Frame
*frame
, const FLAC__int32
*const buffer
[], ALuint offset
)
32 if(mSampleType
== SampleType_UInt8
)
34 ALubyte
*samples
= output
;
35 for(ALuint i
= 0;i
< todo
;i
++)
37 for(ALuint c
= 0;c
< frame
->header
.channels
;c
++)
38 *(samples
++) = ALubyte(buffer
[c
][offset
+i
] + 0x80);
43 int shift
= frame
->header
.bits_per_sample
- 16;
44 ALshort
*samples
= reinterpret_cast<ALshort
*>(output
);
45 for(ALuint i
= 0;i
< todo
;i
++)
47 for(ALuint c
= 0;c
< frame
->header
.channels
;c
++)
48 *(samples
++) = buffer
[c
][offset
+i
] >> shift
;
53 static FLAC__StreamDecoderWriteStatus
WriteCallback(const FLAC__StreamDecoder
*, const FLAC__Frame
*frame
, const FLAC__int32
*const buffer
[], void *client_data
)
55 FlacDecoder
*self
= static_cast<FlacDecoder
*>(client_data
);
57 if(self
->mFrequency
== 0)
59 ALuint bps
= frame
->header
.bits_per_sample
;
61 self
->mSampleType
= SampleType_UInt8
;
64 self
->mSampleType
= SampleType_Int16
;
68 if(frame
->header
.channels
== 1)
69 self
->mSampleConfig
= SampleConfig_Mono
;
70 else if(frame
->header
.channels
== 2)
71 self
->mSampleConfig
= SampleConfig_Stereo
;
73 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT
;
75 self
->mFrameSize
= frame
->header
.channels
* bps
/8;
76 self
->mFrequency
= frame
->header
.sample_rate
;
79 ALubyte
*data
= self
->mOutBytes
+ self
->mOutLen
;
80 ALuint todo
= std::min
<ALuint
>((self
->mOutMax
-self
->mOutLen
) / self
->mFrameSize
,
81 frame
->header
.blocksize
);
82 self
->CopySamples(data
, todo
, frame
, buffer
, 0);
83 self
->mOutLen
+= self
->mFrameSize
* todo
;
85 if(todo
< frame
->header
.blocksize
)
88 todo
= frame
->header
.blocksize
- todo
;
90 ALuint blocklen
= todo
* self
->mFrameSize
;
91 ALuint start
= self
->mData
.size();
93 self
->mData
.resize(start
+blocklen
);
94 data
= &self
->mData
[start
];
96 self
->CopySamples(data
, todo
, frame
, buffer
, offset
);
99 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE
;
101 static void MetadataCallback(const FLAC__StreamDecoder
*,const FLAC__StreamMetadata
*,void*)
104 static void ErrorCallback(const FLAC__StreamDecoder
*,FLAC__StreamDecoderErrorStatus
,void*)
108 static FLAC__StreamDecoderReadStatus
ReadCallback(const FLAC__StreamDecoder
*, FLAC__byte buffer
[], size_t *bytes
, void *client_data
)
110 std::istream
*stream
= static_cast<FlacDecoder
*>(client_data
)->mFile
.get();
114 return FLAC__STREAM_DECODER_READ_STATUS_ABORT
;
116 stream
->read(reinterpret_cast<char*>(buffer
), *bytes
);
117 *bytes
= stream
->gcount();
118 if(*bytes
== 0 && stream
->eof())
119 return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM
;
121 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE
;
123 static FLAC__StreamDecoderSeekStatus
SeekCallback(const FLAC__StreamDecoder
*, FLAC__uint64 absolute_byte_offset
, void *client_data
)
125 std::istream
*stream
= static_cast<FlacDecoder
*>(client_data
)->mFile
.get();
128 if(!stream
->seekg(absolute_byte_offset
))
129 return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR
;
130 return FLAC__STREAM_DECODER_SEEK_STATUS_OK
;
132 static FLAC__StreamDecoderTellStatus
TellCallback(const FLAC__StreamDecoder
*, FLAC__uint64
*absolute_byte_offset
, void *client_data
)
134 std::istream
*stream
= static_cast<FlacDecoder
*>(client_data
)->mFile
.get();
137 *absolute_byte_offset
= stream
->tellg();
138 return FLAC__STREAM_DECODER_TELL_STATUS_OK
;
140 static FLAC__StreamDecoderLengthStatus
LengthCallback(const FLAC__StreamDecoder
*, FLAC__uint64
*stream_length
, void *client_data
)
142 std::istream
*stream
= static_cast<FlacDecoder
*>(client_data
)->mFile
.get();
145 std::streampos pos
= stream
->tellg();
146 if(stream
->seekg(0, std::ios_base::end
))
148 *stream_length
= stream
->tellg();
153 return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR
;
154 return FLAC__STREAM_DECODER_LENGTH_STATUS_OK
;
156 static FLAC__bool
EofCallback(const FLAC__StreamDecoder
*, void *client_data
)
158 std::istream
*stream
= static_cast<FlacDecoder
*>(client_data
)->mFile
.get();
159 return stream
->eof() ? true : false;
163 FlacDecoder(SharedPtr
<std::istream
> file
)
164 : mFile(file
), mFlacFile(nullptr), mSampleConfig(SampleConfig_Mono
), mSampleType(SampleType_Int16
), mFrequency(0),
165 mFrameSize(0), mSamplePos(0), mOutBytes(nullptr), mOutMax(0), mOutLen(0)
167 virtual ~FlacDecoder();
171 virtual ALuint
getFrequency() final
;
172 virtual SampleConfig
getSampleConfig() final
;
173 virtual SampleType
getSampleType() final
;
175 virtual uint64_t getLength() final
;
176 virtual uint64_t getPosition() final
;
177 virtual bool seek(uint64_t pos
) final
;
179 virtual ALuint
read(ALvoid
*ptr
, ALuint count
) final
;
182 FlacDecoder::~FlacDecoder()
186 FLAC__stream_decoder_finish(mFlacFile
);
187 FLAC__stream_decoder_delete(mFlacFile
);
193 bool FlacDecoder::open()
195 mFlacFile
= FLAC__stream_decoder_new();
198 if(FLAC__stream_decoder_init_stream(mFlacFile
, ReadCallback
, SeekCallback
, TellCallback
, LengthCallback
, EofCallback
, WriteCallback
, MetadataCallback
, ErrorCallback
, this) == FLAC__STREAM_DECODER_INIT_STATUS_OK
)
200 while(mData
.size() == 0)
202 if(FLAC__stream_decoder_process_single(mFlacFile
) == false ||
203 FLAC__stream_decoder_get_state(mFlacFile
) == FLAC__STREAM_DECODER_END_OF_STREAM
)
209 FLAC__stream_decoder_finish(mFlacFile
);
211 FLAC__stream_decoder_delete(mFlacFile
);
219 ALuint
FlacDecoder::getFrequency()
224 SampleConfig
FlacDecoder::getSampleConfig()
226 return mSampleConfig
;
229 SampleType
FlacDecoder::getSampleType()
235 uint64_t FlacDecoder::getLength()
237 return FLAC__stream_decoder_get_total_samples(mFlacFile
);
240 uint64_t FlacDecoder::getPosition()
245 bool FlacDecoder::seek(uint64_t pos
)
247 if(!FLAC__stream_decoder_seek_absolute(mFlacFile
, pos
))
253 ALuint
FlacDecoder::read(ALvoid
*ptr
, ALuint count
)
255 mOutBytes
= reinterpret_cast<ALubyte
*>(ptr
);
257 mOutMax
= count
* mFrameSize
;
261 size_t rem
= std::min(mData
.size(), (size_t)mOutMax
);
262 memcpy(ptr
, &mData
[0], rem
);
264 mData
.erase(mData
.begin(), mData
.begin()+rem
);
267 while(mOutLen
< mOutMax
)
269 if(FLAC__stream_decoder_process_single(mFlacFile
) == false ||
270 FLAC__stream_decoder_get_state(mFlacFile
) == FLAC__STREAM_DECODER_END_OF_STREAM
)
273 ALuint ret
= mOutLen
/ mFrameSize
;
281 SharedPtr
<Decoder
> FlacDecoderFactory::createDecoder(SharedPtr
<std::istream
> file
)
283 SharedPtr
<FlacDecoder
> decoder(new FlacDecoder(file
));
284 if(!decoder
->open()) decoder
.reset();