-
Notifications
You must be signed in to change notification settings - Fork 0
/
opl_voice.c
124 lines (110 loc) · 4.78 KB
/
opl_voice.c
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#include "opl_voice.h"
#include <string.h>
#include <math.h>
#ifdef HAVE_STDIO
#include <stdio.h>
#endif
#include "opm_voice.h"
#include "opn_voice.h"
void opl_voice_init(struct opl_voice *v) {
memset(v, 0, sizeof(*v));
}
#ifdef HAVE_STDIO
void opl_voice_dump(struct opl_voice *v) {
printf("name=%.256s\n", v->name);
printf("4OP=%d percussion=%d\n", v->en_4op, v->perc_inst);
for(int i = 0; i < 2; i++) {
printf(
"%d: ch=%c%c%c%c fb=%d c=%d ",
i,
v->ch_fb_cnt[i] & 0x80 ? 'D' : '-',
v->ch_fb_cnt[i] & 0x40 ? 'C' : '-',
v->ch_fb_cnt[i] & 0x20 ? 'B' : '-',
v->ch_fb_cnt[i] & 0x10 ? 'A' : '-',
v->ch_fb_cnt[i] >> 1 & 0x07,
v->ch_fb_cnt[i] & 0x01
);
}
printf("\n");
printf("DAM=%d DVB=%d RYT=%d BD=%d SD=%d TOM=%d TC=%d HH=%d\n",
v->dam_dvb_ryt_bd_sd_tom_tc_hh >> 7,
v->dam_dvb_ryt_bd_sd_tom_tc_hh >> 6 & 1,
v->dam_dvb_ryt_bd_sd_tom_tc_hh >> 5 & 1,
v->dam_dvb_ryt_bd_sd_tom_tc_hh >> 4 & 1,
v->dam_dvb_ryt_bd_sd_tom_tc_hh >> 3 & 1,
v->dam_dvb_ryt_bd_sd_tom_tc_hh >> 2 & 1,
v->dam_dvb_ryt_bd_sd_tom_tc_hh >> 1 & 1,
v->dam_dvb_ryt_bd_sd_tom_tc_hh & 1
);
printf("OP: AR DR SL RR TL MUL EG AM VIB KSR KSL WS\n");
for(int i = 0; i < 4; i++) {
if(!v->en_4op && i >= 2) break;
struct opl_voice_operator *op = &v->operators[i];
printf(
"%2d: %2d %2d %2d %2d %2d %3d %2d %2d %3d %3d %3d %2d\n",
i,
op->ar_dr >> 4,
op->ar_dr & 0x0f,
op->sl_rr >> 4,
op->sl_rr & 0x0f,
op->ksl_tl & 0x3f,
op->am_vib_eg_ksr_mul & 0x0f,
op->am_vib_eg_ksr_mul >> 5 & 1,
op->am_vib_eg_ksr_mul >> 7,
op->am_vib_eg_ksr_mul >> 6 & 1,
op->am_vib_eg_ksr_mul >> 4 & 1,
op->ksl_tl >> 6,
op->ws & 0x07
);
}
}
#endif
void opl_voice_normalize(struct opl_voice *v) {
}
int opl_voice_compare(struct opl_voice *v1, struct opl_voice *v2) {
return -1;
}
int opl_operator_is_silent(struct opl_voice_operator *op) {
return (op->ar_dr >> 4) < 1 || op->ksl_tl > 60; // approximation
}
int opl_voice_is_silent(struct opl_voice *v) {
return 0;
}
int opl_voice_load_opm_voice(struct opl_voice *oplv, struct opm_voice *opmv) {
return 0;
}
int opl_voice_load_opn_voice(struct opl_voice *oplv, struct opn_voice *opnv) {
return 0;
}
int opl_pitch_to_block_fnum(float pitch, int clock) {
uint8_t octave = (69 + 12 * log2(pitch / 440.0)) / 12 - 1;
uint16_t fnum = (144 * pitch * (1 << 18) / clock) / (1 << (octave - 1));
return octave << 11 | (fnum & 0x7ff);
}
float opl_block_fnum_to_pitch(uint8_t block_fnum2, uint8_t fnum1, int clock) {
int block = block_fnum2 >> 3;
int fnum = (block_fnum2 & 0x07) << 8 | fnum1;
return (float)fnum * (float)clock * powf(2.0, block - 19.0) / 144.0;
}
uint8_t opl_voice_get_ch(struct opl_voice *v) { return v->ch_fb_cnt[0] >> 4; }
uint8_t opl_voice_get_fb(struct opl_voice *v) { return v->ch_fb_cnt[0] >> 1 & 0x07; }
uint8_t opl_voice_get_cnt(struct opl_voice *v) { return v->ch_fb_cnt[0] & 0x01; }
uint8_t opl_voice_get_ch1(struct opl_voice *v) { return v->ch_fb_cnt[1] >> 4; }
uint8_t opl_voice_get_fb1(struct opl_voice *v) { return v->ch_fb_cnt[1] >> 1 & 0x07; }
uint8_t opl_voice_get_cnt1(struct opl_voice *v) { return v->ch_fb_cnt[1] & 0x01; }
uint8_t opl_voice_get_am_depth(struct opl_voice *v) { return v->dam_dvb_ryt_bd_sd_tom_tc_hh >> 7; }
uint8_t opl_voice_get_vib_depth(struct opl_voice *v) { return v->dam_dvb_ryt_bd_sd_tom_tc_hh >> 6 & 0x01; }
uint8_t opl_voice_get_ryt(struct opl_voice *v) { return v->dam_dvb_ryt_bd_sd_tom_tc_hh >> 5 & 0x01; }
uint8_t opl_voice_get_perc(struct opl_voice *v) { return v->dam_dvb_ryt_bd_sd_tom_tc_hh >> 4 & 0x1f; }
uint8_t opl_voice_operator_get_am(struct opl_voice *v, int op) { return v->operators[op].am_vib_eg_ksr_mul >> 7; }
uint8_t opl_voice_operator_get_vib(struct opl_voice *v, int op) { return v->operators[op].am_vib_eg_ksr_mul >> 6 & 0x01; }
uint8_t opl_voice_operator_get_eg_typ(struct opl_voice *v, int op) { return v->operators[op].am_vib_eg_ksr_mul >> 5 & 0x01; }
uint8_t opl_voice_operator_get_ksr(struct opl_voice *v, int op) { return v->operators[op].am_vib_eg_ksr_mul >> 4 & 0x01; }
uint8_t opl_voice_operator_get_mul(struct opl_voice *v, int op) { return v->operators[op].am_vib_eg_ksr_mul & 0x0f; }
uint8_t opl_voice_operator_get_ksl(struct opl_voice *v, int op) { return v->operators[op].ksl_tl >> 6; }
uint8_t opl_voice_operator_get_tl(struct opl_voice *v, int op) { return v->operators[op].ksl_tl & 0x3f; }
uint8_t opl_voice_operator_get_ar(struct opl_voice *v, int op) { return v->operators[op].ar_dr >> 4; }
uint8_t opl_voice_operator_get_dr(struct opl_voice *v, int op) { return v->operators[op].ar_dr & 0x0f; }
uint8_t opl_voice_operator_get_sl(struct opl_voice *v, int op) { return v->operators[op].sl_rr >> 4; }
uint8_t opl_voice_operator_get_rr(struct opl_voice *v, int op) { return v->operators[op].sl_rr & 0x0f; }
uint8_t opl_voice_operator_get_ws(struct opl_voice *v, int op) { return v->operators[op].ws & 0x07; }