1 /*
2  * libOPNMIDI is a free Software MIDI synthesizer library with OPN2 (YM2612) emulation
3  *
4  * MIDI parser and player (Original code from ADLMIDI): Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi>
5  * OPNMIDI Library and YM2612 support:   Copyright (c) 2017-2020 Vitaly Novichkov <admin@wohlnet.ru>
6  *
7  * Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
8  * http://iki.fi/bisqwit/source/adlmidi.html
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  */
23 
24 #ifndef OPNMIDI_OPN2_HPP
25 #define OPNMIDI_OPN2_HPP
26 
27 #include "opnbank.h"
28 #include "opnmidi_ptr.hpp"
29 #include "opnmidi_private.hpp"
30 #include "opnmidi_bankmap.h"
31 #include "chips/opn_chip_family.h"
32 
33 /**
34  * @brief OPN2 Chip management class
35  */
36 class OPN2
37 {
38     friend class OPNMIDIplay;
39 public:
40     enum { PercussionTag = 1 << 15 };
41 
42     //! Total number of chip channels between all running emulators
43     uint32_t m_numChannels;
44     //! Just a padding. Reserved.
45     char _padding[4];
46     //! Running chip emulators
47     std::vector<AdlMIDI_SPtr<OPNChipBase > > m_chips;
48 #ifdef OPNMIDI_MIDI2VGM
49     //! Loop Start hook
50     void (*m_loopStartHook)(void*);
51     //! Loop Start hook data
52     void *m_loopStartHookData;
53     //! Loop End hook
54     void (*m_loopEndHook)(void*);
55     //! Loop End hook data
56     void *m_loopEndHookData;
57 #endif
58 private:
59     //! Cached patch data, needed by Touch()
60     std::vector<OpnTimbre>    m_insCache;
61     //! Cached per-channel LFO sensitivity flags
62     std::vector<uint8_t>        m_regLFOSens;
63     //! LFO setup registry cache
64     uint8_t                     m_regLFOSetup;
65 
66 public:
67     /**
68      * @brief MIDI bank entry
69      */
70     struct Bank
71     {
72         //! MIDI Bank instruments
73         OpnInstMeta ins[128];
74     };
75     typedef BasicBankMap<Bank> BankMap;
76     //! MIDI bank instruments data
77     BankMap         m_insBanks;
78     //! MIDI bank-wide setup
79     OpnBankSetup    m_insBankSetup;
80 
81 public:
82     //! Blank instrument template
83     static const OpnInstMeta m_emptyInstrument;
84 
85     //! Total number of running concurrent emulated chips
86     uint32_t m_numChips;
87     //! Carriers-only are scaled by default by volume level. This flag will tell to scale modulators too.
88     bool m_scaleModulators;
89     //! Run emulator at PCM rate if that possible. Reduces sounding accuracy, but decreases CPU usage on lower rates.
90     bool m_runAtPcmRate;
91     //! Enable soft panning
92     bool m_softPanning;
93     //! Master volume, controlled via SysEx (0...127)
94     uint8_t m_masterVolume;
95 
96     //! Just a padding. Reserved.
97     char _padding2[3];
98 
99     /**
100      * @brief Music playing mode
101      */
102     enum MusicMode
103     {
104         //! MIDI mode
105         MODE_MIDI,
106         //! MIDI mode
107         MODE_XMIDI,
108         //! Id-Software Music mode
109         MODE_IMF,
110         //! Creative Music Files mode
111         MODE_CMF,
112         //! EA-MUS (a.k.a. RSXX) mode
113         MODE_RSXX
114     } m_musicMode;
115 
116     /**
117      * @brief Volume models enum
118      */
119     enum VolumesScale
120     {
121         //! Generic volume model (linearization of logarithmic scale)
122         VOLUME_Generic,
123         //! OPN2 native logarithmic scale
124         VOLUME_NATIVE,
125         //! DMX volume scale logarithmic table
126         VOLUME_DMX,
127         //! Apoge Sound System volume scaling model
128         VOLUME_APOGEE,
129         //! Windows 9x driver volume scale table
130         VOLUME_9X
131     } m_volumeScale;
132 
133     //! Reserved
134     bool m_lfoEnable;
135     uint8_t m_lfoFrequency;
136 
137     //! Category of the channel
138     /*! 1 = DAC, 0 = regular
139     */
140     std::vector<char> m_channelCategory;
141 
142     //! Chip family
143     OPNFamily m_chipFamily;
144 
145     /**
146      * @brief C.O. Constructor
147      */
148     OPN2();
149 
150     /**
151      * @brief C.O. Destructor
152      */
153     ~OPN2();
154 
155     /**
156      * @brief Checks are setup locked to be changed on the fly or not
157      * @return true when setup on the fly is locked
158      */
159     bool setupLocked();
160 
161     /**
162      * @brief Write data to OPN2 chip register
163      * @param chip Index of emulated chip. In hardware OPN2 builds, this parameter is ignored
164      * @param port Port of the chip to write
165      * @param index Register address to write
166      * @param value Value to write
167      */
168     void writeReg(size_t chip, uint8_t port, uint8_t index, uint8_t value);
169 
170     /**
171      * @brief Write data to OPN2 chip register
172      * @param chip Index of emulated chip. In hardware OPN2 builds, this parameter is ignored
173      * @param port Port of the chip to write
174      * @param index Register address to write
175      * @param value Value to write
176      */
177     void writeRegI(size_t chip, uint8_t port, uint32_t index, uint32_t value);
178 
179     /**
180      * @brief Write to soft panning control of OPN2 chip emulator
181      * @param chip Index of emulated chip.
182      * @param address Register of channel to write
183      * @param value Value to write
184      */
185     void writePan(size_t chip, uint32_t index, uint32_t value);
186 
187     /**
188      * @brief Off the note in specified chip channel
189      * @param c Channel of chip (Emulated chip choosing by next formula: [c = ch + (chipId * 23)])
190      */
191     void noteOff(size_t c);
192 
193     /**
194      * @brief On the note in specified chip channel with specified frequency of the tone
195      * @param c Channel of chip (Emulated chip choosing by next formula: [c = ch + (chipId * 23)])
196      * @param tone The tone to play (integer part - MIDI halftone, decimal part - relative bend offset)
197      */
198     void noteOn(size_t c, double tone);
199 
200     /**
201      * @brief Change setup of instrument in specified chip channel
202      * @param c Channel of chip (Emulated chip choosing by next formula: [c = ch + (chipId * 23)])
203      * @param volume Volume level (from 0 to 127)
204      * @param brightness CC74 Brightness level (from 0 to 127)
205      */
206     void touchNote(size_t c,
207                    uint_fast32_t velocity,
208                    uint_fast32_t channelVolume = 127,
209                    uint_fast32_t channelExpression = 127,
210                    uint8_t brightness = 127);
211 
212     /**
213      * @brief Set the instrument into specified chip channel
214      * @param c Channel of chip (Emulated chip choosing by next formula: [c = ch + (chipId * 23)])
215      * @param instrument Instrument data to set into the chip channel
216      */
217     void setPatch(size_t c, const OpnTimbre &instrument);
218 
219     /**
220      * @brief Set panpot position
221      * @param c Channel of chip (Emulated chip choosing by next formula: [c = ch + (chipId * 23)])
222      * @param value 3-bit panpot value
223      */
224     void setPan(size_t c, uint8_t value);
225 
226     /**
227      * @brief Shut up all chip channels
228      */
229     void silenceAll();
230 
231     /**
232      * @brief commit LFO enable and frequency
233      */
234     void commitLFOSetup();
235 
236     /**
237      * @brief Set the volume scaling model
238      * @param volumeModel Type of volume scale model scale
239      */
240     void setVolumeScaleModel(OPNMIDI_VolumeModels volumeModel);
241 
242     /**
243      * @brief Get the volume scaling model
244      */
245     OPNMIDI_VolumeModels getVolumeScaleModel();
246 
247     /**
248      * @brief Clean up all running emulated chip instances
249      */
250     void clearChips();
251 
252     /**
253      * @brief Reset chip properties and initialize them
254      * @param emulator Type of chip emulator
255      * @param PCM_RATE Output sample rate to generate on output
256      * @param audioTickHandler PCM-accurate clock hook
257      */
258     void reset(int emulator, unsigned long PCM_RATE, OPNFamily family, void *audioTickHandler);
259 
260     /**
261      * @brief Gets the family of current chips
262      * @return the chip family
263      */
264     OPNFamily chipFamily() const;
265 };
266 
267 /**
268  * @brief Check emulator availability
269  * @param emulator Emulator ID (Opn2_Emulator)
270  * @return true when emulator is available
271  */
272 extern bool opn2_isEmulatorAvailable(int emulator);
273 
274 /**
275  * @brief Find highest emulator
276  * @return The Opn2_Emulator enum value which contains ID of highest emulator
277  */
278 extern int opn2_getHighestEmulator();
279 
280 /**
281  * @brief Find lowest emulator
282  * @return The Opn2_Emulator enum value which contains ID of lowest emulator
283  */
284 extern int opn2_getLowestEmulator();
285 
286 #endif // OPNMIDI_OPN2_HPP
287