// // Created by david on 17.05.20. // #define LOG_TAG "mp3file" #include "mp3file.h" #include #include #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; mp3->offset = 0; mp3->remaining_samples = (int) mp3->num_samples; 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 }