Skip to content

Commit

Permalink
Renderer Flush and BufferFlush methods (#284)
Browse files Browse the repository at this point in the history
* rendererer flush

* renderer code review

* code rev

* update version

* code rev

* codeRabbit rev

* code rev

* sonarcloud code rev

* codeRabbit rev

* sonarcloud code rev
  • Loading branch information
Raffaello committed Nov 15, 2023
1 parent 18b0a17 commit 2939550
Show file tree
Hide file tree
Showing 8 changed files with 106 additions and 60 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ if(DEFINED ENV{VCPKG_ROOT} AND NOT DEFINED CMAKE_TOOLCHAIN_FILE)
endif()


project ("sdl2-hyper-sonic-drivers" VERSION 0.17.1 DESCRIPTION "SDL2 based Hyper-Sonic Drivers for emulating old soundcards")
project ("sdl2-hyper-sonic-drivers" VERSION 0.18.0 DESCRIPTION "SDL2 based Hyper-Sonic Drivers for emulating old soundcards")
include (TestBigEndian)
TEST_BIG_ENDIAN(IS_BIG_ENDIAN)
if(IS_BIG_ENDIAN)
Expand Down
62 changes: 5 additions & 57 deletions sdl2-hyper-sonic-drivers/sdl2-hyper-sonic-drivers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -272,61 +272,6 @@ int song()
}
*/

//int renderMixer()
//{
// using namespace audio::scummvm;
// using namespace hardware::opl::scummvm;
// using namespace hardware::opl;
// using namespace drivers::westwood;
//
// audio::DiskRendererMixerManager mixerManager(44100);
// mixerManager.init();
// mixerManager.startRecording("test.dat");
//
// std::shared_ptr<Mixer> mixer = mixerManager.getMixer();
//
// //spdlog::set_level(spdlog::level::debug);
// auto opl = OPLFactory::create(OplEmulator::NUKED, OplType::OPL3, mixer);
// auto pOpl = dynamic_cast<EmulatedOPL*>( opl.get());
// //auto opl = std::make_shared<hardware::opl::mame::MameOPL>(mixer);
// std::shared_ptr<files::westwood::ADLFile> adlFile = std::make_shared<files::westwood::ADLFile>("test/fixtures/DUNE0.ADL");
//
// ADLDriver adlDrv(opl, adlFile);
// adlDrv.play(4, 0xFF);
// int samples = -1;
// int totSamples = 0;
// bool isPlaying = adlDrv.isPlaying();
// do
// {
// // TODO review, but is dumping the data
// int16_t buf[1024];
//
// samples = pOpl->readBuffer(buf, 1024);
// mixerManager.callbackHandler(reinterpret_cast<uint8_t*>(buf), samples * 2);
// totSamples += samples;
// isPlaying = adlDrv.isPlaying();
// //spdlog::info("isPlaying? {}", isPlaying);
// } while (isPlaying);
//
// //spdlog::info("TotSamples={} --- space require={} ({}KB) [{}MB]", totSamples, totSamples * sizeof(int16_t), totSamples * sizeof(int16_t) / 1024, totSamples * sizeof(int16_t) / 1024 / 1024);
//
// while (!mixer->isReady()) {
// //spdlog::info("mixer not ready");
// utils::delayMillis(100);
// }
//
// utils::delayMillis(1000);
// while (adlDrv.isPlaying())
// {
// //spdlog::info("is playing");
// utils::delayMillis(100);
//
// }
//
// //spdlog::info("renderer quitting...");
//
// return 0;
//}

void rendererMIDI()
{
Expand All @@ -349,7 +294,7 @@ void rendererMIDI()

//audio::sdl2::Renderer r(44100, 1024);

//r.setOutputFile("renderer_midi.wav");
//r.openOutputFile("renderer_midi.wav");

//auto mixer = r.getMixer();
//auto op2f = files::dmx::OP2File("test/fixtures/GENMIDI.OP2");
Expand All @@ -363,7 +308,7 @@ void rendererMIDI()
//while (mid_drv.isPlaying())
// r.renderBuffer(eo);

//r.releaseOutputFile();
//r.closeOutputFile();

//files::WAVFile w("renderer.wav");
//auto sound = w.getSound();
Expand Down Expand Up @@ -483,6 +428,9 @@ int main(int argc, char* argv[])
//midi_adlib_mus_op2_file();
//midi_adlib_xmi();

//rendererMIDI();
return 0;

SDL_Init(SDL_INIT_TIMER | SDL_INIT_AUDIO);

int numAudioDevices = SDL_GetNumAudioDevices(0);
Expand Down
15 changes: 15 additions & 0 deletions sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/audio/IRenderer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <HyperSonicDrivers/audio/IAudioStream.hpp>
#include <HyperSonicDrivers/hardware/opl/OPL.hpp>
#include <HyperSonicDrivers/devices/IDevice.hpp>
#include <HyperSonicDrivers/drivers/IAudioDriver.hpp>
#include <HyperSonicDrivers/files/WAVFile.hpp>

namespace HyperSonicDrivers::audio
Expand All @@ -25,7 +26,21 @@ namespace HyperSonicDrivers::audio

virtual void renderBuffer(IAudioStream* stream) = 0;
inline void renderBuffer(const std::shared_ptr<devices::IDevice>& device) { renderBuffer(device->getHardware()->getAudioStream().get()); };

/**
* It flushes the AudioStream until it detects the silence.
* It returns false if it reached max iterations but it didn't flush it completely.
* It returns true when silence is detected or nothing more to read from the stream
**/
virtual bool renderFlush(IAudioStream* stream) = 0;
inline bool renderFlush(const std::shared_ptr<devices::IDevice>& device) { return renderFlush(device->getHardware()->getAudioStream().get()); };

/**
* this is doing the render until the drv is play the track and call the render flush after all
* it returns the renderFlush returned value
**/
virtual bool renderBufferFlush(IAudioStream* stream, drivers::IAudioDriver& drv, const uint8_t track) = 0;
inline bool renderBufferFlush(const std::shared_ptr<devices::IDevice>& device, drivers::IAudioDriver& drv, const uint8_t track) { return renderBufferFlush(device->getHardware()->getAudioStream().get(), drv, track); };
protected:
std::shared_ptr<IMixer> m_mixer;
std::unique_ptr<files::WAVFile> m_out;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
#include <HyperSonicDrivers/audio/sdl2/Renderer.hpp>
#include <HyperSonicDrivers/audio/sdl2/Mixer.hpp>
#include <HyperSonicDrivers/utils/ILogger.hpp>
#include <algorithm>
#include <ranges>


namespace HyperSonicDrivers::audio::sdl2
{
// MaxRendererFlushIterations defines the maximum number of iterations
// to attempt flushing the renderer buffer to prevent infinite loops.
constexpr int MaxRendererFlushIterations = 1000;

Renderer::Renderer(const uint32_t freq, const uint16_t buffer_size, const uint8_t max_channels)
{
m_mixer = make_mixer<Mixer>(max_channels, freq, buffer_size);
Expand Down Expand Up @@ -32,4 +38,38 @@ namespace HyperSonicDrivers::audio::sdl2
const size_t read = stream->readBuffer(m_buf.data(), m_buf.size());
m_out->save_streaming(m_buf.data(), read);
}

bool Renderer::renderFlush(IAudioStream* stream)
{
// safety check
if (m_buf.empty())
{
m_out->save_prepare(stream->getRate(), stream->isStereo());
m_buf.resize(m_mixer->buffer_size);
}

for(int i = 0; i < MaxRendererFlushIterations; i++)
{
const size_t read = stream->readBuffer(m_buf.data(), m_buf.size());
if (read == 0)
return true;

// check if it is all silence...
if (std::ranges::all_of(m_buf, [](const int16_t sample) { return sample == 0; }))
return true;

m_out->save_streaming(m_buf.data(), read);
}

return false;
}

bool Renderer::renderBufferFlush(IAudioStream* stream, drivers::IAudioDriver& drv, const uint8_t track)
{
drv.play(track);
while (drv.isPlaying())
renderBuffer(stream);

return renderFlush(stream);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,13 @@ namespace HyperSonicDrivers::audio::sdl2

void openOutputFile(const std::filesystem::path& path) override;
void closeOutputFile() noexcept override;

using IRenderer::renderBuffer;
using IRenderer::renderFlush;
using IRenderer::renderBufferFlush;

void renderBuffer(IAudioStream* stream) override;
using IRenderer::renderBuffer;
bool renderFlush(IAudioStream* stream) override;
bool renderBufferFlush(IAudioStream* stream, drivers::IAudioDriver& drv, const uint8_t track) override;
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ namespace HyperSonicDrivers::audio::sdl2
std::filesystem::remove(rfile);

ASSERT_FALSE(std::filesystem::exists(rfile));

{
audio::sdl2::Renderer r(freq, 1024);
r.openOutputFile(rfile);
Expand All @@ -66,6 +65,44 @@ namespace HyperSonicDrivers::audio::sdl2
while (drv1.isPlaying())
r.renderBuffer(opl);

ASSERT_TRUE(r.renderFlush(opl));
r.closeOutputFile();
}

files::WAVFile w(rfile);
auto sound = w.getSound();
files::WAVFile wexp(exp_renderer);
auto exp_sound = wexp.getSound();

ASSERT_EQ(sound->dataSize, exp_sound->dataSize);
ASSERT_EQ(sound->freq, exp_sound->freq);
ASSERT_EQ(sound->stereo, exp_sound->stereo);
EXPECT_EQ(sound->freq, freq);
EXPECT_EQ(sound->stereo, opl->getHardware()->isStereo());
for (uint32_t i = 0; i < sound->dataSize; i++)
{
EXPECT_EQ(sound->data[i], exp_sound->data[i]);
}
}

TEST_P(RendererTest, render_wav2)
{
const std::string exp_renderer = "../fixtures/test_renderer_" + test_name + ".wav";
const std::string rfile = "../fixtures/test_renderer_" + test_name + "_out2.wav";

if (std::filesystem::exists(rfile))
std::filesystem::remove(rfile);

ASSERT_FALSE(std::filesystem::exists(rfile));
{
audio::sdl2::Renderer r(freq, 1024);
r.openOutputFile(rfile);

auto drv1 = drivers::westwood::ADLDriver(opl, eChannelGroup::Music);
auto af = std::make_shared<files::westwood::ADLFile>("../fixtures/DUNE0.ADL");
drv1.setADLFile(af);

ASSERT_TRUE(r.renderBufferFlush(opl, drv1, 4));
r.closeOutputFile();
}

Expand All @@ -84,6 +121,7 @@ namespace HyperSonicDrivers::audio::sdl2
EXPECT_EQ(sound->data[i], exp_sound->data[i]);
}
}

INSTANTIATE_TEST_SUITE_P(
Renderer,
RendererTest,
Expand Down
Binary file not shown.
Binary file not shown.

0 comments on commit 2939550

Please sign in to comment.