DOSBox-X
|
00001 #include "np2glue.h" 00002 //#include "compiler.h" 00003 #include "getsnd.h" 00004 00005 00006 #if defined(__GNUC__) 00007 typedef struct { 00008 char head[4]; 00009 UINT8 size[4]; 00010 char fmt[4]; 00011 } __attribute__ ((packed)) RIFF_HEADER; 00012 00013 typedef struct { 00014 char head[4]; 00015 UINT8 size[4]; 00016 } __attribute__ ((packed)) WAVE_HEADER; 00017 00018 typedef struct { 00019 UINT8 format[2]; 00020 UINT8 channel[2]; 00021 UINT8 rate[4]; 00022 UINT8 rps[4]; 00023 UINT8 block[2]; 00024 UINT8 bit[2]; 00025 } __attribute__ ((packed)) WAVE_INFOS; 00026 00027 typedef struct { 00028 UINT8 exsize[2]; 00029 UINT8 spb[2]; 00030 UINT8 numcoef[2]; 00031 } __attribute__ ((packed)) WAVE_MSA_INFO; 00032 00033 #else /* __GNUC__ */ 00034 00035 #pragma pack(push, 1) 00036 typedef struct { 00037 char head[4]; 00038 UINT8 size[4]; 00039 char fmt[4]; 00040 } RIFF_HEADER; 00041 00042 typedef struct { 00043 char head[4]; 00044 UINT8 size[4]; 00045 } WAVE_HEADER; 00046 00047 typedef struct { 00048 UINT8 format[2]; 00049 UINT8 channel[2]; 00050 UINT8 rate[4]; 00051 UINT8 rps[4]; 00052 UINT8 block[2]; 00053 UINT8 bit[2]; 00054 } WAVE_INFOS; 00055 00056 typedef struct { 00057 UINT8 exsize[2]; 00058 UINT8 spb[2]; 00059 UINT8 numcoef[2]; 00060 } WAVE_MSA_INFO; 00061 #pragma pack(pop) 00062 00063 #endif /* __GNUC__ */ 00064 00065 static const char fmt_riff[] = "RIFF"; 00066 static const char fmt_wave[] = "WAVE"; 00067 static const char fmt_rmp3[] = "RMP3"; 00068 static const char chunk_fmt[] = "fmt "; 00069 static const char chunk_data[] = "data"; 00070 00071 00072 // ---- PCM 00073 00074 #if defined(BYTESEX_LITTLE) 00075 static UINT pcm_dec(GETSND snd, void *dst) { 00076 00077 UINT size; 00078 00079 size = min(snd->blocksize, snd->datsize); 00080 if (size) { 00081 CopyMemory(dst, snd->datptr, size); 00082 snd->datptr += size; 00083 snd->datsize -= size; 00084 size >>= (int)((uintptr_t)snd->snd); 00085 } 00086 return(size); 00087 } 00088 #elif defined(BYTESEX_BIG) 00089 static UINT pcm_dec(GETSND snd, UINT8 *dst) { 00090 00091 UINT size; 00092 UINT cnt; 00093 UINT8 *src; 00094 00095 size = min(snd->blocksize, snd->datsize); 00096 if (size) { 00097 if (snd->bit == 16) { 00098 cnt = size >> 1; 00099 src = snd->datptr; 00100 while(cnt) { 00101 cnt--; 00102 dst[0] = src[1]; 00103 dst[1] = src[0]; 00104 src += 2; 00105 dst += 2; 00106 } 00107 } 00108 else { 00109 CopyMemory(dst, snd->datptr, size); 00110 } 00111 snd->datptr += size; 00112 snd->datsize -= size; 00113 size >>= (int)((uintptr_t)snd->snd); 00114 } 00115 return(size); 00116 } 00117 #endif 00118 00119 static const UINT8 abits[4] = {0, 1, 0, 2}; 00120 00121 static BOOL pcm_open(GETSND snd) { 00122 00123 UINT align; 00124 00125 if ((snd->bit != 8) && (snd->bit != 16)) { 00126 goto pcmopn_err; 00127 } 00128 align = snd->channels * (snd->bit >> 3); 00129 if (snd->blocksize != align) { 00130 goto pcmopn_err; 00131 } 00132 snd->blocksamples = 0x800; // 適当に。 00133 snd->blocksize *= snd->blocksamples; 00134 snd->snd = (void*)((uintptr_t)abits[align - 1]); 00135 snd->dec = (GSDEC)pcm_dec; 00136 return(SUCCESS); 00137 00138 pcmopn_err: 00139 return(FAILURE); 00140 } 00141 00142 00143 // ---- MS-ADPCM 00144 00145 typedef struct { 00146 SINT16 Coef1; 00147 SINT16 Coef2; 00148 } __COEFPAIR; 00149 00150 static const int MSADPCMTable[16] = { 00151 230, 230, 230, 230, 307, 409, 512, 614, 00152 768, 614, 512, 409, 307, 230, 230, 230 00153 }; 00154 00155 static UINT msa_dec(GETSND snd, SINT16 *dst) { 00156 00157 UINT8 *buf; 00158 UINT size; 00159 UINT outsamples; 00160 int pred[2], delta[2], nibble; 00161 UINT i; 00162 UINT8 indata; 00163 __COEFPAIR *coef; 00164 UINT ch; 00165 SINT32 outdata; 00166 00167 buf = snd->datptr; // ワーク使ってません。 00168 size = min(snd->datsize, snd->blocksize); 00169 snd->datptr += size; 00170 snd->datsize -= size; 00171 00172 outsamples = 0; 00173 if (snd->channels == 1) { 00174 if (size >= 7) { 00175 pred[0] = buf[0]; 00176 pred[1] = 0; 00177 delta[0] = LOADINTELWORD(buf+1); 00178 delta[1] = 0; 00179 *dst++ = (SINT16)LOADINTELWORD(buf+5); 00180 *dst++ = (SINT16)LOADINTELWORD(buf+3); 00181 buf += 7; 00182 outsamples = 2 + ((size - 7) * 2); 00183 } 00184 } 00185 else { 00186 if (size >= 14) { 00187 pred[0] = buf[0]; 00188 pred[1] = buf[1]; 00189 delta[0] = LOADINTELWORD(buf+2); 00190 delta[1] = LOADINTELWORD(buf+4); 00191 *dst++ = (SINT16)LOADINTELWORD(buf+10); 00192 *dst++ = (SINT16)LOADINTELWORD(buf+12); 00193 *dst++ = (SINT16)LOADINTELWORD(buf+6); 00194 *dst++ = (SINT16)LOADINTELWORD(buf+8); 00195 buf += 14; 00196 outsamples = 2 + (size - 14); 00197 } 00198 } 00199 coef = (__COEFPAIR *)snd->snd; 00200 nibble = 0; 00201 indata = 0; // for gcc 00202 for (i=2; i<outsamples; i++) { 00203 for (ch=0; ch<snd->channels; ch++) { 00204 int d = delta[ch], p, data; 00205 if (!nibble) { 00206 indata = *buf++; 00207 data = indata >> 4; 00208 } 00209 else { 00210 data = indata & 15; 00211 } 00212 nibble ^= 1; 00213 delta[ch] = (MSADPCMTable[data] * d) >> 8; 00214 if (delta[ch] < 16) { 00215 delta[ch] = 16; 00216 } 00217 p = (((*(dst - snd->channels )) * coef[pred[ch]].Coef1) 00218 +((*(dst - snd->channels*2)) * coef[pred[ch]].Coef2)); 00219 p >>= 8; 00220 outdata = (((data>=8)?(data-16):data) * d) + p; 00221 if (outdata > 32767) { 00222 outdata = 32767; 00223 } 00224 else if (outdata < -32768) { 00225 outdata = -32768; 00226 } 00227 *dst++ = (SINT16)outdata; 00228 } 00229 } 00230 return(outsamples); 00231 } 00232 00233 static void msa_decend(GETSND snd) { 00234 00235 _MFREE(snd->snd); 00236 } 00237 00238 static BOOL msa_open(GETSND snd, WAVE_INFOS *wavehead, UINT headsize) { 00239 00240 WAVE_MSA_INFO *info; 00241 UINT exsize; 00242 UINT numcoef; 00243 UINT spb; 00244 UINT blk; 00245 __COEFPAIR *coef; 00246 UINT8 *p; 00247 00248 if ((snd->bit != 4) || 00249 (headsize < (sizeof(WAVE_INFOS) + sizeof(WAVE_MSA_INFO)))) { 00250 goto msaopn_err; 00251 } 00252 info = (WAVE_MSA_INFO *)(wavehead + 1); 00253 headsize -= sizeof(WAVE_INFOS); 00254 headsize -= sizeof(WAVE_MSA_INFO); 00255 exsize = LOADINTELWORD(info->exsize); 00256 spb = LOADINTELWORD(info->spb); 00257 numcoef = LOADINTELWORD(info->numcoef); 00258 blk = snd->blocksize; 00259 blk /= snd->channels; 00260 blk -= 6; 00261 blk *= 2; 00262 TRACEOUT(("wav: msa: ExtraSize %d / SPB=%d NumOfCoefs=%d", 00263 exsize, spb, numcoef)); 00264 00265 if (blk != spb) { 00266 TRACEOUT(("wav: msa: block size error")); 00267 goto msaopn_err; 00268 } 00269 if (exsize < (numcoef * 4 + 4)) { 00270 TRACEOUT(("wav: msa: extra info size error")); 00271 goto msaopn_err; 00272 } 00273 if (numcoef == 0) { 00274 TRACEOUT(("wav: msa: coef == 0")); 00275 goto msaopn_err; 00276 } 00277 00278 coef = (__COEFPAIR*)_MALLOC(numcoef * sizeof(__COEFPAIR), "adpcm coefs"); 00279 if (coef == NULL) { 00280 goto msaopn_err; 00281 } 00282 00283 snd->blocksamples = spb; 00284 snd->bit = 16; 00285 snd->dec = (GSDEC)msa_dec; 00286 snd->decend = msa_decend; 00287 snd->snd = (void *)coef; 00288 00289 p = (UINT8 *)(info + 1); 00290 do { 00291 coef->Coef1 = LOADINTELWORD(p + 0); 00292 coef->Coef2 = LOADINTELWORD(p + 2); 00293 coef++; 00294 p += 4; 00295 } while(--numcoef); 00296 return(SUCCESS); 00297 00298 msaopn_err: 00299 return(FAILURE); 00300 } 00301 00302 00303 // ---- IMA 00304 00305 #define IMA_MAXSTEP 89 00306 00307 static BOOL ima_init = FALSE; 00308 static UINT8 ima_statetbl[IMA_MAXSTEP][8]; 00309 00310 static const int ima_stateadj[8] = {-1, -1, -1, -1, 2, 4, 6, 8}; 00311 00312 static const int ima_steptable[IMA_MAXSTEP] = { 00313 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 00314 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55, 00315 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, 00316 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449, 00317 494, 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282, 00318 1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327, 3660, 00319 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, 9493,10442, 00320 11487,12635,13899,15289,16818,18500,20350,22385,24623,27086,29794,32767}; 00321 00322 static void ima_inittable(void) { 00323 00324 int i, j, k; 00325 00326 for (i=0; i<IMA_MAXSTEP; i++) { 00327 for (j=0; j<8; j++) { 00328 k = i + ima_stateadj[j]; 00329 if (k < 0) { 00330 k = 0; 00331 } 00332 else if (k >= IMA_MAXSTEP) { 00333 k = IMA_MAXSTEP - 1; 00334 } 00335 ima_statetbl[i][j] = (UINT8)k; 00336 } 00337 } 00338 } 00339 00340 static UINT ima_dec(GETSND snd, SINT16 *dst) { 00341 00342 UINT c; 00343 SINT32 val[2]; 00344 int state[2]; 00345 UINT8 *src; 00346 UINT blk; 00347 00348 if (snd->blocksize > snd->datsize) { 00349 goto imadec_err; 00350 } 00351 src = snd->datptr; // ワーク使ってません。 00352 snd->datptr += snd->blocksize; 00353 snd->datsize -= snd->blocksize; 00354 00355 blk = snd->blocksamples; 00356 for (c=0; c<snd->channels; c++) { 00357 SINT16 tmp; 00358 tmp = LOADINTELWORD(src); 00359 val[c] = tmp; 00360 *dst++ = (SINT16)val[c]; 00361 state[c] = src[2]; 00362 if (state[c] >= IMA_MAXSTEP) { 00363 state[c] = 0; 00364 } 00365 src += 4; 00366 } 00367 blk--; 00368 00369 while(blk >= 8) { 00370 blk -= 8; 00371 for (c=0; c<snd->channels; c++) { 00372 UINT samp, r; 00373 samp = 0; // for gcc 00374 r = 8; 00375 do { 00376 int step, dp; 00377 if (!(r & 1)) { 00378 samp = *src++; 00379 } 00380 else { 00381 samp >>= 4; 00382 } 00383 step = ima_steptable[state[c]]; 00384 state[c] = ima_statetbl[state[c]][samp & 7]; 00385 dp = ((((samp & 7) << 1) + 1) * step) >> 3; 00386 if (!(samp & 8)) { 00387 val[c] += dp; 00388 if (val[c] > 32767) { 00389 val[c] = 32767; 00390 } 00391 } 00392 else { 00393 val[c] -= dp; 00394 if (val[c] < -32768) { 00395 val[c] = -32768; 00396 } 00397 } 00398 *dst = (SINT16)val[c]; 00399 dst += snd->channels; 00400 } while(--r); 00401 dst -= (8 * snd->channels); 00402 dst++; 00403 } 00404 dst += (7 * snd->channels); 00405 } 00406 return(snd->blocksamples); 00407 00408 imadec_err: 00409 return(0); 00410 } 00411 00412 static BOOL ima_open(GETSND snd) { 00413 00414 int blk; 00415 00416 if (snd->bit != 4) { 00417 goto imaopn_err; 00418 } 00419 blk = snd->blocksize; 00420 blk /= snd->channels; 00421 if (blk & 3) { 00422 goto imaopn_err; 00423 } 00424 blk -= 4; // first block; 00425 blk *= 2; 00426 blk += 1; 00427 snd->blocksamples = blk; 00428 snd->bit = 16; 00429 snd->dec = (GSDEC)ima_dec; 00430 if (!ima_init) { 00431 ima_init = TRUE; 00432 ima_inittable(); 00433 } 00434 return(SUCCESS); 00435 00436 imaopn_err: 00437 return(FAILURE); 00438 } 00439 00440 00441 // ---- MP3 00442 00443 #if defined(SUPPORT_MP3) 00444 extern BOOL __mp3_open(GETSND snd, UINT8 *ptr, UINT size); 00445 #endif 00446 00447 00448 // ---- 00449 00450 BOOL getwave_open(GETSND snd, UINT8 *ptr, UINT size) { 00451 00452 RIFF_HEADER *riff; 00453 WAVE_HEADER *head; 00454 WAVE_INFOS *info; 00455 UINT pos; 00456 UINT format; 00457 BOOL r; 00458 UINT headsize = 0; 00459 UINT datasize; 00460 00461 info = NULL; // for gcc 00462 00463 // RIFFのチェック 00464 riff = (RIFF_HEADER *)ptr; 00465 pos = sizeof(RIFF_HEADER); 00466 if (size < pos) { 00467 TRACEOUT(("wav: error RIFF header")); 00468 goto gwopn_err; 00469 } 00470 if (memcmp(riff->head, fmt_riff, 4)) { 00471 TRACEOUT(("wav: error RIFF header")); 00472 goto gwopn_err; 00473 } 00474 if (!memcmp(riff->fmt, fmt_wave, 4)) { 00475 // フォーマットヘッダチェック 00476 head = (WAVE_HEADER *)(ptr + pos); 00477 pos += sizeof(WAVE_HEADER); 00478 if (size < pos) { 00479 TRACEOUT(("wav: error fmt header")); 00480 goto gwopn_err; 00481 } 00482 if (memcmp(head->head, chunk_fmt, 4)) { 00483 TRACEOUT(("wav: error fmt header")); 00484 goto gwopn_err; 00485 } 00486 headsize = LOADINTELDWORD(head->size); 00487 if (headsize < sizeof(WAVE_INFOS)) { 00488 TRACEOUT(("wav: error fmt length")); 00489 goto gwopn_err; 00490 } 00491 00492 // フォーマットチェック 00493 info = (WAVE_INFOS *)(ptr + pos); 00494 pos += headsize; 00495 if (size < pos) { 00496 TRACEOUT(("wav: error fmt data")); 00497 goto gwopn_err; 00498 } 00499 format = LOADINTELWORD(info->format); 00500 snd->channels = LOADINTELWORD(info->channel); 00501 snd->samplingrate = LOADINTELDWORD(info->rate); 00502 snd->blocksize = LOADINTELWORD(info->block); 00503 snd->bit = LOADINTELWORD(info->bit); 00504 TRACEOUT(("wav: fmt: %x / %dch %dHz %dbit", 00505 format, snd->channels, snd->samplingrate, snd->bit)); 00506 if ((UINT)(snd->channels - 1) >= 2) { 00507 TRACEOUT(("wav: channels err")); 00508 goto gwopn_err; 00509 } 00510 } 00511 else if (!memcmp(riff->fmt, fmt_rmp3, 4)) { 00512 format = 0x55; 00513 } 00514 else { 00515 TRACEOUT(("wav: error WAVE header")); 00516 goto gwopn_err; 00517 } 00518 00519 // dataまで移動。 00520 while(1) { 00521 head = (WAVE_HEADER *)(ptr + pos); 00522 pos += sizeof(WAVE_HEADER); 00523 if (size < pos) { 00524 TRACEOUT(("wav: error data header")); 00525 goto gwopn_err; 00526 } 00527 if (!memcmp(head->head, chunk_data, 4)) { 00528 break; 00529 } 00530 pos += LOADINTELDWORD(head->size); 00531 } 00532 ptr += pos; 00533 size -= pos; 00534 datasize = LOADINTELDWORD(head->size); 00535 size = min(size, datasize); 00536 00537 switch(format) { 00538 case 0x01: // PCM 00539 r = pcm_open(snd); 00540 break; 00541 00542 case 0x02: 00543 r = msa_open(snd, info, headsize); 00544 break; 00545 00546 case 0x11: 00547 r = ima_open(snd); 00548 break; 00549 00550 #if defined(SUPPORT_MP3) 00551 case 0x55: 00552 return(__mp3_open(snd, ptr, size)); 00553 #endif 00554 00555 #if defined(SUPPORT_OGG) 00556 case 0x6751: 00557 return(getogg_open(snd, ptr, size)); 00558 #endif 00559 00560 default: 00561 r = FAILURE; 00562 break; 00563 } 00564 if (r != SUCCESS) { 00565 TRACEOUT(("wav: decord open error")); 00566 goto gwopn_err; 00567 } 00568 00569 // 登録〜 00570 snd->datptr = ptr; 00571 snd->datsize = size; 00572 return(SUCCESS); 00573 00574 gwopn_err: 00575 return(FAILURE); 00576 } 00577