1 /*
2  * libInstPatch
3  * Copyright (C) 1999-2014 Element Green <element@elementsofsound.org>
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public License
7  * as published by the Free Software Foundation; version 2.1
8  * of the License only.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18  * 02110-1301, USA or on the web at http://www.gnu.org.
19  */
20 /**
21  * SECTION: sample
22  * @short_description: Audio sample format conversion functions and defines.
23  * @see_also:
24  * @stability: Stable
25  *
26  * This module provides functions for converting audio formats as well as a system
27  * for defining audio formats with a single integer composed of multiple fields
28  * for sample width, channel count, sign and endian byte order.
29  */
30 #include <glib.h>
31 #include <glib-object.h>
32 #include "sample.h"
33 #include "IpatchSampleTransform.h"
34 
35 /* NOTES:
36  * 24 bit is converted to 4 byte integers first (less of a pain)
37  * Floating point audio is assumed to have a range of -1.0 to 1.0.
38  */
39 
40 
41 #define NOP  (void)0;
42 
43 #define TRANS_FUNC(NAME, INTYPE, OUTTYPE, PRE, CODE, POST) \
44 void TFF_ ## NAME (IpatchSampleTransform *transform) \
45 { \
46   INTYPE *inp = transform->buf1; \
47   OUTTYPE *outp = transform->buf2; \
48   guint i, count = transform->samples; \
49   PRE \
50  \
51   for (i = 0; i < count; i++) \
52   CODE; \
53   POST \
54 }
55 
56 /* float transforms */
57 
58 TRANS_FUNC(floattodouble, gfloat, gdouble, NOP, { outp[i] = inp[i]; }, NOP)
59 TRANS_FUNC(doubletofloat, gdouble, gfloat, NOP, { outp[i] = (gfloat)inp[i]; }, NOP)
60 
61 
62 /* signed bit width change funcs */
63 
64 TRANS_FUNC(s8to16, gint8, gint16, NOP, { outp[i] = (gint16)inp[i] << 8; }, NOP)
65 TRANS_FUNC(s8to24, gint8, gint32, NOP, { outp[i] = (gint32)inp[i] << 16; }, NOP)
66 TRANS_FUNC(s8to32, gint8, gint32, NOP, { outp[i] = (gint32)inp[i] << 24; }, NOP)
67 TRANS_FUNC(s8tofloat, gint8, gfloat, NOP,
68 { outp[i] = inp[i] / (float)128.0; }, NOP)
69 TRANS_FUNC(s8todouble, gint8, gdouble, NOP,
70 { outp[i] = inp[i] / (double)128.0; }, NOP)
71 
72 TRANS_FUNC(s16to8, gint16, gint8, NOP, { outp[i] = inp[i] >> 8; }, NOP)
73 TRANS_FUNC(s16to24, gint16, gint32, NOP, { outp[i] = inp[i] << 8; }, NOP)
74 TRANS_FUNC(s16to32, gint16, gint32, NOP, { outp[i] = inp[i] << 16; }, NOP)
75 TRANS_FUNC(s16tofloat, gint16, gfloat, NOP,
76 { outp[i] = inp[i] / (float)32768.0; }, NOP)
77 TRANS_FUNC(s16todouble, gint16, gdouble, NOP,
78 { outp[i] = inp[i] / (double)32768.0; }, NOP)
79 
80 TRANS_FUNC(s24to8, gint32, gint8, NOP, { outp[i] = inp[i] >> 16; }, NOP)
81 TRANS_FUNC(s24to16, gint32, gint16, NOP, { outp[i] = inp[i] >> 8; }, NOP)
82 TRANS_FUNC(s24to32, gint32, gint32, NOP, { outp[i] = inp[i] << 8; }, NOP)
83 TRANS_FUNC(s24tofloat, gint32, gfloat, NOP,
84 { outp[i] = inp[i] / (float)8388608.0; }, NOP)
85 TRANS_FUNC(s24todouble, gint32, gdouble, NOP,
86 { outp[i] = inp[i] / (double)8388608.0; }, NOP)
87 
88 TRANS_FUNC(s32to8, gint32, gint8, NOP, { outp[i] = inp[i] >> 24; }, NOP)
89 TRANS_FUNC(s32to16, gint32, gint16, NOP, { outp[i] = inp[i] >> 16; }, NOP)
90 TRANS_FUNC(s32to24, gint32, gint32, NOP, { outp[i] = inp[i] >> 8; }, NOP)
91 TRANS_FUNC(s32tofloat, gint32, gfloat, NOP,
92 { outp[i] = inp[i] / (float)2147483648.0; }, NOP)
93 TRANS_FUNC(s32todouble, gint32, gdouble, NOP,
94 { outp[i] = inp[i] / (double)2147483648.0; }, NOP)
95 
96 TRANS_FUNC(floattos8, gfloat, gint8, NOP,
97 { outp[i] = (gint8)(inp[i] * 127.0); }, NOP)
98 TRANS_FUNC(floattos16, gfloat, gint16, NOP,
99 { outp[i] = (gint16)(inp[i] * 32767.0); }, NOP)
100 TRANS_FUNC(floattos24, gfloat, gint32, NOP,
101 { outp[i] = (gint32)(inp[i] * 8388607.0); }, NOP)
102 TRANS_FUNC(floattos32, gfloat, gint32, NOP,
103 { outp[i] = (gint32)(inp[i] * 2147483647.0); }, NOP)
104 
105 TRANS_FUNC(doubletos8, gdouble, gint8, NOP,
106 { outp[i] = (gint8)(inp[i] * 127.0); }, NOP)
107 TRANS_FUNC(doubletos16, gdouble, gint16, NOP,
108 { outp[i] = (gint16)(inp[i] * 32767.0); }, NOP)
109 TRANS_FUNC(doubletos24, gdouble, gint32, NOP,
110 { outp[i] = (gint32)(inp[i] * 8388607.0); }, NOP)
111 TRANS_FUNC(doubletos32, gdouble, gint32, NOP,
112 { outp[i] = (gint32)(inp[i] * 2147483647.0); }, NOP)
113 
114 
115 /* unsigned bit width change funcs */
116 
117 TRANS_FUNC(u8to16, guint8, guint16, NOP, { outp[i] = inp[i] << 8; }, NOP)
118 TRANS_FUNC(u8to24, guint8, guint32, NOP, { outp[i] = inp[i] << 16; }, NOP)
119 TRANS_FUNC(u8to32, guint8, guint32, NOP, { outp[i] = inp[i] << 24; }, NOP)
120 TRANS_FUNC(u8tofloat, guint8, gfloat, NOP,
121 { outp[i] = (gint8)(inp[i] ^ 0x80) / (float)128.0; }, NOP)
122 TRANS_FUNC(u8todouble, guint8, gdouble, NOP,
123 { outp[i] = (gint8)(inp[i] ^ 0x80) / (double)128.0; }, NOP)
124 
125 TRANS_FUNC(u16to8, guint16, guint8, NOP, { outp[i] = inp[i] >> 8; }, NOP)
126 TRANS_FUNC(u16to24, guint16, guint32, NOP, { outp[i] = inp[i] << 8; }, NOP)
127 TRANS_FUNC(u16to32, guint16, guint32, NOP, { outp[i] = inp[i] << 16; }, NOP)
128 TRANS_FUNC(u16tofloat, guint16, gfloat, NOP,
129 { outp[i] = (gint16)(inp[i] ^ 0x8000) / (float)32768.0; }, NOP)
130 TRANS_FUNC(u16todouble, guint16, gdouble, NOP,
131 { outp[i] = (gint16)(inp[i] ^ 0x8000) / (double)32768.0; }, NOP)
132 
133 TRANS_FUNC(u24to8, guint32, guint8, NOP, { outp[i] = inp[i] >> 16; }, NOP)
134 TRANS_FUNC(u24to16, guint32, guint16, NOP, { outp[i] = inp[i] >> 8; }, NOP)
135 TRANS_FUNC(u24to32, guint32, guint32, NOP, { outp[i] = inp[i] << 8; }, NOP)
136 TRANS_FUNC(u24tofloat, guint32, gfloat, NOP,
137 { outp[i] = ((gint32)inp[i] - 0x800000) / (float)8388608.0; }, NOP)
138 TRANS_FUNC(u24todouble, guint32, gdouble, NOP,
139 { outp[i] = ((gint32)inp[i] - 0x800000) / (double)8388608.0; }, NOP)
140 
141 TRANS_FUNC(u32to8, guint32, guint8, NOP, { outp[i] = inp[i] >> 24; }, NOP)
142 TRANS_FUNC(u32to16, guint32, guint16, NOP, { outp[i] = inp[i] >> 16; }, NOP)
143 TRANS_FUNC(u32to24, guint32, guint32, NOP, { outp[i] = inp[i] >> 8; }, NOP)
144 TRANS_FUNC(u32tofloat, guint32, gfloat, NOP,
145 { outp[i] = (gint32)(inp[i] ^ 0x80000000) / (float)2147483648.0; }, NOP)
146 TRANS_FUNC(u32todouble, guint32, gdouble, NOP,
147 { outp[i] = (gint32)(inp[i] ^ 0x80000000) / (double)2147483648.0; }, NOP)
148 
149 TRANS_FUNC(floattou8, gfloat, guint8, NOP,
150 { outp[i] = (guint8)((inp[i] + 1.0) * 127.5 + 0.5); }, NOP)
151 TRANS_FUNC(floattou16, gfloat, guint16, NOP,
152 { outp[i] = (guint16)((inp[i] + 1.0) * 32767.5 + 0.5); }, NOP)
153 TRANS_FUNC(floattou24, gfloat, guint32, NOP,
154 { outp[i] = (guint32)((inp[i] + 1.0) * 8388607.5 + 0.5); }, NOP)
155 TRANS_FUNC(floattou32, gfloat, guint32, NOP,
156 { outp[i] = (guint32)((inp[i] + 1.0) * 2147483647.5 + 0.5); }, NOP)
157 
158 TRANS_FUNC(doubletou8, gdouble, guint8, NOP,
159 { outp[i] = (guint8)((inp[i] + 1.0) * 127.5 + 0.5); }, NOP)
160 TRANS_FUNC(doubletou16, gdouble, guint16, NOP,
161 { outp[i] = (guint16)((inp[i] + 1.0) * 32767.5 + 0.5); }, NOP)
162 TRANS_FUNC(doubletou24, gdouble, guint32, NOP,
163 { outp[i] = (guint32)((inp[i] + 1.0) * 8388607.5 + 0.5); }, NOP)
164 TRANS_FUNC(doubletou32, gdouble, guint32, NOP,
165 { outp[i] = (guint32)((inp[i] + 1.0) * 2147483647.5 + 0.5); }, NOP)
166 
167 
168 /* sign changer funcs (24 bit in 4 byte integers requires 2 separate funcs) */
169 
170 TRANS_FUNC(togsign8, guint8, guint8, NOP, { outp[i] = inp[i] ^ 0x80; }, NOP)
171 TRANS_FUNC(togsign16, guint16, guint16, NOP,
172 { outp[i] = inp[i] ^ 0x8000; }, NOP)
173 TRANS_FUNC(signtou24, guint32, guint32, NOP,
174 { outp[i] = inp[i] + 0x800000; }, NOP)
175 TRANS_FUNC(unsigntos24, gint32, gint32, NOP,
176 { outp[i] = ((inp[i] ^ 0x800000) << 8) >> 8; }, NOP)
177 TRANS_FUNC(togsign32, guint32, guint32, NOP,
178 { outp[i] = inp[i] ^ 0x80000000; }, NOP)
179 
180 
181 /* endian swapping funcs */
182 
183 TRANS_FUNC(swap16, guint16, guint16, guint16 t;,
184 { t = inp[i]; outp[i] = t << 8 | t >> 8; }, NOP)
185 TRANS_FUNC(swap32, guint32, guint32, guint32 t;,
186 {
187     t = inp[i]; outp[i] = ((t & 0xFF) << 24) | ((t & 0xFF00) << 8)
188     | ((t & 0xFF0000) >> 8) | ((t & 0xFF000000) >> 24);
189 }, NOP)
190 TRANS_FUNC(swap64, guint64, guint64, guint64 t;,
191 {
192     t = inp[i]; outp[i] = ((t & 0xFF) << 56) | ((t & 0xFF00) << 40)
193     | ((t & 0xFF0000) << 24) | ((t & 0xFF000000) << 8)
194     | ((t & G_GINT64_CONSTANT(0xFF00000000U)) >> 8)
195     | ((t & G_GINT64_CONSTANT(0xFF0000000000U)) >> 24)
196     | ((t & G_GINT64_CONSTANT(0xFF000000000000U)) >> 40)
197     | ((t & G_GINT64_CONSTANT(0xFF00000000000000U)) >> 56);
198 }, NOP)
199 
200 
201 /* funcs for converting between real signed 24 bit (3 byte) and 4 byte words */
202 
203 /* signed little endian 3 bytes to 4 bytes */
204 TRANS_FUNC(sle3bto4b, guint8, guint32, guint i2 = 0;,
205 {
206     outp[i] = inp[i2] | (inp[i2 + 1] << 8) | (inp[i2 + 2] << 16)
207     | ((inp[i2 + 2] & 0x80) ? 0xFF000000 : 0); i2 += 3;
208 }, NOP)
209 
210 /* signed big endian 3 bytes to 4 bytes */
211 TRANS_FUNC(sbe3bto4b, guint8, guint32, guint i2 = 0;,
212 {
213     outp[i] = inp[i2 + 2] | (inp[i2 + 1] << 8) | (inp[i2] << 16)
214     | ((inp[i2] & 0x80) ? 0xFF000000 : 0); i2 += 3;
215 }, NOP)
216 
217 /* 4 bytes to signed little endian 3 bytes */
218 TRANS_FUNC(4btosle3b, guint32, guint8, guint i2 = 0; gint32 t;,
219 {
220     t = inp[i]; outp[i2] = t; outp[i2 + 1] = t >> 8;
221     outp[i2 + 2] = t >> 16; i2 += 3;
222 }, NOP)
223 
224 /* 4 bytes to signed big endian 3 bytes */
225 TRANS_FUNC(4btosbe3b, guint32, guint8, guint i2 = 0; gint32 t;,
226 {
227     t = inp[i]; outp[i2 + 2] = t; outp[i2 + 1] = t >> 8;
228     outp[i2] = t >> 16; i2 += 3;
229 }, NOP)
230 
231 /* funcs for converting between real unsigned 24 bit (3 byte) and 4 byte words */
232 
233 /* unsigned little endian 3 bytes to 4 bytes */
234 TRANS_FUNC(ule3bto4b, guint8, guint32, guint i2 = 0;,
235 {
236     outp[i] = inp[i2] | (inp[i2 + 1] << 8) | (inp[i2 + 2] << 16);
237     i2 += 3;
238 }, NOP)
239 
240 /* unsigned big endian 3 bytes to 4 bytes */
241 TRANS_FUNC(ube3bto4b, guint8, guint32, guint i2 = 0;,
242 {
243     outp[i] = inp[i2 + 2] | (inp[i2 + 1] << 8) | (inp[i2] << 16);
244     i2 += 3;
245 }, NOP)
246 
247 /* 4 bytes to unsigned little endian 3 bytes */
248 TRANS_FUNC(4btoule3b, guint32, guint8, guint i2 = 0; guint32 t;,
249 {
250     t = inp[i]; outp[i2] = t; outp[i2 + 1] = t >> 8;
251     outp[i2 + 2] = t >> 16; i2 += 3;
252 }, NOP)
253 
254 /* 4 bytes to unsigned big endian 3 bytes */
255 TRANS_FUNC(4btoube3b, guint32, guint8, guint i2 = 0; guint32 t;,
256 {
257     t = inp[i]; outp[i2 + 2] = t; outp[i2 + 1] = t >> 8;
258     outp[i2] = t >> 16; i2 += 3;
259 }, NOP)
260 
261 /* mono to stereo transforms */
262 TRANS_FUNC(8mtos, guint8, guint8, NOP,
263 { outp[i << 1] = inp[i]; outp[(i << 1) + 1] = inp[i]; },
264 transform->samples = count << 1;)
265 TRANS_FUNC(16mtos, guint16, guint16, NOP,
266 { outp[i << 1] = inp[i]; outp[(i << 1) + 1] = inp[i]; },
267 transform->samples = count << 1;)
268 TRANS_FUNC(32mtos, guint32, guint32, NOP,
269 { outp[i << 1] = inp[i]; outp[(i << 1) + 1] = inp[i]; },
270 transform->samples = count << 1;)
271 TRANS_FUNC(64mtos, guint64, guint64, NOP,
272 { outp[i << 1] = inp[i]; outp[(i << 1) + 1] = inp[i]; },
273 transform->samples = count << 1;)
274 
275 /* stereo to left transforms */
276 TRANS_FUNC(8stol, guint8, guint8, count >>= 1;,
277 { outp[i] = inp[i << 1]; }, transform->samples = count;)
278 TRANS_FUNC(16stol, guint16, guint16, count >>= 1;,
279 { outp[i] = inp[i << 1]; }, transform->samples = count;)
280 TRANS_FUNC(32stol, guint32, guint32, count >>= 1;,
281 { outp[i] = inp[i << 1]; }, transform->samples = count;)
282 TRANS_FUNC(64stol, guint64, guint64, count >>= 1;,
283 { outp[i] = inp[i << 1]; }, transform->samples = count;)
284 
285 /* stereo to right transforms */
286 TRANS_FUNC(8stor, guint8, guint8, count >>= 1;,
287 { outp[i] = inp[(i << 1) + 1]; }, transform->samples = count;)
288 TRANS_FUNC(16stor, guint16, guint16, count >>= 1;,
289 { outp[i] = inp[(i << 1) + 1]; }, transform->samples = count;)
290 TRANS_FUNC(32stor, guint32, guint32, count >>= 1;,
291 { outp[i] = inp[(i << 1) + 1]; }, transform->samples = count;)
292 TRANS_FUNC(64stor, guint64, guint64, count >>= 1;,
293 { outp[i] = inp[(i << 1) + 1]; }, transform->samples = count;)
294 
295 /* arbitrary channel mapping */
296 TRANS_FUNC(8chanmap, guint8, guint8,
297            int schans = IPATCH_SAMPLE_FORMAT_GET_CHANNEL_COUNT(transform->src_format); \
298            int dchans = IPATCH_SAMPLE_FORMAT_GET_CHANNEL_COUNT(transform->dest_format); \
299            int di; int spos = 0; int dpos = 0;,
300 {
301     \
302 
303     for(di = 0; di < dchans; di++, dpos++) \
304         outp[dpos] = inp[spos + transform->channel_map[di]]; \
305     spos += schans; \
306 },
307 NOP)
308 TRANS_FUNC(16chanmap, guint16, guint16,
309            int schans = IPATCH_SAMPLE_FORMAT_GET_CHANNEL_COUNT(transform->src_format); \
310            int dchans = IPATCH_SAMPLE_FORMAT_GET_CHANNEL_COUNT(transform->dest_format); \
311            int di; int spos = 0; int dpos = 0;,
312 {
313     \
314 
315     for(di = 0; di < dchans; di++, dpos++) \
316         outp[dpos] = inp[spos + transform->channel_map[di]]; \
317     spos += schans; \
318 },
319 NOP)
320 TRANS_FUNC(32chanmap, guint32, guint32,
321            int schans = IPATCH_SAMPLE_FORMAT_GET_CHANNEL_COUNT(transform->src_format); \
322            int dchans = IPATCH_SAMPLE_FORMAT_GET_CHANNEL_COUNT(transform->dest_format); \
323            int di; int spos = 0; int dpos = 0;,
324 {
325     \
326 
327     for(di = 0; di < dchans; di++, dpos++) \
328         outp[dpos] = inp[spos + transform->channel_map[di]]; \
329     spos += schans; \
330 },
331 NOP)
332 TRANS_FUNC(64chanmap, guint64, guint64,
333            int schans = IPATCH_SAMPLE_FORMAT_GET_CHANNEL_COUNT(transform->src_format); \
334            int dchans = IPATCH_SAMPLE_FORMAT_GET_CHANNEL_COUNT(transform->dest_format); \
335            int di; int spos = 0; int dpos = 0;,
336 {
337     \
338 
339     for(di = 0; di < dchans; di++, dpos++) \
340         outp[dpos] = inp[spos + transform->channel_map[di]]; \
341     spos += schans; \
342 },
343 NOP)
344 
345 
346 /* signed transform func matrix [infmt][outfmt] */
347 static IpatchSampleTransformFunc signed_tff[6][6] =
348 {
349     { NULL, TFF_s8to16, TFF_s8to24, TFF_s8to32, TFF_s8tofloat, TFF_s8todouble },
350     {
351         TFF_s16to8, NULL, TFF_s16to24, TFF_s16to32, TFF_s16tofloat,
352         TFF_s16todouble
353     },
354     {
355         TFF_s24to8, TFF_s24to16, NULL, TFF_s24to32, TFF_s24tofloat,
356         TFF_s24todouble
357     },
358     {
359         TFF_s32to8, TFF_s32to16, TFF_s32to24, NULL, TFF_s32tofloat,
360         TFF_s32todouble
361     },
362     {
363         TFF_floattos8, TFF_floattos16, TFF_floattos24, TFF_floattos32, NULL,
364         TFF_floattodouble
365     },
366     {
367         TFF_doubletos8, TFF_doubletos16, TFF_doubletos24, TFF_doubletos32,
368         TFF_doubletofloat, NULL
369     }
370 };
371 
372 /* unsiged transform func matrix [infmt][outfmt] */
373 static IpatchSampleTransformFunc unsigned_tff[6][6] =
374 {
375     { NULL, TFF_u8to16, TFF_u8to24, TFF_u8to32, TFF_u8tofloat, TFF_u8todouble },
376     {
377         TFF_u16to8, NULL, TFF_u16to24, TFF_u16to32, TFF_u16tofloat,
378         TFF_u16todouble
379     },
380     {
381         TFF_u24to8, TFF_u24to16, NULL, TFF_u24to32, TFF_u24tofloat,
382         TFF_u24todouble
383     },
384     {
385         TFF_u32to8, TFF_u32to16, TFF_u32to24, NULL, TFF_u32tofloat,
386         TFF_u32todouble
387     },
388     {
389         TFF_floattou8, TFF_floattou16, TFF_floattou24, TFF_floattou32, NULL,
390         TFF_floattodouble
391     },
392     {
393         TFF_doubletou8, TFF_doubletou16, TFF_doubletou24, TFF_doubletou32,
394         TFF_doubletofloat, NULL
395     }
396 };
397 
398 /* sign toggle transform functions */
399 static IpatchSampleTransformFunc sign_tff[6] =
400 {
401     TFF_togsign8, TFF_togsign16, NULL, TFF_togsign32, NULL, NULL
402 };
403 
404 /* endian swap functions */
405 static IpatchSampleTransformFunc swap_tff[6] =
406 {
407     NULL, TFF_swap16, TFF_swap32, TFF_swap32, TFF_swap32, TFF_swap64
408 };
409 
410 /* mono to stereo transform functions */
411 static IpatchSampleTransformFunc mono_to_stereo_tff[6] =
412 {
413     TFF_8mtos, TFF_16mtos, TFF_32mtos, TFF_32mtos, TFF_32mtos, TFF_64mtos
414 };
415 
416 /* stereo to left transform functions */
417 static IpatchSampleTransformFunc stereo_to_left_tff[6] =
418 {
419     TFF_8stol, TFF_16stol, TFF_32stol, TFF_32stol, TFF_32stol, TFF_64stol
420 };
421 
422 /* stereo to right transform functions */
423 static IpatchSampleTransformFunc stereo_to_right_tff[6] =
424 {
425     TFF_8stor, TFF_16stor, TFF_32stor, TFF_32stor, TFF_32stor, TFF_64stor
426 };
427 
428 /* arbitrary transform functions */
429 static IpatchSampleTransformFunc chanmap_tff[6] =
430 {
431     TFF_8chanmap, TFF_16chanmap, TFF_32chanmap, TFF_32chanmap, TFF_32chanmap, TFF_64chanmap
432 };
433 
434 /* IpatchSampleWidth format sizes in bytes (last 8 reserved) */
435 guint ipatch_sample_width_sizes[16] = { 0, 1, 2, 4, 4, 4, 8, 3,
436                                         0, 0, 0, 0, 0, 0, 0, 0
437                                       };
438 
439 
440 static inline void update_max_size(int *curmax, int format);
441 
442 /**
443  * ipatch_sample_format_bit_width:
444  * @format: Sample format
445  *
446  * Like ipatch_sample_format_width() but gets the effective bit width of the
447  * format.  Of note is this is not always equivelant to the format width * 8.
448  * For example: #IPATCH_SAMPLE_FLOAT has an effective bit width of 23,
449  * #IPATCH_SAMPLE_24BIT has an effective bit width of 24 but is stored in 32
450  * bits.  This function is really only useful for comparing the relative
451  * "quality" of formats, and the actual returned values may change in the
452  * future.
453  *
454  * Returns: Effective bit width of format.
455  */
456 int
ipatch_sample_format_bit_width(int format)457 ipatch_sample_format_bit_width(int format)
458 {
459     int width;
460 
461     width = IPATCH_SAMPLE_FORMAT_GET_WIDTH(format);
462 
463     switch(width)
464     {
465     case IPATCH_SAMPLE_FLOAT:
466         /* actually 24 with the sign bit, but we set it to 23 to be less than
467            24 bit integer audio */
468         return (23);
469 
470     case IPATCH_SAMPLE_DOUBLE:
471         return (52);
472 
473     case IPATCH_SAMPLE_REAL24BIT:
474         return (24);
475         break;
476 
477     default:
478         return (width * 8);
479     }
480 }
481 
482 /**
483  * ipatch_sample_format_verify:
484  * @format: Sample format (#IpatchSampleWidth | #IpatchSampleSign
485  *   | #IpatchSampleEndian | #IpatchSampleChannel).
486  *
487  * Verify a sample format integer.
488  *
489  * Returns: %TRUE if valid, %FALSE otherwise
490  */
491 gboolean
ipatch_sample_format_verify(int format)492 ipatch_sample_format_verify(int format)
493 {
494     int width;
495 
496     width = format & IPATCH_SAMPLE_WIDTH_MASK;
497 
498     if(width < IPATCH_SAMPLE_8BIT || width > IPATCH_SAMPLE_REAL24BIT)
499     {
500         return (FALSE);
501     }
502 
503     if(IPATCH_SAMPLE_FORMAT_IS_UNSIGNED(format)
504             && (width == IPATCH_SAMPLE_FLOAT
505                 || width == IPATCH_SAMPLE_DOUBLE))
506     {
507         return (FALSE);
508     }
509 
510     if(IPATCH_SAMPLE_FORMAT_GET_CHANNEL_COUNT(format) >= IPATCH_SAMPLE_MAX_CHANNELS)
511     {
512         return (FALSE);
513     }
514 
515     return (TRUE);
516 }
517 
518 /**
519  * ipatch_sample_format_transform_verify:
520  * @src_format: Source sample format
521  * @dest_format: Destination sample format
522  * @channel_map: Channel mapping (use #IPATCH_SAMPLE_UNITY_CHANNEL_MAP
523  *   to map all input channels to the same output channels, see
524  *   #IPATCH_SAMPLE_MAP_CHANNEL macro for constructing channel map values)
525  *
526  * Verify source and destination sample formats and channel map for a sample
527  * transform operation.
528  *
529  * Returns: %TRUE on success, %FALSE otherwise
530  */
531 gboolean
ipatch_sample_format_transform_verify(int src_format,int dest_format,guint32 channel_map)532 ipatch_sample_format_transform_verify(int src_format, int dest_format,
533                                       guint32 channel_map)
534 {
535     int src_chans, dest_chans, i;
536 
537     if(!ipatch_sample_format_verify(src_format)
538             || !ipatch_sample_format_verify(dest_format))
539     {
540         return (FALSE);
541     }
542 
543     src_chans = IPATCH_SAMPLE_FORMAT_GET_CHANNEL_COUNT(src_format);
544     dest_chans = IPATCH_SAMPLE_FORMAT_GET_CHANNEL_COUNT(dest_format);
545 
546     for(i = 0; i < dest_chans; i++)
547         if(((channel_map >> (i * 3)) & 0x07) >= (guint32)src_chans)
548         {
549             return (FALSE);
550         }
551 
552     return (TRUE);
553 }
554 
555 /**
556  * ipatch_sample_get_transform_funcs: (skip)
557  * @src_format: Source audio format to convert from
558  * @dest_format: Destination audio format to convert to
559  * @channel_map: Channel mapping (use #IPATCH_SAMPLE_UNITY_CHANNEL_MAP
560  *   to map all input channels to the same output channels, 3 bits times
561  *   #IPATCH_SAMPLE_MAX_CHANNELS (8) = 24 bits total, see
562  *   #IPATCH_SAMPLE_MAP_CHANNEL macro for constructing channel map values)
563  * @buf1_max_frame: Output - maximum sample frame size for first buffer
564  * @buf2_max_frame: Output - maximum sample frame size for second buffer
565  * @funcs: Caller provided array to store transform functions to.  It should
566  *   have at least #IPATCH_SAMPLE_MAX_TRANSFORM_FUNCS elements.
567  *
568  * Get transform function array for converting from @src_format to
569  * @dest_format.
570  *
571  * Returns: Count of function pointers stored to @funcs.  Can be 0 if no
572  *   transform is required.
573  */
574 guint
ipatch_sample_get_transform_funcs(int src_format,int dest_format,guint32 channel_map,guint * buf1_max_frame,guint * buf2_max_frame,IpatchSampleTransformFunc * funcs)575 ipatch_sample_get_transform_funcs(int src_format, int dest_format,
576                                   guint32 channel_map,
577                                   guint *buf1_max_frame,
578                                   guint *buf2_max_frame,
579                                   IpatchSampleTransformFunc *funcs)
580 {
581     int swidth, dwidth, curfmt, schan, dchan;
582     int func_index = 0;
583     int max[2] = { 0 };		/* max frame sizes for buffers */
584 
585     g_return_val_if_fail(ipatch_sample_format_verify(src_format), 0);
586     g_return_val_if_fail(ipatch_sample_format_verify(dest_format), 0);
587     g_return_val_if_fail(funcs != NULL, 0);
588 
589     if(buf1_max_frame)
590     {
591         *buf1_max_frame = 0;
592     }
593 
594     if(buf2_max_frame)
595     {
596         *buf2_max_frame = 0;
597     }
598 
599     swidth = src_format & IPATCH_SAMPLE_WIDTH_MASK;
600     dwidth = dest_format & IPATCH_SAMPLE_WIDTH_MASK;
601     schan = IPATCH_SAMPLE_FORMAT_GET_CHANNEL_COUNT(src_format);
602     dchan = IPATCH_SAMPLE_FORMAT_GET_CHANNEL_COUNT(dest_format);
603     curfmt = src_format;
604 
605     /* init max frame size of first buffer to input frame size */
606     max[0] = ipatch_sample_format_size(curfmt);
607 
608     /* convert to 4 byte 24 bit data before 3 byte */
609     if(G_UNLIKELY(dwidth == IPATCH_SAMPLE_REAL24BIT))
610     {
611         dwidth = IPATCH_SAMPLE_24BIT;
612     }
613 
614     /* if 3 byte 24 bit data, convert to native endian 4 byte integers */
615     if(G_UNLIKELY(swidth == IPATCH_SAMPLE_REAL24BIT))
616     {
617         if(IPATCH_SAMPLE_FORMAT_IS_LENDIAN(src_format))
618             funcs[func_index++] = IPATCH_SAMPLE_FORMAT_IS_SIGNED(src_format)
619                                   ? TFF_sle3bto4b : TFF_ule3bto4b;
620         else
621             funcs[func_index++] = IPATCH_SAMPLE_FORMAT_IS_SIGNED(src_format)
622                                   ? TFF_sbe3bto4b : TFF_ube3bto4b;
623 
624         swidth = IPATCH_SAMPLE_24BIT;
625         curfmt = (curfmt & ~IPATCH_SAMPLE_WIDTH_MASK) | IPATCH_SAMPLE_24BIT;
626 
627         update_max_size(&max[func_index & 1], curfmt);
628     }
629 
630     /* if converting from more channels to less */
631     if(G_UNLIKELY(dchan < schan))
632     {
633         if(G_LIKELY(dchan == 1 && schan == 2))      /* Stereo to mono mapping? */
634         {
635             /* Stereo to left map? */
636             if(IPATCH_SAMPLE_MAP_GET_CHANNEL(channel_map, 0) == 0)
637             {
638                 funcs[func_index++] = stereo_to_left_tff[swidth - 1];
639             }
640             else      /* Stereo to right */
641             {
642                 funcs[func_index++] = stereo_to_right_tff[swidth - 1];
643             }
644         }
645         else
646         {
647             funcs[func_index++] = chanmap_tff[swidth - 1];
648         }
649 
650         curfmt = (curfmt & ~IPATCH_SAMPLE_CHANNEL_MASK) | (dchan - 1);
651         update_max_size(&max[func_index & 1], curfmt);
652     }
653 
654     /* source format differs from host byte order? - swap
655        REAL24BIT is already swapped by 3 to 4 byte conversion above */
656     if(G_UNLIKELY
657             (IPATCH_SAMPLE_FORMAT_IS_LENDIAN(src_format)
658              != (G_BYTE_ORDER == G_LITTLE_ENDIAN) && swap_tff[swidth - 1]
659              && (src_format & IPATCH_SAMPLE_WIDTH_MASK) != IPATCH_SAMPLE_REAL24BIT))
660     {
661         funcs[func_index++] = swap_tff[swidth - 1];
662 
663         curfmt ^= IPATCH_SAMPLE_BENDIAN;
664         update_max_size(&max[func_index & 1], curfmt);
665     }
666 
667     /* if src and dest aren't floating point and sign differs - toggle sign */
668     if(G_UNLIKELY
669             (swidth != IPATCH_SAMPLE_FLOAT && swidth != IPATCH_SAMPLE_DOUBLE
670              && dwidth != IPATCH_SAMPLE_FLOAT && dwidth != IPATCH_SAMPLE_DOUBLE
671              && IPATCH_SAMPLE_FORMAT_IS_SIGNED(src_format)
672              != IPATCH_SAMPLE_FORMAT_IS_SIGNED(dest_format)))
673     {
674         if(G_UNLIKELY(swidth == IPATCH_SAMPLE_24BIT))
675             funcs[func_index++] = IPATCH_SAMPLE_FORMAT_IS_SIGNED(src_format)
676                                   ? TFF_signtou24 : TFF_unsigntos24;
677         else
678         {
679             funcs[func_index++] = sign_tff[swidth - 1];
680         }
681 
682         curfmt ^= IPATCH_SAMPLE_UNSIGNED;
683         update_max_size(&max[func_index & 1], curfmt);
684     }
685 
686     if(G_LIKELY(swidth != dwidth))		/* format differs? */
687     {
688         if(G_UNLIKELY(IPATCH_SAMPLE_FORMAT_IS_FLOATING(curfmt)))
689         {
690             if(IPATCH_SAMPLE_FORMAT_IS_SIGNED(dest_format))
691             {
692                 funcs[func_index++] = signed_tff[swidth - 1][dwidth - 1];
693             }
694             else	/* unsigned */
695             {
696                 funcs[func_index++] = unsigned_tff[swidth - 1][dwidth - 1];
697             }
698         }
699         else
700         {
701             if(IPATCH_SAMPLE_FORMAT_IS_SIGNED(curfmt))   /* signed transform? */
702             {
703                 funcs[func_index++] = signed_tff[swidth - 1][dwidth - 1];
704             }
705             else	/* unsigned */
706             {
707                 funcs[func_index++] = unsigned_tff[swidth - 1][dwidth - 1];
708             }
709         }
710 
711         curfmt = (curfmt & ~IPATCH_SAMPLE_WIDTH_MASK) | dwidth;
712         update_max_size(&max[func_index & 1], curfmt);
713     }
714 
715     /* destination format differs from host byte order? - swap
716        REAL24BIT is swapped below */
717     if(G_UNLIKELY
718             (IPATCH_SAMPLE_FORMAT_IS_LENDIAN(dest_format)
719              != (G_BYTE_ORDER == G_LITTLE_ENDIAN) && swap_tff[dwidth - 1]
720              && (dest_format & IPATCH_SAMPLE_WIDTH_MASK) != IPATCH_SAMPLE_REAL24BIT))
721     {
722         funcs[func_index++] = swap_tff[dwidth - 1];
723 
724         curfmt ^= IPATCH_SAMPLE_BENDIAN;
725         update_max_size(&max[func_index & 1], curfmt);
726     }
727 
728     /* if converting from less channels to more */
729     if(G_UNLIKELY(dchan > schan))
730     {
731         if(G_LIKELY(dchan == 2 && schan == 1))      /* Mono to stereo mapping? */
732         {
733             funcs[func_index++] = mono_to_stereo_tff[dwidth - 1];
734         }
735         else
736         {
737             funcs[func_index++] = chanmap_tff[dwidth - 1];    /* Arbitrary channel mapping */
738         }
739 
740         curfmt = (curfmt & ~IPATCH_SAMPLE_CHANNEL_MASK) | (dchan - 1);
741         update_max_size(&max[func_index & 1], curfmt);
742     }
743 
744     /* OPTME - Could create channel transform funcs for real 24 bit */
745 
746     /* if destination is 3 byte 24 bit data then convert to it */
747     if(G_UNLIKELY
748             ((dest_format & IPATCH_SAMPLE_WIDTH_MASK) == IPATCH_SAMPLE_REAL24BIT))
749     {
750         if(IPATCH_SAMPLE_FORMAT_IS_LENDIAN(dest_format))
751             funcs[func_index++] = IPATCH_SAMPLE_FORMAT_IS_SIGNED(src_format)
752                                   ? TFF_4btosle3b : TFF_4btoule3b;
753         else
754             funcs[func_index++] = IPATCH_SAMPLE_FORMAT_IS_SIGNED(src_format)
755                                   ? TFF_4btosbe3b : TFF_4btoube3b;
756 
757         curfmt = (curfmt & ~IPATCH_SAMPLE_WIDTH_MASK) | IPATCH_SAMPLE_REAL24BIT;
758         update_max_size(&max[func_index & 1], curfmt);
759     }
760 
761     if(buf1_max_frame)
762     {
763         *buf1_max_frame = max[0];
764     }
765 
766     if(buf2_max_frame)
767     {
768         *buf2_max_frame = max[1];
769     }
770 
771     return (func_index);
772 }
773 
774 static inline void
update_max_size(int * curmax,int format)775 update_max_size(int *curmax, int format)
776 {
777     int bytewidth;
778 
779     bytewidth = ipatch_sample_format_size(format);
780 
781     if(bytewidth > *curmax)
782     {
783         *curmax = bytewidth;
784     }
785 }
786