diff options
Diffstat (limited to 'libopna')
| -rw-r--r-- | libopna/opna.c | 13 | ||||
| -rw-r--r-- | libopna/opna.h | 24 | ||||
| -rw-r--r-- | libopna/opnaadpcm.c | 22 | ||||
| -rw-r--r-- | libopna/opnaadpcm.h | 1 | ||||
| -rw-r--r-- | libopna/opnadrum.c | 7 | ||||
| -rw-r--r-- | libopna/opnadrum.h | 1 | ||||
| -rw-r--r-- | libopna/opnafm.c | 2 | ||||
| -rw-r--r-- | libopna/opnafm.h | 4 | ||||
| -rw-r--r-- | libopna/opnassg.c | 2 | ||||
| -rw-r--r-- | libopna/opnassg.h | 1 | 
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 { | 
