Skip to content

Commit db7430b

Browse files
authored
Fix pan and IRateConverters (#281)
* Fix pan and IRateConverters * refactor IMixer * refactor IMixer * IMixer add reset channel group (stop) * update version * restore sonarcloud ci bot comment on PR * revert accidental refactor to isPlaying * revert accidental refactor to isPlaying * revert accidental refactor to isPlaying * revert accidental refactor * revert accidental refactor * revert accidental refactor * code rev * sonarcloud ci rev * sonarcloud code rev
1 parent 1ceb2a6 commit db7430b

File tree

20 files changed

+105
-45
lines changed

20 files changed

+105
-45
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ if(DEFINED ENV{VCPKG_ROOT} AND NOT DEFINED CMAKE_TOOLCHAIN_FILE)
55
endif()
66

77

8-
project ("sdl2-hyper-sonic-drivers" VERSION 0.15.4 DESCRIPTION "SDL2 based Hyper-Sonic Drivers for emulating old soundcards")
8+
project ("sdl2-hyper-sonic-drivers" VERSION 0.16.0 DESCRIPTION "SDL2 based Hyper-Sonic Drivers for emulating old soundcards")
99
include (TestBigEndian)
1010
TEST_BIG_ENDIAN(IS_BIG_ENDIAN)
1111
if(IS_BIG_ENDIAN)

sdl2-hyper-sonic-drivers/examples/pcm-example.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ int main(int argc, char* argv[])
6262
for (int i = 0, sig = +1; i < 3; i++, sig *= -1)
6363
{
6464
cout << i << ". playing same sound again reversed balance" << endl;
65-
delayMillis(200);
65+
delayMillis(500);
6666
drv.play(wavSound, 150, 127 * sig);
6767
drv.play(vocSound, 255, -127 * sig);
6868
}

sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/audio/IMixer.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace HyperSonicDrivers::audio
88
IMixer::IMixer(const uint8_t max_channels,
99
const uint32_t freq, const uint16_t buffer_size) :
1010
max_channels(max_channels),
11-
m_sampleRate(freq), m_samples(buffer_size)
11+
freq(freq), buffer_size(buffer_size)
1212
{
1313
}
1414

@@ -20,5 +20,17 @@ namespace HyperSonicDrivers::audio
2020
void IMixer::setChannelGroupVolume(const mixer::eChannelGroup group, const uint8_t volume) noexcept
2121
{
2222
m_group_settings.at(group2i(group)).volume = volume;
23+
updateChannelsVolumePan_();
24+
}
25+
26+
int8_t IMixer::getChannelGroupPan(const mixer::eChannelGroup group) const noexcept
27+
{
28+
return m_group_settings.at(group2i(group)).pan;
29+
}
30+
31+
void IMixer::setChannelGroupPan(const mixer::eChannelGroup group, const int8_t pan) noexcept
32+
{
33+
m_group_settings[group2i(group)].pan = pan;
34+
updateChannelsVolumePan_();
2335
}
2436
}

sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/audio/IMixer.hpp

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ namespace HyperSonicDrivers::audio
1616
class IMixer
1717
{
1818
public:
19+
const uint8_t max_channels;
20+
const uint32_t freq;
21+
const uint16_t buffer_size;
22+
const uint8_t bitsDepth = 16; // forced to be 16-bits for now
23+
1924
IMixer(IMixer&) = delete;
2025
IMixer& operator=(IMixer&) = delete;
2126

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

4146
virtual void reset() noexcept = 0;
4247
virtual void reset(const uint8_t id) noexcept = 0;
48+
virtual void reset(const mixer::eChannelGroup group) noexcept = 0;
4349

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

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

50-
virtual bool isChannelActive(const uint8_t id) const noexcept = 0;
56+
virtual bool isActive(const uint8_t id) const noexcept = 0;
5157
virtual bool isPaused(const uint8_t id) const noexcept = 0;
5258

59+
virtual bool isActive() const noexcept = 0;
60+
virtual bool isActive(const mixer::eChannelGroup group) = 0;
61+
5362
virtual bool isChannelGroupMuted(const mixer::eChannelGroup group) const noexcept = 0;
5463
virtual void muteChannelGroup(const mixer::eChannelGroup group) noexcept = 0;
5564
virtual void unmuteChannelGroup(const mixer::eChannelGroup group) noexcept = 0;
@@ -66,27 +75,24 @@ namespace HyperSonicDrivers::audio
6675
uint8_t getChannelGroupVolume(const mixer::eChannelGroup group) const noexcept;
6776
void setChannelGroupVolume(const mixer::eChannelGroup group, const uint8_t volume) noexcept;
6877

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

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

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

79-
const uint8_t max_channels;
8086
protected:
87+
virtual void updateChannelsVolumePan_() noexcept = 0;
88+
8189
std::array<mixer::channelGroupSettings_t, mixer::eChannelGroup_size> m_group_settings;
8290
bool m_ready = false; // TODO: not really useful if not used anywhere else except init.
8391
// unless remove init method and do it in the constructor
8492
// and then check if it is ready before use the mixer
8593
// otherwise can just be removed.
8694
bool m_reverseStereo = false;
87-
const uint32_t m_sampleRate;
88-
const uint16_t m_samples;
89-
const uint8_t m_bitsDepth = 16; // forced to be 16-bits for now
95+
9096
uint8_t m_master_volume = mixer::Mixer_max_volume;
9197
};
9298

sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/audio/converters/CopyRateConverter.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,9 @@ namespace HyperSonicDrivers::audio::converters
4747
int16_t out1 = (stereo ? *it++ : out0);
4848

4949
// output left channel
50-
output_channel(obuf[reverseStereo ? 0 : 1], out0, vol_l);
50+
output_channel(obuf[reverseStereo ? 1 : 0], out0, vol_l);
5151
// output right channel
52-
output_channel(obuf[reverseStereo ? 1 : 0], out1, vol_r);
52+
output_channel(obuf[reverseStereo ? 0 : 1], out1, vol_r);
5353
obuf += 2;
5454
}
5555

sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/audio/converters/LinearRateConverter.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,9 @@ namespace HyperSonicDrivers::audio::converters
117117
const int16_t out0 = interpolate(ilast0, icur0, opos);
118118
const int16_t out1 = stereo ? interpolate(ilast1, icur1, opos) : out0;
119119
// output left channel
120-
output_channel(obuf[reverseStereo ? 0 : 1], out0, vol_l);
120+
output_channel(obuf[reverseStereo ? 1 : 0], out0, vol_l);
121121
// output right channel
122-
output_channel(obuf[reverseStereo ? 1 : 0], out1, vol_r);
122+
output_channel(obuf[reverseStereo ? 0 : 1], out1, vol_r);
123123
obuf += 2;
124124

125125
// Increment output position

sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/audio/converters/SimpleRateConverter.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,9 @@ namespace HyperSonicDrivers::audio::converters
9595
opos += opos_inc;
9696

9797
// output left channel
98-
output_channel(obuf[reverseStereo ? 0 : 1], out0, vol_l);
98+
output_channel(obuf[reverseStereo ? 1 : 0], out0, vol_l);
9999
// output right channel
100-
output_channel(obuf[reverseStereo ? 1 : 0], out1, vol_r);
100+
output_channel(obuf[reverseStereo ? 0 : 1], out1, vol_r);
101101
obuf += 2;
102102
}
103103

sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/audio/mixer/Channel.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ namespace HyperSonicDrivers::audio::mixer
1717
reset();
1818
m_group = group;
1919
m_stream = stream;
20-
m_converter = converters::makeIRateConverter(m_stream->getRate(), m_mixer.getOutputRate(), m_stream->isStereo(), reverseStereo);
20+
m_converter = converters::makeIRateConverter(m_stream->getRate(), m_mixer.freq, m_stream->isStereo(), reverseStereo);
2121
}
2222

2323
void Channel::setAudioStream(const mixer::eChannelGroup group, const std::shared_ptr<IAudioStream>& stream,
@@ -118,8 +118,8 @@ namespace HyperSonicDrivers::audio::mixer
118118
const float pan = (127.5f + m_pan) / 255.0f;
119119
// TODO: create different selectable pan laws
120120
// -3dB pan law
121-
m_volL = static_cast<uint16_t>(std::round(sqrt(pan) * vol / ch_max_vol));
122-
m_volR = static_cast<uint16_t>(std::round(sqrt(1 - pan) * vol / ch_max_vol));
121+
m_volL = static_cast<uint16_t>(std::round(sqrt(1 - pan) * vol / ch_max_vol));
122+
m_volR = static_cast<uint16_t>(std::round(sqrt(pan) * vol / ch_max_vol));
123123

124124
// adjust for master volume
125125
const auto m_vol = m_mixer.getMasterVolume();

sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/audio/sdl2/Mixer.cpp

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include <algorithm>
2+
#include <ranges>
23
#include <cstring>
34
#include <cassert>
45
#include <HyperSonicDrivers/audio/sdl2/Mixer.hpp>
@@ -86,6 +87,17 @@ namespace HyperSonicDrivers::audio::sdl2
8687
m_channels[id]->reset();
8788
}
8889

90+
void Mixer::reset(const mixer::eChannelGroup group) noexcept
91+
{
92+
std::scoped_lock lck(m_mutex);
93+
94+
for (const auto& ch : m_channels)
95+
{
96+
if (ch->getChannelGroup() == group)
97+
ch->reset();
98+
}
99+
}
100+
89101
void Mixer::pause() noexcept
90102
{
91103
std::scoped_lock lck(m_mutex);
@@ -116,7 +128,7 @@ namespace HyperSonicDrivers::audio::sdl2
116128
m_channels[id]->unpause();
117129
}
118130

119-
bool Mixer::isChannelActive(const uint8_t id) const noexcept
131+
bool Mixer::isActive(const uint8_t id) const noexcept
120132
{
121133
std::scoped_lock lck(m_mutex);
122134

@@ -130,6 +142,24 @@ namespace HyperSonicDrivers::audio::sdl2
130142
return m_channels[id]->isPaused();
131143
}
132144

145+
bool Mixer::isActive() const noexcept
146+
{
147+
std::scoped_lock lck(m_mutex);
148+
149+
return std::ranges::any_of(m_channels, [](const auto& ch)
150+
{ return !ch->isEnded(); });
151+
}
152+
153+
bool Mixer::isActive(const mixer::eChannelGroup group)
154+
{
155+
std::scoped_lock lck(m_mutex);
156+
157+
return std::ranges::any_of(m_channels, [group](const auto& ch)
158+
{ return ch->getChannelGroup() == group && !ch->isEnded(); });
159+
160+
return false;
161+
}
162+
133163
bool Mixer::isChannelGroupMuted(const mixer::eChannelGroup group) const noexcept
134164
{
135165
return m_group_settings[group2i(group)].mute;
@@ -195,6 +225,12 @@ namespace HyperSonicDrivers::audio::sdl2
195225
updateChannelsVolumePan_();
196226
}
197227

228+
void Mixer::updateChannelsVolumePan_() noexcept
229+
{
230+
for (const auto& ch : m_channels)
231+
ch->updateVolumePan();
232+
}
233+
198234
bool Mixer::init_(SDL_AudioCallback callback, void* userdata)
199235
{
200236
m_ready = false;
@@ -206,10 +242,10 @@ namespace HyperSonicDrivers::audio::sdl2
206242

207243
// Get the desired audio specs
208244
SDL_AudioSpec desired = {
209-
.freq = static_cast<int>(m_sampleRate),
245+
.freq = static_cast<int>(freq),
210246
.format = AUDIO_S16,
211247
.channels = 2,
212-
.samples = m_samples,
248+
.samples = buffer_size,
213249
.callback = callback,
214250
.userdata = userdata
215251
};
@@ -244,12 +280,6 @@ namespace HyperSonicDrivers::audio::sdl2
244280
return true;
245281
}
246282

247-
void Mixer::updateChannelsVolumePan_() noexcept
248-
{
249-
for (const auto& ch : m_channels)
250-
ch->updateVolumePan();
251-
}
252-
253283
size_t Mixer::callback(uint8_t* samples, unsigned int len)
254284
{
255285
const std::scoped_lock lck(m_mutex);

sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/audio/sdl2/Mixer.hpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,19 @@ namespace HyperSonicDrivers::audio::sdl2
3232

3333
void reset() noexcept override;
3434
void reset(const uint8_t id) noexcept override;
35+
void reset(const mixer::eChannelGroup group) noexcept override;
3536

3637
void pause() noexcept override;
3738
void pause(const uint8_t id) noexcept override;
3839

3940
void unpause() noexcept override;
4041
void unpause(const uint8_t id) noexcept override;
4142

42-
bool isChannelActive(const uint8_t id) const noexcept override;
43+
bool isActive(const uint8_t id) const noexcept override;
4344
bool isPaused(const uint8_t id) const noexcept override;
4445

46+
bool isActive() const noexcept override;
47+
bool isActive(const mixer::eChannelGroup group) override;
4548

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

5962
void setMasterVolume(const uint8_t master_volume) noexcept override;
6063

64+
protected:
65+
void updateChannelsVolumePan_() noexcept override;
66+
6167
private:
6268
bool init_(SDL_AudioCallback callback, void* userdata);
63-
void updateChannelsVolumePan_() noexcept;
6469

6570
size_t callback(uint8_t* samples, unsigned int len);
6671
static void sdlCallback(void* this_, uint8_t* samples, int len);

0 commit comments

Comments
 (0)