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