shell32: Fix shlexec crashing on Vista.
[wine] / dlls / dsound / dsound_convert.c
1 /* DirectSound format conversion and mixing routines
2  *
3  * Copyright 2007 Maarten Lankhorst
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
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 GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18  */
19
20 /* 8 bits is unsigned, the rest is signed.
21  * First I tried to reuse existing stuff from alsa-lib, after that
22  * didn't work, I gave up and just went for individual hacks.
23  *
24  * 24 bit is expensive to do, due to unaligned access.
25  * In dlls/winex11.drv/dib_convert.c convert_888_to_0888_asis there is a way
26  * around it, but I'm happy current code works, maybe something for later.
27  *
28  * The ^ 0x80 flips the signed bit, this is the conversion from
29  * signed (-128.. 0.. 127) to unsigned (0...255)
30  * This is only temporary: All 8 bit data should be converted to signed.
31  * then when fed to the sound card, it should be converted to unsigned again.
32  *
33  * Sound is LITTLE endian
34  */
35
36 #include "config.h"
37 #ifdef HAVE_STDINT_H
38 #include <stdint.h>
39 #endif
40 #include <stdarg.h>
41
42 #define NONAMELESSSTRUCT
43 #define NONAMELESSUNION
44 #include "windef.h"
45 #include "winbase.h"
46 #include "mmsystem.h"
47 #include "winternl.h"
48 #include "wine/debug.h"
49 #include "dsound.h"
50 #include "dsdriver.h"
51 #include "dsound_private.h"
52
53 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
54
55 typedef struct {
56     uint8_t byte[3];
57 } int24_struct;
58
59 #ifdef WORDS_BIGENDIAN
60 #define le16(x) RtlUshortByteSwap((x))
61 #define le32(x) RtlUlongByteSwap((x))
62 #else
63 #define le16(x) (x)
64 #define le32(x) (x)
65 #endif
66
67 static void convert_8_to_8 (const void *src, void *dst)
68 {
69     uint8_t *dest = dst;
70     *dest = *(uint8_t*)src;
71 }
72
73 static void convert_8_to_16 (const void *src, void *dst)
74 {
75     uint16_t dest = *(uint8_t*)src, *dest16 = dst;
76     *dest16 = le16(dest * 257 - 32768);
77 }
78
79 static void convert_8_to_24 (const void *src, void *dst)
80 {
81     uint8_t dest = *(uint8_t*)src;
82     int24_struct *dest24 = dst;
83     dest24->byte[0] = dest;
84     dest24->byte[1] = dest;
85     dest24->byte[2] = dest - 0x80;
86 }
87
88 static void convert_8_to_32 (const void *src, void *dst)
89 {
90     uint32_t dest = *(uint8_t*)src, *dest32 = dst;
91     *dest32 = le32(dest * 16843009 - 2147483648U);
92 }
93
94 static void convert_16_to_8 (const void *src, void *dst)
95 {
96     uint8_t *dst8 = dst;
97     *dst8 = (le16(*(uint16_t*)src)) / 256;
98     *dst8 -= 0x80;
99 }
100
101 static void convert_16_to_16 (const void *src, void *dst)
102 {
103     uint16_t *dest = dst;
104     *dest = *(uint16_t*)src;
105 }
106
107 static void convert_16_to_24 (const void *src, void *dst)
108 {
109     uint16_t dest = le16(*(uint16_t*)src);
110     int24_struct *dest24 = dst;
111
112     dest24->byte[0] = dest / 256;
113     dest24->byte[1] = dest;
114     dest24->byte[2] = dest / 256;
115 }
116
117 static void convert_16_to_32 (const void *src, void *dst)
118 {
119     uint32_t dest = *(uint16_t*)src, *dest32 = dst;
120     *dest32 = dest * 65537;
121 }
122
123 static void convert_24_to_8 (const void *src, void *dst)
124 {
125     uint8_t *dst8 = dst;
126     *dst8 = ((int24_struct*)src)->byte[2];
127 }
128
129 static void convert_24_to_16 (const void *src, void *dst)
130 {
131     uint16_t *dest16 = dst;
132     const int24_struct *source = src;
133     *dest16 = le16(source->byte[2] * 256 + source->byte[1]);
134 }
135
136 static void convert_24_to_24 (const void *src, void *dst)
137 {
138     int24_struct *dest24 = dst;
139     const int24_struct *src24 = src;
140     *dest24 = *src24;
141 }
142
143 static void convert_24_to_32 (const void *src, void *dst)
144 {
145     uint32_t *dest32 = dst;
146     const int24_struct *source = src;
147     *dest32 = le32(source->byte[2] * 16777217 + source->byte[1] * 65536 + source->byte[0] * 256);
148 }
149
150 static void convert_32_to_8 (const void *src, void *dst)
151 {
152     uint8_t *dst8 = dst;
153     *dst8 = (le32(*(uint32_t*)src) / 16777216);
154     *dst8 -= 0x80;
155 }
156
157 static void convert_32_to_16 (const void *src, void *dst)
158 {
159     uint16_t *dest16 = dst;
160     *dest16 = le16(le32(*(uint32_t*)src) / 65536);
161 }
162
163 static void convert_32_to_24 (const void *src, void *dst)
164 {
165     uint32_t dest = le32(*(uint32_t*)dst);
166     int24_struct *dest24 = dst;
167
168     dest24->byte[0] = dest / 256;
169     dest24->byte[1] = dest / 65536;
170     dest24->byte[2] = dest / 16777216;
171 }
172
173 static void convert_32_to_32 (const void *src, void *dst)
174 {
175     uint32_t *dest = dst;
176     *dest = *(uint32_t*)src;
177 }
178
179 const bitsconvertfunc convertbpp[4][4] = {
180     { convert_8_to_8, convert_8_to_16, convert_8_to_24, convert_8_to_32 },
181     { convert_16_to_8, convert_16_to_16, convert_16_to_24, convert_16_to_32 },
182     { convert_24_to_8, convert_24_to_16, convert_24_to_24, convert_24_to_32 },
183     { convert_32_to_8, convert_32_to_16, convert_32_to_24, convert_32_to_32 },
184 };
185
186 static void mix8(int8_t *src, int32_t *dst, unsigned len)
187 {
188     TRACE("%p - %p %d\n", src, dst, len);
189     while (len--)
190         /* 8-bit WAV is unsigned, it's here converted to signed, normalize function will convert it back again */
191         *(dst++) += (int8_t)((uint8_t)*(src++) - (uint8_t)0x80);
192 }
193
194 static void mix16(int16_t *src, int32_t *dst, unsigned len)
195 {
196     TRACE("%p - %p %d\n", src, dst, len);
197     len /= 2;
198     while (len--)
199     {
200         *dst += le16(*src);
201         ++dst; ++src;
202     }
203 }
204
205 static void mix24(int24_struct *src, int32_t *dst, unsigned len)
206 {
207     TRACE("%p - %p %d\n", src, dst, len);
208     len /= 3;
209     while (len--)
210     {
211         uint32_t field;
212         field = ((unsigned)src->byte[2] << 16) + ((unsigned)src->byte[1] << 8) + (unsigned)src->byte[0];
213         if (src->byte[2] & 0x80)
214             field |= 0xFF000000U;
215         *(dst++) += field;
216         ++src;
217     }
218 }
219
220 static void mix32(int32_t *src, int64_t *dst, unsigned len)
221 {
222     TRACE("%p - %p %d\n", src, dst, len);
223     len /= 4;
224     while (len--)
225         *(dst++) += le32(*(src++));
226 }
227
228 const mixfunc mixfunctions[4] = {
229     (mixfunc)mix8,
230     (mixfunc)mix16,
231     (mixfunc)mix24,
232     (mixfunc)mix32
233 };
234
235 static void norm8(int32_t *src, int8_t *dst, unsigned len)
236 {
237     TRACE("%p - %p %d\n", src, dst, len);
238     while (len--)
239     {
240         *dst = (*src) + 0x80;
241         if (*src < -0x80)
242             *dst = 0;
243         else if (*src > 0x7f)
244             *dst = 0xff;
245         ++dst;
246         ++src;
247     }
248 }
249
250 static void norm16(int32_t *src, int16_t *dst, unsigned len)
251 {
252     TRACE("%p - %p %d\n", src, dst, len);
253     len /= 2;
254     while (len--)
255     {
256         *dst = le16(*src);
257         if (*src <= -0x8000)
258             *dst = le16(0x8000);
259         else if (*src > 0x7fff)
260             *dst = le16(0x7fff);
261         ++dst;
262         ++src;
263     }
264 }
265
266 static void norm24(int32_t *src, int24_struct *dst, unsigned len)
267 {
268     TRACE("%p - %p %d\n", src, dst, len);
269     len /= 3;
270     while (len--)
271     {
272         if (*src <= -0x800000)
273         {
274             dst->byte[0] = 0;
275             dst->byte[1] = 0;
276             dst->byte[2] = 0x80;
277         }
278         else if (*src > 0x7fffff)
279         {
280             dst->byte[0] = 0xff;
281             dst->byte[1] = 0xff;
282             dst->byte[2] = 0x7f;
283         }
284         else
285         {
286             dst->byte[0] = *src;
287             dst->byte[1] = *src >> 8;
288             dst->byte[2] = *src >> 16;
289         }
290         ++dst;
291         ++src;
292     }
293 }
294
295 static void norm32(int64_t *src, int32_t *dst, unsigned len)
296 {
297     TRACE("%p - %p %d\n", src, dst, len);
298     len /= 4;
299     while (len--)
300     {
301         *dst = le32(*src);
302         if (*src <= -(int64_t)0x80000000)
303             *dst = le32(0x80000000);
304         else if (*src > 0x7fffffff)
305             *dst = le32(0x7fffffff);
306         ++dst;
307         ++src;
308     }
309 }
310
311 const normfunc normfunctions[4] = {
312     (normfunc)norm8,
313     (normfunc)norm16,
314     (normfunc)norm24,
315     (normfunc)norm32,
316 };