aboutsummaryrefslogtreecommitdiff
path: root/libopna
diff options
context:
space:
mode:
Diffstat (limited to 'libopna')
-rw-r--r--libopna/opna.c13
-rw-r--r--libopna/opna.h24
-rw-r--r--libopna/opnaadpcm.c22
-rw-r--r--libopna/opnaadpcm.h1
-rw-r--r--libopna/opnadrum.c7
-rw-r--r--libopna/opnadrum.h1
-rw-r--r--libopna/opnafm.c2
-rw-r--r--libopna/opnafm.h4
-rw-r--r--libopna/opnassg.c2
-rw-r--r--libopna/opnassg.h1
10 files changed, 64 insertions, 13 deletions
diff --git a/libopna/opna.c b/libopna/opna.c
index 4e198a0..fb9e24a 100644
--- a/libopna/opna.c
+++ b/libopna/opna.c
@@ -6,6 +6,7 @@ void opna_reset(struct opna *opna) {
opna_ssg_resampler_reset(&opna->resampler);
opna_drum_reset(&opna->drum);
opna_adpcm_reset(&opna->adpcm);
+ opna->mask = 0;
}
void opna_writereg(struct opna *opna, unsigned reg, unsigned val) {
@@ -22,3 +23,15 @@ void opna_mix(struct opna *opna, int16_t *buf, unsigned samples) {
opna_drum_mix(&opna->drum, buf, samples);
opna_adpcm_mix(&opna->adpcm, buf, samples);
}
+
+unsigned opna_get_mask(const struct opna *opna) {
+ return opna->mask;
+}
+
+void opna_set_mask(struct opna *opna, unsigned mask) {
+ opna->mask = mask & 0xffffu;
+ opna->fm.mask = mask & ((1<<(6+1))-1);
+ opna->ssg.mask = (mask >> 6) & ((1<<(3+1))-1);
+ opna->adpcm.masked = mask & LIBOPNA_CHAN_ADPCM;
+ opna->drum.mask = (mask >> 9) & ((1<<(6+1))-1);
+}
diff --git a/libopna/opna.h b/libopna/opna.h
index a056156..b5e9d87 100644
--- a/libopna/opna.h
+++ b/libopna/opna.h
@@ -10,18 +10,40 @@
extern "C" {
#endif
+enum {
+ LIBOPNA_CHAN_FM_1 = 0x0001,
+ LIBOPNA_CHAN_FM_2 = 0x0002,
+ LIBOPNA_CHAN_FM_3 = 0x0004,
+ LIBOPNA_CHAN_FM_4 = 0x0008,
+ LIBOPNA_CHAN_FM_5 = 0x0010,
+ LIBOPNA_CHAN_FM_6 = 0x0020,
+ LIBOPNA_CHAN_SSG_1 = 0x0040,
+ LIBOPNA_CHAN_SSG_2 = 0x0080,
+ LIBOPNA_CHAN_SSG_3 = 0x0100,
+ LIBOPNA_CHAN_DRUM_BD = 0x0200,
+ LIBOPNA_CHAN_DRUM_SD = 0x0400,
+ LIBOPNA_CHAN_DRUM_TOP = 0x0800,
+ LIBOPNA_CHAN_DRUM_HH = 0x1000,
+ LIBOPNA_CHAN_DRUM_TOM = 0x2000,
+ LIBOPNA_CHAN_DRUM_RIM = 0x4000,
+ LIBOPNA_CHAN_DRUM_ALL = 0x7e00,
+ LIBOPNA_CHAN_ADPCM = 0x8000,
+};
+
struct opna {
struct opna_fm fm;
struct opna_ssg ssg;
struct opna_drum drum;
struct opna_adpcm adpcm;
struct opna_ssg_resampler resampler;
-
+ unsigned mask;
};
void opna_reset(struct opna *opna);
void opna_writereg(struct opna *opna, unsigned reg, unsigned val);
void opna_mix(struct opna *opna, int16_t *buf, unsigned samples);
+unsigned opna_get_mask(const struct opna *opna);
+void opna_set_mask(struct opna *opna, unsigned mask);
#ifdef __cplusplus
}
diff --git a/libopna/opnaadpcm.c b/libopna/opnaadpcm.c
index 1157b56..68dbae5 100644
--- a/libopna/opnaadpcm.c
+++ b/libopna/opnaadpcm.c
@@ -185,16 +185,18 @@ void opna_adpcm_mix(struct opna_adpcm *adpcm, int16_t *buf, unsigned samples) {
if (!(adpcm->control1 & C1_START)) return;
for (unsigned i = 0; i < samples; i++) {
adpcm_calc(adpcm);
- int32_t lo = buf[i*2+0];
- int32_t ro = buf[i*2+1];
- if (adpcm->control2 & C2_L) lo += (adpcm->out>>1);
- if (adpcm->control2 & C2_R) ro += (adpcm->out>>1);
- if (lo < INT16_MIN) lo = INT16_MIN;
- if (lo > INT16_MAX) lo = INT16_MAX;
- if (ro < INT16_MIN) ro = INT16_MIN;
- if (ro > INT16_MAX) ro = INT16_MAX;
- buf[i*2+0] = lo;
- buf[i*2+1] = ro;
+ if (!adpcm->masked) {
+ int32_t lo = buf[i*2+0];
+ int32_t ro = buf[i*2+1];
+ if (adpcm->control2 & C2_L) lo += (adpcm->out>>1);
+ if (adpcm->control2 & C2_R) ro += (adpcm->out>>1);
+ if (lo < INT16_MIN) lo = INT16_MIN;
+ if (lo > INT16_MAX) lo = INT16_MAX;
+ if (ro < INT16_MIN) ro = INT16_MIN;
+ if (ro > INT16_MAX) ro = INT16_MAX;
+ buf[i*2+0] = lo;
+ buf[i*2+1] = ro;
+ }
if (!(adpcm->control1 & C1_START)) return;
}
}
diff --git a/libopna/opnaadpcm.h b/libopna/opnaadpcm.h
index 27a1349..42033ad 100644
--- a/libopna/opnaadpcm.h
+++ b/libopna/opnaadpcm.h
@@ -23,6 +23,7 @@ struct opna_adpcm {
int16_t prev_acc;
uint16_t adpcmd;
int16_t out;
+ bool masked;
};
void opna_adpcm_reset(struct opna_adpcm *adpcm);
diff --git a/libopna/opnadrum.c b/libopna/opnadrum.c
index 2527c1a..1a298af 100644
--- a/libopna/opnadrum.c
+++ b/libopna/opnadrum.c
@@ -25,6 +25,7 @@ void opna_drum_reset(struct opna_drum *drum) {
drum->drums[d].right = false;
}
drum->total_level = 0;
+ drum->mask = 0;
}
void opna_drum_set_rom(struct opna_drum *drum, void *romptr) {
@@ -90,8 +91,10 @@ void opna_drum_mix(struct opna_drum *drum, int16_t *buf, int samples) {
unsigned level = (drum->drums[d].level^0x1f) + (drum->total_level^0x3f);
co *= 15 - (level&7);
co >>= 1+(level>>3);
- if (drum->drums[d].left) lo += co;
- if (drum->drums[d].right) ro += co;
+ if (!(drum->mask & (1u << d))) {
+ if (drum->drums[d].left) lo += co;
+ if (drum->drums[d].right) ro += co;
+ }
drum->drums[d].index++;
if (drum->drums[d].index == drum->drums[d].len) {
drum->drums[d].index = 0;
diff --git a/libopna/opnadrum.h b/libopna/opnadrum.h
index 7c13098..79f95a2 100644
--- a/libopna/opnadrum.h
+++ b/libopna/opnadrum.h
@@ -40,6 +40,7 @@ struct opna_drum {
int16_t rom_hh[OPNA_ROM_HH_SIZE];
int16_t rom_tom[OPNA_ROM_TOM_SIZE];
int16_t rom_rim[OPNA_ROM_RIM_SIZE];
+ unsigned mask;
};
void opna_drum_reset(struct opna_drum *drum);
diff --git a/libopna/opnafm.c b/libopna/opnafm.c
index c7512a8..437fcdc 100644
--- a/libopna/opnafm.c
+++ b/libopna/opnafm.c
@@ -58,6 +58,7 @@ void opna_fm_reset(struct opna_fm *fm) {
fm->ch3.fnum[i] = 0;
fm->ch3.blk[i] = 0;
}
+ fm->mask = 0;
}
#define LIBOPNA_ENABLE_HIRES
// maximum output: 2042<<2 = 8168
@@ -497,6 +498,7 @@ void opna_fm_mix(struct opna_fm *fm, int16_t *buf, unsigned samples) {
opna_fm_chan_phase(&fm->channel[c]);
}
o >>= 1;
+ if (fm->mask & (1<<c)) continue;
if (fm->lselect[c]) lo += o;
if (fm->rselect[c]) ro += o;
}
diff --git a/libopna/opnafm.h b/libopna/opnafm.h
index acd673f..cf4fff5 100644
--- a/libopna/opnafm.h
+++ b/libopna/opnafm.h
@@ -78,6 +78,10 @@ struct opna_fm {
// pan
bool lselect[6];
bool rselect[6];
+
+ // mask
+ // when (1<<channel), the channel is masked
+ unsigned mask;
};
void opna_fm_reset(struct opna_fm *fm);
diff --git a/libopna/opnassg.c b/libopna/opnassg.c
index cc797b0..1345502 100644
--- a/libopna/opnassg.c
+++ b/libopna/opnassg.c
@@ -73,6 +73,7 @@ void opna_ssg_reset(struct opna_ssg *ssg) {
ssg->env_alt = false;
ssg->env_hld = false;
ssg->env_holding = false;
+ ssg->mask = 0;
}
void opna_ssg_resampler_reset(struct opna_ssg_resampler *resampler) {
@@ -171,6 +172,7 @@ void opna_ssg_generate_raw(struct opna_ssg *ssg, int16_t *buf, int samples) {
ssg->ch[ch].tone_counter = 0;
ssg->ch[ch].out = !ssg->ch[ch].out;
}
+ if (ssg->mask & (1<<ch)) continue;
#if 0
if (opna_ssg_tone_out(ssg, ch)) {
int level = opna_ssg_chan_env(ssg, ch)
diff --git a/libopna/opnassg.h b/libopna/opnassg.h
index 5928c49..adcd231 100644
--- a/libopna/opnassg.h
+++ b/libopna/opnassg.h
@@ -24,6 +24,7 @@ struct opna_ssg {
bool env_alt;
bool env_hld;
bool env_holding;
+ unsigned mask;
};
struct opna_ssg_resampler {