Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix pan and IRateConverters #281

Merged
merged 15 commits into from
Nov 12, 2023
18 changes: 9 additions & 9 deletions .github/workflows/sonarcloud.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@ on:
#branches:
# - master

#pull_request:
## branches: [ master ]
# paths-ignore:
# - 'doc/**'
# - '.gitignore'
# - '.gitattributes'
# - 'README.md'
# - 'LICENSE'
# - 'wave_generators.r'
pull_request:
# branches: [ master ]
paths-ignore:
- 'doc/**'
- '.gitignore'
- '.gitattributes'
- 'README.md'
- 'LICENSE'
- 'wave_generators.r'

#permissions: read-all

Expand Down
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.15.4 DESCRIPTION "SDL2 based Hyper-Sonic Drivers for emulating old soundcards")
project ("sdl2-hyper-sonic-drivers" VERSION 0.16.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
2 changes: 1 addition & 1 deletion sdl2-hyper-sonic-drivers/examples/pcm-example.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ int main(int argc, char* argv[])
for (int i = 0, sig = +1; i < 3; i++, sig *= -1)
{
cout << i << ". playing same sound again reversed balance" << endl;
delayMillis(200);
delayMillis(500);
drv.play(wavSound, 150, 127 * sig);
drv.play(vocSound, 255, -127 * sig);
}
Expand Down
14 changes: 13 additions & 1 deletion sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/audio/IMixer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace HyperSonicDrivers::audio
IMixer::IMixer(const uint8_t max_channels,
const uint32_t freq, const uint16_t buffer_size) :
max_channels(max_channels),
m_sampleRate(freq), m_samples(buffer_size)
freq(freq), buffer_size(buffer_size)
{
}

Expand All @@ -20,5 +20,17 @@ namespace HyperSonicDrivers::audio
void IMixer::setChannelGroupVolume(const mixer::eChannelGroup group, const uint8_t volume) noexcept
{
m_group_settings.at(group2i(group)).volume = volume;
updateChannelsVolumePan_();
}

int8_t IMixer::getChannelGroupPan(const mixer::eChannelGroup group) const noexcept
{
return m_group_settings.at(group2i(group)).pan;
}

void IMixer::setChannelGroupPan(const mixer::eChannelGroup group, const int8_t pan) noexcept
{
m_group_settings[group2i(group)].pan = pan;
updateChannelsVolumePan_();
}
}
26 changes: 16 additions & 10 deletions sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/audio/IMixer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ namespace HyperSonicDrivers::audio
class IMixer
{
public:
const uint8_t max_channels;
const uint32_t freq;
const uint16_t buffer_size;
const uint8_t bitsDepth = 16; // forced to be 16-bits for now

IMixer(IMixer&) = delete;
IMixer& operator=(IMixer&) = delete;

Expand All @@ -40,16 +45,20 @@ namespace HyperSonicDrivers::audio

virtual void reset() noexcept = 0;
virtual void reset(const uint8_t id) noexcept = 0;
virtual void reset(const mixer::eChannelGroup group) noexcept = 0;

virtual void pause() noexcept = 0;
virtual void pause(const uint8_t id) noexcept = 0;

virtual void unpause() noexcept = 0;
virtual void unpause(const uint8_t id) noexcept = 0;

virtual bool isChannelActive(const uint8_t id) const noexcept = 0;
virtual bool isActive(const uint8_t id) const noexcept = 0;
virtual bool isPaused(const uint8_t id) const noexcept = 0;

virtual bool isActive() const noexcept = 0;
virtual bool isActive(const mixer::eChannelGroup group) = 0;

virtual bool isChannelGroupMuted(const mixer::eChannelGroup group) const noexcept = 0;
virtual void muteChannelGroup(const mixer::eChannelGroup group) noexcept = 0;
virtual void unmuteChannelGroup(const mixer::eChannelGroup group) noexcept = 0;
Expand All @@ -66,27 +75,24 @@ namespace HyperSonicDrivers::audio
uint8_t getChannelGroupVolume(const mixer::eChannelGroup group) const noexcept;
void setChannelGroupVolume(const mixer::eChannelGroup group, const uint8_t volume) noexcept;

// TODO: these 3 methods are useless if those 3 vars are consts...
inline uint32_t getOutputRate() const noexcept { return m_sampleRate; };
inline uint16_t getBufferSize() const noexcept { return m_samples; };
inline uint8_t getBitsDepth() const noexcept { return m_bitsDepth; };
inline uint8_t getMasterVolume() const noexcept { return m_master_volume; };
int8_t getChannelGroupPan(const mixer::eChannelGroup group) const noexcept;
void setChannelGroupPan(const mixer::eChannelGroup group, const int8_t pan) noexcept;

inline uint8_t getMasterVolume() const noexcept { return m_master_volume; };
virtual void setMasterVolume(const uint8_t master_volume) noexcept = 0;

inline void toggleReverseStereo() noexcept { m_reverseStereo = !m_reverseStereo; };

const uint8_t max_channels;
protected:
virtual void updateChannelsVolumePan_() noexcept = 0;

std::array<mixer::channelGroupSettings_t, mixer::eChannelGroup_size> m_group_settings;
bool m_ready = false; // TODO: not really useful if not used anywhere else except init.
// unless remove init method and do it in the constructor
// and then check if it is ready before use the mixer
// otherwise can just be removed.
bool m_reverseStereo = false;
const uint32_t m_sampleRate;
const uint16_t m_samples;
const uint8_t m_bitsDepth = 16; // forced to be 16-bits for now

uint8_t m_master_volume = mixer::Mixer_max_volume;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ namespace HyperSonicDrivers::audio::converters
int16_t out1 = (stereo ? *it++ : out0);

// output left channel
output_channel(obuf[reverseStereo ? 0 : 1], out0, vol_l);
output_channel(obuf[reverseStereo ? 1 : 0], out0, vol_l);
// output right channel
output_channel(obuf[reverseStereo ? 1 : 0], out1, vol_r);
output_channel(obuf[reverseStereo ? 0 : 1], out1, vol_r);
obuf += 2;
}
Raffaello marked this conversation as resolved.
Show resolved Hide resolved

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,9 @@ namespace HyperSonicDrivers::audio::converters
const int16_t out0 = interpolate(ilast0, icur0, opos);
const int16_t out1 = stereo ? interpolate(ilast1, icur1, opos) : out0;
// output left channel
output_channel(obuf[reverseStereo ? 0 : 1], out0, vol_l);
output_channel(obuf[reverseStereo ? 1 : 0], out0, vol_l);
// output right channel
output_channel(obuf[reverseStereo ? 1 : 0], out1, vol_r);
output_channel(obuf[reverseStereo ? 0 : 1], out1, vol_r);
Raffaello marked this conversation as resolved.
Show resolved Hide resolved
obuf += 2;

// Increment output position
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,9 @@ namespace HyperSonicDrivers::audio::converters
opos += opos_inc;

// output left channel
output_channel(obuf[reverseStereo ? 0 : 1], out0, vol_l);
output_channel(obuf[reverseStereo ? 1 : 0], out0, vol_l);
// output right channel
output_channel(obuf[reverseStereo ? 1 : 0], out1, vol_r);
output_channel(obuf[reverseStereo ? 0 : 1], out1, vol_r);
obuf += 2;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace HyperSonicDrivers::audio::mixer
reset();
m_group = group;
m_stream = stream;
m_converter = converters::makeIRateConverter(m_stream->getRate(), m_mixer.getOutputRate(), m_stream->isStereo(), reverseStereo);
m_converter = converters::makeIRateConverter(m_stream->getRate(), m_mixer.freq, m_stream->isStereo(), reverseStereo);
}

void Channel::setAudioStream(const mixer::eChannelGroup group, const std::shared_ptr<IAudioStream>& stream,
Expand Down Expand Up @@ -118,8 +118,8 @@ namespace HyperSonicDrivers::audio::mixer
const float pan = (127.5f + m_pan) / 255.0f;
// TODO: create different selectable pan laws
// -3dB pan law
m_volL = static_cast<uint16_t>(std::round(sqrt(pan) * vol / ch_max_vol));
m_volR = static_cast<uint16_t>(std::round(sqrt(1 - pan) * vol / ch_max_vol));
m_volL = static_cast<uint16_t>(std::round(sqrt(1 - pan) * vol / ch_max_vol));
m_volR = static_cast<uint16_t>(std::round(sqrt(pan) * vol / ch_max_vol));
Raffaello marked this conversation as resolved.
Show resolved Hide resolved

// adjust for master volume
const auto m_vol = m_mixer.getMasterVolume();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,17 @@ namespace HyperSonicDrivers::audio::sdl2
m_channels[id]->reset();
}

void Mixer::reset(const mixer::eChannelGroup group) noexcept
{
std::scoped_lock lck(m_mutex);

for (const auto& ch : m_channels)
{
if (ch->getChannelGroup() == group)
ch->reset();
}
}

void Mixer::pause() noexcept
{
std::scoped_lock lck(m_mutex);
Expand Down Expand Up @@ -116,7 +127,7 @@ namespace HyperSonicDrivers::audio::sdl2
m_channels[id]->unpause();
}

bool Mixer::isChannelActive(const uint8_t id) const noexcept
bool Mixer::isActive(const uint8_t id) const noexcept
{
std::scoped_lock lck(m_mutex);

Expand All @@ -130,6 +141,28 @@ namespace HyperSonicDrivers::audio::sdl2
return m_channels[id]->isPaused();
}

bool Mixer::isActive() const noexcept
{
std::scoped_lock lck(m_mutex);

for (const auto& ch : m_channels)
if (!ch->isEnded())
return true;

return false;
}

bool Mixer::isActive(const mixer::eChannelGroup group)
{
std::scoped_lock lck(m_mutex);

for (const auto& ch : m_channels)
if (ch->getChannelGroup() == group && !ch->isEnded())
return true;

return false;
}

bool Mixer::isChannelGroupMuted(const mixer::eChannelGroup group) const noexcept
{
return m_group_settings[group2i(group)].mute;
Expand Down Expand Up @@ -195,6 +228,12 @@ namespace HyperSonicDrivers::audio::sdl2
updateChannelsVolumePan_();
}

void Mixer::updateChannelsVolumePan_() noexcept
{
for (const auto& ch : m_channels)
ch->updateVolumePan();
}

bool Mixer::init_(SDL_AudioCallback callback, void* userdata)
{
m_ready = false;
Expand All @@ -206,10 +245,10 @@ namespace HyperSonicDrivers::audio::sdl2

// Get the desired audio specs
SDL_AudioSpec desired = {
.freq = static_cast<int>(m_sampleRate),
.freq = static_cast<int>(freq),
.format = AUDIO_S16,
.channels = 2,
.samples = m_samples,
.samples = buffer_size,
.callback = callback,
.userdata = userdata
};
Expand Down Expand Up @@ -244,12 +283,6 @@ namespace HyperSonicDrivers::audio::sdl2
return true;
}

void Mixer::updateChannelsVolumePan_() noexcept
{
for (const auto& ch : m_channels)
ch->updateVolumePan();
}

size_t Mixer::callback(uint8_t* samples, unsigned int len)
{
const std::scoped_lock lck(m_mutex);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,19 @@ namespace HyperSonicDrivers::audio::sdl2

void reset() noexcept override;
void reset(const uint8_t id) noexcept override;
void reset(const mixer::eChannelGroup group) noexcept override;

void pause() noexcept override;
void pause(const uint8_t id) noexcept override;

void unpause() noexcept override;
void unpause(const uint8_t id) noexcept override;

bool isChannelActive(const uint8_t id) const noexcept override;
bool isActive(const uint8_t id) const noexcept override;
bool isPaused(const uint8_t id) const noexcept override;

bool isActive() const noexcept override;
bool isActive(const mixer::eChannelGroup group) override;

bool isChannelGroupMuted(const mixer::eChannelGroup group) const noexcept override;;
void muteChannelGroup(const mixer::eChannelGroup group) noexcept override;
Expand All @@ -58,9 +61,11 @@ namespace HyperSonicDrivers::audio::sdl2

void setMasterVolume(const uint8_t master_volume) noexcept override;

protected:
void updateChannelsVolumePan_() noexcept override;

private:
bool init_(SDL_AudioCallback callback, void* userdata);
void updateChannelsVolumePan_() noexcept;

size_t callback(uint8_t* samples, unsigned int len);
static void sdlCallback(void* this_, uint8_t* samples, int len);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ namespace HyperSonicDrivers::audio::sdl2
if (m_buf.empty())
{
m_out->save_prepare(stream->getRate(), stream->isStereo());
m_buf.resize(m_mixer->getBufferSize());
m_buf.resize(m_mixer->buffer_size);
}

const size_t read = stream->readBuffer(m_buf.data(), m_buf.size());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ namespace HyperSonicDrivers::files
m_sound = std::make_shared<audio::PCMSound>(
group,
m_channels == 2,
m_sampleRate,
m_freq,
size,
data
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@ namespace HyperSonicDrivers::files
virtual ~IPCMFile() = default;

inline int getChannels() const noexcept { return m_channels; };
inline uint32_t getSampleRate() const noexcept { return m_sampleRate; };
inline uint32_t getSampleRate() const noexcept { return m_freq; };
inline uint8_t getBitsDepth() const noexcept { return m_bitsDepth; };
inline uint32_t getDataSize() const noexcept { return m_dataSize; };
inline std::shared_ptr<uint8_t[]> getData() const noexcept { return m_data; };
inline std::shared_ptr<audio::PCMSound> getSound() const noexcept { return m_sound; };

protected:
int m_channels = 0;
uint32_t m_sampleRate = 0;
uint32_t m_freq = 0;
uint8_t m_bitsDepth = 0;
uint32_t m_dataSize = 0;
std::shared_ptr<uint8_t[]> m_data;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,9 @@ namespace HyperSonicDrivers::files
// channels default = 1
// timeConstant = 65536 - (256000000 / (channels * sampleRate);
// sampleRate = 256000000 / ((65536 - (timeConstant<<8))*channels)
m_sampleRate = 256000000L / ((65536 - (timeConstant << 8)) * m_channels);
m_freq = 256000000L / ((65536 - (timeConstant << 8)) * m_channels);
//m_sampleRate = 1000000 / (256 - timeConstant);
assertValid_(m_sampleRate == (1000000 / (256 - timeConstant)));
assertValid_(m_freq == (1000000 / (256 - timeConstant)));
// pack Method
switch (packMethod)
{
Expand Down Expand Up @@ -137,7 +137,7 @@ namespace HyperSonicDrivers::files
case 9: // extended 2
{
assertValid_(m_version >= 0x0114);
m_sampleRate = db.data[0] + (db.data[1] << 8) + (db.data[2] << 16) + (db.data[3] << 24);
m_freq = db.data[0] + (db.data[1] << 8) + (db.data[2] << 16) + (db.data[3] << 24);
m_bitsDepth = db.data[4];
m_channels = db.data[5];
uint16_t format = db.data[6] + (db.data[7] << 8);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ namespace HyperSonicDrivers::files
m_expDataChunk = true;
m_bitsDepth = static_cast<uint8_t>(m_fmt_chunk.bitsPerSample);
m_channels = m_fmt_chunk.channels;
m_sampleRate = m_fmt_chunk.samplesPerSec;
m_freq = m_fmt_chunk.samplesPerSec;

return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
namespace HyperSonicDrivers::hardware
{
IHardware::IHardware(const std::shared_ptr<audio::IMixer>& mixer) :
m_mixer(mixer), m_output_rate(m_mixer->getOutputRate())
m_mixer(mixer), m_output_rate(m_mixer->freq)
{
if (m_mixer == nullptr)
{
Raffaello marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
Loading
Loading