DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator
src/hardware/snd_pc98/sound/pcm86g.c
00001 #include    "np2glue.h"
00002 //#include      "compiler.h"
00003 //#include      "pccore.h"
00004 //#include      "iocore.h"
00005 #include        "sound.h"
00006 #include        "fmboard.h"
00007 
00008 
00009 #define PCM86GET8(a)                                                                                                    \
00010                 (a) = (SINT8)pcm86.buffer[pcm86.readpos & PCM86_BUFMSK] << 8;   \
00011                 pcm86.readpos++;
00012 
00013 #define PCM86GET16(a)                                                                                                   \
00014                 (a) = (SINT8)pcm86.buffer[pcm86.readpos & PCM86_BUFMSK] << 8;   \
00015                 pcm86.readpos++;                                                                                                \
00016                 (a) += pcm86.buffer[pcm86.readpos & PCM86_BUFMSK];                              \
00017                 pcm86.readpos++;
00018 
00019 #define BYVOLUME(s)             ((((s) >> 6) * pcm86.volume) >> (PCM86_DIVBIT + 4))
00020 
00021 
00022 static void pcm86mono16(SINT32 *pcm, UINT count) {
00023 
00024         if (pcm86.div < PCM86_DIVENV) {                                 // アップさんぷる
00025                 do {
00026                         SINT32 smp;
00027                         if (pcm86.divremain < 0) {
00028                                 SINT32 dat;
00029                                 pcm86.divremain += PCM86_DIVENV;
00030                                 pcm86.realbuf -= 2;
00031                                 if (pcm86.realbuf < 0) {
00032                                         goto pm16_bufempty;
00033                                 }
00034                                 PCM86GET16(dat);
00035                                 pcm86.lastsmp = pcm86.smp;
00036                                 pcm86.smp = dat;
00037                         }
00038                         smp = (pcm86.lastsmp * pcm86.divremain) -
00039                                                         (pcm86.smp * (pcm86.divremain - PCM86_DIVENV));
00040                         pcm[0] += BYVOLUME(smp);
00041                         pcm += 2;
00042                         pcm86.divremain -= pcm86.div;
00043                 } while(--count);
00044         }
00045         else {
00046                 do {
00047                         SINT32 smp;
00048                         smp = pcm86.smp * (pcm86.divremain * -1);
00049                         pcm86.divremain += PCM86_DIVENV;
00050                         while(1) {
00051                                 SINT32 dat;
00052                                 pcm86.realbuf -= 2;
00053                                 if (pcm86.realbuf < 0) {
00054                                         goto pm16_bufempty;
00055                                 }
00056                                 PCM86GET16(dat);
00057                                 pcm86.lastsmp = pcm86.smp;
00058                                 pcm86.smp = dat;
00059                                 if (pcm86.divremain > pcm86.div2) {
00060                                         pcm86.divremain -= pcm86.div2;
00061                                         smp += pcm86.smp * pcm86.div2;
00062                                 }
00063                                 else {
00064                                         break;
00065                                 }
00066                         }
00067                         smp += pcm86.smp * pcm86.divremain;
00068                         pcm[0] += BYVOLUME(smp);
00069                         pcm += 2;
00070                         pcm86.divremain -= pcm86.div2;
00071                 } while(--count);
00072         }
00073         return;
00074 
00075 pm16_bufempty:
00076         pcm86.realbuf += 2;
00077         pcm86.divremain = 0;
00078         pcm86.smp = 0;
00079         pcm86.lastsmp = 0;
00080 }
00081 
00082 static void pcm86stereo16(SINT32 *pcm, UINT count) {
00083 
00084         if (pcm86.div < PCM86_DIVENV) {                                 // アップさんぷる
00085                 do {
00086                         SINT32 smp;
00087                         if (pcm86.divremain < 0) {
00088                                 SINT32 dat;
00089                                 pcm86.divremain += PCM86_DIVENV;
00090                                 pcm86.realbuf -= 4;
00091                                 if (pcm86.realbuf < 0) {
00092                                         goto ps16_bufempty;
00093                                 }
00094                                 PCM86GET16(dat);
00095                                 pcm86.lastsmp_l = pcm86.smp_l;
00096                                 pcm86.smp_l = dat;
00097                                 PCM86GET16(dat);
00098                                 pcm86.lastsmp_r = pcm86.smp_r;
00099                                 pcm86.smp_r = dat;
00100                         }
00101                         smp = (pcm86.lastsmp_l * pcm86.divremain) -
00102                                                         (pcm86.smp_l * (pcm86.divremain - PCM86_DIVENV));
00103                         pcm[0] += BYVOLUME(smp);
00104                         smp = (pcm86.lastsmp_r * pcm86.divremain) -
00105                                                         (pcm86.smp_r * (pcm86.divremain - PCM86_DIVENV));
00106                         pcm[1] += BYVOLUME(smp);
00107                         pcm += 2;
00108                         pcm86.divremain -= pcm86.div;
00109                 } while(--count);
00110         }
00111         else {
00112                 do {
00113                         SINT32 smp_l;
00114                         SINT32 smp_r;
00115                         smp_l = pcm86.smp_l * (pcm86.divremain * -1);
00116                         smp_r = pcm86.smp_r * (pcm86.divremain * -1);
00117                         pcm86.divremain += PCM86_DIVENV;
00118                         while(1) {
00119                                 SINT32 dat;
00120                                 pcm86.realbuf -= 4;
00121                                 if (pcm86.realbuf < 4) {
00122                                         goto ps16_bufempty;
00123                                 }
00124                                 PCM86GET16(dat);
00125                                 pcm86.lastsmp_l = pcm86.smp_l;
00126                                 pcm86.smp_l = dat;
00127                                 PCM86GET16(dat);
00128                                 pcm86.lastsmp_r = pcm86.smp_r;
00129                                 pcm86.smp_r = dat;
00130                                 if (pcm86.divremain > pcm86.div2) {
00131                                         pcm86.divremain -= pcm86.div2;
00132                                         smp_l += pcm86.smp_l * pcm86.div2;
00133                                         smp_r += pcm86.smp_r * pcm86.div2;
00134                                 }
00135                                 else {
00136                                         break;
00137                                 }
00138                         }
00139                         smp_l += pcm86.smp_l * pcm86.divremain;
00140                         smp_r += pcm86.smp_r * pcm86.divremain;
00141                         pcm[0] += BYVOLUME(smp_l);
00142                         pcm[1] += BYVOLUME(smp_r);
00143                         pcm += 2;
00144                         pcm86.divremain -= pcm86.div2;
00145                 } while(--count);
00146         }
00147         return;
00148 
00149 ps16_bufempty:
00150         pcm86.realbuf += 4;
00151         pcm86.divremain = 0;
00152         pcm86.smp_l = 0;
00153         pcm86.smp_r = 0;
00154         pcm86.lastsmp_l = 0;
00155         pcm86.lastsmp_r = 0;
00156 }
00157 
00158 static void pcm86mono8(SINT32 *pcm, UINT count) {
00159 
00160         if (pcm86.div < PCM86_DIVENV) {                                 // アップさんぷる
00161                 do {
00162                         SINT32 smp;
00163                         if (pcm86.divremain < 0) {
00164                                 SINT32 dat;
00165                                 pcm86.divremain += PCM86_DIVENV;
00166                                 pcm86.realbuf--;
00167                                 if (pcm86.realbuf < 0) {
00168                                         goto pm8_bufempty;
00169                                 }
00170                                 PCM86GET8(dat);
00171                                 pcm86.lastsmp = pcm86.smp;
00172                                 pcm86.smp = dat;
00173                         }
00174                         smp = (pcm86.lastsmp * pcm86.divremain) -
00175                                                         (pcm86.smp * (pcm86.divremain - PCM86_DIVENV));
00176                         pcm[0] += BYVOLUME(smp);
00177                         pcm += 2;
00178                         pcm86.divremain -= pcm86.div;
00179                 } while(--count);
00180         }
00181         else {
00182                 do {
00183                         SINT32 smp;
00184                         smp = pcm86.smp * (pcm86.divremain * -1);
00185                         pcm86.divremain += PCM86_DIVENV;
00186                         while(1) {
00187                                 SINT32 dat;
00188                                 pcm86.realbuf--;
00189                                 if (pcm86.realbuf < 0) {
00190                                         goto pm8_bufempty;
00191                                 }
00192                                 PCM86GET8(dat);
00193                                 pcm86.lastsmp = pcm86.smp;
00194                                 pcm86.smp = dat;
00195                                 if (pcm86.divremain > pcm86.div2) {
00196                                         pcm86.divremain -= pcm86.div2;
00197                                         smp += pcm86.smp * pcm86.div2;
00198                                 }
00199                                 else {
00200                                         break;
00201                                 }
00202                         }
00203                         smp += pcm86.smp * pcm86.divremain;
00204                         pcm[0] += BYVOLUME(smp);
00205                         pcm += 2;
00206                         pcm86.divremain -= pcm86.div2;
00207                 } while(--count);
00208         }
00209         return;
00210 
00211 pm8_bufempty:
00212         pcm86.realbuf += 1;
00213         pcm86.divremain = 0;
00214         pcm86.smp = 0;
00215         pcm86.lastsmp = 0;
00216 }
00217 
00218 static void pcm86stereo8(SINT32 *pcm, UINT count) {
00219 
00220         if (pcm86.div < PCM86_DIVENV) {                                 // アップさんぷる
00221                 do {
00222                         SINT32 smp;
00223                         if (pcm86.divremain < 0) {
00224                                 SINT32 dat;
00225                                 pcm86.divremain += PCM86_DIVENV;
00226                                 pcm86.realbuf -= 2;
00227                                 if (pcm86.realbuf < 0) {
00228                                         goto pm8_bufempty;
00229                                 }
00230                                 PCM86GET8(dat);
00231                                 pcm86.lastsmp_l = pcm86.smp_l;
00232                                 pcm86.smp_l = dat;
00233                                 PCM86GET8(dat);
00234                                 pcm86.lastsmp_r = pcm86.smp_r;
00235                                 pcm86.smp_r = dat;
00236                         }
00237                         smp = (pcm86.lastsmp_l * pcm86.divremain) -
00238                                                         (pcm86.smp_l * (pcm86.divremain - PCM86_DIVENV));
00239                         pcm[0] += BYVOLUME(smp);
00240                         smp = (pcm86.lastsmp_r * pcm86.divremain) -
00241                                                         (pcm86.smp_r * (pcm86.divremain - PCM86_DIVENV));
00242                         pcm[1] += BYVOLUME(smp);
00243                         pcm += 2;
00244                         pcm86.divremain -= pcm86.div;
00245                 } while(--count);
00246         }
00247         else {
00248                 do {
00249                         SINT32 smp_l;
00250                         SINT32 smp_r;
00251                         smp_l = pcm86.smp_l * (pcm86.divremain * -1);
00252                         smp_r = pcm86.smp_r * (pcm86.divremain * -1);
00253                         pcm86.divremain += PCM86_DIVENV;
00254                         while(1) {
00255                                 SINT32 dat;
00256                                 pcm86.realbuf -= 2;
00257                                 if (pcm86.realbuf < 0) {
00258                                         goto pm8_bufempty;
00259                                 }
00260                                 PCM86GET8(dat);
00261                                 pcm86.lastsmp_l = pcm86.smp_l;
00262                                 pcm86.smp_l = dat;
00263                                 PCM86GET8(dat);
00264                                 pcm86.lastsmp_r = pcm86.smp_r;
00265                                 pcm86.smp_r = dat;
00266                                 if (pcm86.divremain > pcm86.div2) {
00267                                         pcm86.divremain -= pcm86.div2;
00268                                         smp_l += pcm86.smp_l * pcm86.div2;
00269                                         smp_r += pcm86.smp_r * pcm86.div2;
00270                                 }
00271                                 else {
00272                                         break;
00273                                 }
00274                         }
00275                         smp_l += pcm86.smp_l * pcm86.divremain;
00276                         smp_r += pcm86.smp_r * pcm86.divremain;
00277                         pcm[0] += BYVOLUME(smp_l);
00278                         pcm[1] += BYVOLUME(smp_r);
00279                         pcm += 2;
00280                         pcm86.divremain -= pcm86.div2;
00281                 } while(--count);
00282         }
00283         return;
00284 
00285 pm8_bufempty:
00286         pcm86.realbuf += 2;
00287         pcm86.divremain = 0;
00288         pcm86.smp_l = 0;
00289         pcm86.smp_r = 0;
00290         pcm86.lastsmp_l = 0;
00291         pcm86.lastsmp_r = 0;
00292 }
00293 
00294 void SOUNDCALL pcm86gen_getpcm(void *hdl, SINT32 *pcm, UINT count) {
00295 
00296         if ((count) && (pcm86.fifo & 0x80) && (pcm86.div)) {
00297                 switch(pcm86.dactrl & 0x70) {
00298                         case 0x00:                                              // 16bit-none
00299                                 break;
00300 
00301                         case 0x10:                                              // 16bit-right
00302                                 pcm86mono16(pcm + 1, count);
00303                                 break;
00304 
00305                         case 0x20:                                              // 16bit-left
00306                                 pcm86mono16(pcm, count);
00307                                 break;
00308 
00309                         case 0x30:                                              // 16bit-stereo
00310                                 pcm86stereo16(pcm, count);
00311                                 break;
00312 
00313                         case 0x40:                                              // 8bit-none
00314                                 break;
00315 
00316                         case 0x50:                                              // 8bit-right
00317                                 pcm86mono8(pcm + 1, count);
00318                                 break;
00319 
00320                         case 0x60:                                              // 8bit-left
00321                                 pcm86mono8(pcm, count);
00322                                 break;
00323 
00324                         case 0x70:                                              // 8bit-stereo
00325                                 pcm86stereo8(pcm, count);
00326                                 break;
00327                 }
00328                 pcm86gen_checkbuf();
00329         }
00330         (void)hdl;
00331 }
00332