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 
27 namespace Ultima {
28 namespace 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)
43 typedef int16 OPLSAMPLE;
44 #endif
45 #if (OPL_SAMPLE_BITS==8)
46 typedef int8 OPLSAMPLE;
47 #endif
48 
49 
50 typedef void (*OPL_TIMERHANDLER)(int channel, double interval_Sec);
51 typedef void (*OPL_IRQHANDLER)(int param, int irq);
52 typedef void (*OPL_UPDATEHANDLER)(int param, int min_interval_us);
53 typedef void (*OPL_PORTHANDLER_W)(int param, unsigned char data);
54 typedef unsigned char (*OPL_PORTHANDLER_R)(int param);
55 
56 /* Saving is necessary for member of the 'R' mark for suspend/resume */
57 
58 typedef 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 
100 typedef 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 */
110 typedef 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 
176 class OplClass: public Copl {
177 private:
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 
204 public:
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 
220 private:
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: detection.h:27
Definition: opl_class.h:110
Definition: opl_class.h:176
Definition: fmopl.h:35
Definition: opl_class.h:100
Definition: opl_class.h:58