#include "opl_chip_base.h" #include #if defined(ADLMIDI_ENABLE_HQ_RESAMPLER) #include #endif /* OPLChipBase */ inline OPLChipBase::OPLChipBase() : m_rate(44100) { } inline OPLChipBase::~OPLChipBase() { } /* OPLChipBaseT */ template OPLChipBaseT::OPLChipBaseT() : OPLChipBase() { #if defined(ADLMIDI_ENABLE_HQ_RESAMPLER) m_resampler = new VResampler; #endif setupResampler(m_rate); } template OPLChipBaseT::~OPLChipBaseT() { #if defined(ADLMIDI_ENABLE_HQ_RESAMPLER) delete m_resampler; #endif } template void OPLChipBaseT::setRate(uint32_t rate) { uint32_t oldRate = m_rate; m_rate = rate; if(rate != oldRate) setupResampler(rate); else resetResampler(); } template void OPLChipBaseT::reset() { resetResampler(); } template void OPLChipBaseT::generate(int16_t *output, size_t frames) { static_cast(this)->nativePreGenerate(); for(size_t i = 0; i < frames; ++i) { int32_t frame[2]; static_cast(this)->resampledGenerate(frame); for (unsigned c = 0; c < 2; ++c) { int32_t temp = frame[c]; temp = (temp > -32768) ? temp : -32768; temp = (temp < 32767) ? temp : 32767; output[c] = (int16_t)temp; } output += 2; } static_cast(this)->nativePostGenerate(); } template void OPLChipBaseT::generateAndMix(int16_t *output, size_t frames) { static_cast(this)->nativePreGenerate(); for(size_t i = 0; i < frames; ++i) { int32_t frame[2]; static_cast(this)->resampledGenerate(frame); for (unsigned c = 0; c < 2; ++c) { int32_t temp = (int32_t)output[c] + frame[c]; temp = (temp > -32768) ? temp : -32768; temp = (temp < 32767) ? temp : 32767; output[c] = (int16_t)temp; } output += 2; } static_cast(this)->nativePostGenerate(); } template void OPLChipBaseT::generate32(int32_t *output, size_t frames) { static_cast(this)->nativePreGenerate(); for(size_t i = 0; i < frames; ++i) { static_cast(this)->resampledGenerate(output); output += 2; } static_cast(this)->nativePostGenerate(); } template void OPLChipBaseT::generateAndMix32(int32_t *output, size_t frames) { static_cast(this)->nativePreGenerate(); for(size_t i = 0; i < frames; ++i) { int32_t frame[2]; static_cast(this)->resampledGenerate(frame); output[0] += frame[0]; output[1] += frame[1]; output += 2; } static_cast(this)->nativePostGenerate(); } template void OPLChipBaseT::setupResampler(uint32_t rate) { #if defined(ADLMIDI_ENABLE_HQ_RESAMPLER) m_resampler->setup(rate * (1.0 / 49716), 2, 48); #else m_oldsamples[0] = m_oldsamples[1] = 0; m_samples[0] = m_samples[1] = 0; m_samplecnt = 0; m_rateratio = (int32_t)((rate << rsm_frac) / 49716); #endif } template void OPLChipBaseT::resetResampler() { #if defined(ADLMIDI_ENABLE_HQ_RESAMPLER) m_resampler->reset(); #else m_oldsamples[0] = m_oldsamples[1] = 0; m_samples[0] = m_samples[1] = 0; m_samplecnt = 0; #endif } #if defined(ADLMIDI_ENABLE_HQ_RESAMPLER) template void OPLChipBaseT::resampledGenerate(int32_t *output) { VResampler *rsm = m_resampler; float scale = (float)T::resamplerPreAmplify / (float)T::resamplerPostAttenuate; float f_in[2]; float f_out[2]; rsm->inp_count = 0; rsm->inp_data = f_in; rsm->out_count = 1; rsm->out_data = f_out; while(rsm->process(), rsm->out_count != 0) { int16_t in[2]; static_cast(this)->nativeGenerate(in); f_in[0] = scale * (float)in[0]; f_in[1] = scale * (float)in[1]; rsm->inp_count = 1; rsm->inp_data = f_in; rsm->out_count = 1; rsm->out_data = f_out; } output[0] = std::lround(f_out[0]); output[1] = std::lround(f_out[1]); } #else template void OPLChipBaseT::resampledGenerate(int32_t *output) { int32_t samplecnt = m_samplecnt; const int32_t rateratio = m_rateratio; while(samplecnt >= rateratio) { m_oldsamples[0] = m_samples[0]; m_oldsamples[1] = m_samples[1]; int16_t buffer[2]; static_cast(this)->nativeGenerate(buffer); m_samples[0] = buffer[0] * T::resamplerPreAmplify; m_samples[1] = buffer[1] * T::resamplerPreAmplify; samplecnt -= rateratio; } output[0] = (int32_t)(((m_oldsamples[0] * (rateratio - samplecnt) + m_samples[0] * samplecnt) / rateratio)/T::resamplerPostAttenuate); output[1] = (int32_t)(((m_oldsamples[1] * (rateratio - samplecnt) + m_samples[1] * samplecnt) / rateratio)/T::resamplerPostAttenuate); m_samplecnt = samplecnt + (1 << rsm_frac); } #endif /* OPLChipBaseBufferedT */ template void OPLChipBaseBufferedT::reset() { OPLChipBaseT::reset(); m_bufferIndex = 0; } template void OPLChipBaseBufferedT::nativeGenerate(int16_t *frame) { unsigned bufferIndex = m_bufferIndex; if(bufferIndex == 0) static_cast(this)->nativeGenerateN(m_buffer, Buffer); frame[0] = m_buffer[2 * bufferIndex]; frame[1] = m_buffer[2 * bufferIndex + 1]; bufferIndex = (bufferIndex + 1 < Buffer) ? (bufferIndex + 1) : 0; m_bufferIndex = bufferIndex; }