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