From 27867ba347cb6f37d2d1bfa672540860ebc095b7 Mon Sep 17 00:00:00 2001 From: waker Date: Fri, 10 Dec 2010 21:56:11 +0100 Subject: exposed pcm_convert via plugin API; DSP presets are now being used and are working in converter; implemented support for converting via temp file in converter --- deadbeef.h | 20 +++--- plugins.c | 3 + plugins/dca/Makefile.am | 2 +- plugins/dsp_libsrc/Makefile.am | 3 +- plugins/gtkui/converter.c | 135 +++++++++++++++++++++++++++++++++++------ plugins/musepack/Makefile.am | 2 +- 6 files changed, 133 insertions(+), 32 deletions(-) diff --git a/deadbeef.h b/deadbeef.h index 2357c407..57cc035b 100644 --- a/deadbeef.h +++ b/deadbeef.h @@ -32,6 +32,7 @@ #include #ifdef __cplusplus +#define restrict // shut up g++ extern "C" { #endif @@ -280,6 +281,14 @@ typedef struct DB_md5_s { char data[88]; } DB_md5_t; +typedef struct { + int bps; + int is_float; // bps must be 32 if this is true + int channels; + int samplerate; + uint32_t channelmask; +} ddb_waveformat_t; + // forward decl for plugin struct struct DB_plugin_s; @@ -533,6 +542,9 @@ typedef struct { void (*plug_trigger_event_playlistchanged) (void); // misc utilities int (*is_local_file) (const char *fname); // returns 1 for local filename, 0 otherwise + + // pcm utilities + int (*pcm_convert) (const ddb_waveformat_t * restrict inputfmt, const char * restrict input, const ddb_waveformat_t * restrict outputfmt, char * restrict output, int inputsize); } DB_functions_t; enum { @@ -651,14 +663,6 @@ enum { DDB_SPEAKER_TOP_BACK_RIGHT = 0x20000 }; -typedef struct { - int bps; - int is_float; // bps must be 32 if this is true - int channels; - int samplerate; - uint32_t channelmask; -} ddb_waveformat_t; - typedef struct DB_fileinfo_s { struct DB_decoder_s *plugin; diff --git a/plugins.c b/plugins.c index 238d6524..645f3707 100644 --- a/plugins.c +++ b/plugins.c @@ -42,6 +42,7 @@ #include "conf.h" #include "junklib.h" #include "vfs.h" +#include "premix.h" #define trace(...) { fprintf(stderr, __VA_ARGS__); } //#define trace(fmt,...) @@ -268,6 +269,8 @@ static DB_functions_t deadbeef_api = { .plug_trigger_event_playlistchanged = plug_trigger_event_playlistchanged, // misc utilities .is_local_file = plug_is_local_file, + // pcm utilities + .pcm_convert = pcm_convert, }; DB_functions_t *deadbeef = &deadbeef_api; diff --git a/plugins/dca/Makefile.am b/plugins/dca/Makefile.am index 4a2b4b5a..9819c5aa 100644 --- a/plugins/dca/Makefile.am +++ b/plugins/dca/Makefile.am @@ -25,6 +25,6 @@ bitstream.h dca_la_LDFLAGS = -module dca_la_LIBADD = $(LDADD) -lm -AM_CFLAGS = $(CFLAGS) -fPIC +AM_CFLAGS = $(CFLAGS) -fPIC -std=c99 endif diff --git a/plugins/dsp_libsrc/Makefile.am b/plugins/dsp_libsrc/Makefile.am index 798be19f..42c6a347 100644 --- a/plugins/dsp_libsrc/Makefile.am +++ b/plugins/dsp_libsrc/Makefile.am @@ -7,7 +7,6 @@ dsp_libsrc_la_LDFLAGS = -module dsp_libsrc_la_LIBADD = $(LIBADD) $(LIBSAMPLERATE_DEPS_LIBS) -dsp_libsrc_la_CFLAGS = $(CFLAGS) $(LIBSAMPLERATE_DEPS_CFLAGS) +dsp_libsrc_la_CFLAGS = $(CFLAGS) $(LIBSAMPLERATE_DEPS_CFLAGS) -std=c99 -AM_CFLAGS = -std=c99 endif diff --git a/plugins/gtkui/converter.c b/plugins/gtkui/converter.c index af578f87..18a7fb82 100644 --- a/plugins/gtkui/converter.c +++ b/plugins/gtkui/converter.c @@ -555,6 +555,8 @@ on_converter_ok_clicked (GtkButton *button, if (!p) { return; } + combo = GTK_COMBO_BOX (lookup_widget (converter, "dsp_preset")); + int dsp_idx = gtk_combo_box_get_active (combo); gtk_widget_destroy (converter); converter = NULL; @@ -580,7 +582,14 @@ on_converter_ok_clicked (GtkButton *button, } deadbeef->pl_unlock (); - // ... convert ... + ddb_dsp_preset_t *dsp_preset = NULL; + if (dsp_idx > 0) { + dsp_preset = dsp_presets; + while (dsp_preset && dsp_idx--) { + dsp_preset = dsp_preset->next; + } + } + for (n = 0; n < nsel; n++) { it = items[n]; DB_decoder_t *dec = NULL; @@ -600,30 +609,116 @@ on_converter_ok_clicked (GtkButton *button, char enc[1024]; snprintf (enc, sizeof (enc), p->encoder, out); fprintf (stderr, "executing: %s\n", enc); - FILE *fp = popen (enc, "w"); - if (!fp) { - fprintf (stderr, "converter: failed to open encoder\n"); + FILE *enc_pipe = NULL; + FILE *temp_file = NULL; + + if (p->method == DDB_ENCODER_METHOD_FILE) { + const char *temp_file_name = "/tmp/deadbeef-converter.wav"; // FIXME + temp_file = fopen (temp_file_name, "w+b"); + if (!temp_file) { + fprintf (stderr, "converter: failed to open temp file %s\n", temp_file_name); + if (fileinfo) { + dec->free (fileinfo); + } + continue; + } } else { - // write wave header - char wavehdr[] = { - 0x52, 0x49, 0x46, 0x46, 0x24, 0x70, 0x0d, 0x00, 0x57, 0x41, 0x56, 0x45, 0x66, 0x6d, 0x74, 0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x44, 0xac, 0x00, 0x00, 0x10, 0xb1, 0x02, 0x00, 0x04, 0x00, 0x10, 0x00, 0x64, 0x61, 0x74, 0x61 - }; - fwrite (wavehdr, 1, sizeof (wavehdr), fp); - uint32_t size = (it->endsample-it->startsample) * fileinfo->fmt.channels * fileinfo->fmt.bps / 8; - fwrite (&size, 1, sizeof (size), fp); - - int bs = 8192; - char buffer[bs]; - for (;;) { - int sz = dec->read (fileinfo, buffer, bs); - fwrite (buffer, 1, sz, fp); - if (sz != bs) { - break; + enc_pipe = popen (enc, "w"); + if (!enc_pipe) { + fprintf (stderr, "converter: failed to open encoder\n"); + if (temp_file) { + fclose (temp_file); + } + if (fileinfo) { + dec->free (fileinfo); } + continue; + } + } + + if (!temp_file) { + temp_file = enc_pipe; + } + + // write wave header + char wavehdr[] = { + 0x52, 0x49, 0x46, 0x46, 0x24, 0x70, 0x0d, 0x00, 0x57, 0x41, 0x56, 0x45, 0x66, 0x6d, 0x74, 0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x44, 0xac, 0x00, 0x00, 0x10, 0xb1, 0x02, 0x00, 0x04, 0x00, 0x10, 0x00, 0x64, 0x61, 0x74, 0x61 + }; + int header_written = 0; + uint32_t outsize = 0; + uint32_t outsr = fileinfo->fmt.samplerate; + uint16_t outch = fileinfo->fmt.channels; + uint16_t outbps = fileinfo->fmt.bps; + + int samplesize = fileinfo->fmt.channels * fileinfo->fmt.bps / 8; + int bs = 10250 * samplesize; + char buffer[bs * 4]; + int dspsize = bs / samplesize * sizeof (float) * fileinfo->fmt.channels; + char dspbuffer[dspsize * 4]; + int eof = 0; + for (;;) { + if (eof) { + break; } + int sz = dec->read (fileinfo, buffer, bs); + + if (sz != bs) { + eof = 1; + } + float ratio = 1; + if (dsp_preset) { + ddb_waveformat_t fmt; + memcpy (&fmt, &fileinfo->fmt, sizeof (fmt)); + fmt.bps = 32; + fmt.is_float = 1; + deadbeef->pcm_convert (&fileinfo->fmt, buffer, &fmt, dspbuffer, sz); + + DB_dsp_instance_t *dsp = dsp_preset->chain; + int frames = sz / samplesize; + while (dsp) { + frames = dsp->plugin->process (dsp, (float *)dspbuffer, frames, &fmt.samplerate, &fmt.channels); + dsp = dsp->next; + } + + deadbeef->pcm_convert (&fmt, dspbuffer, &fileinfo->fmt, buffer, frames * sizeof (float) * fmt.channels); + outsr = fmt.samplerate; + outch = fmt.channels; + sz = frames * samplesize; + } + outsize += sz; + + if (!header_written) { + uint32_t size = (it->endsample-it->startsample) * fileinfo->fmt.channels * fileinfo->fmt.bps / 8; + + if (outsr != fileinfo->fmt.samplerate) { + uint64_t temp = size; + temp *= outsr; + temp /= fileinfo->fmt.samplerate; + size = temp; + } + + memcpy (&wavehdr[22], &outch, 2); + memcpy (&wavehdr[24], &outsr, 4); + memcpy (&wavehdr[34], &outbps, 2); + + fwrite (wavehdr, 1, sizeof (wavehdr), temp_file); + fwrite (&size, 1, sizeof (size), temp_file); + header_written = 1; + } + + fwrite (buffer, 1, sz, temp_file); + } + if (temp_file && temp_file != enc_pipe) { + fclose (temp_file); + } + + if (p->method == DDB_ENCODER_METHOD_FILE) { + enc_pipe = popen (enc, "w"); + } - pclose (fp); + if (enc_pipe) { + pclose (enc_pipe); } dec->free (fileinfo); } diff --git a/plugins/musepack/Makefile.am b/plugins/musepack/Makefile.am index 213fee32..c82490aa 100644 --- a/plugins/musepack/Makefile.am +++ b/plugins/musepack/Makefile.am @@ -27,6 +27,6 @@ mpc/minimax.h musepack_la_LDFLAGS = -module musepack_la_LIBADD = $(LDADD) -lm -AM_CFLAGS = $(CFLAGS) -fPIC +AM_CFLAGS = $(CFLAGS) -fPIC -std=c99 endif -- cgit v1.2.3