/main/main.c
size_t
/**
* roll shifts bytes in an array leftward by count and fills the rest of the
* array from StreamBuffer sb.
*
* Returns the number of new bytes read
*/
size_t
/**
* roll_to_syncword searches for a syncword in the buffer and rolls it so that
* the syncword is at the head of the buffer.
*/
size_t
/*
void play_mp3() {
const char TAG[] = "play_mp3";
BaseType_t xerr;
TaskHandle_t rt;
StreamBufferHandle_t sb = xStreamBufferCreate(BUFSIZE, 256);
read_task_parameter_t params = {
.filename = "/sd/Da Funk.mp3",
.sb = sb,
.eof = 0,
};
xerr = xTaskCreate(read_task, "read_task", 4096, ¶ms, 2, &rt);
if (xerr != pdPASS) {
ESP_LOGE(TAG, "Could not launch read task: %d", xerr);
}
size_t n;
HMP3Decoder dec = MP3InitDecoder();
int16_t *samples = NULL;
uint8_t *buf = (uint8_t *) malloc(BUFSIZE);
if (buf == NULL) {
ESP_LOGE(TAG, "Could not allocate read buffer");
return;
}
n = fill_from_streambuffer(sb, buf, BUFSIZE);
printf("received initial %d bytes\n", n);
while (!params.eof) {
n += roll_to_syncword(buf, BUFSIZE, sb, params.eof);
printf("Found syncword at %d\n", n);
MP3FrameInfo fi;
int err = MP3GetNextFrameInfo(dec, &fi, buf);
if (err != 0) {
ESP_LOGE(TAG, "Error getting next frame info: %d", err);
n += roll(buf, BUFSIZE, 1, sb, params.eof);
continue;
}
printf("Frame info:\n");
printf(" bitrate: %d\n", fi.bitrate);
printf(" channels: %d\n", fi.nChans);
printf(" sample rate: %d\n", fi.samprate);
printf(" bits per sample: %d\n", fi.bitsPerSample);
printf(" output samples: %d\n", fi.outputSamps);
printf(" layer: %d\n", fi.layer);
printf(" version: %d\n", fi.version);
int sample_buffer_size = (fi.bitsPerSample / 8) * fi.outputSamps;
if (samples == NULL) {
// Allocate sample buffer
printf("allocating %d byte sample buffer\n", sample_buffer_size);
samples = (int16_t *) malloc(sample_buffer_size);
if (samples == NULL) {
ESP_LOGE(TAG, "Error allocating sample buffer");
return;
}
}
uint8_t *p = buf;
int bytesLeft = BUFSIZE;
while (1) {
uint8_t *p_tmp = p;
int bytesLeft_tmp = bytesLeft;
err = MP3Decode(dec, &p_tmp, &bytesLeft_tmp, samples, 0);
if (err == 0) {
p = p_tmp;
bytesLeft = bytesLeft_tmp;
printf("decoded; %d bytes left\n", bytesLeft);
size_t bytes_written;
esp_err_t e = i2s_write(I2S_NUM_0, samples, sample_buffer_size, &bytes_written, portMAX_DELAY);
if (e != ESP_OK) {
ESP_LOGE("i2s_write", "error %d", e);
}
if (bytes_written < sample_buffer_size) {
ESP_LOGE("i2s_write", "only wrote %d bytes", bytes_written);
}
} else if (err == ERR_MP3_INDATA_UNDERFLOW) {
int c = BUFSIZE - bytesLeft;
int nn = roll(buf, BUFSIZE, c, sb, params.eof);
printf("rolled %d (actual %d, bytes left %d) bytes due to underflow\n", c, nn, bytesLeft);
p = buf;
bytesLeft = BUFSIZE;
n += nn;
} else {
printf("MP3Decode returned %d\n", err);
// Some other error. Roll forward one byte and
// attempt to resync.
n += roll(buf, BUFSIZE, 1, sb, params.eof);
break;
}
};
}
}
void play_mod() {
const char TAG[] = "play_mod";
xmp_context c;
FILE *f;
f = fopen("/sd/Menu.MOD", "r");
c = xmp_create_context();
if (c == NULL) {
ESP_LOGE(TAG, "could not create XMP context");
return;
}
ESP_LOGI(TAG, "created XMP context");
struct xmp_test_info test_info;
int ret = xmp_test_module_from_file(f, &test_info);
if (ret != 0) {
ESP_LOGE(TAG, "could not test module: %d", ret);
return;
}
printf("Title: %s\n", test_info.name);
printf("Type: %s\n", test_info.type);
ret = xmp_load_module_from_file(c, f, 0);
if (ret != 0) {
ESP_LOGE(TAG, "could not load module: %d", ret);
return;
}
ESP_LOGI(TAG, "Loaded");
ret = xmp_start_player(c, 44100, 0);
if (ret != 0) {
ESP_LOGE(TAG, "could not start module playback: %d", ret);
return;
}
struct xmp_frame_info info;
while (1) {
ret = xmp_play_frame(c);
if (ret == -XMP_END) {
break;
} else if (ret != 0) {
ESP_LOGE(TAG, "frame decode error: %d", ret);
return;
}
xmp_get_frame_info(c, &info);
size_t bytes_written;
esp_err_t e = i2s_write(I2S_NUM_0, info.buffer, info.buffer_size, &bytes_written, portMAX_DELAY);
if (e != ESP_OK) {
ESP_LOGE("i2s_write", "error %d", e);
}
if (bytes_written < info.buffer_size) {
ESP_LOGE("i2s_write", "only wrote %d bytes", bytes_written);
}
ESP_LOGI(TAG, "wrote %d samples", bytes_written);
}
}
*/
void
void
void
void
void
void
void
void
void
void
void
int
int
void
/*
void stream_test() {
const char TAG[] = "stream_test";
uint8_t* buf = malloc(256);
StreamBufferHandle_t h = xStreamBufferCreate(256, 1);
uint32_t addr = 0;
sd_get();
ESP_LOGI(TAG, "-------- start --------");
FILE* f = fopen("/sd/cooler.flac", "r");
int64_t t0 = esp_timer_get_time();
for (int i = 0; i < 8 * 1048576; i += 256) {
size_t len = fread(buf, 1, 256, f);
addr += len;
}
int64_t t1 = esp_timer_get_time();
ESP_LOGI(TAG, "Read %d bytes in %lld us: %0.3f KB/sec", addr, t1 - t0, 1000.0 * (double)addr / (double)(t1 - t0));
fclose(f);
file_reader_open("/sd/cooler.flac");
file_reader_subscribe(h);
file_reader_start();
int64_t t0 = esp_timer_get_time();
for (int i = 0; i < 8 * 1048576; i += 256) {
size_t len = xStreamBufferReceive(h, buf, 256, portMAX_DELAY);
//print_hexdump_line(addr, buf);
addr += len;
}
int64_t t1 = esp_timer_get_time();
ESP_LOGI(TAG, "Read %d bytes in %lld us: %0.3f KB/sec", addr, t1 - t0, 1000.0 * (double)addr / (double)(t1 - t0));
file_reader_seek(0, SEEK_SET);
ESP_LOGI(TAG, "--------- seek --------");
for (int i = 0; i < 256 / 16; i++) {
addr += xStreamBufferReceive(h, buf, 16, portMAX_DELAY);
print_hexdump_line(addr, buf);
}
file_reader_close();
ESP_LOGI(TAG, "--------- end ---------");
}
*/
void