DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/hardware/snd_pc98/sound/getsnd/getwave.c
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