1 /*
2  * Interfaces over Yamaha OPN2 (YM2612) chip emulators
3  *
4  * Copyright (c) 2017-2020 Vitaly Novichkov (Wohlstand)
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #ifndef ONP_CHIP_BASE_H
22 #define ONP_CHIP_BASE_H
23 
24 #include "opn_chip_family.h"
25 #include <stdint.h>
26 #include <stddef.h>
27 
28 #if !defined(_MSC_VER) && (__cplusplus <= 199711L)
29 #define final
30 #define override
31 #endif
32 
33 #if defined(OPNMIDI_ENABLE_HQ_RESAMPLER)
34 class VResampler;
35 #endif
36 
37 #if defined(OPNMIDI_AUDIO_TICK_HANDLER)
38 extern void opn2_audioTickHandler(void *instance, uint32_t chipId, uint32_t rate);
39 #endif
40 
41 class OPNChipBase
42 {
43 protected:
44     uint32_t m_id;
45     uint32_t m_rate;
46     uint32_t m_clock;
47     OPNFamily m_family;
48 public:
49     explicit OPNChipBase(OPNFamily f);
50     virtual ~OPNChipBase();
51 
52     virtual OPNFamily family() const = 0;
53     uint32_t clockRate() const;
54     virtual uint32_t nativeClockRate() const = 0;
55 
chipId()56     uint32_t chipId() const { return m_id; }
setChipId(uint32_t id)57     void setChipId(uint32_t id) { m_id = id; }
58 
59     virtual bool canRunAtPcmRate() const = 0;
60     virtual bool isRunningAtPcmRate() const = 0;
61     virtual bool setRunningAtPcmRate(bool r) = 0;
62 #if defined(OPNMIDI_AUDIO_TICK_HANDLER)
63     virtual void setAudioTickHandlerInstance(void *instance) = 0;
64 #endif
65 
66     virtual void setRate(uint32_t rate, uint32_t clock) = 0;
67     virtual uint32_t effectiveRate() const = 0;
68     virtual uint32_t nativeRate() const = 0;
69     virtual void reset() = 0;
70     virtual void writeReg(uint32_t port, uint16_t addr, uint8_t data) = 0;
71 
72     // extended
writePan(uint16_t addr,uint8_t data)73     virtual void writePan(uint16_t addr, uint8_t data) { (void)addr; (void)data; }
74 
75     virtual void nativePreGenerate() = 0;
76     virtual void nativePostGenerate() = 0;
77     virtual void nativeGenerate(int16_t *frame) = 0;
78 
79     virtual void generate(int16_t *output, size_t frames) = 0;
80     virtual void generateAndMix(int16_t *output, size_t frames) = 0;
81     virtual void generate32(int32_t *output, size_t frames) = 0;
82     virtual void generateAndMix32(int32_t *output, size_t frames) = 0;
83 
84     virtual const char* emulatorName() = 0;
85 private:
86     OPNChipBase(const OPNChipBase &c);
87     OPNChipBase &operator=(const OPNChipBase &c);
88 };
89 
90 // A base class providing F-bounded generic and efficient implementations,
91 // supporting resampling of chip outputs
92 template <class T>
93 class OPNChipBaseT : public OPNChipBase
94 {
95 public:
96     explicit OPNChipBaseT(OPNFamily f);
97     virtual ~OPNChipBaseT();
98 
99     OPNFamily family() const override;
100     uint32_t nativeClockRate() const override;
101 
102     bool isRunningAtPcmRate() const override;
103     bool setRunningAtPcmRate(bool r) override;
104 #if defined(OPNMIDI_AUDIO_TICK_HANDLER)
105     void setAudioTickHandlerInstance(void *instance);
106 #endif
107 
108     virtual void setRate(uint32_t rate, uint32_t clock) override;
109     uint32_t effectiveRate() const override;
110     uint32_t nativeRate() const override;
111     virtual void reset() override;
112     void generate(int16_t *output, size_t frames) override;
113     void generateAndMix(int16_t *output, size_t frames) override;
114     void generate32(int32_t *output, size_t frames) override;
115     void generateAndMix32(int32_t *output, size_t frames) override;
116 private:
117     bool m_runningAtPcmRate;
118 #if defined(OPNMIDI_AUDIO_TICK_HANDLER)
119     void *m_audioTickHandlerInstance;
120 #endif
121     void nativeTick(int16_t *frame);
122     void setupResampler(uint32_t rate);
123     void resetResampler();
124     void resampledGenerate(int32_t *output);
125 #if defined(OPNMIDI_ENABLE_HQ_RESAMPLER)
126     VResampler *m_resampler;
127 #else
128     int32_t m_oldsamples[2];
129     int32_t m_samples[2];
130     int32_t m_samplecnt;
131     int32_t m_rateratio;
132     enum { rsm_frac = 10 };
133 #endif
134     // amplitude scale factors in and out of resampler, varying for chips;
135     // values are OK to "redefine", the static polymorphism will accept it.
136     enum { resamplerPreAmplify = 1, resamplerPostAttenuate = 1 };
137 };
138 
139 // A base class which provides frame-by-frame interfaces on emulations which
140 // don't have a routine for it. It produces outputs in fixed size buffers.
141 // Fast register updates will suffer some latency because of buffering.
142 template <class T, unsigned Buffer = 256>
143 class OPNChipBaseBufferedT : public OPNChipBaseT<T>
144 {
145 public:
OPNChipBaseBufferedT(OPNFamily f)146     explicit OPNChipBaseBufferedT(OPNFamily f)
147         : OPNChipBaseT<T>(f), m_bufferIndex(0) {}
~OPNChipBaseBufferedT()148     virtual ~OPNChipBaseBufferedT()
149         {}
150     enum { buffer_size = Buffer };
151 public:
152     void reset() override;
153     void nativeGenerate(int16_t *frame) override;
154 protected:
155     virtual void nativeGenerateN(int16_t *output, size_t frames) = 0;
156 private:
157     unsigned m_bufferIndex;
158     int16_t m_buffer[2 * Buffer];
159 };
160 
161 #include "opn_chip_base.tcc"
162 
163 #endif // ONP_CHIP_BASE_H
164