2 * msg711.drv - G711 codec driver
4 * Copyright 2001 Hidenori Takeshima
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * FIXME - no encoding.
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(msg711);
39 /***********************************************************************/
41 #define ACMDM_DRIVER_NOTIFY (ACMDM_BASE + 1)
42 #define ACMDM_DRIVER_DETAILS (ACMDM_BASE + 10)
44 #define ACMDM_HARDWARE_WAVE_CAPS_INPUT (ACMDM_BASE + 20)
45 #define ACMDM_HARDWARE_WAVE_CAPS_OUTPUT (ACMDM_BASE + 21)
47 #define ACMDM_FORMATTAG_DETAILS (ACMDM_BASE + 25)
48 #define ACMDM_FORMAT_DETAILS (ACMDM_BASE + 26)
49 #define ACMDM_FORMAT_SUGGEST (ACMDM_BASE + 27)
51 #define ACMDM_FILTERTAG_DETAILS (ACMDM_BASE + 50)
52 #define ACMDM_FILTER_DETAILS (ACMDM_BASE + 51)
54 #define ACMDM_STREAM_OPEN (ACMDM_BASE + 76)
55 #define ACMDM_STREAM_CLOSE (ACMDM_BASE + 77)
56 #define ACMDM_STREAM_SIZE (ACMDM_BASE + 78)
57 #define ACMDM_STREAM_CONVERT (ACMDM_BASE + 79)
58 #define ACMDM_STREAM_RESET (ACMDM_BASE + 80)
59 #define ACMDM_STREAM_PREPARE (ACMDM_BASE + 81)
60 #define ACMDM_STREAM_UNPREPARE (ACMDM_BASE + 82)
61 #define ACMDM_STREAM_UPDATE (ACMDM_BASE + 83)
63 typedef struct _ACMDRVSTREAMINSTANCE
66 PWAVEFORMATEX pwfxSrc;
67 PWAVEFORMATEX pwfxDst;
75 } ACMDRVSTREAMINSTANCE, *PACMDRVSTREAMINSTANCE;
77 typedef struct _ACMDRVSTREAMHEADER *PACMDRVSTREAMHEADER;
78 typedef struct _ACMDRVSTREAMHEADER {
84 DWORD cbSrcLengthUsed;
88 DWORD cbDstLengthUsed;
92 PACMDRVSTREAMHEADER *padshNext;
96 /* Internal fields for ACM */
100 DWORD cbPreparedSrcLength;
101 LPBYTE pbPreparedDst;
102 DWORD cbPreparedDstLength;
103 } ACMDRVSTREAMHEADER;
105 typedef struct _ACMDRVSTREAMSIZE
111 } ACMDRVSTREAMSIZE, *PACMDRVSTREAMSIZE;
113 typedef struct _ACMDRVFORMATSUGGEST
117 PWAVEFORMATEX pwfxSrc;
119 PWAVEFORMATEX pwfxDst;
121 } ACMDRVFORMATSUGGEST, *PACMDRVFORMATSUGGEST;
126 /***********************************************************************/
137 typedef struct CodecImpl
142 /***********************************************************************/
144 static const WORD dec_mulaw[256] =
146 0x8284, 0x8684, 0x8A84, 0x8E84, 0x9284, 0x9684, 0x9A84, 0x9E84,
147 0xA284, 0xA684, 0xAA84, 0xAE84, 0xB284, 0xB684, 0xBA84, 0xBE84,
148 0xC184, 0xC384, 0xC584, 0xC784, 0xC984, 0xCB84, 0xCD84, 0xCF84,
149 0xD184, 0xD384, 0xD584, 0xD784, 0xD984, 0xDB84, 0xDD84, 0xDF84,
150 0xE104, 0xE204, 0xE304, 0xE404, 0xE504, 0xE604, 0xE704, 0xE804,
151 0xE904, 0xEA04, 0xEB04, 0xEC04, 0xED04, 0xEE04, 0xEF04, 0xF004,
152 0xF0C4, 0xF144, 0xF1C4, 0xF244, 0xF2C4, 0xF344, 0xF3C4, 0xF444,
153 0xF4C4, 0xF544, 0xF5C4, 0xF644, 0xF6C4, 0xF744, 0xF7C4, 0xF844,
154 0xF8A4, 0xF8E4, 0xF924, 0xF964, 0xF9A4, 0xF9E4, 0xFA24, 0xFA64,
155 0xFAA4, 0xFAE4, 0xFB24, 0xFB64, 0xFBA4, 0xFBE4, 0xFC24, 0xFC64,
156 0xFC94, 0xFCB4, 0xFCD4, 0xFCF4, 0xFD14, 0xFD34, 0xFD54, 0xFD74,
157 0xFD94, 0xFDB4, 0xFDD4, 0xFDF4, 0xFE14, 0xFE34, 0xFE54, 0xFE74,
158 0xFE8C, 0xFE9C, 0xFEAC, 0xFEBC, 0xFECC, 0xFEDC, 0xFEEC, 0xFEFC,
159 0xFF0C, 0xFF1C, 0xFF2C, 0xFF3C, 0xFF4C, 0xFF5C, 0xFF6C, 0xFF7C,
160 0xFF88, 0xFF90, 0xFF98, 0xFFA0, 0xFFA8, 0xFFB0, 0xFFB8, 0xFFC0,
161 0xFFC8, 0xFFD0, 0xFFD8, 0xFFE0, 0xFFE8, 0xFFF0, 0xFFF8, 0x0000,
162 0x7D7C, 0x797C, 0x757C, 0x717C, 0x6D7C, 0x697C, 0x657C, 0x617C,
163 0x5D7C, 0x597C, 0x557C, 0x517C, 0x4D7C, 0x497C, 0x457C, 0x417C,
164 0x3E7C, 0x3C7C, 0x3A7C, 0x387C, 0x367C, 0x347C, 0x327C, 0x307C,
165 0x2E7C, 0x2C7C, 0x2A7C, 0x287C, 0x267C, 0x247C, 0x227C, 0x207C,
166 0x1EFC, 0x1DFC, 0x1CFC, 0x1BFC, 0x1AFC, 0x19FC, 0x18FC, 0x17FC,
167 0x16FC, 0x15FC, 0x14FC, 0x13FC, 0x12FC, 0x11FC, 0x10FC, 0x0FFC,
168 0x0F3C, 0x0EBC, 0x0E3C, 0x0DBC, 0x0D3C, 0x0CBC, 0x0C3C, 0x0BBC,
169 0x0B3C, 0x0ABC, 0x0A3C, 0x09BC, 0x093C, 0x08BC, 0x083C, 0x07BC,
170 0x075C, 0x071C, 0x06DC, 0x069C, 0x065C, 0x061C, 0x05DC, 0x059C,
171 0x055C, 0x051C, 0x04DC, 0x049C, 0x045C, 0x041C, 0x03DC, 0x039C,
172 0x036C, 0x034C, 0x032C, 0x030C, 0x02EC, 0x02CC, 0x02AC, 0x028C,
173 0x026C, 0x024C, 0x022C, 0x020C, 0x01EC, 0x01CC, 0x01AC, 0x018C,
174 0x0174, 0x0164, 0x0154, 0x0144, 0x0134, 0x0124, 0x0114, 0x0104,
175 0x00F4, 0x00E4, 0x00D4, 0x00C4, 0x00B4, 0x00A4, 0x0094, 0x0084,
176 0x0078, 0x0070, 0x0068, 0x0060, 0x0058, 0x0050, 0x0048, 0x0040,
177 0x0038, 0x0030, 0x0028, 0x0020, 0x0018, 0x0010, 0x0008, 0x0000,
180 static const WORD dec_alaw[256] =
182 0xEA80, 0xEB80, 0xE880, 0xE980, 0xEE80, 0xEF80, 0xEC80, 0xED80,
183 0xE280, 0xE380, 0xE080, 0xE180, 0xE680, 0xE780, 0xE480, 0xE580,
184 0xF540, 0xF5C0, 0xF440, 0xF4C0, 0xF740, 0xF7C0, 0xF640, 0xF6C0,
185 0xF140, 0xF1C0, 0xF040, 0xF0C0, 0xF340, 0xF3C0, 0xF240, 0xF2C0,
186 0xAA00, 0xAE00, 0xA200, 0xA600, 0xBA00, 0xBE00, 0xB200, 0xB600,
187 0x8A00, 0x8E00, 0x8200, 0x8600, 0x9A00, 0x9E00, 0x9200, 0x9600,
188 0xD500, 0xD700, 0xD100, 0xD300, 0xDD00, 0xDF00, 0xD900, 0xDB00,
189 0xC500, 0xC700, 0xC100, 0xC300, 0xCD00, 0xCF00, 0xC900, 0xCB00,
190 0xFEA8, 0xFEB8, 0xFE88, 0xFE98, 0xFEE8, 0xFEF8, 0xFEC8, 0xFED8,
191 0xFE28, 0xFE38, 0xFE08, 0xFE18, 0xFE68, 0xFE78, 0xFE48, 0xFE58,
192 0xFFA8, 0xFFB8, 0xFF88, 0xFF98, 0xFFE8, 0xFFF8, 0xFFC8, 0xFFD8,
193 0xFF28, 0xFF38, 0xFF08, 0xFF18, 0xFF68, 0xFF78, 0xFF48, 0xFF58,
194 0xFAA0, 0xFAE0, 0xFA20, 0xFA60, 0xFBA0, 0xFBE0, 0xFB20, 0xFB60,
195 0xF8A0, 0xF8E0, 0xF820, 0xF860, 0xF9A0, 0xF9E0, 0xF920, 0xF960,
196 0xFD50, 0xFD70, 0xFD10, 0xFD30, 0xFDD0, 0xFDF0, 0xFD90, 0xFDB0,
197 0xFC50, 0xFC70, 0xFC10, 0xFC30, 0xFCD0, 0xFCF0, 0xFC90, 0xFCB0,
198 0x1580, 0x1480, 0x1780, 0x1680, 0x1180, 0x1080, 0x1380, 0x1280,
199 0x1D80, 0x1C80, 0x1F80, 0x1E80, 0x1980, 0x1880, 0x1B80, 0x1A80,
200 0x0AC0, 0x0A40, 0x0BC0, 0x0B40, 0x08C0, 0x0840, 0x09C0, 0x0940,
201 0x0EC0, 0x0E40, 0x0FC0, 0x0F40, 0x0CC0, 0x0C40, 0x0DC0, 0x0D40,
202 0x5600, 0x5200, 0x5E00, 0x5A00, 0x4600, 0x4200, 0x4E00, 0x4A00,
203 0x7600, 0x7200, 0x7E00, 0x7A00, 0x6600, 0x6200, 0x6E00, 0x6A00,
204 0x2B00, 0x2900, 0x2F00, 0x2D00, 0x2300, 0x2100, 0x2700, 0x2500,
205 0x3B00, 0x3900, 0x3F00, 0x3D00, 0x3300, 0x3100, 0x3700, 0x3500,
206 0x0158, 0x0148, 0x0178, 0x0168, 0x0118, 0x0108, 0x0138, 0x0128,
207 0x01D8, 0x01C8, 0x01F8, 0x01E8, 0x0198, 0x0188, 0x01B8, 0x01A8,
208 0x0058, 0x0048, 0x0078, 0x0068, 0x0018, 0x0008, 0x0038, 0x0028,
209 0x00D8, 0x00C8, 0x00F8, 0x00E8, 0x0098, 0x0088, 0x00B8, 0x00A8,
210 0x0560, 0x0520, 0x05E0, 0x05A0, 0x0460, 0x0420, 0x04E0, 0x04A0,
211 0x0760, 0x0720, 0x07E0, 0x07A0, 0x0660, 0x0620, 0x06E0, 0x06A0,
212 0x02B0, 0x0290, 0x02F0, 0x02D0, 0x0230, 0x0210, 0x0270, 0x0250,
213 0x03B0, 0x0390, 0x03F0, 0x03D0, 0x0330, 0x0310, 0x0370, 0x0350,
216 static LONG MSG711_Decode( const WORD* pdec, BYTE* pbDst, DWORD cbDstLength, DWORD* pcbDstLengthUsed, BYTE* pbSrc, DWORD cbSrcLength, DWORD* pcbSrcLengthUsed )
221 cSample = cbSrcLength;
222 if ( cSample > (cbDstLength>>1) )
223 cSample = (cbDstLength>>1);
225 *pcbSrcLengthUsed = cSample;
226 *pcbDstLengthUsed = cSample << 1;
228 while ( cSample-- > 0 )
231 *pbDst++ = LOBYTE(w);
232 *pbDst++ = HIBYTE(w);
235 return MMSYSERR_NOERROR;
239 /***********************************************************************/
241 static LONG Codec_DrvQueryConfigure( CodecImpl* This )
243 return MMSYSERR_NOTSUPPORTED;
246 static LONG Codec_DrvConfigure( CodecImpl* This, HWND hwnd, DRVCONFIGINFO* pinfo )
248 return MMSYSERR_NOTSUPPORTED;
251 static LONG Codec_DriverDetails( ACMDRIVERDETAILSW* pDrvDetails )
253 if ( pDrvDetails->cbStruct < sizeof(ACMDRIVERDETAILSW) )
254 return MMSYSERR_INVALPARAM;
256 ZeroMemory( pDrvDetails, sizeof(ACMDRIVERDETAILSW) );
257 pDrvDetails->cbStruct = sizeof(ACMDRIVERDETAILSW);
259 pDrvDetails->fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC;
260 pDrvDetails->fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED;
261 pDrvDetails->wMid = 0xff; /* FIXME? */
262 pDrvDetails->wPid = 0x00; /* FIXME? */
263 pDrvDetails->vdwACM = 0x01000000; /* FIXME? */
264 pDrvDetails->vdwDriver = 0x01000000; /* FIXME? */
265 pDrvDetails->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
266 pDrvDetails->cFormatTags = 3;
267 pDrvDetails->cFilterTags = 0;
268 pDrvDetails->hicon = (HICON)NULL;
269 MultiByteToWideChar( CP_ACP, 0, "WineG711", -1,
270 pDrvDetails->szShortName,
271 sizeof(pDrvDetails->szShortName)/sizeof(WCHAR) );
272 MultiByteToWideChar( CP_ACP, 0, "Wine G711 codec", -1,
273 pDrvDetails->szLongName,
274 sizeof(pDrvDetails->szLongName)/sizeof(WCHAR) );
275 MultiByteToWideChar( CP_ACP, 0, "Brought to you by the Wine team...", -1,
276 pDrvDetails->szCopyright,
277 sizeof(pDrvDetails->szCopyright)/sizeof(WCHAR) );
278 MultiByteToWideChar( CP_ACP, 0, "Refer to LICENSE file", -1,
279 pDrvDetails->szLicensing,
280 sizeof(pDrvDetails->szLicensing)/sizeof(WCHAR) );
281 pDrvDetails->szFeatures[0] = 0;
283 return MMSYSERR_NOERROR;
286 static LONG Codec_QueryAbout( void )
288 return MMSYSERR_NOTSUPPORTED;
291 static LONG Codec_About( HWND hwnd )
293 return MMSYSERR_NOTSUPPORTED;
296 /***********************************************************************/
298 static LONG Codec_FormatTagDetails( CodecImpl* This, ACMFORMATTAGDETAILSW* pFmtTagDetails, DWORD dwFlags )
300 FIXME( "enumerate tags\n" );
304 case ACM_FORMATTAGDETAILSF_INDEX:
305 switch ( pFmtTagDetails->dwFormatTagIndex )
308 pFmtTagDetails->dwFormatTag = 7; /* Mu-Law */
311 pFmtTagDetails->dwFormatTag = 6; /* A-Law */
314 pFmtTagDetails->dwFormatTag = 1; /* PCM */
317 return ACMERR_NOTPOSSIBLE;
320 case ACM_FORMATTAGDETAILSF_FORMATTAG:
321 switch ( pFmtTagDetails->dwFormatTag )
324 pFmtTagDetails->dwFormatTagIndex = 0;
327 pFmtTagDetails->dwFormatTagIndex = 1;
330 pFmtTagDetails->dwFormatTagIndex = 2;
333 return ACMERR_NOTPOSSIBLE;
336 case ACM_FORMATTAGDETAILSF_LARGESTSIZE:
337 if ( pFmtTagDetails->dwFormatTag != 0 &&
338 pFmtTagDetails->dwFormatTag != 1 &&
339 pFmtTagDetails->dwFormatTag != 6 &&
340 pFmtTagDetails->dwFormatTag != 7 )
341 return ACMERR_NOTPOSSIBLE;
342 pFmtTagDetails->dwFormatTagIndex = 0;
345 return MMSYSERR_NOTSUPPORTED;
348 pFmtTagDetails->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
349 pFmtTagDetails->cbFormatSize = sizeof(WAVEFORMATEX);
350 pFmtTagDetails->cStandardFormats = 3; /* FIXME */
351 pFmtTagDetails->szFormatTag[0] = 0; /* FIXME */
353 return MMSYSERR_NOERROR;
356 static LONG Codec_FormatDetails( CodecImpl* This, ACMFORMATDETAILSW* pFmtDetails, DWORD dwFlags )
358 FIXME( "enumerate standard formats\n" );
360 if ( pFmtDetails->cbStruct < sizeof(ACMFORMATDETAILSW) )
361 return MMSYSERR_INVALPARAM;
362 pFmtDetails->cbStruct = sizeof(ACMFORMATDETAILSW);
366 case ACM_FORMATDETAILSF_INDEX:
367 switch ( pFmtDetails->dwFormatIndex )
370 pFmtDetails->dwFormatTag = 7; /* Mu-Law */
373 pFmtDetails->dwFormatTag = 6; /* A-Law */
376 pFmtDetails->dwFormatTag = 1; /* PCM */
379 return MMSYSERR_INVALPARAM;
382 case ACM_FORMATDETAILSF_FORMAT:
383 switch ( pFmtDetails->dwFormatTag )
386 pFmtDetails->dwFormatIndex = 0;
389 pFmtDetails->dwFormatIndex = 1;
392 pFmtDetails->dwFormatIndex = 2;
395 return ACMERR_NOTPOSSIBLE;
399 return MMSYSERR_NOTSUPPORTED;
402 pFmtDetails->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
403 pFmtDetails->pwfx->wFormatTag = pFmtDetails->dwFormatTag;
404 pFmtDetails->pwfx->nChannels = 1;
405 pFmtDetails->pwfx->nSamplesPerSec = 8000;
406 pFmtDetails->pwfx->wBitsPerSample = 8;
407 if ( pFmtDetails->dwFormatTag == 1 )
409 pFmtDetails->cbwfx = sizeof(PCMWAVEFORMAT);
413 pFmtDetails->pwfx->cbSize = 0;
414 pFmtDetails->cbwfx = sizeof(WAVEFORMATEX);
416 pFmtDetails->szFormat[0] = 0; /* FIXME */
418 return MMSYSERR_NOERROR;
422 static LONG Codec_FormatSuggest( CodecImpl* This, ACMDRVFORMATSUGGEST* pFmtSuggest )
426 FIXME( "get suggested format\n" );
428 if ( pFmtSuggest->cbStruct != sizeof(ACMDRVFORMATSUGGEST) )
429 return MMSYSERR_INVALPARAM;
431 if ( pFmtSuggest->cbwfxSrc < sizeof(PCMWAVEFORMAT) ||
432 pFmtSuggest->cbwfxDst < sizeof(PCMWAVEFORMAT) )
433 return MMSYSERR_INVALPARAM;
435 fdwSuggest = pFmtSuggest->fdwSuggest;
437 if ( fdwSuggest & ACM_FORMATSUGGESTF_NCHANNELS )
439 if ( pFmtSuggest->pwfxSrc->nChannels != pFmtSuggest->pwfxDst->nChannels )
440 return ACMERR_NOTPOSSIBLE;
441 fdwSuggest &= ~ACM_FORMATSUGGESTF_NCHANNELS;
444 if ( fdwSuggest & ACM_FORMATSUGGESTF_NSAMPLESPERSEC )
446 if ( pFmtSuggest->pwfxSrc->nSamplesPerSec != pFmtSuggest->pwfxDst->nSamplesPerSec )
447 return ACMERR_NOTPOSSIBLE;
448 fdwSuggest &= ~ACM_FORMATSUGGESTF_NSAMPLESPERSEC;
451 if ( pFmtSuggest->pwfxSrc->wFormatTag == 1 )
454 if ( pFmtSuggest->cbwfxDst < sizeof(WAVEFORMATEX) )
455 return MMSYSERR_INVALPARAM;
456 if ( pFmtSuggest->pwfxSrc->wBitsPerSample != 16 )
457 return ACMERR_NOTPOSSIBLE;
459 if ( fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG )
461 if ( pFmtSuggest->pwfxDst->wFormatTag != 6 &&
462 pFmtSuggest->pwfxDst->wFormatTag != 7 )
463 return ACMERR_NOTPOSSIBLE;
464 fdwSuggest &= ~ACM_FORMATSUGGESTF_WFORMATTAG;
467 if ( fdwSuggest & ACM_FORMATSUGGESTF_WBITSPERSAMPLE )
469 if ( pFmtSuggest->pwfxDst->wBitsPerSample != 8 )
470 return ACMERR_NOTPOSSIBLE;
471 fdwSuggest &= ~ACM_FORMATSUGGESTF_WFORMATTAG;
474 if ( fdwSuggest != 0 )
475 return MMSYSERR_INVALFLAG;
477 if ( !(fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG) )
478 pFmtSuggest->pwfxDst->wFormatTag = 7;
479 pFmtSuggest->pwfxDst->nChannels = pFmtSuggest->pwfxSrc->nChannels;
480 pFmtSuggest->pwfxDst->nSamplesPerSec = pFmtSuggest->pwfxSrc->nSamplesPerSec;
481 pFmtSuggest->pwfxDst->nAvgBytesPerSec = pFmtSuggest->pwfxSrc->nSamplesPerSec * pFmtSuggest->pwfxSrc->nChannels;
482 pFmtSuggest->pwfxDst->nBlockAlign = pFmtSuggest->pwfxSrc->nChannels;
483 pFmtSuggest->pwfxDst->wBitsPerSample = 8;
484 pFmtSuggest->pwfxDst->cbSize = 0;
486 FIXME( "no compressor" );
487 return ACMERR_NOTPOSSIBLE;
492 if ( pFmtSuggest->cbwfxSrc < sizeof(WAVEFORMATEX) )
493 return MMSYSERR_INVALPARAM;
494 if ( pFmtSuggest->pwfxSrc->wFormatTag != 6 &&
495 pFmtSuggest->pwfxSrc->wFormatTag != 7 )
496 return ACMERR_NOTPOSSIBLE;
497 if ( pFmtSuggest->pwfxSrc->wBitsPerSample != 8 )
498 return ACMERR_NOTPOSSIBLE;
500 if ( fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG )
502 if ( pFmtSuggest->pwfxDst->wFormatTag != 1 )
503 return ACMERR_NOTPOSSIBLE;
504 fdwSuggest &= ~ACM_FORMATSUGGESTF_WFORMATTAG;
507 if ( fdwSuggest & ACM_FORMATSUGGESTF_WBITSPERSAMPLE )
509 if ( pFmtSuggest->pwfxDst->wBitsPerSample != 16 )
510 return ACMERR_NOTPOSSIBLE;
511 fdwSuggest &= ~ACM_FORMATSUGGESTF_WFORMATTAG;
514 if ( fdwSuggest != 0 )
515 return MMSYSERR_INVALFLAG;
517 pFmtSuggest->pwfxDst->wFormatTag = 1;
518 pFmtSuggest->pwfxDst->nChannels = pFmtSuggest->pwfxSrc->nChannels;
519 pFmtSuggest->pwfxDst->nSamplesPerSec = pFmtSuggest->pwfxSrc->nSamplesPerSec;
520 pFmtSuggest->pwfxDst->nAvgBytesPerSec = pFmtSuggest->pwfxSrc->nSamplesPerSec * pFmtSuggest->pwfxSrc->nChannels * 2;
521 pFmtSuggest->pwfxDst->nBlockAlign = pFmtSuggest->pwfxSrc->nChannels * 2;
522 pFmtSuggest->pwfxDst->wBitsPerSample = 16;
525 return MMSYSERR_NOERROR;
528 static LONG Codec_FilterTagDetails( CodecImpl* This, ACMFILTERTAGDETAILSW* pFilterTagDetails, DWORD dwFlags )
530 /* This is a codec driver. */
531 return MMSYSERR_NOTSUPPORTED;
534 static LONG Codec_FilterDetails( CodecImpl* This, ACMFILTERDETAILSW* pFilterDetails, DWORD dwFlags )
536 /* This is a codec driver. */
537 return MMSYSERR_NOTSUPPORTED;
540 static LONG Codec_StreamOpen( CodecImpl* This, ACMDRVSTREAMINSTANCE* pStreamInst )
542 enum CodecType codectype = CodecType_Invalid;
544 if ( pStreamInst->cbStruct != sizeof(ACMDRVSTREAMINSTANCE) )
546 TRACE("invalid size of struct\n");
547 return MMSYSERR_INVALPARAM;
550 if ( pStreamInst->fdwOpen & (~(ACM_STREAMOPENF_ASYNC|ACM_STREAMOPENF_NONREALTIME|ACM_STREAMOPENF_QUERY|CALLBACK_EVENT|CALLBACK_FUNCTION|CALLBACK_WINDOW)) )
552 TRACE("unknown flags\n");
553 return MMSYSERR_INVALFLAG;
556 /* No support for async operations. */
557 if ( pStreamInst->fdwOpen & ACM_STREAMOPENF_ASYNC )
558 return MMSYSERR_INVALFLAG;
560 /* This is a codec driver. */
561 if ( pStreamInst->pwfxSrc->nChannels != pStreamInst->pwfxDst->nChannels || pStreamInst->pwfxSrc->nSamplesPerSec != pStreamInst->pwfxDst->nSamplesPerSec )
562 return ACMERR_NOTPOSSIBLE;
563 if ( pStreamInst->pwfltr != NULL )
564 return ACMERR_NOTPOSSIBLE;
566 if ( pStreamInst->pwfxSrc->wFormatTag == 1 )
568 if ( pStreamInst->pwfxSrc->wBitsPerSample != 16 )
569 return ACMERR_NOTPOSSIBLE;
570 if ( pStreamInst->pwfxDst->wBitsPerSample != 8 )
571 return ACMERR_NOTPOSSIBLE;
573 /* Queried as a compressor */
574 FIXME( "Compressor is not implemented now\n" );
575 return ACMERR_NOTPOSSIBLE;
578 if ( pStreamInst->pwfxDst->wFormatTag == 1 )
580 if ( pStreamInst->pwfxDst->wBitsPerSample != 16 )
581 return ACMERR_NOTPOSSIBLE;
582 if ( pStreamInst->pwfxSrc->wBitsPerSample != 8 )
583 return ACMERR_NOTPOSSIBLE;
585 switch ( pStreamInst->pwfxSrc->wFormatTag )
588 TRACE( "A-Law deompressor\n" );
589 codectype = CodecType_DecALaw;
592 TRACE( "Mu-Law deompressor\n" );
593 codectype = CodecType_DecMuLaw;
596 return ACMERR_NOTPOSSIBLE;
601 return ACMERR_NOTPOSSIBLE;
604 if ( pStreamInst->fdwOpen & ACM_STREAMOPENF_QUERY )
605 return MMSYSERR_NOERROR;
607 pStreamInst->dwDriver = (DWORD)codectype;
609 return MMSYSERR_NOERROR;
612 static LONG Codec_StreamClose( CodecImpl* This, ACMDRVSTREAMINSTANCE* pStreamInst )
614 return MMSYSERR_NOERROR;
617 static LONG Codec_StreamSize( CodecImpl* This, ACMDRVSTREAMINSTANCE* pStreamInst, ACMDRVSTREAMSIZE* pStreamSize )
619 enum CodecType codectype;
622 if ( pStreamSize->cbStruct != sizeof(ACMDRVSTREAMSIZE) )
623 return MMSYSERR_INVALPARAM;
625 codectype = (enum CodecType)pStreamInst->dwDriver;
627 res = MMSYSERR_NOERROR;
630 case CodecType_EncMuLaw:
631 case CodecType_EncALaw:
632 if ( pStreamSize->fdwSize == ACM_STREAMSIZEF_SOURCE )
633 pStreamSize->cbDstLength = pStreamSize->cbSrcLength >> 1;
635 if ( pStreamSize->fdwSize == ACM_STREAMSIZEF_DESTINATION )
636 pStreamSize->cbSrcLength = pStreamSize->cbDstLength << 1;
638 res = MMSYSERR_INVALFLAG;
640 case CodecType_DecMuLaw:
641 case CodecType_DecALaw:
642 if ( pStreamSize->fdwSize == ACM_STREAMSIZEF_SOURCE )
643 pStreamSize->cbDstLength = pStreamSize->cbSrcLength << 1;
645 if ( pStreamSize->fdwSize == ACM_STREAMSIZEF_DESTINATION )
646 pStreamSize->cbSrcLength = pStreamSize->cbDstLength >> 1;
648 res = MMSYSERR_INVALFLAG;
651 ERR( "CodecType_Invalid\n" );
652 res = MMSYSERR_NOTSUPPORTED;
659 static LONG Codec_StreamConvert( CodecImpl* This, ACMDRVSTREAMINSTANCE* pStreamInst, ACMDRVSTREAMHEADER* pStreamHdr )
661 enum CodecType codectype;
664 codectype = (enum CodecType)pStreamInst->dwDriver;
666 res = MMSYSERR_NOTSUPPORTED;
669 case CodecType_EncMuLaw:
670 FIXME( "CodecType_EncMuLaw\n" );
672 case CodecType_EncALaw:
673 FIXME( "CodecType_EncALaw\n" );
675 case CodecType_DecMuLaw:
676 TRACE( "CodecType_DecMuLaw\n" );
677 res = MSG711_Decode( dec_mulaw, pStreamHdr->pbDst, pStreamHdr->cbDstLength, &pStreamHdr->cbDstLengthUsed, pStreamHdr->pbSrc, pStreamHdr->cbSrcLength, &pStreamHdr->cbSrcLengthUsed );
679 case CodecType_DecALaw:
680 TRACE( "CodecType_DecALaw\n" );
681 res = MSG711_Decode( dec_alaw, pStreamHdr->pbDst, pStreamHdr->cbDstLength, &pStreamHdr->cbDstLengthUsed, pStreamHdr->pbSrc, pStreamHdr->cbSrcLength, &pStreamHdr->cbSrcLengthUsed );
684 ERR( "CodecType_Invalid\n" );
691 static LONG Codec_StreamReset( CodecImpl* This, ACMDRVSTREAMINSTANCE* pStreamInst, DWORD dwFlags )
693 return MMSYSERR_NOTSUPPORTED;
696 static LONG Codec_StreamPrepare( CodecImpl* This, ACMDRVSTREAMINSTANCE* pStreamInst, ACMDRVSTREAMHEADER* pStreamHdr )
698 return MMSYSERR_NOTSUPPORTED;
701 static LONG Codec_StreamUnprepare( CodecImpl* This, ACMDRVSTREAMINSTANCE* pStreamInst, ACMDRVSTREAMHEADER* pStreamHdr )
703 return MMSYSERR_NOTSUPPORTED;
708 /***********************************************************************/
710 static CodecImpl* Codec_AllocDriver( void )
714 This = HeapAlloc( GetProcessHeap(), 0, sizeof(CodecImpl) );
717 ZeroMemory( This, sizeof(CodecImpl) );
719 /* initialize members. */
724 static void Codec_Close( CodecImpl* This )
727 HeapFree( GetProcessHeap(), 0, This );
732 /***********************************************************************/
734 LONG WINAPI MSG711_DriverProc(
735 DWORD dwDriverId, HDRVR hdrvr, UINT msg, LONG lParam1, LONG lParam2 )
737 TRACE( "DriverProc(%08lx,%08x,%08x,%08lx,%08lx)\n",
738 dwDriverId, hdrvr, msg, lParam1, lParam2 );
750 return (LONG)Codec_AllocDriver();
752 TRACE("DRV_CLOSE\n");
753 Codec_Close( (CodecImpl*)dwDriverId );
756 TRACE("DRV_ENABLE\n");
759 TRACE("DRV_DISABLE\n");
761 case DRV_QUERYCONFIGURE:
762 TRACE("DRV_QUERYCONFIGURE\n");
763 return Codec_DrvQueryConfigure( (CodecImpl*)dwDriverId );
765 TRACE("DRV_CONFIGURE\n");
766 return Codec_DrvConfigure( (CodecImpl*)dwDriverId,
767 (HWND)lParam1, (DRVCONFIGINFO*)lParam2 );
769 TRACE("DRV_INSTALL\n");
772 TRACE("DRV_REMOVE\n");
775 TRACE("DRV_POWER\n");
778 case ACMDM_DRIVER_NOTIFY:
779 return MMSYSERR_NOERROR;
780 case ACMDM_DRIVER_DETAILS:
781 return Codec_DriverDetails((ACMDRIVERDETAILSW*)lParam1);
782 case ACMDM_DRIVER_ABOUT:
783 TRACE("ACMDM_DRIVER_ABOUT\n");
784 return (lParam1 == -1) ? Codec_QueryAbout() : Codec_About( (HWND)lParam1 );
786 case ACMDM_HARDWARE_WAVE_CAPS_INPUT:
787 return MMSYSERR_NOTSUPPORTED;
788 case ACMDM_HARDWARE_WAVE_CAPS_OUTPUT:
789 return MMSYSERR_NOTSUPPORTED;
791 case ACMDM_FORMATTAG_DETAILS:
792 return Codec_FormatTagDetails( (CodecImpl*)dwDriverId, (ACMFORMATTAGDETAILSW*)lParam1, (DWORD)lParam2 );
793 case ACMDM_FORMAT_DETAILS:
794 return Codec_FormatDetails( (CodecImpl*)dwDriverId, (ACMFORMATDETAILSW*)lParam1, (DWORD)lParam2 );
795 case ACMDM_FORMAT_SUGGEST:
796 return Codec_FormatSuggest( (CodecImpl*)dwDriverId, (ACMDRVFORMATSUGGEST*)lParam1 );
798 case ACMDM_FILTERTAG_DETAILS:
799 return Codec_FilterTagDetails( (CodecImpl*)dwDriverId, (ACMFILTERTAGDETAILSW*)lParam1, (DWORD)lParam2 );
800 case ACMDM_FILTER_DETAILS:
801 return Codec_FilterDetails( (CodecImpl*)dwDriverId, (ACMFILTERDETAILSW*)lParam1, (DWORD)lParam2 );
803 case ACMDM_STREAM_OPEN:
804 return Codec_StreamOpen( (CodecImpl*)dwDriverId, (ACMDRVSTREAMINSTANCE*)lParam1 );
805 case ACMDM_STREAM_CLOSE:
806 return Codec_StreamClose( (CodecImpl*)dwDriverId, (ACMDRVSTREAMINSTANCE*)lParam1 );
807 case ACMDM_STREAM_SIZE:
808 return Codec_StreamSize( (CodecImpl*)dwDriverId, (ACMDRVSTREAMINSTANCE*)lParam1, (ACMDRVSTREAMSIZE*)lParam2 );
809 case ACMDM_STREAM_CONVERT:
810 return Codec_StreamConvert( (CodecImpl*)dwDriverId, (ACMDRVSTREAMINSTANCE*)lParam1, (ACMDRVSTREAMHEADER*)lParam2 );
811 case ACMDM_STREAM_RESET:
812 return Codec_StreamReset( (CodecImpl*)dwDriverId, (ACMDRVSTREAMINSTANCE*)lParam1, (DWORD)lParam2 );
813 case ACMDM_STREAM_PREPARE:
814 return Codec_StreamPrepare( (CodecImpl*)dwDriverId, (ACMDRVSTREAMINSTANCE*)lParam1, (ACMDRVSTREAMHEADER*)lParam2 );
815 case ACMDM_STREAM_UNPREPARE:
816 return Codec_StreamUnprepare( (CodecImpl*)dwDriverId, (ACMDRVSTREAMINSTANCE*)lParam1, (ACMDRVSTREAMHEADER*)lParam2 );
820 return DefDriverProc( dwDriverId, hdrvr, msg, lParam1, lParam2 );
823 /***********************************************************************/
825 BOOL WINAPI MSG711_DllMain( HINSTANCE hInst, DWORD dwReason, LPVOID lpvReserved )
827 TRACE( "(%08x,%08lx,%p)\n",hInst,dwReason,lpvReserved );