From 3013fbb93b06e8d30b6b54c324340d6dccad7f3b Mon Sep 17 00:00:00 2001 From: JP Cimalando Date: Tue, 19 Jun 2018 16:12:27 +0200 Subject: get chip base on level with OPNMIDI --- src/chips/dosbox_opl3.cpp | 4 +-- src/chips/dosbox_opl3.h | 1 + src/chips/nuked_opl3.h | 1 + src/chips/nuked_opl3_v174.h | 1 + src/chips/opl_chip_base.h | 30 ++++++++++++++++ src/chips/opl_chip_base.tcc | 84 +++++++++++++++++++++++++++++++++++++++++++-- 6 files changed, 116 insertions(+), 5 deletions(-) (limited to 'src/chips') 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(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(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 #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 OPLChipBaseT::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; @@ -36,6 +54,33 @@ OPLChipBaseT::~OPLChipBaseT() #endif } +template +bool OPLChipBaseT::isRunningAtPcmRate() const +{ + return m_runningAtPcmRate; +} + +template +bool OPLChipBaseT::setRunningAtPcmRate(bool r) +{ + if(r != m_runningAtPcmRate) + { + if(r && !static_cast(this)->canRunAtPcmRate()) + return false; + m_runningAtPcmRate = r; + static_cast(this)->setRate(m_rate); + } + return true; +} + +#if defined(ADLMIDI_AUDIO_TICK_HANDLER) +template +void OPLChipBaseT::setAudioTickHandlerInstance(void *instance) +{ + m_audioTickHandlerInstance = instance; +} +#endif + template void OPLChipBaseT::setRate(uint32_t rate) { @@ -47,6 +92,12 @@ void OPLChipBaseT::setRate(uint32_t rate) resetResampler(); } +template +uint32_t OPLChipBaseT::effectiveRate() const +{ + return m_runningAtPcmRate ? m_rate : (uint32_t)nativeRate; +} + template void OPLChipBaseT::reset() { @@ -118,6 +169,15 @@ void OPLChipBaseT::generateAndMix32(int32_t *output, size_t frames) static_cast(this)->nativePostGenerate(); } +template +void OPLChipBaseT::nativeTick(int16_t *frame) +{ +#if defined(ADLMIDI_AUDIO_TICK_HANDLER) + adl_audioTickHandler(m_audioTickHandlerInstance, m_id, effectiveRate()); +#endif + static_cast(this)->nativeGenerate(frame); +} + template void OPLChipBaseT::setupResampler(uint32_t rate) { @@ -147,6 +207,15 @@ void OPLChipBaseT::resetResampler() template void OPLChipBaseT::resampledGenerate(int32_t *output) { + if(UNLIKELY(m_runningAtPcmRate)) + { + int16_t in[2]; + static_cast(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::resampledGenerate(int32_t *output) while(rsm->process(), rsm->out_count != 0) { int16_t in[2]; - static_cast(this)->nativeGenerate(in); + static_cast(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::resampledGenerate(int32_t *output) template void OPLChipBaseT::resampledGenerate(int32_t *output) { + if(UNLIKELY(m_runningAtPcmRate)) + { + int16_t in[2]; + static_cast(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::resampledGenerate(int32_t *output) m_oldsamples[0] = m_samples[0]; m_oldsamples[1] = m_samples[1]; int16_t buffer[2]; - static_cast(this)->nativeGenerate(buffer); + static_cast(this)->nativeTick(buffer); m_samples[0] = buffer[0] * T::resamplerPreAmplify; m_samples[1] = buffer[1] * T::resamplerPreAmplify; samplecnt -= rateratio; -- cgit v1.2.3