28 uint32_t samples_left;
37 static std::atomic<uint8_t> _active_channels;
38 static std::atomic<uint8_t> _stop_channels;
40 static uint32_t _play_rate = 11025;
41 static uint32_t _max_size = UINT_MAX;
43 static std::mutex _music_stream_mutex;
44 static std::atomic<uint8_t> _effect_vol;
64 return ((b[0] * ((1 << 16) - frac_pos)) + (b[1] * frac_pos)) >> 16;
68 static void mix_int16(
MixerChannel *sc, int16_t *buffer, uint samples, uint8_t effect_vol)
71 const uint SHIFT =
sizeof(T) * CHAR_BIT;
73 if (samples > sc->samples_left) samples = sc->samples_left;
74 sc->samples_left -= samples;
77 const T *b = (
const T *)sc->memory + sc->pos;
78 uint32_t frac_pos = sc->frac_pos;
79 uint32_t frac_speed = sc->frac_speed;
80 int volume_left = sc->volume_left * effect_vol / 255;
81 int volume_right = sc->volume_right * effect_vol / 255;
83 if (frac_speed == 0x10000) {
90 }
while (--samples > 0);
97 frac_pos += frac_speed;
100 }
while (--samples > 0);
103 sc->frac_pos = frac_pos;
104 sc->pos = b - (
const T *)sc->memory;
107 static void MxCloseChannel(uint8_t channel_index)
109 _active_channels.fetch_and(~(1 << channel_index), std::memory_order_release);
119 _stop_channels.fetch_or(~0, std::memory_order_release);
122 void MxMixSamples(
void *buffer, uint samples)
125 static uint last_samples = 0;
126 if (samples != last_samples) {
127 framerate.SetExpectedRate((
double)_play_rate / samples);
128 last_samples = samples;
132 memset(buffer, 0,
sizeof(int16_t) * 2 * samples);
135 std::lock_guard<std::mutex>
lock{ _music_stream_mutex };
137 if (_music_stream) _music_stream((int16_t*)buffer, samples);
141 uint8_t stop = _stop_channels.load(std::memory_order_acquire);
150 uint8_t effect_vol_setting = _effect_vol.load(std::memory_order_relaxed);
151 uint8_t effect_vol = (effect_vol_setting *
153 effect_vol_setting) / (127 * 127);
156 uint8_t active = _active_channels.load(std::memory_order_acquire);
160 mix_int16<int16_t>(mc, (int16_t*)buffer, samples, effect_vol);
162 mix_int16<int8_t>(mc, (int16_t*)buffer, samples, effect_vol);
164 if (mc->samples_left == 0) MxCloseChannel(idx);
170 uint8_t currently_active = _active_channels.load(std::memory_order_acquire);
171 uint8_t available = ~currently_active;
172 if (available == 0)
return nullptr;
178 mc->memory =
nullptr;
182 void MxSetChannelRawSrc(
MixerChannel *mc, int8_t *mem,
size_t size, uint rate,
bool is16bit)
188 mc->frac_speed = (rate << 16) / _play_rate;
190 if (is16bit) size /= 2;
193 while (size >= _max_size) {
195 rate = (rate >> 1) + 1;
198 mc->samples_left = (uint)size * _play_rate / rate;
199 mc->is16bit = is16bit;
212 mc->volume_left = (uint)(sin((1.0 - pan) * M_PI / 2.0) * volume);
213 mc->volume_right = (uint)(sin(pan * M_PI / 2.0) * volume);
219 uint8_t channel_index = mc - _channels;
220 _stop_channels.fetch_and(~(1 << channel_index), std::memory_order_release);
221 _active_channels.fetch_or((1 << channel_index), std::memory_order_release);
231 std::lock_guard<std::mutex>
lock{ _music_stream_mutex };
232 _music_stream = music_callback;
237 bool MxInitialize(uint rate)
239 std::lock_guard<std::mutex>
lock{ _music_stream_mutex };
241 _max_size = UINT_MAX / _play_rate;
242 _music_stream =
nullptr;
246 void SetEffectVolume(uint8_t volume)
248 _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.
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.
void free(const void *ptr)
Version of the standard free that accepts const pointers.
Iterable ensemble of each set bit in a value.
std::mutex lock
synchronization for playback status fields