1 /* 2 * MS ADPCM handling 3 * 4 * Copyright (C) 2002 Eric Pouech 5 * 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 */ 21 22 #include <assert.h> 23 #include <stdarg.h> 24 #include <string.h> 25 #include "windef.h" 26 #include "winbase.h" 27 #include "wingdi.h" 28 #include "winuser.h" 29 #include "winnls.h" 30 #include "mmsystem.h" 31 #include "mmreg.h" 32 #include "msacm.h" 33 #include "msacmdrv.h" 34 #include "wine/debug.h" 35 36 /* see http://www.pcisys.net/~melanson/codecs/adpcm.txt for the details */ 37 38 WINE_DEFAULT_DEBUG_CHANNEL(adpcm); 39 40 /*********************************************************************** 41 * ADPCM_drvOpen 42 */ 43 static LRESULT ADPCM_drvOpen(LPCSTR str) 44 { 45 return 1; 46 } 47 48 /*********************************************************************** 49 * ADPCM_drvClose 50 */ 51 static LRESULT ADPCM_drvClose(DWORD_PTR dwDevID) 52 { 53 return 1; 54 } 55 56 typedef struct tagAcmAdpcmData 57 { 58 void (*convert)(const ACMDRVSTREAMINSTANCE *adsi, 59 const unsigned char*, LPDWORD, unsigned char*, LPDWORD); 60 } AcmAdpcmData; 61 62 /* table to list all supported formats... those are the basic ones. this 63 * also helps given a unique index to each of the supported formats 64 */ 65 typedef struct 66 { 67 int nChannels; 68 int nBits; 69 int rate; 70 } Format; 71 72 static const Format PCM_Formats[] = 73 { 74 {1, 8, 8000}, {2, 8, 8000}, {1, 16, 8000}, {2, 16, 8000}, 75 {1, 8, 11025}, {2, 8, 11025}, {1, 16, 11025}, {2, 16, 11025}, 76 {1, 8, 22050}, {2, 8, 22050}, {1, 16, 22050}, {2, 16, 22050}, 77 {1, 8, 44100}, {2, 8, 44100}, {1, 16, 44100}, {2, 16, 44100}, 78 }; 79 80 static const Format ADPCM_Formats[] = 81 { 82 {1, 4, 8000}, {2, 4, 8000}, {1, 4, 11025}, {2, 4, 11025}, 83 {1, 4, 22050}, {2, 4, 22050}, {1, 4, 44100}, {2, 4, 44100}, 84 }; 85 86 #define NUM_PCM_FORMATS (sizeof(PCM_Formats) / sizeof(PCM_Formats[0])) 87 #define NUM_ADPCM_FORMATS (sizeof(ADPCM_Formats) / sizeof(ADPCM_Formats[0])) 88 89 static int MS_Delta[] = 90 { 91 230, 230, 230, 230, 307, 409, 512, 614, 92 768, 614, 512, 409, 307, 230, 230, 230 93 }; 94 95 96 static ADPCMCOEFSET MSADPCM_CoeffSet[] = 97 { 98 {256, 0}, {512, -256}, {0, 0}, {192, 64}, {240, 0}, {460, -208}, {392, -232} 99 }; 100 101 /*********************************************************************** 102 * ADPCM_GetFormatIndex 103 */ 104 static DWORD ADPCM_GetFormatIndex(const WAVEFORMATEX* wfx) 105 { 106 int i, hi; 107 const Format* fmts; 108 109 switch (wfx->wFormatTag) 110 { 111 case WAVE_FORMAT_PCM: 112 hi = NUM_PCM_FORMATS; 113 fmts = PCM_Formats; 114 break; 115 case WAVE_FORMAT_ADPCM: 116 hi = NUM_ADPCM_FORMATS; 117 fmts = ADPCM_Formats; 118 break; 119 default: 120 return 0xFFFFFFFF; 121 } 122 123 for (i = 0; i < hi; i++) 124 { 125 if (wfx->nChannels == fmts[i].nChannels && 126 wfx->nSamplesPerSec == fmts[i].rate && 127 wfx->wBitsPerSample == fmts[i].nBits) 128 return i; 129 } 130 131 switch (wfx->wFormatTag) 132 { 133 case WAVE_FORMAT_PCM: 134 if(3 > wfx->nChannels && 135 wfx->nChannels > 0 && 136 wfx->nAvgBytesPerSec == 2 * wfx->nSamplesPerSec * wfx->nChannels && 137 wfx->nBlockAlign == 2 * wfx->nChannels && 138 wfx->wBitsPerSample == 16) 139 return hi; 140 break; 141 case WAVE_FORMAT_ADPCM: 142 if(3 > wfx->nChannels && 143 wfx->nChannels > 0 && 144 wfx->wBitsPerSample == 4 && 145 wfx->cbSize == 32) 146 return hi; 147 break; 148 } 149 150 return 0xFFFFFFFF; 151 } 152 153 static void init_wfx_adpcm(ADPCMWAVEFORMAT* awfx) 154 { 155 register WAVEFORMATEX* pwfx = &awfx->wfx; 156 157 /* we assume wFormatTag, nChannels, nSamplesPerSec and wBitsPerSample 158 * have been initialized... */ 159 160 if (pwfx->wFormatTag != WAVE_FORMAT_ADPCM) {FIXME("wrong FT\n"); return;} 161 if (ADPCM_GetFormatIndex(pwfx) == 0xFFFFFFFF) {FIXME("wrong fmt\n"); return;} 162 163 switch (pwfx->nSamplesPerSec) 164 { 165 case 8000: pwfx->nBlockAlign = 256 * pwfx->nChannels; break; 166 case 11025: pwfx->nBlockAlign = 256 * pwfx->nChannels; break; 167 case 22050: pwfx->nBlockAlign = 512 * pwfx->nChannels; break; 168 case 44100: pwfx->nBlockAlign = 1024 * pwfx->nChannels; break; 169 default: break; 170 } 171 pwfx->cbSize = 2 * sizeof(WORD) + 7 * sizeof(ADPCMCOEFSET); 172 /* 7 is the size of the block head (which contains two samples) */ 173 174 awfx->wSamplesPerBlock = pwfx->nBlockAlign * 2 / pwfx->nChannels - 12; 175 pwfx->nAvgBytesPerSec = (pwfx->nSamplesPerSec * pwfx->nBlockAlign) / awfx->wSamplesPerBlock; 176 awfx->wNumCoef = 7; 177 memcpy(awfx->aCoef, MSADPCM_CoeffSet, 7 * sizeof(ADPCMCOEFSET)); 178 } 179 180 /*********************************************************************** 181 * R16 182 * 183 * Read a 16 bit sample (correctly handles endianness) 184 */ 185 static inline short R16(const unsigned char* src) 186 { 187 return (short)((unsigned short)src[0] | ((unsigned short)src[1] << 8)); 188 } 189 190 /*********************************************************************** 191 * W16 192 * 193 * Write a 16 bit sample (correctly handles endianness) 194 */ 195 static inline void W16(unsigned char* dst, short s) 196 { 197 dst[0] = LOBYTE(s); 198 dst[1] = HIBYTE(s); 199 } 200 201 static inline void clamp_sample(int* sample) 202 { 203 if (*sample < -32768) *sample = -32768; 204 if (*sample > 32767) *sample = 32767; 205 } 206 207 static inline void process_nibble(unsigned nibble, int* idelta, 208 int* sample1, int* sample2, 209 const ADPCMCOEFSET* coeff) 210 { 211 int sample; 212 int snibble; 213 214 /* nibble is in fact a signed 4 bit integer => propagate sign if needed */ 215 snibble = (nibble & 0x08) ? (nibble - 16) : nibble; 216 sample = ((*sample1 * coeff->iCoef1) + (*sample2 * coeff->iCoef2)) / 256 + 217 snibble * *idelta; 218 clamp_sample(&sample); 219 220 *sample2 = *sample1; 221 *sample1 = sample; 222 *idelta = ((MS_Delta[nibble] * *idelta) / 256); 223 if (*idelta < 16) *idelta = 16; 224 } 225 226 static inline unsigned char C168(short s) 227 { 228 return HIBYTE(s) ^ (unsigned char)0x80; 229 } 230 231 static void cvtSSms16K(const ACMDRVSTREAMINSTANCE *adsi, 232 const unsigned char* src, LPDWORD nsrc, 233 unsigned char* dst, LPDWORD ndst) 234 { 235 int ideltaL, ideltaR; 236 int sample1L, sample2L; 237 int sample1R, sample2R; 238 ADPCMCOEFSET coeffL, coeffR; 239 int nsamp; 240 int nsamp_blk = ((ADPCMWAVEFORMAT*)adsi->pwfxSrc)->wSamplesPerBlock; 241 DWORD nblock = min(*nsrc / adsi->pwfxSrc->nBlockAlign, 242 *ndst / (nsamp_blk * adsi->pwfxDst->nBlockAlign)); 243 244 *nsrc = nblock * adsi->pwfxSrc->nBlockAlign; 245 *ndst = nblock * nsamp_blk * adsi->pwfxDst->nBlockAlign; 246 247 nsamp_blk -= 2; /* see below for samples from block head */ 248 for (; nblock > 0; nblock--) 249 { 250 const unsigned char* in_src = src; 251 252 /* Catch a problem from Tomb Raider III (bug 21000) where it passes 253 * invalid data after a valid sequence of blocks */ 254 if (*src > 6 || *(src + 1) > 6) 255 { 256 /* Recalculate the amount of used output buffer. We are not changing 257 * nsrc, let's assume the bad data was parsed */ 258 *ndst -= nblock * nsamp_blk * adsi->pwfxDst->nBlockAlign; 259 WARN("Invalid ADPCM data, stopping conversion\n"); 260 break; 261 } 262 coeffL = MSADPCM_CoeffSet[*src++]; 263 coeffR = MSADPCM_CoeffSet[*src++]; 264 265 ideltaL = R16(src); src += 2; 266 ideltaR = R16(src); src += 2; 267 sample1L = R16(src); src += 2; 268 sample1R = R16(src); src += 2; 269 sample2L = R16(src); src += 2; 270 sample2R = R16(src); src += 2; 271 272 if(adsi->pwfxDst->wBitsPerSample == 8){ 273 /* store samples from block head */ 274 *dst = C168(sample2L); ++dst; 275 *dst = C168(sample2R); ++dst; 276 *dst = C168(sample1L); ++dst; 277 *dst = C168(sample1R); ++dst; 278 279 for (nsamp = nsamp_blk; nsamp > 0; nsamp--) 280 { 281 process_nibble(*src >> 4, &ideltaL, &sample1L, &sample2L, &coeffL); 282 *dst = C168(sample1L); ++dst; 283 process_nibble(*src++ & 0x0F, &ideltaR, &sample1R, &sample2R, &coeffR); 284 *dst = C168(sample1R); ++dst; 285 } 286 }else if(adsi->pwfxDst->wBitsPerSample == 16){ 287 /* store samples from block head */ 288 W16(dst, sample2L); dst += 2; 289 W16(dst, sample2R); dst += 2; 290 W16(dst, sample1L); dst += 2; 291 W16(dst, sample1R); dst += 2; 292 293 for (nsamp = nsamp_blk; nsamp > 0; nsamp--) 294 { 295 process_nibble(*src >> 4, &ideltaL, &sample1L, &sample2L, &coeffL); 296 W16(dst, sample1L); dst += 2; 297 process_nibble(*src++ & 0x0F, &ideltaR, &sample1R, &sample2R, &coeffR); 298 W16(dst, sample1R); dst += 2; 299 } 300 } 301 src = in_src + adsi->pwfxSrc->nBlockAlign; 302 } 303 } 304 305 static void cvtMMms16K(const ACMDRVSTREAMINSTANCE *adsi, 306 const unsigned char* src, LPDWORD nsrc, 307 unsigned char* dst, LPDWORD ndst) 308 { 309 int idelta; 310 int sample1, sample2; 311 ADPCMCOEFSET coeff; 312 int nsamp; 313 int nsamp_blk = ((ADPCMWAVEFORMAT*)adsi->pwfxSrc)->wSamplesPerBlock; 314 DWORD nblock = min(*nsrc / adsi->pwfxSrc->nBlockAlign, 315 *ndst / (nsamp_blk * adsi->pwfxDst->nBlockAlign)); 316 317 *nsrc = nblock * adsi->pwfxSrc->nBlockAlign; 318 *ndst = nblock * nsamp_blk * adsi->pwfxDst->nBlockAlign; 319 320 nsamp_blk -= 2; /* see below for samples from block head */ 321 for (; nblock > 0; nblock--) 322 { 323 const unsigned char* in_src = src; 324 325 assert(*src <= 6); 326 coeff = MSADPCM_CoeffSet[*src++]; 327 328 idelta = R16(src); src += 2; 329 sample1 = R16(src); src += 2; 330 sample2 = R16(src); src += 2; 331 332 /* store samples from block head */ 333 if(adsi->pwfxDst->wBitsPerSample == 8){ 334 *dst = C168(sample2); ++dst; 335 *dst = C168(sample1); ++dst; 336 337 for (nsamp = nsamp_blk; nsamp > 0; nsamp -= 2) 338 { 339 process_nibble(*src >> 4, &idelta, &sample1, &sample2, &coeff); 340 *dst = C168(sample1); ++dst; 341 process_nibble(*src++ & 0x0F, &idelta, &sample1, &sample2, &coeff); 342 *dst = C168(sample1); ++dst; 343 } 344 }else if(adsi->pwfxDst->wBitsPerSample == 16){ 345 W16(dst, sample2); dst += 2; 346 W16(dst, sample1); dst += 2; 347 348 for (nsamp = nsamp_blk; nsamp > 0; nsamp -= 2) 349 { 350 process_nibble(*src >> 4, &idelta, &sample1, &sample2, &coeff); 351 W16(dst, sample1); dst += 2; 352 process_nibble(*src++ & 0x0F, &idelta, &sample1, &sample2, &coeff); 353 W16(dst, sample1); dst += 2; 354 } 355 } 356 357 src = in_src + adsi->pwfxSrc->nBlockAlign; 358 } 359 } 360 361 #if 0 362 static void cvtSS16msK(PACMDRVSTREAMINSTANCE adsi, 363 const unsigned char* src, LPDWORD nsrc, 364 unsigned char* dst, LPDWORD ndst) 365 { 366 } 367 368 static void cvtMM16msK(PACMDRVSTREAMINSTANCE adsi, 369 const unsigned char* src, LPDWORD nsrc, 370 unsigned char* dst, LPDWORD ndst) 371 { 372 } 373 #endif 374 375 /*********************************************************************** 376 * ADPCM_DriverDetails 377 * 378 */ 379 static LRESULT ADPCM_DriverDetails(PACMDRIVERDETAILSW add) 380 { 381 add->fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC; 382 add->fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED; 383 add->wMid = MM_MICROSOFT; 384 add->wPid = MM_MSFT_ACM_MSADPCM; 385 add->vdwACM = 0x01000000; 386 add->vdwDriver = 0x01000000; 387 add->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC; 388 add->cFormatTags = 2; /* PCM, MS ADPCM */ 389 add->cFilterTags = 0; 390 add->hicon = NULL; 391 MultiByteToWideChar( CP_ACP, 0, "MS-ADPCM", -1, 392 add->szShortName, sizeof(add->szShortName)/sizeof(WCHAR) ); 393 MultiByteToWideChar( CP_ACP, 0, "Wine MS ADPCM converter", -1, 394 add->szLongName, sizeof(add->szLongName)/sizeof(WCHAR) ); 395 MultiByteToWideChar( CP_ACP, 0, "Brought to you by the Wine team...", -1, 396 add->szCopyright, sizeof(add->szCopyright)/sizeof(WCHAR) ); 397 MultiByteToWideChar( CP_ACP, 0, "Refer to LICENSE file", -1, 398 add->szLicensing, sizeof(add->szLicensing)/sizeof(WCHAR) ); 399 add->szFeatures[0] = 0; 400 401 return MMSYSERR_NOERROR; 402 } 403 404 /*********************************************************************** 405 * ADPCM_FormatTagDetails 406 * 407 */ 408 static LRESULT ADPCM_FormatTagDetails(PACMFORMATTAGDETAILSW aftd, DWORD dwQuery) 409 { 410 static const WCHAR szPcm[]={'P','C','M',0}; 411 static const WCHAR szMsAdPcm[]={'M','i','c','r','o','s','o','f','t',' ','A','D','P','C','M',0}; 412 413 switch (dwQuery) 414 { 415 case ACM_FORMATTAGDETAILSF_INDEX: 416 if (aftd->dwFormatTagIndex >= 2) return ACMERR_NOTPOSSIBLE; 417 break; 418 case ACM_FORMATTAGDETAILSF_LARGESTSIZE: 419 if (aftd->dwFormatTag == WAVE_FORMAT_UNKNOWN) 420 { 421 aftd->dwFormatTagIndex = 1; /* WAVE_FORMAT_ADPCM is bigger than PCM */ 422 break; 423 } 424 /* fall through */ 425 case ACM_FORMATTAGDETAILSF_FORMATTAG: 426 switch (aftd->dwFormatTag) 427 { 428 case WAVE_FORMAT_PCM: aftd->dwFormatTagIndex = 0; break; 429 case WAVE_FORMAT_ADPCM: aftd->dwFormatTagIndex = 1; break; 430 default: return ACMERR_NOTPOSSIBLE; 431 } 432 break; 433 default: 434 WARN("Unsupported query %08x\n", dwQuery); 435 return MMSYSERR_NOTSUPPORTED; 436 } 437 438 aftd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC; 439 switch (aftd->dwFormatTagIndex) 440 { 441 case 0: 442 aftd->dwFormatTag = WAVE_FORMAT_PCM; 443 aftd->cbFormatSize = sizeof(PCMWAVEFORMAT); 444 aftd->cStandardFormats = NUM_PCM_FORMATS; 445 lstrcpyW(aftd->szFormatTag, szPcm); 446 break; 447 case 1: 448 aftd->dwFormatTag = WAVE_FORMAT_ADPCM; 449 aftd->cbFormatSize = sizeof(ADPCMWAVEFORMAT) + (7 - 1) * sizeof(ADPCMCOEFSET); 450 aftd->cStandardFormats = NUM_ADPCM_FORMATS; 451 lstrcpyW(aftd->szFormatTag, szMsAdPcm); 452 break; 453 } 454 return MMSYSERR_NOERROR; 455 } 456 457 /*********************************************************************** 458 * ADPCM_FormatDetails 459 * 460 */ 461 static LRESULT ADPCM_FormatDetails(PACMFORMATDETAILSW afd, DWORD dwQuery) 462 { 463 switch (dwQuery) 464 { 465 case ACM_FORMATDETAILSF_FORMAT: 466 if (ADPCM_GetFormatIndex(afd->pwfx) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE; 467 break; 468 case ACM_FORMATDETAILSF_INDEX: 469 afd->pwfx->wFormatTag = afd->dwFormatTag; 470 switch (afd->dwFormatTag) 471 { 472 case WAVE_FORMAT_PCM: 473 if (afd->dwFormatIndex >= NUM_PCM_FORMATS) return ACMERR_NOTPOSSIBLE; 474 afd->pwfx->nChannels = PCM_Formats[afd->dwFormatIndex].nChannels; 475 afd->pwfx->nSamplesPerSec = PCM_Formats[afd->dwFormatIndex].rate; 476 afd->pwfx->wBitsPerSample = PCM_Formats[afd->dwFormatIndex].nBits; 477 /* native MSACM uses a PCMWAVEFORMAT structure, so cbSize is not accessible 478 * afd->pwfx->cbSize = 0; 479 */ 480 afd->pwfx->nBlockAlign = 481 (afd->pwfx->nChannels * afd->pwfx->wBitsPerSample) / 8; 482 afd->pwfx->nAvgBytesPerSec = 483 afd->pwfx->nSamplesPerSec * afd->pwfx->nBlockAlign; 484 break; 485 case WAVE_FORMAT_ADPCM: 486 if (afd->dwFormatIndex >= NUM_ADPCM_FORMATS) return ACMERR_NOTPOSSIBLE; 487 if (afd->cbwfx < sizeof(ADPCMWAVEFORMAT) + (7 - 1) * sizeof(ADPCMCOEFSET)) 488 return ACMERR_NOTPOSSIBLE; 489 afd->pwfx->nChannels = ADPCM_Formats[afd->dwFormatIndex].nChannels; 490 afd->pwfx->nSamplesPerSec = ADPCM_Formats[afd->dwFormatIndex].rate; 491 afd->pwfx->wBitsPerSample = ADPCM_Formats[afd->dwFormatIndex].nBits; 492 init_wfx_adpcm((ADPCMWAVEFORMAT*)afd->pwfx); 493 break; 494 default: 495 WARN("Unsupported tag %08x\n", afd->dwFormatTag); 496 return MMSYSERR_INVALPARAM; 497 } 498 break; 499 default: 500 WARN("Unsupported query %08x\n", dwQuery); 501 return MMSYSERR_NOTSUPPORTED; 502 } 503 afd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC; 504 afd->szFormat[0] = 0; /* let MSACM format this for us... */ 505 506 return MMSYSERR_NOERROR; 507 } 508 509 /*********************************************************************** 510 * ADPCM_FormatSuggest 511 * 512 */ 513 static LRESULT ADPCM_FormatSuggest(PACMDRVFORMATSUGGEST adfs) 514 { 515 /* some tests ... */ 516 if (adfs->cbwfxSrc < sizeof(PCMWAVEFORMAT) || 517 adfs->cbwfxDst < sizeof(PCMWAVEFORMAT) || 518 adfs->pwfxSrc->wFormatTag == adfs->pwfxDst->wFormatTag || 519 ADPCM_GetFormatIndex(adfs->pwfxSrc) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE; 520 /* FIXME: should do those tests against the real size (according to format tag */ 521 522 /* If no suggestion for destination, then copy source value */ 523 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NCHANNELS)) 524 adfs->pwfxDst->nChannels = adfs->pwfxSrc->nChannels; 525 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NSAMPLESPERSEC)) 526 adfs->pwfxDst->nSamplesPerSec = adfs->pwfxSrc->nSamplesPerSec; 527 528 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WBITSPERSAMPLE)) 529 { 530 if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM) 531 adfs->pwfxDst->wBitsPerSample = 4; 532 else 533 adfs->pwfxDst->wBitsPerSample = 16; 534 } 535 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG)) 536 { 537 if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM) 538 adfs->pwfxDst->wFormatTag = WAVE_FORMAT_ADPCM; 539 else 540 adfs->pwfxDst->wFormatTag = WAVE_FORMAT_PCM; 541 } 542 543 /* recompute other values */ 544 switch (adfs->pwfxDst->wFormatTag) 545 { 546 case WAVE_FORMAT_PCM: 547 adfs->pwfxDst->nBlockAlign = (adfs->pwfxDst->nChannels * adfs->pwfxDst->wBitsPerSample) / 8; 548 adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * adfs->pwfxDst->nBlockAlign; 549 /* check if result is ok */ 550 if (ADPCM_GetFormatIndex(adfs->pwfxDst) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE; 551 break; 552 case WAVE_FORMAT_ADPCM: 553 if (adfs->cbwfxDst < sizeof(ADPCMWAVEFORMAT) + (7 - 1) * sizeof(ADPCMCOEFSET)) 554 return ACMERR_NOTPOSSIBLE; 555 init_wfx_adpcm((ADPCMWAVEFORMAT*)adfs->pwfxDst); 556 /* check if result is ok */ 557 if (ADPCM_GetFormatIndex(adfs->pwfxDst) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE; 558 break; 559 default: 560 return ACMERR_NOTPOSSIBLE; 561 } 562 563 return MMSYSERR_NOERROR; 564 } 565 566 /*********************************************************************** 567 * ADPCM_Reset 568 * 569 */ 570 static void ADPCM_Reset(PACMDRVSTREAMINSTANCE adsi, AcmAdpcmData* aad) 571 { 572 } 573 574 /*********************************************************************** 575 * ADPCM_StreamOpen 576 * 577 */ 578 static LRESULT ADPCM_StreamOpen(PACMDRVSTREAMINSTANCE adsi) 579 { 580 AcmAdpcmData* aad; 581 582 assert(!(adsi->fdwOpen & ACM_STREAMOPENF_ASYNC)); 583 584 if (ADPCM_GetFormatIndex(adsi->pwfxSrc) == 0xFFFFFFFF || 585 ADPCM_GetFormatIndex(adsi->pwfxDst) == 0xFFFFFFFF) 586 return ACMERR_NOTPOSSIBLE; 587 588 aad = HeapAlloc(GetProcessHeap(), 0, sizeof(AcmAdpcmData)); 589 if (aad == 0) return MMSYSERR_NOMEM; 590 591 adsi->dwDriver = (DWORD_PTR)aad; 592 593 if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM && 594 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM) 595 { 596 goto theEnd; 597 } 598 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ADPCM && 599 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM) 600 { 601 /* resampling or mono <=> stereo not available */ 602 if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec || 603 adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels) 604 goto theEnd; 605 606 #if 0 607 { 608 unsigned int nspb = ((IMAADPCMWAVEFORMAT*)adsi->pwfxSrc)->wSamplesPerBlock; 609 FIXME("spb=%u\n", nspb); 610 611 /* we check that in a block, after the header, samples are present on 612 * 4-sample packet pattern 613 * we also check that the block alignment is bigger than the expected size 614 */ 615 if (((nspb - 1) & 3) != 0) goto theEnd; 616 if ((((nspb - 1) / 2) + 4) * adsi->pwfxSrc->nChannels < adsi->pwfxSrc->nBlockAlign) 617 goto theEnd; 618 } 619 #endif 620 621 /* adpcm decoding... */ 622 if (adsi->pwfxDst->nChannels == 2) 623 aad->convert = cvtSSms16K; 624 else if (adsi->pwfxDst->nChannels == 1) 625 aad->convert = cvtMMms16K; 626 } 627 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM && 628 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ADPCM) 629 { 630 if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec || 631 adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels || 632 adsi->pwfxSrc->wBitsPerSample != 16) 633 goto theEnd; 634 #if 0 635 nspb = ((IMAADPCMWAVEFORMAT*)adsi->pwfxDst)->wSamplesPerBlock; 636 FIXME("spb=%u\n", nspb); 637 638 /* we check that in a block, after the header, samples are present on 639 * 4-sample packet pattern 640 * we also check that the block alignment is bigger than the expected size 641 */ 642 if (((nspb - 1) & 3) != 0) goto theEnd; 643 if ((((nspb - 1) / 2) + 4) * adsi->pwfxDst->nChannels < adsi->pwfxDst->nBlockAlign) 644 goto theEnd; 645 #endif 646 #if 0 647 /* adpcm coding... */ 648 if (adsi->pwfxSrc->wBitsPerSample == 16 && adsi->pwfxSrc->nChannels == 2) 649 aad->convert = cvtSS16msK; 650 if (adsi->pwfxSrc->wBitsPerSample == 16 && adsi->pwfxSrc->nChannels == 1) 651 aad->convert = cvtMM16msK; 652 #endif 653 FIXME("We don't support encoding yet\n"); 654 goto theEnd; 655 } 656 else goto theEnd; 657 ADPCM_Reset(adsi, aad); 658 659 return MMSYSERR_NOERROR; 660 661 theEnd: 662 HeapFree(GetProcessHeap(), 0, aad); 663 adsi->dwDriver = 0L; 664 return MMSYSERR_NOTSUPPORTED; 665 } 666 667 /*********************************************************************** 668 * ADPCM_StreamClose 669 * 670 */ 671 static LRESULT ADPCM_StreamClose(PACMDRVSTREAMINSTANCE adsi) 672 { 673 HeapFree(GetProcessHeap(), 0, (void*)adsi->dwDriver); 674 return MMSYSERR_NOERROR; 675 } 676 677 /*********************************************************************** 678 * ADPCM_StreamSize 679 * 680 */ 681 static LRESULT ADPCM_StreamSize(const ACMDRVSTREAMINSTANCE *adsi, PACMDRVSTREAMSIZE adss) 682 { 683 DWORD nblocks; 684 WORD wSamplesPerBlock; 685 /* wSamplesPerBlock formula comes from MSDN ADPCMWAVEFORMAT page.*/ 686 switch (adss->fdwSize) 687 { 688 case ACM_STREAMSIZEF_DESTINATION: 689 /* cbDstLength => cbSrcLength */ 690 if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM && 691 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ADPCM) 692 { 693 wSamplesPerBlock = adsi->pwfxDst->nBlockAlign * 2 / adsi->pwfxDst->nChannels - 12; 694 nblocks = adss->cbDstLength / adsi->pwfxDst->nBlockAlign; 695 if (nblocks == 0) 696 return ACMERR_NOTPOSSIBLE; 697 adss->cbSrcLength = nblocks * adsi->pwfxSrc->nBlockAlign * wSamplesPerBlock; 698 } 699 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ADPCM && 700 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM) 701 { 702 wSamplesPerBlock = adsi->pwfxSrc->nBlockAlign * 2 / adsi->pwfxSrc->nChannels - 12; 703 nblocks = adss->cbDstLength / (adsi->pwfxDst->nBlockAlign * wSamplesPerBlock); 704 if (nblocks == 0) 705 return ACMERR_NOTPOSSIBLE; 706 adss->cbSrcLength = nblocks * adsi->pwfxSrc->nBlockAlign; 707 } 708 else 709 { 710 return MMSYSERR_NOTSUPPORTED; 711 } 712 break; 713 case ACM_STREAMSIZEF_SOURCE: 714 /* cbSrcLength => cbDstLength */ 715 if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM && 716 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ADPCM) 717 { 718 wSamplesPerBlock = adsi->pwfxDst->nBlockAlign * 2 / adsi->pwfxDst->nChannels - 12; 719 nblocks = adss->cbSrcLength / (adsi->pwfxSrc->nBlockAlign * wSamplesPerBlock); 720 if (nblocks == 0) 721 return ACMERR_NOTPOSSIBLE; 722 if (adss->cbSrcLength % (adsi->pwfxSrc->nBlockAlign * wSamplesPerBlock)) 723 /* Round block count up. */ 724 nblocks++; 725 adss->cbDstLength = nblocks * adsi->pwfxDst->nBlockAlign; 726 } 727 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ADPCM && 728 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM) 729 { 730 wSamplesPerBlock = adsi->pwfxSrc->nBlockAlign * 2 / adsi->pwfxSrc->nChannels - 12; 731 nblocks = adss->cbSrcLength / adsi->pwfxSrc->nBlockAlign; 732 if (nblocks == 0) 733 return ACMERR_NOTPOSSIBLE; 734 if (adss->cbSrcLength % adsi->pwfxSrc->nBlockAlign) 735 /* Round block count up. */ 736 nblocks++; 737 adss->cbDstLength = nblocks * adsi->pwfxDst->nBlockAlign * wSamplesPerBlock; 738 } 739 else 740 { 741 return MMSYSERR_NOTSUPPORTED; 742 } 743 break; 744 default: 745 WARN("Unsupported query %08x\n", adss->fdwSize); 746 return MMSYSERR_NOTSUPPORTED; 747 } 748 return MMSYSERR_NOERROR; 749 } 750 751 /*********************************************************************** 752 * ADPCM_StreamConvert 753 * 754 */ 755 static LRESULT ADPCM_StreamConvert(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMHEADER adsh) 756 { 757 AcmAdpcmData* aad = (AcmAdpcmData*)adsi->dwDriver; 758 DWORD nsrc = adsh->cbSrcLength; 759 DWORD ndst = adsh->cbDstLength; 760 761 if (adsh->fdwConvert & 762 ~(ACM_STREAMCONVERTF_BLOCKALIGN| 763 ACM_STREAMCONVERTF_END| 764 ACM_STREAMCONVERTF_START)) 765 { 766 FIXME("Unsupported fdwConvert (%08x), ignoring it\n", adsh->fdwConvert); 767 } 768 /* ACM_STREAMCONVERTF_BLOCKALIGN 769 * currently all conversions are block aligned, so do nothing for this flag 770 * ACM_STREAMCONVERTF_END 771 * no pending data, so do nothing for this flag 772 */ 773 if ((adsh->fdwConvert & ACM_STREAMCONVERTF_START)) 774 { 775 ADPCM_Reset(adsi, aad); 776 } 777 778 aad->convert(adsi, adsh->pbSrc, &nsrc, adsh->pbDst, &ndst); 779 adsh->cbSrcLengthUsed = nsrc; 780 adsh->cbDstLengthUsed = ndst; 781 782 return MMSYSERR_NOERROR; 783 } 784 785 /************************************************************************** 786 * ADPCM_DriverProc [exported] 787 */ 788 LRESULT CALLBACK ADPCM_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg, 789 LPARAM dwParam1, LPARAM dwParam2) 790 { 791 TRACE("(%08lx %p %04x %08lx %08lx);\n", 792 dwDevID, hDriv, wMsg, dwParam1, dwParam2); 793 794 switch (wMsg) 795 { 796 case DRV_LOAD: return 1; 797 case DRV_FREE: return 1; 798 case DRV_OPEN: return ADPCM_drvOpen((LPSTR)dwParam1); 799 case DRV_CLOSE: return ADPCM_drvClose(dwDevID); 800 case DRV_ENABLE: return 1; 801 case DRV_DISABLE: return 1; 802 case DRV_QUERYCONFIGURE: return 1; 803 case DRV_CONFIGURE: MessageBoxA(0, "MSACM MS ADPCM filter !", "Wine Driver", MB_OK); return 1; 804 case DRV_INSTALL: return DRVCNF_RESTART; 805 case DRV_REMOVE: return DRVCNF_RESTART; 806 807 case ACMDM_DRIVER_NOTIFY: 808 /* no caching from other ACM drivers is done so far */ 809 return MMSYSERR_NOERROR; 810 811 case ACMDM_DRIVER_DETAILS: 812 return ADPCM_DriverDetails((PACMDRIVERDETAILSW)dwParam1); 813 814 case ACMDM_FORMATTAG_DETAILS: 815 return ADPCM_FormatTagDetails((PACMFORMATTAGDETAILSW)dwParam1, dwParam2); 816 817 case ACMDM_FORMAT_DETAILS: 818 return ADPCM_FormatDetails((PACMFORMATDETAILSW)dwParam1, dwParam2); 819 820 case ACMDM_FORMAT_SUGGEST: 821 return ADPCM_FormatSuggest((PACMDRVFORMATSUGGEST)dwParam1); 822 823 case ACMDM_STREAM_OPEN: 824 return ADPCM_StreamOpen((PACMDRVSTREAMINSTANCE)dwParam1); 825 826 case ACMDM_STREAM_CLOSE: 827 return ADPCM_StreamClose((PACMDRVSTREAMINSTANCE)dwParam1); 828 829 case ACMDM_STREAM_SIZE: 830 return ADPCM_StreamSize((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMSIZE)dwParam2); 831 832 case ACMDM_STREAM_CONVERT: 833 return ADPCM_StreamConvert((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMHEADER)dwParam2); 834 835 case ACMDM_HARDWARE_WAVE_CAPS_INPUT: 836 case ACMDM_HARDWARE_WAVE_CAPS_OUTPUT: 837 /* this converter is not a hardware driver */ 838 case ACMDM_FILTERTAG_DETAILS: 839 case ACMDM_FILTER_DETAILS: 840 /* this converter is not a filter */ 841 case ACMDM_STREAM_RESET: 842 /* only needed for asynchronous driver... we aren't, so just say it */ 843 return MMSYSERR_NOTSUPPORTED; 844 case ACMDM_STREAM_PREPARE: 845 case ACMDM_STREAM_UNPREPARE: 846 /* nothing special to do here... so don't do anything */ 847 return MMSYSERR_NOERROR; 848 849 default: 850 return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2); 851 } 852 } 853