1 /* 2 * IMA ADPCM handling 3 * 4 * Copyright (C) 2001,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_drvClose 42 */ 43 static LRESULT ADPCM_drvClose(DWORD_PTR dwDevID) 44 { 45 return 1; 46 } 47 48 typedef struct tagAcmAdpcmData 49 { 50 void (*convert)(PACMDRVSTREAMINSTANCE adsi, 51 const unsigned char*, LPDWORD, unsigned char*, LPDWORD); 52 /* IMA encoding only */ 53 BYTE stepIndexL; 54 BYTE stepIndexR; 55 /* short sample; */ 56 } AcmAdpcmData; 57 58 /* table to list all supported formats... those are the basic ones. this 59 * also helps given a unique index to each of the supported formats 60 */ 61 typedef struct 62 { 63 int nChannels; 64 int nBits; 65 int rate; 66 } Format; 67 68 static const Format PCM_Formats[] = 69 { 70 {1, 8, 8000}, {2, 8, 8000}, {1, 16, 8000}, {2, 16, 8000}, 71 {1, 8, 11025}, {2, 8, 11025}, {1, 16, 11025}, {2, 16, 11025}, 72 {1, 8, 22050}, {2, 8, 22050}, {1, 16, 22050}, {2, 16, 22050}, 73 {1, 8, 44100}, {2, 8, 44100}, {1, 16, 44100}, {2, 16, 44100}, 74 }; 75 76 static const Format ADPCM_Formats[] = 77 { 78 {1, 4, 8000}, {2, 4, 8000}, {1, 4, 11025}, {2, 4, 11025}, 79 {1, 4, 22050}, {2, 4, 22050}, {1, 4, 44100}, {2, 4, 44100}, 80 }; 81 82 #define NUM_PCM_FORMATS (sizeof(PCM_Formats) / sizeof(PCM_Formats[0])) 83 #define NUM_ADPCM_FORMATS (sizeof(ADPCM_Formats) / sizeof(ADPCM_Formats[0])) 84 85 /*********************************************************************** 86 * ADPCM_GetFormatIndex 87 */ 88 static DWORD ADPCM_GetFormatIndex(const WAVEFORMATEX *wfx) 89 { 90 int i, hi; 91 const Format* fmts; 92 93 switch (wfx->wFormatTag) 94 { 95 case WAVE_FORMAT_PCM: 96 hi = NUM_PCM_FORMATS; 97 fmts = PCM_Formats; 98 break; 99 case WAVE_FORMAT_IMA_ADPCM: 100 hi = NUM_ADPCM_FORMATS; 101 fmts = ADPCM_Formats; 102 break; 103 default: 104 return 0xFFFFFFFF; 105 } 106 107 for (i = 0; i < hi; i++) 108 { 109 if (wfx->nChannels == fmts[i].nChannels && 110 wfx->nSamplesPerSec == fmts[i].rate && 111 wfx->wBitsPerSample == fmts[i].nBits) 112 return i; 113 } 114 115 switch (wfx->wFormatTag) 116 { 117 case WAVE_FORMAT_PCM: 118 if(3 > wfx->nChannels && 119 wfx->nChannels > 0 && 120 wfx->nAvgBytesPerSec == 2 * wfx->nSamplesPerSec * wfx->nChannels && 121 wfx->nBlockAlign == 2 * wfx->nChannels && 122 wfx->wBitsPerSample == 16) 123 return hi; 124 break; 125 case WAVE_FORMAT_IMA_ADPCM: 126 if(3 > wfx->nChannels && 127 wfx->nChannels > 0 && 128 wfx->wBitsPerSample == 4 && 129 wfx->cbSize == 2) 130 return hi; 131 break; 132 } 133 134 return 0xFFFFFFFF; 135 } 136 137 static void init_wfx_ima_adpcm(IMAADPCMWAVEFORMAT* awfx/*, DWORD nba*/) 138 { 139 WAVEFORMATEX* pwfx = &awfx->wfx; 140 141 /* we assume wFormatTag, nChannels, nSamplesPerSec and wBitsPerSample 142 * have been initialized... */ 143 144 if (pwfx->wFormatTag != WAVE_FORMAT_IMA_ADPCM) {FIXME("wrong FT\n"); return;} 145 if (ADPCM_GetFormatIndex(pwfx) == 0xFFFFFFFF) {FIXME("wrong fmt\n"); return;} 146 147 switch (pwfx->nSamplesPerSec) 148 { 149 case 8000: pwfx->nBlockAlign = 256 * pwfx->nChannels; break; 150 case 11025: pwfx->nBlockAlign = 256 * pwfx->nChannels; break; 151 case 22050: pwfx->nBlockAlign = 512 * pwfx->nChannels; break; 152 case 44100: pwfx->nBlockAlign = 1024 * pwfx->nChannels; break; 153 default: /*pwfx->nBlockAlign = nba;*/ break; 154 } 155 pwfx->cbSize = sizeof(WORD); 156 157 awfx->wSamplesPerBlock = (pwfx->nBlockAlign - (4 * pwfx->nChannels)) * (2 / pwfx->nChannels) + 1; 158 pwfx->nAvgBytesPerSec = (pwfx->nSamplesPerSec * pwfx->nBlockAlign) / awfx->wSamplesPerBlock; 159 } 160 161 /*********************************************************************** 162 * R16 163 * 164 * Read a 16 bit sample (correctly handles endianness) 165 */ 166 static inline short R16(const unsigned char* src) 167 { 168 return (short)((unsigned short)src[0] | ((unsigned short)src[1] << 8)); 169 } 170 171 /*********************************************************************** 172 * W16 173 * 174 * Write a 16 bit sample (correctly handles endianness) 175 */ 176 static inline void W16(unsigned char* dst, short s) 177 { 178 dst[0] = LOBYTE(s); 179 dst[1] = HIBYTE(s); 180 } 181 182 /*********************************************************************** 183 * W8 184 * 185 * Write a 8 bit sample 186 */ 187 static inline void W8(unsigned char* dst, short s) 188 { 189 dst[0] = (unsigned char)((s + 32768) >> 8); 190 } 191 192 193 static inline void W8_16(unsigned char* dst, short s, int bytes) 194 { 195 if(bytes == 1) 196 W8(dst, s); 197 else 198 W16(dst, s); 199 } 200 201 /* IMA (or DVI) APDCM codec routines */ 202 203 static const unsigned IMA_StepTable[89] = 204 { 205 7, 8, 9, 10, 11, 12, 13, 14, 206 16, 17, 19, 21, 23, 25, 28, 31, 207 34, 37, 41, 45, 50, 55, 60, 66, 208 73, 80, 88, 97, 107, 118, 130, 143, 209 157, 173, 190, 209, 230, 253, 279, 307, 210 337, 371, 408, 449, 494, 544, 598, 658, 211 724, 796, 876, 963, 1060, 1166, 1282, 1411, 212 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, 213 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484, 214 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, 215 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 216 32767 217 }; 218 219 static const int IMA_IndexTable[16] = 220 { 221 -1, -1, -1, -1, 2, 4, 6, 8, 222 -1, -1, -1, -1, 2, 4, 6, 8 223 }; 224 225 static inline void clamp_step_index(int* stepIndex) 226 { 227 if (*stepIndex < 0 ) *stepIndex = 0; 228 if (*stepIndex > 88) *stepIndex = 88; 229 } 230 231 static inline void clamp_sample(int* sample) 232 { 233 if (*sample < -32768) *sample = -32768; 234 if (*sample > 32767) *sample = 32767; 235 } 236 237 static inline void process_nibble(unsigned char code, int* stepIndex, int* sample) 238 { 239 unsigned step; 240 int diff; 241 242 code &= 0x0F; 243 244 step = IMA_StepTable[*stepIndex]; 245 diff = step >> 3; 246 if (code & 1) diff += step >> 2; 247 if (code & 2) diff += step >> 1; 248 if (code & 4) diff += step; 249 if (code & 8) *sample -= diff; 250 else *sample += diff; 251 clamp_sample(sample); 252 *stepIndex += IMA_IndexTable[code]; 253 clamp_step_index(stepIndex); 254 } 255 256 static inline unsigned char generate_nibble(int in, int* stepIndex, int* sample) 257 { 258 int effdiff, diff = in - *sample; 259 unsigned step; 260 unsigned char code; 261 262 if (diff < 0) 263 { 264 diff = -diff; 265 code = 8; 266 } 267 else 268 { 269 code = 0; 270 } 271 272 step = IMA_StepTable[*stepIndex]; 273 effdiff = (step >> 3); 274 if (diff >= step) 275 { 276 code |= 4; 277 diff -= step; 278 effdiff += step; 279 } 280 step >>= 1; 281 if (diff >= step) 282 { 283 code |= 2; 284 diff -= step; 285 effdiff += step; 286 } 287 step >>= 1; 288 if (diff >= step) 289 { 290 code |= 1; 291 effdiff += step; 292 } 293 if (code & 8) *sample -= effdiff; 294 else *sample += effdiff; 295 clamp_sample(sample); 296 *stepIndex += IMA_IndexTable[code]; 297 clamp_step_index(stepIndex); 298 return code; 299 } 300 301 static void cvtSSima16K(PACMDRVSTREAMINSTANCE adsi, 302 const unsigned char* src, LPDWORD nsrc, 303 unsigned char* dst, LPDWORD ndst) 304 { 305 int i; 306 int sampleL, sampleR; 307 int stepIndexL, stepIndexR; 308 int nsamp_blk = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxSrc)->wSamplesPerBlock; 309 int nsamp; 310 /* compute the number of entire blocks we can decode... 311 * it's the min of the number of entire blocks in source buffer and the number 312 * of entire blocks in destination buffer 313 */ 314 DWORD nblock = min(*nsrc / adsi->pwfxSrc->nBlockAlign, 315 *ndst / (nsamp_blk * 2 * 2)); 316 317 *nsrc = nblock * adsi->pwfxSrc->nBlockAlign; 318 *ndst = nblock * (nsamp_blk * 2 * 2); 319 320 nsamp_blk--; /* remove the sample in block header */ 321 for (; nblock > 0; nblock--) 322 { 323 const unsigned char* in_src = src; 324 325 /* handle headers first */ 326 sampleL = R16(src); 327 stepIndexL = (unsigned)*(src + 2); 328 clamp_step_index(&stepIndexL); 329 src += 4; 330 W16(dst, sampleL); dst += 2; 331 332 sampleR = R16(src); 333 stepIndexR = (unsigned)*(src + 2); 334 clamp_step_index(&stepIndexR); 335 src += 4; 336 W16(dst, sampleR); dst += 2; 337 338 for (nsamp = nsamp_blk; nsamp > 0; nsamp -= 8) 339 { 340 for (i = 0; i < 4; i++) 341 { 342 process_nibble(*src, &stepIndexL, &sampleL); 343 W16(dst + (2 * i + 0) * 4 + 0, sampleL); 344 process_nibble(*src++ >> 4, &stepIndexL, &sampleL); 345 W16(dst + (2 * i + 1) * 4 + 0, sampleL); 346 } 347 for (i = 0; i < 4; i++) 348 { 349 process_nibble(*src , &stepIndexR, &sampleR); 350 W16(dst + (2 * i + 0) * 4 + 2, sampleR); 351 process_nibble(*src++ >>4, &stepIndexR, &sampleR); 352 W16(dst + (2 * i + 1) * 4 + 2, sampleR); 353 } 354 dst += 32; 355 } 356 /* we have now to realign the source pointer on block */ 357 src = in_src + adsi->pwfxSrc->nBlockAlign; 358 } 359 } 360 361 static void cvtMMimaK(PACMDRVSTREAMINSTANCE adsi, 362 const unsigned char* src, LPDWORD nsrc, 363 unsigned char* dst, LPDWORD ndst) 364 { 365 int sample; 366 int stepIndex; 367 int nsamp_blk = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxSrc)->wSamplesPerBlock; 368 int nsamp; 369 int bytesPerSample = adsi->pwfxDst->wBitsPerSample / 8; 370 /* compute the number of entire blocks we can decode... 371 * it's the min of the number of entire blocks in source buffer and the number 372 * of entire blocks in destination buffer 373 */ 374 DWORD nblock = min(*nsrc / adsi->pwfxSrc->nBlockAlign, *ndst / (nsamp_blk * bytesPerSample)); 375 376 *nsrc = nblock * adsi->pwfxSrc->nBlockAlign; 377 *ndst = nblock * nsamp_blk * bytesPerSample; 378 379 nsamp_blk--; /* remove the sample in block header */ 380 for (; nblock > 0; nblock--) 381 { 382 const unsigned char* in_src = src; 383 384 /* handle header first */ 385 sample = R16(src); 386 stepIndex = (unsigned)*(src + 2); 387 clamp_step_index(&stepIndex); 388 src += 4; 389 W8_16(dst, sample, bytesPerSample); dst += bytesPerSample; 390 391 for (nsamp = nsamp_blk; nsamp > 0; nsamp -= 2) 392 { 393 process_nibble(*src, &stepIndex, &sample); 394 W8_16(dst, sample, bytesPerSample); dst += bytesPerSample; 395 process_nibble(*src++ >> 4, &stepIndex, &sample); 396 W8_16(dst, sample, bytesPerSample); dst += bytesPerSample; 397 } 398 /* we have now to realign the source pointer on block */ 399 src = in_src + adsi->pwfxSrc->nBlockAlign; 400 } 401 } 402 403 static void cvtSS16imaK(PACMDRVSTREAMINSTANCE adsi, 404 const unsigned char* src, LPDWORD nsrc, 405 unsigned char* dst, LPDWORD ndst) 406 { 407 int stepIndexL, stepIndexR; 408 int sampleL, sampleR; 409 BYTE code1, code2; 410 int nsamp_blk = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxDst)->wSamplesPerBlock; 411 int i, nsamp; 412 /* compute the number of entire blocks we can decode... 413 * it's the min of the number of entire blocks in source buffer and the number 414 * of entire blocks in destination buffer 415 */ 416 DWORD nblock = min(*nsrc / (nsamp_blk * 2 * 2), 417 *ndst / adsi->pwfxDst->nBlockAlign); 418 419 *nsrc = nblock * (nsamp_blk * 2 * 2); 420 *ndst = nblock * adsi->pwfxDst->nBlockAlign; 421 422 stepIndexL = ((AcmAdpcmData*)adsi->dwDriver)->stepIndexL; 423 stepIndexR = ((AcmAdpcmData*)adsi->dwDriver)->stepIndexR; 424 425 nsamp_blk--; /* so that we won't count the sample in header while filling the block */ 426 427 for (; nblock > 0; nblock--) 428 { 429 unsigned char* in_dst = dst; 430 431 /* generate header */ 432 sampleL = R16(src); src += 2; 433 W16(dst, sampleL); dst += 2; 434 W16(dst, stepIndexL); dst += 2; 435 436 sampleR = R16(src); src += 2; 437 W16(dst, sampleR); dst += 2; 438 W16(dst, stepIndexR); dst += 2; 439 440 for (nsamp = nsamp_blk; nsamp > 0; nsamp -= 8) 441 { 442 for (i = 0; i < 4; i++) 443 { 444 code1 = generate_nibble(R16(src + (4 * i + 0) * 2), 445 &stepIndexL, &sampleL); 446 code2 = generate_nibble(R16(src + (4 * i + 2) * 2), 447 &stepIndexL, &sampleL); 448 *dst++ = (code2 << 4) | code1; 449 } 450 for (i = 0; i < 4; i++) 451 { 452 code1 = generate_nibble(R16(src + (4 * i + 1) * 2), 453 &stepIndexR, &sampleR); 454 code2 = generate_nibble(R16(src + (4 * i + 3) * 2), 455 &stepIndexR, &sampleR); 456 *dst++ = (code2 << 4) | code1; 457 } 458 src += 32; 459 } 460 dst = in_dst + adsi->pwfxDst->nBlockAlign; 461 } 462 ((AcmAdpcmData*)adsi->dwDriver)->stepIndexL = stepIndexL; 463 ((AcmAdpcmData*)adsi->dwDriver)->stepIndexR = stepIndexR; 464 } 465 466 static void cvtMM16imaK(PACMDRVSTREAMINSTANCE adsi, 467 const unsigned char* src, LPDWORD nsrc, 468 unsigned char* dst, LPDWORD ndst) 469 { 470 int stepIndex; 471 int sample; 472 BYTE code1, code2; 473 int nsamp_blk = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxDst)->wSamplesPerBlock; 474 int nsamp; 475 /* compute the number of entire blocks we can decode... 476 * it's the min of the number of entire blocks in source buffer and the number 477 * of entire blocks in destination buffer 478 */ 479 DWORD nblock = min(*nsrc / (nsamp_blk * 2), 480 *ndst / adsi->pwfxDst->nBlockAlign); 481 482 *nsrc = nblock * (nsamp_blk * 2); 483 *ndst = nblock * adsi->pwfxDst->nBlockAlign; 484 485 stepIndex = ((AcmAdpcmData*)adsi->dwDriver)->stepIndexL; 486 nsamp_blk--; /* so that we won't count the sample in header while filling the block */ 487 488 for (; nblock > 0; nblock--) 489 { 490 unsigned char* in_dst = dst; 491 492 /* generate header */ 493 /* FIXME: what about the last effective sample from previous block ??? */ 494 /* perhaps something like: 495 * sample += R16(src); 496 * clamp_sample(sample); 497 * and with : 498 * + saving the sample in adsi->dwDriver when all blocks are done 499 + + reset should set the field in adsi->dwDriver to 0 too 500 */ 501 sample = R16(src); src += 2; 502 W16(dst, sample); dst += 2; 503 *dst = (unsigned char)(unsigned)stepIndex; 504 dst += 2; 505 506 for (nsamp = nsamp_blk; nsamp > 0; nsamp -= 2) 507 { 508 code1 = generate_nibble(R16(src), &stepIndex, &sample); 509 src += 2; 510 code2 = generate_nibble(R16(src), &stepIndex, &sample); 511 src += 2; 512 *dst++ = (code2 << 4) | code1; 513 } 514 dst = in_dst + adsi->pwfxDst->nBlockAlign; 515 } 516 ((AcmAdpcmData*)adsi->dwDriver)->stepIndexL = stepIndex; 517 } 518 519 /*********************************************************************** 520 * ADPCM_DriverDetails 521 * 522 */ 523 static LRESULT ADPCM_DriverDetails(PACMDRIVERDETAILSW add) 524 { 525 add->fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC; 526 add->fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED; 527 add->wMid = MM_MICROSOFT; 528 add->wPid = MM_MSFT_ACM_IMAADPCM; 529 add->vdwACM = 0x3320000; 530 add->vdwDriver = 0x04000000; 531 add->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC; 532 add->cFormatTags = 2; /* PCM, IMA ADPCM */ 533 add->cFilterTags = 0; 534 add->hicon = NULL; 535 MultiByteToWideChar( CP_ACP, 0, "Microsoft IMA ADPCM", -1, 536 add->szShortName, sizeof(add->szShortName)/sizeof(WCHAR) ); 537 MultiByteToWideChar( CP_ACP, 0, "Microsoft IMA ADPCM CODEC", -1, 538 add->szLongName, sizeof(add->szLongName)/sizeof(WCHAR) ); 539 MultiByteToWideChar( CP_ACP, 0, "Brought to you by the Wine team...", -1, 540 add->szCopyright, sizeof(add->szCopyright)/sizeof(WCHAR) ); 541 MultiByteToWideChar( CP_ACP, 0, "Refer to LICENSE file", -1, 542 add->szLicensing, sizeof(add->szLicensing)/sizeof(WCHAR) ); 543 add->szFeatures[0] = 0; 544 545 return MMSYSERR_NOERROR; 546 } 547 548 /*********************************************************************** 549 * ADPCM_FormatTagDetails 550 * 551 */ 552 static LRESULT ADPCM_FormatTagDetails(PACMFORMATTAGDETAILSW aftd, DWORD dwQuery) 553 { 554 static const WCHAR szPcm[]={'P','C','M',0}; 555 static const WCHAR szImaAdPcm[]={'I','M','A',' ','A','D','P','C','M',0}; 556 557 switch (dwQuery) 558 { 559 case ACM_FORMATTAGDETAILSF_INDEX: 560 if (aftd->dwFormatTagIndex >= 2) return ACMERR_NOTPOSSIBLE; 561 break; 562 case ACM_FORMATTAGDETAILSF_LARGESTSIZE: 563 if (aftd->dwFormatTag == WAVE_FORMAT_UNKNOWN) 564 { 565 aftd->dwFormatTagIndex = 1; /* WAVE_FORMAT_IMA_ADPCM is bigger than PCM */ 566 break; 567 } 568 /* fall through */ 569 case ACM_FORMATTAGDETAILSF_FORMATTAG: 570 switch (aftd->dwFormatTag) 571 { 572 case WAVE_FORMAT_PCM: aftd->dwFormatTagIndex = 0; break; 573 case WAVE_FORMAT_IMA_ADPCM: aftd->dwFormatTagIndex = 1; break; 574 default: return ACMERR_NOTPOSSIBLE; 575 } 576 break; 577 default: 578 WARN("Unsupported query %08x\n", dwQuery); 579 return MMSYSERR_NOTSUPPORTED; 580 } 581 582 aftd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC; 583 switch (aftd->dwFormatTagIndex) 584 { 585 case 0: 586 aftd->dwFormatTag = WAVE_FORMAT_PCM; 587 aftd->cbFormatSize = sizeof(PCMWAVEFORMAT); 588 aftd->cStandardFormats = NUM_PCM_FORMATS; 589 lstrcpyW(aftd->szFormatTag, szPcm); 590 break; 591 case 1: 592 aftd->dwFormatTag = WAVE_FORMAT_IMA_ADPCM; 593 aftd->cbFormatSize = sizeof(IMAADPCMWAVEFORMAT); 594 aftd->cStandardFormats = NUM_ADPCM_FORMATS; 595 lstrcpyW(aftd->szFormatTag, szImaAdPcm); 596 break; 597 } 598 return MMSYSERR_NOERROR; 599 } 600 601 /*********************************************************************** 602 * ADPCM_FormatDetails 603 * 604 */ 605 static LRESULT ADPCM_FormatDetails(PACMFORMATDETAILSW afd, DWORD dwQuery) 606 { 607 switch (dwQuery) 608 { 609 case ACM_FORMATDETAILSF_FORMAT: 610 if (ADPCM_GetFormatIndex(afd->pwfx) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE; 611 break; 612 case ACM_FORMATDETAILSF_INDEX: 613 afd->pwfx->wFormatTag = afd->dwFormatTag; 614 switch (afd->dwFormatTag) 615 { 616 case WAVE_FORMAT_PCM: 617 if (afd->dwFormatIndex >= NUM_PCM_FORMATS) return ACMERR_NOTPOSSIBLE; 618 afd->pwfx->nChannels = PCM_Formats[afd->dwFormatIndex].nChannels; 619 afd->pwfx->nSamplesPerSec = PCM_Formats[afd->dwFormatIndex].rate; 620 afd->pwfx->wBitsPerSample = PCM_Formats[afd->dwFormatIndex].nBits; 621 /* native MSACM uses a PCMWAVEFORMAT structure, so cbSize is not accessible 622 * afd->pwfx->cbSize = 0; 623 */ 624 afd->pwfx->nBlockAlign = 625 (afd->pwfx->nChannels * afd->pwfx->wBitsPerSample) / 8; 626 afd->pwfx->nAvgBytesPerSec = 627 afd->pwfx->nSamplesPerSec * afd->pwfx->nBlockAlign; 628 break; 629 case WAVE_FORMAT_IMA_ADPCM: 630 if (afd->dwFormatIndex >= NUM_ADPCM_FORMATS) return ACMERR_NOTPOSSIBLE; 631 afd->pwfx->nChannels = ADPCM_Formats[afd->dwFormatIndex].nChannels; 632 afd->pwfx->nSamplesPerSec = ADPCM_Formats[afd->dwFormatIndex].rate; 633 afd->pwfx->wBitsPerSample = ADPCM_Formats[afd->dwFormatIndex].nBits; 634 init_wfx_ima_adpcm((IMAADPCMWAVEFORMAT *)afd->pwfx); 635 break; 636 default: 637 WARN("Unsupported tag %08x\n", afd->dwFormatTag); 638 return MMSYSERR_INVALPARAM; 639 } 640 break; 641 default: 642 WARN("Unsupported query %08x\n", dwQuery); 643 return MMSYSERR_NOTSUPPORTED; 644 } 645 afd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC; 646 afd->szFormat[0] = 0; /* let MSACM format this for us... */ 647 648 return MMSYSERR_NOERROR; 649 } 650 651 /*********************************************************************** 652 * ADPCM_FormatSuggest 653 * 654 */ 655 static LRESULT ADPCM_FormatSuggest(PACMDRVFORMATSUGGEST adfs) 656 { 657 /* some tests ... */ 658 if (adfs->cbwfxSrc < sizeof(PCMWAVEFORMAT) || 659 adfs->cbwfxDst < sizeof(PCMWAVEFORMAT) || 660 adfs->pwfxSrc->wFormatTag == adfs->pwfxDst->wFormatTag || 661 ADPCM_GetFormatIndex(adfs->pwfxSrc) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE; 662 663 /* If no suggestion for destination, then copy source value */ 664 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NCHANNELS)) 665 adfs->pwfxDst->nChannels = adfs->pwfxSrc->nChannels; 666 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NSAMPLESPERSEC)) 667 adfs->pwfxDst->nSamplesPerSec = adfs->pwfxSrc->nSamplesPerSec; 668 669 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WBITSPERSAMPLE)) 670 { 671 if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM) 672 adfs->pwfxDst->wBitsPerSample = 4; 673 else 674 adfs->pwfxDst->wBitsPerSample = 16; 675 } 676 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG)) 677 { 678 if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM) 679 adfs->pwfxDst->wFormatTag = WAVE_FORMAT_IMA_ADPCM; 680 else 681 adfs->pwfxDst->wFormatTag = WAVE_FORMAT_PCM; 682 } 683 684 /* recompute other values */ 685 switch (adfs->pwfxDst->wFormatTag) 686 { 687 case WAVE_FORMAT_PCM: 688 if (adfs->cbwfxSrc < sizeof(IMAADPCMWAVEFORMAT)) return ACMERR_NOTPOSSIBLE; 689 adfs->pwfxDst->nBlockAlign = (adfs->pwfxDst->nChannels * adfs->pwfxDst->wBitsPerSample) / 8; 690 adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * adfs->pwfxDst->nBlockAlign; 691 /* check if result is ok */ 692 if (ADPCM_GetFormatIndex(adfs->pwfxDst) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE; 693 break; 694 case WAVE_FORMAT_IMA_ADPCM: 695 if (adfs->cbwfxDst < sizeof(IMAADPCMWAVEFORMAT)) return ACMERR_NOTPOSSIBLE; 696 init_wfx_ima_adpcm((IMAADPCMWAVEFORMAT*)adfs->pwfxDst); 697 /* FIXME: not handling header overhead */ 698 TRACE("setting spb=%u\n", ((IMAADPCMWAVEFORMAT*)adfs->pwfxDst)->wSamplesPerBlock); 699 /* check if result is ok */ 700 if (ADPCM_GetFormatIndex(adfs->pwfxDst) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE; 701 break; 702 default: 703 return ACMERR_NOTPOSSIBLE; 704 } 705 706 return MMSYSERR_NOERROR; 707 } 708 709 /*********************************************************************** 710 * ADPCM_Reset 711 * 712 */ 713 static void ADPCM_Reset(PACMDRVSTREAMINSTANCE adsi, AcmAdpcmData* aad) 714 { 715 aad->stepIndexL = aad->stepIndexR = 0; 716 } 717 718 /*********************************************************************** 719 * ADPCM_StreamOpen 720 * 721 */ 722 static LRESULT ADPCM_StreamOpen(PACMDRVSTREAMINSTANCE adsi) 723 { 724 AcmAdpcmData* aad; 725 unsigned nspb; 726 727 assert(!(adsi->fdwOpen & ACM_STREAMOPENF_ASYNC)); 728 729 if (ADPCM_GetFormatIndex(adsi->pwfxSrc) == 0xFFFFFFFF || 730 ADPCM_GetFormatIndex(adsi->pwfxDst) == 0xFFFFFFFF) 731 return ACMERR_NOTPOSSIBLE; 732 733 aad = HeapAlloc(GetProcessHeap(), 0, sizeof(AcmAdpcmData)); 734 if (aad == 0) return MMSYSERR_NOMEM; 735 736 adsi->dwDriver = (DWORD_PTR)aad; 737 738 if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM && 739 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM) 740 { 741 goto theEnd; 742 } 743 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_IMA_ADPCM && 744 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM) 745 { 746 /* resampling or mono <=> stereo not available 747 * ADPCM algo only define 16 bit per sample output 748 * (The API seems to still allow 8 bit per sample output) 749 */ 750 if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec || 751 adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels || 752 (adsi->pwfxDst->wBitsPerSample != 16 && adsi->pwfxDst->wBitsPerSample != 8)) 753 goto theEnd; 754 755 nspb = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxSrc)->wSamplesPerBlock; 756 TRACE("spb=%u\n", nspb); 757 758 /* we check that in a block, after the header, samples are present on 759 * 4-sample packet pattern 760 * we also check that the block alignment is bigger than the expected size 761 */ 762 if (((nspb - 1) & 3) != 0) goto theEnd; 763 if ((((nspb - 1) / 2) + 4) * adsi->pwfxSrc->nChannels < adsi->pwfxSrc->nBlockAlign) 764 goto theEnd; 765 766 /* adpcm decoding... */ 767 if (adsi->pwfxDst->wBitsPerSample == 16 && adsi->pwfxDst->nChannels == 2) 768 aad->convert = cvtSSima16K; 769 if (adsi->pwfxDst->wBitsPerSample == 16 && adsi->pwfxDst->nChannels == 1) 770 aad->convert = cvtMMimaK; 771 if (adsi->pwfxDst->wBitsPerSample == 8 && adsi->pwfxDst->nChannels == 1) 772 aad->convert = cvtMMimaK; 773 /* FIXME: Stereo support for 8bit samples*/ 774 if (adsi->pwfxDst->wBitsPerSample == 8 && adsi->pwfxDst->nChannels == 2) 775 goto theEnd; 776 } 777 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM && 778 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_IMA_ADPCM) 779 { 780 if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec || 781 adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels || 782 adsi->pwfxSrc->wBitsPerSample != 16) 783 goto theEnd; 784 785 nspb = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxDst)->wSamplesPerBlock; 786 TRACE("spb=%u\n", nspb); 787 788 /* we check that in a block, after the header, samples are present on 789 * 4-sample packet pattern 790 * we also check that the block alignment is bigger than the expected size 791 */ 792 if (((nspb - 1) & 3) != 0) goto theEnd; 793 if ((((nspb - 1) / 2) + 4) * adsi->pwfxDst->nChannels < adsi->pwfxDst->nBlockAlign) 794 goto theEnd; 795 796 /* adpcm coding... */ 797 if (adsi->pwfxSrc->wBitsPerSample == 16 && adsi->pwfxSrc->nChannels == 2) 798 aad->convert = cvtSS16imaK; 799 if (adsi->pwfxSrc->wBitsPerSample == 16 && adsi->pwfxSrc->nChannels == 1) 800 aad->convert = cvtMM16imaK; 801 } 802 else goto theEnd; 803 ADPCM_Reset(adsi, aad); 804 805 return MMSYSERR_NOERROR; 806 807 theEnd: 808 HeapFree(GetProcessHeap(), 0, aad); 809 adsi->dwDriver = 0L; 810 return MMSYSERR_NOTSUPPORTED; 811 } 812 813 /*********************************************************************** 814 * ADPCM_StreamClose 815 * 816 */ 817 static LRESULT ADPCM_StreamClose(PACMDRVSTREAMINSTANCE adsi) 818 { 819 HeapFree(GetProcessHeap(), 0, (void*)adsi->dwDriver); 820 return MMSYSERR_NOERROR; 821 } 822 823 /*********************************************************************** 824 * ADPCM_StreamSize 825 * 826 */ 827 static LRESULT ADPCM_StreamSize(const ACMDRVSTREAMINSTANCE *adsi, PACMDRVSTREAMSIZE adss) 828 { 829 DWORD nblocks; 830 831 switch (adss->fdwSize) 832 { 833 case ACM_STREAMSIZEF_DESTINATION: 834 /* cbDstLength => cbSrcLength */ 835 if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM && 836 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_IMA_ADPCM) 837 { 838 nblocks = adss->cbDstLength / adsi->pwfxDst->nBlockAlign; 839 if (nblocks == 0) 840 return ACMERR_NOTPOSSIBLE; 841 adss->cbSrcLength = nblocks * adsi->pwfxSrc->nBlockAlign * ((IMAADPCMWAVEFORMAT*)adsi->pwfxDst)->wSamplesPerBlock; 842 } 843 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_IMA_ADPCM && 844 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM) 845 { 846 nblocks = adss->cbDstLength / (adsi->pwfxDst->nBlockAlign * ((IMAADPCMWAVEFORMAT*)adsi->pwfxSrc)->wSamplesPerBlock); 847 if (nblocks == 0) 848 return ACMERR_NOTPOSSIBLE; 849 adss->cbSrcLength = nblocks * adsi->pwfxSrc->nBlockAlign; 850 } 851 else 852 { 853 return MMSYSERR_NOTSUPPORTED; 854 } 855 break; 856 case ACM_STREAMSIZEF_SOURCE: 857 /* cbSrcLength => cbDstLength */ 858 if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM && 859 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_IMA_ADPCM) 860 { 861 nblocks = adss->cbSrcLength / (adsi->pwfxSrc->nBlockAlign * ((IMAADPCMWAVEFORMAT*)adsi->pwfxDst)->wSamplesPerBlock); 862 if (nblocks == 0) 863 return ACMERR_NOTPOSSIBLE; 864 if (adss->cbSrcLength % (adsi->pwfxSrc->nBlockAlign * ((IMAADPCMWAVEFORMAT*)adsi->pwfxDst)->wSamplesPerBlock)) 865 /* Round block count up. */ 866 nblocks++; 867 adss->cbDstLength = nblocks * adsi->pwfxDst->nBlockAlign; 868 } 869 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_IMA_ADPCM && 870 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM) 871 { 872 nblocks = adss->cbSrcLength / adsi->pwfxSrc->nBlockAlign; 873 if (nblocks == 0) 874 return ACMERR_NOTPOSSIBLE; 875 if (adss->cbSrcLength % adsi->pwfxSrc->nBlockAlign) 876 /* Round block count up. */ 877 nblocks++; 878 adss->cbDstLength = nblocks * adsi->pwfxDst->nBlockAlign * ((IMAADPCMWAVEFORMAT*)adsi->pwfxSrc)->wSamplesPerBlock; 879 } 880 else 881 { 882 return MMSYSERR_NOTSUPPORTED; 883 } 884 break; 885 default: 886 WARN("Unsupported query %08x\n", adss->fdwSize); 887 return MMSYSERR_NOTSUPPORTED; 888 } 889 return MMSYSERR_NOERROR; 890 } 891 892 /*********************************************************************** 893 * ADPCM_StreamConvert 894 * 895 */ 896 static LRESULT ADPCM_StreamConvert(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMHEADER adsh) 897 { 898 AcmAdpcmData* aad = (AcmAdpcmData*)adsi->dwDriver; 899 DWORD nsrc = adsh->cbSrcLength; 900 DWORD ndst = adsh->cbDstLength; 901 902 if (adsh->fdwConvert & 903 ~(ACM_STREAMCONVERTF_BLOCKALIGN| 904 ACM_STREAMCONVERTF_END| 905 ACM_STREAMCONVERTF_START)) 906 { 907 FIXME("Unsupported fdwConvert (%08x), ignoring it\n", adsh->fdwConvert); 908 } 909 /* ACM_STREAMCONVERTF_BLOCKALIGN 910 * currently all conversions are block aligned, so do nothing for this flag 911 * ACM_STREAMCONVERTF_END 912 * no pending data, so do nothing for this flag 913 */ 914 if ((adsh->fdwConvert & ACM_STREAMCONVERTF_START)) 915 { 916 ADPCM_Reset(adsi, aad); 917 } 918 919 aad->convert(adsi, adsh->pbSrc, &nsrc, adsh->pbDst, &ndst); 920 adsh->cbSrcLengthUsed = nsrc; 921 adsh->cbDstLengthUsed = ndst; 922 923 return MMSYSERR_NOERROR; 924 } 925 926 /************************************************************************** 927 * ADPCM_DriverProc [exported] 928 */ 929 LRESULT CALLBACK ADPCM_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg, 930 LPARAM dwParam1, LPARAM dwParam2) 931 { 932 TRACE("(%08lx %p %04x %08lx %08lx);\n", 933 dwDevID, hDriv, wMsg, dwParam1, dwParam2); 934 935 switch (wMsg) 936 { 937 case DRV_LOAD: return 1; 938 case DRV_FREE: return 1; 939 case DRV_OPEN: return 1; 940 case DRV_CLOSE: return ADPCM_drvClose(dwDevID); 941 case DRV_ENABLE: return 1; 942 case DRV_DISABLE: return 1; 943 case DRV_QUERYCONFIGURE: return 1; 944 case DRV_CONFIGURE: MessageBoxA(0, "MSACM IMA ADPCM filter !", "Wine Driver", MB_OK); return 1; 945 case DRV_INSTALL: return DRVCNF_RESTART; 946 case DRV_REMOVE: return DRVCNF_RESTART; 947 948 case ACMDM_DRIVER_NOTIFY: 949 /* no caching from other ACM drivers is done so far */ 950 return MMSYSERR_NOERROR; 951 952 case ACMDM_DRIVER_DETAILS: 953 return ADPCM_DriverDetails((PACMDRIVERDETAILSW)dwParam1); 954 955 case ACMDM_FORMATTAG_DETAILS: 956 return ADPCM_FormatTagDetails((PACMFORMATTAGDETAILSW)dwParam1, dwParam2); 957 958 case ACMDM_FORMAT_DETAILS: 959 return ADPCM_FormatDetails((PACMFORMATDETAILSW)dwParam1, dwParam2); 960 961 case ACMDM_FORMAT_SUGGEST: 962 return ADPCM_FormatSuggest((PACMDRVFORMATSUGGEST)dwParam1); 963 964 case ACMDM_STREAM_OPEN: 965 return ADPCM_StreamOpen((PACMDRVSTREAMINSTANCE)dwParam1); 966 967 case ACMDM_STREAM_CLOSE: 968 return ADPCM_StreamClose((PACMDRVSTREAMINSTANCE)dwParam1); 969 970 case ACMDM_STREAM_SIZE: 971 return ADPCM_StreamSize((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMSIZE)dwParam2); 972 973 case ACMDM_STREAM_CONVERT: 974 return ADPCM_StreamConvert((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMHEADER)dwParam2); 975 976 case ACMDM_HARDWARE_WAVE_CAPS_INPUT: 977 case ACMDM_HARDWARE_WAVE_CAPS_OUTPUT: 978 /* this converter is not a hardware driver */ 979 case ACMDM_FILTERTAG_DETAILS: 980 case ACMDM_FILTER_DETAILS: 981 /* this converter is not a filter */ 982 case ACMDM_STREAM_RESET: 983 /* only needed for asynchronous driver... we aren't, so just say it */ 984 return MMSYSERR_NOTSUPPORTED; 985 case ACMDM_STREAM_PREPARE: 986 case ACMDM_STREAM_UNPREPARE: 987 /* nothing special to do here... so don't do anything */ 988 return MMSYSERR_NOERROR; 989 990 default: 991 return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2); 992 } 993 } 994