aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt13
-rw-r--r--src/chips/nuked_opl3.cpp91
-rw-r--r--src/chips/nuked_opl3.h13
-rw-r--r--src/chips/nuked_opl3_v174.cpp91
-rw-r--r--src/chips/nuked_opl3_v174.h13
5 files changed, 203 insertions, 18 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ce162a0..0bf7719 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -70,6 +70,7 @@ option(WITH_CPP_EXTRAS "Build with support for C++ extras (features are can
option(WITH_MIDI_SEQUENCER "Build with embedded MIDI sequencer. Disable this if you want use library in real-time MIDI drivers or plugins.)" ON)
option(WITH_MUS_SUPPORT "Build with support for DMX MUS files)" ON)
option(WITH_XMI_SUPPORT "Build with support for AIL XMI files)" ON)
+option(WITH_HQ_RESAMPLER "Build with support for high quality resampling" OFF)
option(libADLMIDI_STATIC "Build static library of libADLMIDI" ON)
option(libADLMIDI_SHARED "Build shared library of libADLMIDI" OFF)
@@ -480,6 +481,17 @@ if(WITH_VLC_PLUGIN)
endif()
+if(WITH_HQ_RESAMPLER)
+ find_library(ZITA_RESAMPLER_LIBRARY "zita-resampler" REQUIRED)
+ add_definitions(-DADLMIDI_ENABLE_HQ_RESAMPLER)
+ if(libADLMIDI_SHARED)
+ target_link_libraries(ADLMIDI_shared PUBLIC "${ZITA_RESAMPLER_LIBRARY}")
+ endif()
+ if(libADLMIDI_STATIC)
+ target_link_libraries(ADLMIDI_static PUBLIC "${ZITA_RESAMPLER_LIBRARY}")
+ endif()
+endif()
+
install(TARGETS ${libADLMIDI_INSTALLS}
RUNTIME DESTINATION "bin"
LIBRARY DESTINATION "lib"
@@ -512,6 +524,7 @@ message("WITH_MIDI_SEQUENCER = ${WITH_MIDI_SEQUENCER}")
message("WITH_CPP_EXTRAS = ${WITH_CPP_EXTRAS}")
message("WITH_MUS_SUPPORT = ${WITH_MUS_SUPPORT}")
message("WITH_XMI_SUPPORT = ${WITH_XMI_SUPPORT}")
+message("WITH_HQ_RESAMPLER = ${WITH_HQ_RESAMPLER}")
message("libADLMIDI_STATIC = ${libADLMIDI_STATIC}")
message("libADLMIDI_SHARED = ${libADLMIDI_SHARED}")
message("EXAMPLE_SDL2_AUDIO = ${EXAMPLE_SDL2_AUDIO}")
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)";
diff --git a/src/chips/nuked_opl3.h b/src/chips/nuked_opl3.h
index ceb1dfd..765a451 100644
--- a/src/chips/nuked_opl3.h
+++ b/src/chips/nuked_opl3.h
@@ -3,12 +3,18 @@
#include "opl_chip_base.h"
+#if defined(ADLMIDI_ENABLE_HQ_RESAMPLER)
+class VResampler;
+#endif
+
class NukedOPL3 final : public OPLChipBase
{
void *m_chip;
+#if defined(ADLMIDI_ENABLE_HQ_RESAMPLER)
+ VResampler *m_resampler;
+#endif
public:
NukedOPL3();
- NukedOPL3(const NukedOPL3 &c);
virtual ~NukedOPL3() override;
virtual void setRate(uint32_t rate) override;
@@ -20,6 +26,11 @@ public:
virtual int generate32(int32_t *output, size_t frames) override;
virtual int generateAndMix32(int32_t *output, size_t frames) override;
virtual const char *emulatorName() override;
+private:
+#if defined(ADLMIDI_ENABLE_HQ_RESAMPLER)
+ void generateResampledHq(int16_t *out);
+ void generateResampledHq32(int32_t *out);
+#endif
};
#endif // NUKED_OPL3_H
diff --git a/src/chips/nuked_opl3_v174.cpp b/src/chips/nuked_opl3_v174.cpp
index 0dcf925..675e104 100644
--- a/src/chips/nuked_opl3_v174.cpp
+++ b/src/chips/nuked_opl3_v174.cpp
@@ -1,26 +1,29 @@
#include "nuked_opl3_v174.h"
#include "nuked/nukedopl3_174.h"
#include <cstring>
+#include <cmath>
+
+#if defined(ADLMIDI_ENABLE_HQ_RESAMPLER)
+#include <zita-resampler/vresampler.h>
+#endif
NukedOPL3v174::NukedOPL3v174() :
OPLChipBase()
{
m_chip = new opl3_chip;
+#if defined(ADLMIDI_ENABLE_HQ_RESAMPLER)
+ m_resampler = new VResampler;
+#endif
reset(m_rate);
}
-NukedOPL3v174::NukedOPL3v174(const NukedOPL3v174 &c):
- OPLChipBase(c)
-{
- m_chip = new opl3_chip;
- std::memset(m_chip, 0, sizeof(opl3_chip));
- reset(c.m_rate);
-}
-
NukedOPL3v174::~NukedOPL3v174()
{
opl3_chip *chip_r = reinterpret_cast<opl3_chip*>(m_chip);
delete chip_r;
+#if defined(ADLMIDI_ENABLE_HQ_RESAMPLER)
+ delete m_resampler;
+#endif
}
void NukedOPL3v174::setRate(uint32_t rate)
@@ -29,6 +32,9 @@ void NukedOPL3v174::setRate(uint32_t rate)
opl3_chip *chip_r = reinterpret_cast<opl3_chip*>(m_chip);
std::memset(chip_r, 0, sizeof(opl3_chip));
OPL3v17_Reset(chip_r, rate);
+#if defined(ADLMIDI_ENABLE_HQ_RESAMPLER)
+ m_resampler->setup(rate * (1.0 / 49716), 2, 48);
+#endif
}
void NukedOPL3v174::reset()
@@ -49,15 +55,34 @@ void NukedOPL3v174::writeReg(uint16_t addr, uint8_t data)
int NukedOPL3v174::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);
OPL3v17_GenerateStream(chip_r, output, (Bit32u)frames);
+#endif
return (int)frames;
}
int NukedOPL3v174::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);
OPL3v17_GenerateStreamMix(chip_r, output, (Bit32u)frames);
+#endif
return (int)frames;
}
@@ -65,10 +90,15 @@ int NukedOPL3v174::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];
OPL3v17_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 NukedOPL3v174::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];
OPL3v17_GenerateResampled(chip_r, frame);
+#endif
output[0] += (int32_t)frame[0];
output[1] += (int32_t)frame[1];
output += 2;
@@ -87,6 +123,45 @@ int NukedOPL3v174::generateAndMix32(int32_t *output, size_t frames)
return (int)frames;
}
+#if defined(ADLMIDI_ENABLE_HQ_RESAMPLER)
+void NukedOPL3v174::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 NukedOPL3v174::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];
+ OPL3v17_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 *NukedOPL3v174::emulatorName()
{
return "Nuked OPL3 (v 1.7.4)";
diff --git a/src/chips/nuked_opl3_v174.h b/src/chips/nuked_opl3_v174.h
index acbdcca..efe65ba 100644
--- a/src/chips/nuked_opl3_v174.h
+++ b/src/chips/nuked_opl3_v174.h
@@ -3,12 +3,18 @@
#include "opl_chip_base.h"
+#if defined(ADLMIDI_ENABLE_HQ_RESAMPLER)
+class VResampler;
+#endif
+
class NukedOPL3v174 final : public OPLChipBase
{
void *m_chip;
+#if defined(ADLMIDI_ENABLE_HQ_RESAMPLER)
+ VResampler *m_resampler;
+#endif
public:
NukedOPL3v174();
- NukedOPL3v174(const NukedOPL3v174 &c);
virtual ~NukedOPL3v174() override;
virtual void setRate(uint32_t rate) override;
@@ -20,6 +26,11 @@ public:
virtual int generate32(int32_t *output, size_t frames) override;
virtual int generateAndMix32(int32_t *output, size_t frames) override;
virtual const char *emulatorName() override;
+private:
+#if defined(ADLMIDI_ENABLE_HQ_RESAMPLER)
+ void generateResampledHq(int16_t *out);
+ void generateResampledHq32(int32_t *out);
+#endif
};
#endif // NUKED_OPL3174_H