Diff for /np2/sound/sound.c between versions 1.2 and 1.17

version 1.2, 2003/10/19 14:56:15 version 1.17, 2004/07/03 17:25:39
Line 1 Line 1
 #include        "compiler.h"  #include        "compiler.h"
   #include        "wavefile.h"
   #include        "dosio.h"
 #include        "soundmng.h"  #include        "soundmng.h"
 #include        "i286.h"  #include        "cpucore.h"
 #include        "pccore.h"  #include        "pccore.h"
 #include        "iocore.h"  #include        "iocore.h"
 #include        "sound.h"  #include        "sound.h"
 #include        "sndcsec.h"  #include        "sndcsec.h"
 #include        "beep.h"  #include        "beep.h"
   #include        "getsnd.h"
   
   
         UINT32  opna_rate = 22050;          SOUNDCFG        soundcfg;
   
 static int      writebytes = 0;  
         UINT32  ratebase200 = 110;  
         UINT32  dsound_lastclock = 0;  
   
   
   
   
 #define STREAM_CBMAX    16  #define STREAM_CBMAX    16
Line 28  typedef struct { Line 25  typedef struct {
         SINT32  *buffer;          SINT32  *buffer;
         SINT32  *ptr;          SINT32  *ptr;
         UINT    samples;          UINT    samples;
           UINT    reserve;
         UINT    remain;          UINT    remain;
   #if defined(SUPPORT_WAVEREC)
           WAVEWR  rec;
   #endif
         CBTBL   *cbreg;          CBTBL   *cbreg;
         CBTBL   cb[STREAM_CBMAX];          CBTBL   cb[STREAM_CBMAX];
 } SNDSTREAM;  } SNDSTREAM;
Line 38  static SNDSTREAM sndstream; Line 39  static SNDSTREAM sndstream;
   
 static void streamreset(void) {  static void streamreset(void) {
   
           SNDCSEC_ENTER;
         sndstream.ptr = sndstream.buffer;          sndstream.ptr = sndstream.buffer;
         sndstream.remain = sndstream.samples;          sndstream.remain = sndstream.samples + sndstream.reserve;
         sndstream.cbreg = sndstream.cb;          sndstream.cbreg = sndstream.cb;
           SNDCSEC_LEAVE;
 }  }
   
 static void streamprepare(UINT samples) {  static void streamprepare(UINT samples) {
Line 62  static void streamprepare(UINT samples)  Line 65  static void streamprepare(UINT samples) 
 }  }
   
   
   #if defined(SUPPORT_WAVEREC)
   // ---- wave rec
   
   BOOL sound_recstart(const char *filename) {
   
           WAVEWR  rec;
   
           sound_recstop();
           if (sndstream.buffer == NULL) {
                   return(FAILURE);
           }
           rec = wavewr_open(filename, soundcfg.rate, 16, 2);
           sndstream.rec = rec;
           if (rec) {
                   return(SUCCESS);
           }
           return(FAILURE);
   }
   
   void sound_recstop(void) {
   
           WAVEWR  rec;
   
           rec = sndstream.rec;
           sndstream.rec = NULL;
           wavewr_close(rec);
   }
   
   static void streamfilewrite(UINT samples) {
   
           CBTBL   *cb;
           UINT    count;
           SINT32  buf32[2*512];
           BYTE    buf[2*2*512];
           UINT    r;
           UINT    i;
           SINT32  samp;
   
           while(samples) {
                   count = min(samples, 512);
                   ZeroMemory(buf32, count * 2 * sizeof(SINT32));
                   cb = sndstream.cb;
                   while(cb < sndstream.cbreg) {
                           cb->cbfn(cb->hdl, buf32, count);
                           cb++;
                   }
                   r = min(sndstream.remain, count);
                   if (r) {
                           CopyMemory(sndstream.ptr, buf32, r * 2 * sizeof(SINT32));
                           sndstream.ptr += r * 2;
                           sndstream.remain -= r;
                   }
                   for (i=0; i<count*2; i++) {
                           samp = buf32[i];
                           if (samp > 32767) {
                                   samp = 32767;
                           }
                           else if (samp < -32768) {
                                   samp = -32768;
                           }
                           // little endianなので satuation_s16は使えない
                           buf[i*2+0] = (BYTE)samp;
                           buf[i*2+1] = (BYTE)(samp >> 8);
                   }
                   wavewr_write(sndstream.rec, buf, count * 4);
                   samples -= count;
           }
   }
   
   static void filltailsample(UINT count) {
   
           SINT32  *ptr;
           UINT    orgsize;
           SINT32  sampl;
           SINT32  sampr;
   
           count = min(sndstream.remain, count);
           if (count) {
                   ptr = sndstream.ptr;
                   orgsize = (ptr - sndstream.buffer) / 2;
                   if (orgsize == 0) {
                           sampl = 0;
                           sampr = 0;
                   }
                   else {
                           sampl = *(ptr - 2);
                           sampr = *(ptr - 1);
                   }
                   sndstream.ptr += count * 2;
                   sndstream.remain -= count;
                   do {
                           ptr[0] = sampl;
                           ptr[1] = sampr;
                           ptr += 2;
                   } while(--count);
           }
   }
   #endif
   
   
 // ----  // ----
   
 BOOL sound_create(UINT rate, UINT ms) {  BOOL sound_create(UINT rate, UINT ms) {
   
         UINT    samples;          UINT    samples;
           UINT    reserve;
   
         ZeroMemory(&sndstream, sizeof(sndstream));          ZeroMemory(&sndstream, sizeof(sndstream));
         if (rate == 0) {  
                 return(SUCCESS);  
         }  
         switch(rate) {          switch(rate) {
                 case 11025:                  case 11025:
                         opna_rate = 11025;  
                         break;  
   
                 case 22050:                  case 22050:
                         opna_rate = 22050;  
                         break;  
   
                 case 44100:                  case 44100:
                         opna_rate = 44100;  
                         break;                          break;
   
                 default:                  default:
Line 94  BOOL sound_create(UINT rate, UINT ms) { Line 188  BOOL sound_create(UINT rate, UINT ms) {
         }          }
         soundmng_reset();          soundmng_reset();
   
         sndstream.buffer = (SINT32 *)_MALLOC(samples * 2 * sizeof(SINT32),          soundcfg.rate = rate;
                                                                                                                                 "stream");          sound_changeclock();
   
   #if defined(SOUNDRESERVE)
           reserve = rate * SOUNDRESERVE / 1000;
   #else
           reserve = 0;
   #endif
           sndstream.buffer = (SINT32 *)_MALLOC((samples + reserve) * 2 
                                                                                                   * sizeof(SINT32), "stream");
         if (sndstream.buffer == NULL) {          if (sndstream.buffer == NULL) {
                 goto scre_err2;                  goto scre_err2;
         }          }
         sndstream.samples = samples;          sndstream.samples = samples;
         streamreset();          sndstream.reserve = reserve;
         ratebase200 = (opna_rate + 199) / 200;  
   
         SNDCSEC_INIT;          SNDCSEC_INIT;
           streamreset();
         return(SUCCESS);          return(SUCCESS);
   
 scre_err2:  scre_err2:
Line 116  scre_err1: Line 218  scre_err1:
 void sound_destroy(void) {  void sound_destroy(void) {
   
         if (sndstream.buffer) {          if (sndstream.buffer) {
                 SNDCSEC_TERM;  #if defined(SUPPORT_WAVEREC)
                   sound_recstop();
   #endif
                 soundmng_stop();                  soundmng_stop();
                   streamreset();
                 soundmng_destroy();                  soundmng_destroy();
                   SNDCSEC_TERM;
                 _MFREE(sndstream.buffer);                  _MFREE(sndstream.buffer);
                 sndstream.buffer = NULL;                  sndstream.buffer = NULL;
         }          }
Line 130  void sound_reset(void) { Line 235  void sound_reset(void) {
         if (sndstream.buffer) {          if (sndstream.buffer) {
                 soundmng_reset();                  soundmng_reset();
                 streamreset();                  streamreset();
                 dsound_lastclock = I286_CLOCK;                  soundcfg.lastclock = CPU_CLOCK;
                 beep_eventreset();                  beep_eventreset();
         }          }
 }  }
   
   void sound_changeclock(void) {
   
           UINT32  clock;
           UINT    hz;
           UINT    hzmax;
   
           if (sndstream.buffer == NULL) {
                   return;
           }
   
           // とりあえず 25で割り切れる。
           clock = pccore.realclock / 25;
           hz = soundcfg.rate / 25;
   
           // で、クロック数に合せて調整。(64bit演算しろよな的)
           hzmax = (1 << (32 - 8)) / (clock >> 8);
           while(hzmax < hz) {
                   clock = (clock + 1) >> 1;
                   hz = (hz + 1) >> 1;
           }
           TRACEOUT(("hzbase/clockbase = %d/%d", hz, clock));
           soundcfg.hzbase = hz;
           soundcfg.clockbase = clock;
           soundcfg.minclock = 2 * clock / hz;
           soundcfg.lastclock = CPU_CLOCK;
   }
   
 void sound_streamregist(void *hdl, SOUNDCB cbfn) {  void sound_streamregist(void *hdl, SOUNDCB cbfn) {
   
         if (sndstream.buffer) {          if (sndstream.buffer) {
Line 152  void sound_streamregist(void *hdl, SOUND Line 284  void sound_streamregist(void *hdl, SOUND
   
 void sound_sync(void) {  void sound_sync(void) {
   
         UINT    length;          UINT32  length;
   
         if (sndstream.buffer == NULL) {          if (sndstream.buffer == NULL) {
                 return;                  return;
         }          }
   
         length = (I286_CLOCK + I286_BASECLOCK - I286_REMCLOCK          length = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK - soundcfg.lastclock;
                                                                                         - dsound_lastclock) * ratebase200;          if (length < soundcfg.minclock) {
         if (length < pc.dsoundclock2) {  
                 return;                  return;
         }          }
         length /= pc.dsoundclock;          length = (length * soundcfg.hzbase) / soundcfg.clockbase;
         if (length) {          if (length == 0) {
                 SNDCSEC_ENTER;                  return;
                 streamprepare(length);  
                 SNDCSEC_LEAVE;  
                 writebytes += length;  
                 dsound_lastclock += (length * pc.dsoundclock / ratebase200);  
                 beep_eventreset();  
         }          }
           SNDCSEC_ENTER;
         if (writebytes >= 100) {  #if defined(SUPPORT_WAVEREC)
                 writebytes = 0;          if (sndstream.rec) {
                   streamfilewrite(length);
           }
           else
   #endif
           streamprepare(length);
           soundcfg.lastclock += length * soundcfg.clockbase / soundcfg.hzbase;
           beep_eventreset();
           SNDCSEC_LEAVE;
   
           soundcfg.writecount += length;
           if (soundcfg.writecount >= 100) {
                   soundcfg.writecount = 0;
                 soundmng_sync();                  soundmng_sync();
         }          }
 }  }
   
   static volatile int locks = 0;
   
 const SINT32 *sound_pcmlock(void) {  const SINT32 *sound_pcmlock(void) {
   
 const SINT32 *ret;  const SINT32 *ret;
   
           if (locks) {
                   TRACEOUT(("sound pcm lock: already locked"));
                   return(NULL);
           }
           locks++;
         ret = sndstream.buffer;          ret = sndstream.buffer;
         if (ret) {          if (ret) {
                 SNDCSEC_ENTER;                  SNDCSEC_ENTER;
                 if (sndstream.remain) {                  if (sndstream.remain > sndstream.reserve)
                         streamprepare(sndstream.remain);  #if defined(SUPPORT_WAVEREC)
                         dsound_lastclock = I286_CLOCK;                          if (sndstream.rec) {
                                   filltailsample(sndstream.remain - sndstream.reserve);
                           }
                           else
   #endif
                   {
                           streamprepare(sndstream.remain - sndstream.reserve);
                           soundcfg.lastclock = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK;
                         beep_eventreset();                          beep_eventreset();
                 }                  }
         }          }
           else {
                   locks--;
           }
         return(ret);          return(ret);
 }  }
   
 void sound_pcmunlock(const SINT32 *hdl) {  void sound_pcmunlock(const SINT32 *hdl) {
   
           int             leng;
   
         if (hdl) {          if (hdl) {
                 sndstream.ptr = sndstream.buffer;                  leng = sndstream.reserve - sndstream.remain;
                 sndstream.remain = sndstream.samples;                  if (leng > 0) {
                           CopyMemory(sndstream.buffer,
                                                   sndstream.buffer + (sndstream.samples * 2),
                                                                                                   leng * 2 * sizeof(SINT32));
                   }
                   sndstream.ptr = sndstream.buffer + (leng * 2);
                   sndstream.remain = sndstream.samples + sndstream.reserve - leng;
   //              sndstream.remain += sndstream.samples;
                 SNDCSEC_LEAVE;                  SNDCSEC_LEAVE;
                   locks--;
         }          }
 }  }
   
   
   // ---- pcmmix
   
   BOOL pcmmix_regist(PMIXDAT *dat, void *datptr, UINT datsize, UINT rate) {
   
           GETSND  gs;
           BYTE    tmp[256];
           UINT    size;
           UINT    r;
           SINT16  *buf;
   
           gs = getsnd_create(datptr, datsize);
           if (gs == NULL) {
                   goto pmr_err1;
           }
           if (getsnd_setmixproc(gs, rate, 1) != SUCCESS) {
                   goto pmr_err2;
           }
           size = 0;
           do {
                   r = getsnd_getpcmbyleng(gs, tmp, sizeof(tmp));
                   size += r;
           } while(r);
           getsnd_destroy(gs);
           if (size == 0) {
                   goto pmr_err1;
           }
   
           buf = (SINT16 *)_MALLOC(size, "PCM DATA");
           if (buf == NULL) {
                   goto pmr_err1;
           }
           gs = getsnd_create(datptr, datsize);
           if (gs == NULL) {
                   goto pmr_err1;
           }
           if (getsnd_setmixproc(gs, rate, 1) != SUCCESS) {
                   goto pmr_err2;
           }
           r = getsnd_getpcmbyleng(gs, buf, size);
           getsnd_destroy(gs);
           dat->sample = buf;
           dat->samples = r / 2;
           return(SUCCESS);
   
   pmr_err2:
           getsnd_destroy(gs);
   
   pmr_err1:
           return(FAILURE);
   }
   
   BOOL pcmmix_regfile(PMIXDAT *dat, const char *fname, UINT rate) {
   
           FILEH   fh;
           UINT    size;
           BYTE    *ptr;
           BOOL    r;
   
           r = FAILURE;
           fh = file_open_rb(fname);
           if (fh == FILEH_INVALID) {
                   goto pmrf_err1;
           }
           size = file_getsize(fh);
           if (size == 0) {
                   goto pmrf_err2;
           }
           ptr = (BYTE *)_MALLOC(size, fname);
           if (ptr == NULL) {
                   goto pmrf_err2;
           }
           file_read(fh, ptr, size);
           file_close(fh);
           r = pcmmix_regist(dat, ptr, size, rate);
           _MFREE(ptr);
           return(r);
   
   pmrf_err2:
           file_close(fh);
   
   pmrf_err1:
           return(FAILURE);
   }
   
   void SOUNDCALL pcmmix_getpcm(PCMMIX hdl, SINT32 *pcm, UINT count) {
   
           UINT32          bitmap;
           PMIXTRK         *t;
   const SINT16    *s;
           UINT            srem;
           SINT32          *d;
           UINT            drem;
           UINT            r;
           UINT            j;
           UINT            flag;
           SINT32          vol;
           SINT32          samp;
   
           if ((hdl->hdr.playing == 0) || (count == 0))  {
                   return;
           }
           t = hdl->trk;
           bitmap = 1;
           do {
                   if (hdl->hdr.playing & bitmap) {
                           s = t->pcm;
                           srem = t->remain;
                           d = pcm;
                           drem = count;
                           flag = t->flag;
                           vol = t->volume;
                           do {
                                   r = min(srem, drem);
                                   switch(flag & (PMIXFLAG_L | PMIXFLAG_R)) {
                                           case PMIXFLAG_L:
                                                   for (j=0; j<r; j++) {
                                                           d[j*2+0] += (s[j] * vol) >> 12;
                                                   }
                                                   break;
   
                                           case PMIXFLAG_R:
                                                   for (j=0; j<r; j++) {
                                                           d[j*2+1] += (s[j] * vol) >> 12;
                                                   }
                                                   break;
   
                                           case PMIXFLAG_L | PMIXFLAG_R:
                                                   for (j=0; j<r; j++) {
                                                           samp = (s[j] * vol) >> 12;
                                                           d[j*2+0] += samp;
                                                           d[j*2+1] += samp;
                                                   }
                                                   break;
                                   }
                                   s += r;
                                   d += r*2;
                                   srem -= r;
                                   if (srem == 0) {
                                           if (flag & PMIXFLAG_LOOP) {
                                                   s = t->data.sample;
                                                   srem = t->data.samples;
                                           }
                                           else {
                                                   hdl->hdr.playing &= ~bitmap;
                                                   break;
                                           }
                                   }
                                   drem -= r;
                           } while(drem);
                           t->pcm = s;
                           t->remain = srem;
                   }
                   t++;
                   bitmap <<= 1;
           } while(bitmap < hdl->hdr.enable);
   }
   

Removed from v.1.2  
changed lines
  Added in v.1.17


RetroPC.NET-CVS <cvs@retropc.net>