NP2kai/sound/rhythmc.c
2019-03-21 20:48:05 +09:00

160 lines
3.1 KiB
C
Executable File

/**
* @file rhythmc.c
* @brief Implementation of the OPNA rhythm
*/
#include "compiler.h"
#include <math.h>
#include "rhythm.h"
#include "pccore.h"
static const OEMCHAR file_2608bd[] = OEMTEXT("2608_bd.wav");
static const OEMCHAR file_2608sd[] = OEMTEXT("2608_sd.wav");
static const OEMCHAR file_2608top[] = OEMTEXT("2608_top.wav");
static const OEMCHAR file_2608hh[] = OEMTEXT("2608_hh.wav");
static const OEMCHAR file_2608tom[] = OEMTEXT("2608_tom.wav");
static const OEMCHAR file_2608rim[] = OEMTEXT("2608_rim.wav");
static const OEMCHAR *rhythmfile[6] = {
file_2608bd, file_2608sd, file_2608top,
file_2608hh, file_2608tom, file_2608rim};
typedef struct {
UINT rate;
UINT pcmexist;
PMIXDAT pcm[6];
UINT vol;
UINT voltbl[96];
} RHYTHMCFG;
static RHYTHMCFG rhythmcfg;
void rhythm_initialize(UINT rate) {
UINT i;
ZeroMemory(&rhythmcfg, sizeof(rhythmcfg));
rhythmcfg.rate = rate;
for (i=0; i<96; i++) {
rhythmcfg.voltbl[i] = (UINT)(32768.0 *
pow(2.0, (double)i * (-3.0) / 40.0));
}
}
void rhythm_deinitialize(void) {
UINT i;
SINT16 *ptr;
for (i=0; i<6; i++) {
ptr = rhythmcfg.pcm[i].sample;
rhythmcfg.pcm[i].sample = NULL;
if (ptr) {
_MFREE(ptr);
}
}
}
static void rhythm_load(void) {
int i;
OEMCHAR path[MAX_PATH];
for (i=0; i<6; i++) {
if (rhythmcfg.pcm[i].sample == NULL) {
getbiospath(path, rhythmfile[i], NELEMENTS(path));
pcmmix_regfile(rhythmcfg.pcm + i, path, rhythmcfg.rate);
}
}
}
UINT rhythm_getcaps(void) {
UINT ret;
UINT i;
ret = 0;
for (i=0; i<6; i++) {
if (rhythmcfg.pcm[i].sample) {
ret |= 1 << i;
}
}
return(ret);
}
void rhythm_setvol(UINT vol) {
rhythmcfg.vol = vol;
}
void rhythm_reset(RHYTHM rhy)
{
memset(rhy, 0, sizeof(*rhy));
}
void rhythm_bind(RHYTHM rhy) {
UINT i;
rhythm_load();
rhy->hdr.enable = 0x3f;
for (i=0; i<6; i++) {
rhy->trk[i].data = rhythmcfg.pcm[i];
}
rhythm_update(rhy);
sound_streamregist(rhy, (SOUNDCB)pcmmix_getpcm);
}
void rhythm_update(RHYTHM rhy) {
UINT i;
for (i=0; i<6; i++) {
rhy->trk[i].volume = (rhythmcfg.voltbl[rhy->vol + rhy->trkvol[i]] *
rhythmcfg.vol) >> 10;
}
}
void rhythm_setreg(RHYTHM rhy, UINT reg, REG8 value) {
PMIXTRK *trk;
REG8 bit;
if (reg == 0x10) {
sound_sync();
trk = rhy->trk;
bit = 0x01;
do {
if (value & bit) {
if (value & 0x80) {
rhy->hdr.playing &= ~((UINT)bit);
}
else if (trk->data.sample) {
trk->pcm = trk->data.sample;
trk->remain = trk->data.samples;
rhy->hdr.playing |= bit;
}
}
trk++;
bit <<= 1;
} while(bit < 0x40);
}
else if (reg == 0x11) {
sound_sync();
rhy->vol = (~value) & 0x3f;
rhythm_update(rhy);
}
else if ((reg >= 0x18) && (reg < 0x1e)) {
sound_sync();
trk = rhy->trk + (reg - 0x18);
trk->flag = ((value & 0x80) >> 7) + ((value & 0x40) >> 5);
value = (~value) & 0x1f;
rhy->trkvol[reg - 0x18] = (UINT8)value;
trk->volume = (rhythmcfg.voltbl[rhy->vol + value] *
rhythmcfg.vol) >> 10;
}
}