306 lines
9.3 KiB
C++
Executable File
306 lines
9.3 KiB
C++
Executable File
/* layer3.c */
|
|
|
|
#ifdef ESP32
|
|
|
|
#include "types.h"
|
|
#include "tables.h"
|
|
#include "layer3.h"
|
|
#include "l3subband.h"
|
|
#include "l3mdct.h"
|
|
#include "l3loop.h"
|
|
#include "bitstream.h"
|
|
#include "l3bitstream.h"
|
|
#include "esp_heap_caps.h"
|
|
#include "esp_system.h"
|
|
#include "freertos/FreeRTOS.h"
|
|
|
|
static uint32_t counter[5] = {0};
|
|
|
|
static int granules_per_frame[4] = {
|
|
1, /* MPEG 2.5 */
|
|
-1, /* Reserved */
|
|
1, /* MPEG II */
|
|
2 /* MPEG I */
|
|
};
|
|
|
|
/* Set default values for important vars */
|
|
void shine_set_config_mpeg_defaults(shine_mpeg_t *mpeg) {
|
|
mpeg->bitr = 128;
|
|
mpeg->emph = NONE;
|
|
mpeg->copyright = 0;
|
|
mpeg->original = 1;
|
|
}
|
|
|
|
int shine_mpeg_version(int samplerate_index) {
|
|
/* Pick mpeg version according to samplerate index. */
|
|
if (samplerate_index < 3) {
|
|
/* First 3 samplerates are for MPEG-I */
|
|
return MPEG_I;
|
|
} else if (samplerate_index < 6) {
|
|
/* Then it's MPEG-II */
|
|
return MPEG_II;
|
|
} else {
|
|
/* Finally, MPEG-2.5 */
|
|
return MPEG_25;
|
|
}
|
|
}
|
|
|
|
int shine_find_samplerate_index(int freq) {
|
|
int i;
|
|
|
|
for(i=0;i<9;i++) {
|
|
if(freq==samplerates[i]) return i;
|
|
}
|
|
return -1; /* error - not a valid samplerate for encoder */
|
|
}
|
|
|
|
int shine_find_bitrate_index(int bitr, int mpeg_version) {
|
|
int i;
|
|
|
|
for(i=0;i<16;i++) {
|
|
if(bitr==bitrates[i][mpeg_version]) return i;
|
|
}
|
|
return -1; /* error - not a valid samplerate for encoder */
|
|
}
|
|
|
|
int shine_check_config(int freq, int bitr) {
|
|
int samplerate_index, bitrate_index, mpeg_version;
|
|
|
|
samplerate_index = shine_find_samplerate_index(freq);
|
|
if (samplerate_index < 0) {
|
|
return -1;
|
|
}
|
|
mpeg_version = shine_mpeg_version(samplerate_index);
|
|
|
|
bitrate_index = shine_find_bitrate_index(bitr, mpeg_version);
|
|
if (bitrate_index < 0) {
|
|
return -1;
|
|
}
|
|
return mpeg_version;
|
|
}
|
|
|
|
int shine_samples_per_pass(shine_t s) {
|
|
return s->mpeg.granules_per_frame * GRANULE_SIZE;
|
|
}
|
|
|
|
/* Compute default encoding values. */
|
|
shine_global_config *shine_initialise(shine_config_t *pub_config) {
|
|
double avg_slots_per_frame;
|
|
shine_global_config *config;
|
|
int x, y;
|
|
if (shine_check_config(pub_config->wave.samplerate, pub_config->mpeg.bitr) < 0) {
|
|
return NULL;
|
|
}
|
|
|
|
config = (shine_global_config*)heap_caps_malloc(sizeof(shine_global_config), MALLOC_CAP_SPIRAM);
|
|
if (config == NULL) {
|
|
return config;
|
|
}
|
|
|
|
memset(config, 0, sizeof(shine_global_config));
|
|
|
|
#ifdef SHINE_DEBUG
|
|
printf("l3_enc & mdct_freq each: %d\n", sizeof(int32_t)*GRANULE_SIZE*MAX_GRANULES*MAX_CHANNELS);
|
|
#endif
|
|
|
|
for (x = 0; x < MAX_CHANNELS; x++) {
|
|
for (y = 0; y < MAX_GRANULES; y++) {
|
|
// 2 * 2 * 576 each
|
|
config->l3_enc[x][y] = (int*)heap_caps_malloc_prefer(4*GRANULE_SIZE, MALLOC_CAP_32BIT, MALLOC_CAP_SPIRAM|MALLOC_CAP_32BIT); //Significant performance hit in IRAM
|
|
if (!config->l3_enc[x][y]) {
|
|
// error should never occur because of spiram size
|
|
//config->l3_enc[x][y] = (int*)heap_caps_malloc(sizeof(int32_t)*GRANULE_SIZE,MALLOC_CAP_SPIRAM|MALLOC_CAP_32BIT);
|
|
}
|
|
config->mdct_freq[x][y] = (int*)heap_caps_malloc_prefer(4*GRANULE_SIZE, MALLOC_CAP_32BIT, MALLOC_CAP_SPIRAM|MALLOC_CAP_32BIT); //OK 1%
|
|
if (!config->mdct_freq[x][y]) {
|
|
// error
|
|
//config->mdct_freq[x][y] = (int*)heap_caps_malloc(sizeof(int32_t)*GRANULE_SIZE, MALLOC_CAP_SPIRAM|MALLOC_CAP_32BIT);
|
|
}
|
|
}
|
|
}
|
|
#ifdef SHINE_DEBUG
|
|
printf("l3loop struct: %d\n", sizeof(l3loop_t));
|
|
#endif
|
|
config->l3loop = (l3loop_t*)heap_caps_malloc(sizeof(l3loop_t), MALLOC_CAP_SPIRAM);
|
|
#ifdef SHINE_DEBUG
|
|
printf("xrsq & xrabs each: %d\n", sizeof(int)*GRANULE_SIZE);
|
|
#endif
|
|
config->l3loop->xrsq = (int*)heap_caps_malloc_prefer(4*GRANULE_SIZE, MALLOC_CAP_32BIT, MALLOC_CAP_SPIRAM|MALLOC_CAP_32BIT); //OK 0.5%
|
|
if (!config->l3loop->xrsq) {
|
|
// error
|
|
//config->l3loop->xrsq = (int*)heap_caps_malloc(sizeof(int32_t)*GRANULE_SIZE, MALLOC_CAP_SPIRAM|MALLOC_CAP_32BIT); //OK 0.5%
|
|
}
|
|
|
|
config->l3loop->xrabs = (int*)heap_caps_malloc_prefer(4*GRANULE_SIZE, MALLOC_CAP_32BIT, MALLOC_CAP_SPIRAM|MALLOC_CAP_32BIT); //OK 0.5%
|
|
if (!config->l3loop->xrabs) {
|
|
//config->l3loop->xrabs = (int*)heap_caps_malloc(sizeof(int32_t)*GRANULE_SIZE, MALLOC_CAP_SPIRAM|MALLOC_CAP_32BIT); //OK 0.5%
|
|
}
|
|
|
|
/*typedef struct {
|
|
int32_t *xr;
|
|
int32_t *xrsq[GRANULE_SIZE];
|
|
int32_t *xrabs[GRANULE_SIZE];
|
|
int32_t xrmax;
|
|
int32_t en_tot[MAX_GRANULES];
|
|
int32_t en[MAX_GRANULES][21];
|
|
int32_t xm[MAX_GRANULES][21];
|
|
int32_t xrmaxl[MAX_GRANULES];
|
|
double steptab[128];
|
|
int32_t steptabi[128];
|
|
int16_t int2idx[10000];
|
|
} l3loop_t;*/
|
|
|
|
shine_subband_initialise(config);
|
|
shine_mdct_initialise(config);
|
|
shine_loop_initialise(config);
|
|
|
|
/* Copy public config. */
|
|
config->wave.channels = pub_config->wave.channels;
|
|
config->wave.samplerate = pub_config->wave.samplerate;
|
|
config->mpeg.mode = pub_config->mpeg.mode;
|
|
config->mpeg.bitr = pub_config->mpeg.bitr;
|
|
config->mpeg.emph = pub_config->mpeg.emph;
|
|
config->mpeg.copyright = pub_config->mpeg.copyright;
|
|
config->mpeg.original = pub_config->mpeg.original;
|
|
|
|
/* Set default values. */
|
|
config->ResvMax = 0;
|
|
config->ResvSize = 0;
|
|
config->mpeg.layer = LAYER_III;
|
|
config->mpeg.crc = 0;
|
|
config->mpeg.ext = 0;
|
|
config->mpeg.mode_ext = 0;
|
|
config->mpeg.bits_per_slot = 8;
|
|
|
|
config->mpeg.samplerate_index = shine_find_samplerate_index(config->wave.samplerate);
|
|
config->mpeg.version = shine_mpeg_version(config->mpeg.samplerate_index);
|
|
config->mpeg.bitrate_index = shine_find_bitrate_index(config->mpeg.bitr, config->mpeg.version);
|
|
config->mpeg.granules_per_frame = granules_per_frame[config->mpeg.version];
|
|
|
|
/* Figure average number of 'slots' per frame. */
|
|
avg_slots_per_frame = ((double)config->mpeg.granules_per_frame * GRANULE_SIZE /
|
|
((double)config->wave.samplerate)) *
|
|
(1000*(double)config->mpeg.bitr /
|
|
(double)config->mpeg.bits_per_slot);
|
|
|
|
config->mpeg.whole_slots_per_frame = (int)avg_slots_per_frame;
|
|
|
|
config->mpeg.frac_slots_per_frame = avg_slots_per_frame - (double)config->mpeg.whole_slots_per_frame;
|
|
config->mpeg.slot_lag = -config->mpeg.frac_slots_per_frame;
|
|
|
|
if(config->mpeg.frac_slots_per_frame==0) {
|
|
config->mpeg.padding = 0;
|
|
}
|
|
|
|
shine_open_bit_stream(&config->bs, BUFFER_SIZE);
|
|
|
|
memset((char *)&config->side_info,0,sizeof(shine_side_info_t));
|
|
|
|
/* determine the mean bitrate for main data */
|
|
if (config->mpeg.granules_per_frame == 2) { /* MPEG 1 */
|
|
config->sideinfo_len = 8 * ((config->wave.channels==1) ? 4 + 17 : 4 + 32);
|
|
} else { /* MPEG 2 */
|
|
config->sideinfo_len = 8 * ((config->wave.channels==1) ? 4 + 9 : 4 + 17);
|
|
}
|
|
return config;
|
|
}
|
|
|
|
|
|
|
|
uint32_t *shine_get_counters() {
|
|
return counter;
|
|
}
|
|
|
|
/* Counter results
|
|
Counters 1550541561 : 1550541629 : 1553135798 : 1555116724 : 1555309952
|
|
68
|
|
core 1 will do:
|
|
2594169
|
|
core 0 will do:
|
|
1980926
|
|
193228
|
|
|
|
|
|
Counters 2664123380 : 2664123448 : 2666717886 : 2668665908 : 2668859025
|
|
*/
|
|
|
|
|
|
static unsigned char *shine_encode_buffer_internal(shine_global_config *config, int *written, int stride) {
|
|
counter[0] = xthal_get_ccount();
|
|
if(config->mpeg.frac_slots_per_frame) {
|
|
config->mpeg.padding = (config->mpeg.slot_lag <= (config->mpeg.frac_slots_per_frame - 1.0));
|
|
config->mpeg.slot_lag += (config->mpeg.padding - config->mpeg.frac_slots_per_frame);
|
|
}
|
|
|
|
config->mpeg.bits_per_frame = 8*(config->mpeg.whole_slots_per_frame + config->mpeg.padding);
|
|
config->mean_bits = (config->mpeg.bits_per_frame - config->sideinfo_len)/config->mpeg.granules_per_frame;
|
|
counter[1] = xthal_get_ccount();
|
|
/* apply mdct to the polyphase output */
|
|
// put on core 1
|
|
shine_mdct_sub(config, stride);
|
|
counter[2] = xthal_get_ccount();
|
|
/* bit and noise allocation */
|
|
//put on core 0
|
|
shine_iteration_loop(config);
|
|
counter[3] = xthal_get_ccount();
|
|
/* write the frame to the bitstream */
|
|
shine_format_bitstream(config);
|
|
counter[4] = xthal_get_ccount();
|
|
/* Return data. */
|
|
*written = config->bs.data_position;
|
|
config->bs.data_position = 0;
|
|
|
|
return config->bs.data;
|
|
}
|
|
|
|
unsigned char *shine_encode_buffer(shine_global_config *config, int16_t **data, int *written) {
|
|
config->buffer[0] = data[0];
|
|
if (config->wave.channels == 2) {
|
|
config->buffer[1] = data[1];
|
|
}
|
|
return shine_encode_buffer_internal(config, written, 1);
|
|
}
|
|
|
|
unsigned char *shine_encode_buffer_interleaved(shine_global_config *config, int16_t *data, int *written) {
|
|
config->buffer[0] = data;
|
|
if (config->wave.channels == 2) {
|
|
config->buffer[1] = data + 1;
|
|
}
|
|
return shine_encode_buffer_internal(config, written, config->wave.channels);
|
|
}
|
|
|
|
unsigned char *shine_flush(shine_global_config *config, int *written) {
|
|
*written = config->bs.data_position;
|
|
config->bs.data_position = 0;
|
|
return config->bs.data;
|
|
}
|
|
|
|
void shine_close(shine_global_config *config) {
|
|
shine_close_bit_stream(&config->bs);
|
|
|
|
for (uint16_t x = 0; x < MAX_CHANNELS; x++) {
|
|
for (uint16_t y = 0; y < MAX_GRANULES; y++) {
|
|
if (config->l3_enc[x][y]) {
|
|
free(config->l3_enc[x][y]);
|
|
}
|
|
if (config->mdct_freq[x][y]) {
|
|
free(config->mdct_freq[x][y]);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (config->l3loop) {
|
|
free(config->l3loop);
|
|
}
|
|
if (config->l3loop->xrsq) {
|
|
free(config->l3loop->xrsq);
|
|
}
|
|
if (config->l3loop->xrabs) {
|
|
free(config->l3loop->xrabs);
|
|
}
|
|
|
|
free(config);
|
|
}
|
|
|
|
#endif // ESP32
|