Audacious  $Id:Doxyfile42802007-03-2104:39:00Znenolod$
audio.c
Go to the documentation of this file.
00001 /*
00002  * audio.c
00003  * Copyright 2009-2011 John Lindgren
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright notice,
00009  *    this list of conditions, and the following disclaimer.
00010  *
00011  * 2. Redistributions in binary form must reproduce the above copyright notice,
00012  *    this list of conditions, and the following disclaimer in the documentation
00013  *    provided with the distribution.
00014  *
00015  * This software is provided "as is" and without any warranty, express or
00016  * implied. In no event shall the authors be liable for any damages arising from
00017  * the use of this software.
00018  */
00019 
00020 #include <glib.h>
00021 #include <stdint.h>
00022 
00023 #include "audio.h"
00024 #include "config.h"
00025 
00026 #define FROM_INT_LOOP(NAME, TYPE, SWAP, OFFSET, RANGE) \
00027 static void NAME (const TYPE * in, float * out, int samples) \
00028 { \
00029     const TYPE * end = in + samples; \
00030     while (in < end) \
00031         * out ++ = (TYPE) (SWAP (* in ++) - OFFSET) / (double) RANGE; \
00032 }
00033 
00034 #define TO_INT_LOOP(NAME, TYPE, SWAP, OFFSET, RANGE) \
00035 static void NAME (const float * in, TYPE * out, int samples) \
00036 { \
00037     const float * end = in + samples; \
00038     while (in < end) \
00039     { \
00040         double f = * in ++; \
00041         * out ++ = SWAP (OFFSET + (TYPE) (CLAMP (f, -1, 1) * (double) RANGE)); \
00042     } \
00043 }
00044 
00045 static inline int8_t noop8 (int8_t i) {return i;}
00046 static inline int16_t noop16 (int16_t i) {return i;}
00047 static inline int32_t noop32 (int32_t i) {return i;}
00048 
00049 FROM_INT_LOOP (from_s8, int8_t, noop8, 0x00, 0x7f)
00050 FROM_INT_LOOP (from_u8, int8_t, noop8, 0x80, 0x7f)
00051 FROM_INT_LOOP (from_s16, int16_t, noop16, 0x0000, 0x7fff)
00052 FROM_INT_LOOP (from_u16, int16_t, noop16, 0x8000, 0x7fff)
00053 FROM_INT_LOOP (from_s24, int32_t, noop32, 0x000000, 0x7fffff)
00054 FROM_INT_LOOP (from_u24, int32_t, noop32, 0x800000, 0x7fffff)
00055 FROM_INT_LOOP (from_s32, int32_t, noop32, 0x00000000, 0x7fffffff)
00056 FROM_INT_LOOP (from_u32, int32_t, noop32, 0x80000000, 0x7fffffff)
00057 
00058 TO_INT_LOOP (to_s8, int8_t, noop8, 0x00, 0x7f)
00059 TO_INT_LOOP (to_u8, int8_t, noop8, 0x80, 0x7f)
00060 TO_INT_LOOP (to_s16, int16_t, noop16, 0x0000, 0x7fff)
00061 TO_INT_LOOP (to_u16, int16_t, noop16, 0x8000, 0x7fff)
00062 TO_INT_LOOP (to_s24, int32_t, noop32, 0x000000, 0x7fffff)
00063 TO_INT_LOOP (to_u24, int32_t, noop32, 0x800000, 0x7fffff)
00064 TO_INT_LOOP (to_s32, int32_t, noop32, 0x00000000, 0x7fffffff)
00065 TO_INT_LOOP (to_u32, int32_t, noop32, 0x80000000, 0x7fffffff)
00066 
00067 static inline int16_t swap16 (int16_t i) {return GUINT16_SWAP_LE_BE (i);}
00068 static inline int32_t swap32 (int32_t i) {return GUINT32_SWAP_LE_BE (i);}
00069 
00070 FROM_INT_LOOP (from_s16_swap, int16_t, swap16, 0x0000, 0x7fff)
00071 FROM_INT_LOOP (from_u16_swap, int16_t, swap16, 0x8000, 0x7fff)
00072 FROM_INT_LOOP (from_s24_swap, int32_t, swap32, 0x000000, 0x7fffff)
00073 FROM_INT_LOOP (from_u24_swap, int32_t, swap32, 0x800000, 0x7fffff)
00074 FROM_INT_LOOP (from_s32_swap, int32_t, swap32, 0x00000000, 0x7fffffff)
00075 FROM_INT_LOOP (from_u32_swap, int32_t, swap32, 0x80000000, 0x7fffffff)
00076 
00077 TO_INT_LOOP (to_s16_swap, int16_t, swap16, 0x0000, 0x7fff)
00078 TO_INT_LOOP (to_u16_swap, int16_t, swap16, 0x8000, 0x7fff)
00079 TO_INT_LOOP (to_s24_swap, int32_t, swap32, 0x000000, 0x7fffff)
00080 TO_INT_LOOP (to_u24_swap, int32_t, swap32, 0x800000, 0x7fffff)
00081 TO_INT_LOOP (to_s32_swap, int32_t, swap32, 0x00000000, 0x7fffffff)
00082 TO_INT_LOOP (to_u32_swap, int32_t, swap32, 0x80000000, 0x7fffffff)
00083 
00084 typedef void (* FromFunc) (const void * in, float * out, int samples);
00085 typedef void (* ToFunc) (const float * in, void * out, int samples);
00086 
00087 struct
00088 {
00089     int format;
00090     FromFunc from;
00091     ToFunc to;
00092 }
00093 convert_table [] =
00094 {
00095     {FMT_S8, (FromFunc) from_s8, (ToFunc) to_s8},
00096     {FMT_U8, (FromFunc) from_u8, (ToFunc) to_u8},
00097 
00098 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
00099     {FMT_S16_LE, (FromFunc) from_s16, (ToFunc) to_s16},
00100     {FMT_U16_LE, (FromFunc) from_u16, (ToFunc) to_u16},
00101     {FMT_S24_LE, (FromFunc) from_s24, (ToFunc) to_s24},
00102     {FMT_U24_LE, (FromFunc) from_u24, (ToFunc) to_u24},
00103     {FMT_S32_LE, (FromFunc) from_s32, (ToFunc) to_s32},
00104     {FMT_U32_LE, (FromFunc) from_u32, (ToFunc) to_u32},
00105 
00106     {FMT_S16_BE, (FromFunc) from_s16_swap, (ToFunc) to_s16_swap},
00107     {FMT_U16_BE, (FromFunc) from_u16_swap, (ToFunc) to_u16_swap},
00108     {FMT_S24_BE, (FromFunc) from_s24_swap, (ToFunc) to_s24_swap},
00109     {FMT_U24_BE, (FromFunc) from_u24_swap, (ToFunc) to_u24_swap},
00110     {FMT_S32_BE, (FromFunc) from_s32_swap, (ToFunc) to_s32_swap},
00111     {FMT_U32_BE, (FromFunc) from_u32_swap, (ToFunc) to_u32_swap},
00112 #else
00113     {FMT_S16_BE, (FromFunc) from_s16, (ToFunc) to_s16},
00114     {FMT_U16_BE, (FromFunc) from_u16, (ToFunc) to_u16},
00115     {FMT_S24_BE, (FromFunc) from_s24, (ToFunc) to_s24},
00116     {FMT_U24_BE, (FromFunc) from_u24, (ToFunc) to_u24},
00117     {FMT_S32_BE, (FromFunc) from_s32, (ToFunc) to_s32},
00118     {FMT_U32_BE, (FromFunc) from_u32, (ToFunc) to_u32},
00119 
00120     {FMT_S16_LE, (FromFunc) from_s16_swap, (ToFunc) to_s16_swap},
00121     {FMT_U16_LE, (FromFunc) from_u16_swap, (ToFunc) to_u16_swap},
00122     {FMT_S24_LE, (FromFunc) from_s24_swap, (ToFunc) to_s24_swap},
00123     {FMT_U24_LE, (FromFunc) from_u24_swap, (ToFunc) to_u24_swap},
00124     {FMT_S32_LE, (FromFunc) from_s32_swap, (ToFunc) to_s32_swap},
00125     {FMT_U32_LE, (FromFunc) from_u32_swap, (ToFunc) to_u32_swap},
00126 #endif
00127 };
00128 
00129 EXPORT void audio_from_int (const void * in, int format, float * out, int samples)
00130 {
00131     int entry;
00132 
00133     for (entry = 0; entry < G_N_ELEMENTS (convert_table); entry ++)
00134     {
00135         if (convert_table[entry].format == format)
00136         {
00137             convert_table[entry].from (in, out, samples);
00138             return;
00139         }
00140     }
00141 }
00142 
00143 EXPORT void audio_to_int (const float * in, void * out, int format, int samples)
00144 {
00145     int entry;
00146 
00147     for (entry = 0; entry < G_N_ELEMENTS (convert_table); entry ++)
00148     {
00149         if (convert_table[entry].format == format)
00150         {
00151             convert_table[entry].to (in, out, samples);
00152             return;
00153         }
00154     }
00155 }
00156 
00157 EXPORT void audio_amplify (float * data, int channels, int frames, float * factors)
00158 {
00159     float * end = data + channels * frames;
00160     int channel;
00161 
00162     while (data < end)
00163     {
00164         for (channel = 0; channel < channels; channel ++)
00165         {
00166             * data = * data * factors[channel];
00167             data ++;
00168         }
00169     }
00170 }