[MSG711.ACM] Sync with Wine Staging 4.18. CORE-16441
[reactos.git] / dll / win32 / msg711.acm / msg711.c
1 /*
2 * G711 handling (includes A-Law & MU-Law)
3 *
4 * Copyright (C) 2002 Eric Pouech
5 *
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22 #include <assert.h>
23 #include <stdarg.h>
24 #include <string.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wingdi.h"
28 #include "winuser.h"
29 #include "winnls.h"
30 #include "mmsystem.h"
31 #include "mmreg.h"
32 #include "msacm.h"
33 #include "msacmdrv.h"
34 #include "wine/debug.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(g711);
37
38 /***********************************************************************
39 * G711_drvOpen
40 */
41 static LRESULT G711_drvOpen(LPCSTR str)
42 {
43 return 1;
44 }
45
46 /***********************************************************************
47 * G711_drvClose
48 */
49 static LRESULT G711_drvClose(DWORD_PTR dwDevID)
50 {
51 return 1;
52 }
53
54 typedef struct tagAcmG711Data
55 {
56 void (*convert)(PACMDRVSTREAMINSTANCE adsi,
57 const unsigned char*, LPDWORD, unsigned char*, LPDWORD);
58 } AcmG711Data;
59
60 /* table to list all supported formats... those are the basic ones. this
61 * also helps given a unique index to each of the supported formats
62 */
63 typedef struct
64 {
65 int nChannels;
66 int nBits;
67 int rate;
68 } Format;
69
70 static const Format PCM_Formats[] =
71 {
72 /*{1, 8, 8000}, {2, 8, 8000}, */{1, 16, 8000}, {2, 16, 8000},
73 /*{1, 8, 11025}, {2, 8, 11025}, */{1, 16, 11025}, {2, 16, 11025},
74 /*{1, 8, 22050}, {2, 8, 22050}, */{1, 16, 22050}, {2, 16, 22050},
75 /*{1, 8, 44100}, {2, 8, 44100}, */{1, 16, 44100}, {2, 16, 44100},
76 };
77
78 static const Format ALaw_Formats[] =
79 {
80 {1, 8, 8000}, {2, 8, 8000}, {1, 8, 11025}, {2, 8, 11025},
81 {1, 8, 22050}, {2, 8, 22050}, {1, 8, 44100}, {2, 8, 44100},
82 };
83
84 static const Format ULaw_Formats[] =
85 {
86 {1, 8, 8000}, {2, 8, 8000}, {1, 8, 11025}, {2, 8, 11025},
87 {1, 8, 22050}, {2, 8, 22050}, {1, 8, 44100}, {2, 8, 44100},
88 };
89
90 /***********************************************************************
91 * G711_GetFormatIndex
92 */
93 static DWORD G711_GetFormatIndex(const WAVEFORMATEX *wfx)
94 {
95 int i, hi;
96 const Format* fmts;
97
98 switch (wfx->wFormatTag)
99 {
100 case WAVE_FORMAT_PCM:
101 hi = ARRAY_SIZE(PCM_Formats);
102 fmts = PCM_Formats;
103 break;
104 case WAVE_FORMAT_ALAW:
105 hi = ARRAY_SIZE(ALaw_Formats);
106 fmts = ALaw_Formats;
107 break;
108 case WAVE_FORMAT_MULAW:
109 hi = ARRAY_SIZE(ULaw_Formats);
110 fmts = ULaw_Formats;
111 break;
112 default:
113 return 0xFFFFFFFF;
114 }
115
116 for (i = 0; i < hi; i++)
117 {
118 if (wfx->nChannels == fmts[i].nChannels &&
119 wfx->nSamplesPerSec == fmts[i].rate &&
120 wfx->wBitsPerSample == fmts[i].nBits)
121 return i;
122 }
123
124 return 0xFFFFFFFF;
125 }
126
127 /***********************************************************************
128 * R16
129 *
130 * Read a 16 bit sample (correctly handles endianness)
131 */
132 static inline short R16(const unsigned char* src)
133 {
134 return (short)((unsigned short)src[0] | ((unsigned short)src[1] << 8));
135 }
136
137 /***********************************************************************
138 * W16
139 *
140 * Write a 16 bit sample (correctly handles endianness)
141 */
142 static inline void W16(unsigned char* dst, short s)
143 {
144 dst[0] = LOBYTE(s);
145 dst[1] = HIBYTE(s);
146 }
147
148 /* You can uncomment this if you don't want the statically generated conversion
149 * table, but rather recompute the Xlaw => PCM conversion for each sample
150 #define NO_FASTDECODE
151 * Since the conversion tables are rather small (2k), I don't think it's really
152 * interesting not to use them, but keeping the actual conversion code around
153 * is helpful to regenerate the tables when needed.
154 */
155
156 /* -------------------------------------------------------------------------------*/
157
158 /*
159 * This source code is a product of Sun Microsystems, Inc. and is provided
160 * for unrestricted use. Users may copy or modify this source code without
161 * charge.
162 *
163 * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
164 * THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
165 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
166 *
167 * Sun source code is provided with no support and without any obligation on
168 * the part of Sun Microsystems, Inc. to assist in its use, correction,
169 * modification or enhancement.
170 *
171 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
172 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
173 * OR ANY PART THEREOF.
174 *
175 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
176 * or profits or other special, indirect and consequential damages, even if
177 * Sun has been advised of the possibility of such damages.
178 *
179 * Sun Microsystems, Inc.
180 * 2550 Garcia Avenue
181 * Mountain View, California 94043
182 */
183
184 /*
185 * g711.c
186 *
187 * u-law, A-law and linear PCM conversions.
188 */
189
190 /*
191 * December 30, 1994:
192 * Functions linear2alaw, linear2ulaw have been updated to correctly
193 * convert unquantized 16 bit values.
194 * Tables for direct u- to A-law and A- to u-law conversions have been
195 * corrected.
196 * Borge Lindberg, Center for PersonKommunikation, Aalborg University.
197 * bli@cpk.auc.dk
198 *
199 */
200
201 #define SIGN_BIT (0x80) /* Sign bit for an A-law byte. */
202 #define QUANT_MASK (0xf) /* Quantization field mask. */
203 #define NSEGS (8) /* Number of A-law segments. */
204 #define SEG_SHIFT (4) /* Left shift for segment number. */
205 #define SEG_MASK (0x70) /* Segment field mask. */
206
207 static const short seg_aend[8] = {0x1F, 0x3F, 0x7F, 0x0FF, 0x1FF, 0x3FF, 0x7FF, 0x0FFF};
208 static const short seg_uend[8] = {0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF};
209
210 /* copy from CCITT G.711 specifications */
211 static const unsigned char _u2a[128] = { /* u- to A-law conversions */
212 1, 1, 2, 2, 3, 3, 4, 4,
213 5, 5, 6, 6, 7, 7, 8, 8,
214 9, 10, 11, 12, 13, 14, 15, 16,
215 17, 18, 19, 20, 21, 22, 23, 24,
216 25, 27, 29, 31, 33, 34, 35, 36,
217 37, 38, 39, 40, 41, 42, 43, 44,
218 46, 48, 49, 50, 51, 52, 53, 54,
219 55, 56, 57, 58, 59, 60, 61, 62,
220 64, 65, 66, 67, 68, 69, 70, 71,
221 72, 73, 74, 75, 76, 77, 78, 79,
222 /* corrected:
223 81, 82, 83, 84, 85, 86, 87, 88,
224 should be: */
225 80, 82, 83, 84, 85, 86, 87, 88,
226 89, 90, 91, 92, 93, 94, 95, 96,
227 97, 98, 99, 100, 101, 102, 103, 104,
228 105, 106, 107, 108, 109, 110, 111, 112,
229 113, 114, 115, 116, 117, 118, 119, 120,
230 121, 122, 123, 124, 125, 126, 127, 128};
231
232 static const unsigned char _a2u[128] = { /* A- to u-law conversions */
233 1, 3, 5, 7, 9, 11, 13, 15,
234 16, 17, 18, 19, 20, 21, 22, 23,
235 24, 25, 26, 27, 28, 29, 30, 31,
236 32, 32, 33, 33, 34, 34, 35, 35,
237 36, 37, 38, 39, 40, 41, 42, 43,
238 44, 45, 46, 47, 48, 48, 49, 49,
239 50, 51, 52, 53, 54, 55, 56, 57,
240 58, 59, 60, 61, 62, 63, 64, 64,
241 65, 66, 67, 68, 69, 70, 71, 72,
242 /* corrected:
243 73, 74, 75, 76, 77, 78, 79, 79,
244 should be: */
245 73, 74, 75, 76, 77, 78, 79, 80,
246
247 80, 81, 82, 83, 84, 85, 86, 87,
248 88, 89, 90, 91, 92, 93, 94, 95,
249 96, 97, 98, 99, 100, 101, 102, 103,
250 104, 105, 106, 107, 108, 109, 110, 111,
251 112, 113, 114, 115, 116, 117, 118, 119,
252 120, 121, 122, 123, 124, 125, 126, 127};
253
254 static short
255 search(
256 int val, /* changed from "short" *drago* */
257 const short *table,
258 int size) /* changed from "short" *drago* */
259 {
260 int i; /* changed from "short" *drago* */
261
262 for (i = 0; i < size; i++) {
263 if (val <= *table++)
264 return (i);
265 }
266 return (size);
267 }
268
269 /*
270 * linear2alaw() - Convert a 16-bit linear PCM value to 8-bit A-law
271 *
272 * linear2alaw() accepts an 16-bit integer and encodes it as A-law data.
273 *
274 * Linear Input Code Compressed Code
275 * ------------------------ ---------------
276 * 0000000wxyza 000wxyz
277 * 0000001wxyza 001wxyz
278 * 000001wxyzab 010wxyz
279 * 00001wxyzabc 011wxyz
280 * 0001wxyzabcd 100wxyz
281 * 001wxyzabcde 101wxyz
282 * 01wxyzabcdef 110wxyz
283 * 1wxyzabcdefg 111wxyz
284 *
285 * For further information see John C. Bellamy's Digital Telephony, 1982,
286 * John Wiley & Sons, pps 98-111 and 472-476.
287 */
288 static inline unsigned char
289 linear2alaw(int pcm_val) /* 2's complement (16-bit range) */
290 /* changed from "short" *drago* */
291 {
292 int mask; /* changed from "short" *drago* */
293 int seg; /* changed from "short" *drago* */
294 unsigned char aval;
295
296 pcm_val = pcm_val >> 3;
297
298 if (pcm_val >= 0) {
299 mask = 0xD5; /* sign (7th) bit = 1 */
300 } else {
301 mask = 0x55; /* sign bit = 0 */
302 pcm_val = -pcm_val - 1;
303 }
304
305 /* Convert the scaled magnitude to segment number. */
306 seg = search(pcm_val, seg_aend, 8);
307
308 /* Combine the sign, segment, and quantization bits. */
309
310 if (seg >= 8) /* out of range, return maximum value. */
311 return (unsigned char) (0x7F ^ mask);
312 else {
313 aval = (unsigned char) seg << SEG_SHIFT;
314 if (seg < 2)
315 aval |= (pcm_val >> 1) & QUANT_MASK;
316 else
317 aval |= (pcm_val >> seg) & QUANT_MASK;
318 return (aval ^ mask);
319 }
320 }
321
322 #ifdef NO_FASTDECODE
323 /*
324 * alaw2linear() - Convert an A-law value to 16-bit linear PCM
325 *
326 */
327 static inline int
328 alaw2linear(unsigned char a_val)
329 {
330 int t; /* changed from "short" *drago* */
331 int seg; /* changed from "short" *drago* */
332
333 a_val ^= 0x55;
334
335 t = (a_val & QUANT_MASK) << 4;
336 seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT;
337 switch (seg) {
338 case 0:
339 t += 8;
340 break;
341 case 1:
342 t += 0x108;
343 break;
344 default:
345 t += 0x108;
346 t <<= seg - 1;
347 }
348 return ((a_val & SIGN_BIT) ? t : -t);
349 }
350 #else
351 /* EPP (for Wine):
352 * this array has been statically generated from the above routine
353 */
354 static const unsigned short _a2l[] = {
355 0xEA80, 0xEB80, 0xE880, 0xE980, 0xEE80, 0xEF80, 0xEC80, 0xED80,
356 0xE280, 0xE380, 0xE080, 0xE180, 0xE680, 0xE780, 0xE480, 0xE580,
357 0xF540, 0xF5C0, 0xF440, 0xF4C0, 0xF740, 0xF7C0, 0xF640, 0xF6C0,
358 0xF140, 0xF1C0, 0xF040, 0xF0C0, 0xF340, 0xF3C0, 0xF240, 0xF2C0,
359 0xAA00, 0xAE00, 0xA200, 0xA600, 0xBA00, 0xBE00, 0xB200, 0xB600,
360 0x8A00, 0x8E00, 0x8200, 0x8600, 0x9A00, 0x9E00, 0x9200, 0x9600,
361 0xD500, 0xD700, 0xD100, 0xD300, 0xDD00, 0xDF00, 0xD900, 0xDB00,
362 0xC500, 0xC700, 0xC100, 0xC300, 0xCD00, 0xCF00, 0xC900, 0xCB00,
363 0xFEA8, 0xFEB8, 0xFE88, 0xFE98, 0xFEE8, 0xFEF8, 0xFEC8, 0xFED8,
364 0xFE28, 0xFE38, 0xFE08, 0xFE18, 0xFE68, 0xFE78, 0xFE48, 0xFE58,
365 0xFFA8, 0xFFB8, 0xFF88, 0xFF98, 0xFFE8, 0xFFF8, 0xFFC8, 0xFFD8,
366 0xFF28, 0xFF38, 0xFF08, 0xFF18, 0xFF68, 0xFF78, 0xFF48, 0xFF58,
367 0xFAA0, 0xFAE0, 0xFA20, 0xFA60, 0xFBA0, 0xFBE0, 0xFB20, 0xFB60,
368 0xF8A0, 0xF8E0, 0xF820, 0xF860, 0xF9A0, 0xF9E0, 0xF920, 0xF960,
369 0xFD50, 0xFD70, 0xFD10, 0xFD30, 0xFDD0, 0xFDF0, 0xFD90, 0xFDB0,
370 0xFC50, 0xFC70, 0xFC10, 0xFC30, 0xFCD0, 0xFCF0, 0xFC90, 0xFCB0,
371 0x1580, 0x1480, 0x1780, 0x1680, 0x1180, 0x1080, 0x1380, 0x1280,
372 0x1D80, 0x1C80, 0x1F80, 0x1E80, 0x1980, 0x1880, 0x1B80, 0x1A80,
373 0x0AC0, 0x0A40, 0x0BC0, 0x0B40, 0x08C0, 0x0840, 0x09C0, 0x0940,
374 0x0EC0, 0x0E40, 0x0FC0, 0x0F40, 0x0CC0, 0x0C40, 0x0DC0, 0x0D40,
375 0x5600, 0x5200, 0x5E00, 0x5A00, 0x4600, 0x4200, 0x4E00, 0x4A00,
376 0x7600, 0x7200, 0x7E00, 0x7A00, 0x6600, 0x6200, 0x6E00, 0x6A00,
377 0x2B00, 0x2900, 0x2F00, 0x2D00, 0x2300, 0x2100, 0x2700, 0x2500,
378 0x3B00, 0x3900, 0x3F00, 0x3D00, 0x3300, 0x3100, 0x3700, 0x3500,
379 0x0158, 0x0148, 0x0178, 0x0168, 0x0118, 0x0108, 0x0138, 0x0128,
380 0x01D8, 0x01C8, 0x01F8, 0x01E8, 0x0198, 0x0188, 0x01B8, 0x01A8,
381 0x0058, 0x0048, 0x0078, 0x0068, 0x0018, 0x0008, 0x0038, 0x0028,
382 0x00D8, 0x00C8, 0x00F8, 0x00E8, 0x0098, 0x0088, 0x00B8, 0x00A8,
383 0x0560, 0x0520, 0x05E0, 0x05A0, 0x0460, 0x0420, 0x04E0, 0x04A0,
384 0x0760, 0x0720, 0x07E0, 0x07A0, 0x0660, 0x0620, 0x06E0, 0x06A0,
385 0x02B0, 0x0290, 0x02F0, 0x02D0, 0x0230, 0x0210, 0x0270, 0x0250,
386 0x03B0, 0x0390, 0x03F0, 0x03D0, 0x0330, 0x0310, 0x0370, 0x0350,
387 };
388 static inline int
389 alaw2linear(unsigned char a_val)
390 {
391 return (short)_a2l[a_val];
392 }
393 #endif
394
395 #define BIAS (0x84) /* Bias for linear code. */
396 #define CLIP 8159
397
398 /*
399 * linear2ulaw() - Convert a linear PCM value to u-law
400 *
401 * In order to simplify the encoding process, the original linear magnitude
402 * is biased by adding 33 which shifts the encoding range from (0 - 8158) to
403 * (33 - 8191). The result can be seen in the following encoding table:
404 *
405 * Biased Linear Input Code Compressed Code
406 * ------------------------ ---------------
407 * 00000001wxyza 000wxyz
408 * 0000001wxyzab 001wxyz
409 * 000001wxyzabc 010wxyz
410 * 00001wxyzabcd 011wxyz
411 * 0001wxyzabcde 100wxyz
412 * 001wxyzabcdef 101wxyz
413 * 01wxyzabcdefg 110wxyz
414 * 1wxyzabcdefgh 111wxyz
415 *
416 * Each biased linear code has a leading 1 which identifies the segment
417 * number. The value of the segment number is equal to 7 minus the number
418 * of leading 0's. The quantization interval is directly available as the
419 * four bits wxyz. * The trailing bits (a - h) are ignored.
420 *
421 * Ordinarily the complement of the resulting code word is used for
422 * transmission, and so the code word is complemented before it is returned.
423 *
424 * For further information see John C. Bellamy's Digital Telephony, 1982,
425 * John Wiley & Sons, pps 98-111 and 472-476.
426 */
427 static inline unsigned char
428 linear2ulaw(short pcm_val) /* 2's complement (16-bit range) */
429 {
430 short mask;
431 short seg;
432 unsigned char uval;
433
434 /* Get the sign and the magnitude of the value. */
435 pcm_val = pcm_val >> 2;
436 if (pcm_val < 0) {
437 pcm_val = -pcm_val;
438 mask = 0x7F;
439 } else {
440 mask = 0xFF;
441 }
442 if ( pcm_val > CLIP ) pcm_val = CLIP; /* clip the magnitude */
443 pcm_val += (BIAS >> 2);
444
445 /* Convert the scaled magnitude to segment number. */
446 seg = search(pcm_val, seg_uend, 8);
447
448 /*
449 * Combine the sign, segment, quantization bits;
450 * and complement the code word.
451 */
452 if (seg >= 8) /* out of range, return maximum value. */
453 return (unsigned char) (0x7F ^ mask);
454 else {
455 uval = (unsigned char) (seg << 4) | ((pcm_val >> (seg + 1)) & 0xF);
456 return (uval ^ mask);
457 }
458 }
459
460 #ifdef NO_FASTDECODE
461 /*
462 * ulaw2linear() - Convert a u-law value to 16-bit linear PCM
463 *
464 * First, a biased linear code is derived from the code word. An unbiased
465 * output can then be obtained by subtracting 33 from the biased code.
466 *
467 * Note that this function expects to be passed the complement of the
468 * original code word. This is in keeping with ISDN conventions.
469 */
470 static inline short
471 ulaw2linear(unsigned char u_val)
472 {
473 short t;
474
475 /* Complement to obtain normal u-law value. */
476 u_val = ~u_val;
477
478 /*
479 * Extract and bias the quantization bits. Then
480 * shift up by the segment number and subtract out the bias.
481 */
482 t = ((u_val & QUANT_MASK) << 3) + BIAS;
483 t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT;
484
485 return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS));
486 }
487 #else
488 /* EPP (for Wine):
489 * this array has been statically generated from the above routine
490 */
491 static const unsigned short _u2l[] = {
492 0x8284, 0x8684, 0x8A84, 0x8E84, 0x9284, 0x9684, 0x9A84, 0x9E84,
493 0xA284, 0xA684, 0xAA84, 0xAE84, 0xB284, 0xB684, 0xBA84, 0xBE84,
494 0xC184, 0xC384, 0xC584, 0xC784, 0xC984, 0xCB84, 0xCD84, 0xCF84,
495 0xD184, 0xD384, 0xD584, 0xD784, 0xD984, 0xDB84, 0xDD84, 0xDF84,
496 0xE104, 0xE204, 0xE304, 0xE404, 0xE504, 0xE604, 0xE704, 0xE804,
497 0xE904, 0xEA04, 0xEB04, 0xEC04, 0xED04, 0xEE04, 0xEF04, 0xF004,
498 0xF0C4, 0xF144, 0xF1C4, 0xF244, 0xF2C4, 0xF344, 0xF3C4, 0xF444,
499 0xF4C4, 0xF544, 0xF5C4, 0xF644, 0xF6C4, 0xF744, 0xF7C4, 0xF844,
500 0xF8A4, 0xF8E4, 0xF924, 0xF964, 0xF9A4, 0xF9E4, 0xFA24, 0xFA64,
501 0xFAA4, 0xFAE4, 0xFB24, 0xFB64, 0xFBA4, 0xFBE4, 0xFC24, 0xFC64,
502 0xFC94, 0xFCB4, 0xFCD4, 0xFCF4, 0xFD14, 0xFD34, 0xFD54, 0xFD74,
503 0xFD94, 0xFDB4, 0xFDD4, 0xFDF4, 0xFE14, 0xFE34, 0xFE54, 0xFE74,
504 0xFE8C, 0xFE9C, 0xFEAC, 0xFEBC, 0xFECC, 0xFEDC, 0xFEEC, 0xFEFC,
505 0xFF0C, 0xFF1C, 0xFF2C, 0xFF3C, 0xFF4C, 0xFF5C, 0xFF6C, 0xFF7C,
506 0xFF88, 0xFF90, 0xFF98, 0xFFA0, 0xFFA8, 0xFFB0, 0xFFB8, 0xFFC0,
507 0xFFC8, 0xFFD0, 0xFFD8, 0xFFE0, 0xFFE8, 0xFFF0, 0xFFF8, 0x0000,
508 0x7D7C, 0x797C, 0x757C, 0x717C, 0x6D7C, 0x697C, 0x657C, 0x617C,
509 0x5D7C, 0x597C, 0x557C, 0x517C, 0x4D7C, 0x497C, 0x457C, 0x417C,
510 0x3E7C, 0x3C7C, 0x3A7C, 0x387C, 0x367C, 0x347C, 0x327C, 0x307C,
511 0x2E7C, 0x2C7C, 0x2A7C, 0x287C, 0x267C, 0x247C, 0x227C, 0x207C,
512 0x1EFC, 0x1DFC, 0x1CFC, 0x1BFC, 0x1AFC, 0x19FC, 0x18FC, 0x17FC,
513 0x16FC, 0x15FC, 0x14FC, 0x13FC, 0x12FC, 0x11FC, 0x10FC, 0x0FFC,
514 0x0F3C, 0x0EBC, 0x0E3C, 0x0DBC, 0x0D3C, 0x0CBC, 0x0C3C, 0x0BBC,
515 0x0B3C, 0x0ABC, 0x0A3C, 0x09BC, 0x093C, 0x08BC, 0x083C, 0x07BC,
516 0x075C, 0x071C, 0x06DC, 0x069C, 0x065C, 0x061C, 0x05DC, 0x059C,
517 0x055C, 0x051C, 0x04DC, 0x049C, 0x045C, 0x041C, 0x03DC, 0x039C,
518 0x036C, 0x034C, 0x032C, 0x030C, 0x02EC, 0x02CC, 0x02AC, 0x028C,
519 0x026C, 0x024C, 0x022C, 0x020C, 0x01EC, 0x01CC, 0x01AC, 0x018C,
520 0x0174, 0x0164, 0x0154, 0x0144, 0x0134, 0x0124, 0x0114, 0x0104,
521 0x00F4, 0x00E4, 0x00D4, 0x00C4, 0x00B4, 0x00A4, 0x0094, 0x0084,
522 0x0078, 0x0070, 0x0068, 0x0060, 0x0058, 0x0050, 0x0048, 0x0040,
523 0x0038, 0x0030, 0x0028, 0x0020, 0x0018, 0x0010, 0x0008, 0x0000,
524 };
525 static inline short ulaw2linear(unsigned char u_val)
526 {
527 return (short)_u2l[u_val];
528 }
529 #endif
530
531 /* A-law to u-law conversion */
532 static inline unsigned char
533 alaw2ulaw(unsigned char aval)
534 {
535 aval &= 0xff;
536 return (unsigned char) ((aval & 0x80) ? (0xFF ^ _a2u[aval ^ 0xD5]) :
537 (0x7F ^ _a2u[aval ^ 0x55]));
538 }
539
540 /* u-law to A-law conversion */
541 static inline unsigned char
542 ulaw2alaw(unsigned char uval)
543 {
544 uval &= 0xff;
545 return (uval & 0x80) ? (0xD5 ^ (_u2a[0xFF ^ uval] - 1)) : (0x55 ^ (_u2a[0x7F ^ uval] - 1));
546 }
547
548 /* -------------------------------------------------------------------------------*/
549
550 static void cvtXXalaw16K(PACMDRVSTREAMINSTANCE adsi,
551 const unsigned char* src, LPDWORD srcsize,
552 unsigned char* dst, LPDWORD dstsize)
553 {
554 DWORD len = min(*srcsize, *dstsize / 2);
555 DWORD i;
556 short w;
557
558 *srcsize = len;
559 *dstsize = len * 2;
560 for (i = 0; i < len; i++)
561 {
562 w = alaw2linear(*src++);
563 W16(dst, w); dst += 2;
564 }
565 }
566
567 static void cvtXX16alawK(PACMDRVSTREAMINSTANCE adsi,
568 const unsigned char* src, LPDWORD srcsize,
569 unsigned char* dst, LPDWORD dstsize)
570 {
571 DWORD len = min(*srcsize / 2, *dstsize);
572 DWORD i;
573
574 *srcsize = len * 2;
575 *dstsize = len;
576 for (i = 0; i < len; i++)
577 {
578 *dst++ = linear2alaw(R16(src)); src += 2;
579 }
580 }
581
582 static void cvtXXulaw16K(PACMDRVSTREAMINSTANCE adsi,
583 const unsigned char* src, LPDWORD srcsize,
584 unsigned char* dst, LPDWORD dstsize)
585 {
586 DWORD len = min(*srcsize, *dstsize / 2);
587 DWORD i;
588 short w;
589
590 *srcsize = len;
591 *dstsize = len * 2;
592 for (i = 0; i < len; i++)
593 {
594 w = ulaw2linear(*src++);
595 W16(dst, w); dst += 2;
596 }
597 }
598
599 static void cvtXX16ulawK(PACMDRVSTREAMINSTANCE adsi,
600 const unsigned char* src, LPDWORD srcsize,
601 unsigned char* dst, LPDWORD dstsize)
602 {
603 DWORD len = min(*srcsize / 2, *dstsize);
604 DWORD i;
605
606 *srcsize = len * 2;
607 *dstsize = len;
608 for (i = 0; i < len; i++)
609 {
610 *dst++ = linear2ulaw(R16(src)); src += 2;
611 }
612 }
613
614 static void cvtXXalawulawK(PACMDRVSTREAMINSTANCE adsi,
615 const unsigned char* src, LPDWORD srcsize,
616 unsigned char* dst, LPDWORD dstsize)
617 {
618 DWORD len = min(*srcsize, *dstsize);
619 DWORD i;
620
621 *srcsize = len;
622 *dstsize = len;
623
624 for (i = 0; i < len; i++)
625 *dst++ = alaw2ulaw(*src++);
626 }
627
628
629 static void cvtXXulawalawK(PACMDRVSTREAMINSTANCE adsi,
630 const unsigned char* src, LPDWORD srcsize,
631 unsigned char* dst, LPDWORD dstsize)
632 {
633 DWORD len = min(*srcsize, *dstsize);
634 DWORD i;
635
636 *srcsize = len;
637 *dstsize = len;
638
639 for (i = 0; i < len; i++)
640 *dst++ = ulaw2alaw(*src++);
641 }
642
643 /***********************************************************************
644 * G711_DriverDetails
645 *
646 */
647 static LRESULT G711_DriverDetails(PACMDRIVERDETAILSW add)
648 {
649 add->fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC;
650 add->fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED;
651 add->wMid = MM_MICROSOFT;
652 add->wPid = MM_MSFT_ACM_G711;
653 add->vdwACM = 0x01000000;
654 add->vdwDriver = 0x01000000;
655 add->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
656 add->cFormatTags = 3; /* PCM, G711 A-LAW & MU-LAW */
657 add->cFilterTags = 0;
658 add->hicon = NULL;
659 MultiByteToWideChar( CP_ACP, 0, "Microsoft CCITT G.711", -1,
660 add->szShortName, ARRAY_SIZE( add->szShortName ));
661 MultiByteToWideChar( CP_ACP, 0, "Wine G711 converter", -1,
662 add->szLongName, ARRAY_SIZE( add->szLongName ));
663 MultiByteToWideChar( CP_ACP, 0, "Brought to you by the Wine team...", -1,
664 add->szCopyright, ARRAY_SIZE( add->szCopyright ));
665 MultiByteToWideChar( CP_ACP, 0, "Refer to LICENSE file", -1,
666 add->szLicensing, ARRAY_SIZE( add->szLicensing ));
667 add->szFeatures[0] = 0;
668
669 return MMSYSERR_NOERROR;
670 }
671
672 /***********************************************************************
673 * G711_FormatTagDetails
674 *
675 */
676 static LRESULT G711_FormatTagDetails(PACMFORMATTAGDETAILSW aftd, DWORD dwQuery)
677 {
678 static const WCHAR szPcm[]={'P','C','M',0};
679 static const WCHAR szALaw[]={'A','-','L','a','w',0};
680 static const WCHAR szULaw[]={'U','-','L','a','w',0};
681
682 switch (dwQuery)
683 {
684 case ACM_FORMATTAGDETAILSF_INDEX:
685 if (aftd->dwFormatTagIndex >= 3) return ACMERR_NOTPOSSIBLE;
686 break;
687 case ACM_FORMATTAGDETAILSF_LARGESTSIZE:
688 if (aftd->dwFormatTag == WAVE_FORMAT_UNKNOWN)
689 {
690 aftd->dwFormatTagIndex = 1;
691 break;
692 }
693 /* fall through */
694 case ACM_FORMATTAGDETAILSF_FORMATTAG:
695 switch (aftd->dwFormatTag)
696 {
697 case WAVE_FORMAT_PCM: aftd->dwFormatTagIndex = 0; break;
698 case WAVE_FORMAT_ALAW: aftd->dwFormatTagIndex = 1; break;
699 case WAVE_FORMAT_MULAW: aftd->dwFormatTagIndex = 2; break;
700 default: return ACMERR_NOTPOSSIBLE;
701 }
702 break;
703 default:
704 WARN("Unsupported query %08x\n", dwQuery);
705 return MMSYSERR_NOTSUPPORTED;
706 }
707
708 aftd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
709 switch (aftd->dwFormatTagIndex)
710 {
711 case 0:
712 aftd->dwFormatTag = WAVE_FORMAT_PCM;
713 aftd->cbFormatSize = sizeof(PCMWAVEFORMAT);
714 aftd->cStandardFormats = ARRAY_SIZE(PCM_Formats);
715 lstrcpyW(aftd->szFormatTag, szPcm);
716 break;
717 case 1:
718 aftd->dwFormatTag = WAVE_FORMAT_ALAW;
719 aftd->cbFormatSize = sizeof(WAVEFORMATEX);
720 aftd->cStandardFormats = ARRAY_SIZE(ALaw_Formats);
721 lstrcpyW(aftd->szFormatTag, szALaw);
722 break;
723 case 2:
724 aftd->dwFormatTag = WAVE_FORMAT_MULAW;
725 aftd->cbFormatSize = sizeof(WAVEFORMATEX);
726 aftd->cStandardFormats = ARRAY_SIZE(ULaw_Formats);
727 lstrcpyW(aftd->szFormatTag, szULaw);
728 break;
729 }
730 return MMSYSERR_NOERROR;
731 }
732
733 /***********************************************************************
734 * G711_FormatDetails
735 *
736 */
737 static LRESULT G711_FormatDetails(PACMFORMATDETAILSW afd, DWORD dwQuery)
738 {
739 switch (dwQuery)
740 {
741 case ACM_FORMATDETAILSF_FORMAT:
742 if (G711_GetFormatIndex(afd->pwfx) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
743 break;
744 case ACM_FORMATDETAILSF_INDEX:
745 afd->pwfx->wFormatTag = afd->dwFormatTag;
746 switch (afd->dwFormatTag)
747 {
748 case WAVE_FORMAT_PCM:
749 if (afd->dwFormatIndex >= ARRAY_SIZE(PCM_Formats)) return ACMERR_NOTPOSSIBLE;
750 afd->pwfx->nChannels = PCM_Formats[afd->dwFormatIndex].nChannels;
751 afd->pwfx->nSamplesPerSec = PCM_Formats[afd->dwFormatIndex].rate;
752 afd->pwfx->wBitsPerSample = PCM_Formats[afd->dwFormatIndex].nBits;
753 afd->pwfx->nBlockAlign = afd->pwfx->nChannels * 2;
754 afd->pwfx->nAvgBytesPerSec = afd->pwfx->nSamplesPerSec * afd->pwfx->nBlockAlign;
755 break;
756 case WAVE_FORMAT_ALAW:
757 if (afd->dwFormatIndex >= ARRAY_SIZE(ALaw_Formats)) return ACMERR_NOTPOSSIBLE;
758 afd->pwfx->nChannels = ALaw_Formats[afd->dwFormatIndex].nChannels;
759 afd->pwfx->nSamplesPerSec = ALaw_Formats[afd->dwFormatIndex].rate;
760 afd->pwfx->wBitsPerSample = ALaw_Formats[afd->dwFormatIndex].nBits;
761 afd->pwfx->nBlockAlign = ALaw_Formats[afd->dwFormatIndex].nChannels;
762 afd->pwfx->nAvgBytesPerSec = afd->pwfx->nSamplesPerSec * afd->pwfx->nChannels;
763 afd->pwfx->cbSize = 0;
764 break;
765 case WAVE_FORMAT_MULAW:
766 if (afd->dwFormatIndex >= ARRAY_SIZE(ULaw_Formats)) return ACMERR_NOTPOSSIBLE;
767 afd->pwfx->nChannels = ULaw_Formats[afd->dwFormatIndex].nChannels;
768 afd->pwfx->nSamplesPerSec = ULaw_Formats[afd->dwFormatIndex].rate;
769 afd->pwfx->wBitsPerSample = ULaw_Formats[afd->dwFormatIndex].nBits;
770 afd->pwfx->nBlockAlign = ULaw_Formats[afd->dwFormatIndex].nChannels;
771 afd->pwfx->nAvgBytesPerSec = afd->pwfx->nSamplesPerSec * afd->pwfx->nChannels;
772 afd->pwfx->cbSize = 0;
773 break;
774 default:
775 WARN("Unsupported tag %08x\n", afd->dwFormatTag);
776 return MMSYSERR_INVALPARAM;
777 }
778 break;
779 default:
780 WARN("Unsupported query %08x\n", dwQuery);
781 return MMSYSERR_NOTSUPPORTED;
782 }
783 afd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
784 afd->szFormat[0] = 0; /* let MSACM format this for us... */
785
786 return MMSYSERR_NOERROR;
787 }
788
789 /***********************************************************************
790 * G711_FormatSuggest
791 *
792 */
793 static LRESULT G711_FormatSuggest(PACMDRVFORMATSUGGEST adfs)
794 {
795 /* some tests ... */
796 if (adfs->cbwfxSrc < sizeof(PCMWAVEFORMAT) ||
797 adfs->cbwfxDst < sizeof(PCMWAVEFORMAT) ||
798 G711_GetFormatIndex(adfs->pwfxSrc) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
799 /* FIXME: should do those tests against the real size (according to format tag */
800
801 /* If no suggestion for destination, then copy source value */
802 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NCHANNELS))
803 adfs->pwfxDst->nChannels = adfs->pwfxSrc->nChannels;
804 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NSAMPLESPERSEC))
805 adfs->pwfxDst->nSamplesPerSec = adfs->pwfxSrc->nSamplesPerSec;
806
807 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WBITSPERSAMPLE))
808 {
809 if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM)
810 adfs->pwfxDst->wBitsPerSample = 8;
811 else
812 adfs->pwfxDst->wBitsPerSample = 16;
813 }
814 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG))
815 {
816 switch (adfs->pwfxSrc->wFormatTag)
817 {
818 case WAVE_FORMAT_PCM: adfs->pwfxDst->wFormatTag = WAVE_FORMAT_ALAW; break;
819 case WAVE_FORMAT_ALAW: adfs->pwfxDst->wFormatTag = WAVE_FORMAT_PCM; break;
820 case WAVE_FORMAT_MULAW: adfs->pwfxDst->wFormatTag = WAVE_FORMAT_PCM; break;
821 }
822 }
823 /* check if result is ok */
824 if (G711_GetFormatIndex(adfs->pwfxDst) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
825
826 /* recompute other values */
827 switch (adfs->pwfxDst->wFormatTag)
828 {
829 case WAVE_FORMAT_PCM:
830 adfs->pwfxDst->nBlockAlign = adfs->pwfxDst->nChannels * 2;
831 adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * adfs->pwfxDst->nBlockAlign;
832 break;
833 case WAVE_FORMAT_ALAW:
834 adfs->pwfxDst->nBlockAlign = adfs->pwfxDst->nChannels;
835 adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * adfs->pwfxSrc->nChannels;
836 break;
837 case WAVE_FORMAT_MULAW:
838 adfs->pwfxDst->nBlockAlign = adfs->pwfxDst->nChannels;
839 adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * adfs->pwfxSrc->nChannels;
840 break;
841 }
842
843 return MMSYSERR_NOERROR;
844 }
845
846 /***********************************************************************
847 * G711_Reset
848 *
849 */
850 static void G711_Reset(PACMDRVSTREAMINSTANCE adsi, AcmG711Data* aad)
851 {
852 }
853
854 /***********************************************************************
855 * G711_StreamOpen
856 *
857 */
858 static LRESULT G711_StreamOpen(PACMDRVSTREAMINSTANCE adsi)
859 {
860 AcmG711Data* aad;
861
862 assert(!(adsi->fdwOpen & ACM_STREAMOPENF_ASYNC));
863
864 if (G711_GetFormatIndex(adsi->pwfxSrc) == 0xFFFFFFFF ||
865 G711_GetFormatIndex(adsi->pwfxDst) == 0xFFFFFFFF)
866 return ACMERR_NOTPOSSIBLE;
867
868 aad = HeapAlloc(GetProcessHeap(), 0, sizeof(AcmG711Data));
869 if (aad == 0) return MMSYSERR_NOMEM;
870
871 adsi->dwDriver = (DWORD_PTR)aad;
872
873 if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
874 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
875 {
876 goto theEnd;
877 }
878 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ALAW &&
879 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
880 {
881 /* resampling or mono <=> stereo not available
882 * G711 algo only define 16 bit per sample output
883 */
884 if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
885 adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
886 adsi->pwfxDst->wBitsPerSample != 16)
887 goto theEnd;
888
889 /* g711 A-Law decoding... */
890 if (adsi->pwfxDst->wBitsPerSample == 16)
891 aad->convert = cvtXXalaw16K;
892 }
893 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
894 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ALAW)
895 {
896 if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
897 adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
898 adsi->pwfxSrc->wBitsPerSample != 16)
899 goto theEnd;
900
901 /* g711 coding... */
902 if (adsi->pwfxSrc->wBitsPerSample == 16)
903 aad->convert = cvtXX16alawK;
904 }
905 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MULAW &&
906 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
907 {
908 /* resampling or mono <=> stereo not available
909 * G711 algo only define 16 bit per sample output
910 */
911 if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
912 adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
913 adsi->pwfxDst->wBitsPerSample != 16)
914 goto theEnd;
915
916 /* g711 MU-Law decoding... */
917 if (adsi->pwfxDst->wBitsPerSample == 16)
918 aad->convert = cvtXXulaw16K;
919 }
920 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
921 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MULAW)
922 {
923 if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
924 adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
925 adsi->pwfxSrc->wBitsPerSample != 16)
926 goto theEnd;
927
928 /* g711 coding... */
929 if (adsi->pwfxSrc->wBitsPerSample == 16)
930 aad->convert = cvtXX16ulawK;
931 }
932 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MULAW &&
933 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ALAW)
934 {
935 if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
936 adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels)
937 goto theEnd;
938
939 /* MU-Law => A-Law... */
940 aad->convert = cvtXXulawalawK;
941 }
942 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ALAW &&
943 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MULAW)
944 {
945 if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
946 adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels)
947 goto theEnd;
948
949 /* A-Law => MU-Law... */
950 aad->convert = cvtXXalawulawK;
951 }
952 else goto theEnd;
953
954 G711_Reset(adsi, aad);
955
956 return MMSYSERR_NOERROR;
957
958 theEnd:
959 HeapFree(GetProcessHeap(), 0, aad);
960 adsi->dwDriver = 0L;
961 return MMSYSERR_NOTSUPPORTED;
962 }
963
964 /***********************************************************************
965 * G711_StreamClose
966 *
967 */
968 static LRESULT G711_StreamClose(PACMDRVSTREAMINSTANCE adsi)
969 {
970 HeapFree(GetProcessHeap(), 0, (void*)adsi->dwDriver);
971 return MMSYSERR_NOERROR;
972 }
973
974 /***********************************************************************
975 * G711_StreamSize
976 *
977 */
978 static LRESULT G711_StreamSize(const ACMDRVSTREAMINSTANCE *adsi, PACMDRVSTREAMSIZE adss)
979 {
980 switch (adss->fdwSize)
981 {
982 case ACM_STREAMSIZEF_DESTINATION:
983 /* cbDstLength => cbSrcLength */
984 if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
985 (adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ALAW ||
986 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MULAW))
987 {
988 adss->cbSrcLength = adss->cbDstLength * 2;
989 }
990 else if ((adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ALAW ||
991 adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MULAW) &&
992 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
993 {
994 adss->cbSrcLength = adss->cbDstLength / 2;
995 }
996 else if ((adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ALAW ||
997 adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MULAW) &&
998 (adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ALAW ||
999 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MULAW))
1000 {
1001 adss->cbSrcLength = adss->cbDstLength;
1002 }
1003 else
1004 {
1005 return MMSYSERR_NOTSUPPORTED;
1006 }
1007 break;
1008 case ACM_STREAMSIZEF_SOURCE:
1009 /* cbSrcLength => cbDstLength */
1010 if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
1011 (adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ALAW ||
1012 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MULAW))
1013 {
1014 adss->cbDstLength = adss->cbSrcLength / 2;
1015 }
1016 else if ((adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ALAW ||
1017 adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MULAW) &&
1018 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
1019 {
1020 adss->cbDstLength = adss->cbSrcLength * 2;
1021 }
1022 else if ((adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ALAW ||
1023 adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MULAW) &&
1024 (adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ALAW ||
1025 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MULAW))
1026 {
1027 adss->cbDstLength = adss->cbSrcLength;
1028 }
1029 else
1030 {
1031 return MMSYSERR_NOTSUPPORTED;
1032 }
1033 break;
1034 default:
1035 WARN("Unsupported query %08x\n", adss->fdwSize);
1036 return MMSYSERR_NOTSUPPORTED;
1037 }
1038 return MMSYSERR_NOERROR;
1039 }
1040
1041 /***********************************************************************
1042 * G711_StreamConvert
1043 *
1044 */
1045 static LRESULT G711_StreamConvert(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMHEADER adsh)
1046 {
1047 AcmG711Data* aad = (AcmG711Data*)adsi->dwDriver;
1048 DWORD nsrc = adsh->cbSrcLength;
1049 DWORD ndst = adsh->cbDstLength;
1050
1051 if (adsh->fdwConvert &
1052 ~(ACM_STREAMCONVERTF_BLOCKALIGN|
1053 ACM_STREAMCONVERTF_END|
1054 ACM_STREAMCONVERTF_START))
1055 {
1056 FIXME("Unsupported fdwConvert (%08x), ignoring it\n", adsh->fdwConvert);
1057 }
1058 /* ACM_STREAMCONVERTF_BLOCKALIGN
1059 * currently all conversions are block aligned, so do nothing for this flag
1060 * ACM_STREAMCONVERTF_END
1061 * no pending data, so do nothing for this flag
1062 */
1063 if ((adsh->fdwConvert & ACM_STREAMCONVERTF_START))
1064 {
1065 G711_Reset(adsi, aad);
1066 }
1067
1068 aad->convert(adsi, adsh->pbSrc, &nsrc, adsh->pbDst, &ndst);
1069 adsh->cbSrcLengthUsed = nsrc;
1070 adsh->cbDstLengthUsed = ndst;
1071
1072 return MMSYSERR_NOERROR;
1073 }
1074
1075 /**************************************************************************
1076 * G711_DriverProc [exported]
1077 */
1078 LRESULT CALLBACK G711_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg,
1079 LPARAM dwParam1, LPARAM dwParam2)
1080 {
1081 TRACE("(%08lx %p %04x %08lx %08lx);\n",
1082 dwDevID, hDriv, wMsg, dwParam1, dwParam2);
1083
1084 switch (wMsg)
1085 {
1086 case DRV_LOAD: return 1;
1087 case DRV_FREE: return 1;
1088 case DRV_OPEN: return G711_drvOpen((LPSTR)dwParam1);
1089 case DRV_CLOSE: return G711_drvClose(dwDevID);
1090 case DRV_ENABLE: return 1;
1091 case DRV_DISABLE: return 1;
1092 case DRV_QUERYCONFIGURE: return 1;
1093 case DRV_CONFIGURE: MessageBoxA(0, "MS G711 (a-Law & mu-Law) filter !", "Wine Driver", MB_OK); return 1;
1094 case DRV_INSTALL: return DRVCNF_RESTART;
1095 case DRV_REMOVE: return DRVCNF_RESTART;
1096
1097 case ACMDM_DRIVER_NOTIFY:
1098 /* no caching from other ACM drivers is done so far */
1099 return MMSYSERR_NOERROR;
1100
1101 case ACMDM_DRIVER_DETAILS:
1102 return G711_DriverDetails((PACMDRIVERDETAILSW)dwParam1);
1103
1104 case ACMDM_FORMATTAG_DETAILS:
1105 return G711_FormatTagDetails((PACMFORMATTAGDETAILSW)dwParam1, dwParam2);
1106
1107 case ACMDM_FORMAT_DETAILS:
1108 return G711_FormatDetails((PACMFORMATDETAILSW)dwParam1, dwParam2);
1109
1110 case ACMDM_FORMAT_SUGGEST:
1111 return G711_FormatSuggest((PACMDRVFORMATSUGGEST)dwParam1);
1112
1113 case ACMDM_STREAM_OPEN:
1114 return G711_StreamOpen((PACMDRVSTREAMINSTANCE)dwParam1);
1115
1116 case ACMDM_STREAM_CLOSE:
1117 return G711_StreamClose((PACMDRVSTREAMINSTANCE)dwParam1);
1118
1119 case ACMDM_STREAM_SIZE:
1120 return G711_StreamSize((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMSIZE)dwParam2);
1121
1122 case ACMDM_STREAM_CONVERT:
1123 return G711_StreamConvert((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMHEADER)dwParam2);
1124
1125 case ACMDM_HARDWARE_WAVE_CAPS_INPUT:
1126 case ACMDM_HARDWARE_WAVE_CAPS_OUTPUT:
1127 /* this converter is not a hardware driver */
1128 case ACMDM_FILTERTAG_DETAILS:
1129 case ACMDM_FILTER_DETAILS:
1130 /* this converter is not a filter */
1131 case ACMDM_STREAM_RESET:
1132 /* only needed for asynchronous driver... we aren't, so just say it */
1133 return MMSYSERR_NOTSUPPORTED;
1134 case ACMDM_STREAM_PREPARE:
1135 case ACMDM_STREAM_UNPREPARE:
1136 /* nothing special to do here... so don't do anything */
1137 return MMSYSERR_NOERROR;
1138
1139 default:
1140 return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
1141 }
1142 }