| 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 | |
| 6 | namespace 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 = frameSamples - data->samplesToRead; |
| 82 | UINT32 = 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 | |