diff --git a/CMakeLists.txt b/CMakeLists.txt index 6fe1ca7..7f4e5ee 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,8 +8,10 @@ function(em_file name) ${CMAKE_SOURCE_DIR}/decoder.cpp ${CMAKE_SOURCE_DIR}/${name}.cpp -o ${CMAKE_BINARY_DIR}/${name}.js - -s WASM=0 - -g4 + -s FILESYSTEM=0 + -s ENVIRONMENT=web + -Oz + --llvm-lto 1 ) endfunction(em_file) diff --git a/decoder.cpp b/decoder.cpp index 8ea3656..e4c7d0e 100644 --- a/decoder.cpp +++ b/decoder.cpp @@ -49,15 +49,21 @@ Decoder::~Decoder() delete[] glue; } -void Decoder::addFragment(intptr_t bufferPtr, uint32_t length) +void Decoder::addFragment(const emscripten::val& array) { + uint32_t length = array["length"].as(); + if (length < GLUE_LENGTH / 2) { - std::cout << "An attempt to add fragment smaller then half of the glue buffer, ignoring"; + std::cout << "Error: an attempt to add fragment smaller then half of the glue buffer, ignoring"; return; } - std::cout << "Adding new fragment " << length << " bytes long" << std::endl; - uint8_t* buffer = (uint8_t(*))bufferPtr; - RawBuffer rb = {buffer, length, 0, 0}; + uint8_t* buffer = new uint8_t[length]; + + for (int i = 0; i < length; ++i) { + buffer[i] = array[std::to_string(i)].as(); + } + + RawBuffer rb = {buffer, length}; pending.push_back(rb); switch (state) { @@ -111,9 +117,7 @@ emscripten::val Decoder::decode(uint32_t count) for (int i = 0; success < available; ++i) { int res = mad_frame_decode(frame, stream); - if (res == 0) { - ++success; - } else { + if (res != 0) { if (MAD_RECOVERABLE(stream->error)) { std::cout << "Unexpected error during the decoding process: " << mad_stream_errorstr(stream) << std::endl; @@ -131,11 +135,13 @@ emscripten::val Decoder::decode(uint32_t count) chans[k].set(std::to_string(success * samplesPerFrame + j), emscripten::val(value)); } } + ++success; } cachedLength -= available; + #if DEBUGGING std::cout << "Processed " << available << " frames, " << success << " successfully, last error " << mad_stream_errorstr(stream) << std::endl; - + #endif if (cachedLength == 0) { cached = false; prepareNextBuffer(); @@ -165,6 +171,7 @@ uint32_t Decoder::framesLeft(uint32_t max) mad_header ph; initializeProbe(probe); mad_header_init(&ph); + sampleRate = 0; while (cachedLength < max) { if (mad_header_decode(&ph, &probe) == 0) { @@ -174,14 +181,24 @@ uint32_t Decoder::framesLeft(uint32_t max) samplesPerFrame = MAD_NSBSAMPLES(&ph) * 32; //not sure why 32, it's in libmad source } else { if (sampleRate != ph.samplerate || channels != MAD_NCHANNELS(&ph) || samplesPerFrame != MAD_NSBSAMPLES(&ph) * 32) { - break; + if (cachedLength > 0) { + #if DEBUGGING + std::cout << "sample rate " << sampleRate << " -> " << ph.samplerate << std::endl; + std::cout << "channels " << channels << " -> " << MAD_NCHANNELS(&ph) << std::endl; + std::cout << "samples per frame " << samplesPerFrame << " -> " << MAD_NSBSAMPLES(&ph) * 32 << std::endl; + #endif + probe.next_frame = probe.this_frame; + break; + } } } if (probe.next_frame > probe.this_frame) { ++cachedLength; } } else { + #if DEBUGGING std::cout << "framesLeft error: " << mad_stream_errorstr(&probe) << std::endl; + #endif if (!MAD_RECOVERABLE(probe.error)) { break; } @@ -193,7 +210,9 @@ uint32_t Decoder::framesLeft(uint32_t max) cachedError = probe.error; mad_header_finish(&ph); mad_stream_finish(&probe); + #if DEBUGGING std::cout << cachedLength << " frames are available for decoding" << std::endl; + #endif cached = true; } @@ -227,7 +246,9 @@ void Decoder::changeBuffer() std::cout << "Wrong state on switchBuffer method - onGlueHalf, aborting" << std::endl; break; case onGlueFull: + #if DEBUGGING std::cout << "Having another fragment " << pending[0].length << " bytes long" << std::endl; + #endif switchBuffer(pending[0].ptr, pending[0].length); @@ -269,7 +290,7 @@ void Decoder::initializeProbe(mad_stream& probe) probe.buffer = stream->buffer; probe.bufend = stream->bufend; - //probe.skiplen = stream->skiplen; + probe.skiplen = stream->skiplen; //probe.sync = stream->sync; //probe.freerate = stream->freerate; //probe.this_frame = stream->this_frame; @@ -289,11 +310,15 @@ void Decoder::initializeProbe(mad_stream& probe) void Decoder::switchToGlue() { + #if DEBUGGING std::cout << "Switching to glue" << std::endl; + #endif switchBuffer(glue, GLUE_LENGTH); + #if DEBUGGING std::cout << "Freeing the drained fragment" << std::endl; - free(pending[0].ptr); + #endif + delete[] pending[0].ptr; pending.pop_front(); } @@ -302,7 +327,7 @@ void Decoder::switchBuffer(uint8_t* bufferPtr, uint32_t length) uint32_t left; if (stream->error != MAD_ERROR_BUFLEN) { - std::cout << "WARNING: Switching buffers while the previous one is not drained, error: " << mad_stream_errorstr(stream) << std::endl; + std::cout << "WARNING: Switching buffers while the previous one is not drained, last error: " << mad_stream_errorstr(stream) << std::endl; } if (stream->next_frame != NULL) { left = stream->bufend - stream->next_frame; diff --git a/decoder.h b/decoder.h index 5a8bc9b..3f030e6 100644 --- a/decoder.h +++ b/decoder.h @@ -16,7 +16,7 @@ public: Decoder(); ~Decoder(); - void addFragment(intptr_t bufferPtr, uint32_t length); + void addFragment(const emscripten::val& array); emscripten::val decode(uint32_t count = UINT32_MAX); bool hasMore() const; uint32_t framesLeft(uint32_t max = UINT32_MAX); @@ -34,8 +34,6 @@ private: struct RawBuffer { uint8_t* ptr; uint32_t length; - uint32_t offset; - uint32_t gueard; }; State state; diff --git a/index.html b/index.html index ca3eaba..f6fd8b9 100644 --- a/index.html +++ b/index.html @@ -12,14 +12,13 @@