| version 1.2, 2003/10/19 14:56:15 | version 1.10, 2003/12/08 00:55:33 | 
| Line 1 | Line 1 | 
 | #include        "compiler.h" | #include        "compiler.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" | 
| Line 8 | Line 8 | 
 | #include        "beep.h" | #include        "beep.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 22  typedef struct { | 
 | SINT32  *buffer; | SINT32  *buffer; | 
 | SINT32  *ptr; | SINT32  *ptr; | 
 | UINT    samples; | UINT    samples; | 
 |  | UINT    reserve; | 
 | UINT    remain; | UINT    remain; | 
 | CBTBL   *cbreg; | CBTBL   *cbreg; | 
 | CBTBL   cb[STREAM_CBMAX]; | CBTBL   cb[STREAM_CBMAX]; | 
| Line 38  static SNDSTREAM sndstream; | Line 33  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 67  static void streamprepare(UINT samples) | Line 64  static void streamprepare(UINT samples) | 
 | 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 82  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 112  scre_err1: | 
 | void sound_destroy(void) { | void sound_destroy(void) { | 
 |  |  | 
 | if (sndstream.buffer) { | if (sndstream.buffer) { | 
 | SNDCSEC_TERM; |  | 
 |  |  | 
 | 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 126  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 = pc.realclock / 25; | 
 |  | hz = soundcfg.rate / 25; | 
 |  |  | 
 |  | // で、クロック数に合せて調整。(64bit演算しろよな的) | 
 |  | hzmax = (1 << (32 - 8)) / (clock >> 8); | 
 |  | while(hzmax < hz) { | 
 |  | clock = (clock + 1) >> 1; | 
 |  | hz = (hz + 1) >> 1; | 
 |  | } | 
 |  | 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 174  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) { | streamprepare(length); | 
| writebytes = 0; | 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); | streamprepare(sndstream.remain - sndstream.reserve); | 
| dsound_lastclock = I286_CLOCK; | 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--; | 
 | } | } | 
 | } | } | 
 |  |  |