DOSBox-X
|
00001 #include "np2glue.h" 00002 //#include "compiler.h" 00003 #include "wavefile.h" 00004 #include "dosio.h" 00005 //#include "soundmng.h" 00006 //#include "cpucore.h" 00007 //#include "pccore.h" 00008 //#include "iocore.h" 00009 #include "sound.h" 00010 #include "sndcsec.h" 00011 //#include "beep.h" 00012 #include "getsnd.h" 00013 00014 #if 0 00015 00016 SOUNDCFG soundcfg; 00017 00018 00019 #define STREAM_CBMAX 16 00020 00021 typedef struct { 00022 void *hdl; 00023 SOUNDCB cbfn; 00024 } CBTBL; 00025 00026 typedef struct { 00027 SINT32 *buffer; 00028 SINT32 *ptr; 00029 UINT samples; 00030 UINT reserve; 00031 UINT remain; 00032 #if defined(SUPPORT_WAVEREC) 00033 WAVEWR rec; 00034 #endif 00035 CBTBL *cbreg; 00036 CBTBL cb[STREAM_CBMAX]; 00037 } SNDSTREAM; 00038 00039 static SNDSTREAM sndstream; 00040 00041 static void streamreset(void) { 00042 00043 SNDCSEC_ENTER; 00044 sndstream.ptr = sndstream.buffer; 00045 sndstream.remain = sndstream.samples + sndstream.reserve; 00046 sndstream.cbreg = sndstream.cb; 00047 SNDCSEC_LEAVE; 00048 } 00049 00050 static void streamprepare(UINT samples) { 00051 00052 CBTBL *cb; 00053 UINT count; 00054 00055 count = min(sndstream.remain, samples); 00056 if (count) { 00057 ZeroMemory(sndstream.ptr, count * 2 * sizeof(SINT32)); 00058 cb = sndstream.cb; 00059 while(cb < sndstream.cbreg) { 00060 cb->cbfn(cb->hdl, sndstream.ptr, count); 00061 cb++; 00062 } 00063 sndstream.ptr += count * 2; 00064 sndstream.remain -= count; 00065 } 00066 } 00067 00068 // ---- wave rec 00069 00070 BOOL sound_recstart(const OEMCHAR *filename) { 00071 00072 WAVEWR rec; 00073 00074 sound_recstop(); 00075 if (sndstream.buffer == NULL) { 00076 return(FAILURE); 00077 } 00078 rec = wavewr_open(filename, soundcfg.rate, 16, 2); 00079 sndstream.rec = rec; 00080 if (rec) { 00081 return(SUCCESS); 00082 } 00083 return(FAILURE); 00084 } 00085 00086 void sound_recstop(void) { 00087 00088 WAVEWR rec; 00089 00090 rec = sndstream.rec; 00091 sndstream.rec = NULL; 00092 wavewr_close(rec); 00093 } 00094 00095 static void streamfilewrite(UINT samples) { 00096 00097 CBTBL *cb; 00098 UINT count; 00099 SINT32 buf32[2*512]; 00100 UINT8 buf[2*2*512]; 00101 UINT r; 00102 UINT i; 00103 SINT32 samp; 00104 00105 while(samples) { 00106 count = min(samples, 512); 00107 ZeroMemory(buf32, count * 2 * sizeof(SINT32)); 00108 cb = sndstream.cb; 00109 while(cb < sndstream.cbreg) { 00110 cb->cbfn(cb->hdl, buf32, count); 00111 cb++; 00112 } 00113 r = min(sndstream.remain, count); 00114 if (r) { 00115 CopyMemory(sndstream.ptr, buf32, r * 2 * sizeof(SINT32)); 00116 sndstream.ptr += r * 2; 00117 sndstream.remain -= r; 00118 } 00119 for (i=0; i<count*2; i++) { 00120 samp = buf32[i]; 00121 if (samp > 32767) { 00122 samp = 32767; 00123 } 00124 else if (samp < -32768) { 00125 samp = -32768; 00126 } 00127 // little endianなので satuation_s16は使えない 00128 buf[i*2+0] = (UINT8)samp; 00129 buf[i*2+1] = (UINT8)(samp >> 8); 00130 } 00131 wavewr_write(sndstream.rec, buf, count * 4); 00132 samples -= count; 00133 } 00134 } 00135 00136 static void filltailsample(UINT count) { 00137 00138 SINT32 *ptr; 00139 UINT orgsize; 00140 SINT32 sampl; 00141 SINT32 sampr; 00142 00143 count = min(sndstream.remain, count); 00144 if (count) { 00145 ptr = sndstream.ptr; 00146 orgsize = (ptr - sndstream.buffer) / 2; 00147 if (orgsize == 0) { 00148 sampl = 0; 00149 sampr = 0; 00150 } 00151 else { 00152 sampl = *(ptr - 2); 00153 sampr = *(ptr - 1); 00154 } 00155 sndstream.ptr += count * 2; 00156 sndstream.remain -= count; 00157 do { 00158 ptr[0] = sampl; 00159 ptr[1] = sampr; 00160 ptr += 2; 00161 } while(--count); 00162 } 00163 } 00164 00165 BOOL sound_create(UINT rate, UINT ms) { 00166 00167 UINT samples; 00168 UINT reserve; 00169 00170 ZeroMemory(&sndstream, sizeof(sndstream)); 00171 switch(rate) { 00172 case 11025: 00173 case 22050: 00174 case 44100: 00175 break; 00176 00177 default: 00178 return(FAILURE); 00179 } 00180 samples = soundmng_create(rate, ms); 00181 if (samples == 0) { 00182 goto scre_err1; 00183 } 00184 soundmng_reset(); 00185 00186 soundcfg.rate = rate; 00187 sound_changeclock(); 00188 00189 #if defined(SOUNDRESERVE) 00190 reserve = rate * SOUNDRESERVE / 1000; 00191 #else 00192 reserve = 0; 00193 #endif 00194 sndstream.buffer = (SINT32 *)_MALLOC((samples + reserve) * 2 00195 * sizeof(SINT32), "stream"); 00196 if (sndstream.buffer == NULL) { 00197 goto scre_err2; 00198 } 00199 sndstream.samples = samples; 00200 sndstream.reserve = reserve; 00201 00202 SNDCSEC_INIT; 00203 streamreset(); 00204 return(SUCCESS); 00205 00206 scre_err2: 00207 soundmng_destroy(); 00208 00209 scre_err1: 00210 return(FAILURE); 00211 } 00212 #endif 00213 00214 #if 0 00215 void sound_destroy(void) { 00216 00217 if (sndstream.buffer) { 00218 #if defined(SUPPORT_WAVEREC) 00219 sound_recstop(); 00220 #endif 00221 soundmng_stop(); 00222 streamreset(); 00223 soundmng_destroy(); 00224 SNDCSEC_TERM; 00225 _MFREE(sndstream.buffer); 00226 sndstream.buffer = NULL; 00227 } 00228 } 00229 #endif 00230 00231 #if 0 00232 void sound_reset(void) { 00233 00234 if (sndstream.buffer) { 00235 soundmng_reset(); 00236 streamreset(); 00237 // soundcfg.lastclock = CPU_CLOCK; 00238 beep_eventreset(); 00239 } 00240 } 00241 #endif 00242 00243 #if 0 00244 void sound_changeclock(void) { 00245 00246 UINT32 clk; 00247 UINT hz; 00248 UINT hzmax; 00249 00250 if (sndstream.buffer == NULL) { 00251 return; 00252 } 00253 00254 // とりあえず 25で割り切れる。 00255 clk = pccore.realclock / 25; 00256 hz = soundcfg.rate / 25; 00257 00258 // で、クロック数に合せて調整。(64bit演算しろよな的) 00259 hzmax = (1 << (32 - 8)) / (clk >> 8); 00260 while(hzmax < hz) { 00261 clk = (clk + 1) >> 1; 00262 hz = (hz + 1) >> 1; 00263 } 00264 TRACEOUT(("hzbase/clockbase = %d/%d", hz, clk)); 00265 soundcfg.hzbase = hz; 00266 soundcfg.clockbase = clk; 00267 soundcfg.minclock = 2 * clk / hz; 00268 soundcfg.lastclock = CPU_CLOCK; 00269 } 00270 #endif 00271 00272 #if 0 00273 void sound_streamregist(void *hdl, SOUNDCB cbfn) { 00274 00275 if (sndstream.buffer) { 00276 if ((cbfn) && 00277 (sndstream.cbreg < (sndstream.cb + STREAM_CBMAX))) { 00278 sndstream.cbreg->hdl = hdl; 00279 sndstream.cbreg->cbfn = cbfn; 00280 sndstream.cbreg++; 00281 } 00282 } 00283 } 00284 #endif 00285 00286 00287 // ---- 00288 00289 #if 0 00290 void sound_sync(void) { 00291 00292 UINT32 length; 00293 00294 if (sndstream.buffer == NULL) { 00295 return; 00296 } 00297 00298 length = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK - soundcfg.lastclock; 00299 if (length < soundcfg.minclock) { 00300 return; 00301 } 00302 length = (length * soundcfg.hzbase) / soundcfg.clockbase; 00303 if (length == 0) { 00304 return; 00305 } 00306 SNDCSEC_ENTER; 00307 #if defined(SUPPORT_WAVEREC) 00308 if (sndstream.rec) { 00309 streamfilewrite(length); 00310 } 00311 else 00312 #endif 00313 streamprepare(length); 00314 soundcfg.lastclock += length * soundcfg.clockbase / soundcfg.hzbase; 00315 beep_eventreset(); 00316 SNDCSEC_LEAVE; 00317 00318 soundcfg.writecount += length; 00319 if (soundcfg.writecount >= 100) { 00320 soundcfg.writecount = 0; 00321 soundmng_sync(); 00322 } 00323 } 00324 #endif 00325 00326 #if 0 00327 static volatile int locks = 0; 00328 #endif 00329 00330 #if 0 00331 const SINT32 *sound_pcmlock(void) { 00332 00333 const SINT32 *ret; 00334 00335 if (locks) { 00336 TRACEOUT(("sound pcm lock: already locked")); 00337 return(NULL); 00338 } 00339 locks++; 00340 ret = sndstream.buffer; 00341 if (ret) { 00342 SNDCSEC_ENTER; 00343 if (sndstream.remain > sndstream.reserve) 00344 #if defined(SUPPORT_WAVEREC) 00345 if (sndstream.rec) { 00346 filltailsample(sndstream.remain - sndstream.reserve); 00347 } 00348 else 00349 #endif 00350 { 00351 streamprepare(sndstream.remain - sndstream.reserve); 00352 soundcfg.lastclock = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK; 00353 beep_eventreset(); 00354 } 00355 } 00356 else { 00357 locks--; 00358 } 00359 return(ret); 00360 } 00361 #endif 00362 00363 #if 0 00364 void sound_pcmunlock(const SINT32 *hdl) { 00365 00366 int leng; 00367 00368 if (hdl) { 00369 leng = sndstream.reserve - sndstream.remain; 00370 if (leng > 0) { 00371 CopyMemory(sndstream.buffer, 00372 sndstream.buffer + (sndstream.samples * 2), 00373 leng * 2 * sizeof(SINT32)); 00374 } 00375 sndstream.ptr = sndstream.buffer + (leng * 2); 00376 sndstream.remain = sndstream.samples + sndstream.reserve - leng; 00377 // sndstream.remain += sndstream.samples; 00378 SNDCSEC_LEAVE; 00379 locks--; 00380 } 00381 } 00382 #endif 00383 00384 // ---- pcmmix 00385 00386 BRESULT pcmmix_regist(PMIXDAT *dat, void *datptr, UINT datsize, UINT rate) { 00387 00388 GETSND gs; 00389 UINT8 tmp[256]; 00390 UINT size; 00391 UINT r; 00392 SINT16 *buf; 00393 00394 gs = getsnd_create(datptr, datsize); 00395 if (gs == NULL) { 00396 goto pmr_err1; 00397 } 00398 if (getsnd_setmixproc(gs, rate, 1) != SUCCESS) { 00399 goto pmr_err2; 00400 } 00401 size = 0; 00402 do { 00403 r = getsnd_getpcmbyleng(gs, tmp, sizeof(tmp)); 00404 size += r; 00405 } while(r); 00406 getsnd_destroy(gs); 00407 if (size == 0) { 00408 goto pmr_err1; 00409 } 00410 00411 buf = (SINT16 *)_MALLOC(size, "PCM DATA"); 00412 if (buf == NULL) { 00413 goto pmr_err1; 00414 } 00415 gs = getsnd_create(datptr, datsize); 00416 if (gs == NULL) { 00417 goto pmr_err1; 00418 } 00419 if (getsnd_setmixproc(gs, rate, 1) != SUCCESS) { 00420 goto pmr_err2; 00421 } 00422 r = getsnd_getpcmbyleng(gs, buf, size); 00423 getsnd_destroy(gs); 00424 dat->sample = buf; 00425 dat->samples = r / 2; 00426 return(SUCCESS); 00427 00428 pmr_err2: 00429 getsnd_destroy(gs); 00430 00431 pmr_err1: 00432 return(FAILURE); 00433 } 00434 00435 BRESULT pcmmix_regfile(PMIXDAT *dat, const OEMCHAR *fname, UINT rate) { 00436 00437 FILEH fh; 00438 UINT size; 00439 UINT8 *ptr; 00440 BRESULT r; 00441 00442 r = FAILURE; 00443 fh = file_open_rb(fname); 00444 if (fh == FILEH_INVALID) { 00445 goto pmrf_err1; 00446 } 00447 size = file_getsize(fh); 00448 if (size == 0) { 00449 goto pmrf_err2; 00450 } 00451 ptr = (UINT8 *)_MALLOC(size, fname); 00452 if (ptr == NULL) { 00453 goto pmrf_err2; 00454 } 00455 file_read(fh, ptr, size); 00456 file_close(fh); 00457 r = pcmmix_regist(dat, ptr, size, rate); 00458 _MFREE(ptr); 00459 return(r); 00460 00461 pmrf_err2: 00462 file_close(fh); 00463 00464 pmrf_err1: 00465 return(FAILURE); 00466 } 00467 00468 void SOUNDCALL pcmmix_getpcm(PCMMIX hdl, SINT32 *pcm, UINT count) { 00469 00470 UINT32 bitmap; 00471 PMIXTRK *t; 00472 const SINT16 *s; 00473 UINT srem; 00474 SINT32 *d; 00475 UINT drem; 00476 UINT r; 00477 UINT j; 00478 UINT flag; 00479 SINT32 vol; 00480 SINT32 samp; 00481 00482 if ((hdl->hdr.playing == 0) || (count == 0)) { 00483 return; 00484 } 00485 t = hdl->trk; 00486 bitmap = 1; 00487 do { 00488 if (hdl->hdr.playing & bitmap) { 00489 s = t->pcm; 00490 srem = t->remain; 00491 d = pcm; 00492 drem = count; 00493 flag = t->flag; 00494 vol = t->volume; 00495 do { 00496 r = min(srem, drem); 00497 switch(flag & (PMIXFLAG_L | PMIXFLAG_R)) { 00498 case PMIXFLAG_L: 00499 for (j=0; j<r; j++) { 00500 d[j*2+0] += (s[j] * vol) >> 12; 00501 } 00502 break; 00503 00504 case PMIXFLAG_R: 00505 for (j=0; j<r; j++) { 00506 d[j*2+1] += (s[j] * vol) >> 12; 00507 } 00508 break; 00509 00510 case PMIXFLAG_L | PMIXFLAG_R: 00511 for (j=0; j<r; j++) { 00512 samp = (s[j] * vol) >> 12; 00513 d[j*2+0] += samp; 00514 d[j*2+1] += samp; 00515 } 00516 break; 00517 } 00518 s += r; 00519 d += r*2; 00520 srem -= r; 00521 if (srem == 0) { 00522 if (flag & PMIXFLAG_LOOP) { 00523 s = t->data.sample; 00524 srem = t->data.samples; 00525 } 00526 else { 00527 hdl->hdr.playing &= ~bitmap; 00528 break; 00529 } 00530 } 00531 drem -= r; 00532 } while(drem); 00533 t->pcm = s; 00534 t->remain = srem; 00535 } 00536 t++; 00537 bitmap <<= 1; 00538 } while(bitmap < hdl->hdr.enable); 00539 } 00540