Browse Source

use minimp3 instead of ffmpeg for MP3

master
Alexandros Theodotou 2 years ago
parent
commit
519f8dce24
Signed by: alex
GPG Key ID: 022EAE42313D70F3
  1. 4
      README.md
  2. 21
      inc/ad_plugin.h
  3. 1853
      inc/minimp3.h
  4. 1368
      inc/minimp3_ex.h
  5. 33
      meson.build
  6. 188
      src/ad_minimp3.c
  7. 9
      src/ad_plugin.c
  8. 3
      src/meson.build
  9. 16
      tests/meson.build
  10. 2
      tests/test.c

4
README.md

@ -2,7 +2,7 @@ libaudec @@ -2,7 +2,7 @@ libaudec
========
libaudec (lib audio decoder) is a wrapper library
over ffmpeg, sndfile and libsamplerate for reading
over minimp3, sndfile and libsamplerate for reading
and resampling audio files, based on Robin Gareus'
`audio_decoder` code
(https://github.com/x42/silan/tree/master/audio_decoder)
@ -63,7 +63,7 @@ where specified, are licensed under different @@ -63,7 +63,7 @@ where specified, are licensed under different
licenses.
----
Copyright (C) 2019 Alexandros Theodotou
Copyright (C) 2019-2020 Alexandros Theodotou
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright

21
inc/ad_plugin.h

@ -1,4 +1,24 @@ @@ -1,4 +1,24 @@
/*
* 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/>.
*
* This file incorporates work covered by the following copyright and
* permission notice:
*
* Copyright (C) 2011-2013 Robin Gareus <robin@gareus.org>
*
* This program is free software: you can redistribute it and/or modify
@ -83,4 +103,5 @@ ssize_t ad_read_null(void *, float*, size_t); @@ -83,4 +103,5 @@ ssize_t ad_read_null(void *, float*, size_t);
/* hardcoded backends */
const ad_plugin * adp_get_sndfile();
const ad_plugin * adp_get_ffmpeg();
const ad_plugin * adp_get_minimp3();
#endif

1853
inc/minimp3.h

File diff suppressed because it is too large Load Diff

1368
inc/minimp3_ex.h

File diff suppressed because it is too large Load Diff

33
meson.build

@ -142,21 +142,22 @@ audec_cflags = cc.get_supported_arguments ( @@ -142,21 +142,22 @@ audec_cflags = cc.get_supported_arguments (
audec_cflags)
audec_deps = []
libavcodec_dep = dependency (
'libavcodec', required: get_option ('ffmpeg'))
libavformat_dep = dependency (
'libavformat', required: get_option ('ffmpeg'))
libavutil_dep = dependency (
'libavutil', required: get_option ('ffmpeg'))
audec_deps += [
libavcodec_dep,
libavformat_dep,
libavutil_dep,
]
have_ffmpeg = libavcodec_dep.found () and libavformat_dep.found () and libavutil_dep.found () and not get_option ('ffmpeg').disabled ()
if have_ffmpeg
cdata.set('HAVE_FFMPEG', 1)
endif
#libavcodec_dep = dependency (
#'libavcodec', required: get_option ('ffmpeg'))
#libavformat_dep = dependency (
#'libavformat', required: get_option ('ffmpeg'))
#libavutil_dep = dependency (
#'libavutil', required: get_option ('ffmpeg'))
#audec_deps += [
#libavcodec_dep,
#libavformat_dep,
#libavutil_dep,
#]
#have_ffmpeg = libavcodec_dep.found () and libavformat_dep.found () and libavutil_dep.found () and not get_option ('ffmpeg').disabled ()
#if have_ffmpeg
#cdata.set('HAVE_FFMPEG', 1)
#endif
have_ffmpeg = false
audec_deps += [
dependency('sndfile', version: '>=1.0.25'),
@ -221,8 +222,6 @@ summary = [ @@ -221,8 +222,6 @@ summary = [
'',
' Build type: @0@'.format(
get_option('buildtype')),
' Optional libraries:',
' ffmpeg: @0@'.format(have_ffmpeg),
' Directories:',
' prefix: @0@'.format(prefix),
' includedir: @0@'.format(includedir),

188
src/ad_minimp3.c

@ -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;
}

9
src/ad_plugin.c

@ -89,12 +89,21 @@ choose_backend ( @@ -89,12 +89,21 @@ choose_backend (
plugin = adp_get_sndfile();
}
#if 0
val = adp_get_ffmpeg()->eval(fn);
if (val > max)
{
max = val;
plugin = adp_get_ffmpeg();
}
#endif
val = adp_get_minimp3()->eval(fn);
if (val > max)
{
max = val;
plugin = adp_get_minimp3();
}
return plugin;
}

3
src/meson.build

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
srcs = files ([
'ad_soundfile.c',
'ad_ffmpeg.c',
#'ad_ffmpeg.c',
'ad_minimp3.c',
'ad_plugin.c',
])

16
tests/meson.build

@ -29,13 +29,11 @@ if get_option ('tests') @@ -29,13 +29,11 @@ if get_option ('tests')
meson.current_source_dir(), 'test.wav'),
'44000',
])
if have_ffmpeg and get_option ('mp3_tests')
test (
'mp3_test', e,
args: [
join_paths (
meson.current_source_dir(), 'test.mp3'),
'48000',
])
endif
test (
'mp3_test', e,
args: [
join_paths (
meson.current_source_dir(), 'test.mp3'),
'48000',
])
endif

2
tests/test.c

@ -42,7 +42,7 @@ int main ( @@ -42,7 +42,7 @@ int main (
{
/*expected_frames_before = 294912;*/
/* FIXME audacity says above */
expected_frames_before = 292654;
expected_frames_before = 291583;
expected_sample_rate_before = 44100;
expected_channels_before = 2;
}

Loading…
Cancel
Save