Project Alice
Loading...
Searching...
No Matches
sound_nix.cpp
Go to the documentation of this file.
1#include "sound.hpp"
2#include "system_state.hpp"
3
4#define MINIAUDIO_IMPLEMENTATION 1
5#define MA_NO_FLAC 1
6#define MA_NO_OPENSL 1
7#define MA_NO_WEBAUDIO 1
8#define MA_NO_SNDIO 1
9#define MA_NO_AUDIO4 1
10#define MA_NO_WINMM 1
11#define MA_NO_WASAPI 1
12#define MA_NO_WINMM 1
13#define MA_NO_COREAUDIO 1
14#include "miniaudio.h"
15
16namespace sound {
17
19 if(ma_engine_init(NULL, &engine) != MA_SUCCESS) {
20 std::abort(); //TODO: This shouldn't be a cause for abort
21 }
22}
23
25 ma_engine_uninit(&engine);
26}
27
28void sound_impl::set_volume(std::optional<ma_sound>& sound, float volume) {
29 if(sound.has_value()) {
30 ma_sound_set_volume(&*sound, volume);
31 }
32}
33
34void sound_impl::override_sound(std::optional<ma_sound>& sound, audio_instance& s, float volume) {
35 if(sound.has_value()) {
36 ma_sound_uninit(&*sound);
37 }
38
39 sound.reset();
40 sound.emplace();
41 ma_result result = ma_sound_init_from_file(&engine, s.filename.c_str(), 0, NULL, NULL, &*sound);
42 if(result == MA_SUCCESS) {
43 set_volume(sound, volume);
44 ma_sound_start(&*sound);
45 }
46}
47
48void sound_impl::play_music(int32_t track, float volume) {
49 current_music = track;
50
51 audio_instance audio{};
52 audio.filename = music_list[track].filename.c_str();
53 override_sound(music, audio, volume);
54}
55
57 if(music_list.size() > 0) {
58 int32_t result = int32_t(rand() % music_list.size()); // well aware that using rand is terrible, thanks
59 for(uint32_t i = 0; i < 16 && result == last_music; i++) {
60 result = int32_t(rand() % music_list.size());
61 }
63 }
64}
66 if(music_list.size() > 0) {
67 int32_t result = int32_t((last_music + 1) % music_list.size());
69 }
70}
72 if(music_list.size() > 0) {
73 int32_t result = int32_t((last_music - 1) % music_list.size());
75 }
76}
77
79 if(music.has_value())
80 return music->atEnd;
81 return true;
82}
83
85 state.sound_ptr = std::make_unique<sound_impl>();
86
87 auto root_dir = simple_fs::get_root(state.common_fs);
88 auto const music_dir = simple_fs::open_directory(root_dir, NATIVE("music"));
89 for(auto const& mp3_file : simple_fs::list_files(music_dir, NATIVE(".mp3"))) {
90 audio_instance audio{};
91 audio.set_file(simple_fs::get_full_name(mp3_file));
92 state.sound_ptr->music_list.emplace_back(audio);
93 auto file_name = simple_fs::get_full_name(mp3_file);
94 if(parsers::native_has_fixed_suffix_ci(file_name.c_str(), file_name.c_str() + file_name.length(), NATIVE("thecoronation_titletheme.mp3")))
95 state.sound_ptr->first_music = int32_t(state.sound_ptr->music_list.size()) - 1;
96 }
97 for(auto const& music_subdir : simple_fs::list_subdirectories(music_dir)) {
98 for(auto const& mp3_file : simple_fs::list_files(music_subdir, NATIVE(".mp3"))) {
99 audio_instance audio{};
100 audio.set_file(simple_fs::get_full_name(mp3_file));
101 state.sound_ptr->music_list.emplace_back(audio);
102 }
103 }
104
105 struct {
106 audio_instance* audio;
108 } vanilla_sound_table[] = {
109 //{ &state.sound_ptr->click_sound, NATIVE("GI_ValidClick.wav") },
110 { &state.sound_ptr->technology_finished_sound, NATIVE("UI_TechnologyFinished.wav") },
111 { &state.sound_ptr->army_move_sound, NATIVE("GI_InfantryMove.wav") },
112 { &state.sound_ptr->army_select_sound, NATIVE("GI_InfantrySelected.wav") },
113 { &state.sound_ptr->navy_move_sound, NATIVE("UI_SailMove.wav") },
114 { &state.sound_ptr->navy_select_sound, NATIVE("UI_SailSelected.wav") },
115 { &state.sound_ptr->declaration_of_war_sound, NATIVE("DeclarationofWar.wav") },
116 { &state.sound_ptr->chat_message_sound, NATIVE("GI_ChatMessage.wav") },
117 { &state.sound_ptr->error_sound, NATIVE("GI_ErrorBlip.wav") },
118 { &state.sound_ptr->peace_sound, NATIVE("Misc_Peace.wav") },
119 { &state.sound_ptr->army_built_sound, NATIVE("UI_LandUnitFinished.wav") },
120 { &state.sound_ptr->navy_built_sound, NATIVE("UI_NavalUnitFinished.wav") },
121 { &state.sound_ptr->factory_built_sound, NATIVE("Misc_NewFactory.wav") },
122 { &state.sound_ptr->revolt_sound, NATIVE("Misc_revolt.wav") },
123 { &state.sound_ptr->fort_built_sound, NATIVE("Misc_Fortification.wav") },
124 { &state.sound_ptr->railroad_built_sound, NATIVE("Misc_Infrastructure.wav") },
125 { &state.sound_ptr->naval_base_built_sound, NATIVE("Misc_CoalingStation.wav") },
126 { &state.sound_ptr->minor_event_sound, NATIVE("GI_MinorBlip.wav") },
127 { &state.sound_ptr->major_event_sound, NATIVE("Misc_Attention.wav") },
128 { &state.sound_ptr->decline_sound, NATIVE("GI_FailureBlip.wav") },
129 { &state.sound_ptr->accept_sound, NATIVE("GI_SuccessBlip.wav") },
130 { &state.sound_ptr->diplomatic_request_sound, NATIVE("GI_MessageWindow.wav") },
131 { &state.sound_ptr->election_sound, NATIVE("Misc_ElectionHeld.wav") },
132 { &state.sound_ptr->land_battle_sounds[0], NATIVE("Combat_Cavalry_1.wav") },
133 { &state.sound_ptr->land_battle_sounds[1], NATIVE("Combat_Cavalry_2.wav") },
134 { &state.sound_ptr->land_battle_sounds[2], NATIVE("Combat_Cavalry_3.wav") },
135 { &state.sound_ptr->land_battle_sounds[3], NATIVE("Combat_Infantry_1.wav") },
136 { &state.sound_ptr->land_battle_sounds[4], NATIVE("Combat_Infantry_2.wav") },
137 { &state.sound_ptr->land_battle_sounds[5], NATIVE("Combat_Infantry_3.wav") },
138 { &state.sound_ptr->naval_battle_sounds[0], NATIVE("Combat_MajorShip_1.wav") },
139 { &state.sound_ptr->naval_battle_sounds[1], NATIVE("Combat_MajorShip_2.wav") },
140 { &state.sound_ptr->naval_battle_sounds[2], NATIVE("Combat_MajorShip_3.wav") },
141 { &state.sound_ptr->naval_battle_sounds[3], NATIVE("Combat_MinorShip_1.wav") },
142 { &state.sound_ptr->naval_battle_sounds[4], NATIVE("Combat_MinorShip_2.wav") },
143 { &state.sound_ptr->naval_battle_sounds[5], NATIVE("Combat_MinorShip_3.wav") },
144 };
145 auto const sound_directory = simple_fs::open_directory(root_dir, NATIVE("sound"));
146 for(const auto& e : vanilla_sound_table) {
147 auto file_peek = simple_fs::peek_file(sound_directory, e.name);
148 e.audio->set_file(file_peek ? simple_fs::get_full_name(*file_peek) : native_string());
149 }
150 struct {
151 audio_instance* audio;
153 } new_sound_table[] = {
154 { &state.sound_ptr->click_sound, NATIVE("NU_AltClick.wav") },
155 { &state.sound_ptr->click_left_sound, NATIVE("NU_ClickL.wav") },
156 { &state.sound_ptr->click_right_sound, NATIVE("NU_ClickR.wav") },
157 { &state.sound_ptr->console_open_sound, NATIVE("NU_OpenConsole.wav") },
158 { &state.sound_ptr->console_close_sound, NATIVE("NU_CloseConsole.wav") },
159 { &state.sound_ptr->tab_budget_sound, NATIVE("NU_TabBudget.wav") },
160 { &state.sound_ptr->hover_sound, NATIVE("NU_Hover.wav") },
161 { &state.sound_ptr->checkbox_sound, NATIVE("NU_Checkbox.wav") },
162 { &state.sound_ptr->enact_sound, NATIVE("NU_Enact.wav") },
163 { &state.sound_ptr->subtab_sound, NATIVE("NU_Subtab.wav") },
164 { &state.sound_ptr->delete_sound, NATIVE("NU_Delete.wav") },
165 { &state.sound_ptr->autochoose_sound, NATIVE("NU_Autochoose.wav") },
166 { &state.sound_ptr->tab_politics_sound, NATIVE("NU_TabPolitics.wav") },
167 { &state.sound_ptr->tab_diplomacy_sound, NATIVE("NU_TabDiplomacy.wav") },
168 { &state.sound_ptr->tab_military_sound, NATIVE("NU_TabMilitary.wav") },
169 { &state.sound_ptr->tab_population_sound, NATIVE("NU_TabPopulation.wav") },
170 { &state.sound_ptr->tab_production_sound, NATIVE("NU_TabProduction.wav") },
171 { &state.sound_ptr->tab_technology_sound, NATIVE("NU_TabTechnology.wav") },
172 { &state.sound_ptr->tab_military_sound, NATIVE("NU_TabMilitary.wav") },
173 { &state.sound_ptr->event_sound, NATIVE("NU_Event.wav") },
174 { &state.sound_ptr->decision_sound, NATIVE("NU_Decision.wav") },
175 { &state.sound_ptr->pause_sound, NATIVE("NU_Pause.wav") },
176 { &state.sound_ptr->unpause_sound, NATIVE("NU_Unpause.wav") },
177 { &state.sound_ptr->province_select_sounds[0], NATIVE("NU_ProvSelect1.wav") },
178 { &state.sound_ptr->province_select_sounds[1], NATIVE("NU_ProvSelect2.wav") },
179 { &state.sound_ptr->province_select_sounds[2], NATIVE("NU_ProvSelect3.wav") },
180 { &state.sound_ptr->province_select_sounds[3], NATIVE("NU_ProvSelect4.wav") },
181 };
182 auto const assets_directory = simple_fs::open_directory(root_dir, NATIVE("\\assets"));
183 for(const auto& e : new_sound_table) {
184 auto file_peek = simple_fs::peek_file(assets_directory, e.name);
185 e.audio->set_file(file_peek ? simple_fs::get_full_name(*file_peek) : native_string());
186 }
187}
188void change_effect_volume(sys::state& state, float v) {
189 state.sound_ptr->set_volume(state.sound_ptr->effect_sound, v);
190}
191void change_interface_volume(sys::state& state, float v) {
192 state.sound_ptr->set_volume(state.sound_ptr->interface_sound, v);
193}
194void change_music_volume(sys::state& state, float v) {
195 state.sound_ptr->set_volume(state.sound_ptr->music, v);
196}
197
198void play_effect(sys::state& state, audio_instance& s, float volume) {
199 if(state.sound_ptr->global_pause)
200 return;
201 state.sound_ptr->override_sound(state.sound_ptr->effect_sound, s, volume);
202}
203void play_interface_sound(sys::state& state, audio_instance& s, float volume) {
204 if(state.sound_ptr->global_pause)
205 return;
206 state.sound_ptr->override_sound(state.sound_ptr->interface_sound, s, volume);
207}
208
209void stop_music(sys::state& state) {
210 if(state.sound_ptr->music.has_value()) {
211 ma_sound_stop(&*state.sound_ptr->music);
212 }
213}
214void start_music(sys::state& state, float v) {
215 if(v > 0.0f && state.sound_ptr->music_list.size() != 0) {
216 if(state.sound_ptr->first_music != -1) {
217 state.sound_ptr->play_music(state.sound_ptr->first_music, v);
218 } else {
219 if(state.sound_ptr->music.has_value()) {
220 ma_sound_start(&*state.sound_ptr->music);
221 }
222 }
223 }
224}
225
226void pause_all(sys::state& state) {
227 if(state.sound_ptr.get()) {
228 state.sound_ptr->global_pause = true;
229 if(state.sound_ptr->effect_sound.has_value()) {
230 ma_sound_stop(&*state.sound_ptr->effect_sound);
231 }
232 if(state.sound_ptr->interface_sound.has_value()) {
233 ma_sound_stop(&*state.sound_ptr->interface_sound);
234 }
235 if(state.sound_ptr->music.has_value()) {
236 ma_sound_stop(&*state.sound_ptr->music);
237 }
238 }
239}
240void resume_all(sys::state& state) {
241 if(state.sound_ptr.get()) {
242 state.sound_ptr->global_pause = false;
243 if(state.sound_ptr->effect_sound.has_value()) {
244 ma_sound_start(&*state.sound_ptr->effect_sound);
245 }
246 if(state.sound_ptr->interface_sound.has_value()) {
247 ma_sound_start(&*state.sound_ptr->interface_sound);
248 }
249 if(state.sound_ptr->music.has_value()) {
250 ma_sound_start(&*state.sound_ptr->music);
251 }
252 }
253}
254
256 if(state.sound_ptr->music_finished()) {
257 state.sound_ptr->play_new_track(state);
258 }
259}
260
261// returns the default click sound -- expect this list of functions to expand as
262// we implement more of the fixed sound effects
264 return state.sound_ptr->click_sound;
265}
267 return state.sound_ptr->click_left_sound;
268}
270 return state.sound_ptr->click_right_sound;
271}
273 return state.sound_ptr->tab_budget_sound;
274}
276 return state.sound_ptr->hover_sound;
277}
279 return state.sound_ptr->checkbox_sound;
280}
282 return state.sound_ptr->enact_sound;
283}
285 return state.sound_ptr->subtab_sound;
286}
288 return state.sound_ptr->delete_sound;
289}
291 return state.sound_ptr->autochoose_sound;
292}
294 return state.sound_ptr->tab_politics_sound;
295}
297 return state.sound_ptr->tab_diplomacy_sound;
298}
300 return state.sound_ptr->tab_military_sound;
301}
303 return state.sound_ptr->tab_population_sound;
304}
306 return state.sound_ptr->tab_production_sound;
307}
309 return state.sound_ptr->tab_technology_sound;
310}
312 return state.sound_ptr->army_select_sound;
313}
315 return state.sound_ptr->army_move_sound;
316}
318 return state.sound_ptr->navy_select_sound;
319}
321 return state.sound_ptr->navy_move_sound;
322}
324 return state.sound_ptr->error_sound;
325}
327 return state.sound_ptr->peace_sound;
328}
330 return state.sound_ptr->army_built_sound;
331}
333 return state.sound_ptr->navy_built_sound;
334}
336 return state.sound_ptr->declaration_of_war_sound;
337}
339 return state.sound_ptr->technology_finished_sound;
340}
342 return state.sound_ptr->factory_built_sound;
343}
345 return state.sound_ptr->election_sound;
346}
348 return state.sound_ptr->revolt_sound;
349}
351 return state.sound_ptr->fort_built_sound;
352}
354 return state.sound_ptr->railroad_built_sound;
355}
357 return state.sound_ptr->naval_base_built_sound;
358}
360 return state.sound_ptr->minor_event_sound;
361}
363 return state.sound_ptr->major_event_sound;
364}
366 return state.sound_ptr->decline_sound;
367}
369 return state.sound_ptr->accept_sound;
370}
372 return state.sound_ptr->diplomatic_request_sound;
373}
375 return state.sound_ptr->chat_message_sound;
376}
378 return state.sound_ptr->console_open_sound;
379}
381 return state.sound_ptr->console_close_sound;
382}
383
385 return state.sound_ptr->event_sound;
386}
388 return state.sound_ptr->decision_sound;
389}
391 return state.sound_ptr->pause_sound;
392}
394 return state.sound_ptr->unpause_sound;
395}
396
398 return state.sound_ptr->land_battle_sounds[int32_t(std::rand() % 6)];
399}
401 return state.sound_ptr->naval_battle_sounds[int32_t(std::rand() % 6)];
402}
404 return state.sound_ptr->province_select_sounds[int32_t(std::rand() % 4)];
405}
406
408 state.sound_ptr->play_new_track(state);
409}
411 state.sound_ptr->play_next_track(state);
412}
414 state.sound_ptr->play_previous_track(state);
415}
416
418 if(state.sound_ptr->music.has_value())
419 return state.sound_ptr->music_list[state.sound_ptr->current_music].filename;
420 return "";
421}
422
423} // namespace sound
native_string filename
Definition: sound_nix.hpp:10
void set_volume(std::optional< ma_sound > &sound, float volume)
Definition: sound_nix.cpp:28
void play_music(int32_t track, float volume)
Definition: sound_nix.cpp:48
std::vector< audio_instance > music_list
Definition: sound_nix.hpp:80
int32_t last_music
Definition: sound_nix.hpp:81
ma_engine engine
Definition: sound_nix.hpp:29
void play_new_track(sys::state &ws)
Definition: sound_nix.cpp:56
int32_t current_music
Definition: sound_nix.hpp:83
void play_previous_track(sys::state &ws)
Definition: sound_nix.cpp:71
bool music_finished()
Definition: sound_nix.cpp:78
void play_next_track(sys::state &ws)
Definition: sound_nix.cpp:65
std::optional< ma_sound > music
Definition: sound_nix.hpp:27
void override_sound(std::optional< ma_sound > &sound, audio_instance &s, float volume)
Definition: sound_nix.cpp:34
bool native_has_fixed_suffix_ci(char const *start, char const *end, char const (&t)[N])
Definition: parsers.hpp:252
std::vector< unopened_file > list_files(directory const &dir, native_char const *extension)
std::vector< directory > list_subdirectories(directory const &dir)
directory open_directory(directory const &dir, native_string_view directory_name)
directory get_root(file_system const &fs)
native_string get_full_name(directory const &f)
std::optional< unopened_file > peek_file(directory const &dir, native_string_view file_name)
Definition: sound.hpp:15
audio_instance & get_peace_sound(sys::state &state)
Definition: sound_nix.cpp:326
audio_instance & get_minor_event_sound(sys::state &state)
Definition: sound_nix.cpp:359
void pause_all(sys::state &state)
Definition: sound_nix.cpp:226
audio_instance & get_revolt_sound(sys::state &state)
Definition: sound_nix.cpp:347
audio_instance & get_hover_sound(sys::state &state)
Definition: sound_nix.cpp:275
void initialize_sound_system(sys::state &state)
Definition: sound_nix.cpp:84
audio_instance & get_tab_population_sound(sys::state &state)
Definition: sound_nix.cpp:302
void resume_all(sys::state &state)
Definition: sound_nix.cpp:240
audio_instance & get_tab_production_sound(sys::state &state)
Definition: sound_nix.cpp:305
audio_instance & get_army_built_sound(sys::state &state)
Definition: sound_nix.cpp:329
audio_instance & get_event_sound(sys::state &state)
Definition: sound_nix.cpp:384
audio_instance & get_decision_sound(sys::state &state)
Definition: sound_nix.cpp:387
audio_instance & get_tab_budget_sound(sys::state &state)
Definition: sound_nix.cpp:272
audio_instance & get_accept_sound(sys::state &state)
Definition: sound_nix.cpp:368
void play_next_track(sys::state &state)
Definition: sound_nix.cpp:410
void update_music_track(sys::state &state)
Definition: sound_nix.cpp:255
audio_instance & get_technology_finished_sound(sys::state &state)
Definition: sound_nix.cpp:338
void change_effect_volume(sys::state &state, float v)
Definition: sound_nix.cpp:188
audio_instance & get_enact_sound(sys::state &state)
Definition: sound_nix.cpp:281
audio_instance & get_declaration_of_war_sound(sys::state &state)
Definition: sound_nix.cpp:335
audio_instance & get_console_open_sound(sys::state &state)
Definition: sound_nix.cpp:377
audio_instance & get_console_close_sound(sys::state &state)
Definition: sound_nix.cpp:380
audio_instance & get_tab_technology_sound(sys::state &state)
Definition: sound_nix.cpp:308
void stop_music(sys::state &state)
Definition: sound_nix.cpp:209
audio_instance & get_delete_sound(sys::state &state)
Definition: sound_nix.cpp:287
audio_instance & get_unpause_sound(sys::state &state)
Definition: sound_nix.cpp:393
audio_instance & get_click_left_sound(sys::state &state)
Definition: sound_nix.cpp:266
void change_interface_volume(sys::state &state, float v)
Definition: sound_nix.cpp:191
audio_instance & get_random_land_battle_sound(sys::state &state)
Definition: sound_nix.cpp:397
audio_instance & get_click_right_sound(sys::state &state)
Definition: sound_nix.cpp:269
audio_instance & get_naval_base_built_sound(sys::state &state)
Definition: sound_nix.cpp:356
audio_instance & get_tab_politics_sound(sys::state &state)
Definition: sound_nix.cpp:293
audio_instance & get_major_event_sound(sys::state &state)
Definition: sound_nix.cpp:362
native_string get_current_track_name(sys::state &state)
Definition: sound_nix.cpp:417
audio_instance & get_random_province_select_sound(sys::state &state)
Definition: sound_nix.cpp:403
audio_instance & get_railroad_built_sound(sys::state &state)
Definition: sound_nix.cpp:353
audio_instance & get_navy_move_sound(sys::state &state)
Definition: sound_nix.cpp:320
void play_effect(sys::state &state, audio_instance &s, float volume)
Definition: sound_nix.cpp:198
audio_instance & get_random_naval_battle_sound(sys::state &state)
Definition: sound_nix.cpp:400
audio_instance & get_pause_sound(sys::state &state)
Definition: sound_nix.cpp:390
void play_previous_track(sys::state &state)
Definition: sound_nix.cpp:413
audio_instance & get_navy_select_sound(sys::state &state)
Definition: sound_nix.cpp:317
audio_instance & get_checkbox_sound(sys::state &state)
Definition: sound_nix.cpp:278
void start_music(sys::state &state, float v)
Definition: sound_nix.cpp:214
audio_instance & get_decline_sound(sys::state &state)
Definition: sound_nix.cpp:365
audio_instance & get_election_sound(sys::state &state)
Definition: sound_nix.cpp:344
audio_instance & get_navy_built_sound(sys::state &state)
Definition: sound_nix.cpp:332
void play_new_track(sys::state &state)
Definition: sound_nix.cpp:407
audio_instance & get_army_select_sound(sys::state &state)
Definition: sound_nix.cpp:311
audio_instance & get_fort_built_sound(sys::state &state)
Definition: sound_nix.cpp:350
void play_interface_sound(sys::state &state, audio_instance &s, float volume)
Definition: sound_nix.cpp:203
audio_instance & get_diplomatic_request_sound(sys::state &state)
Definition: sound_nix.cpp:371
audio_instance & get_chat_message_sound(sys::state &state)
Definition: sound_nix.cpp:374
audio_instance & get_tab_diplomacy_sound(sys::state &state)
Definition: sound_nix.cpp:296
audio_instance & get_click_sound(sys::state &state)
Definition: sound_nix.cpp:263
audio_instance & get_error_sound(sys::state &state)
Definition: sound_nix.cpp:323
audio_instance & get_subtab_sound(sys::state &state)
Definition: sound_nix.cpp:284
void change_music_volume(sys::state &state, float v)
Definition: sound_nix.cpp:194
audio_instance & get_autochoose_sound(sys::state &state)
Definition: sound_nix.cpp:290
audio_instance & get_factory_built_sound(sys::state &state)
Definition: sound_nix.cpp:341
audio_instance & get_army_move_sound(sys::state &state)
Definition: sound_nix.cpp:314
audio_instance & get_tab_military_sound(sys::state &state)
Definition: sound_nix.cpp:299
#define NATIVE(X)
std::string_view native_string_view
std::string native_string
uint uint32_t
user_settings_s user_settings