diff options
Diffstat (limited to 'src/chips/opl_chip_base.tcc')
-rw-r--r-- | src/chips/opl_chip_base.tcc | 84 |
1 files changed, 81 insertions, 3 deletions
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; |