1/*
2 * Copyright (c) 2003-2004, Marcus Overhagen
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 *  * Redistributions of source code must retain the above copyright notice,
9 *    this list of conditions and the following disclaimer.
10 *  * Redistributions in binary form must reproduce the above copyright notice,
11 *    this list of conditions and the following disclaimer in the documentation
12 *    and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
18 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
21 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
22 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
23 * OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25#include <ByteOrder.h>
26#include <OS.h>
27#include "AudioConversion.h"
28#include "RawFormats.h"
29
30// XXX GCC doesn't always generate nice code...
31
32typedef float float32;
33typedef double float64;
34
35class uint8_sample
36{
37public:
38	inline operator uint8() const { return data; }
39	inline operator int8()  const { return (int32)data - 128; }
40	inline operator int16() const { return ((int32)data - 128) << 8; }
41	inline operator int32() const { return ((int32)data - 128) << 24; }
42	inline operator float() const { return ((int32)data - 128) * (1.0f / 127.0f); }
43private:
44	uint8 data;
45} _PACKED;
46
47class int8_sample
48{
49public:
50	inline operator uint8() const { return (int32)data + 128; }
51	inline operator int8()  const { return data; }
52	inline operator int16() const { return (int16)data << 8; }
53	inline operator int32() const { return (int32)data << 24; }
54	inline operator float() const { return (int32)data * (1.0f / 127.0f); }
55private:
56	int8 data;
57} _PACKED;
58
59class int16_sample
60{
61public:
62	inline operator uint8() const { return (uint8)((int8)(data >> 8) + 128); }
63	inline operator int8()  const { return (int8)(data >> 8); }
64	inline operator int16() const { return data; }
65	inline operator int32() const { return (int32)data << 16; }
66	inline operator float() const { return data * (1.0f / 32767.0f); }
67private:
68	int16 data;
69} _PACKED;
70
71class int24_sample
72{
73public:
74#if B_HOST_IS_LENDIAN
75	inline operator uint8() const { return (int32)data[2] + 128; }
76	inline operator int8()  const { return (int8)data[2]; }
77	inline operator int16() const { return (int16)((uint32)data[2] << 8 | (uint32)data[1]); }
78	inline operator int32() const { return (int32)((uint32)data[2] << 24 | (uint32)data[1] << 16 | (uint32)data[0] << 8); }
79	inline operator float() const { return (int32)((uint32)data[2] << 24 | (uint32)data[1] << 16 | (uint32)data[0] << 8) * (1.0f / 2147483647.0f); }
80#else
81	inline operator uint8() const { return (int32)data[0] + 128; }
82	inline operator int8()  const { return (int8)data[0]; }
83	inline operator int16() const { return (int16)((uint32)data[0] << 8 | (uint32)data[1]); }
84	inline operator int32() const { return (int32)((uint32)data[0] << 24 | (uint32)data[1] << 16 | (uint32)data[2] << 8); }
85	inline operator float() const { return (int32)((uint32)data[0] << 24 | (uint32)data[1] << 16 | (uint32)data[2] << 8) * (1.0f / 2147483647.0f); }
86#endif
87private:
88	uint8 data[3];
89} _PACKED;
90
91class int32_sample
92{
93public:
94	inline operator uint8() const { return (int8)(data >> 24) + 128; }
95	inline operator int8()  const { return (int8)(data >> 24); }
96	inline operator int16() const { return (int16)(data >> 16); }
97	inline operator int32() const { return data; }
98	inline operator float() const { return data * (1.0f / 2147483647.0f); }
99private:
100	int32 data;
101} _PACKED;
102
103class float32_sample
104{
105public:
106	inline operator uint8() const { int32 v = (int32)(data * 127.0f) + 128; if (v > 255) v = 255; else if (v < 0) v = 0; return v; }
107	inline operator int8()  const { int32 v = (int32)(data * 127.0f); if (v > 127) v = 127; else if (v < -127) v = -127; return v; }
108	inline operator int16() const { int32 v = (int32)(data * 32767.0f); if (v > 32767) v = 32767; else if (v < -32767) v = -32767; return v; }
109	inline operator int32() const { if (data <= -1.0f) return INT32_MIN; if (data >= 1.0f) return INT32_MAX; return (int32)(data * INT32_MAX); }
110	inline operator float() const { return data; }
111private:
112	float32 data;
113} _PACKED;
114
115class float64_sample
116{
117public:
118	inline operator uint8() const { int32 v = (int32)(data * 127.0f) + 128; if (v > 255) v = 255; else if (v < 0) v = 0; return v; }
119	inline operator int8()  const { int32 v = (int32)(data * 127.0f); if (v > 127) v = 127; else if (v < -127) v = -127; return v; }
120	inline operator int16() const { int32 v = (int32)(data * 32767.0f); if (v > 32767) v = 32767; else if (v < -32767) v = -32767; return v; }
121	inline operator int32() const { float64 v; if (data < -1.0) v = -1.0; else if (data > 1.0) v = 1.0; else v = data; return (int32)(v * INT32_MAX); }
122	inline operator float() const { return data; }
123private:
124	float64 data;
125} _PACKED;
126
127#define CONVERT(src_type, dst_type)				\
128void src_type##_to_##dst_type (void *dst, const void *src, int32 count) \
129{												\
130	const src_type##_sample *s = (const src_type##_sample *) src;	\
131	dst_type *d = (dst_type *) dst;	\
132	int32 c = count >> 4;				\
133	if (!c) goto fin1;							\
134	do {										\
135		d[0] = s[0]; d[1] = s[1];				\
136		d[2] = s[2]; d[3] = s[3];				\
137		d[4] = s[4]; d[5] = s[5];				\
138		d[6] = s[6]; d[7] = s[7];				\
139		d[8] = s[8]; d[9] = s[9];				\
140		d[10] = s[10]; d[11] = s[11];			\
141		d[12] = s[12]; d[13] = s[13];			\
142		d[14] = s[14]; d[15] = s[15];			\
143		s += 16; d += 16;						\
144	} while (--c);								\
145fin1:											\
146	c = count & 15;								\
147	if (!c) goto fin2;							\
148	do {										\
149		*(d++) = *(s++);						\
150	} while (--c);								\
151fin2:											\
152	;											\
153}
154
155
156CONVERT(uint8, uint8)
157CONVERT(uint8, int8)
158CONVERT(uint8, int16)
159CONVERT(uint8, int32)
160CONVERT(uint8, float32)
161
162CONVERT(int8, uint8)
163CONVERT(int8, int8)
164CONVERT(int8, int16)
165CONVERT(int8, int32)
166CONVERT(int8, float32)
167
168CONVERT(int16, uint8)
169CONVERT(int16, int8)
170CONVERT(int16, int16)
171CONVERT(int16, int32)
172CONVERT(int16, float32)
173
174CONVERT(int24, uint8)
175CONVERT(int24, int8)
176CONVERT(int24, int16)
177CONVERT(int24, int32)
178CONVERT(int24, float32)
179
180CONVERT(int32, uint8)
181CONVERT(int32, int8)
182CONVERT(int32, int16)
183CONVERT(int32, int32)
184CONVERT(int32, float32)
185
186CONVERT(float32, uint8)
187CONVERT(float32, int8)
188CONVERT(float32, int16)
189CONVERT(float32, int32)
190CONVERT(float32, float32)
191
192CONVERT(float64, uint8)
193CONVERT(float64, int8)
194CONVERT(float64, int16)
195CONVERT(float64, int32)
196CONVERT(float64, float32)
197
198void
199swap_int16(void *data, int32 count)
200{
201	swap_data(B_INT16_TYPE, data, count * 2, B_SWAP_ALWAYS);
202}
203
204void
205swap_int24(void *data, int32 count)
206{
207	int32 c = count;
208	uint8 *d = (uint8 *)data;
209	if (!c)
210		return;
211	do {
212		uint8 temp = d[0];
213		d[0] = d[2];
214		d[2] = temp;
215		d += 3;
216	} while (--c);
217}
218
219void
220swap_int32(void *data, int32 count)
221{
222	swap_data(B_INT32_TYPE, data, count * 4, B_SWAP_ALWAYS);
223}
224
225void
226swap_float32(void *data, int32 count)
227{
228	swap_data(B_FLOAT_TYPE, data, count * 4, B_SWAP_ALWAYS);
229}
230
231void
232swap_float64(void *data, int32 count)
233{
234	swap_data(B_INT64_TYPE, data, count * 8, B_SWAP_ALWAYS);
235}
236