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
93
94
95
96
97
98
99
100
101
102
103
|
#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
enum ppz8_interp {
PPZ8_INTERP_NONE,
PPZ8_INTERP_LINEAR,
PPZ8_INTERP_SINC,
};
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;
uint8_t vol;
uint8_t pan;
uint8_t voice;
bool playing;
bool looped;
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;
enum ppz8_interp interp;
};
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);
static inline void ppz8_set_interpolation(struct ppz8 *ppz8, enum ppz8_interp interp) {
ppz8->interp = interp;
}
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
|