ASW Lib
A.D.S. Games SDL Wrapper Library. A library targeted at Allegro4 users who want to switch to SDL3 and use modern c++.
Loading...
Searching...
No Matches
sound.cpp
Go to the documentation of this file.
2
3#include <SDL3_mixer/SDL_mixer.h>
4#include <algorithm>
5#include <array>
6#include <cmath>
7
8#include "./asw/modules/log.h"
9
10namespace {
11float master_volume = 1.0F;
12float sfx_volume = 1.0F;
13float music_volume = 1.0F;
14
15std::array<MIX_Track*, 16> tracks;
16MIX_Track* music_track = nullptr;
17MIX_Mixer* mixer = nullptr;
18
19float compute_sfx_volume(float vol)
20{
21 auto volume = vol * sfx_volume;
22 return std::clamp(volume, 0.0F, 1.0F);
23}
24
25float compute_music_volume(float vol)
26{
27 auto volume = vol * music_volume;
28 return std::clamp(volume, 0.0F, 1.0F);
29}
30
32{
33 for (size_t i = 0; i < tracks.size(); ++i) {
34 if (!MIX_TrackPlaying(tracks[i])) {
35 return static_cast<int>(i);
36 }
37 }
38 return -1;
39}
40
41} // namespace
42
44{
45 return mixer;
46}
47
49{
50 auto* m = mixer;
51 mixer = nullptr;
52 if (m != nullptr) {
53 MIX_DestroyMixer(m);
54 }
55 MIX_Quit();
56}
57
59{
60 if (!MIX_Init()) {
61 asw::log::error("Failed to initialize SDL_mixer: {}", SDL_GetError());
62 return false;
63 }
64
65 if (mixer != nullptr) {
66 asw::log::warn("Mixer already initialized");
67 return true;
68 }
69
70 // Initialize SDL_mixer
71 SDL_AudioSpec spec;
72 spec.format = SDL_AUDIO_S16LE;
73 spec.freq = 44100;
74 spec.channels = 2;
75
76 mixer = MIX_CreateMixerDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &spec);
77 if (mixer == nullptr) {
78 asw::log::error("Failed to create mixer: {}", SDL_GetError());
79 return false;
80 }
81
82 for (auto& track : tracks) {
83 track = MIX_CreateTrack(mixer);
84 if (track == nullptr) {
85 asw::log::error("Failed to create track: {}", SDL_GetError());
86 return false;
87 }
88 }
89
90 music_track = MIX_CreateTrack(mixer);
91 if (music_track == nullptr) {
92 asw::log::error("Failed to create music track: {}", SDL_GetError());
93 return false;
94 }
95
96 return true;
97}
98
99void asw::sound::play(const asw::Sample& sample, float volume, float pan, bool loop)
100{
101 const int channel = find_free_track();
102 if (channel >= 0) {
103 // Find first free track and play sample on it
104 auto& track = tracks[channel];
105 MIX_SetTrackAudio(track, sample.get());
106 MIX_SetTrackGain(track, compute_sfx_volume(volume));
107
108 // Stereo gains for panning using equal power panning
109 const float left = std::sqrtf((1.0F - pan) * 0.5F);
110 const float right = std::sqrtf((1.0F + pan) * 0.5F);
111
112 MIX_StereoGains gains;
113 gains.left = left;
114 gains.right = right;
115 MIX_SetTrackStereo(track, &gains);
116
117 // Play the track, looping if requested
118 const SDL_PropertiesID options = SDL_CreateProperties();
119 SDL_SetNumberProperty(options, MIX_PROP_PLAY_LOOPS_NUMBER, loop ? -1 : 0);
120 MIX_PlayTrack(track, options);
121 }
122}
123
124void asw::sound::play_music(const asw::Music& sample, float volume, float fade_in_s)
125{
126 MIX_SetTrackGain(music_track, compute_music_volume(volume));
127 MIX_SetTrackAudio(music_track, sample.get());
128
129 const SDL_PropertiesID options = SDL_CreateProperties();
130 SDL_SetNumberProperty(options, MIX_PROP_PLAY_LOOPS_NUMBER, -1);
131 SDL_SetNumberProperty(
132 options, MIX_PROP_PLAY_FADE_IN_MILLISECONDS_NUMBER, static_cast<int>(fade_in_s * 1000.0F));
133 MIX_PlayTrack(music_track, options);
134}
135
136void asw::sound::stop_music(float fade_out_s)
137
138{
139 const auto fade_out_frames
140 = MIX_TrackMSToFrames(music_track, static_cast<Sint64>(fade_out_s * 1000.0F));
141 MIX_StopTrack(music_track, fade_out_frames);
142}
143
145{
146 MIX_PauseTrack(music_track);
147}
148
150{
151 MIX_ResumeTrack(music_track);
152}
153
155{
156 return MIX_TrackPlaying(music_track);
157}
158
160{
161 return MIX_TrackPaused(music_track);
162}
163
165{
166 master_volume = std::clamp(volume, 0.0F, 1.0F);
167 MIX_SetMixerGain(mixer, master_volume);
168}
169
171{
172 sfx_volume = std::clamp(volume, 0.0F, 1.0F);
173}
174
176{
177 music_volume = std::clamp(volume, 0.0F, 1.0F);
178}
179
181{
182 return master_volume;
183}
184
186{
187 return sfx_volume;
188}
189
191{
192 return music_volume;
193}
Structured logging system.
std::array< MIX_Track *, 16 > tracks
Definition sound.cpp:15
float compute_music_volume(float vol)
Definition sound.cpp:25
float compute_sfx_volume(float vol)
Definition sound.cpp:19
void error(const std::string &message)
Log an error message.
Definition log.cpp:178
void warn(const std::string &message)
Log a warning message.
Definition log.cpp:173
bool is_music_paused()
Check if music is paused.
Definition sound.cpp:159
void pause_music()
Pause the currently playing music.
Definition sound.cpp:144
float get_master_volume()
Get the current master volume multiplier.
Definition sound.cpp:180
void play_music(const asw::Music &sample, float volume=1.0F, float fade_in_s=0.0F)
Play a music sample.
Definition sound.cpp:124
bool is_music_playing()
Check if music is currently playing.
Definition sound.cpp:154
void set_sfx_volume(float volume)
Set the SFX volume multiplier.
Definition sound.cpp:170
float get_music_volume()
Get the current music volume multiplier.
Definition sound.cpp:190
void resume_music()
Resume paused music.
Definition sound.cpp:149
void _shutdown()
Shut down the sound module. Called automatically by asw::core::shutdown().
Definition sound.cpp:48
MIX_Mixer * get_mixer()
Get the SDL mixer device.
Definition sound.cpp:43
float get_sfx_volume()
Get the current SFX volume multiplier.
Definition sound.cpp:185
void set_music_volume(float volume)
Set the music volume multiplier.
Definition sound.cpp:175
void set_master_volume(float volume)
Set the master volume multiplier (affects all audio).
Definition sound.cpp:164
void play(const asw::Sample &sample, float volume=1.0F, float pan=0.5F, bool loop=false)
Play a sample.
Definition sound.cpp:99
void stop_music(float fade_out_s=0.0F)
Stop the currently playing music.
Definition sound.cpp:136
bool _init()
Initialize the sound module. Called automatically by asw::core::init().
Definition sound.cpp:58
std::shared_ptr< MIX_Audio > Sample
Alias for a shared pointer to an MIX_Audio.
Definition types.h:44
std::shared_ptr< MIX_Audio > Music
Alias for a shared pointer to an MIX_Audio.
Definition types.h:47
Sound module for the ASW library.