Audacious  $Id:Doxyfile42802007-03-2104:39:00Znenolod$
audio.c
Go to the documentation of this file.
1 /*
2  * audio.c
3  * Copyright 2009-2011 John Lindgren
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions, and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions, and the following disclaimer in the documentation
13  * provided with the distribution.
14  *
15  * This software is provided "as is" and without any warranty, express or
16  * implied. In no event shall the authors be liable for any damages arising from
17  * the use of this software.
18  */
19 
20 #include <glib.h>
21 #include <stdint.h>
22 
23 #include "audio.h"
24 #include "config.h"
25 
26 #define FROM_INT_LOOP(NAME, TYPE, SWAP, OFFSET, RANGE) \
27 static void NAME (const TYPE * in, float * out, int samples) \
28 { \
29  const TYPE * end = in + samples; \
30  while (in < end) \
31  * out ++ = (TYPE) (SWAP (* in ++) - OFFSET) / (double) RANGE; \
32 }
33 
34 #define TO_INT_LOOP(NAME, TYPE, SWAP, OFFSET, RANGE) \
35 static void NAME (const float * in, TYPE * out, int samples) \
36 { \
37  const float * end = in + samples; \
38  while (in < end) \
39  { \
40  double f = * in ++; \
41  * out ++ = SWAP (OFFSET + (TYPE) (CLAMP (f, -1, 1) * (double) RANGE)); \
42  } \
43 }
44 
45 static inline int8_t NOOP8 (int8_t i) {return i;}
46 static inline int16_t NOOP16 (int16_t i) {return i;}
47 static inline int32_t NOOP32 (int32_t i) {return i;}
48 
49 FROM_INT_LOOP (from_s8, int8_t, NOOP8, 0x00, 0x7f)
50 FROM_INT_LOOP (from_u8, int8_t, NOOP8, 0x80, 0x7f)
51 FROM_INT_LOOP (from_s16, int16_t, NOOP16, 0x0000, 0x7fff)
52 FROM_INT_LOOP (from_u16, int16_t, NOOP16, 0x8000, 0x7fff)
53 FROM_INT_LOOP (from_s24, int32_t, NOOP32, 0x000000, 0x7fffff)
54 FROM_INT_LOOP (from_u24, int32_t, NOOP32, 0x800000, 0x7fffff)
55 FROM_INT_LOOP (from_s32, int32_t, NOOP32, 0x00000000, 0x7fffffff)
56 FROM_INT_LOOP (from_u32, int32_t, NOOP32, 0x80000000, 0x7fffffff)
57 
58 TO_INT_LOOP (to_s8, int8_t, NOOP8, 0x00, 0x7f)
59 TO_INT_LOOP (to_u8, int8_t, NOOP8, 0x80, 0x7f)
60 TO_INT_LOOP (to_s16, int16_t, NOOP16, 0x0000, 0x7fff)
61 TO_INT_LOOP (to_u16, int16_t, NOOP16, 0x8000, 0x7fff)
62 TO_INT_LOOP (to_s24, int32_t, NOOP32, 0x000000, 0x7fffff)
63 TO_INT_LOOP (to_u24, int32_t, NOOP32, 0x800000, 0x7fffff)
64 TO_INT_LOOP (to_s32, int32_t, NOOP32, 0x00000000, 0x7fffffff)
65 TO_INT_LOOP (to_u32, int32_t, NOOP32, 0x80000000, 0x7fffffff)
66 
67 static inline int16_t SWAP16 (int16_t i) {return GUINT16_SWAP_LE_BE (i);}
68 static inline int32_t SWAP32 (int32_t i) {return GUINT32_SWAP_LE_BE (i);}
69 
70 FROM_INT_LOOP (from_s16_swap, int16_t, SWAP16, 0x0000, 0x7fff)
71 FROM_INT_LOOP (from_u16_swap, int16_t, SWAP16, 0x8000, 0x7fff)
72 FROM_INT_LOOP (from_s24_swap, int32_t, SWAP32, 0x000000, 0x7fffff)
73 FROM_INT_LOOP (from_u24_swap, int32_t, SWAP32, 0x800000, 0x7fffff)
74 FROM_INT_LOOP (from_s32_swap, int32_t, SWAP32, 0x00000000, 0x7fffffff)
75 FROM_INT_LOOP (from_u32_swap, int32_t, SWAP32, 0x80000000, 0x7fffffff)
76 
77 TO_INT_LOOP (to_s16_swap, int16_t, SWAP16, 0x0000, 0x7fff)
78 TO_INT_LOOP (to_u16_swap, int16_t, SWAP16, 0x8000, 0x7fff)
79 TO_INT_LOOP (to_s24_swap, int32_t, SWAP32, 0x000000, 0x7fffff)
80 TO_INT_LOOP (to_u24_swap, int32_t, SWAP32, 0x800000, 0x7fffff)
81 TO_INT_LOOP (to_s32_swap, int32_t, SWAP32, 0x00000000, 0x7fffffff)
82 TO_INT_LOOP (to_u32_swap, int32_t, SWAP32, 0x80000000, 0x7fffffff)
83 
84 typedef void (* FromFunc) (const void * in, float * out, int samples);
85 typedef void (* ToFunc) (const float * in, void * out, int samples);
86 
87 struct
88 {
89  int format;
92 }
93 convert_table [] =
94 {
95  {FMT_S8, (FromFunc) from_s8, (ToFunc) to_s8},
96  {FMT_U8, (FromFunc) from_u8, (ToFunc) to_u8},
97 
98 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
99  {FMT_S16_LE, (FromFunc) from_s16, (ToFunc) to_s16},
100  {FMT_U16_LE, (FromFunc) from_u16, (ToFunc) to_u16},
101  {FMT_S24_LE, (FromFunc) from_s24, (ToFunc) to_s24},
102  {FMT_U24_LE, (FromFunc) from_u24, (ToFunc) to_u24},
103  {FMT_S32_LE, (FromFunc) from_s32, (ToFunc) to_s32},
104  {FMT_U32_LE, (FromFunc) from_u32, (ToFunc) to_u32},
105 
106  {FMT_S16_BE, (FromFunc) from_s16_swap, (ToFunc) to_s16_swap},
107  {FMT_U16_BE, (FromFunc) from_u16_swap, (ToFunc) to_u16_swap},
108  {FMT_S24_BE, (FromFunc) from_s24_swap, (ToFunc) to_s24_swap},
109  {FMT_U24_BE, (FromFunc) from_u24_swap, (ToFunc) to_u24_swap},
110  {FMT_S32_BE, (FromFunc) from_s32_swap, (ToFunc) to_s32_swap},
111  {FMT_U32_BE, (FromFunc) from_u32_swap, (ToFunc) to_u32_swap},
112 #else
113  {FMT_S16_BE, (FromFunc) from_s16, (ToFunc) to_s16},
114  {FMT_U16_BE, (FromFunc) from_u16, (ToFunc) to_u16},
115  {FMT_S24_BE, (FromFunc) from_s24, (ToFunc) to_s24},
116  {FMT_U24_BE, (FromFunc) from_u24, (ToFunc) to_u24},
117  {FMT_S32_BE, (FromFunc) from_s32, (ToFunc) to_s32},
118  {FMT_U32_BE, (FromFunc) from_u32, (ToFunc) to_u32},
119 
120  {FMT_S16_LE, (FromFunc) from_s16_swap, (ToFunc) to_s16_swap},
121  {FMT_U16_LE, (FromFunc) from_u16_swap, (ToFunc) to_u16_swap},
122  {FMT_S24_LE, (FromFunc) from_s24_swap, (ToFunc) to_s24_swap},
123  {FMT_U24_LE, (FromFunc) from_u24_swap, (ToFunc) to_u24_swap},
124  {FMT_S32_LE, (FromFunc) from_s32_swap, (ToFunc) to_s32_swap},
125  {FMT_U32_LE, (FromFunc) from_u32_swap, (ToFunc) to_u32_swap},
126 #endif
127 };
128 
129 EXPORT void audio_from_int (const void * in, int format, float * out, int samples)
130 {
131  int entry;
132 
133  for (entry = 0; entry < G_N_ELEMENTS (convert_table); entry ++)
134  {
135  if (convert_table[entry].format == format)
136  {
137  convert_table[entry].from (in, out, samples);
138  return;
139  }
140  }
141 }
142 
143 EXPORT void audio_to_int (const float * in, void * out, int format, int samples)
144 {
145  int entry;
146 
147  for (entry = 0; entry < G_N_ELEMENTS (convert_table); entry ++)
148  {
149  if (convert_table[entry].format == format)
150  {
151  convert_table[entry].to (in, out, samples);
152  return;
153  }
154  }
155 }
156 
157 EXPORT void audio_amplify (float * data, int channels, int frames, float * factors)
158 {
159  float * end = data + channels * frames;
160  int channel;
161 
162  while (data < end)
163  {
164  for (channel = 0; channel < channels; channel ++)
165  {
166  * data = * data * factors[channel];
167  data ++;
168  }
169  }
170 }