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