From e3cad2f46925ac0b9ae303bea68a5fe508e78bc9 Mon Sep 17 00:00:00 2001 From: JP Cimalando Date: Sun, 3 Jun 2018 14:50:53 +0200 Subject: optional high-quality resampling --- src/chips/nuked_opl3.cpp | 91 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 83 insertions(+), 8 deletions(-) (limited to 'src/chips/nuked_opl3.cpp') diff --git a/src/chips/nuked_opl3.cpp b/src/chips/nuked_opl3.cpp index 70fc525..fc6363d 100644 --- a/src/chips/nuked_opl3.cpp +++ b/src/chips/nuked_opl3.cpp @@ -1,26 +1,29 @@ #include "nuked_opl3.h" #include "nuked/nukedopl3.h" #include +#include + +#if defined(ADLMIDI_ENABLE_HQ_RESAMPLER) +#include +#endif NukedOPL3::NukedOPL3() : OPLChipBase() { m_chip = new opl3_chip; +#if defined(ADLMIDI_ENABLE_HQ_RESAMPLER) + m_resampler = new VResampler; +#endif reset(m_rate); } -NukedOPL3::NukedOPL3(const NukedOPL3 &c): - OPLChipBase(c) -{ - m_chip = new opl3_chip; - std::memset(m_chip, 0, sizeof(opl3_chip)); - reset(c.m_rate); -} - NukedOPL3::~NukedOPL3() { opl3_chip *chip_r = reinterpret_cast(m_chip); delete chip_r; +#if defined(ADLMIDI_ENABLE_HQ_RESAMPLER) + delete m_resampler; +#endif } void NukedOPL3::setRate(uint32_t rate) @@ -29,6 +32,9 @@ void NukedOPL3::setRate(uint32_t rate) opl3_chip *chip_r = reinterpret_cast(m_chip); std::memset(chip_r, 0, sizeof(opl3_chip)); OPL3_Reset(chip_r, rate); +#if defined(ADLMIDI_ENABLE_HQ_RESAMPLER) + m_resampler->setup(rate * (1.0 / 49716), 2, 48); +#endif } void NukedOPL3::reset() @@ -49,15 +55,34 @@ void NukedOPL3::writeReg(uint16_t addr, uint8_t data) int NukedOPL3::generate(int16_t *output, size_t frames) { +#if defined(ADLMIDI_ENABLE_HQ_RESAMPLER) + for(size_t i = 0; i < frames; ++i) + { + generateResampledHq(output); + output += 2; + } +#else opl3_chip *chip_r = reinterpret_cast(m_chip); OPL3_GenerateStream(chip_r, output, (Bit32u)frames); +#endif return (int)frames; } int NukedOPL3::generateAndMix(int16_t *output, size_t frames) { +#if defined(ADLMIDI_ENABLE_HQ_RESAMPLER) + for(size_t i = 0; i < frames; ++i) + { + int16_t frame[2]; + generateResampledHq(frame); + output[0] += (int32_t)frame[0]; + output[1] += (int32_t)frame[1]; + output += 2; + } +#else opl3_chip *chip_r = reinterpret_cast(m_chip); OPL3_GenerateStreamMix(chip_r, output, (Bit32u)frames); +#endif return (int)frames; } @@ -65,10 +90,15 @@ int NukedOPL3::generate32(int32_t *output, size_t frames) { opl3_chip *chip_r = reinterpret_cast(m_chip); for(size_t i = 0; i < frames; ++i) { +#if defined(ADLMIDI_ENABLE_HQ_RESAMPLER) + (void)chip_r; + generateResampledHq32(output); +#else int16_t frame[2]; OPL3_GenerateResampled(chip_r, frame); output[0] = (int32_t)frame[0]; output[1] = (int32_t)frame[1]; +#endif output += 2; } return (int)frames; @@ -78,8 +108,14 @@ int NukedOPL3::generateAndMix32(int32_t *output, size_t frames) { opl3_chip *chip_r = reinterpret_cast(m_chip); for(size_t i = 0; i < frames; ++i) { +#if defined(ADLMIDI_ENABLE_HQ_RESAMPLER) + (void)chip_r; + int32_t frame[2]; + generateResampledHq32(frame); +#else int16_t frame[2]; OPL3_GenerateResampled(chip_r, frame); +#endif output[0] += (int32_t)frame[0]; output[1] += (int32_t)frame[1]; output += 2; @@ -87,6 +123,45 @@ int NukedOPL3::generateAndMix32(int32_t *output, size_t frames) return (int)frames; } +#if defined(ADLMIDI_ENABLE_HQ_RESAMPLER) +void NukedOPL3::generateResampledHq(int16_t *out) +{ + int32_t temps[2]; + generateResampledHq32(temps); + for(unsigned i = 0; i < 2; ++i) + { + int32_t temp = temps[i]; + temp = (temp > -32768) ? temp : -32768; + temp = (temp < 32767) ? temp : 32767; + out[i] = temp; + } +} + +void NukedOPL3::generateResampledHq32(int32_t *out) +{ + opl3_chip *chip_r = reinterpret_cast(m_chip); + VResampler *rsm = m_resampler; + 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]; + OPL3_Generate(chip_r, in); + f_in[0] = (float)in[0], f_in[1] = (float)in[1]; + rsm->inp_count = 1; + rsm->inp_data = f_in; + rsm->out_count = 1; + rsm->out_data = f_out; + } + out[0] = std::lround(f_out[0]); + out[1] = std::lround(f_out[1]); +} +#endif + const char *NukedOPL3::emulatorName() { return "Nuked OPL3 (v 1.8)"; -- cgit v1.2.3 From 32d4a6d002297f6978b6e76907a279c5f8c203fe Mon Sep 17 00:00:00 2001 From: JP Cimalando Date: Sun, 3 Jun 2018 22:29:19 +0200 Subject: clamp the outputs of 16bit adding generators --- src/chips/nuked_opl3.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'src/chips/nuked_opl3.cpp') diff --git a/src/chips/nuked_opl3.cpp b/src/chips/nuked_opl3.cpp index fc6363d..6490f7f 100644 --- a/src/chips/nuked_opl3.cpp +++ b/src/chips/nuked_opl3.cpp @@ -73,10 +73,14 @@ int NukedOPL3::generateAndMix(int16_t *output, size_t frames) #if defined(ADLMIDI_ENABLE_HQ_RESAMPLER) for(size_t i = 0; i < frames; ++i) { - int16_t frame[2]; - generateResampledHq(frame); - output[0] += (int32_t)frame[0]; - output[1] += (int32_t)frame[1]; + int32_t frame[2]; + generateResampledHq32(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] = temp; + } output += 2; } #else -- cgit v1.2.3 From 7cfe4dbcef738681b5445aa14b35fc1a6f8ff001 Mon Sep 17 00:00:00 2001 From: JP Cimalando Date: Thu, 7 Jun 2018 07:21:29 +0200 Subject: chips: create a common method set for generation and resampling --- src/chips/nuked_opl3.cpp | 141 +++-------------------------------------------- 1 file changed, 9 insertions(+), 132 deletions(-) (limited to 'src/chips/nuked_opl3.cpp') diff --git a/src/chips/nuked_opl3.cpp b/src/chips/nuked_opl3.cpp index 6490f7f..48e5c17 100644 --- a/src/chips/nuked_opl3.cpp +++ b/src/chips/nuked_opl3.cpp @@ -1,50 +1,34 @@ #include "nuked_opl3.h" #include "nuked/nukedopl3.h" #include -#include - -#if defined(ADLMIDI_ENABLE_HQ_RESAMPLER) -#include -#endif NukedOPL3::NukedOPL3() : - OPLChipBase() + OPLChipBaseT() { m_chip = new opl3_chip; -#if defined(ADLMIDI_ENABLE_HQ_RESAMPLER) - m_resampler = new VResampler; -#endif - reset(m_rate); + setRate(m_rate); } NukedOPL3::~NukedOPL3() { opl3_chip *chip_r = reinterpret_cast(m_chip); delete chip_r; -#if defined(ADLMIDI_ENABLE_HQ_RESAMPLER) - delete m_resampler; -#endif } void NukedOPL3::setRate(uint32_t rate) { - OPLChipBase::setRate(rate); + OPLChipBaseT::setRate(rate); opl3_chip *chip_r = reinterpret_cast(m_chip); std::memset(chip_r, 0, sizeof(opl3_chip)); OPL3_Reset(chip_r, rate); -#if defined(ADLMIDI_ENABLE_HQ_RESAMPLER) - m_resampler->setup(rate * (1.0 / 49716), 2, 48); -#endif } void NukedOPL3::reset() { - setRate(m_rate); -} - -void NukedOPL3::reset(uint32_t rate) -{ - setRate(rate); + OPLChipBaseT::reset(); + opl3_chip *chip_r = reinterpret_cast(m_chip); + std::memset(chip_r, 0, sizeof(opl3_chip)); + OPL3_Reset(chip_r, m_rate); } void NukedOPL3::writeReg(uint16_t addr, uint8_t data) @@ -53,118 +37,11 @@ void NukedOPL3::writeReg(uint16_t addr, uint8_t data) OPL3_WriteRegBuffered(chip_r, addr, data); } -int NukedOPL3::generate(int16_t *output, size_t frames) -{ -#if defined(ADLMIDI_ENABLE_HQ_RESAMPLER) - for(size_t i = 0; i < frames; ++i) - { - generateResampledHq(output); - output += 2; - } -#else - opl3_chip *chip_r = reinterpret_cast(m_chip); - OPL3_GenerateStream(chip_r, output, (Bit32u)frames); -#endif - return (int)frames; -} - -int NukedOPL3::generateAndMix(int16_t *output, size_t frames) -{ -#if defined(ADLMIDI_ENABLE_HQ_RESAMPLER) - for(size_t i = 0; i < frames; ++i) - { - int32_t frame[2]; - generateResampledHq32(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] = temp; - } - output += 2; - } -#else - opl3_chip *chip_r = reinterpret_cast(m_chip); - OPL3_GenerateStreamMix(chip_r, output, (Bit32u)frames); -#endif - return (int)frames; -} - -int NukedOPL3::generate32(int32_t *output, size_t frames) -{ - opl3_chip *chip_r = reinterpret_cast(m_chip); - for(size_t i = 0; i < frames; ++i) { -#if defined(ADLMIDI_ENABLE_HQ_RESAMPLER) - (void)chip_r; - generateResampledHq32(output); -#else - int16_t frame[2]; - OPL3_GenerateResampled(chip_r, frame); - output[0] = (int32_t)frame[0]; - output[1] = (int32_t)frame[1]; -#endif - output += 2; - } - return (int)frames; -} - -int NukedOPL3::generateAndMix32(int32_t *output, size_t frames) -{ - opl3_chip *chip_r = reinterpret_cast(m_chip); - for(size_t i = 0; i < frames; ++i) { -#if defined(ADLMIDI_ENABLE_HQ_RESAMPLER) - (void)chip_r; - int32_t frame[2]; - generateResampledHq32(frame); -#else - int16_t frame[2]; - OPL3_GenerateResampled(chip_r, frame); -#endif - output[0] += (int32_t)frame[0]; - output[1] += (int32_t)frame[1]; - output += 2; - } - return (int)frames; -} - -#if defined(ADLMIDI_ENABLE_HQ_RESAMPLER) -void NukedOPL3::generateResampledHq(int16_t *out) -{ - int32_t temps[2]; - generateResampledHq32(temps); - for(unsigned i = 0; i < 2; ++i) - { - int32_t temp = temps[i]; - temp = (temp > -32768) ? temp : -32768; - temp = (temp < 32767) ? temp : 32767; - out[i] = temp; - } -} - -void NukedOPL3::generateResampledHq32(int32_t *out) +void NukedOPL3::nativeGenerate(int16_t *frame) { opl3_chip *chip_r = reinterpret_cast(m_chip); - VResampler *rsm = m_resampler; - 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]; - OPL3_Generate(chip_r, in); - f_in[0] = (float)in[0], f_in[1] = (float)in[1]; - rsm->inp_count = 1; - rsm->inp_data = f_in; - rsm->out_count = 1; - rsm->out_data = f_out; - } - out[0] = std::lround(f_out[0]); - out[1] = std::lround(f_out[1]); + OPL3_Generate(chip_r, frame); } -#endif const char *NukedOPL3::emulatorName() { -- cgit v1.2.3