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;  |