1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
3#include "BsFLACDecoder.h"
4#include "FileSystem/BsDataStream.h"
5
6namespace bs
7{
8 FLAC__StreamDecoderReadStatus streamRead(const FLAC__StreamDecoder*, FLAC__byte buffer[], size_t* bytes, void* clientData)
9 {
10 FLACDecoderData* data = (FLACDecoderData*)(clientData);
11
12 INT64 count = (INT64)data->stream->read(buffer, *bytes);
13 if (count > 0)
14 {
15 *bytes = (size_t)count;
16 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
17 }
18
19 if (count == 0)
20 return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
21
22 return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
23 }
24
25 FLAC__StreamDecoderSeekStatus streamSeek(const FLAC__StreamDecoder*, FLAC__uint64 absoluteByteOffset, void* clientData)
26 {
27 FLACDecoderData* data = (FLACDecoderData*)(clientData);
28
29 data->stream->seek(data->streamOffset + (UINT32)absoluteByteOffset);
30 INT64 position = (INT64)(data->stream->tell() - data->streamOffset);
31 if (position >= 0)
32 return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
33 else
34 return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
35 }
36
37 FLAC__StreamDecoderTellStatus streamTell(const FLAC__StreamDecoder*, FLAC__uint64* absoluteByteOffset, void* clientData)
38 {
39 FLACDecoderData* data = (FLACDecoderData*)(clientData);
40
41 INT64 position = (INT64)(data->stream->tell() - data->streamOffset);
42 if (position >= 0)
43 {
44 *absoluteByteOffset = position;
45 return FLAC__STREAM_DECODER_TELL_STATUS_OK;
46 }
47 else
48 {
49 return FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
50 }
51 }
52
53 FLAC__StreamDecoderLengthStatus streamLength(const FLAC__StreamDecoder*, FLAC__uint64* streamLength, void* clientData)
54 {
55 FLACDecoderData* data = (FLACDecoderData*)(clientData);
56
57 *streamLength = data->stream->size() - data->streamOffset;
58 return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
59 }
60
61 FLAC__bool streamEof(const FLAC__StreamDecoder*, void* clientData)
62 {
63 FLACDecoderData* data = (FLACDecoderData*)(clientData);
64
65 return data->stream->eof();
66 }
67
68 FLAC__StreamDecoderWriteStatus streamWrite(const FLAC__StreamDecoder*, const FLAC__Frame* frame, const FLAC__int32* const buffer[], void* clientData)
69 {
70 FLACDecoderData* data = (FLACDecoderData*)(clientData);
71
72 if (!data->output) // Seek
73 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
74
75 UINT32 bytesPerSample = data->info.bitDepth / 8;
76
77 // If we received more data than we need, store it in the overflow buffer
78 UINT32 frameSamples = frame->header.blocksize * frame->header.channels;
79 if (data->samplesToRead < frameSamples)
80 {
81 UINT32 numExtraSamples = frameSamples - data->samplesToRead;
82 UINT32 extraBytes = numExtraSamples * bytesPerSample;
83 data->overflow.reserve(extraBytes);
84 }
85
86 assert(bytesPerSample <= 4);
87 for (UINT32 i = 0; i < frame->header.blocksize; i++)
88 {
89 for (UINT32 j = 0; j < frame->header.channels; j++)
90 {
91 if (data->samplesToRead > 0)
92 {
93 memcpy(data->output, &buffer[j][i], bytesPerSample);
94
95 data->output += bytesPerSample;
96 data->samplesToRead--;
97 }
98 else
99 {
100 UINT8 sample[4];
101 memcpy(sample, &buffer[j][i], bytesPerSample);
102
103 for(UINT32 k = 0; k < bytesPerSample; k++)
104 data->overflow.push_back(sample[k]);
105 }
106 }
107 }
108
109 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
110 }
111
112 void streamMetadata(const FLAC__StreamDecoder*, const FLAC__StreamMetadata* meta, void* clientData)
113 {
114 FLACDecoderData* data = (FLACDecoderData*)(clientData);
115
116 if (meta->type == FLAC__METADATA_TYPE_STREAMINFO)
117 {
118 data->info.numSamples = (UINT32)meta->data.stream_info.total_samples * meta->data.stream_info.channels;
119 data->info.sampleRate = meta->data.stream_info.sample_rate;
120 data->info.numChannels = meta->data.stream_info.channels;
121 data->info.bitDepth = meta->data.stream_info.bits_per_sample;
122 }
123 }
124
125 void streamError(const FLAC__StreamDecoder*, FLAC__StreamDecoderErrorStatus, void* clientData)
126 {
127 FLACDecoderData* data = (FLACDecoderData*)(clientData);
128 data->error = true;
129 }
130
131 FLACDecoder::~FLACDecoder()
132 {
133 close();
134 }
135
136 bool FLACDecoder::isValid(const SPtr<DataStream>& stream, UINT32 offset)
137 {
138 stream->seek(offset);
139
140 FLAC__StreamDecoder* decoder = FLAC__stream_decoder_new();
141 if (!decoder)
142 return false;
143
144 FLACDecoderData data;
145 data.stream = stream;
146 mData.streamOffset = offset;
147 FLAC__stream_decoder_init_stream(decoder, &streamRead, &streamSeek, &streamTell, &streamLength, &streamEof,
148 &streamWrite, nullptr, &streamError, &data);
149
150 bool valid = FLAC__stream_decoder_process_until_end_of_metadata(decoder) != 0;
151
152 FLAC__stream_decoder_finish(decoder);
153 FLAC__stream_decoder_delete(decoder);
154
155 return valid && !data.error;
156 }
157
158 bool FLACDecoder::open(const SPtr<DataStream>& stream, AudioDataInfo& info, UINT32 offset)
159 {
160 if (stream == nullptr)
161 return false;
162
163 stream->seek(offset);
164
165 mDecoder = FLAC__stream_decoder_new();
166 if (mDecoder == nullptr)
167 {
168 LOGERR("Failed to open a FLAC file.");
169 return false;
170 }
171
172 mData.stream = stream;
173 mData.streamOffset = offset;
174 FLAC__stream_decoder_init_stream(mDecoder, &streamRead, &streamSeek, &streamTell, &streamLength, &streamEof,
175 &streamWrite, &streamMetadata, &streamError, &mData);
176
177 if (!FLAC__stream_decoder_process_until_end_of_metadata(mDecoder))
178 {
179 close();
180 LOGERR("Failed to open a FLAC file.");
181 return false;
182 }
183
184 info = mData.info;
185
186 return true;
187 }
188
189 void FLACDecoder::seek(UINT32 offset)
190 {
191 mData.output = nullptr;
192 mData.samplesToRead = 0;
193 mData.overflow.clear();
194
195 FLAC__stream_decoder_seek_absolute(mDecoder, offset);
196 }
197
198 UINT32 FLACDecoder::read(UINT8* samples, UINT32 numSamples)
199 {
200 UINT32 overflowSize = (UINT32)mData.overflow.size();
201 UINT32 overflowNumSamples = 0;
202
203 UINT32 bytesPerSample = mData.info.bitDepth / 8;
204 if (overflowSize > 0)
205 {
206 UINT32 sampleSize = numSamples * bytesPerSample;
207 if (overflowSize > sampleSize)
208 {
209 std::copy(mData.overflow.begin(), mData.overflow.begin() + sampleSize, samples);
210 mData.overflow.erase(mData.overflow.begin(), mData.overflow.begin() + sampleSize);
211
212 return numSamples;
213 }
214 else
215 std::copy(mData.overflow.begin(), mData.overflow.end(), samples);
216
217 overflowNumSamples = overflowSize / bytesPerSample;
218 }
219
220 mData.output = samples + overflowSize;
221 mData.samplesToRead = numSamples - overflowNumSamples;
222 mData.overflow.clear();
223
224 while (mData.samplesToRead > 0)
225 {
226 if (!FLAC__stream_decoder_process_single(mDecoder))
227 break;
228
229 if (FLAC__stream_decoder_get_state(mDecoder) == FLAC__STREAM_DECODER_END_OF_STREAM)
230 break;
231 }
232
233 return numSamples - mData.samplesToRead;
234 }
235
236 void FLACDecoder::close()
237 {
238 if (mDecoder != nullptr)
239 {
240 FLAC__stream_decoder_finish(mDecoder);
241 FLAC__stream_decoder_delete(mDecoder);
242 mDecoder = nullptr;
243 }
244 }
245}
246