diff options
| author | Takamichi Horikawa <takamichiho@gmail.com> | 2017-04-03 22:19:14 +0900 | 
|---|---|---|
| committer | Takamichi Horikawa <takamichiho@gmail.com> | 2017-04-03 22:19:49 +0900 | 
| commit | fd698bc65313888c689877128d4b489c64f2e85f (patch) | |
| tree | 0ad39ba217b1b43ffa1156f7ab81fcb6b186b9aa /fmdriver | |
| parent | 4e4ba88b67cc9e891a69d65bbde460e1ba51a39e (diff) | |
pmd: fix PPZ8 loop
Diffstat (limited to 'fmdriver')
| -rw-r--r-- | fmdriver/fmdriver_common.c | 32 | ||||
| -rw-r--r-- | fmdriver/fmdriver_common.h | 1 | ||||
| -rw-r--r-- | fmdriver/fmdriver_pmd.c | 45 | ||||
| -rw-r--r-- | fmdriver/fmdriver_pmd.h | 2 | ||||
| -rw-r--r-- | fmdriver/ppz8.c | 13 | ||||
| -rw-r--r-- | fmdriver/ppz8.h | 4 | 
6 files changed, 91 insertions, 6 deletions
| diff --git a/fmdriver/fmdriver_common.c b/fmdriver/fmdriver_common.c index 26e6def..b919c3a 100644 --- a/fmdriver/fmdriver_common.c +++ b/fmdriver/fmdriver_common.c @@ -69,3 +69,35 @@ uint8_t fmdriver_ssg_freq2key(uint16_t freq) {    if (octave > 8) return 0x8b;    return (octave << 4) | note;  } + +uint8_t fmdriver_ppz8_freq2key(uint32_t freq) { +  if (!freq) return 0x00; +  int octave = 16+4; +  while (!(freq & 0x80000000u)) { +    freq <<= 1; +    octave--; +  } +  if (octave < 0) return 0x00; +  if (octave > 8) return 0x8b; +  // round(0x8000*(2**((i+0.5)/12))) +  static const uint16_t freqtab[0xc] = { +    0x83c0, +    0x8b96, +    0x93e3, +    0x9cae, +    0xa5ff, +    0xafde, +    0xba53, +    0xc567, +    0xd124, +    0xdd94, +    0xeac1, +    0xf8b6 +  }; +  uint16_t freqhigh = freq >> 16; +  int note = 0; +  for (; note < 12; note++) { +    if (freqhigh < freqtab[note]) break; +  } +  return (octave << 4) | note; +} diff --git a/fmdriver/fmdriver_common.h b/fmdriver/fmdriver_common.h index 30cf12c..99679cb 100644 --- a/fmdriver/fmdriver_common.h +++ b/fmdriver/fmdriver_common.h @@ -35,6 +35,7 @@ static inline void fmdriver_fillpcmname(char *dest, const char *src) {  uint8_t fmdriver_fm_freq2key(uint16_t freq);  uint8_t fmdriver_ssg_freq2key(uint16_t freq); +uint8_t fmdriver_ppz8_freq2key(uint32_t freq);  #if 0  #include <stdio.h> diff --git a/fmdriver/fmdriver_pmd.c b/fmdriver/fmdriver_pmd.c index 09630bf..7090fc8 100644 --- a/fmdriver/fmdriver_pmd.c +++ b/fmdriver/fmdriver_pmd.c @@ -45,6 +45,41 @@ enum {  // 0790: PPZ8 +static uint8_t pmd_adpcm_freq2key(uint16_t freq) { +  if (!freq) return 0x00; +  static const uint16_t freqtab[12] = { +    0x8738, // e upper limit +    0x8f42, +    0x97c7, +    0xa0cd, +    0xaa5d, +    0xb47e, +    0xbf3a, +    0xca99, +    0xd6a5, +    0xe369, +    0xf0ee, +    0xff42, +  }; +  int octave = 5; +  while (!(freq & 0x8000u)) { +    freq <<= 1; +    octave -= 1; +  } +  int key = 0; +  for (; key < 12; key++) { +    if (freq < freqtab[key]) break; +  } +  key += 5; +  if (key >= 12) { +    key -= 12; +    octave++; +  } +  if (octave < 0) return 0x00; +  if (octave > 8) return 0x8b; +  return (octave << 4) | key; +} +  // 33f7: write standard  // 341f: write extended  // 3447 @@ -1299,6 +1334,7 @@ static void pmd_note_freq_adpcm(    static const uint16_t adpcm_tonetable[0x10] = {      // 0788      // ??? +    // different from round((16000*2*0x10000/(8000000/144))*(2**((i-7)/12)))      0x6264,      0x6840,      0x6e74, @@ -1306,7 +1342,7 @@ static void pmd_note_freq_adpcm(      0x7bfc,      0x835e,      0x8b2e, -    0x9376, +    0x9376,// g      0x9c3c,      0xa588,      0xaf62, @@ -1783,6 +1819,7 @@ static void pmd_adpcm_freq_out(    if (newfreq > 0xffff) newfreq = 0xffff;    if (newfreq < 0) newfreq = 0;    freq = newfreq; +  part->output_freq = freq;    work->opna_writereg(work, 0x109, freq);    work->opna_writereg(work, 0x10a, freq >> 8);  } @@ -1809,6 +1846,7 @@ static void pmd_ppz8_freq_out(    int64_t outfreq = freq + det;    if (outfreq < 0) outfreq = 0;    if (outfreq > INT32_MAX) outfreq = INT32_MAX; +  part->output_freq = outfreq;    if (work->ppz8) {      work->ppz8_functbl->channel_freq(work->ppz8, pmd->proc_ch, outfreq);    } @@ -5680,9 +5718,12 @@ static void pmd_work_status_update(        }        break;      case PART_TYPE_ADPCM: -      //track->playing = false; +      track->actual_key = ((track->key & 0xf) == 0xf) ? +        0xff : pmd_adpcm_freq2key(part->output_freq);        break;      case PART_TYPE_PPZ8: +      track->actual_key = ((track->key & 0xf) == 0xf) ? +        0xff : fmdriver_ppz8_freq2key(part->output_freq);        break;      }    } diff --git a/fmdriver/fmdriver_pmd.h b/fmdriver/fmdriver_pmd.h index 708dd9e..25d42d7 100644 --- a/fmdriver/fmdriver_pmd.h +++ b/fmdriver/fmdriver_pmd.h @@ -238,7 +238,7 @@ struct pmd_part {    bool proc_masked;    // for display    uint8_t len; -  uint16_t output_freq; +  uint32_t output_freq;  };  struct pmd_ssgeff_data { diff --git a/fmdriver/ppz8.c b/fmdriver/ppz8.c index 7540ca0..4dea524 100644 --- a/fmdriver/ppz8.c +++ b/fmdriver/ppz8.c @@ -1,8 +1,14 @@  #include "ppz8.h"  #include "fmdriver_common.h" -//#include <stdio.h>  #include <string.h> +unsigned ppz8_get_mask(const struct ppz8 *ppz8) { +  return ppz8->mask; +} +void ppz8_set_mask(struct ppz8 *ppz8, unsigned mask) { +  ppz8->mask = mask & 0xffu; +} +  void ppz8_init(struct ppz8 *ppz8, uint16_t srate, uint16_t mix_volume) {    for (int i = 0; i < 2; i++) {      struct ppz8_pcmbuf *buf = &ppz8->buf[i]; @@ -143,6 +149,7 @@ void ppz8_mix(struct ppz8 *ppz8, int16_t *buf, unsigned samples) {        struct ppz8_channel *channel = &ppz8->channel[p];        if (!channel->playing) continue;        int32_t out = ppz8_channel_calc(ppz8, channel); +      if ((1u << p) & (ppz8->mask)) continue;        out *= ppz8->mix_volume;        out >>= 15;        lo += (out * pan_vol[channel->pan][0]) >> 2; @@ -317,8 +324,8 @@ static void ppz8_channel_loop_voice(struct ppz8 *ppz8, uint8_t ch, uint8_t v) {    struct ppz8_channel *channel = &ppz8->channel[ch];    struct ppz8_pcmbuf *buf = &ppz8->buf[v>>7];    struct ppz8_pcmvoice *voice = &buf->voice[v & 0x7f]; -  channel->loopstartptr = ((uint64_t)(voice->loopstart)>>1)<<16; -  channel->loopendptr = ((uint64_t)(voice->loopend)>>1)<<16; +  channel->loopstartoff = voice->loopstart; +  channel->loopendoff = voice->loopend;  }  static uint32_t ppz8_voice_length(struct ppz8 *ppz8, uint8_t v) { diff --git a/fmdriver/ppz8.h b/fmdriver/ppz8.h index cb9a158..f4ef4cb 100644 --- a/fmdriver/ppz8.h +++ b/fmdriver/ppz8.h @@ -43,6 +43,7 @@ struct ppz8 {    uint16_t srate;    uint8_t totalvol;    uint16_t mix_volume; +  unsigned mask;  };  void ppz8_init(struct ppz8 *ppz8, uint16_t srate, uint16_t mix_volume); @@ -63,6 +64,9 @@ static inline uint32_t ppz8_pzi_decodebuf_samples(uint32_t pzidatalen) {    return (pzidatalen - 0x920) * 2;  } +unsigned ppz8_get_mask(const struct ppz8 *ppz8); +void ppz8_set_mask(struct ppz8 *ppz8, unsigned mask); +  struct ppz8_functbl {    void (*channel_play)(struct ppz8 *ppz8, uint8_t channel, uint8_t voice);    void (*channel_stop)(struct ppz8 *ppz8, uint8_t channel); | 
