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