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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 #include "../msacmdrv.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(g711);
35 /***********************************************************************
38 static DWORD G711_drvOpen(LPCSTR str)
43 /***********************************************************************
46 static DWORD G711_drvClose(DWORD dwDevID)
51 typedef struct tagAcmG711Data
53 void (*convert)(PACMDRVSTREAMINSTANCE adsi,
54 const unsigned char*, LPDWORD, unsigned char*, LPDWORD);
57 /* table to list all supported formats... those are the basic ones. this
58 * also helps given a unique index to each of the supported formats
67 static Format PCM_Formats[] =
69 /*{1, 8, 8000}, {2, 8, 8000}, */{1, 16, 8000}, {2, 16, 8000},
70 /*{1, 8, 11025}, {2, 8, 11025}, */{1, 16, 11025}, {2, 16, 11025},
71 /*{1, 8, 22050}, {2, 8, 22050}, */{1, 16, 22050}, {2, 16, 22050},
72 /*{1, 8, 44100}, {2, 8, 44100}, */{1, 16, 44100}, {2, 16, 44100},
75 static Format ALaw_Formats[] =
77 {1, 8, 8000}, {2, 8, 8000}, {1, 8, 11025}, {2, 8, 11025},
78 {1, 8, 22050}, {2, 8, 22050}, {1, 8, 44100}, {2, 8, 44100},
81 static Format ULaw_Formats[] =
83 {1, 8, 8000}, {2, 8, 8000}, {1, 8, 11025}, {2, 8, 11025},
84 {1, 8, 22050}, {2, 8, 22050}, {1, 8, 44100}, {2, 8, 44100},
87 #define NUM_PCM_FORMATS (sizeof(PCM_Formats) / sizeof(PCM_Formats[0]))
88 #define NUM_ALAW_FORMATS (sizeof(ALaw_Formats) / sizeof(ALaw_Formats[0]))
89 #define NUM_ULAW_FORMATS (sizeof(ULaw_Formats) / sizeof(ULaw_Formats[0]))
91 /***********************************************************************
94 static DWORD G711_GetFormatIndex(LPWAVEFORMATEX wfx)
99 switch (wfx->wFormatTag)
101 case WAVE_FORMAT_PCM:
102 hi = NUM_PCM_FORMATS;
105 case WAVE_FORMAT_ALAW:
106 hi = NUM_ALAW_FORMATS;
109 case WAVE_FORMAT_MULAW:
110 hi = NUM_ULAW_FORMATS;
117 for (i = 0; i < hi; i++)
119 if (wfx->nChannels == fmts[i].nChannels &&
120 wfx->nSamplesPerSec == fmts[i].rate &&
121 wfx->wBitsPerSample == fmts[i].nBits)
128 /***********************************************************************
131 * Read a 16 bit sample (correctly handles endianess)
133 static inline short R16(const unsigned char* src)
135 return (short)((unsigned short)src[0] | ((unsigned short)src[1] << 8));
138 /***********************************************************************
141 * Write a 16 bit sample (correctly handles endianess)
143 static inline void W16(unsigned char* dst, short s)
149 /* You can uncomment this if you don't want the statically generated conversion
150 * table, but rather recompute the Xlaw => PCM conversion for each sample
151 #define NO_FASTDECODE
152 * Since the conversion tables are rather small (2k), I don't think it's really
153 * interesting not to use them, but keeping the actual conversion code around
154 * is helpful to regenerate the tables when needed.
157 /* -------------------------------------------------------------------------------*/
160 * This source code is a product of Sun Microsystems, Inc. and is provided
161 * for unrestricted use. Users may copy or modify this source code without
164 * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
165 * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
166 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
168 * Sun source code is provided with no support and without any obligation on
169 * the part of Sun Microsystems, Inc. to assist in its use, correction,
170 * modification or enhancement.
172 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
173 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
174 * OR ANY PART THEREOF.
176 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
177 * or profits or other special, indirect and consequential damages, even if
178 * Sun has been advised of the possibility of such damages.
180 * Sun Microsystems, Inc.
182 * Mountain View, California 94043
188 * u-law, A-law and linear PCM conversions.
193 * Functions linear2alaw, linear2ulaw have been updated to correctly
194 * convert unquantized 16 bit values.
195 * Tables for direct u- to A-law and A- to u-law conversions have been
197 * Borge Lindberg, Center for PersonKommunikation, Aalborg University.
202 #define SIGN_BIT (0x80) /* Sign bit for a A-law byte. */
203 #define QUANT_MASK (0xf) /* Quantization field mask. */
204 #define NSEGS (8) /* Number of A-law segments. */
205 #define SEG_SHIFT (4) /* Left shift for segment number. */
206 #define SEG_MASK (0x70) /* Segment field mask. */
208 static short seg_aend[8] = {0x1F, 0x3F, 0x7F, 0xFF,
209 0x1FF, 0x3FF, 0x7FF, 0xFFF};
210 static short seg_uend[8] = {0x3F, 0x7F, 0xFF, 0x1FF,
211 0x3FF, 0x7FF, 0xFFF, 0x1FFF};
213 /* copy from CCITT G.711 specifications */
214 static unsigned char _u2a[128] = { /* u- to A-law conversions */
215 1, 1, 2, 2, 3, 3, 4, 4,
216 5, 5, 6, 6, 7, 7, 8, 8,
217 9, 10, 11, 12, 13, 14, 15, 16,
218 17, 18, 19, 20, 21, 22, 23, 24,
219 25, 27, 29, 31, 33, 34, 35, 36,
220 37, 38, 39, 40, 41, 42, 43, 44,
221 46, 48, 49, 50, 51, 52, 53, 54,
222 55, 56, 57, 58, 59, 60, 61, 62,
223 64, 65, 66, 67, 68, 69, 70, 71,
224 72, 73, 74, 75, 76, 77, 78, 79,
226 81, 82, 83, 84, 85, 86, 87, 88,
228 80, 82, 83, 84, 85, 86, 87, 88,
229 89, 90, 91, 92, 93, 94, 95, 96,
230 97, 98, 99, 100, 101, 102, 103, 104,
231 105, 106, 107, 108, 109, 110, 111, 112,
232 113, 114, 115, 116, 117, 118, 119, 120,
233 121, 122, 123, 124, 125, 126, 127, 128};
235 static unsigned char _a2u[128] = { /* A- to u-law conversions */
236 1, 3, 5, 7, 9, 11, 13, 15,
237 16, 17, 18, 19, 20, 21, 22, 23,
238 24, 25, 26, 27, 28, 29, 30, 31,
239 32, 32, 33, 33, 34, 34, 35, 35,
240 36, 37, 38, 39, 40, 41, 42, 43,
241 44, 45, 46, 47, 48, 48, 49, 49,
242 50, 51, 52, 53, 54, 55, 56, 57,
243 58, 59, 60, 61, 62, 63, 64, 64,
244 65, 66, 67, 68, 69, 70, 71, 72,
246 73, 74, 75, 76, 77, 78, 79, 79,
248 73, 74, 75, 76, 77, 78, 79, 80,
250 80, 81, 82, 83, 84, 85, 86, 87,
251 88, 89, 90, 91, 92, 93, 94, 95,
252 96, 97, 98, 99, 100, 101, 102, 103,
253 104, 105, 106, 107, 108, 109, 110, 111,
254 112, 113, 114, 115, 116, 117, 118, 119,
255 120, 121, 122, 123, 124, 125, 126, 127};
259 int val, /* changed from "short" *drago* */
261 int size) /* changed from "short" *drago* */
263 int i; /* changed from "short" *drago* */
265 for (i = 0; i < size; i++) {
273 * linear2alaw() - Convert a 16-bit linear PCM value to 8-bit A-law
275 * linear2alaw() accepts an 16-bit integer and encodes it as A-law data.
277 * Linear Input Code Compressed Code
278 * ------------------------ ---------------
279 * 0000000wxyza 000wxyz
280 * 0000001wxyza 001wxyz
281 * 000001wxyzab 010wxyz
282 * 00001wxyzabc 011wxyz
283 * 0001wxyzabcd 100wxyz
284 * 001wxyzabcde 101wxyz
285 * 01wxyzabcdef 110wxyz
286 * 1wxyzabcdefg 111wxyz
288 * For further information see John C. Bellamy's Digital Telephony, 1982,
289 * John Wiley & Sons, pps 98-111 and 472-476.
291 static inline unsigned char
292 linear2alaw(int pcm_val) /* 2's complement (16-bit range) */
293 /* changed from "short" *drago* */
295 int mask; /* changed from "short" *drago* */
296 int seg; /* changed from "short" *drago* */
299 pcm_val = pcm_val >> 3;
302 mask = 0xD5; /* sign (7th) bit = 1 */
304 mask = 0x55; /* sign bit = 0 */
305 pcm_val = -pcm_val - 1;
308 /* Convert the scaled magnitude to segment number. */
309 seg = search(pcm_val, seg_aend, 8);
311 /* Combine the sign, segment, and quantization bits. */
313 if (seg >= 8) /* out of range, return maximum value. */
314 return (unsigned char) (0x7F ^ mask);
316 aval = (unsigned char) seg << SEG_SHIFT;
318 aval |= (pcm_val >> 1) & QUANT_MASK;
320 aval |= (pcm_val >> seg) & QUANT_MASK;
321 return (aval ^ mask);
327 * alaw2linear() - Convert an A-law value to 16-bit linear PCM
331 alaw2linear(unsigned char a_val)
333 int t; /* changed from "short" *drago* */
334 int seg; /* changed from "short" *drago* */
338 t = (a_val & QUANT_MASK) << 4;
339 seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT;
351 return ((a_val & SIGN_BIT) ? t : -t);
355 * this array has been statically generated from the above routine
357 static unsigned short _a2l[] = {
358 0xEA80, 0xEB80, 0xE880, 0xE980, 0xEE80, 0xEF80, 0xEC80, 0xED80,
359 0xE280, 0xE380, 0xE080, 0xE180, 0xE680, 0xE780, 0xE480, 0xE580,
360 0xF540, 0xF5C0, 0xF440, 0xF4C0, 0xF740, 0xF7C0, 0xF640, 0xF6C0,
361 0xF140, 0xF1C0, 0xF040, 0xF0C0, 0xF340, 0xF3C0, 0xF240, 0xF2C0,
362 0xAA00, 0xAE00, 0xA200, 0xA600, 0xBA00, 0xBE00, 0xB200, 0xB600,
363 0x8A00, 0x8E00, 0x8200, 0x8600, 0x9A00, 0x9E00, 0x9200, 0x9600,
364 0xD500, 0xD700, 0xD100, 0xD300, 0xDD00, 0xDF00, 0xD900, 0xDB00,
365 0xC500, 0xC700, 0xC100, 0xC300, 0xCD00, 0xCF00, 0xC900, 0xCB00,
366 0xFEA8, 0xFEB8, 0xFE88, 0xFE98, 0xFEE8, 0xFEF8, 0xFEC8, 0xFED8,
367 0xFE28, 0xFE38, 0xFE08, 0xFE18, 0xFE68, 0xFE78, 0xFE48, 0xFE58,
368 0xFFA8, 0xFFB8, 0xFF88, 0xFF98, 0xFFE8, 0xFFF8, 0xFFC8, 0xFFD8,
369 0xFF28, 0xFF38, 0xFF08, 0xFF18, 0xFF68, 0xFF78, 0xFF48, 0xFF58,
370 0xFAA0, 0xFAE0, 0xFA20, 0xFA60, 0xFBA0, 0xFBE0, 0xFB20, 0xFB60,
371 0xF8A0, 0xF8E0, 0xF820, 0xF860, 0xF9A0, 0xF9E0, 0xF920, 0xF960,
372 0xFD50, 0xFD70, 0xFD10, 0xFD30, 0xFDD0, 0xFDF0, 0xFD90, 0xFDB0,
373 0xFC50, 0xFC70, 0xFC10, 0xFC30, 0xFCD0, 0xFCF0, 0xFC90, 0xFCB0,
374 0x1580, 0x1480, 0x1780, 0x1680, 0x1180, 0x1080, 0x1380, 0x1280,
375 0x1D80, 0x1C80, 0x1F80, 0x1E80, 0x1980, 0x1880, 0x1B80, 0x1A80,
376 0x0AC0, 0x0A40, 0x0BC0, 0x0B40, 0x08C0, 0x0840, 0x09C0, 0x0940,
377 0x0EC0, 0x0E40, 0x0FC0, 0x0F40, 0x0CC0, 0x0C40, 0x0DC0, 0x0D40,
378 0x5600, 0x5200, 0x5E00, 0x5A00, 0x4600, 0x4200, 0x4E00, 0x4A00,
379 0x7600, 0x7200, 0x7E00, 0x7A00, 0x6600, 0x6200, 0x6E00, 0x6A00,
380 0x2B00, 0x2900, 0x2F00, 0x2D00, 0x2300, 0x2100, 0x2700, 0x2500,
381 0x3B00, 0x3900, 0x3F00, 0x3D00, 0x3300, 0x3100, 0x3700, 0x3500,
382 0x0158, 0x0148, 0x0178, 0x0168, 0x0118, 0x0108, 0x0138, 0x0128,
383 0x01D8, 0x01C8, 0x01F8, 0x01E8, 0x0198, 0x0188, 0x01B8, 0x01A8,
384 0x0058, 0x0048, 0x0078, 0x0068, 0x0018, 0x0008, 0x0038, 0x0028,
385 0x00D8, 0x00C8, 0x00F8, 0x00E8, 0x0098, 0x0088, 0x00B8, 0x00A8,
386 0x0560, 0x0520, 0x05E0, 0x05A0, 0x0460, 0x0420, 0x04E0, 0x04A0,
387 0x0760, 0x0720, 0x07E0, 0x07A0, 0x0660, 0x0620, 0x06E0, 0x06A0,
388 0x02B0, 0x0290, 0x02F0, 0x02D0, 0x0230, 0x0210, 0x0270, 0x0250,
389 0x03B0, 0x0390, 0x03F0, 0x03D0, 0x0330, 0x0310, 0x0370, 0x0350,
392 alaw2linear(unsigned char a_val)
394 return (short)_a2l[a_val];
398 #define BIAS (0x84) /* Bias for linear code. */
402 * linear2ulaw() - Convert a linear PCM value to u-law
404 * In order to simplify the encoding process, the original linear magnitude
405 * is biased by adding 33 which shifts the encoding range from (0 - 8158) to
406 * (33 - 8191). The result can be seen in the following encoding table:
408 * Biased Linear Input Code Compressed Code
409 * ------------------------ ---------------
410 * 00000001wxyza 000wxyz
411 * 0000001wxyzab 001wxyz
412 * 000001wxyzabc 010wxyz
413 * 00001wxyzabcd 011wxyz
414 * 0001wxyzabcde 100wxyz
415 * 001wxyzabcdef 101wxyz
416 * 01wxyzabcdefg 110wxyz
417 * 1wxyzabcdefgh 111wxyz
419 * Each biased linear code has a leading 1 which identifies the segment
420 * number. The value of the segment number is equal to 7 minus the number
421 * of leading 0's. The quantization interval is directly available as the
422 * four bits wxyz. * The trailing bits (a - h) are ignored.
424 * Ordinarily the complement of the resulting code word is used for
425 * transmission, and so the code word is complemented before it is returned.
427 * For further information see John C. Bellamy's Digital Telephony, 1982,
428 * John Wiley & Sons, pps 98-111 and 472-476.
430 static inline unsigned char
431 linear2ulaw(short pcm_val) /* 2's complement (16-bit range) */
437 /* Get the sign and the magnitude of the value. */
438 pcm_val = pcm_val >> 2;
445 if ( pcm_val > CLIP ) pcm_val = CLIP; /* clip the magnitude */
446 pcm_val += (BIAS >> 2);
448 /* Convert the scaled magnitude to segment number. */
449 seg = search(pcm_val, seg_uend, 8);
452 * Combine the sign, segment, quantization bits;
453 * and complement the code word.
455 if (seg >= 8) /* out of range, return maximum value. */
456 return (unsigned char) (0x7F ^ mask);
458 uval = (unsigned char) (seg << 4) | ((pcm_val >> (seg + 1)) & 0xF);
459 return (uval ^ mask);
465 * ulaw2linear() - Convert a u-law value to 16-bit linear PCM
467 * First, a biased linear code is derived from the code word. An unbiased
468 * output can then be obtained by subtracting 33 from the biased code.
470 * Note that this function expects to be passed the complement of the
471 * original code word. This is in keeping with ISDN conventions.
474 ulaw2linear(unsigned char u_val)
478 /* Complement to obtain normal u-law value. */
482 * Extract and bias the quantization bits. Then
483 * shift up by the segment number and subtract out the bias.
485 t = ((u_val & QUANT_MASK) << 3) + BIAS;
486 t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT;
488 return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS));
492 * this array has been statically generated from the above routine
494 static unsigned short _u2l[] = {
495 0x8284, 0x8684, 0x8A84, 0x8E84, 0x9284, 0x9684, 0x9A84, 0x9E84,
496 0xA284, 0xA684, 0xAA84, 0xAE84, 0xB284, 0xB684, 0xBA84, 0xBE84,
497 0xC184, 0xC384, 0xC584, 0xC784, 0xC984, 0xCB84, 0xCD84, 0xCF84,
498 0xD184, 0xD384, 0xD584, 0xD784, 0xD984, 0xDB84, 0xDD84, 0xDF84,
499 0xE104, 0xE204, 0xE304, 0xE404, 0xE504, 0xE604, 0xE704, 0xE804,
500 0xE904, 0xEA04, 0xEB04, 0xEC04, 0xED04, 0xEE04, 0xEF04, 0xF004,
501 0xF0C4, 0xF144, 0xF1C4, 0xF244, 0xF2C4, 0xF344, 0xF3C4, 0xF444,
502 0xF4C4, 0xF544, 0xF5C4, 0xF644, 0xF6C4, 0xF744, 0xF7C4, 0xF844,
503 0xF8A4, 0xF8E4, 0xF924, 0xF964, 0xF9A4, 0xF9E4, 0xFA24, 0xFA64,
504 0xFAA4, 0xFAE4, 0xFB24, 0xFB64, 0xFBA4, 0xFBE4, 0xFC24, 0xFC64,
505 0xFC94, 0xFCB4, 0xFCD4, 0xFCF4, 0xFD14, 0xFD34, 0xFD54, 0xFD74,
506 0xFD94, 0xFDB4, 0xFDD4, 0xFDF4, 0xFE14, 0xFE34, 0xFE54, 0xFE74,
507 0xFE8C, 0xFE9C, 0xFEAC, 0xFEBC, 0xFECC, 0xFEDC, 0xFEEC, 0xFEFC,
508 0xFF0C, 0xFF1C, 0xFF2C, 0xFF3C, 0xFF4C, 0xFF5C, 0xFF6C, 0xFF7C,
509 0xFF88, 0xFF90, 0xFF98, 0xFFA0, 0xFFA8, 0xFFB0, 0xFFB8, 0xFFC0,
510 0xFFC8, 0xFFD0, 0xFFD8, 0xFFE0, 0xFFE8, 0xFFF0, 0xFFF8, 0x0000,
511 0x7D7C, 0x797C, 0x757C, 0x717C, 0x6D7C, 0x697C, 0x657C, 0x617C,
512 0x5D7C, 0x597C, 0x557C, 0x517C, 0x4D7C, 0x497C, 0x457C, 0x417C,
513 0x3E7C, 0x3C7C, 0x3A7C, 0x387C, 0x367C, 0x347C, 0x327C, 0x307C,
514 0x2E7C, 0x2C7C, 0x2A7C, 0x287C, 0x267C, 0x247C, 0x227C, 0x207C,
515 0x1EFC, 0x1DFC, 0x1CFC, 0x1BFC, 0x1AFC, 0x19FC, 0x18FC, 0x17FC,
516 0x16FC, 0x15FC, 0x14FC, 0x13FC, 0x12FC, 0x11FC, 0x10FC, 0x0FFC,
517 0x0F3C, 0x0EBC, 0x0E3C, 0x0DBC, 0x0D3C, 0x0CBC, 0x0C3C, 0x0BBC,
518 0x0B3C, 0x0ABC, 0x0A3C, 0x09BC, 0x093C, 0x08BC, 0x083C, 0x07BC,
519 0x075C, 0x071C, 0x06DC, 0x069C, 0x065C, 0x061C, 0x05DC, 0x059C,
520 0x055C, 0x051C, 0x04DC, 0x049C, 0x045C, 0x041C, 0x03DC, 0x039C,
521 0x036C, 0x034C, 0x032C, 0x030C, 0x02EC, 0x02CC, 0x02AC, 0x028C,
522 0x026C, 0x024C, 0x022C, 0x020C, 0x01EC, 0x01CC, 0x01AC, 0x018C,
523 0x0174, 0x0164, 0x0154, 0x0144, 0x0134, 0x0124, 0x0114, 0x0104,
524 0x00F4, 0x00E4, 0x00D4, 0x00C4, 0x00B4, 0x00A4, 0x0094, 0x0084,
525 0x0078, 0x0070, 0x0068, 0x0060, 0x0058, 0x0050, 0x0048, 0x0040,
526 0x0038, 0x0030, 0x0028, 0x0020, 0x0018, 0x0010, 0x0008, 0x0000,
528 static inline short ulaw2linear(unsigned char u_val)
530 return (short)_u2l[u_val];
534 /* A-law to u-law conversion */
535 static inline unsigned char
536 alaw2ulaw(unsigned char aval)
539 return (unsigned char) ((aval & 0x80) ? (0xFF ^ _a2u[aval ^ 0xD5]) :
540 (0x7F ^ _a2u[aval ^ 0x55]));
543 /* u-law to A-law conversion */
544 static inline unsigned char
545 ulaw2alaw(unsigned char uval)
548 return (unsigned char) ((uval & 0x80) ? (0xD5 ^ (_u2a[0xFF ^ uval] - 1)) :
549 (unsigned char) (0x55 ^ (_u2a[0x7F ^ uval] - 1)));
552 /* -------------------------------------------------------------------------------*/
554 static void cvtXXalaw16K(PACMDRVSTREAMINSTANCE adsi,
555 const unsigned char* src, LPDWORD srcsize,
556 unsigned char* dst, LPDWORD dstsize)
558 DWORD len = min(*srcsize, *dstsize / 2);
564 for (i = 0; i < len; i++)
566 w = alaw2linear(*src++);
567 W16(dst, w); dst += 2;
571 static void cvtXX16alawK(PACMDRVSTREAMINSTANCE adsi,
572 const unsigned char* src, LPDWORD srcsize,
573 unsigned char* dst, LPDWORD dstsize)
575 DWORD len = min(*srcsize / 2, *dstsize);
580 for (i = 0; i < len; i++)
582 *dst++ = linear2alaw(R16(src)); src += 2;
586 static void cvtXXulaw16K(PACMDRVSTREAMINSTANCE adsi,
587 const unsigned char* src, LPDWORD srcsize,
588 unsigned char* dst, LPDWORD dstsize)
590 DWORD len = min(*srcsize, *dstsize / 2);
596 for (i = 0; i < len; i++)
598 w = ulaw2linear(*src++);
599 W16(dst, w); dst += 2;
603 static void cvtXX16ulawK(PACMDRVSTREAMINSTANCE adsi,
604 const unsigned char* src, LPDWORD srcsize,
605 unsigned char* dst, LPDWORD dstsize)
607 DWORD len = min(*srcsize / 2, *dstsize);
612 for (i = 0; i < len; i++)
614 *dst++ = linear2ulaw(R16(src)); src += 2;
618 static void cvtXXalawulawK(PACMDRVSTREAMINSTANCE adsi,
619 const unsigned char* src, LPDWORD srcsize,
620 unsigned char* dst, LPDWORD dstsize)
622 DWORD len = min(*srcsize, *dstsize);
628 for (i = 0; i < len; i++)
629 *dst++ = alaw2ulaw(*src++);
633 static void cvtXXulawalawK(PACMDRVSTREAMINSTANCE adsi,
634 const unsigned char* src, LPDWORD srcsize,
635 unsigned char* dst, LPDWORD dstsize)
637 DWORD len = min(*srcsize, *dstsize);
643 for (i = 0; i < len; i++)
644 *dst++ = ulaw2alaw(*src++);
647 /***********************************************************************
651 static LRESULT G711_DriverDetails(PACMDRIVERDETAILSW add)
653 add->fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC;
654 add->fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED;
657 add->vdwACM = 0x01000000;
658 add->vdwDriver = 0x01000000;
659 add->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
660 add->cFormatTags = 3; /* PCM, G711 A-LAW & MU-LAW */
661 add->cFilterTags = 0;
663 MultiByteToWideChar( CP_ACP, 0, "WINE-G711", -1,
664 add->szShortName, sizeof(add->szShortName)/sizeof(WCHAR) );
665 MultiByteToWideChar( CP_ACP, 0, "Wine G711 converter", -1,
666 add->szLongName, sizeof(add->szLongName)/sizeof(WCHAR) );
667 MultiByteToWideChar( CP_ACP, 0, "Brought to you by the Wine team...", -1,
668 add->szCopyright, sizeof(add->szCopyright)/sizeof(WCHAR) );
669 MultiByteToWideChar( CP_ACP, 0, "Refer to LICENSE file", -1,
670 add->szLicensing, sizeof(add->szLicensing)/sizeof(WCHAR) );
671 add->szFeatures[0] = 0;
673 return MMSYSERR_NOERROR;
676 /***********************************************************************
677 * G711_FormatTagDetails
680 static LRESULT G711_FormatTagDetails(PACMFORMATTAGDETAILSW aftd, DWORD dwQuery)
682 static WCHAR szPcm[]={'P','C','M',0};
683 static WCHAR szALaw[]={'A','-','L','a','w',0};
684 static WCHAR szULaw[]={'U','-','L','a','w',0};
688 case ACM_FORMATTAGDETAILSF_INDEX:
689 if (aftd->dwFormatTagIndex >= 3) return ACMERR_NOTPOSSIBLE;
691 case ACM_FORMATTAGDETAILSF_LARGESTSIZE:
692 if (aftd->dwFormatTag == WAVE_FORMAT_UNKNOWN)
694 aftd->dwFormatTagIndex = 1;
698 case ACM_FORMATTAGDETAILSF_FORMATTAG:
699 switch (aftd->dwFormatTag)
701 case WAVE_FORMAT_PCM: aftd->dwFormatTagIndex = 0; break;
702 case WAVE_FORMAT_ALAW: aftd->dwFormatTagIndex = 1; break;
703 case WAVE_FORMAT_MULAW: aftd->dwFormatTagIndex = 2; break;
704 default: return ACMERR_NOTPOSSIBLE;
708 WARN("Unsupported query %08lx\n", dwQuery);
709 return MMSYSERR_NOTSUPPORTED;
712 aftd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
713 switch (aftd->dwFormatTagIndex)
716 aftd->dwFormatTag = WAVE_FORMAT_PCM;
717 aftd->cbFormatSize = sizeof(PCMWAVEFORMAT);
718 aftd->cStandardFormats = NUM_PCM_FORMATS;
719 lstrcpyW(aftd->szFormatTag, szPcm);
722 aftd->dwFormatTag = WAVE_FORMAT_ALAW;
723 aftd->cbFormatSize = sizeof(WAVEFORMATEX);
724 aftd->cStandardFormats = NUM_ALAW_FORMATS;
725 lstrcpyW(aftd->szFormatTag, szALaw);
728 aftd->dwFormatTag = WAVE_FORMAT_MULAW;
729 aftd->cbFormatSize = sizeof(WAVEFORMATEX);
730 aftd->cStandardFormats = NUM_ULAW_FORMATS;
731 lstrcpyW(aftd->szFormatTag, szULaw);
734 return MMSYSERR_NOERROR;
737 /***********************************************************************
741 static LRESULT G711_FormatDetails(PACMFORMATDETAILSW afd, DWORD dwQuery)
745 case ACM_FORMATDETAILSF_FORMAT:
746 if (G711_GetFormatIndex(afd->pwfx) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
748 case ACM_FORMATDETAILSF_INDEX:
749 afd->pwfx->wFormatTag = afd->dwFormatTag;
750 switch (afd->dwFormatTag)
752 case WAVE_FORMAT_PCM:
753 if (afd->dwFormatIndex >= NUM_PCM_FORMATS) return ACMERR_NOTPOSSIBLE;
754 afd->pwfx->nChannels = PCM_Formats[afd->dwFormatIndex].nChannels;
755 afd->pwfx->nSamplesPerSec = PCM_Formats[afd->dwFormatIndex].rate;
756 afd->pwfx->wBitsPerSample = PCM_Formats[afd->dwFormatIndex].nBits;
757 afd->pwfx->nBlockAlign = afd->pwfx->nChannels * 2;
758 afd->pwfx->nAvgBytesPerSec = afd->pwfx->nSamplesPerSec * afd->pwfx->nBlockAlign;
760 case WAVE_FORMAT_ALAW:
761 if (afd->dwFormatIndex >= NUM_ALAW_FORMATS) return ACMERR_NOTPOSSIBLE;
762 afd->pwfx->nChannels = ALaw_Formats[afd->dwFormatIndex].nChannels;
763 afd->pwfx->nSamplesPerSec = ALaw_Formats[afd->dwFormatIndex].rate;
764 afd->pwfx->wBitsPerSample = ALaw_Formats[afd->dwFormatIndex].nBits;
765 afd->pwfx->nBlockAlign = ALaw_Formats[afd->dwFormatIndex].nChannels;
766 afd->pwfx->nAvgBytesPerSec = afd->pwfx->nSamplesPerSec * afd->pwfx->nChannels;
767 afd->pwfx->cbSize = 0;
769 case WAVE_FORMAT_MULAW:
770 if (afd->dwFormatIndex >= NUM_ULAW_FORMATS) return ACMERR_NOTPOSSIBLE;
771 afd->pwfx->nChannels = ULaw_Formats[afd->dwFormatIndex].nChannels;
772 afd->pwfx->nSamplesPerSec = ULaw_Formats[afd->dwFormatIndex].rate;
773 afd->pwfx->wBitsPerSample = ULaw_Formats[afd->dwFormatIndex].nBits;
774 afd->pwfx->nBlockAlign = ULaw_Formats[afd->dwFormatIndex].nChannels;
775 afd->pwfx->nAvgBytesPerSec = afd->pwfx->nSamplesPerSec * afd->pwfx->nChannels;
776 afd->pwfx->cbSize = 0;
779 WARN("Unsupported tag %08lx\n", afd->dwFormatTag);
780 return MMSYSERR_INVALPARAM;
784 WARN("Unsupported query %08lx\n", dwQuery);
785 return MMSYSERR_NOTSUPPORTED;
787 afd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
788 afd->szFormat[0] = 0; /* let MSACM format this for us... */
790 return MMSYSERR_NOERROR;
793 /***********************************************************************
797 static LRESULT G711_FormatSuggest(PACMDRVFORMATSUGGEST adfs)
800 if (adfs->cbwfxSrc < sizeof(PCMWAVEFORMAT) ||
801 adfs->cbwfxDst < sizeof(PCMWAVEFORMAT) ||
802 G711_GetFormatIndex(adfs->pwfxSrc) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
803 /* FIXME: should do those tests against the real size (according to format tag */
805 /* If no suggestion for destination, then copy source value */
806 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NCHANNELS))
807 adfs->pwfxDst->nChannels = adfs->pwfxSrc->nChannels;
808 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NSAMPLESPERSEC))
809 adfs->pwfxDst->nSamplesPerSec = adfs->pwfxSrc->nSamplesPerSec;
811 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WBITSPERSAMPLE))
813 if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM)
814 adfs->pwfxDst->wBitsPerSample = 8;
816 adfs->pwfxDst->wBitsPerSample = 16;
818 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG))
820 switch (adfs->pwfxSrc->wFormatTag)
822 case WAVE_FORMAT_PCM: adfs->pwfxDst->wFormatTag = WAVE_FORMAT_ALAW; break;
823 case WAVE_FORMAT_ALAW: adfs->pwfxDst->wFormatTag = WAVE_FORMAT_PCM; break;
824 case WAVE_FORMAT_MULAW: adfs->pwfxDst->wFormatTag = WAVE_FORMAT_PCM; break;
827 /* check if result is ok */
828 if (G711_GetFormatIndex(adfs->pwfxDst) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
830 /* recompute other values */
831 switch (adfs->pwfxDst->wFormatTag)
833 case WAVE_FORMAT_PCM:
834 adfs->pwfxDst->nBlockAlign = adfs->pwfxDst->nChannels;
835 adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * adfs->pwfxDst->nBlockAlign;
837 case WAVE_FORMAT_ALAW:
838 adfs->pwfxDst->nBlockAlign = adfs->pwfxDst->nChannels * 2;
839 adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * adfs->pwfxSrc->nChannels * 2;
841 case WAVE_FORMAT_MULAW:
842 adfs->pwfxDst->nBlockAlign = adfs->pwfxDst->nChannels * 2;
843 adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * adfs->pwfxSrc->nChannels * 2;
850 return MMSYSERR_NOERROR;
853 /***********************************************************************
857 static void G711_Reset(PACMDRVSTREAMINSTANCE adsi, AcmG711Data* aad)
861 /***********************************************************************
865 static LRESULT G711_StreamOpen(PACMDRVSTREAMINSTANCE adsi)
869 assert(!(adsi->fdwOpen & ACM_STREAMOPENF_ASYNC));
871 if (G711_GetFormatIndex(adsi->pwfxSrc) == 0xFFFFFFFF ||
872 G711_GetFormatIndex(adsi->pwfxDst) == 0xFFFFFFFF)
873 return ACMERR_NOTPOSSIBLE;
875 aad = HeapAlloc(GetProcessHeap(), 0, sizeof(AcmG711Data));
876 if (aad == 0) return MMSYSERR_NOMEM;
878 adsi->dwDriver = (DWORD)aad;
880 if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
881 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
885 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ALAW &&
886 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
888 /* resampling or mono <=> stereo not available
889 * G711 algo only define 16 bit per sample output
891 if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
892 adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
893 adsi->pwfxDst->wBitsPerSample != 16)
896 /* g711 A-Law decoding... */
897 if (adsi->pwfxDst->wBitsPerSample == 16)
898 aad->convert = cvtXXalaw16K;
900 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
901 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ALAW)
903 if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
904 adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
905 adsi->pwfxSrc->wBitsPerSample != 16)
909 if (adsi->pwfxSrc->wBitsPerSample == 16)
910 aad->convert = cvtXX16alawK;
912 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MULAW &&
913 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
915 /* resampling or mono <=> stereo not available
916 * G711 algo only define 16 bit per sample output
918 if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
919 adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
920 adsi->pwfxDst->wBitsPerSample != 16)
923 /* g711 MU-Law decoding... */
924 if (adsi->pwfxDst->wBitsPerSample == 16)
925 aad->convert = cvtXXulaw16K;
927 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
928 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ALAW)
930 if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
931 adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
932 adsi->pwfxSrc->wBitsPerSample != 16)
936 if (adsi->pwfxSrc->wBitsPerSample == 16)
937 aad->convert = cvtXX16ulawK;
939 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MULAW &&
940 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ALAW)
942 if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
943 adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels)
946 /* MU-Law => A-Law... */
947 aad->convert = cvtXXulawalawK;
949 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ALAW &&
950 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MULAW)
952 if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
953 adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels)
956 /* A-Law => MU-Law... */
957 aad->convert = cvtXXalawulawK;
961 G711_Reset(adsi, aad);
963 return MMSYSERR_NOERROR;
966 HeapFree(GetProcessHeap(), 0, aad);
968 return MMSYSERR_NOTSUPPORTED;
971 /***********************************************************************
975 static LRESULT G711_StreamClose(PACMDRVSTREAMINSTANCE adsi)
977 HeapFree(GetProcessHeap(), 0, (void*)adsi->dwDriver);
978 return MMSYSERR_NOERROR;
981 /***********************************************************************
985 static inline DWORD G711_round(DWORD a, DWORD b, DWORD c)
988 /* to be sure, always return an entire number of c... */
989 return ((double)a * (double)b + (double)c - 1) / (double)c;
992 /***********************************************************************
996 static LRESULT G711_StreamSize(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMSIZE adss)
998 switch (adss->fdwSize)
1000 case ACM_STREAMSIZEF_DESTINATION:
1001 /* cbDstLength => cbSrcLength */
1002 if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
1003 (adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ALAW ||
1004 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MULAW))
1006 adss->cbSrcLength = adss->cbDstLength / 2;
1008 else if ((adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ALAW ||
1009 adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MULAW) &&
1010 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
1012 adss->cbSrcLength = adss->cbDstLength * 2;
1014 else if ((adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ALAW ||
1015 adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MULAW) &&
1016 (adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ALAW ||
1017 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MULAW))
1019 adss->cbSrcLength = adss->cbDstLength;
1023 return MMSYSERR_NOTSUPPORTED;
1026 case ACM_STREAMSIZEF_SOURCE:
1027 /* cbSrcLength => cbDstLength */
1028 if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
1029 (adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ALAW ||
1030 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MULAW))
1032 adss->cbDstLength = adss->cbSrcLength * 2;
1034 else if ((adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ALAW ||
1035 adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MULAW) &&
1036 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
1038 adss->cbDstLength = adss->cbSrcLength / 2;
1040 else if ((adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ALAW ||
1041 adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MULAW) &&
1042 (adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ALAW ||
1043 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MULAW))
1045 adss->cbDstLength = adss->cbSrcLength;
1049 return MMSYSERR_NOTSUPPORTED;
1053 WARN("Unsupported query %08lx\n", adss->fdwSize);
1054 return MMSYSERR_NOTSUPPORTED;
1057 return MMSYSERR_NOERROR;
1060 /***********************************************************************
1061 * G711_StreamConvert
1064 static LRESULT G711_StreamConvert(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMHEADER adsh)
1066 AcmG711Data* aad = (AcmG711Data*)adsi->dwDriver;
1067 DWORD nsrc = adsh->cbSrcLength;
1068 DWORD ndst = adsh->cbDstLength;
1070 if (adsh->fdwConvert &
1071 ~(ACM_STREAMCONVERTF_BLOCKALIGN|
1072 ACM_STREAMCONVERTF_END|
1073 ACM_STREAMCONVERTF_START))
1075 FIXME("Unsupported fdwConvert (%08lx), ignoring it\n", adsh->fdwConvert);
1077 /* ACM_STREAMCONVERTF_BLOCKALIGN
1078 * currently all conversions are block aligned, so do nothing for this flag
1079 * ACM_STREAMCONVERTF_END
1080 * no pending data, so do nothing for this flag
1082 if ((adsh->fdwConvert & ACM_STREAMCONVERTF_START))
1084 G711_Reset(adsi, aad);
1087 aad->convert(adsi, adsh->pbSrc, &nsrc, adsh->pbDst, &ndst);
1088 adsh->cbSrcLengthUsed = nsrc;
1089 adsh->cbDstLengthUsed = ndst;
1091 return MMSYSERR_NOERROR;
1094 /**************************************************************************
1095 * G711_DriverProc [exported]
1097 LRESULT CALLBACK G711_DriverProc(DWORD dwDevID, HDRVR hDriv, UINT wMsg,
1098 LPARAM dwParam1, LPARAM dwParam2)
1100 TRACE("(%08lx %08lx %04x %08lx %08lx);\n",
1101 dwDevID, (DWORD)hDriv, wMsg, dwParam1, dwParam2);
1105 case DRV_LOAD: return 1;
1106 case DRV_FREE: return 1;
1107 case DRV_OPEN: return G711_drvOpen((LPSTR)dwParam1);
1108 case DRV_CLOSE: return G711_drvClose(dwDevID);
1109 case DRV_ENABLE: return 1;
1110 case DRV_DISABLE: return 1;
1111 case DRV_QUERYCONFIGURE: return 1;
1112 case DRV_CONFIGURE: MessageBoxA(0, "MS G711 (a-Law & mu-Law) filter !", "Wine Driver", MB_OK); return 1;
1113 case DRV_INSTALL: return DRVCNF_RESTART;
1114 case DRV_REMOVE: return DRVCNF_RESTART;
1116 case ACMDM_DRIVER_NOTIFY:
1117 /* no caching from other ACM drivers is done so far */
1118 return MMSYSERR_NOERROR;
1120 case ACMDM_DRIVER_DETAILS:
1121 return G711_DriverDetails((PACMDRIVERDETAILSW)dwParam1);
1123 case ACMDM_FORMATTAG_DETAILS:
1124 return G711_FormatTagDetails((PACMFORMATTAGDETAILSW)dwParam1, dwParam2);
1126 case ACMDM_FORMAT_DETAILS:
1127 return G711_FormatDetails((PACMFORMATDETAILSW)dwParam1, dwParam2);
1129 case ACMDM_FORMAT_SUGGEST:
1130 return G711_FormatSuggest((PACMDRVFORMATSUGGEST)dwParam1);
1132 case ACMDM_STREAM_OPEN:
1133 return G711_StreamOpen((PACMDRVSTREAMINSTANCE)dwParam1);
1135 case ACMDM_STREAM_CLOSE:
1136 return G711_StreamClose((PACMDRVSTREAMINSTANCE)dwParam1);
1138 case ACMDM_STREAM_SIZE:
1139 return G711_StreamSize((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMSIZE)dwParam2);
1141 case ACMDM_STREAM_CONVERT:
1142 return G711_StreamConvert((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMHEADER)dwParam2);
1144 case ACMDM_HARDWARE_WAVE_CAPS_INPUT:
1145 case ACMDM_HARDWARE_WAVE_CAPS_OUTPUT:
1146 /* this converter is not a hardware driver */
1147 case ACMDM_FILTERTAG_DETAILS:
1148 case ACMDM_FILTER_DETAILS:
1149 /* this converter is not a filter */
1150 case ACMDM_STREAM_RESET:
1151 /* only needed for asynchronous driver... we aren't, so just say it */
1152 return MMSYSERR_NOTSUPPORTED;
1153 case ACMDM_STREAM_PREPARE:
1154 case ACMDM_STREAM_UNPREPARE:
1155 /* nothing special to do here... so don't do anything */
1156 return MMSYSERR_NOERROR;
1159 return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);