Browse Source

Read mp3 files on RAM

Signed-off-by: falkTX <falktx@falktx.com>
tags/v2.3.0-RC1
falkTX 3 years ago
parent
commit
5f22d4bcac
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
12 changed files with 3399 additions and 10 deletions
  1. +1
    -1
      source/backend/engine/CarlaEngine.cpp
  2. +3
    -0
      source/backend/utils/Information.cpp
  3. +6
    -0
      source/modules/audio_decoder/Makefile
  4. +1
    -0
      source/modules/audio_decoder/ad.h
  5. +1
    -0
      source/modules/audio_decoder/ad_ffmpeg.c
  6. +150
    -0
      source/modules/audio_decoder/ad_minimp3.c
  7. +3
    -0
      source/modules/audio_decoder/ad_plugin.c
  8. +1
    -0
      source/modules/audio_decoder/ad_plugin.h
  9. +1853
    -0
      source/modules/audio_decoder/minimp3.h
  10. +1368
    -0
      source/modules/audio_decoder/minimp3_ex.h
  11. +10
    -9
      source/native-plugins/audio-base.hpp
  12. +2
    -0
      source/native-plugins/audio-file.cpp

+ 1
- 1
source/backend/engine/CarlaEngine.cpp View File

@@ -1199,6 +1199,7 @@ bool CarlaEngine::loadFile(const char* const filename)
// -------------------------------------------------------------------

if (
extension == "mp3" ||
#ifdef HAVE_SNDFILE
extension == "aif" ||
extension == "aifc" ||
@@ -1232,7 +1233,6 @@ bool CarlaEngine::loadFile(const char* const filename)
extension == "amr" ||
extension == "ape" ||
extension == "mp2" ||
extension == "mp3" ||
extension == "mpc" ||
extension == "wma" ||
# ifndef HAVE_SNDFILE


+ 3
- 0
source/backend/utils/Information.cpp View File

@@ -168,6 +168,9 @@ const char* const* carla_get_supported_file_extensions()
// FFmpeg without sndfile
"flac", "oga", "ogg", "w64", "wav",
# endif
#else
// minimp3
"mp3",
#endif

// MIDI files


+ 6
- 0
source/modules/audio_decoder/Makefile View File

@@ -16,6 +16,7 @@ BUILD_C_FLAGS += -Werror=deprecated-declarations

OBJS = \
$(OBJDIR)/ad_ffmpeg.c.o \
$(OBJDIR)/ad_minimp3.c.o \
$(OBJDIR)/ad_plugin.c.o \
$(OBJDIR)/ad_soundfile.c.o

@@ -46,6 +47,11 @@ $(OBJDIR)/ad_ffmpeg.c.o: ad_ffmpeg.c
@echo "Compiling $<"
@$(CC) $< $(BUILD_C_FLAGS) $(FFMPEG_FLAGS) -c -o $@

$(OBJDIR)/ad_minimp3.c.o: ad_minimp3.c
-@mkdir -p $(OBJDIR)
@echo "Compiling $<"
@$(CC) $< $(BUILD_C_FLAGS) -c -o $@

$(OBJDIR)/ad_plugin.c.o: ad_plugin.c
-@mkdir -p $(OBJDIR)
@echo "Compiling $<"


+ 1
- 0
source/modules/audio_decoder/ad.h View File

@@ -34,6 +34,7 @@ struct adinfo {
int bit_rate;
int bit_depth;
char * meta_data;
int can_seek;
};

/* global init function - register codecs */


+ 1
- 0
source/modules/audio_decoder/ad_ffmpeg.c View File

@@ -66,6 +66,7 @@ static int ad_info_ffmpeg(void *sf, struct adinfo *nfo) {
nfo->bit_rate = priv->formatContext->bit_rate;
nfo->bit_depth = 0;
nfo->meta_data = NULL;
nfo->can_seek = 1;

#ifdef WITH_GTK // XXX replace g_* functions with POSIX equiv
AVDictionaryEntry *tag = NULL;


+ 150
- 0
source/modules/audio_decoder/ad_minimp3.c View File

@@ -0,0 +1,150 @@
/**
Copyright (C) 2011-2013 Robin Gareus <robin@gareus.org>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser Public License as published by
the Free Software Foundation; either version 2.1, or (at your option)
any later version.

This program 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 Lesser Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

*/
#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, struct adinfo *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->sample_rate ? (nfo->frames * 1000) / nfo->sample_rate : 0;
nfo->bit_depth = 16;
nfo->bit_rate = priv->dec_ex.info.bitrate_kbps;
nfo->meta_data = NULL;
nfo->can_seek = 0;
}
return 0;
}

static void *ad_open_minimp3(const char *filename, struct adinfo *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(0, "unable to open file '%s'.", filename);
char err_str[600];
err_to_string (res, err_str);
puts (err_str);
dbg (0, "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;
}

+ 3
- 0
source/modules/audio_decoder/ad_plugin.c View File

@@ -53,6 +53,9 @@ static ad_plugin const * choose_backend(const char *fn) {
val=adp_get_sndfile()->eval(fn);
if (val>max) {max=val; b=adp_get_sndfile();}

val = adp_get_minimp3()->eval(fn);
if (val > max) {max=val; b=adp_get_minimp3();}

val=adp_get_ffmpeg()->eval(fn);
if (val>max) {max=val; b=adp_get_ffmpeg();}



+ 1
- 0
source/modules/audio_decoder/ad_plugin.h View File

@@ -60,5 +60,6 @@ ssize_t ad_read_null(void *, float*, size_t);

/* hardcoded backends */
const ad_plugin * adp_get_sndfile();
const ad_plugin * adp_get_minimp3();
const ad_plugin * adp_get_ffmpeg();
#endif

+ 1853
- 0
source/modules/audio_decoder/minimp3.h
File diff suppressed because it is too large
View File


+ 1368
- 0
source/modules/audio_decoder/minimp3_ex.h
File diff suppressed because it is too large
View File


+ 10
- 9
source/native-plugins/audio-base.hpp View File

@@ -159,7 +159,7 @@ struct AudioFilePool {
const bool loopingMode,
const bool isOffline,
bool& needsRead,
uint32_t& needsReadFrame)
uint64_t& needsReadFrame)
{
CARLA_SAFE_ASSERT_RETURN(numFrames != 0, false);
CARLA_SAFE_ASSERT_RETURN(maxFrame != 0, false);
@@ -378,7 +378,7 @@ public:
maxFrame = fileNumFrames;
}

if (fileNumFrames <= maxPoolNumFrames)
if (fileNumFrames <= maxPoolNumFrames || ! fFileNfo.can_seek)
{
// entire file fits in a small pool, lets read it now
const uint32_t poolNumFrames = needsResample
@@ -497,7 +497,7 @@ public:
_tryPoolSwap(pool);

bool needsRead = false;
uint32_t needsReadFrame;
uint64_t needsReadFrame;
const bool ret = pool.tryPutData(out1, out2, framePos, frames, loopMode, isOffline, needsRead, needsReadFrame);

if (needsRead)
@@ -773,7 +773,7 @@ public:
} while (i < poolNumFrames);

// lock, and put data asap
const CarlaMutexLocker cml(fPoolMutex);
const CarlaMutexLocker cmlp(fPoolMutex);
const water::GenericScopedLock<water::SpinLock> gsl(fPool.mutex);

std::memcpy(fPool.buffer[0], pbuffer0, sizeof(float)*poolNumFrames);
@@ -814,7 +814,8 @@ private:
// NOTE it is assumed that `pool` mutex is locked
void _tryPoolSwap(AudioFilePool& pool)
{
uint32_t tmp_u;
uint32_t tmp_u32;
uint64_t tmp_u64;
float* tmp_fp;

const CarlaMutexTryLocker cmtl(fPoolMutex);
@@ -827,13 +828,13 @@ private:
if (! fPoolReadyToSwap)
return;

tmp_u = pool.startFrame;
tmp_u64 = pool.startFrame;
pool.startFrame = fPool.startFrame;
fPool.startFrame = tmp_u;
fPool.startFrame = tmp_u64;

tmp_u = pool.numFrames;
tmp_u32 = pool.numFrames;
pool.numFrames = fPool.numFrames;
fPool.numFrames = tmp_u;
fPool.numFrames = tmp_u32;

tmp_fp = pool.buffer[0];
pool.buffer[0] = fPool.buffer[0];


+ 2
- 0
source/native-plugins/audio-file.cpp View File

@@ -30,6 +30,8 @@ static const char* const audiofilesWildcard =
# ifndef HAVE_SNDFILE
"*.flac;*.oga;*.ogg;*.w64;*.wav;"
# endif
#else
"*.mp3;"
#endif
#if !defined(HAVE_SNDFILE) && !defined(HAVE_FFMPEG)
""


Loading…
Cancel
Save