diff options
Diffstat (limited to 'src/chips')
-rw-r--r-- | src/chips/dosbox_opl3.cpp | 4 | ||||
-rw-r--r-- | src/chips/dosbox_opl3.h | 1 | ||||
-rw-r--r-- | src/chips/nuked_opl3.h | 1 | ||||
-rw-r--r-- | src/chips/nuked_opl3_v174.h | 1 | ||||
-rw-r--r-- | src/chips/opl_chip_base.h | 30 | ||||
-rw-r--r-- | src/chips/opl_chip_base.tcc | 84 |
6 files changed, 116 insertions, 5 deletions
diff --git a/src/chips/dosbox_opl3.cpp b/src/chips/dosbox_opl3.cpp index af4cb08..30fa38e 100644 --- a/src/chips/dosbox_opl3.cpp +++ b/src/chips/dosbox_opl3.cpp @@ -23,7 +23,7 @@ void DosBoxOPL3::setRate(uint32_t rate) DBOPL::Handler *chip_r = reinterpret_cast<DBOPL::Handler*>(m_chip); chip_r->~Handler(); new(chip_r) DBOPL::Handler; - chip_r->Init(49716); + chip_r->Init(effectiveRate()); } void DosBoxOPL3::reset() @@ -32,7 +32,7 @@ void DosBoxOPL3::reset() DBOPL::Handler *chip_r = reinterpret_cast<DBOPL::Handler*>(m_chip); chip_r->~Handler(); new(chip_r) DBOPL::Handler; - chip_r->Init(49716); + chip_r->Init(effectiveRate()); } void DosBoxOPL3::writeReg(uint16_t addr, uint8_t data) diff --git a/src/chips/dosbox_opl3.h b/src/chips/dosbox_opl3.h index f4c68da..1928026 100644 --- a/src/chips/dosbox_opl3.h +++ b/src/chips/dosbox_opl3.h @@ -10,6 +10,7 @@ public: DosBoxOPL3(); ~DosBoxOPL3() override; + bool canRunAtPcmRate() const override { return true; } void setRate(uint32_t rate) override; void reset() override; void writeReg(uint16_t addr, uint8_t data) override; diff --git a/src/chips/nuked_opl3.h b/src/chips/nuked_opl3.h index 25d9ed5..1b34e9a 100644 --- a/src/chips/nuked_opl3.h +++ b/src/chips/nuked_opl3.h @@ -10,6 +10,7 @@ public: NukedOPL3(); ~NukedOPL3() override; + bool canRunAtPcmRate() const override { return false; } void setRate(uint32_t rate) override; void reset() override; void writeReg(uint16_t addr, uint8_t data) override; diff --git a/src/chips/nuked_opl3_v174.h b/src/chips/nuked_opl3_v174.h index b9c5ba6..f14221f 100644 --- a/src/chips/nuked_opl3_v174.h +++ b/src/chips/nuked_opl3_v174.h @@ -10,6 +10,7 @@ public: NukedOPL3v174(); ~NukedOPL3v174() override; + bool canRunAtPcmRate() const override { return false; } void setRate(uint32_t rate) override; void reset() override; void writeReg(uint16_t addr, uint8_t data) override; diff --git a/src/chips/opl_chip_base.h b/src/chips/opl_chip_base.h index 5721a81..879d6da 100644 --- a/src/chips/opl_chip_base.h +++ b/src/chips/opl_chip_base.h @@ -13,15 +13,33 @@ class VResampler; #endif +#if defined(ADLMIDI_AUDIO_TICK_HANDLER) +extern void adl_audioTickHandler(void *instance, uint32_t chipId, uint32_t rate); +#endif + class OPLChipBase { +public: + enum { nativeRate = 49716 }; protected: + uint32_t m_id; uint32_t m_rate; public: OPLChipBase(); virtual ~OPLChipBase(); + uint32_t chipId() const { return m_id; } + void setChipId(uint32_t id) { m_id = id; } + + virtual bool canRunAtPcmRate() const = 0; + virtual bool isRunningAtPcmRate() const = 0; + virtual bool setRunningAtPcmRate(bool r) = 0; +#if defined(ADLMIDI_AUDIO_TICK_HANDLER) + virtual void setAudioTickHandlerInstance(void *instance) = 0; +#endif + virtual void setRate(uint32_t rate) = 0; + virtual uint32_t effectiveRate() const = 0; virtual void reset() = 0; virtual void writeReg(uint16_t addr, uint8_t data) = 0; @@ -49,13 +67,25 @@ public: OPLChipBaseT(); virtual ~OPLChipBaseT(); + bool isRunningAtPcmRate() const override; + bool setRunningAtPcmRate(bool r) override; +#if defined(ADLMIDI_AUDIO_TICK_HANDLER) + void setAudioTickHandlerInstance(void *instance); +#endif + virtual void setRate(uint32_t rate) override; + uint32_t effectiveRate() const override; virtual void reset() override; void generate(int16_t *output, size_t frames) override; void generateAndMix(int16_t *output, size_t frames) override; void generate32(int32_t *output, size_t frames) override; void generateAndMix32(int32_t *output, size_t frames) override; private: + bool m_runningAtPcmRate; +#if defined(ADLMIDI_AUDIO_TICK_HANDLER) + void *m_audioTickHandlerInstance; +#endif + void nativeTick(int16_t *frame); void setupResampler(uint32_t rate); void resetResampler(); void resampledGenerate(int32_t *output); diff --git a/src/chips/opl_chip_base.tcc b/src/chips/opl_chip_base.tcc index 58145bc..48ad103 100644 --- a/src/chips/opl_chip_base.tcc +++ b/src/chips/opl_chip_base.tcc @@ -5,9 +5,22 @@ #include <zita-resampler/vresampler.h> #endif +#if !defined(LIKELY) && defined(__GNUC__) +#define LIKELY(x) __builtin_expect((x), 1) +#elif !defined(LIKELY) +#define LIKELY(x) (x) +#endif + +#if !defined(UNLIKELY) && defined(__GNUC__) +#define UNLIKELY(x) __builtin_expect((x), 0) +#elif !defined(UNLIKELY) +#define UNLIKELY(x) (x) +#endif + /* OPLChipBase */ inline OPLChipBase::OPLChipBase() : + m_id(0), m_rate(44100) { } @@ -20,7 +33,12 @@ inline OPLChipBase::~OPLChipBase() template <class T> OPLChipBaseT<T>::OPLChipBaseT() - : OPLChipBase() + : OPLChipBase(), + m_runningAtPcmRate(false) +#if defined(ADLMIDI_AUDIO_TICK_HANDLER) + , + m_audioTickHandlerInstance(NULL) +#endif { #if defined(ADLMIDI_ENABLE_HQ_RESAMPLER) m_resampler = new VResampler; @@ -37,6 +55,33 @@ OPLChipBaseT<T>::~OPLChipBaseT() } template <class T> +bool OPLChipBaseT<T>::isRunningAtPcmRate() const +{ + return m_runningAtPcmRate; +} + +template <class T> +bool OPLChipBaseT<T>::setRunningAtPcmRate(bool r) +{ + if(r != m_runningAtPcmRate) + { + if(r && !static_cast<T *>(this)->canRunAtPcmRate()) + return false; + m_runningAtPcmRate = r; + static_cast<T *>(this)->setRate(m_rate); + } + return true; +} + +#if defined(ADLMIDI_AUDIO_TICK_HANDLER) +template <class T> +void OPLChipBaseT<T>::setAudioTickHandlerInstance(void *instance) +{ + m_audioTickHandlerInstance = instance; +} +#endif + +template <class T> void OPLChipBaseT<T>::setRate(uint32_t rate) { uint32_t oldRate = m_rate; @@ -48,6 +93,12 @@ void OPLChipBaseT<T>::setRate(uint32_t rate) } template <class T> +uint32_t OPLChipBaseT<T>::effectiveRate() const +{ + return m_runningAtPcmRate ? m_rate : (uint32_t)nativeRate; +} + +template <class T> void OPLChipBaseT<T>::reset() { resetResampler(); @@ -119,6 +170,15 @@ void OPLChipBaseT<T>::generateAndMix32(int32_t *output, size_t frames) } template <class T> +void OPLChipBaseT<T>::nativeTick(int16_t *frame) +{ +#if defined(ADLMIDI_AUDIO_TICK_HANDLER) + adl_audioTickHandler(m_audioTickHandlerInstance, m_id, effectiveRate()); +#endif + static_cast<T *>(this)->nativeGenerate(frame); +} + +template <class T> void OPLChipBaseT<T>::setupResampler(uint32_t rate) { #if defined(ADLMIDI_ENABLE_HQ_RESAMPLER) @@ -147,6 +207,15 @@ void OPLChipBaseT<T>::resetResampler() template <class T> void OPLChipBaseT<T>::resampledGenerate(int32_t *output) { + if(UNLIKELY(m_runningAtPcmRate)) + { + int16_t in[2]; + static_cast<T *>(this)->nativeTick(in); + output[0] = (int32_t)in[0] * T::resamplerPreAmplify / T::resamplerPostAttenuate; + output[1] = (int32_t)in[1] * T::resamplerPreAmplify / T::resamplerPostAttenuate; + return; + } + VResampler *rsm = m_resampler; float scale = (float)T::resamplerPreAmplify / (float)T::resamplerPostAttenuate; @@ -159,7 +228,7 @@ void OPLChipBaseT<T>::resampledGenerate(int32_t *output) while(rsm->process(), rsm->out_count != 0) { int16_t in[2]; - static_cast<T *>(this)->nativeGenerate(in); + static_cast<T *>(this)->nativeTick(in); f_in[0] = scale * (float)in[0]; f_in[1] = scale * (float)in[1]; rsm->inp_count = 1; @@ -174,6 +243,15 @@ void OPLChipBaseT<T>::resampledGenerate(int32_t *output) template <class T> void OPLChipBaseT<T>::resampledGenerate(int32_t *output) { + if(UNLIKELY(m_runningAtPcmRate)) + { + int16_t in[2]; + static_cast<T *>(this)->nativeTick(in); + output[0] = (int32_t)in[0] * T::resamplerPreAmplify / T::resamplerPostAttenuate; + output[1] = (int32_t)in[1] * T::resamplerPreAmplify / T::resamplerPostAttenuate; + return; + } + int32_t samplecnt = m_samplecnt; const int32_t rateratio = m_rateratio; while(samplecnt >= rateratio) @@ -181,7 +259,7 @@ void OPLChipBaseT<T>::resampledGenerate(int32_t *output) m_oldsamples[0] = m_samples[0]; m_oldsamples[1] = m_samples[1]; int16_t buffer[2]; - static_cast<T *>(this)->nativeGenerate(buffer); + static_cast<T *>(this)->nativeTick(buffer); m_samples[0] = buffer[0] * T::resamplerPreAmplify; m_samples[1] = buffer[1] * T::resamplerPreAmplify; samplecnt -= rateratio; |