2026-03-02 09:42:44 +01:00
|
|
|
//
|
|
|
|
|
// Created by david on 17.05.20.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
#define LOG_TAG "mp3file"
|
|
|
|
|
|
|
|
|
|
#include "mp3file.h"
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <cstdlib>
|
|
|
|
|
#include "logging.h"
|
|
|
|
|
|
|
|
|
|
MP3File* mp3file_init(mpg123_handle *handle) {
|
|
|
|
|
MP3File* mp3file = (MP3File *) malloc(sizeof(MP3File));
|
|
|
|
|
if(mp3file == NULL) return NULL;
|
|
|
|
|
memset(mp3file, 0, sizeof(MP3File));
|
|
|
|
|
mp3file->handle = handle;
|
|
|
|
|
return mp3file;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void mp3file_delete(MP3File *mp3file) {
|
|
|
|
|
if(mp3file == NULL) return;
|
|
|
|
|
mpg123_close(mp3file->handle);
|
|
|
|
|
mpg123_delete(mp3file->handle);
|
|
|
|
|
if(mp3file->buffer) {
|
|
|
|
|
free(mp3file->buffer);
|
|
|
|
|
mp3file->buffer = 0;
|
|
|
|
|
}
|
|
|
|
|
free(mp3file);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MP3File* mp3file_open(const char *filename, int forceEncoding) {
|
|
|
|
|
const char *errorText = "";
|
|
|
|
|
#define handleError(text) \
|
|
|
|
|
do { \
|
|
|
|
|
errorText = text; \
|
|
|
|
|
goto on_error; \
|
|
|
|
|
} while(0)
|
|
|
|
|
|
|
|
|
|
int err = MPG123_OK;
|
|
|
|
|
mpg123_handle *mh = mpg123_new(NULL, &err);
|
|
|
|
|
if(err != MPG123_OK || mh == NULL) {
|
|
|
|
|
LOGE("mpg123_new() failed: %s", mpg123_plain_strerror(err));
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MP3File* mp3 = mp3file_init(mh);
|
|
|
|
|
if(mp3 == NULL) handleError("malloc() failed");
|
|
|
|
|
err = mpg123_open(mh, filename);
|
|
|
|
|
if(err != MPG123_OK) handleError("mpg123_open()");
|
|
|
|
|
|
|
|
|
|
int encoding;
|
|
|
|
|
err = mpg123_getformat(mh, &mp3->rate, &mp3->channels, &encoding);
|
|
|
|
|
if(err != MPG123_OK) handleError("mpg123_getformat()");
|
|
|
|
|
if(encoding != MPG123_ENC_SIGNED_16) handleError("unknown file encoding");
|
|
|
|
|
|
|
|
|
|
if(forceEncoding != 0) {
|
|
|
|
|
encoding = forceEncoding;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Ensure that this output format will not change
|
|
|
|
|
// (it could, when we allow it).
|
|
|
|
|
mpg123_format_none(mh);
|
|
|
|
|
err = mpg123_format(mh, mp3->rate, mp3->channels, encoding);
|
|
|
|
|
if(err != MPG123_OK) handleError("could not set mpg123_format()");
|
|
|
|
|
|
|
|
|
|
mp3->buffer_size = mpg123_outblock(mh);
|
|
|
|
|
mp3->buffer = (unsigned char*) malloc(mp3->buffer_size);
|
|
|
|
|
if(mp3->buffer == NULL) handleError("malloc() failed");
|
|
|
|
|
|
|
|
|
|
mp3->num_samples = mpg123_length(mh);
|
|
|
|
|
mp3->samples_per_frame = mpg123_spf(mh);
|
|
|
|
|
mp3->secs_per_frame = mpg123_tpf(mh);
|
|
|
|
|
|
|
|
|
|
if (mp3->num_samples == MPG123_ERR || mp3->samples_per_frame < 0)
|
|
|
|
|
mp3->num_frames = 0;
|
|
|
|
|
else
|
|
|
|
|
mp3->num_frames = mp3->num_samples / mp3->samples_per_frame;
|
|
|
|
|
|
|
|
|
|
if (mp3->num_samples == MPG123_ERR || mp3->samples_per_frame < 0 || mp3->secs_per_frame < 0)
|
|
|
|
|
mp3->duration = 0;
|
|
|
|
|
else
|
|
|
|
|
mp3->duration = mp3->num_samples / mp3->samples_per_frame * mp3->secs_per_frame;
|
|
|
|
|
|
2026-03-05 14:28:23 +01:00
|
|
|
mp3->offset = 0;
|
|
|
|
|
mp3->remaining_samples = (int) mp3->num_samples;
|
2026-03-02 09:42:44 +01:00
|
|
|
LOGV("channels: %d rate: %ld num_samples: %ld", mp3->channels, mp3->rate, mp3->num_samples);
|
|
|
|
|
return mp3;
|
|
|
|
|
|
|
|
|
|
on_error:
|
|
|
|
|
LOGE("%s, err = %s", errorText, mpg123_plain_strerror(err));
|
|
|
|
|
mp3file_delete(mp3);
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
#undef handleError
|
|
|
|
|
}
|