The USE_STACK_HACK #define allocates and free's huge blocks of data (always the same size) which the allocator seems to have problems with over time. If the microcontroller is using the encoder for just a single thread (this is the common use case) then the primebuff0 and primebuff1 buffers can just be recycled.
This is the fix I am using on my own code.
In config.h
// If you know the encoder will be used in a single threaded environment, you can use this hack to just
// recycle the memory. This will prevent memory fragmentation. Only use this if you are sure that the
// encoder will be called from a single thread.
#ifndef USE_STACK_HACK_RECYCLE_ALLOCATION_SINGLE_THREADED
#define USE_STACK_HACK_RECYCLE_ALLOCATION_SINGLE_THREADED 0
#endif
Then in encoder.c
static void
lame_encode_frame_init(lame_internal_flags *gfc, const sample_t *const inbuf[2])
{
DEBUGF(gfc, __FUNCTION__);
SessionConfig_t const *const cfg = &gfc->cfg;
int ch, gr;
if (gfc->lame_encode_frame_init == 0)
{
#if USE_STACK_HACK
#if USE_STACK_HACK_RECYCLE_ALLOCATION_SINGLE_THREADED
if (primebuff0 == NULL)
primebuff0 = lame_calloc(sample_t, 286 + 1152 + 576);
if (primebuff1 == NULL)
primebuff1 = lame_calloc(sample_t, 286 + 1152 + 576);
#else
primebuff0 = lame_calloc(sample_t, 286 + 1152 + 576);
primebuff1 = lame_calloc(sample_t, 286 + 1152 + 576);
#endif
#else
sample_t primebuff0[286 + 1152 + 576];
sample_t primebuff1[286 + 1152 + 576];
memset(primebuff0, 0, sizeof(primebuff0));
memset(primebuff1, 0, sizeof(primebuff1));
#endif
int const framesize = 576 * cfg->mode_gr;
/* prime the MDCT/polyphase filterbank with a short block */
int i, j;
gfc->lame_encode_frame_init = 1;
for (i = 0, j = 0; i < 286 + 576 * (1 + cfg->mode_gr); ++i)
{
if (i < framesize)
{
primebuff0[i] = 0;
if (cfg->channels_out == 2)
primebuff1[i] = 0;
}
else
{
primebuff0[i] = inbuf[0][j];
if (cfg->channels_out == 2)
primebuff1[i] = inbuf[1][j];
++j;
}
}
/* polyphase filtering / mdct */
for (gr = 0; gr < cfg->mode_gr; gr++)
{
for (ch = 0; ch < cfg->channels_out; ch++)
{
gfc->l3_side.tt[gr][ch].block_type = SHORT_TYPE;
}
}
mdct_sub48(gfc, primebuff0, primebuff1);
/* check FFT will not use a negative starting offset */
#if 576 < FFTOFFSET
#error FFTOFFSET greater than 576: FFT uses a negative offset
#endif
#if USE_STACK_HACK
#if USE_STACK_HACK_RECYCLE_ALLOCATION_SINGLE_THREADED
memset(primebuff0, 0, sizeof(sample_t) * (286 + 1152 + 576));
memset(primebuff1, 0, sizeof(sample_t) * (286 + 1152 + 576));
#else
lame_free(primebuff0);
lame_free(primebuff1);
primebuff1 = NULL;
primebuff0 = NULL;
#endif
#endif
/* check if we have enough data for FFT */
assert(gfc->sv_enc.mf_size >= (BLKSIZE + framesize - FFTOFFSET));
/* check if we have enough data for polyphase filterbank */
assert(gfc->sv_enc.mf_size >= (512 + framesize - 32));
}
}
The
USE_STACK_HACK
#define allocates and free's huge blocks of data (always the same size) which the allocator seems to have problems with over time. If the microcontroller is using the encoder for just a single thread (this is the common use case) then theprimebuff0
andprimebuff1
buffers can just be recycled.This is the fix I am using on my own code.
In
config.h
Then in
encoder.c