aboutsummaryrefslogtreecommitdiff
path: root/fmdriver/ppz8.h
blob: 35c67dca164724a6fc7fc7a6d87dcb294c04a096 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#ifndef MYON_PPZ8_H_INCLUDED
#define MYON_PPZ8_H_INCLUDED

#include <stdint.h>
#include <stdbool.h>
#include <stdatomic.h>
#include "leveldata/leveldata.h"

#ifdef __cplusplus
extern "C" {
#endif

struct ppz8_pcmvoice {
  uint32_t start;
  uint32_t len;
  uint32_t loopstart;
  uint32_t loopend;
  uint16_t origfreq;
};

struct ppz8_pcmbuf {
  int16_t *data;
  uint32_t buflen;
  struct ppz8_pcmvoice voice[128];
};

struct ppz8_channel {
  uint64_t ptr;
  uint64_t loopstartptr;
  uint64_t loopendptr;
  uint64_t endptr;
  uint32_t freq;
  uint32_t loopstartoff;
  uint32_t loopendoff;
  int16_t prevout[2];
  uint8_t vol;
  uint8_t pan;
  uint8_t voice;
  bool playing;
  struct leveldata leveldata;
};

struct ppz8 {
  struct ppz8_pcmbuf buf[2];
  struct ppz8_channel channel[8];
  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);
void ppz8_mix(struct ppz8 *ppz8, int16_t *buf, unsigned samples);
bool ppz8_pvi_load(struct ppz8 *ppz8, uint8_t buf,
                   const uint8_t *pvidata, uint32_t pvidatalen,
                   int16_t *decodebuf);
bool ppz8_pzi_load(struct ppz8 *ppz8, uint8_t bnum,
                   const uint8_t *pzidata, uint32_t pzidatalen,
                   int16_t *decodebuf);

static inline uint32_t ppz8_pvi_decodebuf_samples(uint32_t pvidatalen) {
  if (pvidatalen < 0x210) return 0;
  return (pvidatalen - 0x210) * 2;
}
static inline uint32_t ppz8_pzi_decodebuf_samples(uint32_t pzidatalen) {
  if (pzidatalen < 0x920) return 0;
  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);
  void (*channel_volume)(struct ppz8 *ppz8, uint8_t channel, uint8_t vol);
  void (*channel_freq)(struct ppz8 *ppz8, uint8_t channel, uint32_t freq);
  void (*channel_loopoffset)(struct ppz8 *ppz8, uint8_t channel,
                             uint32_t startoff, uint32_t endoff);
  void (*channel_pan)(struct ppz8 *ppz8, uint8_t channel, uint8_t pan);
  void (*total_volume)(struct ppz8 *ppz8, uint8_t vol);
  void (*channel_loop_voice)(struct ppz8 *ppz8, uint8_t channel, uint8_t voice);
  uint32_t (*voice_length)(struct ppz8 *ppz8, uint8_t voice);
};

extern const struct ppz8_functbl ppz8_functbl;

#ifdef __cplusplus
}
#endif

#endif // MYON_PPZ8_H_INCLUDED