shithub: sox

Download patch

ref: a45ef1d2e89d59bd27456b3a01eb4d7f88e4d35d
parent: 7fa7da16022d3d00ce03e4f04d3fa69d82a8267f
author: robs <robs>
date: Tue May 12 16:59:36 EDT 2009

further step towards dl mp3

--- a/src/mp3-duration.h
+++ b/src/mp3-duration.h
@@ -79,12 +79,12 @@
 
 #endif
 
-static unsigned long xing_frames(struct mad_bitptr ptr, unsigned bitlen)
+static unsigned long xing_frames(priv_t * p, struct mad_bitptr ptr, unsigned bitlen)
 {
   #define XING_MAGIC ( ('X' << 24) | ('i' << 16) | ('n' << 8) | 'g' )
-  if (bitlen >= 96 && mad_bit_read(&ptr, 32) == XING_MAGIC &&
-      (mad_bit_read(&ptr, 32) & 1 )) /* XING_FRAMES */
-    return mad_bit_read(&ptr, 32);
+  if (bitlen >= 96 && p->mad_bit_read(&ptr, 32) == XING_MAGIC &&
+      (p->mad_bit_read(&ptr, 32) & 1 )) /* XING_FRAMES */
+    return p->mad_bit_read(&ptr, 32);
   return 0;
 }
 
@@ -94,19 +94,21 @@
   t->fraction = (d - t->seconds) * MAD_TIMER_RESOLUTION + .5;
 }
 
-static size_t mp3_duration_ms(FILE * fp, unsigned char *buffer)
+static size_t mp3_duration_ms(sox_format_t * ft, unsigned char *buffer)
 {
+  priv_t              * p = (priv_t *) ft->priv;
+  FILE                * fp = ft->fp;
   struct mad_stream   mad_stream;
   struct mad_header   mad_header;
   struct mad_frame    mad_frame;
   mad_timer_t         time = mad_timer_zero;
-  size_t          initial_bitrate = 0; /* Initialised to prevent warning */
-  size_t          tagsize = 0, consumed = 0, frames = 0;
+  size_t              initial_bitrate = 0; /* Initialised to prevent warning */
+  size_t              tagsize = 0, consumed = 0, frames = 0;
   sox_bool            vbr = sox_false, depadded = sox_false;
 
-  mad_stream_init(&mad_stream);
-  mad_header_init(&mad_header);
-  mad_frame_init(&mad_frame);
+  p->mad_stream_init(&mad_stream);
+  p->mad_header_init(&mad_header);
+  p->mad_frame_init(&mad_frame);
 
   do {  /* Read data from the MP3 file */
     int read, padding = 0;
@@ -120,11 +122,11 @@
     }
     for (; !depadded && padding < read && !buffer[padding]; ++padding);
     depadded = sox_true;
-    mad_stream_buffer(&mad_stream, buffer + padding, leftover + read - padding);
+    p->mad_stream_buffer(&mad_stream, buffer + padding, leftover + read - padding);
 
     while (sox_true) {  /* Decode frame headers */
       mad_stream.error = MAD_ERROR_NONE;
-      if (mad_header_decode(&mad_header, &mad_stream) == -1) {
+      if (p->mad_header_decode(&mad_header, &mad_stream) == -1) {
         if (mad_stream.error == MAD_ERROR_BUFLEN)
           break;  /* Normal behaviour; get some more data from the file */
         if (!MAD_RECOVERABLE(mad_stream.error)) {
@@ -139,7 +141,7 @@
               fseeko(fp, (off_t)(tagsize - available), SEEK_CUR);
               depadded = sox_false;
             }
-            mad_stream_skip(&mad_stream, min(tagsize, available));
+            p->mad_stream_skip(&mad_stream, min(tagsize, available));
           }
           else lsx_warn("MAD lost sync");
         }
@@ -147,7 +149,7 @@
         continue; /* Not an audio frame */
       }
 
-      mad_timer_add(&time, mad_header.duration);
+      p->mad_timer_add(&time, mad_header.duration);
       consumed += mad_stream.next_frame - mad_stream.this_frame;
 
       if (!frames) {
@@ -155,13 +157,13 @@
 
         /* Get the precise frame count from the XING header if present */
         mad_frame.header = mad_header;
-        if (mad_frame_decode(&mad_frame, &mad_stream) == -1)
+        if (p->mad_frame_decode(&mad_frame, &mad_stream) == -1)
           if (!MAD_RECOVERABLE(mad_stream.error)) {
             lsx_warn("unrecoverable MAD error");
             break;
           }
-        if ((frames = xing_frames(mad_stream.anc_ptr, mad_stream.anc_bitlen))) {
-          mad_timer_multiply(&time, (signed long)frames);
+        if ((frames = xing_frames(p, mad_stream.anc_ptr, mad_stream.anc_bitlen))) {
+          p->mad_timer_multiply(&time, (signed long)frames);
           lsx_debug("got exact duration from XING frame count (%lu)", (unsigned long)frames);
           break;
         }
@@ -179,9 +181,9 @@
     }
   } while (mad_stream.error == MAD_ERROR_BUFLEN);
 
-  mad_frame_finish(&mad_frame);
+  p->mad_frame_finish(&mad_frame);
   mad_header_finish(&mad_header);
-  mad_stream_finish(&mad_stream);
+  p->mad_stream_finish(&mad_stream);
   rewind(fp);
-  return mad_timer_count(time, MAD_UNITS_MILLISECONDS);
+  return p->mad_timer_count(time, MAD_UNITS_MILLISECONDS);
 }
--- a/src/mp3.c
+++ b/src/mp3.c
@@ -28,54 +28,78 @@
   #define ID3_TAG_FLAG_FOOTERPRESENT 0x10
 #endif
 
+#if defined HAVE_LIBLTDL
+  #include <ltdl.h>
+#if defined DL_MAD
+mad_timer_t const mad_timer_zero;
+#endif
+#endif
+
+#if 0
+#define DL_MAD
+#define DL_LAME
+#endif
+
 #define INPUT_BUFFER_SIZE       (sox_globals.bufsiz)
 
 /* Private data */
 typedef struct {
 #ifdef HAVE_MAD_H
-        struct mad_stream       Stream;
-        struct mad_frame        Frame;
-        struct mad_synth        Synth;
-        mad_timer_t             Timer;
-        unsigned char           *InputBuffer;
-        ptrdiff_t             cursamp;
-        size_t              FrameCount;
+  struct mad_stream       Stream;
+  struct mad_frame        Frame;
+  struct mad_synth        Synth;
+  mad_timer_t             Timer;
+  unsigned char           *InputBuffer;
+  ptrdiff_t               cursamp;
+  size_t                  FrameCount;
 
-	void (*mad_stream_buffer)(struct mad_stream *, unsigned char const *,
-				  unsigned long);
-	void (*mad_stream_skip)(struct mad_stream *, unsigned long);
-	int (*mad_stream_sync)(struct mad_stream *);
-	void (*mad_stream_init)(struct mad_stream *);
-	void (*mad_frame_init)(struct mad_frame *);
-	void (*mad_synth_init)(struct mad_synth *);
-	int (*mad_frame_decode)(struct mad_frame *, struct mad_stream *);
-	void (*mad_timer_add)(mad_timer_t *, mad_timer_t);
-	void (*mad_synth_frame)(struct mad_synth *, struct mad_frame const *);
-	char const *(*mad_stream_errorstr)(struct mad_stream const *);
-	void (*mad_frame_finish)(struct mad_frame *);
-	void (*mad_stream_finish)(struct mad_stream *);
+  void (*mad_stream_buffer)(struct mad_stream *, unsigned char const *,
+                            unsigned long);
+  void (*mad_stream_skip)(struct mad_stream *, unsigned long);
+  int (*mad_stream_sync)(struct mad_stream *);
+  void (*mad_stream_init)(struct mad_stream *);
+  void (*mad_frame_init)(struct mad_frame *);
+  void (*mad_synth_init)(struct mad_synth *);
+  int (*mad_frame_decode)(struct mad_frame *, struct mad_stream *);
+  void (*mad_timer_add)(mad_timer_t *, mad_timer_t);
+  void (*mad_synth_frame)(struct mad_synth *, struct mad_frame const *);
+  char const *(*mad_stream_errorstr)(struct mad_stream const *);
+  void (*mad_frame_finish)(struct mad_frame *);
+  void (*mad_stream_finish)(struct mad_stream *);
+  unsigned long (*mad_bit_read)(struct mad_bitptr *, unsigned int);
+  int (*mad_header_decode)(struct mad_header *, struct mad_stream *);
+  void (*mad_header_init)(struct mad_header *);
+  signed long (*mad_timer_count)(mad_timer_t, enum mad_units);
+  void (*mad_timer_multiply)(mad_timer_t *, signed long);
+  #if defined HAVE_LIBLTDL && defined DL_MAD
+  lt_dlhandle mad_lth;
+  #endif
 #endif /*HAVE_MAD_H*/
+
 #ifdef HAVE_LAME_LAME_H
-        lame_global_flags       *gfp;
+  lame_global_flags       *gfp;
 
-	lame_global_flags * (*lame_init)(void);
-	int (*lame_set_num_channels)(lame_global_flags *, int);
-	int (*lame_get_num_channels)(const lame_global_flags *);
-	int (*lame_set_in_samplerate)(lame_global_flags *, int);
-	int (*lame_set_bWriteVbrTag)(lame_global_flags *, int);
-	int (*lame_init_params)(lame_global_flags *);
-	int (*lame_set_errorf)(lame_global_flags *, 
-			       void (*func)(const char *, va_list));
-	int (*lame_set_debugf)(lame_global_flags *,
-			       void (*func)(const char *, va_list));
-	int (*lame_set_msgf)(lame_global_flags *,
-			     void (*func)(const char *, va_list));
-	int (*lame_encode_buffer)(lame_global_flags *, const short int[],
-				  const short int[], const int, 
-				  unsigned char *, const int);
-	int (*lame_encode_flush)(lame_global_flags *, unsigned char *,
-				 int);
-	int (*lame_close)(lame_global_flags *);
+  lame_global_flags * (*lame_init)(void);
+  int (*lame_set_num_channels)(lame_global_flags *, int);
+  int (*lame_get_num_channels)(const lame_global_flags *);
+  int (*lame_set_in_samplerate)(lame_global_flags *, int);
+  int (*lame_set_bWriteVbrTag)(lame_global_flags *, int);
+  int (*lame_init_params)(lame_global_flags *);
+  int (*lame_set_errorf)(lame_global_flags *, 
+                         void (*func)(const char *, va_list));
+  int (*lame_set_debugf)(lame_global_flags *,
+                         void (*func)(const char *, va_list));
+  int (*lame_set_msgf)(lame_global_flags *,
+                       void (*func)(const char *, va_list));
+  int (*lame_encode_buffer)(lame_global_flags *, const short int[],
+                            const short int[], const int, 
+                            unsigned char *, const int);
+  int (*lame_encode_flush)(lame_global_flags *, unsigned char *,
+                           int);
+  int (*lame_close)(lame_global_flags *);
+  #if defined HAVE_LIBLTDL && defined DL_LAME
+  lt_dlhandle lame_lth;
+  #endif
 #endif /*HAVE_LAME_LAME_H*/
 } priv_t;
 
@@ -144,7 +168,7 @@
         return SOX_EOF;
     }
 
-    mad_stream_buffer(&p->Stream, p->InputBuffer, bytes_read+remaining);
+    p->mad_stream_buffer(&p->Stream, p->InputBuffer, bytes_read+remaining);
     p->Stream.error = 0;
 
     return SOX_SUCCESS;
@@ -191,23 +215,50 @@
 
 static int startread(sox_format_t * ft)
 {
-    priv_t *p = (priv_t *) ft->priv;
-    size_t ReadSize;
-    sox_bool ignore_length = ft->signal.length == SOX_IGNORE_LENGTH;
+  priv_t *p = (priv_t *) ft->priv;
+  size_t ReadSize;
+  sox_bool ignore_length = ft->signal.length == SOX_IGNORE_LENGTH;
 
-    p->mad_stream_buffer = mad_stream_buffer;
-    p->mad_stream_skip = mad_stream_skip;
-    p->mad_stream_sync = mad_stream_sync;
-    p->mad_stream_init = mad_stream_init;
-    p->mad_frame_init = mad_frame_init;
-    p->mad_synth_init = mad_synth_init;
-    p->mad_frame_decode = mad_frame_decode;
-    p->mad_timer_add = mad_timer_add;
-    p->mad_synth_frame = mad_synth_frame;
-    p->mad_stream_errorstr = mad_stream_errorstr;
-    p->mad_frame_finish = mad_frame_finish;
-    p->mad_stream_finish = mad_stream_finish;
+#if defined HAVE_LIBLTDL && defined DL_MAD
+  #define DL_LIB_NAME "MAD decoder library (libmad"
+  #define LOAD_FN_PTR(x) \
+    if (!(ltptr.ptr = lt_dlsym(p->mad_lth, #x))) { \
+      lsx_fail("incompatible " DL_LIB_NAME " is missing "#x")"); \
+      return SOX_EOF; \
+    } \
+    p->x = ltptr.fn;
+  union {void (* fn)(); lt_ptr ptr;} ltptr;
+  p->mad_lth = lt_dlopenext("libmad");
+  if (!p->mad_lth) {
+    lsx_fail("could not find " DL_LIB_NAME ")");
+    return SOX_EOF;
+  }
+#else
+  #define DL_LIB_NAME
+  #define LOAD_FN_PTR(x) p->x = x;
+#endif 
 
+  LOAD_FN_PTR(mad_bit_read)
+  LOAD_FN_PTR(mad_frame_decode)
+  LOAD_FN_PTR(mad_frame_finish)
+  LOAD_FN_PTR(mad_frame_init)
+  LOAD_FN_PTR(mad_header_decode)
+  LOAD_FN_PTR(mad_header_init)
+  LOAD_FN_PTR(mad_stream_buffer)
+  LOAD_FN_PTR(mad_stream_errorstr)
+  LOAD_FN_PTR(mad_stream_finish)
+  LOAD_FN_PTR(mad_stream_init)
+  LOAD_FN_PTR(mad_stream_skip)
+  LOAD_FN_PTR(mad_stream_sync)
+  LOAD_FN_PTR(mad_synth_frame)
+  LOAD_FN_PTR(mad_synth_init)
+  LOAD_FN_PTR(mad_timer_add)
+  LOAD_FN_PTR(mad_timer_count)
+  LOAD_FN_PTR(mad_timer_multiply)
+
+#undef LOAD_FN_PTR
+#undef DL_LIB_NAME
+
     p->InputBuffer = NULL;
 
     p->InputBuffer=lsx_malloc(INPUT_BUFFER_SIZE);
@@ -220,7 +271,7 @@
       if (!ft->signal.length)
 #endif
         if (!ignore_length)
-          ft->signal.length = mp3_duration_ms(ft->fp, p->InputBuffer);
+          ft->signal.length = mp3_duration_ms(ft, p->InputBuffer);
     }
 
     p->mad_stream_init(&p->Stream);
@@ -384,7 +435,9 @@
   p->mad_stream_finish(&p->Stream);
 
   free(p->InputBuffer);
-
+#if defined HAVE_LIBLTDL && defined DL_MAD
+  lt_dlclose(p->mad_lth);
+#endif
   return SOX_SUCCESS;
 }
 #else /*HAVE_MAD_H*/
@@ -407,19 +460,41 @@
 {
   priv_t *p = (priv_t *) ft->priv;
 
-  p->lame_init = lame_init;
-  p->lame_set_num_channels = lame_set_num_channels;
-  p->lame_get_num_channels = lame_get_num_channels;
-  p->lame_set_in_samplerate = lame_set_in_samplerate;
-  p->lame_set_bWriteVbrTag = lame_set_bWriteVbrTag;
-  p->lame_init_params = lame_init_params;
-  p->lame_set_errorf = lame_set_errorf;
-  p->lame_set_debugf = lame_set_debugf;
-  p->lame_set_msgf = lame_set_msgf;
-  p->lame_encode_buffer = lame_encode_buffer;
-  p->lame_encode_flush = lame_encode_flush;
-  p->lame_close = lame_close;
+#if defined HAVE_LIBLTDL && defined DL_LAME
+  #define DL_LIB_NAME "LAME encoder library (libmp3lame"
+  #define LOAD_FN_PTR(x) \
+    if (!(ltptr.ptr = lt_dlsym(p->lame_lth, #x))) { \
+      lsx_fail("incompatible " DL_LIB_NAME " is missing "#x")"); \
+      return SOX_EOF; \
+    } \
+    p->x = ltptr.fn;
+  union {void (* fn)(); lt_ptr ptr;} ltptr;
+  p->lame_lth = lt_dlopenext("libmp3lame");
+  if (!p->lame_lth) {
+    lsx_fail("could not find " DL_LIB_NAME ")");
+    return SOX_EOF;
+  }
+#else
+  #define DL_LIB_NAME
+  #define LOAD_FN_PTR(x) p->x = x;
+#endif 
 
+  LOAD_FN_PTR(lame_init)
+  LOAD_FN_PTR(lame_set_num_channels)
+  LOAD_FN_PTR(lame_get_num_channels)
+  LOAD_FN_PTR(lame_set_in_samplerate)
+  LOAD_FN_PTR(lame_set_bWriteVbrTag)
+  LOAD_FN_PTR(lame_init_params)
+  LOAD_FN_PTR(lame_set_errorf)
+  LOAD_FN_PTR(lame_set_debugf)
+  LOAD_FN_PTR(lame_set_msgf)
+  LOAD_FN_PTR(lame_encode_buffer)
+  LOAD_FN_PTR(lame_encode_flush)
+  LOAD_FN_PTR(lame_close)
+
+#undef LOAD_FN_PTR
+#undef DL_LIB_NAME
+
   if (ft->encoding.encoding != SOX_ENCODING_MP3) {
     if(ft->encoding.encoding != SOX_ENCODING_UNKNOWN)
       lsx_report("Encoding forced to MP3");
@@ -554,6 +629,9 @@
     lsx_fail_errno(ft, SOX_EOF, "File write failed");
 
   p->lame_close(p->gfp);
+#if defined HAVE_LIBLTDL && defined DL_MAD
+  lt_dlclose(p->lame_lth);
+#endif
   return SOX_SUCCESS;
 }