diff --git a/src/AACDecoderHelix.h b/src/AACDecoderHelix.h index a3580dd..ab58937 100644 --- a/src/AACDecoderHelix.h +++ b/src/AACDecoderHelix.h @@ -3,8 +3,8 @@ #include "CommonHelix.h" #include "libhelix-aac/aacdec.h" -#define AAC_MAX_OUTPUT_SIZE 2048 -#define AAC_MAX_FRAME_SIZE 1600 +#define AAC_MAX_OUTPUT_SIZE 1024 * 3 +#define AAC_MAX_FRAME_SIZE 2100 namespace libhelix { @@ -19,24 +19,20 @@ typedef void (*AACDataCallback)(_AACFrameInfo &info,short *pwm_buffer, size_t le */ class AACDecoderHelix : public CommonHelix { public: - AACDecoderHelix() { - decoder = AACInitDecoder(); - } + AACDecoderHelix() = default; #ifdef ARDUINO AACDecoderHelix(Print &output, AACInfoCallback infoCallback=nullptr){ - decoder = AACInitDecoder(); this->out = &output; this->infoCallback = infoCallback; } #endif AACDecoderHelix(AACDataCallback dataCallback){ - decoder = AACInitDecoder(); this->pwmCallback = dataCallback; } - ~AACDecoderHelix(){ - AACFreeDecoder(decoder); + virtual ~AACDecoderHelix(){ + end(); } @@ -50,10 +46,11 @@ class AACDecoderHelix : public CommonHelix { /// Releases the reserved memory - void end(){ - LOG(Debug, "end"); - if (CommonHelix::active){ + virtual void end() override { + LOG_HELIX(Debug, "end"); + if (decoder!=nullptr){ AACFreeDecoder(decoder); + decoder = nullptr; } CommonHelix::end(); } @@ -69,22 +66,29 @@ class AACDecoderHelix : public CommonHelix { AACInfoCallback infoCallback = nullptr; _AACFrameInfo aacFrameInfo; - size_t maxFrameSize(){ + /// Allocate the decoder + virtual void allocateDecoder() override { + if (decoder==nullptr){ + decoder = AACInitDecoder(); + } + } + + size_t maxFrameSize() override { return max_frame_size == 0 ? AAC_MAX_FRAME_SIZE : max_frame_size; } - size_t maxPWMSize() { + size_t maxPWMSize() override { return max_pwm_size == 0 ? AAC_MAX_OUTPUT_SIZE : max_pwm_size; } - int findSynchWord(int offset=0) { + int findSynchWord(int offset=0) override { int result = AACFindSyncWord(frame_buffer+offset, buffer_size)+offset; return result < 0 ? result : result + offset; } /// decods the data and removes the decoded frame from the buffer - void decode(Range r) { - LOG(Debug, "decode %d", r.end); + void decode(Range r) override { + LOG_HELIX(Debug, "decode %d", r.end); int len = buffer_size - r.start; int bytesLeft = len; uint8_t* ptr = frame_buffer + r.start; @@ -93,8 +97,8 @@ class AACDecoderHelix : public CommonHelix { int decoded = len - bytesLeft; assert(decoded == ptr-(frame_buffer + r.start)); if (result==0){ - LOG(Debug, "-> bytesLeft %d -> %d = %d ", buffer_size, bytesLeft, decoded); - LOG(Debug, "-> End of frame (%d) vs end of decoding (%d)", r.end, decoded) + LOG_HELIX(Debug, "-> bytesLeft %d -> %d = %d ", buffer_size, bytesLeft, decoded); + LOG_HELIX(Debug, "-> End of frame (%d) vs end of decoding (%d)", r.end, decoded) // return the decoded result _AACFrameInfo info; @@ -106,14 +110,14 @@ class AACDecoderHelix : public CommonHelix { buffer_size -= decoded; //assert(buffer_size<=maxFrameSize()); memmove(frame_buffer, frame_buffer+r.start+decoded, buffer_size); - LOG(Debug, " -> decoded %d bytes - remaining buffer_size: %d", decoded, buffer_size); + LOG_HELIX(Debug, " -> decoded %d bytes - remaining buffer_size: %d", decoded, buffer_size); } else { - LOG(Warning, " -> decoded %d > buffersize %d", decoded, buffer_size); + LOG_HELIX(Warning, " -> decoded %d > buffersize %d", decoded, buffer_size); buffer_size = 0; } } else { // decoding error - LOG(Debug, " -> decode error: %d - removing frame!", result); + LOG_HELIX(Debug, " -> decode error: %d - removing frame!", result); int ignore = decoded; if (ignore == 0) ignore = r.end; // We advance to the next synch world @@ -123,13 +127,12 @@ class AACDecoderHelix : public CommonHelix { } else { buffer_size = 0; } - } } // return the result PWM data void provideResult(_AACFrameInfo &info){ - LOG(Debug, "provideResult: %d samples",info.outputSamps); + LOG_HELIX(Debug, "provideResult: %d samples",info.outputSamps); if (info.outputSamps>0){ // provide result if(pwmCallback!=nullptr){ diff --git a/src/CommonHelix.h b/src/CommonHelix.h index 7b418f9..c1a6387 100644 --- a/src/CommonHelix.h +++ b/src/CommonHelix.h @@ -77,16 +77,19 @@ class CommonHelix { if (active){ end(); } + + allocateDecoder(); + if (frame_buffer == nullptr) { - LOG(Info,"allocating frame_buffer with %zu bytes", maxFrameSize()); + LOG_HELIX(Info,"allocating frame_buffer with %zu bytes", maxFrameSize()); frame_buffer = new uint8_t[maxFrameSize()]; } if (pwm_buffer == nullptr) { - LOG(Info,"allocating pwm_buffer with %zu bytes", maxPWMSize()); + LOG_HELIX(Info,"allocating pwm_buffer with %zu bytes", maxPWMSize()); pwm_buffer = new short[maxPWMSize()]; } if (pwm_buffer==nullptr || frame_buffer==nullptr){ - LOG(Error, "Not enough memory for buffers"); + LOG_HELIX(Error, "Not enough memory for buffers"); active = false; return; } @@ -108,7 +111,7 @@ class CommonHelix { */ virtual size_t write(const void *in_ptr, size_t in_size) { - LOG(Debug, "write %zu", in_size); + LOG_HELIX(Debug, "write %zu", in_size); size_t start = 0; if (active){ uint8_t* ptr8 = (uint8_t* )in_ptr; @@ -118,7 +121,7 @@ class CommonHelix { // we have some space left in the buffer int written_len = writeFrame(ptr8+start, write_len); start += written_len; - LOG(Info,"-> Written %zu of %zu - Counter %zu", start, in_size, frame_counter); + LOG_HELIX(Info,"-> Written %zu of %zu - Counter %zu", start, in_size, frame_counter); write_len = min(in_size - start, static_cast(maxFrameSize()-buffer_size)); // add delay - e.g. needed by esp32 and esp8266 if (delay_ms>0){ @@ -126,7 +129,7 @@ class CommonHelix { } } } else { - LOG(Warning, "CommonHelix not active"); + LOG_HELIX(Warning, "CommonHelix not active"); } return start; @@ -156,6 +159,8 @@ class CommonHelix { Print *out = nullptr; #endif + virtual void allocateDecoder() = 0; + /// Provides the maximum frame size - this is allocated on the heap and you can reduce the heap size my minimizing this value virtual size_t maxFrameSize() = 0; @@ -180,23 +185,23 @@ class CommonHelix { /// we add the data to the buffer until it is full size_t appendToBuffer(const void *in_ptr, int in_size){ - LOG(Info, "appendToBuffer: %d (at %p)", in_size, frame_buffer); + LOG_HELIX(Info, "appendToBuffer: %d (at %p)", in_size, frame_buffer); int buffer_size_old = buffer_size; int process_size = min((int)(maxFrameSize() - buffer_size), in_size); memmove(frame_buffer+buffer_size, in_ptr, process_size); buffer_size += process_size; if (buffer_size>maxFrameSize()){ - LOG(Error, "Increase MAX_FRAME_SIZE > %zu", buffer_size); + LOG_HELIX(Error, "Increase MAX_FRAME_SIZE > %zu", buffer_size); } assert(buffer_size<=maxFrameSize()); - LOG(Debug, "appendToBuffer %d + %d -> %u", buffer_size_old, process_size, buffer_size ); + LOG_HELIX(Debug, "appendToBuffer %d + %d -> %u", buffer_size_old, process_size, buffer_size ); return process_size; } /// appends the data to the frame buffer and decodes size_t writeFrame(const void *in_ptr, size_t in_size){ - LOG(Debug, "writeFrame %zu", in_size); + LOG_HELIX(Debug, "writeFrame %zu", in_size); size_t result = 0; // in the beginning we ingnore all data until we found the first synch word result = appendToBuffer(in_ptr, in_size); @@ -205,7 +210,7 @@ class CommonHelix { if(r.isValid(maxFrameSize())){ decode(r); } else { - LOG(Warning, " -> invalid frame size: %d / max: %d", (int) r.end-r.start, (int) maxFrameSize()); + LOG_HELIX(Warning, " -> invalid frame size: %d / max: %d", (int) r.end-r.start, (int) maxFrameSize()); } frame_counter++; return result; @@ -213,31 +218,31 @@ class CommonHelix { /// returns valid start and end synch word. Range synchronizeFrame() { - LOG(Debug, "synchronizeFrame"); + LOG_HELIX(Debug, "synchronizeFrame"); Range range = frameRange(); if (range.start<0){ // there is no Synch in the buffer at all -> we can ignore all data range.end = -1; - LOG(Debug, "-> no synch") + LOG_HELIX(Debug, "-> no synch") if (buffer_size==maxFrameSize()) { buffer_size = 0; - LOG(Debug, "-> buffer cleared"); + LOG_HELIX(Debug, "-> buffer cleared"); } } else if (range.start>0) { // make sure that buffer starts with a synch word - LOG(Debug, "-> moving to new start %d",range.start); + LOG_HELIX(Debug, "-> moving to new start %d",range.start); buffer_size -= range.start; assert(buffer_size<=maxFrameSize()); memmove(frame_buffer, frame_buffer + range.start, buffer_size); range.end -= range.start; range.start = 0; - LOG(Debug, "-> we are at beginning of synch word"); + LOG_HELIX(Debug, "-> we are at beginning of synch word"); } else if (range.start==0) { - LOG(Debug, "-> we are at beginning of synch word"); + LOG_HELIX(Debug, "-> we are at beginning of synch word"); if (range.end<0 && buffer_size == maxFrameSize()){ buffer_size = 0; - LOG(Debug, "-> buffer cleared"); + LOG_HELIX(Debug, "-> buffer cleared"); } } return range; @@ -248,7 +253,7 @@ class CommonHelix { Range result; result.start = findSynchWord(0); result.end = findSynchWord(result.start+SYNCH_WORD_LEN); - LOG(Debug, "-> frameRange -> %d - %d", result.start, result.end); + LOG_HELIX(Debug, "-> frameRange -> %d - %d", result.start, result.end); return result; } diff --git a/src/MP3DecoderHelix.h b/src/MP3DecoderHelix.h index b2fb3ef..624c4af 100644 --- a/src/MP3DecoderHelix.h +++ b/src/MP3DecoderHelix.h @@ -26,34 +26,29 @@ class MP3DecoderHelix : public CommonHelix { public: MP3DecoderHelix(){ - decoder = MP3InitDecoder(); this->mp3_type = MP3Normal; } #ifdef ARDUINO MP3DecoderHelix(Print &output, MP3Type mp3Type=MP3Normal, MP3InfoCallback infoCallback=nullptr){ - decoder = MP3InitDecoder(); this->out = &output; this->infoCallback = infoCallback; this->mp3_type = mp3Type; } #endif MP3DecoderHelix(MP3DataCallback dataCallback, MP3Type mp3Type=MP3Normal){ - decoder = MP3InitDecoder(); this->pwmCallback = dataCallback; this->mp3_type = mp3Type; } MP3DecoderHelix(MP3Type mp3Type){ - decoder = MP3InitDecoder(); this->mp3_type = mp3Type; } - ~MP3DecoderHelix(){ - MP3FreeDecoder(decoder); + virtual ~MP3DecoderHelix(){ + end(); } - void setInfoCallback(MP3InfoCallback cb){ this->infoCallback = cb; } @@ -67,6 +62,15 @@ class MP3DecoderHelix : public CommonHelix { return mp3FrameInfo; } + /// Releases the reserved memory + virtual void end() override { + LOG_HELIX(Debug, "end"); + if (decoder!=nullptr){ + MP3FreeDecoder(decoder); + decoder = nullptr; + } + CommonHelix::end(); + } protected: HMP3Decoder decoder = nullptr; @@ -75,25 +79,32 @@ class MP3DecoderHelix : public CommonHelix { MP3Type mp3_type; MP3FrameInfo mp3FrameInfo; + /// Allocate the decoder + virtual void allocateDecoder() override { + if (decoder==nullptr){ + decoder = MP3InitDecoder(); + } + } + /// determines the frame buffer size that will be allocated - size_t maxFrameSize(){ + size_t maxFrameSize() override { return max_frame_size == 0 ? MP3_MAX_FRAME_SIZE : max_frame_size; } /// Determines the pwm buffer size that will be allocated - size_t maxPWMSize() { + size_t maxPWMSize() override { return max_pwm_size == 0 ? MP3_MAX_OUTPUT_SIZE : max_pwm_size; } /// Finds the synch word in the available buffer data starting from the indicated offset - int findSynchWord(int offset=0) { + int findSynchWord(int offset=0) override { int result = MP3FindSyncWord(frame_buffer+offset, buffer_size); return result < 0 ? result : result + offset; } /// decods the data - void decode(Range r) { - LOG(Debug, "decode %d", r.end); + void decode(Range r) override { + LOG_HELIX(Debug, "decode %d", r.end); int len = buffer_size - r.start; int bytesLeft = len; uint8_t* ptr = frame_buffer + r.start; @@ -102,8 +113,8 @@ class MP3DecoderHelix : public CommonHelix { int decoded = len - bytesLeft; if (result==0){ - LOG(Debug, "-> bytesLeft %d -> %d = %d ", buffer_size, bytesLeft, decoded); - LOG(Debug, "-> End of frame (%d) vs end of decoding (%d)", r.end, decoded) + LOG_HELIX(Debug, "-> bytesLeft %d -> %d = %d ", buffer_size, bytesLeft, decoded); + LOG_HELIX(Debug, "-> End of frame (%d) vs end of decoding (%d)", r.end, decoded) // return the decoded result MP3FrameInfo info; @@ -115,14 +126,14 @@ class MP3DecoderHelix : public CommonHelix { buffer_size -= decoded; //assert(buffer_size<=maxFrameSize()); memmove(frame_buffer, frame_buffer+r.start+decoded, buffer_size); - LOG(Debug, " -> decoded %d bytes - remaining buffer_size: %d", decoded, buffer_size); + LOG_HELIX(Debug, " -> decoded %d bytes - remaining buffer_size: %d", decoded, buffer_size); } else { - LOG(Warning, " -> decoded %d > buffersize %d", decoded, buffer_size); + LOG_HELIX(Warning, " -> decoded %d > buffersize %d", decoded, buffer_size); buffer_size = 0; } } else { // decoding error - LOG(Debug, " -> decode error: %d - removing frame!", result); + LOG_HELIX(Debug, " -> decode error: %d - removing frame!", result); int ignore = decoded; if (ignore == 0) ignore = r.end; // We advance to the next synch world @@ -141,7 +152,7 @@ class MP3DecoderHelix : public CommonHelix { // increase PWM size if this fails assert(info.outputSamps provideResult: %d", info.outputSamps); + LOG_HELIX(Debug, "=> provideResult: %d", info.outputSamps); if (info.outputSamps>0){ // provide result if(pwmCallback!=nullptr){ diff --git a/src/helix_log.h b/src/helix_log.h index a71cede..60566bc 100644 --- a/src/helix_log.h +++ b/src/helix_log.h @@ -15,12 +15,12 @@ // Logging Implementation #if HELIX_LOGGING_ACTIVE == true - static char log_buffer[512]; - enum LogLevel {Debug, Info, Warning, Error}; - static LogLevel minLogLevel = HELIX_LOG_LEVEL; + static char log_buffer_helix[512]; + enum LogLevelHelix {Debug, Info, Warning, Error}; + static LogLevelHelix minLogLevelHelix = HELIX_LOG_LEVEL; // We print the log based on the log level - #define LOG(level,...) { if(level>=minLogLevel) { int l = snprintf(log_buffer,512, __VA_ARGS__); HELIX_LOGGING_OUT.write("libhelix - "); HELIX_LOGGING_OUT.write(log_buffer,l); HELIX_LOGGING_OUT.println(); } } + #define LOG_HELIX(level,...) { if(level>=minLogLevelHelix) { int l = snprintf(log_buffer_helix,512, __VA_ARGS__); HELIX_LOGGING_OUT.write("libhelix - "); HELIX_LOGGING_OUT.write(log_buffer_helix,l); HELIX_LOGGING_OUT.println(); } } #else // Remove all log statments from the code - #define LOG(...) + #define LOG_HELIX(...) #endif