advapi32: Return a fake handle from EventRegister.
[wine/multimedia.git] / dlls / dsound / dsound_convert.c
blob63f1eb0bfbe859d1bc241e87929874d56256e99d
1 /* DirectSound format conversion and mixing routines
3 * Copyright 2007 Maarten Lankhorst
4 * Copyright 2011 Owen Rudge for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 /* 8 bits is unsigned, the rest is signed.
22 * First I tried to reuse existing stuff from alsa-lib, after that
23 * didn't work, I gave up and just went for individual hacks.
25 * 24 bit is expensive to do, due to unaligned access.
26 * In dlls/winex11.drv/dib_convert.c convert_888_to_0888_asis there is a way
27 * around it, but I'm happy current code works, maybe something for later.
29 * The ^ 0x80 flips the signed bit, this is the conversion from
30 * signed (-128.. 0.. 127) to unsigned (0...255)
31 * This is only temporary: All 8 bit data should be converted to signed.
32 * then when fed to the sound card, it should be converted to unsigned again.
34 * Sound is LITTLE endian
37 #include "config.h"
39 #include <stdarg.h>
40 #include <math.h>
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 "dsound_private.h"
52 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
54 #ifdef WORDS_BIGENDIAN
55 #define le16(x) RtlUshortByteSwap((x))
56 #define le32(x) RtlUlongByteSwap((x))
57 #else
58 #define le16(x) (x)
59 #define le32(x) (x)
60 #endif
62 static float get8(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel)
64 const BYTE* buf = dsb->buffer->memory;
65 buf += pos + channel;
66 return (buf[0] - 0x80) / (float)0x80;
69 static float get16(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel)
71 const BYTE* buf = dsb->buffer->memory;
72 const SHORT *sbuf = (const SHORT*)(buf + pos + 2 * channel);
73 SHORT sample = (SHORT)le16(*sbuf);
74 return sample / (float)0x8000;
77 static float get24(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel)
79 LONG sample;
80 const BYTE* buf = dsb->buffer->memory;
81 buf += pos + 3 * channel;
82 /* The next expression deliberately has an overflow for buf[2] >= 0x80,
83 this is how negative values are made.
85 sample = (buf[0] << 8) | (buf[1] << 16) | (buf[2] << 24);
86 return sample / (float)0x80000000U;
89 static float get32(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel)
91 const BYTE* buf = dsb->buffer->memory;
92 const LONG *sbuf = (const LONG*)(buf + pos + 4 * channel);
93 LONG sample = le32(*sbuf);
94 return sample / (float)0x80000000U;
97 static float getieee32(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel)
99 const BYTE* buf = dsb->buffer->memory;
100 const float *sbuf = (const float*)(buf + pos + 4 * channel);
101 /* The value will be clipped later, when put into some non-float buffer */
102 return *sbuf;
105 const bitsgetfunc getbpp[5] = {get8, get16, get24, get32, getieee32};
107 float get_mono(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel)
109 DWORD channels = dsb->pwfx->nChannels;
110 DWORD c;
111 float val = 0;
112 /* XXX: does Windows include LFE into the mix? */
113 for (c = 0; c < channels; c++)
114 val += dsb->get_aux(dsb, pos, c);
115 val /= channels;
116 return val;
119 static void put8(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value)
121 BYTE* buf = dsb->device->tmp_buffer;
122 buf += pos + channel;
123 if(value <= -1.f)
124 *buf = 0;
125 else if(value >= 1.f * 0x7F / 0x80)
126 *buf = 0xFF;
127 else
128 *buf = lrintf((value + 1.f) * 0x80);
131 static void put16(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value)
133 BYTE* buf = dsb->device->tmp_buffer;
134 SHORT *sbuf = (SHORT*)(buf + pos + 2 * channel);
135 if(value <= -1.f)
136 *sbuf = 0x8000;
137 else if(value >= 1.f * 0x7FFF / 0x8000)
138 *sbuf = 0x7FFF;
139 else
140 *sbuf = le16(lrintf(value * 0x8000));
143 static void put24(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value)
145 BYTE* buf = dsb->device->tmp_buffer;
146 LONG t;
147 buf += pos + 3 * channel;
148 if(value <= -1.f)
149 t = 0x80000000;
150 else if(value >= 1.f * 0x7FFFFF / 0x800000)
151 t = 0x7FFFFF00;
152 else
153 t = lrintf(value * 0x80000000U);
154 buf[0] = (t >> 8) & 0xFF;
155 buf[1] = (t >> 16) & 0xFF;
156 buf[2] = (t >> 24) & 0xFF;
159 static void put32(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value)
161 BYTE* buf = dsb->device->tmp_buffer;
162 LONG *sbuf = (LONG*)(buf + pos + 4 * channel);
163 if(value <= -1.f)
164 *sbuf = 0x80000000;
165 else if(value >= 1.f * 0x7FFFFFFF / 0x80000000U) /* this rounds to 1.f */
166 *sbuf = 0x7FFFFFFF;
167 else
168 *sbuf = le32(lrintf(value * 0x80000000U));
171 const bitsputfunc putbpp[4] = {put8, put16, put24, put32};
173 void put_mono2stereo(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value)
175 dsb->put_aux(dsb, pos, 0, value);
176 dsb->put_aux(dsb, pos, 1, value);
179 static void mix8(signed char *src, INT *dst, unsigned len)
181 TRACE("%p - %p %d\n", src, dst, len);
182 while (len--)
183 /* 8-bit WAV is unsigned, it's here converted to signed, normalize function will convert it back again */
184 *(dst++) += (signed char)((BYTE)*(src++) - (BYTE)0x80);
187 static void mix16(SHORT *src, INT *dst, unsigned len)
189 TRACE("%p - %p %d\n", src, dst, len);
190 len /= 2;
191 while (len--)
193 *dst += le16(*src);
194 ++dst; ++src;
198 static void mix24(BYTE *src, INT *dst, unsigned len)
200 TRACE("%p - %p %d\n", src, dst, len);
201 len /= 3;
202 while (len--)
204 DWORD field;
205 field = ((DWORD)src[2] << 16) + ((DWORD)src[1] << 8) + (DWORD)src[0];
206 if (src[2] & 0x80)
207 field |= 0xFF000000U;
208 *(dst++) += field;
209 src += 3;
213 static void mix32(INT *src, LONGLONG *dst, unsigned len)
215 TRACE("%p - %p %d\n", src, dst, len);
216 len /= 4;
217 while (len--)
218 *(dst++) += le32(*(src++));
221 const mixfunc mixfunctions[4] = {
222 (mixfunc)mix8,
223 (mixfunc)mix16,
224 (mixfunc)mix24,
225 (mixfunc)mix32
228 static void norm8(INT *src, signed char *dst, unsigned len)
230 TRACE("%p - %p %d\n", src, dst, len);
231 while (len--)
233 *dst = (*src) + 0x80;
234 if (*src < -0x80)
235 *dst = 0;
236 else if (*src > 0x7f)
237 *dst = 0xff;
238 ++dst;
239 ++src;
243 static void norm16(INT *src, SHORT *dst, unsigned len)
245 TRACE("%p - %p %d\n", src, dst, len);
246 len /= 2;
247 while (len--)
249 *dst = le16(*src);
250 if (*src <= -0x8000)
251 *dst = le16(0x8000);
252 else if (*src > 0x7fff)
253 *dst = le16(0x7fff);
254 ++dst;
255 ++src;
259 static void norm24(INT *src, BYTE *dst, unsigned len)
261 TRACE("%p - %p %d\n", src, dst, len);
262 len /= 3;
263 while (len--)
265 if (*src <= -0x800000)
267 dst[0] = 0;
268 dst[1] = 0;
269 dst[2] = 0x80;
271 else if (*src > 0x7fffff)
273 dst[0] = 0xff;
274 dst[1] = 0xff;
275 dst[2] = 0x7f;
277 else
279 dst[0] = *src;
280 dst[1] = *src >> 8;
281 dst[2] = *src >> 16;
283 dst += 3;
284 ++src;
288 static void norm32(LONGLONG *src, INT *dst, unsigned len)
290 TRACE("%p - %p %d\n", src, dst, len);
291 len /= 4;
292 while (len--)
294 *dst = le32(*src);
295 if (*src <= -(LONGLONG)0x80000000)
296 *dst = le32(0x80000000);
297 else if (*src > 0x7fffffff)
298 *dst = le32(0x7fffffff);
299 ++dst;
300 ++src;
304 const normfunc normfunctions[4] = {
305 (normfunc)norm8,
306 (normfunc)norm16,
307 (normfunc)norm24,
308 (normfunc)norm32,