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