remove CDDA mod

This commit is contained in:
Tomohiro Yoshidomi 2017-10-02 18:13:18 +09:00
parent 2fa46a2404
commit d498e50734
6 changed files with 1074 additions and 1144 deletions

20
cbus/ideio.c Executable file → Normal file
View 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) {

View File

@ -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);
}

View File

@ -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

View File

@ -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;
}

View File

@ -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--;
}
}

View File

@ -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;
// CDDAƒTƒ“ƒvƒŠƒ“ƒOƒf[ƒ^ŠÔˆø‚«‚Ì‚œ‚߂̏¬×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