Imported Upstream version 1.0.26
[platform/upstream/libsndfile.git] / src / common.h
index ed57804..12caf53 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
+** Copyright (C) 1999-2014 Erik de Castro Lopo <erikd@mega-nerd.com>
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU Lesser General Public License as published by
 #      define WARN_UNUSED
 #endif
 
-#define        SF_BUFFER_LEN                   (8192*2)
-#define        SF_FILENAME_LEN                 (512)
+#define        SF_BUFFER_LEN                   (8192)
+#define        SF_FILENAME_LEN                 (1024)
 #define SF_SYSERR_LEN                  (256)
 #define SF_MAX_STRINGS                 (32)
-#define SF_STR_BUFFER_LEN              (8192)
-#define        SF_HEADER_LEN                   (4100 + SF_STR_BUFFER_LEN)
+#define        SF_HEADER_LEN                   (12292)
+#define        SF_PARSELOG_LEN                 (2048)
 
 #define        PSF_SEEK_ERROR                  ((sf_count_t) -1)
 
-
 #define        BITWIDTH2BYTES(x)       (((x) + 7) / 8)
 
 /*     For some reason sizeof returns an unsigned  value which causes
 
 #define                NOT(x)                  (! (x))
 
-#if (COMPILER_IS_GCC == 1)
-#define                SF_MAX(x,y)             ({ \
+#if COMPILER_IS_GCC
+#define                SF_MAX(x, y)    ({ \
                                                                typeof (x) sf_max_x1 = (x) ; \
                                                                typeof (y) sf_max_y1 = (y) ; \
                                                                (void) (&sf_max_x1 == &sf_max_y1) ; \
                                                                sf_max_x1 > sf_max_y1 ? sf_max_x1 : sf_max_y1 ; })
 
-#define                SF_MIN(x,y)             ({ \
+#define                SF_MIN(x, y)    ({ \
                                                                typeof (x) sf_min_x2 = (x) ; \
                                                                typeof (y) sf_min_y2 = (y) ; \
                                                                (void) (&sf_min_x2 == &sf_min_y2) ; \
                                                                sf_min_x2 < sf_min_y2 ? sf_min_x2 : sf_min_y2 ; })
 #else
-#define                SF_MAX(a,b)             ((a) > (b) ? (a) : (b))
-#define                SF_MIN(a,b)             ((a) < (b) ? (a) : (b))
+#define                SF_MAX(a, b)    ((a) > (b) ? (a) : (b))
+#define                SF_MIN(a, b)    ((a) < (b) ? (a) : (b))
 #endif
 
 
-#define                SF_MAX_CHANNELS 256
+#define                COMPILE_TIME_ASSERT(e)  (sizeof (struct { int : - !! (e) ; }))
+
+
+#define                SF_MAX_CHANNELS         1024
 
 
 /*
-*      Macros for spliting the format file of SF_INFI into contrainer type,
+*      Macros for spliting the format file of SF_INFO into container type,
 **     codec type and endian-ness.
 */
 #define SF_CONTAINER(x)                ((x) & SF_FORMAT_TYPEMASK)
@@ -173,6 +175,22 @@ enum
 } ;
 
 /*---------------------------------------------------------------------------------------
+*/
+
+typedef struct
+{      unsigned        kuki_offset ;
+       unsigned        pakt_offset ;
+
+       unsigned        bits_per_sample ;
+       unsigned        frames_per_packet ;
+
+       int64_t         packets ;
+       int64_t         valid_frames ;
+       int32_t         priming_frames ;
+       int32_t         remainder_frames ;
+} ALAC_DECODER_INFO ;
+
+/*---------------------------------------------------------------------------------------
 **     PEAK_CHUNK - This chunk type is common to both AIFF and WAVE files although their
 **     endian encodings are different.
 */
@@ -193,19 +211,8 @@ typedef struct
        /* CAF */
        unsigned int    edit_number ;
 
-#if HAVE_FLEXIBLE_ARRAY
        /* the per channel peak info */
        PEAK_POS                peaks [] ;
-#else
-       /*
-       ** This is not ISO compliant C. It works on some compilers which
-       ** don't support the ISO standard flexible struct array which is
-       ** used above. If your compiler doesn't like this I suggest you find
-       ** youself a 1999 ISO C standards compilant compiler. GCC-3.X is
-       ** highly recommended.
-       */
-       PEAK_POS                peaks [0] ;
-#endif
 } PEAK_INFO ;
 
 static inline PEAK_INFO *
@@ -216,9 +223,44 @@ peak_info_calloc (int channels)
 typedef struct
 {      int             type ;
        int             flags ;
-       char    *str ;
+       size_t  offset ;
 } STR_DATA ;
 
+typedef struct
+{      int64_t         hash ;
+       char            id [64] ;
+       unsigned        id_size ;
+       uint32_t        mark32 ;
+       sf_count_t      offset ;
+       uint32_t        len ;
+} READ_CHUNK ;
+
+typedef struct
+{      int64_t         hash ;
+       uint32_t        mark32 ;
+       uint32_t        len ;
+       void            *data ;
+} WRITE_CHUNK ;
+
+typedef struct
+{      uint32_t        count ;
+       uint32_t        used ;
+       READ_CHUNK      *chunks ;
+} READ_CHUNKS ;
+typedef struct
+{      uint32_t        count ;
+       uint32_t        used ;
+       WRITE_CHUNK     *chunks ;
+} WRITE_CHUNKS ;
+
+struct SF_CHUNK_ITERATOR
+{      uint32_t        current ;
+       int64_t         hash ;
+       char            id [64] ;
+       unsigned        id_size ;
+       SNDFILE         *sndfile ;
+} ;
+
 static inline size_t
 make_size_t (int x)
 {      return (size_t) x ;
@@ -226,12 +268,21 @@ make_size_t (int x)
 
 typedef SF_BROADCAST_INFO_VAR (16 * 1024) SF_BROADCAST_INFO_16K ;
 
+typedef SF_CART_INFO_VAR (16 * 1024) SF_CART_INFO_16K ;
+
 #if SIZEOF_WCHAR_T == 2
 typedef wchar_t        sfwchar_t ;
 #else
 typedef int16_t sfwchar_t ;
 #endif
 
+
+static inline void *
+psf_memdup (const void *src, size_t n)
+{      void * mem = calloc (1, n & 3 ? n + 4 - (n & 3) : n) ;
+       return memcpy (mem, src, n) ;
+} /* psf_memdup */
+
 /*
 **     This version of isprint specifically ignores any locale info. Its used for
 **     determining which characters can be printed in things like hexdumps.
@@ -282,6 +333,24 @@ typedef struct
 } PSF_FILE ;
 
 
+
+typedef union
+{      double                  dbuf    [SF_BUFFER_LEN / sizeof (double)] ;
+#if (defined (SIZEOF_INT64_T) && (SIZEOF_INT64_T == 8))
+       int64_t                 lbuf    [SF_BUFFER_LEN / sizeof (int64_t)] ;
+#else
+       long                    lbuf    [SF_BUFFER_LEN / sizeof (double)] ;
+#endif
+       float                   fbuf    [SF_BUFFER_LEN / sizeof (float)] ;
+       int                             ibuf    [SF_BUFFER_LEN / sizeof (int)] ;
+       short                   sbuf    [SF_BUFFER_LEN / sizeof (short)] ;
+       char                    cbuf    [SF_BUFFER_LEN / sizeof (char)] ;
+       signed char             scbuf   [SF_BUFFER_LEN / sizeof (signed char)] ;
+       unsigned char   ucbuf   [SF_BUFFER_LEN / sizeof (signed char)] ;
+} BUF_UNION ;
+
+
+
 typedef struct sf_private_tag
 {
        /* Canary in a coal mine. */
@@ -291,49 +360,38 @@ typedef struct sf_private_tag
                char c [16] ;
                } canary ;
 
-       /* Force the compiler to double align the start of buffer. */
-       union
-       {       double                  dbuf    [SF_BUFFER_LEN / sizeof (double)] ;
-#if (defined (SIZEOF_INT64_T) && (SIZEOF_INT64_T == 8))
-               int64_t                 lbuf    [SF_BUFFER_LEN / sizeof (int64_t)] ;
-#else
-               long                    lbuf    [SF_BUFFER_LEN / sizeof (double)] ;
-#endif
-               float                   fbuf    [SF_BUFFER_LEN / sizeof (float)] ;
-               int                             ibuf    [SF_BUFFER_LEN / sizeof (int)] ;
-               short                   sbuf    [SF_BUFFER_LEN / sizeof (short)] ;
-               char                    cbuf    [SF_BUFFER_LEN / sizeof (char)] ;
-               signed char             scbuf   [SF_BUFFER_LEN / sizeof (signed char)] ;
-               unsigned char   ucbuf   [SF_BUFFER_LEN / sizeof (signed char)] ;
-               } u ;
-
-
        PSF_FILE                file, rsrc ;
 
        char                    syserr          [SF_SYSERR_LEN] ;
 
-       /* logbuffer and logindex should only be changed within the logging functions
+       /* parselog and indx should only be changed within the logging functions
        ** of common.c
        */
-       char                    logbuffer       [SF_BUFFER_LEN] ;
+       struct
+       {       char                    buf     [SF_PARSELOG_LEN] ;
+               int                             indx ;
+       } parselog ;
+
        unsigned char   header          [SF_HEADER_LEN] ; /* Must be unsigned */
        int                             rwf_endian ;    /* Header endian-ness flag. */
 
        /* Storage and housekeeping data for adding/reading strings from
        ** sound files.
        */
-       STR_DATA                strings [SF_MAX_STRINGS] ;
-       char                    str_storage [SF_STR_BUFFER_LEN] ;
-       char                    *str_end ;
-       int                             str_flags ;
+       struct
+       {       STR_DATA        data [SF_MAX_STRINGS] ;
+               char            *storage ;
+               size_t          storage_len ;
+               size_t          storage_used ;
+               uint32_t        flags ;
+       } strings ;
 
        /* Guard value. If this changes the buffers above have overflowed. */
        int                             Magick ;
 
        unsigned                unique_id ;
 
-       /* Index variables for maintaining logbuffer and header above. */
-       int                             logindex ;
+       /* Index variables for maintaining parselog and header above. */
        int                             headindex, headend ;
        int                             has_text ;
 
@@ -370,6 +428,9 @@ typedef struct sf_private_tag
        /* Broadcast (EBU) Info */
        SF_BROADCAST_INFO_16K *broadcast_16k ;
 
+       /* Cart (AES46) Info */
+       SF_CART_INFO_16K *cart_16k ;
+
        /* Channel map data (if present) : an array of ints. */
        int                             *channel_map ;
 
@@ -424,6 +485,7 @@ typedef struct sf_private_tag
        sf_count_t              (*seek)                 (struct sf_private_tag*, int mode, sf_count_t samples_from_start) ;
        int                             (*write_header) (struct sf_private_tag*, int calc_length) ;
        int                             (*command)              (struct sf_private_tag*, int command, void *data, int datasize) ;
+       int                             (*byterate)             (struct sf_private_tag*) ;
 
        /*
        **      Separate close functions for the codec and the container.
@@ -438,6 +500,17 @@ typedef struct sf_private_tag
        int                                     virtual_io ;
        SF_VIRTUAL_IO           vio ;
        void                            *vio_user_data ;
+
+       /* Chunk get/set. */
+       SF_CHUNK_ITERATOR       *iterator ;
+
+       READ_CHUNKS                     rchunks ;
+       WRITE_CHUNKS            wchunks ;
+
+       int                                     (*set_chunk)            (struct sf_private_tag*, const SF_CHUNK_INFO * chunk_info) ;
+       SF_CHUNK_ITERATOR *     (*next_chunk_iterator)  (struct sf_private_tag*, SF_CHUNK_ITERATOR * iterator) ;
+       int                                     (*get_chunk_size)       (struct sf_private_tag*, const SF_CHUNK_ITERATOR * iterator, SF_CHUNK_INFO * chunk_info) ;
+       int                                     (*get_chunk_data)       (struct sf_private_tag*, const SF_CHUNK_ITERATOR * iterator, SF_CHUNK_INFO * chunk_info) ;
 } SF_PRIVATE ;
 
 
@@ -460,6 +533,7 @@ enum
        SFE_BAD_FILE_PTR,
        SFE_BAD_INT_PTR,
        SFE_BAD_STAT_SIZE,
+       SFE_NO_TEMP_DIR,
        SFE_MALLOC_FAILED,
        SFE_UNIMPLEMENTED,
        SFE_BAD_READ_ALIGN,
@@ -499,6 +573,8 @@ enum
        SFE_CMD_HAS_DATA,
        SFE_BAD_BROADCAST_INFO_SIZE,
        SFE_BAD_BROADCAST_INFO_TOO_BIG,
+       SFE_BAD_CART_INFO_SIZE,
+       SFE_BAD_CART_INFO_TOO_BIG,
 
        SFE_STR_NO_SUPPORT,
        SFE_STR_NOT_WRITE,
@@ -523,6 +599,7 @@ enum
        SFE_WAV_BAD_LIST,
        SFE_WAV_ADPCM_NOT4BIT,
        SFE_WAV_ADPCM_CHANNELS,
+       SFE_WAV_ADPCM_SAMPLES,
        SFE_WAV_GSM610_FORMAT,
        SFE_WAV_UNKNOWN_CHUNK,
        SFE_WAV_WVPK_DATA,
@@ -631,6 +708,13 @@ enum
        SFE_VORBIS_ENCODER_BUG,
 
        SFE_RF64_NOT_RF64,
+       SFE_BAD_CHUNK_PTR,
+       SFE_UNKNOWN_CHUNK,
+       SFE_BAD_CHUNK_FORMAT,
+       SFE_BAD_CHUNK_MARKER,
+       SFE_BAD_CHUNK_DATA_PTR,
+       SFE_ALAC_FAIL_TMPFILE,
+       SFE_FILENAME_TOO_LONG,
 
        SFE_MAX_ERROR                   /* This must be last in list. */
 } ;
@@ -642,13 +726,13 @@ int u_bitwidth_to_subformat (int bits) ;
 /*  Functions for reading and writing floats and doubles on processors
 **     with non-IEEE floats/doubles.
 */
-float  float32_be_read         (unsigned char *cptr) ;
-float  float32_le_read         (unsigned char *cptr) ;
+float  float32_be_read         (const unsigned char *cptr) ;
+float  float32_le_read         (const unsigned char *cptr) ;
 void   float32_be_write        (float in, unsigned char *out) ;
 void   float32_le_write        (float in, unsigned char *out) ;
 
-double double64_be_read        (unsigned char *cptr) ;
-double double64_le_read        (unsigned char *cptr) ;
+double double64_be_read        (const unsigned char *cptr) ;
+double double64_le_read        (const unsigned char *cptr) ;
 void   double64_be_write       (double in, unsigned char *out) ;
 void   double64_le_write       (double in, unsigned char *out) ;
 
@@ -662,6 +746,8 @@ int32_t     psf_rand_int32 (void) ;
 void append_snprintf (char * dest, size_t maxlen, const char * fmt, ...) ;
 void psf_strlcpy_crlf (char *dest, const char *src, size_t destmax, size_t srcmax) ;
 
+sf_count_t psf_decode_frame_count (SF_PRIVATE *psf) ;
+
 /* Functions used when writing file headers. */
 
 int            psf_binheader_writef    (SF_PRIVATE *psf, const char *format, ...) ;
@@ -774,15 +860,16 @@ int               caf_open        (SF_PRIVATE *psf) ;
 int            mpc2k_open      (SF_PRIVATE *psf) ;
 int            rf64_open       (SF_PRIVATE *psf) ;
 
-/* In progress. Do not currently work. */
-
 int            ogg_vorbis_open (SF_PRIVATE *psf) ;
 int            ogg_speex_open  (SF_PRIVATE *psf) ;
 int            ogg_pcm_open    (SF_PRIVATE *psf) ;
+int            ogg_opus_open   (SF_PRIVATE *psf) ;
+int            ogg_open        (SF_PRIVATE *psf) ;
 
 
+/* In progress. Do not currently work. */
+
 int            mpeg_open       (SF_PRIVATE *psf) ;
-int            ogg_open        (SF_PRIVATE *psf) ;
 int            rx2_open        (SF_PRIVATE *psf) ;
 int            txw_open        (SF_PRIVATE *psf) ;
 int            wve_open        (SF_PRIVATE *psf) ;
@@ -804,6 +891,7 @@ int         gsm610_init             (SF_PRIVATE *psf) ;
 int            vox_adpcm_init  (SF_PRIVATE *psf) ;
 int            flac_init               (SF_PRIVATE *psf) ;
 int            g72x_init               (SF_PRIVATE * psf) ;
+int            alac_init               (SF_PRIVATE *psf, const ALAC_DECODER_INFO * info) ;
 
 int    dither_init             (SF_PRIVATE *psf, int mode) ;
 
@@ -818,18 +906,27 @@ int               interleave_init (SF_PRIVATE *psf) ;
 ** Chunk logging functions.
 */
 
-typedef struct
-{      struct
-       {       int chunk ;
-               sf_count_t offset ;
-               sf_count_t len ;
-       } l [100] ;
+SF_CHUNK_ITERATOR * psf_get_chunk_iterator (SF_PRIVATE * psf, const char * marker_str) ;
+SF_CHUNK_ITERATOR * psf_next_chunk_iterator (const READ_CHUNKS * pchk , SF_CHUNK_ITERATOR *iterator) ;
+int            psf_store_read_chunk_u32 (READ_CHUNKS * pchk, uint32_t marker, sf_count_t offset, uint32_t len) ;
+int            psf_store_read_chunk_str (READ_CHUNKS * pchk, const char * marker, sf_count_t offset, uint32_t len) ;
+int            psf_save_write_chunk (WRITE_CHUNKS * pchk, const SF_CHUNK_INFO * chunk_info) ;
+int            psf_find_read_chunk_str (const READ_CHUNKS * pchk, const char * marker) ;
+int            psf_find_read_chunk_m32 (const READ_CHUNKS * pchk, uint32_t marker) ;
+int            psf_find_read_chunk_iterator (const READ_CHUNKS * pchk, const SF_CHUNK_ITERATOR * marker) ;
 
-       int count ;
-} PRIV_CHUNK4 ;
+int            psf_find_write_chunk (WRITE_CHUNKS * pchk, const char * marker) ;
 
-void pchk4_store (PRIV_CHUNK4 * pchk, int marker, sf_count_t offset, sf_count_t len) ;
-int pchk4_find (PRIV_CHUNK4 * pchk, int marker) ;
+static inline int
+fourcc_to_marker (const SF_CHUNK_INFO * chunk_info)
+{      const unsigned char * cptr ;
+
+       if (chunk_info->id_size != 4)
+               return 0 ;
+
+       cptr = (const unsigned char *) chunk_info->id ;
+       return (cptr [3] << 24) + (cptr [2] << 16) + (cptr [1] << 8) + cptr [0] ;
+} /* fourcc_to_marker */
 
 /*------------------------------------------------------------------------------------
 ** Functions that work like OpenBSD's strlcpy/strlcat to replace strncpy/strncat.
@@ -873,6 +970,10 @@ int                broadcast_var_set (SF_PRIVATE *psf, const SF_BROADCAST_INFO * data, size_t
 int            broadcast_var_get (SF_PRIVATE *psf, SF_BROADCAST_INFO * data, size_t datasize) ;
 
 
+SF_CART_INFO_16K * cart_var_alloc (void) ;
+int            cart_var_set (SF_PRIVATE *psf, const SF_CART_INFO * date, size_t datasize) ;
+int            cart_var_get (SF_PRIVATE *psf, SF_CART_INFO * data, size_t datasize) ;
+
 typedef struct
 {      int channels ;
        int endianness ;
@@ -881,6 +982,10 @@ typedef struct
 int audio_detect (SF_PRIVATE * psf, AUDIO_DETECT *ad, const unsigned char * data, int datalen) ;
 int id3_skip (SF_PRIVATE * psf) ;
 
+void   alac_get_desc_chunk_items (int subformat, uint32_t *fmt_flags, uint32_t *frames_per_packet) ;
+
+FILE * psf_open_tmpfile (char * fname, size_t fnamelen) ;
+
 /*------------------------------------------------------------------------------------
 ** Helper/debug functions.
 */
@@ -915,5 +1020,45 @@ int sf_dither_float               (const SF_DITHER_INFO *dither, const float *in, float *out,
 int sf_dither_double   (const SF_DITHER_INFO *dither, const double *in, double *out, int count) ;
 #endif
 
-#endif /* SNDFILE_COMMON_H */
+/*------------------------------------------------------------------------------------
+** Data conversion functions.
+*/
+
+void psf_f2s_array (const float *src, short *dest, int count, int normalize) ;
+void psf_f2s_clip_array (const float *src, short *dest, int count, int normalize) ;
+
+void psf_d2s_array (const double *src, short *dest, int count, int normalize) ;
+void psf_d2s_clip_array (const double *src, short *dest, int count, int normalize) ;
+
+void psf_f2i_array (const float *src, int *dest, int count, int normalize) ;
+void psf_f2i_clip_array (const float *src, int *dest, int count, int normalize) ;
+
+void psf_d2i_array (const double *src, int *dest, int count, int normalize) ;
+void psf_d2i_clip_array (const double *src, int *dest, int count, int normalize) ;
+
 
+/*------------------------------------------------------------------------------------
+** Left and right shift on int. According to the C standard, the left and right
+** shift operations applied to a negative integer results in undefined behavior.
+** These twp functions work around that.
+*/
+
+#if __GNUC__
+#define ALWAYS_INLINE          __attribute__ ((always_inline))
+#else
+#define ALWAYS_INLINE
+#endif
+
+static inline int32_t ALWAYS_INLINE
+arith_shift_left (int32_t x, int shift)
+{      return (int32_t) (((uint32_t) x) << shift) ;
+} /* arith_shift_left */
+
+static inline int32_t ALWAYS_INLINE
+arith_shift_right (int32_t x, int shift)
+{      if (x >= 0)
+               return x >> shift ;
+       return ~ ((~x) >> shift) ;
+} /* arith_shift_right */
+
+#endif /* SNDFILE_COMMON_H */