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