diff --git a/src/FlacDecoder.cpp b/src/FlacDecoder.cpp index e91ba36..32051be 100644 --- a/src/FlacDecoder.cpp +++ b/src/FlacDecoder.cpp @@ -89,6 +89,63 @@ public: } } + + FlacDecoderInternal(AudioData * d, const std::vector & memory) : d(d), data(std::move(memory)), dataPos(0) + { + + ///////////////////////////// + // Initialize FLAC library // + ///////////////////////////// + + decoderInternal = FLAC__stream_decoder_new(); + + FLAC__stream_decoder_set_metadata_respond(decoderInternal, FLAC__METADATA_TYPE_STREAMINFO); + + bool initialized = FLAC__stream_decoder_init_stream( + decoderInternal, + read_callback, + seek_callback, + tell_callback, + length_callback, + eof_callback, + s_writeCallback, + s_metadataCallback, + s_errorCallback, + this + ) == FLAC__STREAM_DECODER_INIT_STATUS_OK; + + FLAC__stream_decoder_set_md5_checking(decoderInternal, true); + + ////////////////////// + // Read Stream Data // + ///////////////////// + + if (initialized) + { + // Find the size and allocate memory + FLAC__stream_decoder_process_until_end_of_metadata(decoderInternal); + + // Read memory out into our temporary internalBuffer + FLAC__stream_decoder_process_until_end_of_stream(decoderInternal); + + // Presently unneeded, but useful for reference + // FLAC__ChannelAssignment channelAssignment = FLAC__stream_decoder_get_channel_assignment(decoderInternal); + + // Fill out remaining user data + d->lengthSeconds = (float) numSamples / (float) d->sampleRate; + + auto totalSamples = numSamples * d->channelCount; + + // Next, process internal buffer into the user-visible samples array + ConvertToFloat32(d->samples.data(), internalBuffer.data(), totalSamples, d->sourceFormat); + } + + else + { + throw std::runtime_error("Unable to initialize FLAC decoder"); + } + + } ~FlacDecoderInternal() { @@ -148,12 +205,51 @@ public: { std::cerr << "FLAC Decoder Error: " << FLAC__StreamDecoderErrorStatusString[status] << std::endl; } + + static FLAC__StreamDecoderReadStatus read_callback(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data) { + FlacDecoderInternal *decoderInternal = (FlacDecoderInternal *)client_data; + size_t readLength = std::min(*bytes, decoderInternal->data.size() - decoderInternal->dataPos); + if (readLength > 0) { + memcpy(buffer, decoderInternal->data.data(), readLength); + decoderInternal->dataPos += readLength; + *bytes = readLength; + if (decoderInternal->dataPos < decoderInternal->data.size()) { + return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; + } else { + return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; + } + } else { + return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; + } + } + static FLAC__StreamDecoderSeekStatus seek_callback(const FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data) { + FlacDecoderInternal *decoderInternal = (FlacDecoderInternal *)client_data; + size_t newPos = std::min(absolute_byte_offset, decoderInternal->data.size() - decoderInternal->dataPos); + decoderInternal->dataPos = newPos; + return FLAC__STREAM_DECODER_SEEK_STATUS_OK; + } + static FLAC__StreamDecoderTellStatus tell_callback(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data) { + FlacDecoderInternal *decoderInternal = (FlacDecoderInternal *)client_data; + *absolute_byte_offset = decoderInternal->dataPos; + return FLAC__STREAM_DECODER_TELL_STATUS_OK; + } + static FLAC__StreamDecoderLengthStatus length_callback(const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data) { + FlacDecoderInternal *decoderInternal = (FlacDecoderInternal *)client_data; + *stream_length = decoderInternal->data.size(); + return FLAC__STREAM_DECODER_LENGTH_STATUS_OK; + } + static FLAC__bool eof_callback(const FLAC__StreamDecoder *decoder, void *client_data) { + FlacDecoderInternal *decoderInternal = (FlacDecoderInternal *)client_data; + return decoderInternal->dataPos == decoderInternal->data.size(); + } private: NO_COPY(FlacDecoderInternal); FLAC__StreamDecoder * decoderInternal; + std::vector data; + size_t dataPos; size_t bufferPosition = 0; size_t numSamples = 0; @@ -174,7 +270,7 @@ void FlacDecoder::LoadFromPath(AudioData * data, const std::string & path) void FlacDecoder::LoadFromBuffer(AudioData * data, const std::vector & memory) { - throw LoadBufferNotImplEx(); + FlacDecoderInternal decoder(data, memory); } std::vector FlacDecoder::GetSupportedFileExtensions()