dwrite: Implement CreateFontFaceFromHdc().
[wine.git] / dlls / dsound / dsound_convert.c
blobd3d686a2cbd0586f28a259137264009740051ede
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 inline unsigned char f_to_8(float value)
121 if(value <= -1.f)
122 return 0;
123 if(value >= 1.f * 0x7f / 0x80)
124 return 0xFF;
125 return lrintf((value + 1.f) * 0x80);
128 static inline SHORT f_to_16(float value)
130 if(value <= -1.f)
131 return 0x8000;
132 if(value >= 1.f * 0x7FFF / 0x8000)
133 return 0x7FFF;
134 return le16(lrintf(value * 0x8000));
137 static LONG f_to_24(float value)
139 if(value <= -1.f)
140 return 0x80000000;
141 if(value >= 1.f * 0x7FFFFF / 0x800000)
142 return 0x7FFFFF00;
143 return lrintf(value * 0x80000000U);
146 static inline LONG f_to_32(float value)
148 if(value <= -1.f)
149 return 0x80000000;
150 if(value >= 1.f * 0x7FFFFFFF / 0x80000000U) /* this rounds to 1.f */
151 return 0x7FFFFFFF;
152 return le32(lrintf(value * 0x80000000U));
155 void putieee32(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value)
157 BYTE *buf = (BYTE *)dsb->device->tmp_buffer;
158 float *fbuf = (float*)(buf + pos + sizeof(float) * channel);
159 *fbuf = value;
162 void put_mono2stereo(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value)
164 dsb->put_aux(dsb, pos, 0, value);
165 dsb->put_aux(dsb, pos, 1, value);
168 void mixieee32(float *src, float *dst, unsigned samples)
170 TRACE("%p - %p %d\n", src, dst, samples);
171 while (samples--)
172 *(dst++) += *(src++);
175 static void norm8(float *src, unsigned char *dst, unsigned len)
177 TRACE("%p - %p %d\n", src, dst, len);
178 while (len--)
180 *dst = f_to_8(*src);
181 ++dst;
182 ++src;
186 static void norm16(float *src, SHORT *dst, unsigned len)
188 TRACE("%p - %p %d\n", src, dst, len);
189 len /= 2;
190 while (len--)
192 *dst = f_to_16(*src);
193 ++dst;
194 ++src;
198 static void norm24(float *src, BYTE *dst, unsigned len)
200 TRACE("%p - %p %d\n", src, dst, len);
201 len /= 3;
202 while (len--)
204 LONG t = f_to_24(*src);
205 dst[0] = (t >> 8) & 0xFF;
206 dst[1] = (t >> 16) & 0xFF;
207 dst[2] = t >> 24;
208 dst += 3;
209 ++src;
213 static void norm32(float *src, INT *dst, unsigned len)
215 TRACE("%p - %p %d\n", src, dst, len);
216 len /= 4;
217 while (len--)
219 *dst = f_to_32(*src);
220 ++dst;
221 ++src;
225 static void normieee32(float *src, float *dst, unsigned len)
227 TRACE("%p - %p %d\n", src, dst, len);
228 len /= 4;
229 while (len--)
231 if(*src > 1)
232 *dst = 1;
233 else if(*src < -1)
234 *dst = -1;
235 else
236 *dst = *src;
237 ++dst;
238 ++src;
242 const normfunc normfunctions[5] = {
243 (normfunc)norm8,
244 (normfunc)norm16,
245 (normfunc)norm24,
246 (normfunc)norm32,
247 (normfunc)normieee32