ScummVM API documentation
opl_class.h
1/* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21
22#ifndef NUVIE_SOUND_ADPLUG_OPL_CLASS_H
23#define NUVIE_SOUND_ADPLUG_OPL_CLASS_H
24
25#include "ultima/nuvie/sound/adplug/opl.h"
26
27namespace Ultima {
28namespace Nuvie {
29
30#define HAS_YM3812 1
31#define HAS_YM3526 0
32#define HAS_Y8950 0
33
34/* --- select emulation chips --- */
35#define BUILD_YM3812 (HAS_YM3812)
36#define BUILD_YM3526 (HAS_YM3526)
37#define BUILD_Y8950 (HAS_Y8950)
38
39/* select output bits size of output : 8 or 16 */
40#define OPL_SAMPLE_BITS 16
41
42#if (OPL_SAMPLE_BITS==16)
43typedef int16 OPLSAMPLE;
44#endif
45#if (OPL_SAMPLE_BITS==8)
46typedef int8 OPLSAMPLE;
47#endif
48
49
50typedef void (*OPL_TIMERHANDLER)(int channel, double interval_Sec);
51typedef void (*OPL_IRQHANDLER)(int param, int irq);
52typedef void (*OPL_UPDATEHANDLER)(int param, int min_interval_us);
53typedef void (*OPL_PORTHANDLER_W)(int param, unsigned char data);
54typedef unsigned char (*OPL_PORTHANDLER_R)(int param);
55
56/* Saving is necessary for member of the 'R' mark for suspend/resume */
57
58typedef struct {
59 uint32 ar; /* attack rate: AR<<2 */
60 uint32 dr; /* decay rate: DR<<2 */
61 uint32 rr; /* release rate:RR<<2 */
62 uint8 KSR; /* key scale rate */
63 uint8 ksl; /* keyscale level */
64 uint8 ksr; /* key scale rate: kcode>>KSR */
65 uint8 mul; /* multiple: mul_tab[ML] */
66
67 /* Phase Generator */
68 uint32 Cnt; /* frequency counter */
69 uint32 Incr; /* frequency counter step */
70 uint8 FB; /* feedback shift value */
71 signed int *connect1; /* slot1 output pointer */
72 int32 op1_out[2]; /* slot1 output for feedback */
73 uint8 CON; /* connection (algorithm) type */
74
75 /* Envelope Generator */
76 uint8 eg_type; /* percussive/non-percussive mode */
77 uint8 state; /* phase type */
78 uint32 TL; /* total level: TL << 2 */
79 int32 TLL; /* adjusted now TL */
80 int32 volume; /* envelope counter */
81 uint32 sl; /* sustain level: sl_tab[SL] */
82
83 uint8 eg_sh_ar; /* (attack state) */
84 uint8 eg_sel_ar; /* (attack state) */
85 uint8 eg_sh_dr; /* (decay state) */
86 uint8 eg_sel_dr; /* (decay state) */
87 uint8 eg_sh_rr; /* (release state) */
88 uint8 eg_sel_rr; /* (release state) */
89
90 uint32 key; /* 0 = KEY OFF, >0 = KEY ON */
91
92 /* LFO */
93 uint32 AMmask; /* LFO Amplitude Modulation enable mask */
94 uint8 vib; /* LFO Phase Modulation enable flag (active high)*/
95
96 /* waveform select */
97 unsigned int wavetable;
98} OPL_SLOT;
99
100typedef struct {
101 OPL_SLOT SLOT[2];
102 /* phase generator state */
103 uint32 block_fnum; /* block+fnum */
104 uint32 fc; /* Freq. Increment base */
105 uint32 ksl_base; /* KeyScaleLevel Base step */
106 uint8 kcode; /* key code (for key scaling) */
107} OPL_CH;
108
109/* OPL state */
110typedef struct fm_opl_f {
111 /* FM channel slots */
112 OPL_CH P_CH[9]; /* OPL/OPL2 chips have 9 channels*/
113
114 uint32 eg_cnt; /* global envelope generator counter */
115 uint32 eg_timer; /* global envelope generator counter works at frequency = chipclock/72 */
116 uint32 eg_timer_add; /* step of eg_timer */
117 uint32 eg_timer_overflow; /* envelope generator timer overlfows every 1 sample (on real chip) */
118
119 uint8 rhythm; /* Rhythm mode */
120
121 uint32 fn_tab[1024]; /* fnumber->increment counter */
122
123 /* LFO */
124 uint8 lfo_am_depth;
125 uint8 lfo_pm_depth_range;
126 uint32 lfo_am_cnt;
127 uint32 lfo_am_inc;
128 uint32 lfo_pm_cnt;
129 uint32 lfo_pm_inc;
130
131 uint32 noise_rng; /* 23 bit noise shift register */
132 uint32 noise_p; /* current noise 'phase' */
133 uint32 noise_f; /* current noise period */
134
135 uint8 wavesel; /* waveform select enable flag */
136
137 int T[2]; /* timer counters */
138 uint8 st[2]; /* timer enable */
139
140 /* external event callback handlers */
141 OPL_TIMERHANDLER TimerHandler; /* TIMER handler */
142 int TimerParam; /* TIMER parameter */
143 OPL_IRQHANDLER IRQHandler; /* IRQ handler */
144 int IRQParam; /* IRQ parameter */
145 OPL_UPDATEHANDLER UpdateHandler;/* stream update handler */
146 int UpdateParam; /* stream update parameter */
147
148 uint8 type; /* chip type */
149 uint8 address; /* address register */
150 uint8 status; /* status flag */
151 uint8 statusmask; /* status mask */
152 uint8 mode; /* Reg.08 : CSM,notesel,etc. */
153
154 int clock; /* master clock (Hz) */
155 int rate; /* sampling rate (Hz) */
156 double freqbase; /* frequency base */
157 double TimerBase; /* Timer base time (==sampling time)*/
158} FM_OPL;
159
160#define MAX_OPL_CHIPS 2
161
162/* sinwave entries */
163#define SIN_BITS 10
164#define SIN_LEN (1<<SIN_BITS)
165#define SIN_MASK (SIN_LEN-1)
166
167#define TL_RES_LEN (256) /* 8 bits addressing (real chip) */
168
169/* TL_TAB_LEN is calculated as:
170* 12 - sinus amplitude bits (Y axis)
171* 2 - sinus sign bit (Y axis)
172* TL_RES_LEN - sinus resolution (X axis)
173*/
174#define TL_TAB_LEN (12*2*TL_RES_LEN)
175
176class OplClass: public Copl {
177private:
178
179 FM_OPL *OPL_YM3812[MAX_OPL_CHIPS]; /* array of pointers to the YM3812's */
180 int YM3812NumChips; /* number of chips */
181
182 signed int tl_tab[TL_TAB_LEN];
183
184 /* sin waveform table in 'decibel' scale */
185 /* four waveforms on OPL2 type chips */
186 unsigned int sin_tab[SIN_LEN * 4];
187
188 /* lock level of common table */
189 int num_lock;
190
191 /* work table */
192 void *cur_chip; /* current chip point */
193 OPL_SLOT *SLOT7_1, *SLOT7_2, *SLOT8_1, *SLOT8_2;
194
195 signed int phase_modulation; /* phase modulation input (SLOT 2) */
196 signed int output[1];
197
198 uint32 LFO_AM;
199 int32 LFO_PM;
200
201 bool use16bit, stereo;
202 int oplRate;
203
204public:
205 OplClass(int rate, bool bit16, bool usestereo); // rate = sample rate
206 ~OplClass() override {
207 YM3812Shutdown();
208 }
209
210 int getRate() {
211 return oplRate;
212 }
213
214 void update(short *buf, int samples); // fill buffer
215
216 // template methods
217 void write(int reg, int val) override;
218 void init() override;
219
220private:
221 int YM3812Init(int num, int clock, int rate);
222 void YM3812Shutdown(void);
223 void YM3812ResetChip(int which);
224 int YM3812Write(int which, int a, int v);
225 unsigned char YM3812Read(int which, int a);
226 int YM3812TimerOver(int which, int c);
227 void YM3812UpdateOne(int which, int16 *buffer, int length);
228
229 void YM3812SetTimerHandler(int which, OPL_TIMERHANDLER TimerHandler, int channelOffset);
230 void YM3812SetIRQHandler(int which, OPL_IRQHANDLER IRQHandler, int param);
231 void YM3812SetUpdateHandler(int which, OPL_UPDATEHANDLER UpdateHandler, int param);
232
233 int init_tables(void);
234 void OPLWriteReg(FM_OPL *OPL, int r, int v);
235 void OPLResetChip(FM_OPL *OPL);
236 int OPL_LockTable(void);
237 FM_OPL *OPLCreate(int type, int clock, int rate);
238 void OPL_UnLockTable(void);
239 void OPLDestroy(FM_OPL *OPL);
240 int OPLWrite(FM_OPL *OPL, int a, int v);
241
242 inline void advance_lfo(FM_OPL *OPL);
243 inline void advancex(FM_OPL *OPL);
244 inline signed int op_calc(uint32 phase, unsigned int env, signed int pm, unsigned int wave_tab);
245 inline signed int op_calc1(uint32 phase, unsigned int env, signed int pm, unsigned int wave_tab);
246 inline void OPL_CALC_CH(OPL_CH *CH);
247 inline void OPL_CALC_RH(OPL_CH *CH, unsigned int noise);
248};
249
250} // End of namespace Nuvie
251} // End of namespace Ultima
252
253#endif
Definition: opl.h:30
Definition: opl_class.h:176
Definition: opl_class.h:100
Definition: opl_class.h:58
Definition: opl_class.h:110