gst_plugins_base/gst/audioconvert/audioconvert.c
changeset 0 0e761a78d257
child 8 4a7fac7dd34a
equal deleted inserted replaced
-1:000000000000 0:0e761a78d257
       
     1 /* GStreamer
       
     2  * Copyright (C) 2005 Wim Taymans <wim at fluendo dot com>
       
     3  *
       
     4  * audioconvert.c: Convert audio to different audio formats automatically
       
     5  *
       
     6  * This library is free software; you can redistribute it and/or
       
     7  * modify it under the terms of the GNU Library General Public
       
     8  * License as published by the Free Software Foundation; either
       
     9  * version 2 of the License, or (at your option) any later version.
       
    10  *
       
    11  * This library is distributed in the hope that it will be useful,
       
    12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    14  * Library General Public License for more details.
       
    15  *
       
    16  * You should have received a copy of the GNU Library General Public
       
    17  * License along with this library; if not, write to the
       
    18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
       
    19  * Boston, MA 02111-1307, USA.
       
    20  */
       
    21 
       
    22 #ifdef HAVE_CONFIG_H
       
    23 #include "config.h"
       
    24 #endif
       
    25 
       
    26 #include <math.h>
       
    27 #include <string.h>
       
    28 
       
    29 #include "gstchannelmix.h"
       
    30 #include "gstaudioquantize.h"
       
    31 #include "audioconvert.h"
       
    32 #include "gst/floatcast/floatcast.h"
       
    33 
       
    34 /* sign bit in the intermediate format */
       
    35 #define SIGNED  (1U<<31)
       
    36 
       
    37 /*** 
       
    38  * unpack code
       
    39  */
       
    40 #define MAKE_UNPACK_FUNC_NAME(name)                                     \
       
    41 audio_convert_unpack_##name
       
    42 
       
    43 /* unpack from integer to signed integer 32 */
       
    44 #define MAKE_UNPACK_FUNC_II(name, stride, sign, READ_FUNC)              \
       
    45 static void                                                             \
       
    46 MAKE_UNPACK_FUNC_NAME (name) (guint8 *src, gint32 *dst,                 \
       
    47         gint scale, gint count)                                         \
       
    48 {                                                                       \
       
    49   for (;count; count--) {                                               \
       
    50     *dst++ = (((gint32) READ_FUNC (src)) << scale) ^ (sign);            \
       
    51     src+=stride;                                                        \
       
    52   }                                                                     \
       
    53 }
       
    54 
       
    55 /* unpack from float to signed integer 32 */
       
    56 #define MAKE_UNPACK_FUNC_FI(name, type, READ_FUNC)                            \
       
    57 static void                                                                   \
       
    58 MAKE_UNPACK_FUNC_NAME (name) (type * src, gint32 * dst, gint s, gint count)   \
       
    59 {                                                                             \
       
    60   gdouble temp;                                                               \
       
    61                                                                               \
       
    62   for (; count; count--) {                                                    \
       
    63     /* blow up to 32 bit */                                                   \
       
    64     temp = floor ((READ_FUNC (*src++) * 2147483647.0) + 0.5);                 \
       
    65     *dst++ = (gint32) CLAMP (temp, G_MININT32, G_MAXINT32);                   \
       
    66   }                                                                           \
       
    67 }
       
    68 
       
    69 
       
    70 /* unpack from float to float 64 (double) */
       
    71 #define MAKE_UNPACK_FUNC_FF(name, type, FUNC)                                 \
       
    72 static void                                                                   \
       
    73 MAKE_UNPACK_FUNC_NAME (name) (type * src, gdouble * dst, gint s,              \
       
    74     gint count)                                                               \
       
    75 {                                                                             \
       
    76   for (; count; count--)                                                      \
       
    77     *dst++ = (gdouble) FUNC (*src++);                                         \
       
    78 }
       
    79 
       
    80 /* unpack from int to float 64 (double) */
       
    81 #define MAKE_UNPACK_FUNC_IF(name, stride, sign, READ_FUNC)                    \
       
    82 static void                                                                   \
       
    83 MAKE_UNPACK_FUNC_NAME (name) (guint8 * src, gdouble * dst, gint scale,        \
       
    84     gint count)                                                               \
       
    85 {                                                                             \
       
    86   gdouble tmp;                                                                \
       
    87   for (; count; count--) {                                                    \
       
    88     tmp = (gdouble) ((((gint32) READ_FUNC (src)) << scale) ^ (sign));         \
       
    89     *dst++ = tmp * (1.0 / 2147483647.0);                                      \
       
    90     src += stride;                                                            \
       
    91   }                                                                           \
       
    92 }
       
    93 
       
    94 #define READ8(p)          GST_READ_UINT8(p)
       
    95 #define READ16_FROM_LE(p) GST_READ_UINT16_LE (p)
       
    96 #define READ16_FROM_BE(p) GST_READ_UINT16_BE (p)
       
    97 #define READ24_FROM_LE(p) (p[0] | (p[1] << 8) | (p[2] << 16))
       
    98 #define READ24_FROM_BE(p) (p[2] | (p[1] << 8) | (p[0] << 16))
       
    99 #define READ32_FROM_LE(p) GST_READ_UINT32_LE (p)
       
   100 #define READ32_FROM_BE(p) GST_READ_UINT32_BE (p)
       
   101 
       
   102 MAKE_UNPACK_FUNC_II (u8, 1, SIGNED, READ8);
       
   103 MAKE_UNPACK_FUNC_II (s8, 1, 0, READ8);
       
   104 MAKE_UNPACK_FUNC_II (u16_le, 2, SIGNED, READ16_FROM_LE);
       
   105 MAKE_UNPACK_FUNC_II (s16_le, 2, 0, READ16_FROM_LE);
       
   106 MAKE_UNPACK_FUNC_II (u16_be, 2, SIGNED, READ16_FROM_BE);
       
   107 MAKE_UNPACK_FUNC_II (s16_be, 2, 0, READ16_FROM_BE);
       
   108 MAKE_UNPACK_FUNC_II (u24_le, 3, SIGNED, READ24_FROM_LE);
       
   109 MAKE_UNPACK_FUNC_II (s24_le, 3, 0, READ24_FROM_LE);
       
   110 MAKE_UNPACK_FUNC_II (u24_be, 3, SIGNED, READ24_FROM_BE);
       
   111 MAKE_UNPACK_FUNC_II (s24_be, 3, 0, READ24_FROM_BE);
       
   112 MAKE_UNPACK_FUNC_II (u32_le, 4, SIGNED, READ32_FROM_LE);
       
   113 MAKE_UNPACK_FUNC_II (s32_le, 4, 0, READ32_FROM_LE);
       
   114 MAKE_UNPACK_FUNC_II (u32_be, 4, SIGNED, READ32_FROM_BE);
       
   115 MAKE_UNPACK_FUNC_II (s32_be, 4, 0, READ32_FROM_BE);
       
   116 MAKE_UNPACK_FUNC_FI (float_le, gfloat, GFLOAT_FROM_LE);
       
   117 MAKE_UNPACK_FUNC_FI (float_be, gfloat, GFLOAT_FROM_BE);
       
   118 MAKE_UNPACK_FUNC_FI (double_le, gdouble, GDOUBLE_FROM_LE);
       
   119 MAKE_UNPACK_FUNC_FI (double_be, gdouble, GDOUBLE_FROM_BE);
       
   120 MAKE_UNPACK_FUNC_FF (float_hq_le, gfloat, GFLOAT_FROM_LE);
       
   121 MAKE_UNPACK_FUNC_FF (float_hq_be, gfloat, GFLOAT_FROM_BE);
       
   122 MAKE_UNPACK_FUNC_FF (double_hq_le, gdouble, GDOUBLE_FROM_LE);
       
   123 MAKE_UNPACK_FUNC_FF (double_hq_be, gdouble, GDOUBLE_FROM_BE);
       
   124 MAKE_UNPACK_FUNC_IF (u8_float, 1, SIGNED, READ8);
       
   125 MAKE_UNPACK_FUNC_IF (s8_float, 1, 0, READ8);
       
   126 MAKE_UNPACK_FUNC_IF (u16_le_float, 2, SIGNED, READ16_FROM_LE);
       
   127 MAKE_UNPACK_FUNC_IF (s16_le_float, 2, 0, READ16_FROM_LE);
       
   128 MAKE_UNPACK_FUNC_IF (u16_be_float, 2, SIGNED, READ16_FROM_BE);
       
   129 MAKE_UNPACK_FUNC_IF (s16_be_float, 2, 0, READ16_FROM_BE);
       
   130 MAKE_UNPACK_FUNC_IF (u24_le_float, 3, SIGNED, READ24_FROM_LE);
       
   131 MAKE_UNPACK_FUNC_IF (s24_le_float, 3, 0, READ24_FROM_LE);
       
   132 MAKE_UNPACK_FUNC_IF (u24_be_float, 3, SIGNED, READ24_FROM_BE);
       
   133 MAKE_UNPACK_FUNC_IF (s24_be_float, 3, 0, READ24_FROM_BE);
       
   134 MAKE_UNPACK_FUNC_IF (u32_le_float, 4, SIGNED, READ32_FROM_LE);
       
   135 MAKE_UNPACK_FUNC_IF (s32_le_float, 4, 0, READ32_FROM_LE);
       
   136 MAKE_UNPACK_FUNC_IF (u32_be_float, 4, SIGNED, READ32_FROM_BE);
       
   137 MAKE_UNPACK_FUNC_IF (s32_be_float, 4, 0, READ32_FROM_BE);
       
   138 
       
   139 /* One of the double_hq_* functions generated above is ineffecient, but it's
       
   140  * never used anyway.  The same is true for one of the s32_* functions. */
       
   141 
       
   142 /*** 
       
   143  * packing code
       
   144  */
       
   145 #define MAKE_PACK_FUNC_NAME(name)                                       \
       
   146 audio_convert_pack_##name
       
   147 
       
   148 /*
       
   149  * These functions convert the signed 32 bit integers to the
       
   150  * target format. For this to work the following steps are done:
       
   151  *
       
   152  * 1) If the output format is unsigned we will XOR the sign bit. This
       
   153  *    will do the same as if we add 1<<31.
       
   154  * 2) Afterwards we shift to the target depth. It's necessary to left-shift
       
   155  *    on signed values here to get arithmetical shifting.
       
   156  * 3) This is then written into our target array by the corresponding write
       
   157  *    function for the target width.
       
   158  */
       
   159 
       
   160 /* pack from signed integer 32 to integer */
       
   161 #define MAKE_PACK_FUNC_II(name, stride, sign, WRITE_FUNC)               \
       
   162 static void                                                             \
       
   163 MAKE_PACK_FUNC_NAME (name) (gint32 *src, guint8 * dst,                  \
       
   164         gint scale, gint count)                                         \
       
   165 {                                                                       \
       
   166   gint32 tmp;                                                           \
       
   167   for (;count; count--) {                                               \
       
   168     tmp = (*src++ ^ (sign)) >> scale;                                   \
       
   169     WRITE_FUNC (dst, tmp);                                              \
       
   170     dst += stride;                                                      \
       
   171   }                                                                     \
       
   172 }
       
   173 
       
   174 /* pack from signed integer 32 to float */
       
   175 #define MAKE_PACK_FUNC_IF(name, type, FUNC)                             \
       
   176 static void                                                             \
       
   177 MAKE_PACK_FUNC_NAME (name) (gint32 * src, type * dst, gint scale,       \
       
   178     gint count)                                                         \
       
   179 {                                                                       \
       
   180   for (; count; count--)                                                \
       
   181     *dst++ = FUNC ((type) ((*src++) * (1.0 / 2147483647.0)));           \
       
   182 }
       
   183 
       
   184 /* pack from float 64 (double) to float */
       
   185 #define MAKE_PACK_FUNC_FF(name, type, FUNC)                             \
       
   186 static void                                                             \
       
   187 MAKE_PACK_FUNC_NAME (name) (gdouble * src, type * dst, gint s,          \
       
   188     gint count)                                                         \
       
   189 {                                                                       \
       
   190   for (; count; count--)                                                \
       
   191     *dst++ = FUNC ((type) (*src++));                                    \
       
   192 }
       
   193 
       
   194 /* pack from float 64 (double) to signed int.
       
   195  * the floats are already in the correct range. Only a cast is needed.
       
   196  */
       
   197 #define MAKE_PACK_FUNC_FI_S(name, stride, WRITE_FUNC)                   \
       
   198 static void                                                             \
       
   199 MAKE_PACK_FUNC_NAME (name) (gdouble * src, guint8 * dst, gint scale,    \
       
   200     gint count)                                                         \
       
   201 {                                                                       \
       
   202   gint32 tmp;                                                           \
       
   203   for (; count; count--) {                                              \
       
   204     tmp = (gint32) (*src);                                              \
       
   205     WRITE_FUNC (dst, tmp);                                              \
       
   206     src++;                                                              \
       
   207     dst += stride;                                                      \
       
   208   }                                                                     \
       
   209 }
       
   210 
       
   211 /* pack from float 64 (double) to unsigned int.
       
   212  * the floats are already in the correct range. Only a cast is needed
       
   213  * and an addition of 2^(target_depth-1) to get in the correct unsigned
       
   214  * range. */
       
   215 #define MAKE_PACK_FUNC_FI_U(name, stride, WRITE_FUNC)                   \
       
   216 static void                                                             \
       
   217 MAKE_PACK_FUNC_NAME (name) (gdouble * src, guint8 * dst, gint scale,    \
       
   218     gint count)                                                         \
       
   219 {                                                                       \
       
   220   guint32 tmp;                                                          \
       
   221   gdouble limit = (1U<<(32-scale-1));                                   \
       
   222   for (; count; count--) {                                              \
       
   223     tmp = (guint32) (*src + limit);                                     \
       
   224     WRITE_FUNC (dst, tmp);                                              \
       
   225     src++;                                                              \
       
   226     dst += stride;                                                      \
       
   227   }                                                                     \
       
   228 }
       
   229 
       
   230 #define WRITE8(p, v)       GST_WRITE_UINT8 (p, v)
       
   231 #define WRITE16_TO_LE(p,v) GST_WRITE_UINT16_LE (p, (guint16)(v))
       
   232 #define WRITE16_TO_BE(p,v) GST_WRITE_UINT16_BE (p, (guint16)(v))
       
   233 #define WRITE24_TO_LE(p,v) p[0] = v & 0xff; p[1] = (v >> 8) & 0xff; p[2] = (v >> 16) & 0xff
       
   234 #define WRITE24_TO_BE(p,v) p[2] = v & 0xff; p[1] = (v >> 8) & 0xff; p[0] = (v >> 16) & 0xff
       
   235 #define WRITE32_TO_LE(p,v) GST_WRITE_UINT32_LE (p, (guint32)(v))
       
   236 #define WRITE32_TO_BE(p,v) GST_WRITE_UINT32_BE (p, (guint32)(v))
       
   237 
       
   238 MAKE_PACK_FUNC_II (u8, 1, SIGNED, WRITE8);
       
   239 MAKE_PACK_FUNC_II (s8, 1, 0, WRITE8);
       
   240 MAKE_PACK_FUNC_II (u16_le, 2, SIGNED, WRITE16_TO_LE);
       
   241 MAKE_PACK_FUNC_II (s16_le, 2, 0, WRITE16_TO_LE);
       
   242 MAKE_PACK_FUNC_II (u16_be, 2, SIGNED, WRITE16_TO_BE);
       
   243 MAKE_PACK_FUNC_II (s16_be, 2, 0, WRITE16_TO_BE);
       
   244 MAKE_PACK_FUNC_II (u24_le, 3, SIGNED, WRITE24_TO_LE);
       
   245 MAKE_PACK_FUNC_II (s24_le, 3, 0, WRITE24_TO_LE);
       
   246 MAKE_PACK_FUNC_II (u24_be, 3, SIGNED, WRITE24_TO_BE);
       
   247 MAKE_PACK_FUNC_II (s24_be, 3, 0, WRITE24_TO_BE);
       
   248 MAKE_PACK_FUNC_II (u32_le, 4, SIGNED, WRITE32_TO_LE);
       
   249 MAKE_PACK_FUNC_II (s32_le, 4, 0, WRITE32_TO_LE);
       
   250 MAKE_PACK_FUNC_II (u32_be, 4, SIGNED, WRITE32_TO_BE);
       
   251 MAKE_PACK_FUNC_II (s32_be, 4, 0, WRITE32_TO_BE);
       
   252 MAKE_PACK_FUNC_IF (float_le, gfloat, GFLOAT_TO_LE);
       
   253 MAKE_PACK_FUNC_IF (float_be, gfloat, GFLOAT_TO_BE);
       
   254 MAKE_PACK_FUNC_IF (double_le, gdouble, GDOUBLE_TO_LE);
       
   255 MAKE_PACK_FUNC_IF (double_be, gdouble, GDOUBLE_TO_BE);
       
   256 MAKE_PACK_FUNC_FF (float_hq_le, gfloat, GFLOAT_TO_LE);
       
   257 MAKE_PACK_FUNC_FF (float_hq_be, gfloat, GFLOAT_TO_BE);
       
   258 MAKE_PACK_FUNC_FI_U (u8_float, 1, WRITE8);
       
   259 MAKE_PACK_FUNC_FI_S (s8_float, 1, WRITE8);
       
   260 MAKE_PACK_FUNC_FI_U (u16_le_float, 2, WRITE16_TO_LE);
       
   261 MAKE_PACK_FUNC_FI_S (s16_le_float, 2, WRITE16_TO_LE);
       
   262 MAKE_PACK_FUNC_FI_U (u16_be_float, 2, WRITE16_TO_BE);
       
   263 MAKE_PACK_FUNC_FI_S (s16_be_float, 2, WRITE16_TO_BE);
       
   264 MAKE_PACK_FUNC_FI_U (u24_le_float, 3, WRITE24_TO_LE);
       
   265 MAKE_PACK_FUNC_FI_S (s24_le_float, 3, WRITE24_TO_LE);
       
   266 MAKE_PACK_FUNC_FI_U (u24_be_float, 3, WRITE24_TO_BE);
       
   267 MAKE_PACK_FUNC_FI_S (s24_be_float, 3, WRITE24_TO_BE);
       
   268 MAKE_PACK_FUNC_FI_U (u32_le_float, 4, WRITE32_TO_LE);
       
   269 MAKE_PACK_FUNC_FI_S (s32_le_float, 4, WRITE32_TO_LE);
       
   270 MAKE_PACK_FUNC_FI_U (u32_be_float, 4, WRITE32_TO_BE);
       
   271 MAKE_PACK_FUNC_FI_S (s32_be_float, 4, WRITE32_TO_BE);
       
   272 
       
   273 /* For double_hq, packing and unpacking is the same, so we reuse the unpacking
       
   274  * functions here. */
       
   275 #define audio_convert_pack_double_hq_le MAKE_UNPACK_FUNC_NAME (double_hq_le)
       
   276 #define audio_convert_pack_double_hq_be MAKE_UNPACK_FUNC_NAME (double_hq_be)
       
   277 
       
   278 static AudioConvertUnpack unpack_funcs[] = {
       
   279   (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (u8),
       
   280   (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (s8),
       
   281   (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (u8),
       
   282   (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (s8),
       
   283   (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (u16_le),
       
   284   (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (s16_le),
       
   285   (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (u16_be),
       
   286   (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (s16_be),
       
   287   (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (u24_le),
       
   288   (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (s24_le),
       
   289   (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (u24_be),
       
   290   (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (s24_be),
       
   291   (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (u32_le),
       
   292   (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (s32_le),
       
   293   (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (u32_be),
       
   294   (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (s32_be),
       
   295   (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (float_le),
       
   296   (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (float_be),
       
   297   (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (double_le),
       
   298   (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (double_be),
       
   299   (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (float_hq_le),
       
   300   (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (float_hq_be),
       
   301   (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (double_hq_le),
       
   302   (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (double_hq_be),
       
   303   (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (u8_float),
       
   304   (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (s8_float),
       
   305   (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (u8_float),
       
   306   (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (s8_float),
       
   307   (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (u16_le_float),
       
   308   (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (s16_le_float),
       
   309   (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (u16_be_float),
       
   310   (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (s16_be_float),
       
   311   (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (u24_le_float),
       
   312   (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (s24_le_float),
       
   313   (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (u24_be_float),
       
   314   (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (s24_be_float),
       
   315   (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (u32_le_float),
       
   316   (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (s32_le_float),
       
   317   (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (u32_be_float),
       
   318   (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (s32_be_float),
       
   319 };
       
   320 
       
   321 static AudioConvertPack pack_funcs[] = {
       
   322   (AudioConvertPack) MAKE_PACK_FUNC_NAME (u8),
       
   323   (AudioConvertPack) MAKE_PACK_FUNC_NAME (s8),
       
   324   (AudioConvertPack) MAKE_PACK_FUNC_NAME (u8),
       
   325   (AudioConvertPack) MAKE_PACK_FUNC_NAME (s8),
       
   326   (AudioConvertPack) MAKE_PACK_FUNC_NAME (u16_le),
       
   327   (AudioConvertPack) MAKE_PACK_FUNC_NAME (s16_le),
       
   328   (AudioConvertPack) MAKE_PACK_FUNC_NAME (u16_be),
       
   329   (AudioConvertPack) MAKE_PACK_FUNC_NAME (s16_be),
       
   330   (AudioConvertPack) MAKE_PACK_FUNC_NAME (u24_le),
       
   331   (AudioConvertPack) MAKE_PACK_FUNC_NAME (s24_le),
       
   332   (AudioConvertPack) MAKE_PACK_FUNC_NAME (u24_be),
       
   333   (AudioConvertPack) MAKE_PACK_FUNC_NAME (s24_be),
       
   334   (AudioConvertPack) MAKE_PACK_FUNC_NAME (u32_le),
       
   335   (AudioConvertPack) MAKE_PACK_FUNC_NAME (s32_le),
       
   336   (AudioConvertPack) MAKE_PACK_FUNC_NAME (u32_be),
       
   337   (AudioConvertPack) MAKE_PACK_FUNC_NAME (s32_be),
       
   338   (AudioConvertPack) MAKE_PACK_FUNC_NAME (float_le),
       
   339   (AudioConvertPack) MAKE_PACK_FUNC_NAME (float_be),
       
   340   (AudioConvertPack) MAKE_PACK_FUNC_NAME (double_le),
       
   341   (AudioConvertPack) MAKE_PACK_FUNC_NAME (double_be),
       
   342   (AudioConvertPack) MAKE_PACK_FUNC_NAME (float_hq_le),
       
   343   (AudioConvertPack) MAKE_PACK_FUNC_NAME (float_hq_be),
       
   344   (AudioConvertPack) MAKE_PACK_FUNC_NAME (double_hq_le),
       
   345   (AudioConvertPack) MAKE_PACK_FUNC_NAME (double_hq_be),
       
   346   (AudioConvertPack) MAKE_PACK_FUNC_NAME (u8_float),
       
   347   (AudioConvertPack) MAKE_PACK_FUNC_NAME (s8_float),
       
   348   (AudioConvertPack) MAKE_PACK_FUNC_NAME (u8_float),
       
   349   (AudioConvertPack) MAKE_PACK_FUNC_NAME (s8_float),
       
   350   (AudioConvertPack) MAKE_PACK_FUNC_NAME (u16_le_float),
       
   351   (AudioConvertPack) MAKE_PACK_FUNC_NAME (s16_le_float),
       
   352   (AudioConvertPack) MAKE_PACK_FUNC_NAME (u16_be_float),
       
   353   (AudioConvertPack) MAKE_PACK_FUNC_NAME (s16_be_float),
       
   354   (AudioConvertPack) MAKE_PACK_FUNC_NAME (u24_le_float),
       
   355   (AudioConvertPack) MAKE_PACK_FUNC_NAME (s24_le_float),
       
   356   (AudioConvertPack) MAKE_PACK_FUNC_NAME (u24_be_float),
       
   357   (AudioConvertPack) MAKE_PACK_FUNC_NAME (s24_be_float),
       
   358   (AudioConvertPack) MAKE_PACK_FUNC_NAME (u32_le_float),
       
   359   (AudioConvertPack) MAKE_PACK_FUNC_NAME (s32_le_float),
       
   360   (AudioConvertPack) MAKE_PACK_FUNC_NAME (u32_be_float),
       
   361   (AudioConvertPack) MAKE_PACK_FUNC_NAME (s32_be_float),
       
   362 };
       
   363 
       
   364 #define DOUBLE_INTERMEDIATE_FORMAT(ctx)                                 \
       
   365     ((!ctx->in.is_int && !ctx->out.is_int) || (ctx->ns != NOISE_SHAPING_NONE))
       
   366 
       
   367 static gint
       
   368 audio_convert_get_func_index (AudioConvertCtx * ctx, AudioConvertFmt * fmt)
       
   369 {
       
   370   gint index = 0;
       
   371 
       
   372   if (fmt->is_int) {
       
   373     index += (fmt->width / 8 - 1) * 4;
       
   374     index += fmt->endianness == G_LITTLE_ENDIAN ? 0 : 2;
       
   375     index += fmt->sign ? 1 : 0;
       
   376     index += (ctx->ns == NOISE_SHAPING_NONE) ? 0 : 24;
       
   377   } else {
       
   378     /* this is float/double */
       
   379     index = 16;
       
   380     index += (fmt->width == 32) ? 0 : 2;
       
   381     index += (fmt->endianness == G_LITTLE_ENDIAN) ? 0 : 1;
       
   382     index += (DOUBLE_INTERMEDIATE_FORMAT (ctx)) ? 4 : 0;
       
   383   }
       
   384 
       
   385   return index;
       
   386 }
       
   387 
       
   388 static inline gboolean
       
   389 check_default (AudioConvertCtx * ctx, AudioConvertFmt * fmt)
       
   390 {
       
   391   if (!DOUBLE_INTERMEDIATE_FORMAT (ctx)) {
       
   392     return (fmt->width == 32 && fmt->depth == 32 &&
       
   393         fmt->endianness == G_BYTE_ORDER && fmt->sign == TRUE);
       
   394   } else {
       
   395     return (fmt->width == 64 && fmt->endianness == G_BYTE_ORDER);
       
   396   }
       
   397 }
       
   398 #ifdef __SYMBIAN32__
       
   399 EXPORT_C
       
   400 #endif
       
   401 
       
   402 
       
   403 gboolean
       
   404 audio_convert_clean_fmt (AudioConvertFmt * fmt)
       
   405 {
       
   406   g_return_val_if_fail (fmt != NULL, FALSE);
       
   407 
       
   408   g_free (fmt->pos);
       
   409   fmt->pos = NULL;
       
   410 
       
   411   return TRUE;
       
   412 }
       
   413 #ifdef __SYMBIAN32__
       
   414 EXPORT_C
       
   415 #endif
       
   416 
       
   417 
       
   418 
       
   419 gboolean
       
   420 audio_convert_prepare_context (AudioConvertCtx * ctx, AudioConvertFmt * in,
       
   421     AudioConvertFmt * out, DitherType dither, NoiseShapingType ns)
       
   422 {
       
   423   gint idx_in, idx_out;
       
   424 
       
   425   g_return_val_if_fail (ctx != NULL, FALSE);
       
   426   g_return_val_if_fail (in != NULL, FALSE);
       
   427   g_return_val_if_fail (out != NULL, FALSE);
       
   428 
       
   429   /* first clean the existing context */
       
   430   audio_convert_clean_context (ctx);
       
   431 
       
   432   ctx->in = *in;
       
   433   ctx->out = *out;
       
   434 
       
   435   /* Don't dither or apply noise shaping if out depth is bigger than 20 bits
       
   436    * as DA converters only can do a SNR up to 20 bits in reality.
       
   437    * Also don't dither or apply noise shaping if target depth is larger than
       
   438    * source depth. */
       
   439   if (ctx->out.depth <= 20 && (!ctx->in.is_int
       
   440           || ctx->in.depth >= ctx->out.depth)) {
       
   441     ctx->dither = dither;
       
   442     ctx->ns = ns;
       
   443   } else {
       
   444     ctx->dither = DITHER_NONE;
       
   445     ctx->ns = NOISE_SHAPING_NONE;
       
   446   }
       
   447 
       
   448   /* Use simple error feedback when output sample rate is smaller than
       
   449    * 32000 as the other methods might move the noise to audible ranges */
       
   450   if (ctx->ns > NOISE_SHAPING_ERROR_FEEDBACK && ctx->out.rate < 32000)
       
   451     ctx->ns = NOISE_SHAPING_ERROR_FEEDBACK;
       
   452 
       
   453   gst_channel_mix_setup_matrix (ctx);
       
   454 
       
   455   idx_in = audio_convert_get_func_index (ctx, in);
       
   456   ctx->unpack = unpack_funcs[idx_in];
       
   457 
       
   458   idx_out = audio_convert_get_func_index (ctx, out);
       
   459   ctx->pack = pack_funcs[idx_out];
       
   460 
       
   461   /* if both formats are float/double or we use noise shaping use double as
       
   462    * intermediate format and and switch mixing */
       
   463   if (!DOUBLE_INTERMEDIATE_FORMAT (ctx)) {
       
   464     GST_INFO ("use int mixing");
       
   465     ctx->channel_mix = (AudioConvertMix) gst_channel_mix_mix_int;
       
   466   } else {
       
   467     GST_INFO ("use float mixing");
       
   468     ctx->channel_mix = (AudioConvertMix) gst_channel_mix_mix_float;
       
   469   }
       
   470   GST_INFO ("unitsizes: %d -> %d", in->unit_size, out->unit_size);
       
   471 
       
   472   /* check if input is in default format */
       
   473   ctx->in_default = check_default (ctx, in);
       
   474   /* check if channel mixer is passthrough */
       
   475   ctx->mix_passthrough = gst_channel_mix_passthrough (ctx);
       
   476   /* check if output is in default format */
       
   477   ctx->out_default = check_default (ctx, out);
       
   478 
       
   479   GST_INFO ("in default %d, mix passthrough %d, out default %d",
       
   480       ctx->in_default, ctx->mix_passthrough, ctx->out_default);
       
   481 
       
   482   ctx->in_scale = (in->is_int) ? (32 - in->depth) : 0;
       
   483   ctx->out_scale = (out->is_int) ? (32 - out->depth) : 0;
       
   484 
       
   485   gst_audio_quantize_setup (ctx);
       
   486 
       
   487   return TRUE;
       
   488 }
       
   489 #ifdef __SYMBIAN32__
       
   490 EXPORT_C
       
   491 #endif
       
   492 
       
   493 
       
   494 gboolean
       
   495 audio_convert_clean_context (AudioConvertCtx * ctx)
       
   496 {
       
   497   g_return_val_if_fail (ctx != NULL, FALSE);
       
   498 
       
   499   gst_audio_quantize_free (ctx);
       
   500   audio_convert_clean_fmt (&ctx->in);
       
   501   audio_convert_clean_fmt (&ctx->out);
       
   502   gst_channel_mix_unset_matrix (ctx);
       
   503 
       
   504   g_free (ctx->tmpbuf);
       
   505   ctx->tmpbuf = NULL;
       
   506   ctx->tmpbufsize = 0;
       
   507 
       
   508   return TRUE;
       
   509 }
       
   510 #ifdef __SYMBIAN32__
       
   511 EXPORT_C
       
   512 #endif
       
   513 
       
   514 
       
   515 gboolean
       
   516 audio_convert_get_sizes (AudioConvertCtx * ctx, gint samples, gint * srcsize,
       
   517     gint * dstsize)
       
   518 {
       
   519   g_return_val_if_fail (ctx != NULL, FALSE);
       
   520 
       
   521   if (srcsize)
       
   522     *srcsize = samples * ctx->in.unit_size;
       
   523   if (dstsize)
       
   524     *dstsize = samples * ctx->out.unit_size;
       
   525 
       
   526   return TRUE;
       
   527 }
       
   528 #ifdef __SYMBIAN32__
       
   529 EXPORT_C
       
   530 #endif
       
   531 
       
   532 
       
   533 gboolean
       
   534 audio_convert_convert (AudioConvertCtx * ctx, gpointer src,
       
   535     gpointer dst, gint samples, gboolean src_writable)
       
   536 {
       
   537   gint insize, outsize, size;
       
   538   gpointer outbuf, tmpbuf;
       
   539   gint intemp = 0, outtemp = 0, biggest;
       
   540 
       
   541   g_return_val_if_fail (ctx != NULL, FALSE);
       
   542   g_return_val_if_fail (src != NULL, FALSE);
       
   543   g_return_val_if_fail (dst != NULL, FALSE);
       
   544   g_return_val_if_fail (samples >= 0, FALSE);
       
   545 
       
   546   if (samples == 0)
       
   547     return TRUE;
       
   548 
       
   549   insize = ctx->in.unit_size * samples;
       
   550   outsize = ctx->out.unit_size * samples;
       
   551 
       
   552   /* find biggest temp buffer size */
       
   553   size = (DOUBLE_INTERMEDIATE_FORMAT (ctx)) ? sizeof (gdouble)
       
   554       : sizeof (gint32);
       
   555 
       
   556   if (!ctx->in_default)
       
   557     intemp = insize * size * 8 / ctx->in.width;
       
   558   if (!ctx->mix_passthrough || !ctx->out_default)
       
   559     outtemp = outsize * size * 8 / ctx->out.width;
       
   560   biggest = MAX (intemp, outtemp);
       
   561 
       
   562   /* see if one of the buffers can be used as temp */
       
   563   if ((outsize >= biggest) && (ctx->out.unit_size <= size))
       
   564     tmpbuf = dst;
       
   565   else if ((insize >= biggest) && src_writable && (ctx->in.unit_size >= size))
       
   566     tmpbuf = src;
       
   567   else {
       
   568     if (biggest > ctx->tmpbufsize) {
       
   569       ctx->tmpbuf = g_realloc (ctx->tmpbuf, biggest);
       
   570       ctx->tmpbufsize = biggest;
       
   571     }
       
   572     tmpbuf = ctx->tmpbuf;
       
   573   }
       
   574 
       
   575   /* start conversion */
       
   576   if (!ctx->in_default) {
       
   577     /* check if final conversion */
       
   578     if (!(ctx->out_default && ctx->mix_passthrough))
       
   579       outbuf = tmpbuf;
       
   580     else
       
   581       outbuf = dst;
       
   582 
       
   583     /* unpack to default format */
       
   584     ctx->unpack (src, outbuf, ctx->in_scale, samples * ctx->in.channels);
       
   585 
       
   586     src = outbuf;
       
   587   }
       
   588 
       
   589   if (!ctx->mix_passthrough) {
       
   590     /* check if final conversion */
       
   591     if (!ctx->out_default)
       
   592       outbuf = tmpbuf;
       
   593     else
       
   594       outbuf = dst;
       
   595 
       
   596     /* convert channels */
       
   597     ctx->channel_mix (ctx, src, outbuf, samples);
       
   598 
       
   599     src = outbuf;
       
   600   }
       
   601 
       
   602   /* we only need to quantize if output format is int */
       
   603   if (ctx->out.is_int) {
       
   604     if (ctx->out_default)
       
   605       outbuf = dst;
       
   606     else
       
   607       outbuf = tmpbuf;
       
   608     ctx->quantize (ctx, src, outbuf, samples);
       
   609   }
       
   610 
       
   611   if (!ctx->out_default) {
       
   612     /* pack default format into dst */
       
   613     ctx->pack (src, dst, ctx->out_scale, samples * ctx->out.channels);
       
   614   }
       
   615 
       
   616   return TRUE;
       
   617 }