msg711.c 37.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/*
 * G711 handling (includes A-Law & MU-Law)
 *
 *      Copyright (C) 2002		Eric Pouech
 *
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * 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 27 28
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
29
#include "winnls.h"
30
#include "mmsystem.h"
31
#include "mmreg.h"
32
#include "msacm.h"
33
#include "msacmdrv.h"
34 35 36 37 38 39 40
#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(g711);

/***********************************************************************
 *           G711_drvOpen
 */
41
static LRESULT G711_drvOpen(LPCSTR str)
42 43 44 45 46 47 48
{
    return 1;
}

/***********************************************************************
 *           G711_drvClose
 */
49
static LRESULT G711_drvClose(DWORD_PTR dwDevID)
50 51 52 53
{
    return 1;
}

54
typedef struct tagAcmG711Data
55
{
56
    void (*convert)(PACMDRVSTREAMINSTANCE adsi,
57 58 59 60 61 62
		    const unsigned char*, LPDWORD, unsigned char*, LPDWORD);
} AcmG711Data;

/* table to list all supported formats... those are the basic ones. this
 * also helps given a unique index to each of the supported formats
 */
63
typedef	struct
64 65 66 67 68 69
{
    int		nChannels;
    int		nBits;
    int		rate;
} Format;

70
static const Format PCM_Formats[] =
71 72 73 74 75 76 77
{
    /*{1,  8,  8000}, {2,  8,  8000}, */{1, 16,  8000}, {2, 16,  8000},
    /*{1,  8, 11025}, {2,  8, 11025}, */{1, 16, 11025}, {2, 16, 11025},
    /*{1,  8, 22050}, {2,  8, 22050}, */{1, 16, 22050}, {2, 16, 22050},
    /*{1,  8, 44100}, {2,  8, 44100}, */{1, 16, 44100}, {2, 16, 44100},
};

78
static const Format ALaw_Formats[] =
79
{
80
    {1,  8,  8000}, {2,	8,  8000},  {1,  8, 11025}, {2,	 8, 11025},
81 82 83
    {1,  8, 22050}, {2,	8, 22050},  {1,  8, 44100}, {2,	 8, 44100},
};

84
static const Format ULaw_Formats[] =
85
{
86
    {1,  8,  8000}, {2,	8,  8000},  {1,  8, 11025}, {2,	 8, 11025},
87 88 89 90 91 92 93 94 95 96
    {1,  8, 22050}, {2,	8, 22050},  {1,  8, 44100}, {2,	 8, 44100},
};

#define	NUM_PCM_FORMATS		(sizeof(PCM_Formats) / sizeof(PCM_Formats[0]))
#define	NUM_ALAW_FORMATS	(sizeof(ALaw_Formats) / sizeof(ALaw_Formats[0]))
#define	NUM_ULAW_FORMATS	(sizeof(ULaw_Formats) / sizeof(ULaw_Formats[0]))

/***********************************************************************
 *           G711_GetFormatIndex
 */
97
static	DWORD	G711_GetFormatIndex(const WAVEFORMATEX *wfx)
98
{
99 100
    int             i, hi;
    const Format*   fmts;
101 102

    switch (wfx->wFormatTag)
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
    {
    case WAVE_FORMAT_PCM:
	hi = NUM_PCM_FORMATS;
	fmts = PCM_Formats;
	break;
    case WAVE_FORMAT_ALAW:
	hi = NUM_ALAW_FORMATS;
	fmts = ALaw_Formats;
	break;
    case WAVE_FORMAT_MULAW:
	hi = NUM_ULAW_FORMATS;
	fmts = ULaw_Formats;
	break;
    default:
	return 0xFFFFFFFF;
    }
119 120

    for (i = 0; i < hi; i++)
121 122 123 124 125 126
    {
	if (wfx->nChannels == fmts[i].nChannels &&
	    wfx->nSamplesPerSec == fmts[i].rate &&
	    wfx->wBitsPerSample == fmts[i].nBits)
	    return i;
    }
127

128 129 130 131 132 133
    return 0xFFFFFFFF;
}

/***********************************************************************
 *           R16
 *
134
 * Read a 16 bit sample (correctly handles endianness)
135 136 137 138 139 140 141 142 143
 */
static inline short  R16(const unsigned char* src)
{
    return (short)((unsigned short)src[0] | ((unsigned short)src[1] << 8));
}

/***********************************************************************
 *           W16
 *
144
 * Write a 16 bit sample (correctly handles endianness)
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
 */
static inline void  W16(unsigned char* dst, short s)
{
    dst[0] = LOBYTE(s);
    dst[1] = HIBYTE(s);
}

/* You can uncomment this if you don't want the statically generated conversion
 * table, but rather recompute the Xlaw => PCM conversion for each sample
#define NO_FASTDECODE
 * Since the conversion tables are rather small (2k), I don't think it's really
 * interesting not to use them, but keeping the actual conversion code around
 * is helpful to regenerate the tables when needed.
 */

/* -------------------------------------------------------------------------------*/

/*
 * This source code is a product of Sun Microsystems, Inc. and is provided
 * for unrestricted use.  Users may copy or modify this source code without
 * charge.
 *
 * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
 * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
 *
 * Sun source code is provided with no support and without any obligation on
 * the part of Sun Microsystems, Inc. to assist in its use, correction,
 * modification or enhancement.
 *
 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
 * OR ANY PART THEREOF.
 *
 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
 * or profits or other special, indirect and consequential damages, even if
 * Sun has been advised of the possibility of such damages.
 *
 * Sun Microsystems, Inc.
 * 2550 Garcia Avenue
 * Mountain View, California  94043
 */

/*
 * g711.c
 *
 * u-law, A-law and linear PCM conversions.
 */

/*
 * December 30, 1994:
 * Functions linear2alaw, linear2ulaw have been updated to correctly
 * convert unquantized 16 bit values.
 * Tables for direct u- to A-law and A- to u-law conversions have been
 * corrected.
 * Borge Lindberg, Center for PersonKommunikation, Aalborg University.
 * bli@cpk.auc.dk
 *
 */
204

205
#define	SIGN_BIT	(0x80)		/* Sign bit for an A-law byte. */
206 207 208 209 210
#define	QUANT_MASK	(0xf)		/* Quantization field mask. */
#define	NSEGS		(8)		/* Number of A-law segments. */
#define	SEG_SHIFT	(4)		/* Left shift for segment number. */
#define	SEG_MASK	(0x70)		/* Segment field mask. */

211 212
static const short seg_aend[8] = {0x1F, 0x3F, 0x7F, 0x0FF, 0x1FF, 0x3FF, 0x7FF, 0x0FFF};
static const short seg_uend[8] = {0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF};
213 214

/* copy from CCITT G.711 specifications */
215
static const unsigned char _u2a[128] = {		/* u- to A-law conversions */
216 217 218 219 220 221 222 223 224 225 226
	1,	1,	2,	2,	3,	3,	4,	4,
	5,	5,	6,	6,	7,	7,	8,	8,
	9,	10,	11,	12,	13,	14,	15,	16,
	17,	18,	19,	20,	21,	22,	23,	24,
	25,	27,	29,	31,	33,	34,	35,	36,
	37,	38,	39,	40,	41,	42,	43,	44,
	46,	48,	49,	50,	51,	52,	53,	54,
	55,	56,	57,	58,	59,	60,	61,	62,
	64,	65,	66,	67,	68,	69,	70,	71,
	72,	73,	74,	75,	76,	77,	78,	79,
/* corrected:
227
	81,	82,	83,	84,	85,	86,	87,	88,
228 229 230 231 232 233 234 235
   should be: */
	80,	82,	83,	84,	85,	86,	87,	88,
	89,	90,	91,	92,	93,	94,	95,	96,
	97,	98,	99,	100,	101,	102,	103,	104,
	105,	106,	107,	108,	109,	110,	111,	112,
	113,	114,	115,	116,	117,	118,	119,	120,
	121,	122,	123,	124,	125,	126,	127,	128};

236
static const unsigned char _a2u[128] = {		/* A- to u-law conversions */
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260
	1,	3,	5,	7,	9,	11,	13,	15,
	16,	17,	18,	19,	20,	21,	22,	23,
	24,	25,	26,	27,	28,	29,	30,	31,
	32,	32,	33,	33,	34,	34,	35,	35,
	36,	37,	38,	39,	40,	41,	42,	43,
	44,	45,	46,	47,	48,	48,	49,	49,
	50,	51,	52,	53,	54,	55,	56,	57,
	58,	59,	60,	61,	62,	63,	64,	64,
	65,	66,	67,	68,	69,	70,	71,	72,
/* corrected:
	73,	74,	75,	76,	77,	78,	79,	79,
   should be: */
	73,	74,	75,	76,	77,	78,	79,	80,

	80,	81,	82,	83,	84,	85,	86,	87,
	88,	89,	90,	91,	92,	93,	94,	95,
	96,	97,	98,	99,	100,	101,	102,	103,
	104,	105,	106,	107,	108,	109,	110,	111,
	112,	113,	114,	115,	116,	117,	118,	119,
	120,	121,	122,	123,	124,	125,	126,	127};

static short
search(
    int		val,	        /* changed from "short" *drago* */
261
    const short	*table,
262 263 264
    int		size)	        /* changed from "short" *drago* */
{
    int		i;	/* changed from "short" *drago* */
265

266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298
    for (i = 0; i < size; i++) {
        if (val <= *table++)
            return (i);
    }
    return (size);
}

/*
 * linear2alaw() - Convert a 16-bit linear PCM value to 8-bit A-law
 *
 * linear2alaw() accepts an 16-bit integer and encodes it as A-law data.
 *
 *		Linear Input Code	Compressed Code
 *	------------------------	---------------
 *	0000000wxyza			000wxyz
 *	0000001wxyza			001wxyz
 *	000001wxyzab			010wxyz
 *	00001wxyzabc			011wxyz
 *	0001wxyzabcd			100wxyz
 *	001wxyzabcde			101wxyz
 *	01wxyzabcdef			110wxyz
 *	1wxyzabcdefg			111wxyz
 *
 * For further information see John C. Bellamy's Digital Telephony, 1982,
 * John Wiley & Sons, pps 98-111 and 472-476.
 */
static inline unsigned char
linear2alaw(int pcm_val)	/* 2's complement (16-bit range) */
    /* changed from "short" *drago* */
{
    int		mask;	/* changed from "short" *drago* */
    int		seg;	/* changed from "short" *drago* */
    unsigned char	aval;
299

300
    pcm_val = pcm_val >> 3;
301

302 303 304 305 306 307
    if (pcm_val >= 0) {
        mask = 0xD5;		/* sign (7th) bit = 1 */
    } else {
        mask = 0x55;		/* sign bit = 0 */
        pcm_val = -pcm_val - 1;
    }
308

309 310
    /* Convert the scaled magnitude to segment number. */
    seg = search(pcm_val, seg_aend, 8);
311

312
    /* Combine the sign, segment, and quantization bits. */
313

314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335
    if (seg >= 8)		/* out of range, return maximum value. */
        return (unsigned char) (0x7F ^ mask);
    else {
        aval = (unsigned char) seg << SEG_SHIFT;
        if (seg < 2)
            aval |= (pcm_val >> 1) & QUANT_MASK;
        else
            aval |= (pcm_val >> seg) & QUANT_MASK;
        return (aval ^ mask);
    }
}

#ifdef NO_FASTDECODE
/*
 * alaw2linear() - Convert an A-law value to 16-bit linear PCM
 *
 */
static inline int
alaw2linear(unsigned char a_val)
{
    int		t;	/* changed from "short" *drago* */
    int		seg;	/* changed from "short" *drago* */
336

337
    a_val ^= 0x55;
338

339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355
    t = (a_val & QUANT_MASK) << 4;
    seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT;
    switch (seg) {
    case 0:
        t += 8;
        break;
    case 1:
        t += 0x108;
        break;
    default:
        t += 0x108;
        t <<= seg - 1;
    }
    return ((a_val & SIGN_BIT) ? t : -t);
}
#else
/* EPP (for Wine):
356
 * this array has been statically generated from the above routine
357
 */
358
static const unsigned short _a2l[] = {
359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391
0xEA80, 0xEB80, 0xE880, 0xE980, 0xEE80, 0xEF80, 0xEC80, 0xED80,
0xE280, 0xE380, 0xE080, 0xE180, 0xE680, 0xE780, 0xE480, 0xE580,
0xF540, 0xF5C0, 0xF440, 0xF4C0, 0xF740, 0xF7C0, 0xF640, 0xF6C0,
0xF140, 0xF1C0, 0xF040, 0xF0C0, 0xF340, 0xF3C0, 0xF240, 0xF2C0,
0xAA00, 0xAE00, 0xA200, 0xA600, 0xBA00, 0xBE00, 0xB200, 0xB600,
0x8A00, 0x8E00, 0x8200, 0x8600, 0x9A00, 0x9E00, 0x9200, 0x9600,
0xD500, 0xD700, 0xD100, 0xD300, 0xDD00, 0xDF00, 0xD900, 0xDB00,
0xC500, 0xC700, 0xC100, 0xC300, 0xCD00, 0xCF00, 0xC900, 0xCB00,
0xFEA8, 0xFEB8, 0xFE88, 0xFE98, 0xFEE8, 0xFEF8, 0xFEC8, 0xFED8,
0xFE28, 0xFE38, 0xFE08, 0xFE18, 0xFE68, 0xFE78, 0xFE48, 0xFE58,
0xFFA8, 0xFFB8, 0xFF88, 0xFF98, 0xFFE8, 0xFFF8, 0xFFC8, 0xFFD8,
0xFF28, 0xFF38, 0xFF08, 0xFF18, 0xFF68, 0xFF78, 0xFF48, 0xFF58,
0xFAA0, 0xFAE0, 0xFA20, 0xFA60, 0xFBA0, 0xFBE0, 0xFB20, 0xFB60,
0xF8A0, 0xF8E0, 0xF820, 0xF860, 0xF9A0, 0xF9E0, 0xF920, 0xF960,
0xFD50, 0xFD70, 0xFD10, 0xFD30, 0xFDD0, 0xFDF0, 0xFD90, 0xFDB0,
0xFC50, 0xFC70, 0xFC10, 0xFC30, 0xFCD0, 0xFCF0, 0xFC90, 0xFCB0,
0x1580, 0x1480, 0x1780, 0x1680, 0x1180, 0x1080, 0x1380, 0x1280,
0x1D80, 0x1C80, 0x1F80, 0x1E80, 0x1980, 0x1880, 0x1B80, 0x1A80,
0x0AC0, 0x0A40, 0x0BC0, 0x0B40, 0x08C0, 0x0840, 0x09C0, 0x0940,
0x0EC0, 0x0E40, 0x0FC0, 0x0F40, 0x0CC0, 0x0C40, 0x0DC0, 0x0D40,
0x5600, 0x5200, 0x5E00, 0x5A00, 0x4600, 0x4200, 0x4E00, 0x4A00,
0x7600, 0x7200, 0x7E00, 0x7A00, 0x6600, 0x6200, 0x6E00, 0x6A00,
0x2B00, 0x2900, 0x2F00, 0x2D00, 0x2300, 0x2100, 0x2700, 0x2500,
0x3B00, 0x3900, 0x3F00, 0x3D00, 0x3300, 0x3100, 0x3700, 0x3500,
0x0158, 0x0148, 0x0178, 0x0168, 0x0118, 0x0108, 0x0138, 0x0128,
0x01D8, 0x01C8, 0x01F8, 0x01E8, 0x0198, 0x0188, 0x01B8, 0x01A8,
0x0058, 0x0048, 0x0078, 0x0068, 0x0018, 0x0008, 0x0038, 0x0028,
0x00D8, 0x00C8, 0x00F8, 0x00E8, 0x0098, 0x0088, 0x00B8, 0x00A8,
0x0560, 0x0520, 0x05E0, 0x05A0, 0x0460, 0x0420, 0x04E0, 0x04A0,
0x0760, 0x0720, 0x07E0, 0x07A0, 0x0660, 0x0620, 0x06E0, 0x06A0,
0x02B0, 0x0290, 0x02F0, 0x02D0, 0x0230, 0x0210, 0x0270, 0x0250,
0x03B0, 0x0390, 0x03F0, 0x03D0, 0x0330, 0x0310, 0x0370, 0x0350,
};
392
static inline int
393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436
alaw2linear(unsigned char a_val)
{
    return (short)_a2l[a_val];
}
#endif

#define	BIAS		(0x84)		/* Bias for linear code. */
#define CLIP            8159

/*
 * linear2ulaw() - Convert a linear PCM value to u-law
 *
 * In order to simplify the encoding process, the original linear magnitude
 * is biased by adding 33 which shifts the encoding range from (0 - 8158) to
 * (33 - 8191). The result can be seen in the following encoding table:
 *
 *	Biased Linear Input Code	Compressed Code
 *	------------------------	---------------
 *	00000001wxyza			000wxyz
 *	0000001wxyzab			001wxyz
 *	000001wxyzabc			010wxyz
 *	00001wxyzabcd			011wxyz
 *	0001wxyzabcde			100wxyz
 *	001wxyzabcdef			101wxyz
 *	01wxyzabcdefg			110wxyz
 *	1wxyzabcdefgh			111wxyz
 *
 * Each biased linear code has a leading 1 which identifies the segment
 * number. The value of the segment number is equal to 7 minus the number
 * of leading 0's. The quantization interval is directly available as the
 * four bits wxyz.  * The trailing bits (a - h) are ignored.
 *
 * Ordinarily the complement of the resulting code word is used for
 * transmission, and so the code word is complemented before it is returned.
 *
 * For further information see John C. Bellamy's Digital Telephony, 1982,
 * John Wiley & Sons, pps 98-111 and 472-476.
 */
static inline unsigned char
linear2ulaw(short pcm_val)	/* 2's complement (16-bit range) */
{
    short		mask;
    short		seg;
    unsigned char	uval;
437

438 439 440 441 442 443 444 445 446 447
    /* Get the sign and the magnitude of the value. */
    pcm_val = pcm_val >> 2;
    if (pcm_val < 0) {
        pcm_val = -pcm_val;
        mask = 0x7F;
    } else {
        mask = 0xFF;
    }
    if ( pcm_val > CLIP ) pcm_val = CLIP;		/* clip the magnitude */
    pcm_val += (BIAS >> 2);
448

449 450
    /* Convert the scaled magnitude to segment number. */
    seg = search(pcm_val, seg_uend, 8);
451

452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477
    /*
     * Combine the sign, segment, quantization bits;
     * and complement the code word.
     */
    if (seg >= 8)		/* out of range, return maximum value. */
        return (unsigned char) (0x7F ^ mask);
    else {
        uval = (unsigned char) (seg << 4) | ((pcm_val >> (seg + 1)) & 0xF);
        return (uval ^ mask);
    }
}

#ifdef NO_FASTDECODE
/*
 * ulaw2linear() - Convert a u-law value to 16-bit linear PCM
 *
 * First, a biased linear code is derived from the code word. An unbiased
 * output can then be obtained by subtracting 33 from the biased code.
 *
 * Note that this function expects to be passed the complement of the
 * original code word. This is in keeping with ISDN conventions.
 */
static inline short
ulaw2linear(unsigned char u_val)
{
    short		t;
478

479 480
    /* Complement to obtain normal u-law value. */
    u_val = ~u_val;
481

482 483 484 485 486 487
    /*
     * Extract and bias the quantization bits. Then
     * shift up by the segment number and subtract out the bias.
     */
    t = ((u_val & QUANT_MASK) << 3) + BIAS;
    t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT;
488

489 490 491 492
    return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS));
}
#else
/* EPP (for Wine):
493
 * this array has been statically generated from the above routine
494
 */
495
static const unsigned short _u2l[] = {
496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535
0x8284, 0x8684, 0x8A84, 0x8E84, 0x9284, 0x9684, 0x9A84, 0x9E84,
0xA284, 0xA684, 0xAA84, 0xAE84, 0xB284, 0xB684, 0xBA84, 0xBE84,
0xC184, 0xC384, 0xC584, 0xC784, 0xC984, 0xCB84, 0xCD84, 0xCF84,
0xD184, 0xD384, 0xD584, 0xD784, 0xD984, 0xDB84, 0xDD84, 0xDF84,
0xE104, 0xE204, 0xE304, 0xE404, 0xE504, 0xE604, 0xE704, 0xE804,
0xE904, 0xEA04, 0xEB04, 0xEC04, 0xED04, 0xEE04, 0xEF04, 0xF004,
0xF0C4, 0xF144, 0xF1C4, 0xF244, 0xF2C4, 0xF344, 0xF3C4, 0xF444,
0xF4C4, 0xF544, 0xF5C4, 0xF644, 0xF6C4, 0xF744, 0xF7C4, 0xF844,
0xF8A4, 0xF8E4, 0xF924, 0xF964, 0xF9A4, 0xF9E4, 0xFA24, 0xFA64,
0xFAA4, 0xFAE4, 0xFB24, 0xFB64, 0xFBA4, 0xFBE4, 0xFC24, 0xFC64,
0xFC94, 0xFCB4, 0xFCD4, 0xFCF4, 0xFD14, 0xFD34, 0xFD54, 0xFD74,
0xFD94, 0xFDB4, 0xFDD4, 0xFDF4, 0xFE14, 0xFE34, 0xFE54, 0xFE74,
0xFE8C, 0xFE9C, 0xFEAC, 0xFEBC, 0xFECC, 0xFEDC, 0xFEEC, 0xFEFC,
0xFF0C, 0xFF1C, 0xFF2C, 0xFF3C, 0xFF4C, 0xFF5C, 0xFF6C, 0xFF7C,
0xFF88, 0xFF90, 0xFF98, 0xFFA0, 0xFFA8, 0xFFB0, 0xFFB8, 0xFFC0,
0xFFC8, 0xFFD0, 0xFFD8, 0xFFE0, 0xFFE8, 0xFFF0, 0xFFF8, 0x0000,
0x7D7C, 0x797C, 0x757C, 0x717C, 0x6D7C, 0x697C, 0x657C, 0x617C,
0x5D7C, 0x597C, 0x557C, 0x517C, 0x4D7C, 0x497C, 0x457C, 0x417C,
0x3E7C, 0x3C7C, 0x3A7C, 0x387C, 0x367C, 0x347C, 0x327C, 0x307C,
0x2E7C, 0x2C7C, 0x2A7C, 0x287C, 0x267C, 0x247C, 0x227C, 0x207C,
0x1EFC, 0x1DFC, 0x1CFC, 0x1BFC, 0x1AFC, 0x19FC, 0x18FC, 0x17FC,
0x16FC, 0x15FC, 0x14FC, 0x13FC, 0x12FC, 0x11FC, 0x10FC, 0x0FFC,
0x0F3C, 0x0EBC, 0x0E3C, 0x0DBC, 0x0D3C, 0x0CBC, 0x0C3C, 0x0BBC,
0x0B3C, 0x0ABC, 0x0A3C, 0x09BC, 0x093C, 0x08BC, 0x083C, 0x07BC,
0x075C, 0x071C, 0x06DC, 0x069C, 0x065C, 0x061C, 0x05DC, 0x059C,
0x055C, 0x051C, 0x04DC, 0x049C, 0x045C, 0x041C, 0x03DC, 0x039C,
0x036C, 0x034C, 0x032C, 0x030C, 0x02EC, 0x02CC, 0x02AC, 0x028C,
0x026C, 0x024C, 0x022C, 0x020C, 0x01EC, 0x01CC, 0x01AC, 0x018C,
0x0174, 0x0164, 0x0154, 0x0144, 0x0134, 0x0124, 0x0114, 0x0104,
0x00F4, 0x00E4, 0x00D4, 0x00C4, 0x00B4, 0x00A4, 0x0094, 0x0084,
0x0078, 0x0070, 0x0068, 0x0060, 0x0058, 0x0050, 0x0048, 0x0040,
0x0038, 0x0030, 0x0028, 0x0020, 0x0018, 0x0010, 0x0008, 0x0000,
};
static inline short ulaw2linear(unsigned char u_val)
{
    return (short)_u2l[u_val];
}
#endif

/* A-law to u-law conversion */
536
static inline unsigned char
537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554
alaw2ulaw(unsigned char aval)
{
    aval &= 0xff;
    return (unsigned char) ((aval & 0x80) ? (0xFF ^ _a2u[aval ^ 0xD5]) :
                            (0x7F ^ _a2u[aval ^ 0x55]));
}

/* u-law to A-law conversion */
static inline unsigned char
ulaw2alaw(unsigned char uval)
{
    uval &= 0xff;
    return (unsigned char) ((uval & 0x80) ? (0xD5 ^ (_u2a[0xFF ^ uval] - 1)) :
                            (unsigned char) (0x55 ^ (_u2a[0x7F ^ uval] - 1)));
}

/* -------------------------------------------------------------------------------*/

555 556
static void cvtXXalaw16K(PACMDRVSTREAMINSTANCE adsi,
                         const unsigned char* src, LPDWORD srcsize,
557 558 559 560 561
                         unsigned char* dst, LPDWORD dstsize)
{
    DWORD       len = min(*srcsize, *dstsize / 2);
    DWORD       i;
    short       w;
562

563 564 565 566 567 568 569 570 571
    *srcsize = len;
    *dstsize = len * 2;
    for (i = 0; i < len; i++)
    {
        w = alaw2linear(*src++);
        W16(dst, w);    dst += 2;
    }
}

572 573
static void cvtXX16alawK(PACMDRVSTREAMINSTANCE adsi,
                         const unsigned char* src, LPDWORD srcsize,
574 575 576 577 578 579 580 581 582 583 584 585 586
                         unsigned char* dst, LPDWORD dstsize)
{
    DWORD       len = min(*srcsize / 2, *dstsize);
    DWORD       i;

    *srcsize = len * 2;
    *dstsize = len;
    for (i = 0; i < len; i++)
    {
        *dst++ = linear2alaw(R16(src)); src += 2;
    }
}

587 588
static void cvtXXulaw16K(PACMDRVSTREAMINSTANCE adsi,
                         const unsigned char* src, LPDWORD srcsize,
589 590 591 592 593 594 595 596 597 598 599 600 601 602 603
                         unsigned char* dst, LPDWORD dstsize)
{
    DWORD       len = min(*srcsize, *dstsize / 2);
    DWORD       i;
    short       w;

    *srcsize = len;
    *dstsize = len * 2;
    for (i = 0; i < len; i++)
    {
        w = ulaw2linear(*src++);
        W16(dst, w);    dst += 2;
    }
}

604 605
static void cvtXX16ulawK(PACMDRVSTREAMINSTANCE adsi,
                         const unsigned char* src, LPDWORD srcsize,
606 607 608 609 610 611 612 613 614 615 616 617 618
                         unsigned char* dst, LPDWORD dstsize)
{
    DWORD       len = min(*srcsize / 2, *dstsize);
    DWORD       i;

    *srcsize = len * 2;
    *dstsize = len;
    for (i = 0; i < len; i++)
    {
        *dst++ = linear2ulaw(R16(src)); src += 2;
    }
}

619 620
static void cvtXXalawulawK(PACMDRVSTREAMINSTANCE adsi,
                           const unsigned char* src, LPDWORD srcsize,
621 622 623 624 625 626 627 628 629 630 631 632 633
                           unsigned char* dst, LPDWORD dstsize)
{
    DWORD       len = min(*srcsize, *dstsize);
    DWORD       i;

    *srcsize = len;
    *dstsize = len;

    for (i = 0; i < len; i++)
        *dst++ = alaw2ulaw(*src++);
}


634 635
static void cvtXXulawalawK(PACMDRVSTREAMINSTANCE adsi,
                           const unsigned char* src, LPDWORD srcsize,
636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662
                           unsigned char* dst, LPDWORD dstsize)
{
    DWORD       len = min(*srcsize, *dstsize);
    DWORD       i;

    *srcsize = len;
    *dstsize = len;

    for (i = 0; i < len; i++)
        *dst++ = ulaw2alaw(*src++);
}

/***********************************************************************
 *           G711_DriverDetails
 *
 */
static	LRESULT G711_DriverDetails(PACMDRIVERDETAILSW add)
{
    add->fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC;
    add->fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED;
    add->wMid = 0xFF;
    add->wPid = 0x00;
    add->vdwACM = 0x01000000;
    add->vdwDriver = 0x01000000;
    add->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
    add->cFormatTags = 3; /* PCM, G711 A-LAW & MU-LAW */
    add->cFilterTags = 0;
663
    add->hicon = NULL;
664 665 666 667 668 669 670 671 672
    MultiByteToWideChar( CP_ACP, 0, "WINE-G711", -1,
                         add->szShortName, sizeof(add->szShortName)/sizeof(WCHAR) );
    MultiByteToWideChar( CP_ACP, 0, "Wine G711 converter", -1,
                         add->szLongName, sizeof(add->szLongName)/sizeof(WCHAR) );
    MultiByteToWideChar( CP_ACP, 0, "Brought to you by the Wine team...", -1,
                         add->szCopyright, sizeof(add->szCopyright)/sizeof(WCHAR) );
    MultiByteToWideChar( CP_ACP, 0, "Refer to LICENSE file", -1,
                         add->szLicensing, sizeof(add->szLicensing)/sizeof(WCHAR) );
    add->szFeatures[0] = 0;
673

674 675 676 677 678 679 680 681 682
    return MMSYSERR_NOERROR;
}

/***********************************************************************
 *           G711_FormatTagDetails
 *
 */
static	LRESULT	G711_FormatTagDetails(PACMFORMATTAGDETAILSW aftd, DWORD dwQuery)
{
683 684 685
    static const WCHAR szPcm[]={'P','C','M',0};
    static const WCHAR szALaw[]={'A','-','L','a','w',0};
    static const WCHAR szULaw[]={'U','-','L','a','w',0};
686 687

    switch (dwQuery)
688 689 690 691 692
    {
    case ACM_FORMATTAGDETAILSF_INDEX:
	if (aftd->dwFormatTagIndex >= 3) return ACMERR_NOTPOSSIBLE;
	break;
    case ACM_FORMATTAGDETAILSF_LARGESTSIZE:
693
	if (aftd->dwFormatTag == WAVE_FORMAT_UNKNOWN)
694 695 696 697 698
        {
            aftd->dwFormatTagIndex = 1;
	    break;
	}
	/* fall thru */
699 700
    case ACM_FORMATTAGDETAILSF_FORMATTAG:
	switch (aftd->dwFormatTag)
701 702 703 704 705 706 707 708
        {
	case WAVE_FORMAT_PCM:	aftd->dwFormatTagIndex = 0; break;
	case WAVE_FORMAT_ALAW:  aftd->dwFormatTagIndex = 1; break;
	case WAVE_FORMAT_MULAW: aftd->dwFormatTagIndex = 2; break;
	default:		return ACMERR_NOTPOSSIBLE;
	}
	break;
    default:
709
	WARN("Unsupported query %08x\n", dwQuery);
710 711
	return MMSYSERR_NOTSUPPORTED;
    }
712

713
    aftd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
714
    switch (aftd->dwFormatTagIndex)
715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743
    {
    case 0:
	aftd->dwFormatTag = WAVE_FORMAT_PCM;
	aftd->cbFormatSize = sizeof(PCMWAVEFORMAT);
	aftd->cStandardFormats = NUM_PCM_FORMATS;
        lstrcpyW(aftd->szFormatTag, szPcm);
        break;
    case 1:
	aftd->dwFormatTag = WAVE_FORMAT_ALAW;
	aftd->cbFormatSize = sizeof(WAVEFORMATEX);
	aftd->cStandardFormats = NUM_ALAW_FORMATS;
        lstrcpyW(aftd->szFormatTag, szALaw);
	break;
    case 2:
	aftd->dwFormatTag = WAVE_FORMAT_MULAW;
	aftd->cbFormatSize = sizeof(WAVEFORMATEX);
	aftd->cStandardFormats = NUM_ULAW_FORMATS;
        lstrcpyW(aftd->szFormatTag, szULaw);
	break;
    }
    return MMSYSERR_NOERROR;
}

/***********************************************************************
 *           G711_FormatDetails
 *
 */
static	LRESULT	G711_FormatDetails(PACMFORMATDETAILSW afd, DWORD dwQuery)
{
744
    switch (dwQuery)
745 746 747 748 749 750
    {
    case ACM_FORMATDETAILSF_FORMAT:
	if (G711_GetFormatIndex(afd->pwfx) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
	break;
    case ACM_FORMATDETAILSF_INDEX:
	afd->pwfx->wFormatTag = afd->dwFormatTag;
751
	switch (afd->dwFormatTag)
752 753 754 755 756 757 758 759 760 761 762 763 764 765 766
        {
	case WAVE_FORMAT_PCM:
	    if (afd->dwFormatIndex >= NUM_PCM_FORMATS) return ACMERR_NOTPOSSIBLE;
	    afd->pwfx->nChannels = PCM_Formats[afd->dwFormatIndex].nChannels;
	    afd->pwfx->nSamplesPerSec = PCM_Formats[afd->dwFormatIndex].rate;
	    afd->pwfx->wBitsPerSample = PCM_Formats[afd->dwFormatIndex].nBits;
	    afd->pwfx->nBlockAlign = afd->pwfx->nChannels * 2;
	    afd->pwfx->nAvgBytesPerSec = afd->pwfx->nSamplesPerSec * afd->pwfx->nBlockAlign;
	    break;
	case WAVE_FORMAT_ALAW:
	    if (afd->dwFormatIndex >= NUM_ALAW_FORMATS) return ACMERR_NOTPOSSIBLE;
	    afd->pwfx->nChannels = ALaw_Formats[afd->dwFormatIndex].nChannels;
	    afd->pwfx->nSamplesPerSec = ALaw_Formats[afd->dwFormatIndex].rate;
	    afd->pwfx->wBitsPerSample = ALaw_Formats[afd->dwFormatIndex].nBits;
	    afd->pwfx->nBlockAlign = ALaw_Formats[afd->dwFormatIndex].nChannels;
767
	    afd->pwfx->nAvgBytesPerSec = afd->pwfx->nSamplesPerSec * afd->pwfx->nChannels;
768 769 770 771 772 773 774 775
            afd->pwfx->cbSize = 0;
	    break;
	case WAVE_FORMAT_MULAW:
	    if (afd->dwFormatIndex >= NUM_ULAW_FORMATS) return ACMERR_NOTPOSSIBLE;
	    afd->pwfx->nChannels = ULaw_Formats[afd->dwFormatIndex].nChannels;
	    afd->pwfx->nSamplesPerSec = ULaw_Formats[afd->dwFormatIndex].rate;
	    afd->pwfx->wBitsPerSample = ULaw_Formats[afd->dwFormatIndex].nBits;
	    afd->pwfx->nBlockAlign = ULaw_Formats[afd->dwFormatIndex].nChannels;
776
	    afd->pwfx->nAvgBytesPerSec = afd->pwfx->nSamplesPerSec * afd->pwfx->nChannels;
777 778 779
            afd->pwfx->cbSize = 0;
	    break;
	default:
780
            WARN("Unsupported tag %08x\n", afd->dwFormatTag);
781 782 783 784
	    return MMSYSERR_INVALPARAM;
	}
	break;
    default:
785
	WARN("Unsupported query %08x\n", dwQuery);
786
	return MMSYSERR_NOTSUPPORTED;
787 788 789
    }
    afd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
    afd->szFormat[0] = 0; /* let MSACM format this for us... */
790

791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811
    return MMSYSERR_NOERROR;
}

/***********************************************************************
 *           G711_FormatSuggest
 *
 */
static	LRESULT	G711_FormatSuggest(PACMDRVFORMATSUGGEST adfs)
{
    /* some tests ... */
    if (adfs->cbwfxSrc < sizeof(PCMWAVEFORMAT) ||
	adfs->cbwfxDst < sizeof(PCMWAVEFORMAT) ||
	G711_GetFormatIndex(adfs->pwfxSrc) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
    /* FIXME: should do those tests against the real size (according to format tag */

    /* If no suggestion for destination, then copy source value */
    if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NCHANNELS))
	adfs->pwfxDst->nChannels = adfs->pwfxSrc->nChannels;
    if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NSAMPLESPERSEC))
        adfs->pwfxDst->nSamplesPerSec = adfs->pwfxSrc->nSamplesPerSec;

812
    if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WBITSPERSAMPLE))
813
    {
814
	if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM)
815 816 817 818
            adfs->pwfxDst->wBitsPerSample = 8;
        else
            adfs->pwfxDst->wBitsPerSample = 16;
    }
819
    if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG))
820 821 822 823 824 825 826 827 828 829 830 831 832 833 834
    {
	switch (adfs->pwfxSrc->wFormatTag)
        {
        case WAVE_FORMAT_PCM:   adfs->pwfxDst->wFormatTag = WAVE_FORMAT_ALAW; break;
        case WAVE_FORMAT_ALAW:  adfs->pwfxDst->wFormatTag = WAVE_FORMAT_PCM; break;
        case WAVE_FORMAT_MULAW: adfs->pwfxDst->wFormatTag = WAVE_FORMAT_PCM; break;
        }
    }
    /* check if result is ok */
    if (G711_GetFormatIndex(adfs->pwfxDst) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;

    /* recompute other values */
    switch (adfs->pwfxDst->wFormatTag)
    {
    case WAVE_FORMAT_PCM:
835
        adfs->pwfxDst->nBlockAlign = adfs->pwfxDst->nChannels * 2;
836 837 838
        adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * adfs->pwfxDst->nBlockAlign;
        break;
    case WAVE_FORMAT_ALAW:
839 840
        adfs->pwfxDst->nBlockAlign = adfs->pwfxDst->nChannels;
        adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * adfs->pwfxSrc->nChannels;
841 842
        break;
    case WAVE_FORMAT_MULAW:
843 844
        adfs->pwfxDst->nBlockAlign = adfs->pwfxDst->nChannels;
        adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * adfs->pwfxSrc->nChannels;
845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870
        break;
    default:
        FIXME("\n");
        break;
    }

    return MMSYSERR_NOERROR;
}

/***********************************************************************
 *           G711_Reset
 *
 */
static	void	G711_Reset(PACMDRVSTREAMINSTANCE adsi, AcmG711Data* aad)
{
}

/***********************************************************************
 *           G711_StreamOpen
 *
 */
static	LRESULT	G711_StreamOpen(PACMDRVSTREAMINSTANCE adsi)
{
    AcmG711Data*	aad;

    assert(!(adsi->fdwOpen & ACM_STREAMOPENF_ASYNC));
871

872 873 874
    if (G711_GetFormatIndex(adsi->pwfxSrc) == 0xFFFFFFFF ||
	G711_GetFormatIndex(adsi->pwfxDst) == 0xFFFFFFFF)
	return ACMERR_NOTPOSSIBLE;
875

876 877
    aad = HeapAlloc(GetProcessHeap(), 0, sizeof(AcmG711Data));
    if (aad == 0) return MMSYSERR_NOMEM;
878

879
    adsi->dwDriver = (DWORD_PTR)aad;
880

881
    if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
882
	adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
883 884 885 886
    {
	goto theEnd;
    }
    else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ALAW &&
887
             adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
888
    {
889
	/* resampling or mono <=> stereo not available
890 891 892 893 894 895 896 897 898 899 900 901
         * G711 algo only define 16 bit per sample output
         */
	if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
	    adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
            adsi->pwfxDst->wBitsPerSample != 16)
	    goto theEnd;

	/* g711 A-Law decoding... */
	if (adsi->pwfxDst->wBitsPerSample == 16)
	    aad->convert = cvtXXalaw16K;
    }
    else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
902
             adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ALAW)
903 904 905 906 907
    {
	if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
	    adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
            adsi->pwfxSrc->wBitsPerSample != 16)
	    goto theEnd;
908

909 910 911 912 913
	/* g711 coding... */
	if (adsi->pwfxSrc->wBitsPerSample == 16)
	    aad->convert = cvtXX16alawK;
    }
    else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MULAW &&
914
             adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
915
    {
916
	/* resampling or mono <=> stereo not available
917 918 919 920 921 922 923 924 925 926 927 928
         * G711 algo only define 16 bit per sample output
         */
	if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
	    adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
            adsi->pwfxDst->wBitsPerSample != 16)
	    goto theEnd;

	/* g711 MU-Law decoding... */
	if (adsi->pwfxDst->wBitsPerSample == 16)
	    aad->convert = cvtXXulaw16K;
    }
    else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
929
             adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MULAW)
930 931 932 933 934
    {
	if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
	    adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
            adsi->pwfxSrc->wBitsPerSample != 16)
	    goto theEnd;
935

936 937 938 939 940
	/* g711 coding... */
	if (adsi->pwfxSrc->wBitsPerSample == 16)
	    aad->convert = cvtXX16ulawK;
    }
    else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MULAW &&
941
             adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ALAW)
942 943 944 945
    {
	if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
	    adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels)
	    goto theEnd;
946

947 948 949 950
	/* MU-Law => A-Law... */
        aad->convert = cvtXXulawalawK;
    }
    else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ALAW &&
951
             adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MULAW)
952 953 954 955
    {
	if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
	    adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels)
	    goto theEnd;
956

957 958 959 960 961 962 963 964
	/* A-Law => MU-Law... */
        aad->convert = cvtXXalawulawK;
    }
    else goto theEnd;

    G711_Reset(adsi, aad);

    return MMSYSERR_NOERROR;
965

966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985
 theEnd:
    HeapFree(GetProcessHeap(), 0, aad);
    adsi->dwDriver = 0L;
    return MMSYSERR_NOTSUPPORTED;
}

/***********************************************************************
 *           G711_StreamClose
 *
 */
static	LRESULT	G711_StreamClose(PACMDRVSTREAMINSTANCE adsi)
{
    HeapFree(GetProcessHeap(), 0, (void*)adsi->dwDriver);
    return MMSYSERR_NOERROR;
}

/***********************************************************************
 *           G711_StreamSize
 *
 */
986
static	LRESULT G711_StreamSize(const ACMDRVSTREAMINSTANCE *adsi, PACMDRVSTREAMSIZE adss)
987
{
988
    switch (adss->fdwSize)
989 990 991 992 993 994 995
    {
    case ACM_STREAMSIZEF_DESTINATION:
	/* cbDstLength => cbSrcLength */
	if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
	    (adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ALAW ||
             adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MULAW))
        {
996
	    adss->cbSrcLength = adss->cbDstLength * 2;
997 998 999
	}
        else if ((adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ALAW ||
                  adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MULAW) &&
1000
                 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
1001
        {
1002
	    adss->cbSrcLength = adss->cbDstLength / 2;
1003 1004 1005 1006 1007 1008 1009 1010
	}
        else if ((adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ALAW ||
                  adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MULAW) &&
                 (adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ALAW ||
                  adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MULAW))
        {
	    adss->cbSrcLength = adss->cbDstLength;
        }
1011
        else
1012 1013 1014 1015 1016 1017 1018 1019 1020 1021
        {
	    return MMSYSERR_NOTSUPPORTED;
	}
	break;
    case ACM_STREAMSIZEF_SOURCE:
	/* cbSrcLength => cbDstLength */
	if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
	    (adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ALAW ||
             adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MULAW))
        {
1022
	    adss->cbDstLength = adss->cbSrcLength / 2;
1023 1024 1025
	}
        else if ((adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ALAW ||
                  adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MULAW) &&
1026
                 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
1027
        {
1028
	    adss->cbDstLength = adss->cbSrcLength * 2;
1029 1030 1031 1032 1033 1034 1035 1036
	}
        else if ((adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ALAW ||
                  adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MULAW) &&
                 (adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ALAW ||
                  adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MULAW))
        {
	    adss->cbDstLength = adss->cbSrcLength;
        }
1037
        else
1038 1039 1040 1041 1042
        {
	    return MMSYSERR_NOTSUPPORTED;
	}
	break;
    default:
1043
	WARN("Unsupported query %08x\n", adss->fdwSize);
1044
	return MMSYSERR_NOTSUPPORTED;
1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058
    }
    FIXME("\n");
    return MMSYSERR_NOERROR;
}

/***********************************************************************
 *           G711_StreamConvert
 *
 */
static LRESULT G711_StreamConvert(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMHEADER adsh)
{
    AcmG711Data*	aad = (AcmG711Data*)adsi->dwDriver;
    DWORD		nsrc = adsh->cbSrcLength;
    DWORD		ndst = adsh->cbDstLength;
1059 1060

    if (adsh->fdwConvert &
1061 1062
	~(ACM_STREAMCONVERTF_BLOCKALIGN|
	  ACM_STREAMCONVERTF_END|
1063
	  ACM_STREAMCONVERTF_START))
1064
    {
1065
	FIXME("Unsupported fdwConvert (%08x), ignoring it\n", adsh->fdwConvert);
1066 1067 1068 1069 1070 1071
    }
    /* ACM_STREAMCONVERTF_BLOCKALIGN
     *	currently all conversions are block aligned, so do nothing for this flag
     * ACM_STREAMCONVERTF_END
     *	no pending data, so do nothing for this flag
     */
1072
    if ((adsh->fdwConvert & ACM_STREAMCONVERTF_START))
1073 1074 1075 1076 1077 1078 1079
    {
	G711_Reset(adsi, aad);
    }

    aad->convert(adsi, adsh->pbSrc, &nsrc, adsh->pbDst, &ndst);
    adsh->cbSrcLengthUsed = nsrc;
    adsh->cbDstLengthUsed = ndst;
1080

1081 1082 1083 1084 1085 1086
    return MMSYSERR_NOERROR;
}

/**************************************************************************
 * 			G711_DriverProc			[exported]
 */
1087
LRESULT CALLBACK G711_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg,
1088 1089
					 LPARAM dwParam1, LPARAM dwParam2)
{
1090 1091
    TRACE("(%08lx %p %04x %08lx %08lx);\n",
          dwDevID, hDriv, wMsg, dwParam1, dwParam2);
1092 1093

    switch (wMsg)
1094 1095 1096 1097 1098
    {
    case DRV_LOAD:		return 1;
    case DRV_FREE:		return 1;
    case DRV_OPEN:		return G711_drvOpen((LPSTR)dwParam1);
    case DRV_CLOSE:		return G711_drvClose(dwDevID);
1099
    case DRV_ENABLE:		return 1;
1100 1101 1102 1103 1104
    case DRV_DISABLE:		return 1;
    case DRV_QUERYCONFIGURE:	return 1;
    case DRV_CONFIGURE:		MessageBoxA(0, "MS G711 (a-Law & mu-Law) filter !", "Wine Driver", MB_OK); return 1;
    case DRV_INSTALL:		return DRVCNF_RESTART;
    case DRV_REMOVE:		return DRVCNF_RESTART;
1105

1106 1107 1108
    case ACMDM_DRIVER_NOTIFY:
	/* no caching from other ACM drivers is done so far */
	return MMSYSERR_NOERROR;
1109

1110 1111
    case ACMDM_DRIVER_DETAILS:
	return G711_DriverDetails((PACMDRIVERDETAILSW)dwParam1);
1112

1113 1114
    case ACMDM_FORMATTAG_DETAILS:
	return G711_FormatTagDetails((PACMFORMATTAGDETAILSW)dwParam1, dwParam2);
1115

1116 1117
    case ACMDM_FORMAT_DETAILS:
	return G711_FormatDetails((PACMFORMATDETAILSW)dwParam1, dwParam2);
1118

1119 1120
    case ACMDM_FORMAT_SUGGEST:
	return G711_FormatSuggest((PACMDRVFORMATSUGGEST)dwParam1);
1121

1122 1123
    case ACMDM_STREAM_OPEN:
	return G711_StreamOpen((PACMDRVSTREAMINSTANCE)dwParam1);
1124

1125 1126
    case ACMDM_STREAM_CLOSE:
	return G711_StreamClose((PACMDRVSTREAMINSTANCE)dwParam1);
1127

1128 1129
    case ACMDM_STREAM_SIZE:
	return G711_StreamSize((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMSIZE)dwParam2);
1130

1131 1132
    case ACMDM_STREAM_CONVERT:
	return G711_StreamConvert((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMHEADER)dwParam2);
1133

1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146
    case ACMDM_HARDWARE_WAVE_CAPS_INPUT:
    case ACMDM_HARDWARE_WAVE_CAPS_OUTPUT:
	/* this converter is not a hardware driver */
    case ACMDM_FILTERTAG_DETAILS:
    case ACMDM_FILTER_DETAILS:
	/* this converter is not a filter */
    case ACMDM_STREAM_RESET:
	/* only needed for asynchronous driver... we aren't, so just say it */
	return MMSYSERR_NOTSUPPORTED;
    case ACMDM_STREAM_PREPARE:
    case ACMDM_STREAM_UNPREPARE:
	/* nothing special to do here... so don't do anything */
	return MMSYSERR_NOERROR;
1147

1148 1149 1150 1151
    default:
	return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
    }
}