ok() does not support '%S'. Store the Ansi version, convert to Unicode
[wine] / dlls / msacm / msg711 / msg711.c
1 /*
2  * G711 handling (includes A-Law & MU-Law)
3  *
4  *      Copyright (C) 2002              Eric Pouech
5  *
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include <assert.h>
23 #include <string.h>
24 #include "winnls.h"
25 #include "winbase.h"
26 #include "wingdi.h"
27 #include "winuser.h"
28 #include "msacm.h"
29 #include "mmreg.h"
30 #include "../msacmdrv.h"
31 #include "wine/debug.h"
32
33 WINE_DEFAULT_DEBUG_CHANNEL(g711);
34
35 /***********************************************************************
36  *           G711_drvOpen
37  */
38 static  DWORD   G711_drvOpen(LPCSTR str)
39 {
40     return 1;
41 }
42
43 /***********************************************************************
44  *           G711_drvClose
45  */
46 static  DWORD   G711_drvClose(DWORD dwDevID)
47 {
48     return 1;
49 }
50
51 typedef struct tagAcmG711Data
52 {
53     void (*convert)(PACMDRVSTREAMINSTANCE adsi,
54                     const unsigned char*, LPDWORD, unsigned char*, LPDWORD);
55 } AcmG711Data;
56
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
59  */
60 typedef struct
61 {
62     int         nChannels;
63     int         nBits;
64     int         rate;
65 } Format;
66
67 static Format PCM_Formats[] =
68 {
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},
73 };
74
75 static Format ALaw_Formats[] =
76 {
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},
79 };
80
81 static Format ULaw_Formats[] =
82 {
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},
85 };
86
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]))
90
91 /***********************************************************************
92  *           G711_GetFormatIndex
93  */
94 static  DWORD   G711_GetFormatIndex(LPWAVEFORMATEX wfx)
95 {
96     int         i, hi;
97     Format*     fmts;
98
99     switch (wfx->wFormatTag)
100     {
101     case WAVE_FORMAT_PCM:
102         hi = NUM_PCM_FORMATS;
103         fmts = PCM_Formats;
104         break;
105     case WAVE_FORMAT_ALAW:
106         hi = NUM_ALAW_FORMATS;
107         fmts = ALaw_Formats;
108         break;
109     case WAVE_FORMAT_MULAW:
110         hi = NUM_ULAW_FORMATS;
111         fmts = ULaw_Formats;
112         break;
113     default:
114         return 0xFFFFFFFF;
115     }
116
117     for (i = 0; i < hi; i++)
118     {
119         if (wfx->nChannels == fmts[i].nChannels &&
120             wfx->nSamplesPerSec == fmts[i].rate &&
121             wfx->wBitsPerSample == fmts[i].nBits)
122             return i;
123     }
124
125     return 0xFFFFFFFF;
126 }
127
128 /***********************************************************************
129  *           R16
130  *
131  * Read a 16 bit sample (correctly handles endianess)
132  */
133 static inline short  R16(const unsigned char* src)
134 {
135     return (short)((unsigned short)src[0] | ((unsigned short)src[1] << 8));
136 }
137
138 /***********************************************************************
139  *           W16
140  *
141  * Write a 16 bit sample (correctly handles endianess)
142  */
143 static inline void  W16(unsigned char* dst, short s)
144 {
145     dst[0] = LOBYTE(s);
146     dst[1] = HIBYTE(s);
147 }
148
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.
155  */
156
157 /* -------------------------------------------------------------------------------*/
158
159 /*
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
162  * charge.
163  *
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.
167  *
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.
171  *
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.
175  *
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.
179  *
180  * Sun Microsystems, Inc.
181  * 2550 Garcia Avenue
182  * Mountain View, California  94043
183  */
184
185 /*
186  * g711.c
187  *
188  * u-law, A-law and linear PCM conversions.
189  */
190
191 /*
192  * December 30, 1994:
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
196  * corrected.
197  * Borge Lindberg, Center for PersonKommunikation, Aalborg University.
198  * bli@cpk.auc.dk
199  *
200  */
201
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. */
207
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};
212
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,
225 /* corrected:
226         81,     82,     83,     84,     85,     86,     87,     88,
227    should be: */
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};
234
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,
245 /* corrected:
246         73,     74,     75,     76,     77,     78,     79,     79,
247    should be: */
248         73,     74,     75,     76,     77,     78,     79,     80,
249
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};
256
257 static short
258 search(
259     int         val,            /* changed from "short" *drago* */
260     short       *table,
261     int         size)           /* changed from "short" *drago* */
262 {
263     int         i;      /* changed from "short" *drago* */
264
265     for (i = 0; i < size; i++) {
266         if (val <= *table++)
267             return (i);
268     }
269     return (size);
270 }
271
272 /*
273  * linear2alaw() - Convert a 16-bit linear PCM value to 8-bit A-law
274  *
275  * linear2alaw() accepts an 16-bit integer and encodes it as A-law data.
276  *
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
287  *
288  * For further information see John C. Bellamy's Digital Telephony, 1982,
289  * John Wiley & Sons, pps 98-111 and 472-476.
290  */
291 static inline unsigned char
292 linear2alaw(int pcm_val)        /* 2's complement (16-bit range) */
293     /* changed from "short" *drago* */
294 {
295     int         mask;   /* changed from "short" *drago* */
296     int         seg;    /* changed from "short" *drago* */
297     unsigned char       aval;
298
299     pcm_val = pcm_val >> 3;
300
301     if (pcm_val >= 0) {
302         mask = 0xD5;            /* sign (7th) bit = 1 */
303     } else {
304         mask = 0x55;            /* sign bit = 0 */
305         pcm_val = -pcm_val - 1;
306     }
307
308     /* Convert the scaled magnitude to segment number. */
309     seg = search(pcm_val, seg_aend, 8);
310
311     /* Combine the sign, segment, and quantization bits. */
312
313     if (seg >= 8)               /* out of range, return maximum value. */
314         return (unsigned char) (0x7F ^ mask);
315     else {
316         aval = (unsigned char) seg << SEG_SHIFT;
317         if (seg < 2)
318             aval |= (pcm_val >> 1) & QUANT_MASK;
319         else
320             aval |= (pcm_val >> seg) & QUANT_MASK;
321         return (aval ^ mask);
322     }
323 }
324
325 #ifdef NO_FASTDECODE
326 /*
327  * alaw2linear() - Convert an A-law value to 16-bit linear PCM
328  *
329  */
330 static inline int
331 alaw2linear(unsigned char a_val)
332 {
333     int         t;      /* changed from "short" *drago* */
334     int         seg;    /* changed from "short" *drago* */
335
336     a_val ^= 0x55;
337
338     t = (a_val & QUANT_MASK) << 4;
339     seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT;
340     switch (seg) {
341     case 0:
342         t += 8;
343         break;
344     case 1:
345         t += 0x108;
346         break;
347     default:
348         t += 0x108;
349         t <<= seg - 1;
350     }
351     return ((a_val & SIGN_BIT) ? t : -t);
352 }
353 #else
354 /* EPP (for Wine):
355  * this array has been statically generated from the above routine
356  */
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,
390 };
391 static int inline
392 alaw2linear(unsigned char a_val)
393 {
394     return (short)_a2l[a_val];
395 }
396 #endif
397
398 #define BIAS            (0x84)          /* Bias for linear code. */
399 #define CLIP            8159
400
401 /*
402  * linear2ulaw() - Convert a linear PCM value to u-law
403  *
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:
407  *
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
418  *
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.
423  *
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.
426  *
427  * For further information see John C. Bellamy's Digital Telephony, 1982,
428  * John Wiley & Sons, pps 98-111 and 472-476.
429  */
430 static inline unsigned char
431 linear2ulaw(short pcm_val)      /* 2's complement (16-bit range) */
432 {
433     short               mask;
434     short               seg;
435     unsigned char       uval;
436
437     /* Get the sign and the magnitude of the value. */
438     pcm_val = pcm_val >> 2;
439     if (pcm_val < 0) {
440         pcm_val = -pcm_val;
441         mask = 0x7F;
442     } else {
443         mask = 0xFF;
444     }
445     if ( pcm_val > CLIP ) pcm_val = CLIP;               /* clip the magnitude */
446     pcm_val += (BIAS >> 2);
447
448     /* Convert the scaled magnitude to segment number. */
449     seg = search(pcm_val, seg_uend, 8);
450
451     /*
452      * Combine the sign, segment, quantization bits;
453      * and complement the code word.
454      */
455     if (seg >= 8)               /* out of range, return maximum value. */
456         return (unsigned char) (0x7F ^ mask);
457     else {
458         uval = (unsigned char) (seg << 4) | ((pcm_val >> (seg + 1)) & 0xF);
459         return (uval ^ mask);
460     }
461 }
462
463 #ifdef NO_FASTDECODE
464 /*
465  * ulaw2linear() - Convert a u-law value to 16-bit linear PCM
466  *
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.
469  *
470  * Note that this function expects to be passed the complement of the
471  * original code word. This is in keeping with ISDN conventions.
472  */
473 static inline short
474 ulaw2linear(unsigned char u_val)
475 {
476     short               t;
477
478     /* Complement to obtain normal u-law value. */
479     u_val = ~u_val;
480
481     /*
482      * Extract and bias the quantization bits. Then
483      * shift up by the segment number and subtract out the bias.
484      */
485     t = ((u_val & QUANT_MASK) << 3) + BIAS;
486     t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT;
487
488     return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS));
489 }
490 #else
491 /* EPP (for Wine):
492  * this array has been statically generated from the above routine
493  */
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,
527 };
528 static inline short ulaw2linear(unsigned char u_val)
529 {
530     return (short)_u2l[u_val];
531 }
532 #endif
533
534 /* A-law to u-law conversion */
535 static inline unsigned char
536 alaw2ulaw(unsigned char aval)
537 {
538     aval &= 0xff;
539     return (unsigned char) ((aval & 0x80) ? (0xFF ^ _a2u[aval ^ 0xD5]) :
540                             (0x7F ^ _a2u[aval ^ 0x55]));
541 }
542
543 /* u-law to A-law conversion */
544 static inline unsigned char
545 ulaw2alaw(unsigned char uval)
546 {
547     uval &= 0xff;
548     return (unsigned char) ((uval & 0x80) ? (0xD5 ^ (_u2a[0xFF ^ uval] - 1)) :
549                             (unsigned char) (0x55 ^ (_u2a[0x7F ^ uval] - 1)));
550 }
551
552 /* -------------------------------------------------------------------------------*/
553
554 static void cvtXXalaw16K(PACMDRVSTREAMINSTANCE adsi,
555                          const unsigned char* src, LPDWORD srcsize,
556                          unsigned char* dst, LPDWORD dstsize)
557 {
558     DWORD       len = min(*srcsize, *dstsize / 2);
559     DWORD       i;
560     short       w;
561
562     *srcsize = len;
563     *dstsize = len * 2;
564     for (i = 0; i < len; i++)
565     {
566         w = alaw2linear(*src++);
567         W16(dst, w);    dst += 2;
568     }
569 }
570
571 static void cvtXX16alawK(PACMDRVSTREAMINSTANCE adsi,
572                          const unsigned char* src, LPDWORD srcsize,
573                          unsigned char* dst, LPDWORD dstsize)
574 {
575     DWORD       len = min(*srcsize / 2, *dstsize);
576     DWORD       i;
577
578     *srcsize = len * 2;
579     *dstsize = len;
580     for (i = 0; i < len; i++)
581     {
582         *dst++ = linear2alaw(R16(src)); src += 2;
583     }
584 }
585
586 static void cvtXXulaw16K(PACMDRVSTREAMINSTANCE adsi,
587                          const unsigned char* src, LPDWORD srcsize,
588                          unsigned char* dst, LPDWORD dstsize)
589 {
590     DWORD       len = min(*srcsize, *dstsize / 2);
591     DWORD       i;
592     short       w;
593
594     *srcsize = len;
595     *dstsize = len * 2;
596     for (i = 0; i < len; i++)
597     {
598         w = ulaw2linear(*src++);
599         W16(dst, w);    dst += 2;
600     }
601 }
602
603 static void cvtXX16ulawK(PACMDRVSTREAMINSTANCE adsi,
604                          const unsigned char* src, LPDWORD srcsize,
605                          unsigned char* dst, LPDWORD dstsize)
606 {
607     DWORD       len = min(*srcsize / 2, *dstsize);
608     DWORD       i;
609
610     *srcsize = len * 2;
611     *dstsize = len;
612     for (i = 0; i < len; i++)
613     {
614         *dst++ = linear2ulaw(R16(src)); src += 2;
615     }
616 }
617
618 static void cvtXXalawulawK(PACMDRVSTREAMINSTANCE adsi,
619                            const unsigned char* src, LPDWORD srcsize,
620                            unsigned char* dst, LPDWORD dstsize)
621 {
622     DWORD       len = min(*srcsize, *dstsize);
623     DWORD       i;
624
625     *srcsize = len;
626     *dstsize = len;
627
628     for (i = 0; i < len; i++)
629         *dst++ = alaw2ulaw(*src++);
630 }
631
632
633 static void cvtXXulawalawK(PACMDRVSTREAMINSTANCE adsi,
634                            const unsigned char* src, LPDWORD srcsize,
635                            unsigned char* dst, LPDWORD dstsize)
636 {
637     DWORD       len = min(*srcsize, *dstsize);
638     DWORD       i;
639
640     *srcsize = len;
641     *dstsize = len;
642
643     for (i = 0; i < len; i++)
644         *dst++ = ulaw2alaw(*src++);
645 }
646
647 /***********************************************************************
648  *           G711_DriverDetails
649  *
650  */
651 static  LRESULT G711_DriverDetails(PACMDRIVERDETAILSW add)
652 {
653     add->fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC;
654     add->fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED;
655     add->wMid = 0xFF;
656     add->wPid = 0x00;
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;
662     add->hicon = NULL;
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;
672
673     return MMSYSERR_NOERROR;
674 }
675
676 /***********************************************************************
677  *           G711_FormatTagDetails
678  *
679  */
680 static  LRESULT G711_FormatTagDetails(PACMFORMATTAGDETAILSW aftd, DWORD dwQuery)
681 {
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};
685
686     switch (dwQuery)
687     {
688     case ACM_FORMATTAGDETAILSF_INDEX:
689         if (aftd->dwFormatTagIndex >= 3) return ACMERR_NOTPOSSIBLE;
690         break;
691     case ACM_FORMATTAGDETAILSF_LARGESTSIZE:
692         if (aftd->dwFormatTag == WAVE_FORMAT_UNKNOWN)
693         {
694             aftd->dwFormatTagIndex = 1;
695             break;
696         }
697         /* fall thru */
698     case ACM_FORMATTAGDETAILSF_FORMATTAG:
699         switch (aftd->dwFormatTag)
700         {
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;
705         }
706         break;
707     default:
708         WARN("Unsupported query %08lx\n", dwQuery);
709         return MMSYSERR_NOTSUPPORTED;
710     }
711
712     aftd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
713     switch (aftd->dwFormatTagIndex)
714     {
715     case 0:
716         aftd->dwFormatTag = WAVE_FORMAT_PCM;
717         aftd->cbFormatSize = sizeof(PCMWAVEFORMAT);
718         aftd->cStandardFormats = NUM_PCM_FORMATS;
719         lstrcpyW(aftd->szFormatTag, szPcm);
720         break;
721     case 1:
722         aftd->dwFormatTag = WAVE_FORMAT_ALAW;
723         aftd->cbFormatSize = sizeof(WAVEFORMATEX);
724         aftd->cStandardFormats = NUM_ALAW_FORMATS;
725         lstrcpyW(aftd->szFormatTag, szALaw);
726         break;
727     case 2:
728         aftd->dwFormatTag = WAVE_FORMAT_MULAW;
729         aftd->cbFormatSize = sizeof(WAVEFORMATEX);
730         aftd->cStandardFormats = NUM_ULAW_FORMATS;
731         lstrcpyW(aftd->szFormatTag, szULaw);
732         break;
733     }
734     return MMSYSERR_NOERROR;
735 }
736
737 /***********************************************************************
738  *           G711_FormatDetails
739  *
740  */
741 static  LRESULT G711_FormatDetails(PACMFORMATDETAILSW afd, DWORD dwQuery)
742 {
743     switch (dwQuery)
744     {
745     case ACM_FORMATDETAILSF_FORMAT:
746         if (G711_GetFormatIndex(afd->pwfx) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
747         break;
748     case ACM_FORMATDETAILSF_INDEX:
749         afd->pwfx->wFormatTag = afd->dwFormatTag;
750         switch (afd->dwFormatTag)
751         {
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;
759             break;
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;
768             break;
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;
777             break;
778         default:
779             WARN("Unsupported tag %08lx\n", afd->dwFormatTag);
780             return MMSYSERR_INVALPARAM;
781         }
782         break;
783     default:
784         WARN("Unsupported query %08lx\n", dwQuery);
785         return MMSYSERR_NOTSUPPORTED;
786     }
787     afd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
788     afd->szFormat[0] = 0; /* let MSACM format this for us... */
789
790     return MMSYSERR_NOERROR;
791 }
792
793 /***********************************************************************
794  *           G711_FormatSuggest
795  *
796  */
797 static  LRESULT G711_FormatSuggest(PACMDRVFORMATSUGGEST adfs)
798 {
799     /* some tests ... */
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 */
804
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;
810
811     if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WBITSPERSAMPLE))
812     {
813         if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM)
814             adfs->pwfxDst->wBitsPerSample = 8;
815         else
816             adfs->pwfxDst->wBitsPerSample = 16;
817     }
818     if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG))
819     {
820         switch (adfs->pwfxSrc->wFormatTag)
821         {
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;
825         }
826     }
827     /* check if result is ok */
828     if (G711_GetFormatIndex(adfs->pwfxDst) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
829
830     /* recompute other values */
831     switch (adfs->pwfxDst->wFormatTag)
832     {
833     case WAVE_FORMAT_PCM:
834         adfs->pwfxDst->nBlockAlign = adfs->pwfxDst->nChannels;
835         adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * adfs->pwfxDst->nBlockAlign;
836         break;
837     case WAVE_FORMAT_ALAW:
838         adfs->pwfxDst->nBlockAlign = adfs->pwfxDst->nChannels * 2;
839         adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * adfs->pwfxSrc->nChannels * 2;
840         break;
841     case WAVE_FORMAT_MULAW:
842         adfs->pwfxDst->nBlockAlign =  adfs->pwfxDst->nChannels * 2;
843         adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * adfs->pwfxSrc->nChannels * 2;
844         break;
845     default:
846         FIXME("\n");
847         break;
848     }
849
850     return MMSYSERR_NOERROR;
851 }
852
853 /***********************************************************************
854  *           G711_Reset
855  *
856  */
857 static  void    G711_Reset(PACMDRVSTREAMINSTANCE adsi, AcmG711Data* aad)
858 {
859 }
860
861 /***********************************************************************
862  *           G711_StreamOpen
863  *
864  */
865 static  LRESULT G711_StreamOpen(PACMDRVSTREAMINSTANCE adsi)
866 {
867     AcmG711Data*        aad;
868
869     assert(!(adsi->fdwOpen & ACM_STREAMOPENF_ASYNC));
870
871     if (G711_GetFormatIndex(adsi->pwfxSrc) == 0xFFFFFFFF ||
872         G711_GetFormatIndex(adsi->pwfxDst) == 0xFFFFFFFF)
873         return ACMERR_NOTPOSSIBLE;
874
875     aad = HeapAlloc(GetProcessHeap(), 0, sizeof(AcmG711Data));
876     if (aad == 0) return MMSYSERR_NOMEM;
877
878     adsi->dwDriver = (DWORD)aad;
879
880     if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
881         adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
882     {
883         goto theEnd;
884     }
885     else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ALAW &&
886              adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
887     {
888         /* resampling or mono <=> stereo not available
889          * G711 algo only define 16 bit per sample output
890          */
891         if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
892             adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
893             adsi->pwfxDst->wBitsPerSample != 16)
894             goto theEnd;
895
896         /* g711 A-Law decoding... */
897         if (adsi->pwfxDst->wBitsPerSample == 16)
898             aad->convert = cvtXXalaw16K;
899     }
900     else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
901              adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ALAW)
902     {
903         if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
904             adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
905             adsi->pwfxSrc->wBitsPerSample != 16)
906             goto theEnd;
907
908         /* g711 coding... */
909         if (adsi->pwfxSrc->wBitsPerSample == 16)
910             aad->convert = cvtXX16alawK;
911     }
912     else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MULAW &&
913              adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
914     {
915         /* resampling or mono <=> stereo not available
916          * G711 algo only define 16 bit per sample output
917          */
918         if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
919             adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
920             adsi->pwfxDst->wBitsPerSample != 16)
921             goto theEnd;
922
923         /* g711 MU-Law decoding... */
924         if (adsi->pwfxDst->wBitsPerSample == 16)
925             aad->convert = cvtXXulaw16K;
926     }
927     else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
928              adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ALAW)
929     {
930         if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
931             adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
932             adsi->pwfxSrc->wBitsPerSample != 16)
933             goto theEnd;
934
935         /* g711 coding... */
936         if (adsi->pwfxSrc->wBitsPerSample == 16)
937             aad->convert = cvtXX16ulawK;
938     }
939     else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MULAW &&
940              adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ALAW)
941     {
942         if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
943             adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels)
944             goto theEnd;
945
946         /* MU-Law => A-Law... */
947         aad->convert = cvtXXulawalawK;
948     }
949     else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ALAW &&
950              adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MULAW)
951     {
952         if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
953             adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels)
954             goto theEnd;
955
956         /* A-Law => MU-Law... */
957         aad->convert = cvtXXalawulawK;
958     }
959     else goto theEnd;
960
961     G711_Reset(adsi, aad);
962
963     return MMSYSERR_NOERROR;
964
965  theEnd:
966     HeapFree(GetProcessHeap(), 0, aad);
967     adsi->dwDriver = 0L;
968     return MMSYSERR_NOTSUPPORTED;
969 }
970
971 /***********************************************************************
972  *           G711_StreamClose
973  *
974  */
975 static  LRESULT G711_StreamClose(PACMDRVSTREAMINSTANCE adsi)
976 {
977     HeapFree(GetProcessHeap(), 0, (void*)adsi->dwDriver);
978     return MMSYSERR_NOERROR;
979 }
980
981 /***********************************************************************
982  *           G711_round
983  *
984  */
985 static  inline DWORD    G711_round(DWORD a, DWORD b, DWORD c)
986 {
987     assert(a && b && c);
988     /* to be sure, always return an entire number of c... */
989     return ((double)a * (double)b + (double)c - 1) / (double)c;
990 }
991
992 /***********************************************************************
993  *           G711_StreamSize
994  *
995  */
996 static  LRESULT G711_StreamSize(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMSIZE adss)
997 {
998     switch (adss->fdwSize)
999     {
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))
1005         {
1006             adss->cbSrcLength = adss->cbDstLength / 2;
1007         }
1008         else if ((adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ALAW ||
1009                   adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MULAW) &&
1010                  adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
1011         {
1012             adss->cbSrcLength = adss->cbDstLength * 2;
1013         }
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))
1018         {
1019             adss->cbSrcLength = adss->cbDstLength;
1020         }
1021         else
1022         {
1023             return MMSYSERR_NOTSUPPORTED;
1024         }
1025         break;
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))
1031         {
1032             adss->cbDstLength = adss->cbSrcLength * 2;
1033         }
1034         else if ((adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ALAW ||
1035                   adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MULAW) &&
1036                  adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
1037         {
1038             adss->cbDstLength = adss->cbSrcLength / 2;
1039         }
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))
1044         {
1045             adss->cbDstLength = adss->cbSrcLength;
1046         }
1047         else
1048         {
1049             return MMSYSERR_NOTSUPPORTED;
1050         }
1051         break;
1052     default:
1053         WARN("Unsupported query %08lx\n", adss->fdwSize);
1054         return MMSYSERR_NOTSUPPORTED;
1055     }
1056     FIXME("\n");
1057     return MMSYSERR_NOERROR;
1058 }
1059
1060 /***********************************************************************
1061  *           G711_StreamConvert
1062  *
1063  */
1064 static LRESULT G711_StreamConvert(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMHEADER adsh)
1065 {
1066     AcmG711Data*        aad = (AcmG711Data*)adsi->dwDriver;
1067     DWORD               nsrc = adsh->cbSrcLength;
1068     DWORD               ndst = adsh->cbDstLength;
1069
1070     if (adsh->fdwConvert &
1071         ~(ACM_STREAMCONVERTF_BLOCKALIGN|
1072           ACM_STREAMCONVERTF_END|
1073           ACM_STREAMCONVERTF_START))
1074     {
1075         FIXME("Unsupported fdwConvert (%08lx), ignoring it\n", adsh->fdwConvert);
1076     }
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
1081      */
1082     if ((adsh->fdwConvert & ACM_STREAMCONVERTF_START))
1083     {
1084         G711_Reset(adsi, aad);
1085     }
1086
1087     aad->convert(adsi, adsh->pbSrc, &nsrc, adsh->pbDst, &ndst);
1088     adsh->cbSrcLengthUsed = nsrc;
1089     adsh->cbDstLengthUsed = ndst;
1090
1091     return MMSYSERR_NOERROR;
1092 }
1093
1094 /**************************************************************************
1095  *                      G711_DriverProc                 [exported]
1096  */
1097 LRESULT CALLBACK        G711_DriverProc(DWORD dwDevID, HDRVR hDriv, UINT wMsg,
1098                                          LPARAM dwParam1, LPARAM dwParam2)
1099 {
1100     TRACE("(%08lx %08lx %04x %08lx %08lx);\n",
1101           dwDevID, (DWORD)hDriv, wMsg, dwParam1, dwParam2);
1102
1103     switch (wMsg)
1104     {
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;
1115
1116     case ACMDM_DRIVER_NOTIFY:
1117         /* no caching from other ACM drivers is done so far */
1118         return MMSYSERR_NOERROR;
1119
1120     case ACMDM_DRIVER_DETAILS:
1121         return G711_DriverDetails((PACMDRIVERDETAILSW)dwParam1);
1122
1123     case ACMDM_FORMATTAG_DETAILS:
1124         return G711_FormatTagDetails((PACMFORMATTAGDETAILSW)dwParam1, dwParam2);
1125
1126     case ACMDM_FORMAT_DETAILS:
1127         return G711_FormatDetails((PACMFORMATDETAILSW)dwParam1, dwParam2);
1128
1129     case ACMDM_FORMAT_SUGGEST:
1130         return G711_FormatSuggest((PACMDRVFORMATSUGGEST)dwParam1);
1131
1132     case ACMDM_STREAM_OPEN:
1133         return G711_StreamOpen((PACMDRVSTREAMINSTANCE)dwParam1);
1134
1135     case ACMDM_STREAM_CLOSE:
1136         return G711_StreamClose((PACMDRVSTREAMINSTANCE)dwParam1);
1137
1138     case ACMDM_STREAM_SIZE:
1139         return G711_StreamSize((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMSIZE)dwParam2);
1140
1141     case ACMDM_STREAM_CONVERT:
1142         return G711_StreamConvert((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMHEADER)dwParam2);
1143
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;
1157
1158     default:
1159         return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
1160     }
1161     return 0;
1162 }