From b272bf6b64f4229d086bb0340987fb57daddb31f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20=C3=96nnerby?= Date: Fri, 31 Oct 2008 14:42:07 +0000 Subject: [PATCH] Continued on the FLAC decoder. --- src/contrib/flacdecoder/FLACDecoder.cpp | 93 ++++++++++++++++++++++--- src/contrib/flacdecoder/FLACDecoder.h | 13 ++++ 2 files changed, 95 insertions(+), 11 deletions(-) diff --git a/src/contrib/flacdecoder/FLACDecoder.cpp b/src/contrib/flacdecoder/FLACDecoder.cpp index bbad360f4..d4964aa3c 100644 --- a/src/contrib/flacdecoder/FLACDecoder.cpp +++ b/src/contrib/flacdecoder/FLACDecoder.cpp @@ -32,9 +32,16 @@ ////////////////////////////////////////////////////////////////////////////// #include "StdAfx.h" #include "FLACDecoder.h" +#include FLACDecoder::FLACDecoder() :decoder(NULL) + ,outputBufferSize(0) + ,outputBuffer(NULL) + ,channels(0) + ,sampleRate(0) + ,bps(0) + ,totalSamples(0) { /* this->flacCallbacks.read = &FlacRead; this->flacCallbacks.seek = &FlacSeek; @@ -51,6 +58,10 @@ FLACDecoder::~FLACDecoder(){ FLAC__stream_decoder_delete(this->decoder); this->decoder = NULL; } + if(this->outputBuffer){ + delete this->outputBuffer; + this->outputBuffer = NULL; + } } @@ -117,39 +128,83 @@ bool FLACDecoder::Open(musik::core::filestreams::IFileStream *fileStream){ &FlacTell, &FlacFileSize, &FlacEof, - NULL, + &FlacWrite, NULL, NULL, this); if(init_status == FLAC__STREAM_DECODER_INIT_STATUS_OK) { - + // Process until we have metadata + FLAC__stream_decoder_process_until_end_of_metadata(this->decoder); + return true; } return false; } +void FLACDecoder::FlacMeta(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *clientData){ + FLACDecoder *thisPtr = (FLACDecoder*)clientData; + + if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) { + thisPtr->totalSamples = metadata->data.stream_info.total_samples; + thisPtr->sampleRate = metadata->data.stream_info.sample_rate; + thisPtr->channels = metadata->data.stream_info.channels; + thisPtr->bps = metadata->data.stream_info.bits_per_sample; + } +} + + +FLAC__StreamDecoderWriteStatus FLACDecoder::FlacWrite(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame,const FLAC__int32 *const buffer[], void *clientData){ + + FLACDecoder *thisPtr = (FLACDecoder*)clientData; + + // First, lets create a buffer + // If there is already a buffer, delete it + if(thisPtr->outputBuffer && thisPtr->outputBufferSize==0){ + delete thisPtr->outputBuffer; + thisPtr->outputBuffer = NULL; + } + + int nofSamples = thisPtr->channels*frame->header.blocksize; + thisPtr->outputBuffer = new float[nofSamples]; + thisPtr->outputBufferSize = 0; + + // What is the max amplitude + float maxAmplitude = pow(2.0f,(thisPtr->bps-1)); + + // Convert the buffer (16bit int) to the outputBuffer (float) + for(unsigned int i(0); iheader.blocksize; ++i){ + for(int j(0); jchannels; ++j){ + thisPtr->outputBuffer[i] = (((float)buffer[j][i])/maxAmplitude); + } + thisPtr->outputBufferSize++; + } + + return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; +} + void FLACDecoder::Destroy(void){ delete this; } bool FLACDecoder::GetFormat(unsigned long * SampleRate, unsigned long * Channels){ -/* vorbis_info *info = ov_info(&this->oggFile,-1); - if(info){ - *SampleRate = info->rate; - *Channels = info->channels; + *SampleRate = this->sampleRate; + *Channels = this->channels; + + if(*SampleRate && *Channels){ return true; - }*/ + } + return false; } bool FLACDecoder::GetLength(unsigned long * MS){ -/* double time = ov_time_total(&this->oggFile, 0); - if( time!=OV_EINVAL ){ - *MS = (unsigned long)(time * 1000.0); + if(this->totalSamples && this->sampleRate){ + *MS = this->totalSamples/this->sampleRate; return true; - }*/ + } + return false; } @@ -172,5 +227,21 @@ bool FLACDecoder::SetState(unsigned long State){ } bool FLACDecoder::GetBuffer(float ** ppBuffer, unsigned long * NumSamples){ + if(this->outputBuffer && this->outputBufferSize>0){ + *ppBuffer = this->outputBuffer; + *NumSamples = this->outputBufferSize; + this->outputBufferSize = 0; + return true; + } + + if( FLAC__stream_decoder_process_single(this->decoder) ){ + if(this->outputBuffer && this->outputBufferSize>0){ + *ppBuffer = this->outputBuffer; + *NumSamples = this->outputBufferSize; + this->outputBufferSize = 0; + return true; + } + } + return false; } diff --git a/src/contrib/flacdecoder/FLACDecoder.h b/src/contrib/flacdecoder/FLACDecoder.h index 3517ec595..f1b3149c5 100644 --- a/src/contrib/flacdecoder/FLACDecoder.h +++ b/src/contrib/flacdecoder/FLACDecoder.h @@ -69,9 +69,22 @@ public: static FLAC__StreamDecoderLengthStatus FlacFileSize(const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *clientData); + static FLAC__StreamDecoderWriteStatus FlacWrite(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame,const FLAC__int32 *const buffer[], void *clientData); + static void FlacMeta(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *clientData); + + protected: musik::core::filestreams::IFileStream *fileStream; FLAC__StreamDecoder *decoder; + + long channels; + long sampleRate; + long totalSamples; + int bps; + + float *outputBuffer; + unsigned long outputBufferSize; + // FLAC__IOCallbacks flacCallbacks; };