10 changed files with 3467 additions and 30 deletions
@ -0,0 +1,188 @@
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Alexandros Theodotou <alex at zrythm dot org> |
||||
* |
||||
* This file is part of libaudec |
||||
* |
||||
* libaudec is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License as published by |
||||
* the Free Software Foundation, either version 3 of the License, or |
||||
* (at your option) any later version. |
||||
* |
||||
* libaudec is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License |
||||
* along with libaudec. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/ |
||||
|
||||
#include "config.h" |
||||
|
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
#include <strings.h> |
||||
#include <unistd.h> |
||||
#include <math.h> |
||||
|
||||
#include "ad_plugin.h" |
||||
|
||||
#define MINIMP3_FLOAT_OUTPUT |
||||
#define MINIMP3_IMPLEMENTATION |
||||
#include "minimp3_ex.h" |
||||
|
||||
/* internal abstraction */ |
||||
|
||||
typedef struct { |
||||
mp3dec_ex_t dec_ex; |
||||
} minimp3_audio_decoder; |
||||
|
||||
static void |
||||
err_to_string ( |
||||
int err_code, |
||||
char * buf) |
||||
{ |
||||
switch (err_code) |
||||
{ |
||||
case MP3D_E_PARAM: |
||||
strcpy (buf, "Parameter error"); |
||||
break; |
||||
case MP3D_E_MEMORY: |
||||
strcpy (buf, "Memory error"); |
||||
break; |
||||
case MP3D_E_IOERROR: |
||||
strcpy (buf, "IO error"); |
||||
break; |
||||
case MP3D_E_USER: |
||||
strcpy (buf, "User error"); |
||||
break; |
||||
case MP3D_E_DECODE: |
||||
strcpy (buf, "Decode error"); |
||||
break; |
||||
default: |
||||
strcpy (buf, "Unknown error"); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
static int |
||||
ad_info_minimp3 ( |
||||
void * sf, |
||||
AudecInfo * nfo) |
||||
{ |
||||
minimp3_audio_decoder *priv = |
||||
(minimp3_audio_decoder*) sf; |
||||
if (!priv) |
||||
return -1; |
||||
if (nfo) |
||||
{ |
||||
nfo->channels = priv->dec_ex.info.channels; |
||||
nfo->frames = priv->dec_ex.samples / nfo->channels; |
||||
nfo->sample_rate = priv->dec_ex.info.hz; |
||||
nfo->length = |
||||
nfo->frames ? |
||||
(nfo->frames * 1000) / nfo->sample_rate : 0; |
||||
nfo->bit_depth = 0; |
||||
nfo->bit_rate = |
||||
priv->dec_ex.info.bitrate_kbps; |
||||
nfo->meta_data = NULL; |
||||
nfo->bpm = 0; |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
static void * |
||||
ad_open_minimp3 ( |
||||
const char * filename, |
||||
AudecInfo * nfo) |
||||
{ |
||||
minimp3_audio_decoder *priv = |
||||
(minimp3_audio_decoder*) |
||||
calloc (1, sizeof(minimp3_audio_decoder)); |
||||
int res = |
||||
mp3dec_ex_open ( |
||||
&priv->dec_ex, filename, MP3D_SEEK_TO_SAMPLE); |
||||
if (res) |
||||
{ |
||||
dbg ( |
||||
AUDEC_DEBUG_LEVEL_ERROR, |
||||
"unable to open file '%s'.", filename); |
||||
char err_str[600]; |
||||
err_to_string (res, err_str); |
||||
puts (err_str); |
||||
dbg ( |
||||
AUDEC_DEBUG_LEVEL_ERROR, "error=%i", res); |
||||
free (priv); |
||||
return NULL; |
||||
} |
||||
ad_info_minimp3 (priv, nfo); |
||||
return (void*) priv; |
||||
} |
||||
|
||||
static int |
||||
ad_close_minimp3 ( |
||||
void *sf) |
||||
{ |
||||
minimp3_audio_decoder *priv = (minimp3_audio_decoder*) sf; |
||||
if (!priv) return -1; |
||||
if (!sf) |
||||
{ |
||||
dbg (0, "fatal: bad file close.\n"); |
||||
return -1; |
||||
} |
||||
mp3dec_ex_close (&priv->dec_ex); |
||||
free (priv); |
||||
return 0; |
||||
} |
||||
|
||||
static int64_t |
||||
ad_seek_minimp3 ( |
||||
void *sf, int64_t pos) |
||||
{ |
||||
minimp3_audio_decoder *priv = (minimp3_audio_decoder*) sf; |
||||
if (!priv) return -1; |
||||
return mp3dec_ex_seek (&priv->dec_ex, pos); |
||||
} |
||||
|
||||
static ssize_t |
||||
ad_read_minimp3 ( |
||||
void *sf, float* d, size_t len) |
||||
{ |
||||
minimp3_audio_decoder *priv = (minimp3_audio_decoder*) sf; |
||||
if (!priv) return -1; |
||||
return mp3dec_ex_read (&priv->dec_ex, d, len); |
||||
} |
||||
|
||||
static int ad_eval_minimp3(const char *f) |
||||
{ |
||||
char *ext = strrchr(f, '.'); |
||||
if (strstr (f, "://")) return 0; |
||||
if (!ext) return 5; |
||||
if (!strcasecmp(ext, ".mp3")) return 100; |
||||
return 0; |
||||
} |
||||
|
||||
static const ad_plugin ad_minimp3 = { |
||||
#if 1 |
||||
.eval = &ad_eval_minimp3, |
||||
.open = &ad_open_minimp3, |
||||
.close = &ad_close_minimp3, |
||||
.info = &ad_info_minimp3, |
||||
.seek = &ad_seek_minimp3, |
||||
.read = &ad_read_minimp3 |
||||
#else |
||||
&ad_eval_null, |
||||
&ad_open_null, |
||||
&ad_close_null, |
||||
&ad_info_null, |
||||
&ad_seek_null, |
||||
&ad_read_null |
||||
#endif |
||||
}; |
||||
|
||||
/* dlopen handler */ |
||||
const ad_plugin * adp_get_minimp3() { |
||||
return &ad_minimp3; |
||||
} |
||||
|
Loading…
Reference in new issue