aboutsummaryrefslogtreecommitdiff
path: root/src/chips/nuked_opl3.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/chips/nuked_opl3.cpp')
-rw-r--r--src/chips/nuked_opl3.cpp91
1 files changed, 83 insertions, 8 deletions
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 <cstring>
+#include <cmath>
+
+#if defined(ADLMIDI_ENABLE_HQ_RESAMPLER)
+#include <zita-resampler/vresampler.h>
+#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<opl3_chip*>(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<opl3_chip*>(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<opl3_chip*>(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<opl3_chip*>(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<opl3_chip*>(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<opl3_chip*>(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<opl3_chip*>(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)";