2 * G711 handling (includes A-Law & MU-Law)
4 * Copyright (C) 2002 Eric Pouech
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.
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.
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
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(g711
);
38 /***********************************************************************
41 static LRESULT
G711_drvOpen(LPCSTR str
)
46 /***********************************************************************
49 static LRESULT
G711_drvClose(DWORD_PTR dwDevID
)
54 typedef struct tagAcmG711Data
56 void (*convert
)(PACMDRVSTREAMINSTANCE adsi
,
57 const unsigned char*, LPDWORD
, unsigned char*, LPDWORD
);
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
70 static Format PCM_Formats
[] =
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},
78 static Format ALaw_Formats
[] =
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},
84 static Format ULaw_Formats
[] =
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},
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]))
94 /***********************************************************************
97 static DWORD
G711_GetFormatIndex(LPWAVEFORMATEX wfx
)
102 switch (wfx
->wFormatTag
)
104 case WAVE_FORMAT_PCM
:
105 hi
= NUM_PCM_FORMATS
;
108 case WAVE_FORMAT_ALAW
:
109 hi
= NUM_ALAW_FORMATS
;
112 case WAVE_FORMAT_MULAW
:
113 hi
= NUM_ULAW_FORMATS
;
120 for (i
= 0; i
< hi
; i
++)
122 if (wfx
->nChannels
== fmts
[i
].nChannels
&&
123 wfx
->nSamplesPerSec
== fmts
[i
].rate
&&
124 wfx
->wBitsPerSample
== fmts
[i
].nBits
)
131 /***********************************************************************
134 * Read a 16 bit sample (correctly handles endianess)
136 static inline short R16(const unsigned char* src
)
138 return (short)((unsigned short)src
[0] | ((unsigned short)src
[1] << 8));
141 /***********************************************************************
144 * Write a 16 bit sample (correctly handles endianess)
146 static inline void W16(unsigned char* dst
, short s
)
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.
160 /* -------------------------------------------------------------------------------*/
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
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.
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.
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.
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.
183 * Sun Microsystems, Inc.
185 * Mountain View, California 94043
191 * u-law, A-law and linear PCM conversions.
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
200 * Borge Lindberg, Center for PersonKommunikation, Aalborg University.
205 #define SIGN_BIT (0x80) /* Sign bit for a 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. */
211 static short seg_aend
[8] = {0x1F, 0x3F, 0x7F, 0xFF,
212 0x1FF, 0x3FF, 0x7FF, 0xFFF};
213 static short seg_uend
[8] = {0x3F, 0x7F, 0xFF, 0x1FF,
214 0x3FF, 0x7FF, 0xFFF, 0x1FFF};
216 /* copy from CCITT G.711 specifications */
217 static unsigned char _u2a
[128] = { /* u- to A-law conversions */
218 1, 1, 2, 2, 3, 3, 4, 4,
219 5, 5, 6, 6, 7, 7, 8, 8,
220 9, 10, 11, 12, 13, 14, 15, 16,
221 17, 18, 19, 20, 21, 22, 23, 24,
222 25, 27, 29, 31, 33, 34, 35, 36,
223 37, 38, 39, 40, 41, 42, 43, 44,
224 46, 48, 49, 50, 51, 52, 53, 54,
225 55, 56, 57, 58, 59, 60, 61, 62,
226 64, 65, 66, 67, 68, 69, 70, 71,
227 72, 73, 74, 75, 76, 77, 78, 79,
229 81, 82, 83, 84, 85, 86, 87, 88,
231 80, 82, 83, 84, 85, 86, 87, 88,
232 89, 90, 91, 92, 93, 94, 95, 96,
233 97, 98, 99, 100, 101, 102, 103, 104,
234 105, 106, 107, 108, 109, 110, 111, 112,
235 113, 114, 115, 116, 117, 118, 119, 120,
236 121, 122, 123, 124, 125, 126, 127, 128};
238 static unsigned char _a2u
[128] = { /* A- to u-law conversions */
239 1, 3, 5, 7, 9, 11, 13, 15,
240 16, 17, 18, 19, 20, 21, 22, 23,
241 24, 25, 26, 27, 28, 29, 30, 31,
242 32, 32, 33, 33, 34, 34, 35, 35,
243 36, 37, 38, 39, 40, 41, 42, 43,
244 44, 45, 46, 47, 48, 48, 49, 49,
245 50, 51, 52, 53, 54, 55, 56, 57,
246 58, 59, 60, 61, 62, 63, 64, 64,
247 65, 66, 67, 68, 69, 70, 71, 72,
249 73, 74, 75, 76, 77, 78, 79, 79,
251 73, 74, 75, 76, 77, 78, 79, 80,
253 80, 81, 82, 83, 84, 85, 86, 87,
254 88, 89, 90, 91, 92, 93, 94, 95,
255 96, 97, 98, 99, 100, 101, 102, 103,
256 104, 105, 106, 107, 108, 109, 110, 111,
257 112, 113, 114, 115, 116, 117, 118, 119,
258 120, 121, 122, 123, 124, 125, 126, 127};
262 int val
, /* changed from "short" *drago* */
264 int size
) /* changed from "short" *drago* */
266 int i
; /* changed from "short" *drago* */
268 for (i
= 0; i
< size
; i
++) {
276 * linear2alaw() - Convert a 16-bit linear PCM value to 8-bit A-law
278 * linear2alaw() accepts an 16-bit integer and encodes it as A-law data.
280 * Linear Input Code Compressed Code
281 * ------------------------ ---------------
282 * 0000000wxyza 000wxyz
283 * 0000001wxyza 001wxyz
284 * 000001wxyzab 010wxyz
285 * 00001wxyzabc 011wxyz
286 * 0001wxyzabcd 100wxyz
287 * 001wxyzabcde 101wxyz
288 * 01wxyzabcdef 110wxyz
289 * 1wxyzabcdefg 111wxyz
291 * For further information see John C. Bellamy's Digital Telephony, 1982,
292 * John Wiley & Sons, pps 98-111 and 472-476.
294 static inline unsigned char
295 linear2alaw(int pcm_val
) /* 2's complement (16-bit range) */
296 /* changed from "short" *drago* */
298 int mask
; /* changed from "short" *drago* */
299 int seg
; /* changed from "short" *drago* */
302 pcm_val
= pcm_val
>> 3;
305 mask
= 0xD5; /* sign (7th) bit = 1 */
307 mask
= 0x55; /* sign bit = 0 */
308 pcm_val
= -pcm_val
- 1;
311 /* Convert the scaled magnitude to segment number. */
312 seg
= search(pcm_val
, seg_aend
, 8);
314 /* Combine the sign, segment, and quantization bits. */
316 if (seg
>= 8) /* out of range, return maximum value. */
317 return (unsigned char) (0x7F ^ mask
);
319 aval
= (unsigned char) seg
<< SEG_SHIFT
;
321 aval
|= (pcm_val
>> 1) & QUANT_MASK
;
323 aval
|= (pcm_val
>> seg
) & QUANT_MASK
;
324 return (aval
^ mask
);
330 * alaw2linear() - Convert an A-law value to 16-bit linear PCM
334 alaw2linear(unsigned char a_val
)
336 int t
; /* changed from "short" *drago* */
337 int seg
; /* changed from "short" *drago* */
341 t
= (a_val
& QUANT_MASK
) << 4;
342 seg
= ((unsigned)a_val
& SEG_MASK
) >> SEG_SHIFT
;
354 return ((a_val
& SIGN_BIT
) ? t
: -t
);
358 * this array has been statically generated from the above routine
360 static unsigned short _a2l
[] = {
361 0xEA80, 0xEB80, 0xE880, 0xE980, 0xEE80, 0xEF80, 0xEC80, 0xED80,
362 0xE280, 0xE380, 0xE080, 0xE180, 0xE680, 0xE780, 0xE480, 0xE580,
363 0xF540, 0xF5C0, 0xF440, 0xF4C0, 0xF740, 0xF7C0, 0xF640, 0xF6C0,
364 0xF140, 0xF1C0, 0xF040, 0xF0C0, 0xF340, 0xF3C0, 0xF240, 0xF2C0,
365 0xAA00, 0xAE00, 0xA200, 0xA600, 0xBA00, 0xBE00, 0xB200, 0xB600,
366 0x8A00, 0x8E00, 0x8200, 0x8600, 0x9A00, 0x9E00, 0x9200, 0x9600,
367 0xD500, 0xD700, 0xD100, 0xD300, 0xDD00, 0xDF00, 0xD900, 0xDB00,
368 0xC500, 0xC700, 0xC100, 0xC300, 0xCD00, 0xCF00, 0xC900, 0xCB00,
369 0xFEA8, 0xFEB8, 0xFE88, 0xFE98, 0xFEE8, 0xFEF8, 0xFEC8, 0xFED8,
370 0xFE28, 0xFE38, 0xFE08, 0xFE18, 0xFE68, 0xFE78, 0xFE48, 0xFE58,
371 0xFFA8, 0xFFB8, 0xFF88, 0xFF98, 0xFFE8, 0xFFF8, 0xFFC8, 0xFFD8,
372 0xFF28, 0xFF38, 0xFF08, 0xFF18, 0xFF68, 0xFF78, 0xFF48, 0xFF58,
373 0xFAA0, 0xFAE0, 0xFA20, 0xFA60, 0xFBA0, 0xFBE0, 0xFB20, 0xFB60,
374 0xF8A0, 0xF8E0, 0xF820, 0xF860, 0xF9A0, 0xF9E0, 0xF920, 0xF960,
375 0xFD50, 0xFD70, 0xFD10, 0xFD30, 0xFDD0, 0xFDF0, 0xFD90, 0xFDB0,
376 0xFC50, 0xFC70, 0xFC10, 0xFC30, 0xFCD0, 0xFCF0, 0xFC90, 0xFCB0,
377 0x1580, 0x1480, 0x1780, 0x1680, 0x1180, 0x1080, 0x1380, 0x1280,
378 0x1D80, 0x1C80, 0x1F80, 0x1E80, 0x1980, 0x1880, 0x1B80, 0x1A80,
379 0x0AC0, 0x0A40, 0x0BC0, 0x0B40, 0x08C0, 0x0840, 0x09C0, 0x0940,
380 0x0EC0, 0x0E40, 0x0FC0, 0x0F40, 0x0CC0, 0x0C40, 0x0DC0, 0x0D40,
381 0x5600, 0x5200, 0x5E00, 0x5A00, 0x4600, 0x4200, 0x4E00, 0x4A00,
382 0x7600, 0x7200, 0x7E00, 0x7A00, 0x6600, 0x6200, 0x6E00, 0x6A00,
383 0x2B00, 0x2900, 0x2F00, 0x2D00, 0x2300, 0x2100, 0x2700, 0x2500,
384 0x3B00, 0x3900, 0x3F00, 0x3D00, 0x3300, 0x3100, 0x3700, 0x3500,
385 0x0158, 0x0148, 0x0178, 0x0168, 0x0118, 0x0108, 0x0138, 0x0128,
386 0x01D8, 0x01C8, 0x01F8, 0x01E8, 0x0198, 0x0188, 0x01B8, 0x01A8,
387 0x0058, 0x0048, 0x0078, 0x0068, 0x0018, 0x0008, 0x0038, 0x0028,
388 0x00D8, 0x00C8, 0x00F8, 0x00E8, 0x0098, 0x0088, 0x00B8, 0x00A8,
389 0x0560, 0x0520, 0x05E0, 0x05A0, 0x0460, 0x0420, 0x04E0, 0x04A0,
390 0x0760, 0x0720, 0x07E0, 0x07A0, 0x0660, 0x0620, 0x06E0, 0x06A0,
391 0x02B0, 0x0290, 0x02F0, 0x02D0, 0x0230, 0x0210, 0x0270, 0x0250,
392 0x03B0, 0x0390, 0x03F0, 0x03D0, 0x0330, 0x0310, 0x0370, 0x0350,
395 alaw2linear(unsigned char a_val
)
397 return (short)_a2l
[a_val
];
401 #define BIAS (0x84) /* Bias for linear code. */
405 * linear2ulaw() - Convert a linear PCM value to u-law
407 * In order to simplify the encoding process, the original linear magnitude
408 * is biased by adding 33 which shifts the encoding range from (0 - 8158) to
409 * (33 - 8191). The result can be seen in the following encoding table:
411 * Biased Linear Input Code Compressed Code
412 * ------------------------ ---------------
413 * 00000001wxyza 000wxyz
414 * 0000001wxyzab 001wxyz
415 * 000001wxyzabc 010wxyz
416 * 00001wxyzabcd 011wxyz
417 * 0001wxyzabcde 100wxyz
418 * 001wxyzabcdef 101wxyz
419 * 01wxyzabcdefg 110wxyz
420 * 1wxyzabcdefgh 111wxyz
422 * Each biased linear code has a leading 1 which identifies the segment
423 * number. The value of the segment number is equal to 7 minus the number
424 * of leading 0's. The quantization interval is directly available as the
425 * four bits wxyz. * The trailing bits (a - h) are ignored.
427 * Ordinarily the complement of the resulting code word is used for
428 * transmission, and so the code word is complemented before it is returned.
430 * For further information see John C. Bellamy's Digital Telephony, 1982,
431 * John Wiley & Sons, pps 98-111 and 472-476.
433 static inline unsigned char
434 linear2ulaw(short pcm_val
) /* 2's complement (16-bit range) */
440 /* Get the sign and the magnitude of the value. */
441 pcm_val
= pcm_val
>> 2;
448 if ( pcm_val
> CLIP
) pcm_val
= CLIP
; /* clip the magnitude */
449 pcm_val
+= (BIAS
>> 2);
451 /* Convert the scaled magnitude to segment number. */
452 seg
= search(pcm_val
, seg_uend
, 8);
455 * Combine the sign, segment, quantization bits;
456 * and complement the code word.
458 if (seg
>= 8) /* out of range, return maximum value. */
459 return (unsigned char) (0x7F ^ mask
);
461 uval
= (unsigned char) (seg
<< 4) | ((pcm_val
>> (seg
+ 1)) & 0xF);
462 return (uval
^ mask
);
468 * ulaw2linear() - Convert a u-law value to 16-bit linear PCM
470 * First, a biased linear code is derived from the code word. An unbiased
471 * output can then be obtained by subtracting 33 from the biased code.
473 * Note that this function expects to be passed the complement of the
474 * original code word. This is in keeping with ISDN conventions.
477 ulaw2linear(unsigned char u_val
)
481 /* Complement to obtain normal u-law value. */
485 * Extract and bias the quantization bits. Then
486 * shift up by the segment number and subtract out the bias.
488 t
= ((u_val
& QUANT_MASK
) << 3) + BIAS
;
489 t
<<= ((unsigned)u_val
& SEG_MASK
) >> SEG_SHIFT
;
491 return ((u_val
& SIGN_BIT
) ? (BIAS
- t
) : (t
- BIAS
));
495 * this array has been statically generated from the above routine
497 static unsigned short _u2l
[] = {
498 0x8284, 0x8684, 0x8A84, 0x8E84, 0x9284, 0x9684, 0x9A84, 0x9E84,
499 0xA284, 0xA684, 0xAA84, 0xAE84, 0xB284, 0xB684, 0xBA84, 0xBE84,
500 0xC184, 0xC384, 0xC584, 0xC784, 0xC984, 0xCB84, 0xCD84, 0xCF84,
501 0xD184, 0xD384, 0xD584, 0xD784, 0xD984, 0xDB84, 0xDD84, 0xDF84,
502 0xE104, 0xE204, 0xE304, 0xE404, 0xE504, 0xE604, 0xE704, 0xE804,
503 0xE904, 0xEA04, 0xEB04, 0xEC04, 0xED04, 0xEE04, 0xEF04, 0xF004,
504 0xF0C4, 0xF144, 0xF1C4, 0xF244, 0xF2C4, 0xF344, 0xF3C4, 0xF444,
505 0xF4C4, 0xF544, 0xF5C4, 0xF644, 0xF6C4, 0xF744, 0xF7C4, 0xF844,
506 0xF8A4, 0xF8E4, 0xF924, 0xF964, 0xF9A4, 0xF9E4, 0xFA24, 0xFA64,
507 0xFAA4, 0xFAE4, 0xFB24, 0xFB64, 0xFBA4, 0xFBE4, 0xFC24, 0xFC64,
508 0xFC94, 0xFCB4, 0xFCD4, 0xFCF4, 0xFD14, 0xFD34, 0xFD54, 0xFD74,
509 0xFD94, 0xFDB4, 0xFDD4, 0xFDF4, 0xFE14, 0xFE34, 0xFE54, 0xFE74,
510 0xFE8C, 0xFE9C, 0xFEAC, 0xFEBC, 0xFECC, 0xFEDC, 0xFEEC, 0xFEFC,
511 0xFF0C, 0xFF1C, 0xFF2C, 0xFF3C, 0xFF4C, 0xFF5C, 0xFF6C, 0xFF7C,
512 0xFF88, 0xFF90, 0xFF98, 0xFFA0, 0xFFA8, 0xFFB0, 0xFFB8, 0xFFC0,
513 0xFFC8, 0xFFD0, 0xFFD8, 0xFFE0, 0xFFE8, 0xFFF0, 0xFFF8, 0x0000,
514 0x7D7C, 0x797C, 0x757C, 0x717C, 0x6D7C, 0x697C, 0x657C, 0x617C,
515 0x5D7C, 0x597C, 0x557C, 0x517C, 0x4D7C, 0x497C, 0x457C, 0x417C,
516 0x3E7C, 0x3C7C, 0x3A7C, 0x387C, 0x367C, 0x347C, 0x327C, 0x307C,
517 0x2E7C, 0x2C7C, 0x2A7C, 0x287C, 0x267C, 0x247C, 0x227C, 0x207C,
518 0x1EFC, 0x1DFC, 0x1CFC, 0x1BFC, 0x1AFC, 0x19FC, 0x18FC, 0x17FC,
519 0x16FC, 0x15FC, 0x14FC, 0x13FC, 0x12FC, 0x11FC, 0x10FC, 0x0FFC,
520 0x0F3C, 0x0EBC, 0x0E3C, 0x0DBC, 0x0D3C, 0x0CBC, 0x0C3C, 0x0BBC,
521 0x0B3C, 0x0ABC, 0x0A3C, 0x09BC, 0x093C, 0x08BC, 0x083C, 0x07BC,
522 0x075C, 0x071C, 0x06DC, 0x069C, 0x065C, 0x061C, 0x05DC, 0x059C,
523 0x055C, 0x051C, 0x04DC, 0x049C, 0x045C, 0x041C, 0x03DC, 0x039C,
524 0x036C, 0x034C, 0x032C, 0x030C, 0x02EC, 0x02CC, 0x02AC, 0x028C,
525 0x026C, 0x024C, 0x022C, 0x020C, 0x01EC, 0x01CC, 0x01AC, 0x018C,
526 0x0174, 0x0164, 0x0154, 0x0144, 0x0134, 0x0124, 0x0114, 0x0104,
527 0x00F4, 0x00E4, 0x00D4, 0x00C4, 0x00B4, 0x00A4, 0x0094, 0x0084,
528 0x0078, 0x0070, 0x0068, 0x0060, 0x0058, 0x0050, 0x0048, 0x0040,
529 0x0038, 0x0030, 0x0028, 0x0020, 0x0018, 0x0010, 0x0008, 0x0000,
531 static inline short ulaw2linear(unsigned char u_val
)
533 return (short)_u2l
[u_val
];
537 /* A-law to u-law conversion */
538 static inline unsigned char
539 alaw2ulaw(unsigned char aval
)
542 return (unsigned char) ((aval
& 0x80) ? (0xFF ^ _a2u
[aval
^ 0xD5]) :
543 (0x7F ^ _a2u
[aval
^ 0x55]));
546 /* u-law to A-law conversion */
547 static inline unsigned char
548 ulaw2alaw(unsigned char uval
)
551 return (unsigned char) ((uval
& 0x80) ? (0xD5 ^ (_u2a
[0xFF ^ uval
] - 1)) :
552 (unsigned char) (0x55 ^ (_u2a
[0x7F ^ uval
] - 1)));
555 /* -------------------------------------------------------------------------------*/
557 static void cvtXXalaw16K(PACMDRVSTREAMINSTANCE adsi
,
558 const unsigned char* src
, LPDWORD srcsize
,
559 unsigned char* dst
, LPDWORD dstsize
)
561 DWORD len
= min(*srcsize
, *dstsize
/ 2);
567 for (i
= 0; i
< len
; i
++)
569 w
= alaw2linear(*src
++);
570 W16(dst
, w
); dst
+= 2;
574 static void cvtXX16alawK(PACMDRVSTREAMINSTANCE adsi
,
575 const unsigned char* src
, LPDWORD srcsize
,
576 unsigned char* dst
, LPDWORD dstsize
)
578 DWORD len
= min(*srcsize
/ 2, *dstsize
);
583 for (i
= 0; i
< len
; i
++)
585 *dst
++ = linear2alaw(R16(src
)); src
+= 2;
589 static void cvtXXulaw16K(PACMDRVSTREAMINSTANCE adsi
,
590 const unsigned char* src
, LPDWORD srcsize
,
591 unsigned char* dst
, LPDWORD dstsize
)
593 DWORD len
= min(*srcsize
, *dstsize
/ 2);
599 for (i
= 0; i
< len
; i
++)
601 w
= ulaw2linear(*src
++);
602 W16(dst
, w
); dst
+= 2;
606 static void cvtXX16ulawK(PACMDRVSTREAMINSTANCE adsi
,
607 const unsigned char* src
, LPDWORD srcsize
,
608 unsigned char* dst
, LPDWORD dstsize
)
610 DWORD len
= min(*srcsize
/ 2, *dstsize
);
615 for (i
= 0; i
< len
; i
++)
617 *dst
++ = linear2ulaw(R16(src
)); src
+= 2;
621 static void cvtXXalawulawK(PACMDRVSTREAMINSTANCE adsi
,
622 const unsigned char* src
, LPDWORD srcsize
,
623 unsigned char* dst
, LPDWORD dstsize
)
625 DWORD len
= min(*srcsize
, *dstsize
);
631 for (i
= 0; i
< len
; i
++)
632 *dst
++ = alaw2ulaw(*src
++);
636 static void cvtXXulawalawK(PACMDRVSTREAMINSTANCE adsi
,
637 const unsigned char* src
, LPDWORD srcsize
,
638 unsigned char* dst
, LPDWORD dstsize
)
640 DWORD len
= min(*srcsize
, *dstsize
);
646 for (i
= 0; i
< len
; i
++)
647 *dst
++ = ulaw2alaw(*src
++);
650 /***********************************************************************
654 static LRESULT
G711_DriverDetails(PACMDRIVERDETAILSW add
)
656 add
->fccType
= ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC
;
657 add
->fccComp
= ACMDRIVERDETAILS_FCCCOMP_UNDEFINED
;
660 add
->vdwACM
= 0x01000000;
661 add
->vdwDriver
= 0x01000000;
662 add
->fdwSupport
= ACMDRIVERDETAILS_SUPPORTF_CODEC
;
663 add
->cFormatTags
= 3; /* PCM, G711 A-LAW & MU-LAW */
664 add
->cFilterTags
= 0;
666 MultiByteToWideChar( CP_ACP
, 0, "WINE-G711", -1,
667 add
->szShortName
, sizeof(add
->szShortName
)/sizeof(WCHAR
) );
668 MultiByteToWideChar( CP_ACP
, 0, "Wine G711 converter", -1,
669 add
->szLongName
, sizeof(add
->szLongName
)/sizeof(WCHAR
) );
670 MultiByteToWideChar( CP_ACP
, 0, "Brought to you by the Wine team...", -1,
671 add
->szCopyright
, sizeof(add
->szCopyright
)/sizeof(WCHAR
) );
672 MultiByteToWideChar( CP_ACP
, 0, "Refer to LICENSE file", -1,
673 add
->szLicensing
, sizeof(add
->szLicensing
)/sizeof(WCHAR
) );
674 add
->szFeatures
[0] = 0;
676 return MMSYSERR_NOERROR
;
679 /***********************************************************************
680 * G711_FormatTagDetails
683 static LRESULT
G711_FormatTagDetails(PACMFORMATTAGDETAILSW aftd
, DWORD dwQuery
)
685 static const WCHAR szPcm
[]={'P','C','M',0};
686 static const WCHAR szALaw
[]={'A','-','L','a','w',0};
687 static const WCHAR szULaw
[]={'U','-','L','a','w',0};
691 case ACM_FORMATTAGDETAILSF_INDEX
:
692 if (aftd
->dwFormatTagIndex
>= 3) return ACMERR_NOTPOSSIBLE
;
694 case ACM_FORMATTAGDETAILSF_LARGESTSIZE
:
695 if (aftd
->dwFormatTag
== WAVE_FORMAT_UNKNOWN
)
697 aftd
->dwFormatTagIndex
= 1;
701 case ACM_FORMATTAGDETAILSF_FORMATTAG
:
702 switch (aftd
->dwFormatTag
)
704 case WAVE_FORMAT_PCM
: aftd
->dwFormatTagIndex
= 0; break;
705 case WAVE_FORMAT_ALAW
: aftd
->dwFormatTagIndex
= 1; break;
706 case WAVE_FORMAT_MULAW
: aftd
->dwFormatTagIndex
= 2; break;
707 default: return ACMERR_NOTPOSSIBLE
;
711 WARN("Unsupported query %08x\n", dwQuery
);
712 return MMSYSERR_NOTSUPPORTED
;
715 aftd
->fdwSupport
= ACMDRIVERDETAILS_SUPPORTF_CODEC
;
716 switch (aftd
->dwFormatTagIndex
)
719 aftd
->dwFormatTag
= WAVE_FORMAT_PCM
;
720 aftd
->cbFormatSize
= sizeof(PCMWAVEFORMAT
);
721 aftd
->cStandardFormats
= NUM_PCM_FORMATS
;
722 lstrcpyW(aftd
->szFormatTag
, szPcm
);
725 aftd
->dwFormatTag
= WAVE_FORMAT_ALAW
;
726 aftd
->cbFormatSize
= sizeof(WAVEFORMATEX
);
727 aftd
->cStandardFormats
= NUM_ALAW_FORMATS
;
728 lstrcpyW(aftd
->szFormatTag
, szALaw
);
731 aftd
->dwFormatTag
= WAVE_FORMAT_MULAW
;
732 aftd
->cbFormatSize
= sizeof(WAVEFORMATEX
);
733 aftd
->cStandardFormats
= NUM_ULAW_FORMATS
;
734 lstrcpyW(aftd
->szFormatTag
, szULaw
);
737 return MMSYSERR_NOERROR
;
740 /***********************************************************************
744 static LRESULT
G711_FormatDetails(PACMFORMATDETAILSW afd
, DWORD dwQuery
)
748 case ACM_FORMATDETAILSF_FORMAT
:
749 if (G711_GetFormatIndex(afd
->pwfx
) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE
;
751 case ACM_FORMATDETAILSF_INDEX
:
752 afd
->pwfx
->wFormatTag
= afd
->dwFormatTag
;
753 switch (afd
->dwFormatTag
)
755 case WAVE_FORMAT_PCM
:
756 if (afd
->dwFormatIndex
>= NUM_PCM_FORMATS
) return ACMERR_NOTPOSSIBLE
;
757 afd
->pwfx
->nChannels
= PCM_Formats
[afd
->dwFormatIndex
].nChannels
;
758 afd
->pwfx
->nSamplesPerSec
= PCM_Formats
[afd
->dwFormatIndex
].rate
;
759 afd
->pwfx
->wBitsPerSample
= PCM_Formats
[afd
->dwFormatIndex
].nBits
;
760 afd
->pwfx
->nBlockAlign
= afd
->pwfx
->nChannels
* 2;
761 afd
->pwfx
->nAvgBytesPerSec
= afd
->pwfx
->nSamplesPerSec
* afd
->pwfx
->nBlockAlign
;
763 case WAVE_FORMAT_ALAW
:
764 if (afd
->dwFormatIndex
>= NUM_ALAW_FORMATS
) return ACMERR_NOTPOSSIBLE
;
765 afd
->pwfx
->nChannels
= ALaw_Formats
[afd
->dwFormatIndex
].nChannels
;
766 afd
->pwfx
->nSamplesPerSec
= ALaw_Formats
[afd
->dwFormatIndex
].rate
;
767 afd
->pwfx
->wBitsPerSample
= ALaw_Formats
[afd
->dwFormatIndex
].nBits
;
768 afd
->pwfx
->nBlockAlign
= ALaw_Formats
[afd
->dwFormatIndex
].nChannels
;
769 afd
->pwfx
->nAvgBytesPerSec
= afd
->pwfx
->nSamplesPerSec
* afd
->pwfx
->nChannels
;
770 afd
->pwfx
->cbSize
= 0;
772 case WAVE_FORMAT_MULAW
:
773 if (afd
->dwFormatIndex
>= NUM_ULAW_FORMATS
) return ACMERR_NOTPOSSIBLE
;
774 afd
->pwfx
->nChannels
= ULaw_Formats
[afd
->dwFormatIndex
].nChannels
;
775 afd
->pwfx
->nSamplesPerSec
= ULaw_Formats
[afd
->dwFormatIndex
].rate
;
776 afd
->pwfx
->wBitsPerSample
= ULaw_Formats
[afd
->dwFormatIndex
].nBits
;
777 afd
->pwfx
->nBlockAlign
= ULaw_Formats
[afd
->dwFormatIndex
].nChannels
;
778 afd
->pwfx
->nAvgBytesPerSec
= afd
->pwfx
->nSamplesPerSec
* afd
->pwfx
->nChannels
;
779 afd
->pwfx
->cbSize
= 0;
782 WARN("Unsupported tag %08x\n", afd
->dwFormatTag
);
783 return MMSYSERR_INVALPARAM
;
787 WARN("Unsupported query %08x\n", dwQuery
);
788 return MMSYSERR_NOTSUPPORTED
;
790 afd
->fdwSupport
= ACMDRIVERDETAILS_SUPPORTF_CODEC
;
791 afd
->szFormat
[0] = 0; /* let MSACM format this for us... */
793 return MMSYSERR_NOERROR
;
796 /***********************************************************************
800 static LRESULT
G711_FormatSuggest(PACMDRVFORMATSUGGEST adfs
)
803 if (adfs
->cbwfxSrc
< sizeof(PCMWAVEFORMAT
) ||
804 adfs
->cbwfxDst
< sizeof(PCMWAVEFORMAT
) ||
805 G711_GetFormatIndex(adfs
->pwfxSrc
) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE
;
806 /* FIXME: should do those tests against the real size (according to format tag */
808 /* If no suggestion for destination, then copy source value */
809 if (!(adfs
->fdwSuggest
& ACM_FORMATSUGGESTF_NCHANNELS
))
810 adfs
->pwfxDst
->nChannels
= adfs
->pwfxSrc
->nChannels
;
811 if (!(adfs
->fdwSuggest
& ACM_FORMATSUGGESTF_NSAMPLESPERSEC
))
812 adfs
->pwfxDst
->nSamplesPerSec
= adfs
->pwfxSrc
->nSamplesPerSec
;
814 if (!(adfs
->fdwSuggest
& ACM_FORMATSUGGESTF_WBITSPERSAMPLE
))
816 if (adfs
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_PCM
)
817 adfs
->pwfxDst
->wBitsPerSample
= 8;
819 adfs
->pwfxDst
->wBitsPerSample
= 16;
821 if (!(adfs
->fdwSuggest
& ACM_FORMATSUGGESTF_WFORMATTAG
))
823 switch (adfs
->pwfxSrc
->wFormatTag
)
825 case WAVE_FORMAT_PCM
: adfs
->pwfxDst
->wFormatTag
= WAVE_FORMAT_ALAW
; break;
826 case WAVE_FORMAT_ALAW
: adfs
->pwfxDst
->wFormatTag
= WAVE_FORMAT_PCM
; break;
827 case WAVE_FORMAT_MULAW
: adfs
->pwfxDst
->wFormatTag
= WAVE_FORMAT_PCM
; break;
830 /* check if result is ok */
831 if (G711_GetFormatIndex(adfs
->pwfxDst
) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE
;
833 /* recompute other values */
834 switch (adfs
->pwfxDst
->wFormatTag
)
836 case WAVE_FORMAT_PCM
:
837 adfs
->pwfxDst
->nBlockAlign
= adfs
->pwfxDst
->nChannels
;
838 adfs
->pwfxDst
->nAvgBytesPerSec
= adfs
->pwfxDst
->nSamplesPerSec
* adfs
->pwfxDst
->nBlockAlign
;
840 case WAVE_FORMAT_ALAW
:
841 adfs
->pwfxDst
->nBlockAlign
= adfs
->pwfxDst
->nChannels
* 2;
842 adfs
->pwfxDst
->nAvgBytesPerSec
= adfs
->pwfxDst
->nSamplesPerSec
* adfs
->pwfxSrc
->nChannels
* 2;
844 case WAVE_FORMAT_MULAW
:
845 adfs
->pwfxDst
->nBlockAlign
= adfs
->pwfxDst
->nChannels
* 2;
846 adfs
->pwfxDst
->nAvgBytesPerSec
= adfs
->pwfxDst
->nSamplesPerSec
* adfs
->pwfxSrc
->nChannels
* 2;
853 return MMSYSERR_NOERROR
;
856 /***********************************************************************
860 static void G711_Reset(PACMDRVSTREAMINSTANCE adsi
, AcmG711Data
* aad
)
864 /***********************************************************************
868 static LRESULT
G711_StreamOpen(PACMDRVSTREAMINSTANCE adsi
)
872 assert(!(adsi
->fdwOpen
& ACM_STREAMOPENF_ASYNC
));
874 if (G711_GetFormatIndex(adsi
->pwfxSrc
) == 0xFFFFFFFF ||
875 G711_GetFormatIndex(adsi
->pwfxDst
) == 0xFFFFFFFF)
876 return ACMERR_NOTPOSSIBLE
;
878 aad
= HeapAlloc(GetProcessHeap(), 0, sizeof(AcmG711Data
));
879 if (aad
== 0) return MMSYSERR_NOMEM
;
881 adsi
->dwDriver
= (DWORD
)aad
;
883 if (adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_PCM
&&
884 adsi
->pwfxDst
->wFormatTag
== WAVE_FORMAT_PCM
)
888 else if (adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_ALAW
&&
889 adsi
->pwfxDst
->wFormatTag
== WAVE_FORMAT_PCM
)
891 /* resampling or mono <=> stereo not available
892 * G711 algo only define 16 bit per sample output
894 if (adsi
->pwfxSrc
->nSamplesPerSec
!= adsi
->pwfxDst
->nSamplesPerSec
||
895 adsi
->pwfxSrc
->nChannels
!= adsi
->pwfxDst
->nChannels
||
896 adsi
->pwfxDst
->wBitsPerSample
!= 16)
899 /* g711 A-Law decoding... */
900 if (adsi
->pwfxDst
->wBitsPerSample
== 16)
901 aad
->convert
= cvtXXalaw16K
;
903 else if (adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_PCM
&&
904 adsi
->pwfxDst
->wFormatTag
== WAVE_FORMAT_ALAW
)
906 if (adsi
->pwfxSrc
->nSamplesPerSec
!= adsi
->pwfxDst
->nSamplesPerSec
||
907 adsi
->pwfxSrc
->nChannels
!= adsi
->pwfxDst
->nChannels
||
908 adsi
->pwfxSrc
->wBitsPerSample
!= 16)
912 if (adsi
->pwfxSrc
->wBitsPerSample
== 16)
913 aad
->convert
= cvtXX16alawK
;
915 else if (adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_MULAW
&&
916 adsi
->pwfxDst
->wFormatTag
== WAVE_FORMAT_PCM
)
918 /* resampling or mono <=> stereo not available
919 * G711 algo only define 16 bit per sample output
921 if (adsi
->pwfxSrc
->nSamplesPerSec
!= adsi
->pwfxDst
->nSamplesPerSec
||
922 adsi
->pwfxSrc
->nChannels
!= adsi
->pwfxDst
->nChannels
||
923 adsi
->pwfxDst
->wBitsPerSample
!= 16)
926 /* g711 MU-Law decoding... */
927 if (adsi
->pwfxDst
->wBitsPerSample
== 16)
928 aad
->convert
= cvtXXulaw16K
;
930 else if (adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_PCM
&&
931 adsi
->pwfxDst
->wFormatTag
== WAVE_FORMAT_MULAW
)
933 if (adsi
->pwfxSrc
->nSamplesPerSec
!= adsi
->pwfxDst
->nSamplesPerSec
||
934 adsi
->pwfxSrc
->nChannels
!= adsi
->pwfxDst
->nChannels
||
935 adsi
->pwfxSrc
->wBitsPerSample
!= 16)
939 if (adsi
->pwfxSrc
->wBitsPerSample
== 16)
940 aad
->convert
= cvtXX16ulawK
;
942 else if (adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_MULAW
&&
943 adsi
->pwfxDst
->wFormatTag
== WAVE_FORMAT_ALAW
)
945 if (adsi
->pwfxSrc
->nSamplesPerSec
!= adsi
->pwfxDst
->nSamplesPerSec
||
946 adsi
->pwfxSrc
->nChannels
!= adsi
->pwfxDst
->nChannels
)
949 /* MU-Law => A-Law... */
950 aad
->convert
= cvtXXulawalawK
;
952 else if (adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_ALAW
&&
953 adsi
->pwfxDst
->wFormatTag
== WAVE_FORMAT_MULAW
)
955 if (adsi
->pwfxSrc
->nSamplesPerSec
!= adsi
->pwfxDst
->nSamplesPerSec
||
956 adsi
->pwfxSrc
->nChannels
!= adsi
->pwfxDst
->nChannels
)
959 /* A-Law => MU-Law... */
960 aad
->convert
= cvtXXalawulawK
;
964 G711_Reset(adsi
, aad
);
966 return MMSYSERR_NOERROR
;
969 HeapFree(GetProcessHeap(), 0, aad
);
971 return MMSYSERR_NOTSUPPORTED
;
974 /***********************************************************************
978 static LRESULT
G711_StreamClose(PACMDRVSTREAMINSTANCE adsi
)
980 HeapFree(GetProcessHeap(), 0, (void*)adsi
->dwDriver
);
981 return MMSYSERR_NOERROR
;
984 /***********************************************************************
988 static inline DWORD
G711_round(DWORD a
, DWORD b
, DWORD c
)
991 /* to be sure, always return an entire number of c... */
992 return ((double)a
* (double)b
+ (double)c
- 1) / (double)c
;
995 /***********************************************************************
999 static LRESULT
G711_StreamSize(PACMDRVSTREAMINSTANCE adsi
, PACMDRVSTREAMSIZE adss
)
1001 switch (adss
->fdwSize
)
1003 case ACM_STREAMSIZEF_DESTINATION
:
1004 /* cbDstLength => cbSrcLength */
1005 if (adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_PCM
&&
1006 (adsi
->pwfxDst
->wFormatTag
== WAVE_FORMAT_ALAW
||
1007 adsi
->pwfxDst
->wFormatTag
== WAVE_FORMAT_MULAW
))
1009 adss
->cbSrcLength
= adss
->cbDstLength
/ 2;
1011 else if ((adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_ALAW
||
1012 adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_MULAW
) &&
1013 adsi
->pwfxDst
->wFormatTag
== WAVE_FORMAT_PCM
)
1015 adss
->cbSrcLength
= adss
->cbDstLength
* 2;
1017 else if ((adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_ALAW
||
1018 adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_MULAW
) &&
1019 (adsi
->pwfxDst
->wFormatTag
== WAVE_FORMAT_ALAW
||
1020 adsi
->pwfxDst
->wFormatTag
== WAVE_FORMAT_MULAW
))
1022 adss
->cbSrcLength
= adss
->cbDstLength
;
1026 return MMSYSERR_NOTSUPPORTED
;
1029 case ACM_STREAMSIZEF_SOURCE
:
1030 /* cbSrcLength => cbDstLength */
1031 if (adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_PCM
&&
1032 (adsi
->pwfxDst
->wFormatTag
== WAVE_FORMAT_ALAW
||
1033 adsi
->pwfxDst
->wFormatTag
== WAVE_FORMAT_MULAW
))
1035 adss
->cbDstLength
= adss
->cbSrcLength
* 2;
1037 else if ((adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_ALAW
||
1038 adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_MULAW
) &&
1039 adsi
->pwfxDst
->wFormatTag
== WAVE_FORMAT_PCM
)
1041 adss
->cbDstLength
= adss
->cbSrcLength
/ 2;
1043 else if ((adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_ALAW
||
1044 adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_MULAW
) &&
1045 (adsi
->pwfxDst
->wFormatTag
== WAVE_FORMAT_ALAW
||
1046 adsi
->pwfxDst
->wFormatTag
== WAVE_FORMAT_MULAW
))
1048 adss
->cbDstLength
= adss
->cbSrcLength
;
1052 return MMSYSERR_NOTSUPPORTED
;
1056 WARN("Unsupported query %08x\n", adss
->fdwSize
);
1057 return MMSYSERR_NOTSUPPORTED
;
1060 return MMSYSERR_NOERROR
;
1063 /***********************************************************************
1064 * G711_StreamConvert
1067 static LRESULT
G711_StreamConvert(PACMDRVSTREAMINSTANCE adsi
, PACMDRVSTREAMHEADER adsh
)
1069 AcmG711Data
* aad
= (AcmG711Data
*)adsi
->dwDriver
;
1070 DWORD nsrc
= adsh
->cbSrcLength
;
1071 DWORD ndst
= adsh
->cbDstLength
;
1073 if (adsh
->fdwConvert
&
1074 ~(ACM_STREAMCONVERTF_BLOCKALIGN
|
1075 ACM_STREAMCONVERTF_END
|
1076 ACM_STREAMCONVERTF_START
))
1078 FIXME("Unsupported fdwConvert (%08x), ignoring it\n", adsh
->fdwConvert
);
1080 /* ACM_STREAMCONVERTF_BLOCKALIGN
1081 * currently all conversions are block aligned, so do nothing for this flag
1082 * ACM_STREAMCONVERTF_END
1083 * no pending data, so do nothing for this flag
1085 if ((adsh
->fdwConvert
& ACM_STREAMCONVERTF_START
))
1087 G711_Reset(adsi
, aad
);
1090 aad
->convert(adsi
, adsh
->pbSrc
, &nsrc
, adsh
->pbDst
, &ndst
);
1091 adsh
->cbSrcLengthUsed
= nsrc
;
1092 adsh
->cbDstLengthUsed
= ndst
;
1094 return MMSYSERR_NOERROR
;
1097 /**************************************************************************
1098 * G711_DriverProc [exported]
1100 LRESULT CALLBACK
G711_DriverProc(DWORD_PTR dwDevID
, HDRVR hDriv
, UINT wMsg
,
1101 LPARAM dwParam1
, LPARAM dwParam2
)
1103 TRACE("(%08lx %p %04x %08lx %08lx);\n",
1104 dwDevID
, hDriv
, wMsg
, dwParam1
, dwParam2
);
1108 case DRV_LOAD
: return 1;
1109 case DRV_FREE
: return 1;
1110 case DRV_OPEN
: return G711_drvOpen((LPSTR
)dwParam1
);
1111 case DRV_CLOSE
: return G711_drvClose(dwDevID
);
1112 case DRV_ENABLE
: return 1;
1113 case DRV_DISABLE
: return 1;
1114 case DRV_QUERYCONFIGURE
: return 1;
1115 case DRV_CONFIGURE
: MessageBoxA(0, "MS G711 (a-Law & mu-Law) filter !", "Wine Driver", MB_OK
); return 1;
1116 case DRV_INSTALL
: return DRVCNF_RESTART
;
1117 case DRV_REMOVE
: return DRVCNF_RESTART
;
1119 case ACMDM_DRIVER_NOTIFY
:
1120 /* no caching from other ACM drivers is done so far */
1121 return MMSYSERR_NOERROR
;
1123 case ACMDM_DRIVER_DETAILS
:
1124 return G711_DriverDetails((PACMDRIVERDETAILSW
)dwParam1
);
1126 case ACMDM_FORMATTAG_DETAILS
:
1127 return G711_FormatTagDetails((PACMFORMATTAGDETAILSW
)dwParam1
, dwParam2
);
1129 case ACMDM_FORMAT_DETAILS
:
1130 return G711_FormatDetails((PACMFORMATDETAILSW
)dwParam1
, dwParam2
);
1132 case ACMDM_FORMAT_SUGGEST
:
1133 return G711_FormatSuggest((PACMDRVFORMATSUGGEST
)dwParam1
);
1135 case ACMDM_STREAM_OPEN
:
1136 return G711_StreamOpen((PACMDRVSTREAMINSTANCE
)dwParam1
);
1138 case ACMDM_STREAM_CLOSE
:
1139 return G711_StreamClose((PACMDRVSTREAMINSTANCE
)dwParam1
);
1141 case ACMDM_STREAM_SIZE
:
1142 return G711_StreamSize((PACMDRVSTREAMINSTANCE
)dwParam1
, (PACMDRVSTREAMSIZE
)dwParam2
);
1144 case ACMDM_STREAM_CONVERT
:
1145 return G711_StreamConvert((PACMDRVSTREAMINSTANCE
)dwParam1
, (PACMDRVSTREAMHEADER
)dwParam2
);
1147 case ACMDM_HARDWARE_WAVE_CAPS_INPUT
:
1148 case ACMDM_HARDWARE_WAVE_CAPS_OUTPUT
:
1149 /* this converter is not a hardware driver */
1150 case ACMDM_FILTERTAG_DETAILS
:
1151 case ACMDM_FILTER_DETAILS
:
1152 /* this converter is not a filter */
1153 case ACMDM_STREAM_RESET
:
1154 /* only needed for asynchronous driver... we aren't, so just say it */
1155 return MMSYSERR_NOTSUPPORTED
;
1156 case ACMDM_STREAM_PREPARE
:
1157 case ACMDM_STREAM_UNPREPARE
:
1158 /* nothing special to do here... so don't do anything */
1159 return MMSYSERR_NOERROR
;
1162 return DefDriverProc(dwDevID
, hDriv
, wMsg
, dwParam1
, dwParam2
);