22 std::shared_ptr<std::vector<uint8_t>> memory;
28 uint32_t samples_left;
39static std::atomic<MixerChannelMask> _active_channels;
40static std::atomic<MixerChannelMask> _stop_channels;
42static uint32_t _play_rate = 11025;
43static uint32_t _max_size = UINT_MAX;
45static std::mutex _music_stream_mutex;
46static std::atomic<uint8_t> _effect_vol;
66 return ((b[0] * ((1 << 16) - frac_pos)) + (b[1] * frac_pos)) >> 16;
70static void mix_int16(
MixerChannel *sc, int16_t *buffer, uint samples, uint8_t effect_vol)
73 const uint SHIFT =
sizeof(T) * CHAR_BIT;
75 if (samples > sc->samples_left) samples = sc->samples_left;
76 sc->samples_left -= samples;
79 const T *b =
reinterpret_cast<const T *
>(sc->memory->data()) + sc->pos;
80 uint32_t frac_pos = sc->frac_pos;
81 uint32_t frac_speed = sc->frac_speed;
82 int volume_left = sc->volume_left * effect_vol / 255;
83 int volume_right = sc->volume_right * effect_vol / 255;
85 if (frac_speed == 0x10000) {
92 }
while (--samples > 0);
99 frac_pos += frac_speed;
102 }
while (--samples > 0);
105 sc->frac_pos = frac_pos;
106 sc->pos = b -
reinterpret_cast<const T *
>(sc->memory->data());
109static void MxCloseChannel(uint8_t channel_index)
111 _active_channels.fetch_and(~(1U << channel_index), std::memory_order_release);
121 _stop_channels.fetch_or(~0, std::memory_order_release);
124void MxMixSamples(
void *buffer, uint samples)
127 static uint last_samples = 0;
128 if (samples != last_samples) {
129 framerate.SetExpectedRate((
double)_play_rate / samples);
130 last_samples = samples;
134 memset(buffer, 0,
sizeof(int16_t) * 2 * samples);
137 std::lock_guard<std::mutex>
lock{ _music_stream_mutex };
139 if (_music_stream) _music_stream((int16_t*)buffer, samples);
152 uint8_t effect_vol_setting = _effect_vol.load(std::memory_order_relaxed);
153 uint8_t effect_vol = (effect_vol_setting *
155 effect_vol_setting) / (127 * 127);
162 mix_int16<int16_t>(mc, (int16_t*)buffer, samples, effect_vol);
164 mix_int16<int8_t>(mc, (int16_t*)buffer, samples, effect_vol);
166 if (mc->samples_left == 0) MxCloseChannel(idx);
172 MixerChannelMask currently_active = _active_channels.load(std::memory_order_acquire);
174 if (available == 0)
return nullptr;
179 mc->memory =
nullptr;
183void MxSetChannelRawSrc(
MixerChannel *mc,
const std::shared_ptr<std::vector<uint8_t>> &mem, uint rate,
bool is16bit)
189 mc->frac_speed = (rate << 16U) / _play_rate;
191 size_t size = mc->memory->size();
192 if (is16bit) size /= 2;
197 while (size >= _max_size) {
199 rate = (rate >> 1) + 1;
203 mc->samples_left = (uint)size * _play_rate / rate;
204 mc->is16bit = is16bit;
217 mc->volume_left = (uint)(sin((1.0 - pan) * M_PI / 2.0) * volume);
218 mc->volume_right = (uint)(sin(pan * M_PI / 2.0) * volume);
224 uint8_t channel_index = mc - _channels;
225 _stop_channels.fetch_and(~(1U << channel_index), std::memory_order_release);
226 _active_channels.fetch_or((1U << channel_index), std::memory_order_release);
236 std::lock_guard<std::mutex>
lock{ _music_stream_mutex };
237 _music_stream = music_callback;
242bool MxInitialize(uint rate)
244 std::lock_guard<std::mutex>
lock{ _music_stream_mutex };
246 _max_size = UINT_MAX / _play_rate;
247 _music_stream =
nullptr;
251void SetEffectVolume(uint8_t volume)
253 _effect_vol.store(volume, std::memory_order_relaxed);
constexpr uint8_t FindFirstBit(T x)
Search the first set bit in a value.
Types for recording game performance data.
@ PFE_SOUND
Speed of mixing audio samples.
constexpr T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
void MxCloseAllChannels()
Close all mixer channels.
static int RateConversion(T *b, int frac_pos)
Perform the rate conversion between the input and output.
uint8_t MixerChannelMask
Type representing a bitmask of mixer channels.
uint32_t MxSetMusicSource(MxStreamCallback music_callback)
Set source of PCM music.
void MxSetChannelVolume(MixerChannel *mc, uint volume, float pan)
Set volume and pan parameters for a sound.
static const int MAX_VOLUME
The theoretical maximum volume for a single sound sample.
Functions to mix sound samples.
void(* MxStreamCallback)(int16_t *buffer, size_t samples)
Type of callback functions for supplying PCM music.
A number of safeguards to prevent using unsafe methods.
Types related to global configuration settings.
Definition of base types and functions in a cross-platform compatible way.
Iterable ensemble of each set bit in a value.
std::mutex lock
synchronization for playback status fields