mirror of
https://github.com/libretro/NP2kai.git
synced 2024-10-07 06:43:29 +00:00
remove CDDA mod
This commit is contained in:
parent
2fa46a2404
commit
d498e50734
20
cbus/ideio.c
Executable file → Normal file
20
cbus/ideio.c
Executable file → Normal file
@ -1212,10 +1212,6 @@ static BRESULT SOUNDCALL playdevaudio(IDEDRV drv, SINT32 *pcm, UINT count) {
|
||||
const UINT8 *ptr;
|
||||
SINT sampl;
|
||||
SINT sampr;
|
||||
UINT skipcnt;
|
||||
|
||||
// CDDA
|
||||
count = count * soundcfg.cddaskip;
|
||||
|
||||
sxsi = sxsi_getptr(drv->sxsidrv);
|
||||
if ((sxsi == NULL) || (sxsi->devtype != SXSIDEV_CDROM) ||
|
||||
@ -1229,27 +1225,13 @@ const UINT8 *ptr;
|
||||
count -= r;
|
||||
ptr = drv->dabuf + 2352 - (drv->dabufrem * 4);
|
||||
drv->dabufrem -= r;
|
||||
skipcnt = 0;
|
||||
do {
|
||||
sampl = ((SINT8)ptr[1] << 8) + ptr[0];
|
||||
sampr = ((SINT8)ptr[3] << 8) + ptr[2];
|
||||
#if 0
|
||||
pcm[0] += (SINT)((int)(sampl)*np2cfg.davolume/255);
|
||||
pcm[1] += (SINT)((int)(sampr)*np2cfg.davolume/255);
|
||||
#else
|
||||
skipcnt++;
|
||||
if ((skipcnt % soundcfg.cddaskip) == 0) {
|
||||
pcm[0] += sampl;
|
||||
pcm[1] += sampr;
|
||||
// (kaiE)
|
||||
pcm[0] = (pcm[0] * np2cfg.vol_cdda) >> 6;
|
||||
pcm[1] = (pcm[1] * np2cfg.vol_cdda) >> 6;
|
||||
//
|
||||
pcm += 2;
|
||||
}
|
||||
#endif
|
||||
ptr += 4;
|
||||
// pcm += 2;
|
||||
pcm += 2;
|
||||
} while(--r);
|
||||
}
|
||||
if (count == 0) {
|
||||
|
545
cbus/pcm86io.c
545
cbus/pcm86io.c
@ -1,278 +1,267 @@
|
||||
#include "compiler.h"
|
||||
#include "cpucore.h"
|
||||
#include "pccore.h"
|
||||
#include "iocore.h"
|
||||
#include "pcm86io.h"
|
||||
#include "sound.h"
|
||||
#include "fmboard.h"
|
||||
|
||||
|
||||
extern PCM86CFG pcm86cfg;
|
||||
|
||||
static const UINT8 pcm86bits[] = {1, 1, 1, 2, 0, 0, 0, 1};
|
||||
static const SINT32 pcm86rescue[] = {PCM86_RESCUE * 32, PCM86_RESCUE * 24,
|
||||
PCM86_RESCUE * 16, PCM86_RESCUE * 12,
|
||||
PCM86_RESCUE * 8, PCM86_RESCUE * 6,
|
||||
PCM86_RESCUE * 4, PCM86_RESCUE * 3};
|
||||
|
||||
static const UINT8 s_irqtable[8] = {0xff, 0xff, 0xff, 0xff, 0x03, 0x0a, 0x0d, 0x0c};
|
||||
|
||||
|
||||
static void IOOUTCALL pcm86_oa460(UINT port, REG8 val)
|
||||
{
|
||||
// TRACEOUT(("86pcm out %.4x %.2x", port, val));
|
||||
g_pcm86.soundflags = (g_pcm86.soundflags & 0xfe) | (val & 1);
|
||||
fmboard_extenable((REG8)(val & 1));
|
||||
(void)port;
|
||||
}
|
||||
|
||||
static void IOOUTCALL pcm86_oa466(UINT port, REG8 val) {
|
||||
|
||||
// TRACEOUT(("86pcm out %.4x %.2x", port, val));
|
||||
if ((val & 0xe0) == 0xa0) {
|
||||
sound_sync();
|
||||
g_pcm86.vol5 = (~val) & 15;
|
||||
g_pcm86.volume = pcm86cfg.vol * g_pcm86.vol5;
|
||||
}
|
||||
(void)port;
|
||||
}
|
||||
|
||||
static void IOOUTCALL pcm86_oa468(UINT port, REG8 val) {
|
||||
|
||||
REG8 xchgbit;
|
||||
|
||||
// TRACEOUT(("86pcm out %.4x %.2x", port, val));
|
||||
sound_sync();
|
||||
xchgbit = g_pcm86.fifo ^ val;
|
||||
// バッファリセット判定
|
||||
if ((xchgbit & 8) && (val & 8)) {
|
||||
g_pcm86.readpos = 0; // バッファリセット
|
||||
g_pcm86.wrtpos = 0;
|
||||
g_pcm86.realbuf = 0;
|
||||
g_pcm86.virbuf = 0;
|
||||
g_pcm86.lastclock = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK;
|
||||
g_pcm86.lastclock <<= 6;
|
||||
}
|
||||
if ((xchgbit & 0x10) && (!(val & 0x10))) {
|
||||
g_pcm86.irqflag = 0;
|
||||
// g_pcm86.write = 0;
|
||||
// g_pcm86.reqirq = 0;
|
||||
}
|
||||
// サンプリングレート変更
|
||||
if (xchgbit & 7) {
|
||||
g_pcm86.rescue = pcm86rescue[val & 7] << g_pcm86.stepbit;
|
||||
pcm86_setpcmrate(val);
|
||||
}
|
||||
#if 1 // これ重大なバグ....
|
||||
g_pcm86.fifo = val;
|
||||
#else
|
||||
g_pcm86.fifo = val & (~0x10);
|
||||
#endif
|
||||
if ((xchgbit & 0x80) && (val & 0x80)) {
|
||||
g_pcm86.lastclock = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK;
|
||||
g_pcm86.lastclock <<= 6;
|
||||
}
|
||||
pcm86_setnextintr();
|
||||
(void)port;
|
||||
}
|
||||
|
||||
static void IOOUTCALL pcm86_oa46a(UINT port, REG8 val) {
|
||||
|
||||
// TRACEOUT(("86pcm out %.4x %.2x", port, val));
|
||||
sound_sync();
|
||||
if (g_pcm86.fifo & 0x20) {
|
||||
#if 1
|
||||
if (val != 0xff) {
|
||||
g_pcm86.fifosize = (UINT16)((val + 1) << 7);
|
||||
}
|
||||
else {
|
||||
g_pcm86.fifosize = 0x7ffc;
|
||||
}
|
||||
#else
|
||||
if (!val) {
|
||||
val++;
|
||||
}
|
||||
g_pcm86.fifosize = (WORD)(val) << 7;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
g_pcm86.dactrl = val;
|
||||
g_pcm86.stepbit = pcm86bits[(val >> 4) & 7];
|
||||
g_pcm86.stepmask = (1 << g_pcm86.stepbit) - 1;
|
||||
g_pcm86.rescue = pcm86rescue[g_pcm86.fifo & 7] << g_pcm86.stepbit;
|
||||
}
|
||||
pcm86_setnextintr();
|
||||
(void)port;
|
||||
}
|
||||
|
||||
static void IOOUTCALL pcm86_oa46c(UINT port, REG8 val) {
|
||||
|
||||
// TRACEOUT(("86pcm out %.4x %.2x", port, val));
|
||||
#if 1
|
||||
if (g_pcm86.virbuf < PCM86_LOGICALBUF) {
|
||||
g_pcm86.virbuf++;
|
||||
}
|
||||
g_pcm86.buffer[g_pcm86.wrtpos] = val;
|
||||
g_pcm86.wrtpos = (g_pcm86.wrtpos + 1) & PCM86_BUFMSK;
|
||||
g_pcm86.realbuf++;
|
||||
// バッファオーバーフローの監視
|
||||
if (g_pcm86.realbuf >= PCM86_REALBUFSIZE) {
|
||||
#if 1
|
||||
g_pcm86.realbuf -= 4;
|
||||
g_pcm86.readpos = (g_pcm86.readpos + 4) & PCM86_BUFMSK;
|
||||
#else
|
||||
g_pcm86.realbuf &= 3; // align4決めウチ
|
||||
g_pcm86.realbuf += PCM86_REALBUFSIZE - 4;
|
||||
#endif
|
||||
}
|
||||
g_pcm86.write = 1; // (kaiD)
|
||||
g_pcm86.reqirq = 1;
|
||||
#else
|
||||
if (g_pcm86.virbuf < PCM86_LOGICALBUF) {
|
||||
g_pcm86.virbuf++;
|
||||
g_pcm86.buffer[g_pcm86.wrtpos] = val;
|
||||
g_pcm86.wrtpos = (g_pcm86.wrtpos + 1) & PCM86_BUFMSK;
|
||||
g_pcm86.realbuf++;
|
||||
// バッファオーバーフローの監視
|
||||
if (g_pcm86.realbuf >= PCM86_REALBUFSIZE) {
|
||||
g_pcm86.realbuf &= 3; // align4決めウチ
|
||||
g_pcm86.realbuf += PCM86_REALBUFSIZE - 4;
|
||||
}
|
||||
g_pcm86.write = 1;
|
||||
g_pcm86.reqirq = 1;
|
||||
}
|
||||
#endif
|
||||
(void)port;
|
||||
}
|
||||
|
||||
static REG8 IOINPCALL pcm86_ia460(UINT port)
|
||||
{
|
||||
(void)port;
|
||||
return g_pcm86.soundflags;
|
||||
}
|
||||
|
||||
static REG8 IOINPCALL pcm86_ia466(UINT port) {
|
||||
|
||||
UINT32 past;
|
||||
UINT32 cnt;
|
||||
UINT32 stepclock;
|
||||
REG8 ret;
|
||||
|
||||
past = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK;
|
||||
past <<= 6;
|
||||
past -= g_pcm86.lastclock;
|
||||
stepclock = g_pcm86.stepclock;
|
||||
if (past >= stepclock) {
|
||||
cnt = past / stepclock;
|
||||
g_pcm86.lastclock += (cnt * stepclock);
|
||||
past -= cnt * stepclock;
|
||||
if (g_pcm86.fifo & 0x80) {
|
||||
sound_sync();
|
||||
RECALC_NOWCLKWAIT(cnt);
|
||||
}
|
||||
}
|
||||
ret = ((past << 1) >= stepclock)?1:0;
|
||||
if (g_pcm86.virbuf >= PCM86_LOGICALBUF) { // バッファフル
|
||||
ret |= 0x80;
|
||||
}
|
||||
else if (!g_pcm86.virbuf) { // バッファ0
|
||||
ret |= 0x40; // ちと変…
|
||||
}
|
||||
(void)port;
|
||||
// TRACEOUT(("86pcm in %.4x %.2x", port, ret));
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static REG8 IOINPCALL pcm86_ia468(UINT port) {
|
||||
|
||||
REG8 ret;
|
||||
|
||||
ret = g_pcm86.fifo & (~0x10);
|
||||
#if 0 // #if 1 // (kai8)
|
||||
if (g_pcm86gen_intrq()) {
|
||||
ret |= 0x10;
|
||||
}
|
||||
#elif 1 //
|
||||
if (g_pcm86.fifo & 0x20) {
|
||||
sound_sync();
|
||||
#if 0 // (kaiE)
|
||||
// if (g_pcm86.virbuf <= g_pcm86.fifosize) {
|
||||
if (g_pcm86.virbuf <= g_pcm86.fifosize && g_pcm86.virbuf > 0) { // (kaiD)
|
||||
// if (g_pcm86.write) { // (kai8)
|
||||
// g_pcm86.write = 0; // (kai8)
|
||||
// } // (kai8)
|
||||
// else { // (kai8)
|
||||
ret |= 0x10;
|
||||
// } // (kai8)
|
||||
}
|
||||
#else
|
||||
//
|
||||
if (g_pcm86.write) {
|
||||
if (g_pcm86.virbuf)
|
||||
g_pcm86.write = 0;
|
||||
} else if (g_pcm86.virbuf <= g_pcm86.fifosize) {
|
||||
ret |= 0x10;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
if ((g_pcm86.write) && (g_pcm86.fifo & 0x20)) {
|
||||
g_pcm86.write = 0;
|
||||
sound_sync();
|
||||
if (g_pcm86.virbuf <= g_pcm86.fifosize) {
|
||||
g_pcm86.write = 0;
|
||||
ret |= 0x10;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
(void)port;
|
||||
// TRACEOUT(("86pcm in %.4x %.2x", port, ret));
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static REG8 IOINPCALL pcm86_ia46a(UINT port) {
|
||||
|
||||
(void)port;
|
||||
// TRACEOUT(("86pcm in %.4x %.2x", port, g_pcm86.dactrl));
|
||||
return(g_pcm86.dactrl);
|
||||
}
|
||||
|
||||
static REG8 IOINPCALL pcm86_inpdummy(UINT port) {
|
||||
|
||||
(void)port;
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
// ----
|
||||
|
||||
/**
|
||||
* Reset
|
||||
* @param[in] cDipSw Dip switch
|
||||
*/
|
||||
void pcm86io_setopt(REG8 cDipSw)
|
||||
{
|
||||
g_pcm86.soundflags = ((~cDipSw) >> 1) & 0x70;
|
||||
g_pcm86.irq = s_irqtable[(cDipSw >> 2) & 7];
|
||||
}
|
||||
|
||||
void pcm86io_bind(void) {
|
||||
|
||||
sound_streamregist(&g_pcm86, (SOUNDCB)pcm86gen_getpcm);
|
||||
|
||||
iocore_attachout(0xa460, pcm86_oa460);
|
||||
iocore_attachout(0xa466, pcm86_oa466);
|
||||
iocore_attachout(0xa468, pcm86_oa468);
|
||||
iocore_attachout(0xa46a, pcm86_oa46a);
|
||||
iocore_attachout(0xa46c, pcm86_oa46c);
|
||||
|
||||
iocore_attachinp(0xa460, pcm86_ia460);
|
||||
iocore_attachinp(0xa462, pcm86_inpdummy);
|
||||
iocore_attachinp(0xa464, pcm86_inpdummy);
|
||||
iocore_attachinp(0xa466, pcm86_ia466);
|
||||
iocore_attachinp(0xa468, pcm86_ia468);
|
||||
iocore_attachinp(0xa46a, pcm86_ia46a);
|
||||
iocore_attachinp(0xa46c, pcm86_inpdummy);
|
||||
iocore_attachinp(0xa46e, pcm86_inpdummy);
|
||||
}
|
||||
|
||||
#include "compiler.h"
|
||||
#include "cpucore.h"
|
||||
#include "pccore.h"
|
||||
#include "iocore.h"
|
||||
#include "pcm86io.h"
|
||||
#include "sound.h"
|
||||
#include "fmboard.h"
|
||||
|
||||
|
||||
extern PCM86CFG pcm86cfg;
|
||||
|
||||
static const UINT8 pcm86bits[] = {1, 1, 1, 2, 0, 0, 0, 1};
|
||||
static const SINT32 pcm86rescue[] = {PCM86_RESCUE * 32, PCM86_RESCUE * 24,
|
||||
PCM86_RESCUE * 16, PCM86_RESCUE * 12,
|
||||
PCM86_RESCUE * 8, PCM86_RESCUE * 6,
|
||||
PCM86_RESCUE * 4, PCM86_RESCUE * 3};
|
||||
|
||||
static const UINT8 s_irqtable[8] = {0xff, 0xff, 0xff, 0xff, 0x03, 0x0a, 0x0d, 0x0c};
|
||||
|
||||
|
||||
static void IOOUTCALL pcm86_oa460(UINT port, REG8 val)
|
||||
{
|
||||
// TRACEOUT(("86pcm out %.4x %.2x", port, val));
|
||||
g_pcm86.soundflags = (g_pcm86.soundflags & 0xfe) | (val & 1);
|
||||
fmboard_extenable((REG8)(val & 1));
|
||||
(void)port;
|
||||
}
|
||||
|
||||
static void IOOUTCALL pcm86_oa466(UINT port, REG8 val) {
|
||||
|
||||
// TRACEOUT(("86pcm out %.4x %.2x", port, val));
|
||||
if ((val & 0xe0) == 0xa0) {
|
||||
sound_sync();
|
||||
g_pcm86.vol5 = (~val) & 15;
|
||||
g_pcm86.volume = pcm86cfg.vol * g_pcm86.vol5;
|
||||
}
|
||||
(void)port;
|
||||
}
|
||||
|
||||
static void IOOUTCALL pcm86_oa468(UINT port, REG8 val) {
|
||||
|
||||
REG8 xchgbit;
|
||||
|
||||
// TRACEOUT(("86pcm out %.4x %.2x", port, val));
|
||||
sound_sync();
|
||||
xchgbit = g_pcm86.fifo ^ val;
|
||||
// バッファリセット判定
|
||||
if ((xchgbit & 8) && (val & 8)) {
|
||||
g_pcm86.readpos = 0; // バッファリセット
|
||||
g_pcm86.wrtpos = 0;
|
||||
g_pcm86.realbuf = 0;
|
||||
g_pcm86.virbuf = 0;
|
||||
g_pcm86.lastclock = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK;
|
||||
g_pcm86.lastclock <<= 6;
|
||||
}
|
||||
if ((xchgbit & 0x10) && (!(val & 0x10))) {
|
||||
g_pcm86.irqflag = 0;
|
||||
// g_pcm86.write = 0;
|
||||
// g_pcm86.reqirq = 0;
|
||||
}
|
||||
// サンプリングレート変更
|
||||
if (xchgbit & 7) {
|
||||
g_pcm86.rescue = pcm86rescue[val & 7] << g_pcm86.stepbit;
|
||||
pcm86_setpcmrate(val);
|
||||
}
|
||||
#if 1 // これ重大なバグ....
|
||||
g_pcm86.fifo = val;
|
||||
#else
|
||||
g_pcm86.fifo = val & (~0x10);
|
||||
#endif
|
||||
if ((xchgbit & 0x80) && (val & 0x80)) {
|
||||
g_pcm86.lastclock = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK;
|
||||
g_pcm86.lastclock <<= 6;
|
||||
}
|
||||
pcm86_setnextintr();
|
||||
(void)port;
|
||||
}
|
||||
|
||||
static void IOOUTCALL pcm86_oa46a(UINT port, REG8 val) {
|
||||
|
||||
// TRACEOUT(("86pcm out %.4x %.2x", port, val));
|
||||
sound_sync();
|
||||
if (g_pcm86.fifo & 0x20) {
|
||||
#if 1
|
||||
if (val != 0xff) {
|
||||
g_pcm86.fifosize = (UINT16)((val + 1) << 7);
|
||||
}
|
||||
else {
|
||||
g_pcm86.fifosize = 0x7ffc;
|
||||
}
|
||||
#else
|
||||
if (!val) {
|
||||
val++;
|
||||
}
|
||||
g_pcm86.fifosize = (WORD)(val) << 7;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
g_pcm86.dactrl = val;
|
||||
g_pcm86.stepbit = pcm86bits[(val >> 4) & 7];
|
||||
g_pcm86.stepmask = (1 << g_pcm86.stepbit) - 1;
|
||||
g_pcm86.rescue = pcm86rescue[g_pcm86.fifo & 7] << g_pcm86.stepbit;
|
||||
}
|
||||
pcm86_setnextintr();
|
||||
(void)port;
|
||||
}
|
||||
|
||||
static void IOOUTCALL pcm86_oa46c(UINT port, REG8 val) {
|
||||
|
||||
// TRACEOUT(("86pcm out %.4x %.2x", port, val));
|
||||
#if 1
|
||||
if (g_pcm86.virbuf < PCM86_LOGICALBUF) {
|
||||
g_pcm86.virbuf++;
|
||||
}
|
||||
g_pcm86.buffer[g_pcm86.wrtpos] = val;
|
||||
g_pcm86.wrtpos = (g_pcm86.wrtpos + 1) & PCM86_BUFMSK;
|
||||
g_pcm86.realbuf++;
|
||||
// バッファオーバーフローの監視
|
||||
if (g_pcm86.realbuf >= PCM86_REALBUFSIZE) {
|
||||
#if 1
|
||||
g_pcm86.realbuf -= 4;
|
||||
g_pcm86.readpos = (g_pcm86.readpos + 4) & PCM86_BUFMSK;
|
||||
#else
|
||||
g_pcm86.realbuf &= 3; // align4決めウチ
|
||||
g_pcm86.realbuf += PCM86_REALBUFSIZE - 4;
|
||||
#endif
|
||||
}
|
||||
// g_pcm86.write = 1;
|
||||
g_pcm86.reqirq = 1;
|
||||
#else
|
||||
if (g_pcm86.virbuf < PCM86_LOGICALBUF) {
|
||||
g_pcm86.virbuf++;
|
||||
g_pcm86.buffer[g_pcm86.wrtpos] = val;
|
||||
g_pcm86.wrtpos = (g_pcm86.wrtpos + 1) & PCM86_BUFMSK;
|
||||
g_pcm86.realbuf++;
|
||||
// バッファオーバーフローの監視
|
||||
if (g_pcm86.realbuf >= PCM86_REALBUFSIZE) {
|
||||
g_pcm86.realbuf &= 3; // align4決めウチ
|
||||
g_pcm86.realbuf += PCM86_REALBUFSIZE - 4;
|
||||
}
|
||||
// g_pcm86.write = 1;
|
||||
g_pcm86.reqirq = 1;
|
||||
}
|
||||
#endif
|
||||
(void)port;
|
||||
}
|
||||
|
||||
static REG8 IOINPCALL pcm86_ia460(UINT port)
|
||||
{
|
||||
(void)port;
|
||||
return g_pcm86.soundflags;
|
||||
}
|
||||
|
||||
static REG8 IOINPCALL pcm86_ia466(UINT port) {
|
||||
|
||||
UINT32 past;
|
||||
UINT32 cnt;
|
||||
UINT32 stepclock;
|
||||
REG8 ret;
|
||||
|
||||
past = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK;
|
||||
past <<= 6;
|
||||
past -= g_pcm86.lastclock;
|
||||
stepclock = g_pcm86.stepclock;
|
||||
if (past >= stepclock) {
|
||||
cnt = past / stepclock;
|
||||
g_pcm86.lastclock += (cnt * stepclock);
|
||||
past -= cnt * stepclock;
|
||||
if (g_pcm86.fifo & 0x80) {
|
||||
sound_sync();
|
||||
RECALC_NOWCLKWAIT(cnt);
|
||||
}
|
||||
}
|
||||
ret = ((past << 1) >= stepclock)?1:0;
|
||||
if (g_pcm86.virbuf >= PCM86_LOGICALBUF) { // バッファフル
|
||||
ret |= 0x80;
|
||||
}
|
||||
else if (!g_pcm86.virbuf) { // バッファ0
|
||||
ret |= 0x40; // ちと変…
|
||||
}
|
||||
(void)port;
|
||||
// TRACEOUT(("86pcm in %.4x %.2x", port, ret));
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static REG8 IOINPCALL pcm86_ia468(UINT port) {
|
||||
|
||||
REG8 ret;
|
||||
|
||||
ret = g_pcm86.fifo & (~0x10);
|
||||
#if 1
|
||||
if (pcm86gen_intrq()) {
|
||||
ret |= 0x10;
|
||||
}
|
||||
#elif 1 // むしろこう?
|
||||
if (g_pcm86.fifo & 0x20) {
|
||||
sound_sync();
|
||||
if (g_pcm86.virbuf <= g_pcm86.fifosize) {
|
||||
if (g_pcm86.write) {
|
||||
g_pcm86.write = 0;
|
||||
}
|
||||
else {
|
||||
ret |= 0x10;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
if ((g_pcm86.write) && (g_pcm86.fifo & 0x20)) {
|
||||
// g_pcm86.write = 0;
|
||||
sound_sync();
|
||||
if (g_pcm86.virbuf <= g_pcm86.fifosize) {
|
||||
g_pcm86.write = 0;
|
||||
ret |= 0x10;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
(void)port;
|
||||
// TRACEOUT(("86pcm in %.4x %.2x", port, ret));
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static REG8 IOINPCALL pcm86_ia46a(UINT port) {
|
||||
|
||||
(void)port;
|
||||
// TRACEOUT(("86pcm in %.4x %.2x", port, g_pcm86.dactrl));
|
||||
return(g_pcm86.dactrl);
|
||||
}
|
||||
|
||||
static REG8 IOINPCALL pcm86_inpdummy(UINT port) {
|
||||
|
||||
(void)port;
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
// ----
|
||||
|
||||
/**
|
||||
* Reset
|
||||
* @param[in] cDipSw Dip switch
|
||||
*/
|
||||
void pcm86io_setopt(REG8 cDipSw)
|
||||
{
|
||||
g_pcm86.soundflags = ((~cDipSw) >> 1) & 0x70;
|
||||
g_pcm86.irq = s_irqtable[(cDipSw >> 2) & 7];
|
||||
}
|
||||
|
||||
void pcm86io_bind(void) {
|
||||
|
||||
sound_streamregist(&g_pcm86, (SOUNDCB)pcm86gen_getpcm);
|
||||
|
||||
iocore_attachout(0xa460, pcm86_oa460);
|
||||
iocore_attachout(0xa466, pcm86_oa466);
|
||||
iocore_attachout(0xa468, pcm86_oa468);
|
||||
iocore_attachout(0xa46a, pcm86_oa46a);
|
||||
iocore_attachout(0xa46c, pcm86_oa46c);
|
||||
|
||||
iocore_attachinp(0xa460, pcm86_ia460);
|
||||
iocore_attachinp(0xa462, pcm86_inpdummy);
|
||||
iocore_attachinp(0xa464, pcm86_inpdummy);
|
||||
iocore_attachinp(0xa466, pcm86_ia466);
|
||||
iocore_attachinp(0xa468, pcm86_ia468);
|
||||
iocore_attachinp(0xa46a, pcm86_ia46a);
|
||||
iocore_attachinp(0xa46c, pcm86_inpdummy);
|
||||
iocore_attachinp(0xa46e, pcm86_inpdummy);
|
||||
}
|
||||
|
||||
|
205
sound/pcm86.h
205
sound/pcm86.h
@ -1,103 +1,102 @@
|
||||
/**
|
||||
* @file pcm86.h
|
||||
* @brief Interface of the 86-PCM
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "sound.h"
|
||||
#include "nevent.h"
|
||||
|
||||
enum {
|
||||
PCM86_LOGICALBUF = 0x8000,
|
||||
PCM86_BUFSIZE = (1 << 16),
|
||||
PCM86_BUFMSK = ((1 << 16) - 1),
|
||||
|
||||
PCM86_DIVBIT = 10,
|
||||
PCM86_DIVENV = (1 << PCM86_DIVBIT),
|
||||
|
||||
PCM86_RESCUE = 20
|
||||
};
|
||||
|
||||
#define PCM86_EXTBUF g_pcm86.rescue /* 救済延滞… */
|
||||
#define PCM86_REALBUFSIZE (PCM86_LOGICALBUF + PCM86_EXTBUF)
|
||||
|
||||
#define RECALC_NOWCLKWAIT(cnt) \
|
||||
do \
|
||||
{ \
|
||||
g_pcm86.virbuf -= (cnt << g_pcm86.stepbit); \
|
||||
if (g_pcm86.virbuf < 0) \
|
||||
{ \
|
||||
g_pcm86.virbuf &= g_pcm86.stepmask; \
|
||||
} \
|
||||
} while (0 /*CONSTCOND*/)
|
||||
|
||||
typedef struct {
|
||||
SINT32 divremain;
|
||||
SINT32 div;
|
||||
SINT32 div2;
|
||||
SINT32 smp;
|
||||
SINT32 lastsmp;
|
||||
SINT32 smp_l;
|
||||
SINT32 lastsmp_l;
|
||||
SINT32 smp_r;
|
||||
SINT32 lastsmp_r;
|
||||
|
||||
UINT32 readpos; /* DSOUND再生位置 */
|
||||
UINT32 wrtpos; /* 書込み位置 */
|
||||
SINT32 realbuf; /* DSOUND用のデータ数 */
|
||||
SINT32 virbuf; /* 86PCM(bufsize:0x8000)のデータ数 */
|
||||
SINT32 rescue;
|
||||
|
||||
SINT32 fifosize;
|
||||
SINT32 volume;
|
||||
SINT32 vol5;
|
||||
|
||||
UINT32 lastclock;
|
||||
UINT32 stepclock;
|
||||
UINT stepmask;
|
||||
|
||||
UINT8 fifo;
|
||||
UINT8 soundflags; /*!< サウンド フラグ (A460) */
|
||||
UINT8 dactrl;
|
||||
//UINT8 _write;
|
||||
UINT8 write; // (kaiD)
|
||||
UINT8 stepbit;
|
||||
UINT8 irq;
|
||||
UINT8 reqirq;
|
||||
UINT8 irqflag;
|
||||
|
||||
UINT8 buffer[PCM86_BUFSIZE];
|
||||
} _PCM86, *PCM86;
|
||||
|
||||
typedef struct {
|
||||
UINT rate;
|
||||
UINT vol;
|
||||
} PCM86CFG;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
extern const UINT pcm86rate8[];
|
||||
|
||||
void pcm86_cb(NEVENTITEM item);
|
||||
|
||||
void pcm86gen_initialize(UINT rate);
|
||||
void pcm86gen_setvol(UINT vol);
|
||||
|
||||
void pcm86_reset(void);
|
||||
void pcm86gen_update(void);
|
||||
void pcm86_setpcmrate(REG8 val);
|
||||
void pcm86_setnextintr(void);
|
||||
|
||||
void SOUNDCALL pcm86gen_checkbuf(PCM86 pcm86);
|
||||
void SOUNDCALL pcm86gen_getpcm(PCM86 pcm86, SINT32 *lpBuffer, UINT nCount);
|
||||
|
||||
BOOL pcm86gen_intrq(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/**
|
||||
* @file pcm86.h
|
||||
* @brief Interface of the 86-PCM
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "sound.h"
|
||||
#include "nevent.h"
|
||||
|
||||
enum {
|
||||
PCM86_LOGICALBUF = 0x8000,
|
||||
PCM86_BUFSIZE = (1 << 16),
|
||||
PCM86_BUFMSK = ((1 << 16) - 1),
|
||||
|
||||
PCM86_DIVBIT = 10,
|
||||
PCM86_DIVENV = (1 << PCM86_DIVBIT),
|
||||
|
||||
PCM86_RESCUE = 20
|
||||
};
|
||||
|
||||
#define PCM86_EXTBUF g_pcm86.rescue /* 救済延滞… */
|
||||
#define PCM86_REALBUFSIZE (PCM86_LOGICALBUF + PCM86_EXTBUF)
|
||||
|
||||
#define RECALC_NOWCLKWAIT(cnt) \
|
||||
do \
|
||||
{ \
|
||||
g_pcm86.virbuf -= (cnt << g_pcm86.stepbit); \
|
||||
if (g_pcm86.virbuf < 0) \
|
||||
{ \
|
||||
g_pcm86.virbuf &= g_pcm86.stepmask; \
|
||||
} \
|
||||
} while (0 /*CONSTCOND*/)
|
||||
|
||||
typedef struct {
|
||||
SINT32 divremain;
|
||||
SINT32 div;
|
||||
SINT32 div2;
|
||||
SINT32 smp;
|
||||
SINT32 lastsmp;
|
||||
SINT32 smp_l;
|
||||
SINT32 lastsmp_l;
|
||||
SINT32 smp_r;
|
||||
SINT32 lastsmp_r;
|
||||
|
||||
UINT32 readpos; /* DSOUND再生位置 */
|
||||
UINT32 wrtpos; /* 書込み位置 */
|
||||
SINT32 realbuf; /* DSOUND用のデータ数 */
|
||||
SINT32 virbuf; /* 86PCM(bufsize:0x8000)のデータ数 */
|
||||
SINT32 rescue;
|
||||
|
||||
SINT32 fifosize;
|
||||
SINT32 volume;
|
||||
SINT32 vol5;
|
||||
|
||||
UINT32 lastclock;
|
||||
UINT32 stepclock;
|
||||
UINT stepmask;
|
||||
|
||||
UINT8 fifo;
|
||||
UINT8 soundflags; /*!< サウンド フラグ (A460) */
|
||||
UINT8 dactrl;
|
||||
UINT8 _write;
|
||||
UINT8 stepbit;
|
||||
UINT8 irq;
|
||||
UINT8 reqirq;
|
||||
UINT8 irqflag;
|
||||
|
||||
UINT8 buffer[PCM86_BUFSIZE];
|
||||
} _PCM86, *PCM86;
|
||||
|
||||
typedef struct {
|
||||
UINT rate;
|
||||
UINT vol;
|
||||
} PCM86CFG;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
extern const UINT pcm86rate8[];
|
||||
|
||||
void pcm86_cb(NEVENTITEM item);
|
||||
|
||||
void pcm86gen_initialize(UINT rate);
|
||||
void pcm86gen_setvol(UINT vol);
|
||||
|
||||
void pcm86_reset(void);
|
||||
void pcm86gen_update(void);
|
||||
void pcm86_setpcmrate(REG8 val);
|
||||
void pcm86_setnextintr(void);
|
||||
|
||||
void SOUNDCALL pcm86gen_checkbuf(PCM86 pcm86);
|
||||
void SOUNDCALL pcm86gen_getpcm(PCM86 pcm86, SINT32 *lpBuffer, UINT nCount);
|
||||
|
||||
BOOL pcm86gen_intrq(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
461
sound/pcm86c.c
461
sound/pcm86c.c
@ -1,237 +1,224 @@
|
||||
/**
|
||||
* @file pcm86c.c
|
||||
* @brief Implementation of the 86-PCM
|
||||
*/
|
||||
|
||||
#include "compiler.h"
|
||||
#include "pcm86.h"
|
||||
#include "pccore.h"
|
||||
#include "cpucore.h"
|
||||
#include "iocore.h"
|
||||
#include "fmboard.h"
|
||||
|
||||
/* サンプリングレートに8掛けた物 */
|
||||
#if 1
|
||||
const UINT pcm86rate8[] = {
|
||||
44100 * 8,
|
||||
33080 * 8,
|
||||
22050 * 8,
|
||||
16540 * 8,
|
||||
11030 * 8,
|
||||
8270 * 8,
|
||||
5520 * 8,
|
||||
4130 * 8
|
||||
};
|
||||
#else
|
||||
const UINT pcm86rate8[] = {352800, 264600, 176400, 132300,
|
||||
88200, 66150, 44010, 33075};
|
||||
#endif
|
||||
|
||||
/* 32,24,16,12, 8, 6, 4, 3 - 最少公倍数: 96 */
|
||||
/* 3, 4, 6, 8,12,16,24,32 */
|
||||
|
||||
static const UINT clk25_128[] = {
|
||||
0x00001bde, 0x00002527, 0x000037bb, 0x00004a4e,
|
||||
0x00006f75, 0x0000949c, 0x0000df5f, 0x00012938};
|
||||
static const UINT clk20_128[] = {
|
||||
0x000016a4, 0x00001e30, 0x00002d48, 0x00003c60,
|
||||
0x00005a8f, 0x000078bf, 0x0000b57d, 0x0000f17d};
|
||||
|
||||
|
||||
PCM86CFG pcm86cfg;
|
||||
|
||||
|
||||
void pcm86gen_initialize(UINT rate)
|
||||
{
|
||||
pcm86cfg.rate = rate;
|
||||
}
|
||||
|
||||
void pcm86gen_setvol(UINT vol)
|
||||
{
|
||||
pcm86cfg.vol = vol;
|
||||
pcm86gen_update();
|
||||
}
|
||||
|
||||
void pcm86_reset(void)
|
||||
{
|
||||
PCM86 pcm86 = &g_pcm86;
|
||||
|
||||
memset(pcm86, 0, sizeof(*pcm86));
|
||||
pcm86->fifosize = 0x80;
|
||||
pcm86->dactrl = 0x32;
|
||||
pcm86->stepmask = (1 << 2) - 1;
|
||||
pcm86->stepbit = 2;
|
||||
pcm86->stepclock = (pccore.baseclock << 6);
|
||||
pcm86->stepclock /= 44100;
|
||||
pcm86->stepclock *= pccore.multiple;
|
||||
pcm86->rescue = (PCM86_RESCUE * 32) << 2;
|
||||
pcm86->irq = 0xff;
|
||||
}
|
||||
|
||||
void pcm86gen_update(void)
|
||||
{
|
||||
PCM86 pcm86 = &g_pcm86;
|
||||
|
||||
pcm86->volume = pcm86cfg.vol * pcm86->vol5;
|
||||
pcm86_setpcmrate(pcm86->fifo);
|
||||
}
|
||||
|
||||
void pcm86_setpcmrate(REG8 val)
|
||||
{
|
||||
PCM86 pcm86 = &g_pcm86;
|
||||
SINT32 rate;
|
||||
|
||||
rate = pcm86rate8[val & 7];
|
||||
pcm86->stepclock = (pccore.baseclock << 6);
|
||||
pcm86->stepclock /= rate;
|
||||
pcm86->stepclock *= (pccore.multiple << 3);
|
||||
if (pcm86cfg.rate)
|
||||
{
|
||||
pcm86->div = (rate << (PCM86_DIVBIT - 3)) / pcm86cfg.rate;
|
||||
pcm86->div2 = (pcm86cfg.rate << (PCM86_DIVBIT + 3)) / rate;
|
||||
}
|
||||
}
|
||||
|
||||
void pcm86_cb(NEVENTITEM item)
|
||||
{
|
||||
PCM86 pcm86 = &g_pcm86;
|
||||
|
||||
if (pcm86->reqirq)
|
||||
{
|
||||
sound_sync();
|
||||
// RECALC_NOWCLKP;
|
||||
|
||||
if (pcm86->virbuf <= pcm86->fifosize)
|
||||
{
|
||||
pcm86->reqirq = 0;
|
||||
pcm86->irqflag = 1;
|
||||
if (pcm86->irq != 0xff)
|
||||
{
|
||||
pic_setirq(pcm86->irq);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pcm86_setnextintr();
|
||||
}
|
||||
}
|
||||
(void)item;
|
||||
}
|
||||
|
||||
void pcm86_setnextintr(void) {
|
||||
|
||||
PCM86 pcm86 = &g_pcm86;
|
||||
SINT32 cnt;
|
||||
SINT32 clk;
|
||||
|
||||
if (pcm86->fifo & 0x80)
|
||||
{
|
||||
cnt = pcm86->virbuf - pcm86->fifosize;
|
||||
if (cnt > 0)
|
||||
{
|
||||
cnt += pcm86->stepmask;
|
||||
cnt >>= pcm86->stepbit;
|
||||
// cnt += 4; /* ちょっと延滞させる */
|
||||
/* ここで clk = pccore.realclock * cnt / 86pcm_rate */
|
||||
/* clk = ((pccore.baseclock / 86pcm_rate) * cnt) * pccore.multiple */
|
||||
if (pccore.cpumode & CPUMODE_8MHZ) {
|
||||
clk = clk20_128[pcm86->fifo & 7];
|
||||
}
|
||||
else {
|
||||
clk = clk25_128[pcm86->fifo & 7];
|
||||
}
|
||||
/* cntは最大 8000h で 32bitで収まるように… */
|
||||
clk *= cnt;
|
||||
clk >>= 7;
|
||||
// clk++; /* roundup */
|
||||
clk *= pccore.multiple;
|
||||
nevent_set(NEVENT_86PCM, clk, pcm86_cb, NEVENT_ABSOLUTE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SOUNDCALL pcm86gen_checkbuf(PCM86 pcm86)
|
||||
{
|
||||
long bufs;
|
||||
UINT32 past;
|
||||
static SINT32 lastvirbuf = 0;
|
||||
static UINT32 lastvirbufcnt = 0;
|
||||
|
||||
past = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK;
|
||||
past <<= 6;
|
||||
past -= pcm86->lastclock;
|
||||
if (past >= pcm86->stepclock)
|
||||
{
|
||||
past = past / pcm86->stepclock;
|
||||
pcm86->lastclock += (past * pcm86->stepclock);
|
||||
RECALC_NOWCLKWAIT(past);
|
||||
}
|
||||
|
||||
// XXX: Windowsでフリーズする問題の暫定対症療法(ある程度時間が経った小さいバッファを捨てる)
|
||||
if(0 < pcm86->virbuf && pcm86->virbuf < 128){
|
||||
if(pcm86->virbuf == lastvirbuf){
|
||||
lastvirbufcnt++;
|
||||
if(lastvirbufcnt > 500){
|
||||
// 500回呼ばれても値が変化しなかったら捨てる
|
||||
pcm86->virbuf = 0;
|
||||
lastvirbufcnt = 0;
|
||||
}
|
||||
}else{
|
||||
lastvirbuf = pcm86->virbuf;
|
||||
lastvirbufcnt = 0;
|
||||
}
|
||||
}else{
|
||||
lastvirbufcnt = 0;
|
||||
}
|
||||
|
||||
bufs = pcm86->realbuf - pcm86->virbuf;
|
||||
if (bufs < 0) /* 処理落ちてる… */
|
||||
{
|
||||
bufs &= ~3;
|
||||
pcm86->virbuf += bufs;
|
||||
if (pcm86->virbuf <= pcm86->fifosize)
|
||||
{
|
||||
pcm86->reqirq = 0;
|
||||
pcm86->irqflag = 1;
|
||||
if (pcm86->irq != 0xff)
|
||||
{
|
||||
pic_setirq(pcm86->irq);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pcm86_setnextintr();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bufs -= PCM86_EXTBUF;
|
||||
if (bufs > 0)
|
||||
{
|
||||
bufs &= ~3;
|
||||
pcm86->realbuf -= bufs;
|
||||
pcm86->readpos += bufs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOL pcm86gen_intrq(void)
|
||||
{
|
||||
PCM86 pcm86 = &g_pcm86;
|
||||
|
||||
if (pcm86->irqflag)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
if (pcm86->fifo & 0x20)
|
||||
{
|
||||
sound_sync();
|
||||
if ((pcm86->reqirq) && (pcm86->virbuf <= pcm86->fifosize))
|
||||
{
|
||||
pcm86->reqirq = 0;
|
||||
pcm86->irqflag = 1;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
/**
|
||||
* @file pcm86c.c
|
||||
* @brief Implementation of the 86-PCM
|
||||
*/
|
||||
|
||||
#include "compiler.h"
|
||||
#include "pcm86.h"
|
||||
#include "pccore.h"
|
||||
#include "cpucore.h"
|
||||
#include "iocore.h"
|
||||
#include "fmboard.h"
|
||||
|
||||
/* サンプリングレートに8掛けた物 */
|
||||
const UINT pcm86rate8[] = {352800, 264600, 176400, 132300,
|
||||
88200, 66150, 44010, 33075};
|
||||
|
||||
/* 32,24,16,12, 8, 6, 4, 3 - 最少公倍数: 96 */
|
||||
/* 3, 4, 6, 8,12,16,24,32 */
|
||||
|
||||
static const UINT clk25_128[] = {
|
||||
0x00001bde, 0x00002527, 0x000037bb, 0x00004a4e,
|
||||
0x00006f75, 0x0000949c, 0x0000df5f, 0x00012938};
|
||||
static const UINT clk20_128[] = {
|
||||
0x000016a4, 0x00001e30, 0x00002d48, 0x00003c60,
|
||||
0x00005a8f, 0x000078bf, 0x0000b57d, 0x0000f17d};
|
||||
|
||||
|
||||
PCM86CFG pcm86cfg;
|
||||
|
||||
|
||||
void pcm86gen_initialize(UINT rate)
|
||||
{
|
||||
pcm86cfg.rate = rate;
|
||||
}
|
||||
|
||||
void pcm86gen_setvol(UINT vol)
|
||||
{
|
||||
pcm86cfg.vol = vol;
|
||||
pcm86gen_update();
|
||||
}
|
||||
|
||||
void pcm86_reset(void)
|
||||
{
|
||||
PCM86 pcm86 = &g_pcm86;
|
||||
|
||||
memset(pcm86, 0, sizeof(*pcm86));
|
||||
pcm86->fifosize = 0x80;
|
||||
pcm86->dactrl = 0x32;
|
||||
pcm86->stepmask = (1 << 2) - 1;
|
||||
pcm86->stepbit = 2;
|
||||
pcm86->stepclock = (pccore.baseclock << 6);
|
||||
pcm86->stepclock /= 44100;
|
||||
pcm86->stepclock *= pccore.multiple;
|
||||
pcm86->rescue = (PCM86_RESCUE * 32) << 2;
|
||||
pcm86->irq = 0xff;
|
||||
}
|
||||
|
||||
void pcm86gen_update(void)
|
||||
{
|
||||
PCM86 pcm86 = &g_pcm86;
|
||||
|
||||
pcm86->volume = pcm86cfg.vol * pcm86->vol5;
|
||||
pcm86_setpcmrate(pcm86->fifo);
|
||||
}
|
||||
|
||||
void pcm86_setpcmrate(REG8 val)
|
||||
{
|
||||
PCM86 pcm86 = &g_pcm86;
|
||||
SINT32 rate;
|
||||
|
||||
rate = pcm86rate8[val & 7];
|
||||
pcm86->stepclock = (pccore.baseclock << 6);
|
||||
pcm86->stepclock /= rate;
|
||||
pcm86->stepclock *= (pccore.multiple << 3);
|
||||
if (pcm86cfg.rate)
|
||||
{
|
||||
pcm86->div = (rate << (PCM86_DIVBIT - 3)) / pcm86cfg.rate;
|
||||
pcm86->div2 = (pcm86cfg.rate << (PCM86_DIVBIT + 3)) / rate;
|
||||
}
|
||||
}
|
||||
|
||||
void pcm86_cb(NEVENTITEM item)
|
||||
{
|
||||
PCM86 pcm86 = &g_pcm86;
|
||||
|
||||
if (pcm86->reqirq)
|
||||
{
|
||||
sound_sync();
|
||||
// RECALC_NOWCLKP;
|
||||
|
||||
if (pcm86->virbuf <= pcm86->fifosize)
|
||||
{
|
||||
pcm86->reqirq = 0;
|
||||
pcm86->irqflag = 1;
|
||||
if (pcm86->irq != 0xff)
|
||||
{
|
||||
pic_setirq(pcm86->irq);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pcm86_setnextintr();
|
||||
}
|
||||
}
|
||||
(void)item;
|
||||
}
|
||||
|
||||
void pcm86_setnextintr(void) {
|
||||
|
||||
PCM86 pcm86 = &g_pcm86;
|
||||
SINT32 cnt;
|
||||
SINT32 clk;
|
||||
|
||||
if (pcm86->fifo & 0x80)
|
||||
{
|
||||
cnt = pcm86->virbuf - pcm86->fifosize;
|
||||
if (cnt > 0)
|
||||
{
|
||||
cnt += pcm86->stepmask;
|
||||
cnt >>= pcm86->stepbit;
|
||||
// cnt += 4; /* ちょっと延滞させる */
|
||||
/* ここで clk = pccore.realclock * cnt / 86pcm_rate */
|
||||
/* clk = ((pccore.baseclock / 86pcm_rate) * cnt) * pccore.multiple */
|
||||
if (pccore.cpumode & CPUMODE_8MHZ) {
|
||||
clk = clk20_128[pcm86->fifo & 7];
|
||||
}
|
||||
else {
|
||||
clk = clk25_128[pcm86->fifo & 7];
|
||||
}
|
||||
/* cntは最大 8000h で 32bitで収まるように… */
|
||||
clk *= cnt;
|
||||
clk >>= 7;
|
||||
// clk++; /* roundup */
|
||||
clk *= pccore.multiple;
|
||||
nevent_set(NEVENT_86PCM, clk, pcm86_cb, NEVENT_ABSOLUTE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SOUNDCALL pcm86gen_checkbuf(PCM86 pcm86)
|
||||
{
|
||||
long bufs;
|
||||
UINT32 past;
|
||||
static SINT32 lastvirbuf = 0;
|
||||
static UINT32 lastvirbufcnt = 0;
|
||||
|
||||
past = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK;
|
||||
past <<= 6;
|
||||
past -= pcm86->lastclock;
|
||||
if (past >= pcm86->stepclock)
|
||||
{
|
||||
past = past / pcm86->stepclock;
|
||||
pcm86->lastclock += (past * pcm86->stepclock);
|
||||
RECALC_NOWCLKWAIT(past);
|
||||
}
|
||||
|
||||
// XXX: Windowsでフリーズする問題の暫定対症療法(ある程度時間が経った小さいバッファを捨てる)
|
||||
if(0 < pcm86->virbuf && pcm86->virbuf < 128){
|
||||
if(pcm86->virbuf == lastvirbuf){
|
||||
lastvirbufcnt++;
|
||||
if(lastvirbufcnt > 500){
|
||||
// 500回呼ばれても値が変化しなかったら捨てる
|
||||
pcm86->virbuf = 0;
|
||||
lastvirbufcnt = 0;
|
||||
}
|
||||
}else{
|
||||
lastvirbuf = pcm86->virbuf;
|
||||
lastvirbufcnt = 0;
|
||||
}
|
||||
}else{
|
||||
lastvirbufcnt = 0;
|
||||
}
|
||||
|
||||
bufs = pcm86->realbuf - pcm86->virbuf;
|
||||
if (bufs < 0) /* 処理落ちてる… */
|
||||
{
|
||||
bufs &= ~3;
|
||||
pcm86->virbuf += bufs;
|
||||
if (pcm86->virbuf <= pcm86->fifosize)
|
||||
{
|
||||
pcm86->reqirq = 0;
|
||||
pcm86->irqflag = 1;
|
||||
if (pcm86->irq != 0xff)
|
||||
{
|
||||
pic_setirq(pcm86->irq);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pcm86_setnextintr();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bufs -= PCM86_EXTBUF;
|
||||
if (bufs > 0)
|
||||
{
|
||||
bufs &= ~3;
|
||||
pcm86->realbuf -= bufs;
|
||||
pcm86->readpos += bufs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOL pcm86gen_intrq(void)
|
||||
{
|
||||
PCM86 pcm86 = &g_pcm86;
|
||||
|
||||
if (pcm86->irqflag)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
if (pcm86->fifo & 0x20)
|
||||
{
|
||||
sound_sync();
|
||||
if ((pcm86->reqirq) && (pcm86->virbuf <= pcm86->fifosize))
|
||||
{
|
||||
pcm86->reqirq = 0;
|
||||
pcm86->irqflag = 1;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
858
sound/sound.c
858
sound/sound.c
@ -1,441 +1,417 @@
|
||||
/**
|
||||
* @file sound.c
|
||||
* @brief Implementation of the sound
|
||||
*/
|
||||
|
||||
#include "compiler.h"
|
||||
#include "sound.h"
|
||||
#include "cpucore.h"
|
||||
#include "pccore.h"
|
||||
#include "iocore.h"
|
||||
#include "sndcsec.h"
|
||||
#include "beep.h"
|
||||
#include "soundmng.h"
|
||||
#if defined(SUPPORT_WAVEREC)
|
||||
#include "common/wavefile.h"
|
||||
#endif /* defined(SUPPORT_WAVEREC) */
|
||||
|
||||
SOUNDCFG soundcfg;
|
||||
|
||||
|
||||
#define STREAM_CBMAX 16
|
||||
|
||||
typedef struct {
|
||||
void *hdl;
|
||||
SOUNDCB cbfn;
|
||||
} CBTBL;
|
||||
|
||||
typedef struct {
|
||||
SINT32 *buffer;
|
||||
SINT32 *ptr;
|
||||
UINT samples;
|
||||
UINT reserve;
|
||||
UINT remain;
|
||||
#if defined(SUPPORT_WAVEREC)
|
||||
WAVEFILEH rec;
|
||||
#endif /* defined(SUPPORT_WAVEREC) */
|
||||
CBTBL *cbreg;
|
||||
CBTBL cb[STREAM_CBMAX];
|
||||
} SNDSTREAM;
|
||||
|
||||
static SNDSTREAM sndstream;
|
||||
|
||||
|
||||
static void streamreset(void) {
|
||||
|
||||
SNDCSEC_ENTER;
|
||||
sndstream.ptr = sndstream.buffer;
|
||||
sndstream.remain = sndstream.samples + sndstream.reserve;
|
||||
sndstream.cbreg = sndstream.cb;
|
||||
SNDCSEC_LEAVE;
|
||||
}
|
||||
|
||||
static void streamprepare(UINT samples) {
|
||||
|
||||
CBTBL *cb;
|
||||
UINT count;
|
||||
|
||||
count = min(sndstream.remain, samples);
|
||||
if (count) {
|
||||
ZeroMemory(sndstream.ptr, count * 2 * sizeof(SINT32));
|
||||
cb = sndstream.cb;
|
||||
while(cb < sndstream.cbreg) {
|
||||
cb->cbfn(cb->hdl, sndstream.ptr, count);
|
||||
cb++;
|
||||
}
|
||||
sndstream.ptr += count * 2;
|
||||
sndstream.remain -= count;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if defined(SUPPORT_WAVEREC)
|
||||
// ---- wave rec
|
||||
|
||||
/**
|
||||
* Starts recording
|
||||
* @param[in] lpFilename The filename
|
||||
* @retval SUCCESS If succeeded
|
||||
* @retval FAILURE If failed
|
||||
*/
|
||||
BRESULT sound_recstart(const OEMCHAR *lpFilename)
|
||||
{
|
||||
WAVEFILEH rec;
|
||||
|
||||
sound_recstop();
|
||||
if (sndstream.buffer == NULL)
|
||||
{
|
||||
return FAILURE;
|
||||
}
|
||||
rec = wavefile_create(lpFilename, soundcfg.rate, 16, 2);
|
||||
sndstream.rec = rec;
|
||||
if (rec)
|
||||
{
|
||||
return SUCCESS;
|
||||
}
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops recording
|
||||
*/
|
||||
void sound_recstop(void)
|
||||
{
|
||||
WAVEFILEH rec;
|
||||
|
||||
rec = sndstream.rec;
|
||||
sndstream.rec = NULL;
|
||||
wavefile_close(rec);
|
||||
}
|
||||
|
||||
/**
|
||||
* is recording?
|
||||
* @retval TRUE Yes
|
||||
*/
|
||||
BOOL sound_isrecording(void)
|
||||
{
|
||||
return (sndstream.rec != NULL) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* write
|
||||
* @param[in] samples The count of samples
|
||||
*/
|
||||
static void streamfilewrite(UINT nSamples)
|
||||
{
|
||||
UINT nCount;
|
||||
SINT32 buf32[2 * 512];
|
||||
CBTBL *cb;
|
||||
UINT8 buf[2 * 512][2];
|
||||
UINT r;
|
||||
UINT i;
|
||||
SINT32 nSample;
|
||||
|
||||
while (nSamples)
|
||||
{
|
||||
nCount = min(nSamples, 512);
|
||||
memset(buf32, 0, nCount * 2 * sizeof(buf32[0]));
|
||||
cb = sndstream.cb;
|
||||
while (cb < sndstream.cbreg)
|
||||
{
|
||||
cb->cbfn(cb->hdl, buf32, nCount);
|
||||
cb++;
|
||||
}
|
||||
r = min(sndstream.remain, nCount);
|
||||
if (r)
|
||||
{
|
||||
memcpy(sndstream.ptr, buf32, r * 2 * sizeof(buf32[0]));
|
||||
sndstream.ptr += r * 2;
|
||||
sndstream.remain -= r;
|
||||
}
|
||||
for (i = 0; i < nCount * 2; i++)
|
||||
{
|
||||
nSample = buf32[i];
|
||||
if (nSample > 32767)
|
||||
{
|
||||
nSample = 32767;
|
||||
}
|
||||
else if (nSample < -32768)
|
||||
{
|
||||
nSample = -32768;
|
||||
}
|
||||
// little endianなので satuation_s16は使えない
|
||||
buf[i][0] = (UINT8)nSample;
|
||||
buf[i][1] = (UINT8)(nSample >> 8);
|
||||
}
|
||||
wavefile_write(sndstream.rec, buf, nCount * 2 * sizeof(buf[0]));
|
||||
nSamples -= nCount;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* fill
|
||||
* @param[in] samples The count of samples
|
||||
*/
|
||||
static void filltailsample(UINT nCount)
|
||||
{
|
||||
SINT32 *ptr;
|
||||
UINT nOrgSize;
|
||||
SINT32 nSampleL;
|
||||
SINT32 nSampleR;
|
||||
|
||||
nCount = min(sndstream.remain, nCount);
|
||||
if (nCount)
|
||||
{
|
||||
ptr = sndstream.ptr;
|
||||
nOrgSize = (UINT)((ptr - sndstream.buffer) / 2);
|
||||
if (nOrgSize == 0)
|
||||
{
|
||||
nSampleL = 0;
|
||||
nSampleR = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
nSampleL = *(ptr - 2);
|
||||
nSampleR = *(ptr - 1);
|
||||
}
|
||||
sndstream.ptr += nCount * 2;
|
||||
sndstream.remain -= nCount;
|
||||
do
|
||||
{
|
||||
ptr[0] = nSampleL;
|
||||
ptr[1] = nSampleR;
|
||||
ptr += 2;
|
||||
} while (--nCount);
|
||||
}
|
||||
}
|
||||
#endif /* defined(SUPPORT_WAVEREC) */
|
||||
|
||||
|
||||
// ----
|
||||
|
||||
BRESULT sound_create(UINT rate, UINT ms) {
|
||||
|
||||
UINT samples;
|
||||
UINT reserve;
|
||||
|
||||
ZeroMemory(&sndstream, sizeof(sndstream));
|
||||
// CDDA
|
||||
#if 0
|
||||
switch(rate) {
|
||||
case 11025:
|
||||
case 22050:
|
||||
case 44100:
|
||||
case 48000:
|
||||
case 88200:
|
||||
case 96000:
|
||||
case 176400:
|
||||
case 192000:
|
||||
break;
|
||||
|
||||
default:
|
||||
return(FAILURE);
|
||||
}
|
||||
#else
|
||||
switch(rate) {
|
||||
case 11025:
|
||||
soundcfg.cddaskip = 4;
|
||||
break;
|
||||
case 22050:
|
||||
soundcfg.cddaskip = 2;
|
||||
break;
|
||||
case 44100:
|
||||
soundcfg.cddaskip = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
soundcfg.cddaskip = 1;
|
||||
return(FAILURE);
|
||||
}
|
||||
#endif
|
||||
samples = soundmng_create(rate, ms);
|
||||
if (samples == 0) {
|
||||
goto scre_err1;
|
||||
}
|
||||
soundmng_reset();
|
||||
|
||||
soundcfg.rate = rate;
|
||||
sound_changeclock();
|
||||
|
||||
#if defined(SOUNDRESERVE)
|
||||
reserve = rate * SOUNDRESERVE / 1000;
|
||||
#else
|
||||
reserve = 0;
|
||||
#endif
|
||||
#ifdef __LIBRETRO__
|
||||
reserve=0;
|
||||
//samples=735; //44100Hz/60fps=735 (sample/flame)
|
||||
samples=782; //44100Hz/56.4fps=781.9 (sample/flame)
|
||||
#endif
|
||||
sndstream.buffer = (SINT32 *)_MALLOC((samples + reserve) * 2
|
||||
* sizeof(SINT32), "stream");
|
||||
if (sndstream.buffer == NULL) {
|
||||
goto scre_err2;
|
||||
}
|
||||
sndstream.samples = samples;
|
||||
sndstream.reserve = reserve;
|
||||
|
||||
SNDCSEC_INIT;
|
||||
streamreset();
|
||||
return(SUCCESS);
|
||||
|
||||
scre_err2:
|
||||
soundmng_destroy();
|
||||
|
||||
scre_err1:
|
||||
return(FAILURE);
|
||||
}
|
||||
|
||||
void sound_destroy(void) {
|
||||
|
||||
if (sndstream.buffer) {
|
||||
#if defined(SUPPORT_WAVEREC)
|
||||
sound_recstop();
|
||||
#endif /* defined(SUPPORT_WAVEREC) */
|
||||
soundmng_stop();
|
||||
streamreset();
|
||||
soundmng_destroy();
|
||||
SNDCSEC_TERM;
|
||||
_MFREE(sndstream.buffer);
|
||||
sndstream.buffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void sound_reset(void) {
|
||||
|
||||
if (sndstream.buffer) {
|
||||
soundmng_reset();
|
||||
streamreset();
|
||||
soundcfg.lastclock = CPU_CLOCK;
|
||||
beep_eventreset();
|
||||
}
|
||||
}
|
||||
|
||||
void sound_changeclock(void) {
|
||||
|
||||
UINT32 clk;
|
||||
UINT hz;
|
||||
UINT hzmax;
|
||||
|
||||
if (sndstream.buffer == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
// とりあえず 25で割り切れる。
|
||||
clk = pccore.realclock / 25;
|
||||
hz = soundcfg.rate / 25;
|
||||
|
||||
// で、クロック数に合せて調整。(64bit演算しろよな的)
|
||||
hzmax = (1 << (32 - 8)) / (clk >> 8);
|
||||
while(hzmax < hz) {
|
||||
clk = (clk + 1) >> 1;
|
||||
hz = (hz + 1) >> 1;
|
||||
}
|
||||
TRACEOUT(("hzbase/clockbase = %d/%d", hz, clk));
|
||||
soundcfg.hzbase = hz;
|
||||
soundcfg.clockbase = clk;
|
||||
soundcfg.minclock = 2 * clk / hz;
|
||||
soundcfg.lastclock = CPU_CLOCK;
|
||||
}
|
||||
|
||||
void sound_streamregist(void *hdl, SOUNDCB cbfn) {
|
||||
|
||||
if (sndstream.buffer) {
|
||||
if ((cbfn) &&
|
||||
(sndstream.cbreg < (sndstream.cb + STREAM_CBMAX))) {
|
||||
sndstream.cbreg->hdl = hdl;
|
||||
sndstream.cbreg->cbfn = cbfn;
|
||||
sndstream.cbreg++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ----
|
||||
|
||||
void sound_sync(void) {
|
||||
|
||||
UINT32 length;
|
||||
|
||||
if (sndstream.buffer == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
length = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK - soundcfg.lastclock;
|
||||
if (length < soundcfg.minclock) {
|
||||
return;
|
||||
}
|
||||
length = (length * soundcfg.hzbase) / soundcfg.clockbase;
|
||||
if (length == 0) {
|
||||
return;
|
||||
}
|
||||
SNDCSEC_ENTER;
|
||||
#if defined(SUPPORT_WAVEREC)
|
||||
if (sndstream.rec) {
|
||||
streamfilewrite(length);
|
||||
}
|
||||
else
|
||||
#endif /* defined(SUPPORT_WAVEREC) */
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
static volatile int locks = 0;
|
||||
|
||||
const SINT32 *sound_pcmlock(void) {
|
||||
|
||||
const SINT32 *ret;
|
||||
|
||||
if (locks) {
|
||||
TRACEOUT(("sound pcm lock: already locked"));
|
||||
return(NULL);
|
||||
}
|
||||
locks++;
|
||||
ret = sndstream.buffer;
|
||||
if (ret) {
|
||||
SNDCSEC_ENTER;
|
||||
if (sndstream.remain > sndstream.reserve)
|
||||
#if defined(SUPPORT_WAVEREC)
|
||||
if (sndstream.rec) {
|
||||
filltailsample(sndstream.remain - sndstream.reserve);
|
||||
}
|
||||
else
|
||||
#endif /* defined(SUPPORT_WAVEREC) */
|
||||
{
|
||||
streamprepare(sndstream.remain - sndstream.reserve);
|
||||
soundcfg.lastclock = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK;
|
||||
beep_eventreset();
|
||||
}
|
||||
}
|
||||
else {
|
||||
locks--;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
void sound_pcmunlock(const SINT32 *hdl) {
|
||||
|
||||
int leng;
|
||||
|
||||
if (hdl) {
|
||||
leng = sndstream.reserve - sndstream.remain;
|
||||
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;
|
||||
locks--;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @file sound.c
|
||||
* @brief Implementation of the sound
|
||||
*/
|
||||
|
||||
#include "compiler.h"
|
||||
#include "sound.h"
|
||||
#include "cpucore.h"
|
||||
#include "pccore.h"
|
||||
#include "iocore.h"
|
||||
#include "sndcsec.h"
|
||||
#include "beep.h"
|
||||
#include "soundmng.h"
|
||||
#if defined(SUPPORT_WAVEREC)
|
||||
#include "common/wavefile.h"
|
||||
#endif /* defined(SUPPORT_WAVEREC) */
|
||||
|
||||
SOUNDCFG soundcfg;
|
||||
|
||||
|
||||
#define STREAM_CBMAX 16
|
||||
|
||||
typedef struct {
|
||||
void *hdl;
|
||||
SOUNDCB cbfn;
|
||||
} CBTBL;
|
||||
|
||||
typedef struct {
|
||||
SINT32 *buffer;
|
||||
SINT32 *ptr;
|
||||
UINT samples;
|
||||
UINT reserve;
|
||||
UINT remain;
|
||||
#if defined(SUPPORT_WAVEREC)
|
||||
WAVEFILEH rec;
|
||||
#endif /* defined(SUPPORT_WAVEREC) */
|
||||
CBTBL *cbreg;
|
||||
CBTBL cb[STREAM_CBMAX];
|
||||
} SNDSTREAM;
|
||||
|
||||
static SNDSTREAM sndstream;
|
||||
|
||||
|
||||
static void streamreset(void) {
|
||||
|
||||
SNDCSEC_ENTER;
|
||||
sndstream.ptr = sndstream.buffer;
|
||||
sndstream.remain = sndstream.samples + sndstream.reserve;
|
||||
sndstream.cbreg = sndstream.cb;
|
||||
SNDCSEC_LEAVE;
|
||||
}
|
||||
|
||||
static void streamprepare(UINT samples) {
|
||||
|
||||
CBTBL *cb;
|
||||
UINT count;
|
||||
|
||||
count = min(sndstream.remain, samples);
|
||||
if (count) {
|
||||
ZeroMemory(sndstream.ptr, count * 2 * sizeof(SINT32));
|
||||
cb = sndstream.cb;
|
||||
while(cb < sndstream.cbreg) {
|
||||
cb->cbfn(cb->hdl, sndstream.ptr, count);
|
||||
cb++;
|
||||
}
|
||||
sndstream.ptr += count * 2;
|
||||
sndstream.remain -= count;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if defined(SUPPORT_WAVEREC)
|
||||
// ---- wave rec
|
||||
|
||||
/**
|
||||
* Starts recording
|
||||
* @param[in] lpFilename The filename
|
||||
* @retval SUCCESS If succeeded
|
||||
* @retval FAILURE If failed
|
||||
*/
|
||||
BRESULT sound_recstart(const OEMCHAR *lpFilename)
|
||||
{
|
||||
WAVEFILEH rec;
|
||||
|
||||
sound_recstop();
|
||||
if (sndstream.buffer == NULL)
|
||||
{
|
||||
return FAILURE;
|
||||
}
|
||||
rec = wavefile_create(lpFilename, soundcfg.rate, 16, 2);
|
||||
sndstream.rec = rec;
|
||||
if (rec)
|
||||
{
|
||||
return SUCCESS;
|
||||
}
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops recording
|
||||
*/
|
||||
void sound_recstop(void)
|
||||
{
|
||||
WAVEFILEH rec;
|
||||
|
||||
rec = sndstream.rec;
|
||||
sndstream.rec = NULL;
|
||||
wavefile_close(rec);
|
||||
}
|
||||
|
||||
/**
|
||||
* is recording?
|
||||
* @retval TRUE Yes
|
||||
*/
|
||||
BOOL sound_isrecording(void)
|
||||
{
|
||||
return (sndstream.rec != NULL) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* write
|
||||
* @param[in] samples The count of samples
|
||||
*/
|
||||
static void streamfilewrite(UINT nSamples)
|
||||
{
|
||||
UINT nCount;
|
||||
SINT32 buf32[2 * 512];
|
||||
CBTBL *cb;
|
||||
UINT8 buf[2 * 512][2];
|
||||
UINT r;
|
||||
UINT i;
|
||||
SINT32 nSample;
|
||||
|
||||
while (nSamples)
|
||||
{
|
||||
nCount = min(nSamples, 512);
|
||||
memset(buf32, 0, nCount * 2 * sizeof(buf32[0]));
|
||||
cb = sndstream.cb;
|
||||
while (cb < sndstream.cbreg)
|
||||
{
|
||||
cb->cbfn(cb->hdl, buf32, nCount);
|
||||
cb++;
|
||||
}
|
||||
r = min(sndstream.remain, nCount);
|
||||
if (r)
|
||||
{
|
||||
memcpy(sndstream.ptr, buf32, r * 2 * sizeof(buf32[0]));
|
||||
sndstream.ptr += r * 2;
|
||||
sndstream.remain -= r;
|
||||
}
|
||||
for (i = 0; i < nCount * 2; i++)
|
||||
{
|
||||
nSample = buf32[i];
|
||||
if (nSample > 32767)
|
||||
{
|
||||
nSample = 32767;
|
||||
}
|
||||
else if (nSample < -32768)
|
||||
{
|
||||
nSample = -32768;
|
||||
}
|
||||
// little endianなので satuation_s16は使えない
|
||||
buf[i][0] = (UINT8)nSample;
|
||||
buf[i][1] = (UINT8)(nSample >> 8);
|
||||
}
|
||||
wavefile_write(sndstream.rec, buf, nCount * 2 * sizeof(buf[0]));
|
||||
nSamples -= nCount;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* fill
|
||||
* @param[in] samples The count of samples
|
||||
*/
|
||||
static void filltailsample(UINT nCount)
|
||||
{
|
||||
SINT32 *ptr;
|
||||
UINT nOrgSize;
|
||||
SINT32 nSampleL;
|
||||
SINT32 nSampleR;
|
||||
|
||||
nCount = min(sndstream.remain, nCount);
|
||||
if (nCount)
|
||||
{
|
||||
ptr = sndstream.ptr;
|
||||
nOrgSize = (UINT)((ptr - sndstream.buffer) / 2);
|
||||
if (nOrgSize == 0)
|
||||
{
|
||||
nSampleL = 0;
|
||||
nSampleR = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
nSampleL = *(ptr - 2);
|
||||
nSampleR = *(ptr - 1);
|
||||
}
|
||||
sndstream.ptr += nCount * 2;
|
||||
sndstream.remain -= nCount;
|
||||
do
|
||||
{
|
||||
ptr[0] = nSampleL;
|
||||
ptr[1] = nSampleR;
|
||||
ptr += 2;
|
||||
} while (--nCount);
|
||||
}
|
||||
}
|
||||
#endif /* defined(SUPPORT_WAVEREC) */
|
||||
|
||||
|
||||
// ----
|
||||
|
||||
BRESULT sound_create(UINT rate, UINT ms) {
|
||||
|
||||
UINT samples;
|
||||
UINT reserve;
|
||||
|
||||
ZeroMemory(&sndstream, sizeof(sndstream));
|
||||
switch(rate) {
|
||||
case 11025:
|
||||
case 22050:
|
||||
case 44100:
|
||||
case 48000:
|
||||
case 88200:
|
||||
case 96000:
|
||||
case 176400:
|
||||
case 192000:
|
||||
break;
|
||||
|
||||
default:
|
||||
return(FAILURE);
|
||||
}
|
||||
samples = soundmng_create(rate, ms);
|
||||
if (samples == 0) {
|
||||
goto scre_err1;
|
||||
}
|
||||
soundmng_reset();
|
||||
|
||||
soundcfg.rate = rate;
|
||||
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) {
|
||||
goto scre_err2;
|
||||
}
|
||||
sndstream.samples = samples;
|
||||
sndstream.reserve = reserve;
|
||||
|
||||
SNDCSEC_INIT;
|
||||
streamreset();
|
||||
return(SUCCESS);
|
||||
|
||||
scre_err2:
|
||||
soundmng_destroy();
|
||||
|
||||
scre_err1:
|
||||
return(FAILURE);
|
||||
}
|
||||
|
||||
void sound_destroy(void) {
|
||||
|
||||
if (sndstream.buffer) {
|
||||
#if defined(SUPPORT_WAVEREC)
|
||||
sound_recstop();
|
||||
#endif /* defined(SUPPORT_WAVEREC) */
|
||||
soundmng_stop();
|
||||
streamreset();
|
||||
soundmng_destroy();
|
||||
SNDCSEC_TERM;
|
||||
_MFREE(sndstream.buffer);
|
||||
sndstream.buffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void sound_reset(void) {
|
||||
|
||||
if (sndstream.buffer) {
|
||||
soundmng_reset();
|
||||
streamreset();
|
||||
soundcfg.lastclock = CPU_CLOCK;
|
||||
beep_eventreset();
|
||||
}
|
||||
}
|
||||
|
||||
void sound_changeclock(void) {
|
||||
|
||||
UINT32 clk;
|
||||
UINT hz;
|
||||
UINT hzmax;
|
||||
|
||||
if (sndstream.buffer == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
// とりあえず 25で割り切れる。
|
||||
clk = pccore.realclock / 25;
|
||||
hz = soundcfg.rate / 25;
|
||||
|
||||
// で、クロック数に合せて調整。(64bit演算しろよな的)
|
||||
hzmax = (1 << (32 - 8)) / (clk >> 8);
|
||||
while(hzmax < hz) {
|
||||
clk = (clk + 1) >> 1;
|
||||
hz = (hz + 1) >> 1;
|
||||
}
|
||||
TRACEOUT(("hzbase/clockbase = %d/%d", hz, clk));
|
||||
soundcfg.hzbase = hz;
|
||||
soundcfg.clockbase = clk;
|
||||
soundcfg.minclock = 2 * clk / hz;
|
||||
soundcfg.lastclock = CPU_CLOCK;
|
||||
}
|
||||
|
||||
void sound_streamregist(void *hdl, SOUNDCB cbfn) {
|
||||
|
||||
if (sndstream.buffer) {
|
||||
if ((cbfn) &&
|
||||
(sndstream.cbreg < (sndstream.cb + STREAM_CBMAX))) {
|
||||
sndstream.cbreg->hdl = hdl;
|
||||
sndstream.cbreg->cbfn = cbfn;
|
||||
sndstream.cbreg++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ----
|
||||
|
||||
void sound_sync(void) {
|
||||
|
||||
UINT32 length;
|
||||
|
||||
if (sndstream.buffer == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
length = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK - soundcfg.lastclock;
|
||||
if (length < soundcfg.minclock) {
|
||||
return;
|
||||
}
|
||||
length = (length * soundcfg.hzbase) / soundcfg.clockbase;
|
||||
if (length == 0) {
|
||||
return;
|
||||
}
|
||||
SNDCSEC_ENTER;
|
||||
#if defined(SUPPORT_WAVEREC)
|
||||
if (sndstream.rec) {
|
||||
streamfilewrite(length);
|
||||
}
|
||||
else
|
||||
#endif /* defined(SUPPORT_WAVEREC) */
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
static volatile int locks = 0;
|
||||
|
||||
const SINT32 *sound_pcmlock(void) {
|
||||
|
||||
const SINT32 *ret;
|
||||
|
||||
if (locks) {
|
||||
TRACEOUT(("sound pcm lock: already locked"));
|
||||
return(NULL);
|
||||
}
|
||||
locks++;
|
||||
ret = sndstream.buffer;
|
||||
if (ret) {
|
||||
SNDCSEC_ENTER;
|
||||
if (sndstream.remain > sndstream.reserve)
|
||||
#if defined(SUPPORT_WAVEREC)
|
||||
if (sndstream.rec) {
|
||||
filltailsample(sndstream.remain - sndstream.reserve);
|
||||
}
|
||||
else
|
||||
#endif /* defined(SUPPORT_WAVEREC) */
|
||||
{
|
||||
streamprepare(sndstream.remain - sndstream.reserve);
|
||||
soundcfg.lastclock = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK;
|
||||
beep_eventreset();
|
||||
}
|
||||
}
|
||||
else {
|
||||
locks--;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
void sound_pcmunlock(const SINT32 *hdl) {
|
||||
|
||||
int leng;
|
||||
|
||||
if (hdl) {
|
||||
leng = sndstream.reserve - sndstream.remain;
|
||||
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;
|
||||
locks--;
|
||||
}
|
||||
}
|
||||
|
129
sound/sound.h
129
sound/sound.h
@ -1,66 +1,63 @@
|
||||
/**
|
||||
* @file sound.h
|
||||
* @brief Interface of the sound
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef SOUNDCALL
|
||||
#define SOUNDCALL
|
||||
#endif
|
||||
|
||||
#if !defined(DISABLE_SOUND)
|
||||
|
||||
typedef void (SOUNDCALL * SOUNDCB)(void *hdl, SINT32 *pcm, UINT count);
|
||||
|
||||
typedef struct {
|
||||
UINT rate;
|
||||
// CDDATvOf[^Ôø«Ìœß̬×H
|
||||
UINT cddaskip;
|
||||
//
|
||||
UINT32 hzbase;
|
||||
UINT32 clockbase;
|
||||
UINT32 minclock;
|
||||
UINT32 lastclock;
|
||||
UINT writecount;
|
||||
} SOUNDCFG;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern SOUNDCFG soundcfg;
|
||||
|
||||
BRESULT sound_create(UINT rate, UINT ms);
|
||||
void sound_destroy(void);
|
||||
|
||||
void sound_reset(void);
|
||||
void sound_changeclock(void);
|
||||
void sound_streamregist(void *hdl, SOUNDCB cbfn);
|
||||
|
||||
void sound_sync(void);
|
||||
|
||||
const SINT32 *sound_pcmlock(void);
|
||||
void sound_pcmunlock(const SINT32 *hdl);
|
||||
|
||||
#if defined(SUPPORT_WAVEREC)
|
||||
BRESULT sound_recstart(const OEMCHAR *filename);
|
||||
void sound_recstop(void);
|
||||
BOOL sound_isrecording(void);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#define sound_pcmlock() (NULL)
|
||||
#define sound_pcmunlock(h)
|
||||
#define sound_reset()
|
||||
#define sound_changeclock()
|
||||
#define sound_sync()
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @file sound.h
|
||||
* @brief Interface of the sound
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef SOUNDCALL
|
||||
#define SOUNDCALL
|
||||
#endif
|
||||
|
||||
#if !defined(DISABLE_SOUND)
|
||||
|
||||
typedef void (SOUNDCALL * SOUNDCB)(void *hdl, SINT32 *pcm, UINT count);
|
||||
|
||||
typedef struct {
|
||||
UINT rate;
|
||||
UINT32 hzbase;
|
||||
UINT32 clockbase;
|
||||
UINT32 minclock;
|
||||
UINT32 lastclock;
|
||||
UINT writecount;
|
||||
} SOUNDCFG;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern SOUNDCFG soundcfg;
|
||||
|
||||
BRESULT sound_create(UINT rate, UINT ms);
|
||||
void sound_destroy(void);
|
||||
|
||||
void sound_reset(void);
|
||||
void sound_changeclock(void);
|
||||
void sound_streamregist(void *hdl, SOUNDCB cbfn);
|
||||
|
||||
void sound_sync(void);
|
||||
|
||||
const SINT32 *sound_pcmlock(void);
|
||||
void sound_pcmunlock(const SINT32 *hdl);
|
||||
|
||||
#if defined(SUPPORT_WAVEREC)
|
||||
BRESULT sound_recstart(const OEMCHAR *filename);
|
||||
void sound_recstop(void);
|
||||
BOOL sound_isrecording(void);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#define sound_pcmlock() (NULL)
|
||||
#define sound_pcmunlock(h)
|
||||
#define sound_reset()
|
||||
#define sound_changeclock()
|
||||
#define sound_sync()
|
||||
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user