aboutsummaryrefslogtreecommitdiff
path: root/extension/src/openvic-extension/singletons/SoundSingleton.hpp
blob: 67305a9f4cfc4b7b45f4b6340d39423a23181683 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#pragma once

#include <godot_cpp/core/class_db.hpp>
#include <godot_cpp/core/object.hpp>
#include <godot_cpp/variant/string.hpp>
#include <godot_cpp/variant/string_name.hpp>

#include <godot_cpp/classes/file_access.hpp>
#include <godot_cpp/classes/audio_stream.hpp>
#include <godot_cpp/classes/audio_stream_mp3.hpp>
#include <godot_cpp/classes/audio_stream_wav.hpp>
#include <godot_cpp/templates/vector.hpp>

#include <openvic-simulation/types/OrderedContainers.hpp>
#include <openvic-simulation/types/IdentifierRegistry.hpp>
#include <openvic-simulation/types/fixed_point/FixedPoint.hpp>

namespace OpenVic {

   class SoundSingleton : public godot::Object {

      GDCLASS(SoundSingleton, godot::Object);

      static inline SoundSingleton* _singleton = nullptr;

      //cache of songs
      //names will be like "subfolder/songname", with "music/" base folder and the extension (.mp3) being excluded
      using song_asset_map_t = deque_ordered_map<godot::StringName, godot::Ref<godot::AudioStreamMP3>>;
      song_asset_map_t tracks;

      //cache of sfx (map file name to an audio stream), only used temporarily until the sfx_define_map is built
      using sfx_asset_map_t = deque_ordered_map<godot::StringName, godot::Ref<godot::AudioStreamWAV>>;
      sfx_asset_map_t sfx;

      //define name, stream ref, volume for sound effects so we can get these properties with a simple call in godot
      struct sound_asset_t {
         std::optional<godot::Ref<godot::AudioStreamWAV>> audioStream;
         std::optional<fixed_point_t> volume;
      };
      using sfx_define_map_t = deque_ordered_map<godot::StringName,sound_asset_t>;
      sfx_define_map_t sfx_define;

      static constexpr std::string_view title_theme_name = "thecoronation_titletheme.mp3";
      static constexpr std::string_view music_folder = "music/";
      static constexpr std::string_view sound_folder = "sound/";

      //property for gd scripts to access song names
      godot::Array PROPERTY(song_list);
      godot::String PROPERTY(title_theme);

      //property for gd scripts to access sound names
      godot::Array PROPERTY(sound_list);

   public:
      SoundSingleton();
      ~SoundSingleton();
      static SoundSingleton* get_singleton();

   protected:
      static void _bind_methods();

      godot::String to_define_file_name(godot::String const& path, std::string_view const& base_folder) const;
      godot::String read_riff_str(godot::Ref<godot::FileAccess> const& file, int size=4) const;

   private:
      /* Loads AudioStreams (.mp3 or .wav) at runtime using godot's functions*/
      godot::Ref<godot::AudioStreamMP3> _load_godot_mp3(godot::String const& path) const;
      godot::Ref<godot::AudioStreamWAV> _load_godot_wav(godot::String const& path) const;

   public:
      //gets a song from the cache ('tracks' variable), or if not, then from the files using _load_godot_mp3
      godot::Ref<godot::AudioStreamMP3> get_song(godot::String const& name);
      godot::Ref<godot::AudioStreamWAV> get_sound(godot::String const& path);

      //load the files into memory
      bool load_music();
      bool load_sounds();
      bool load_title_theme();

      //for sound effects, get the stream and relative volume it should play at from the sfx map
      godot::Ref<godot::AudioStreamWAV> get_sound_stream(godot::String const& path);
      float get_sound_base_volume(godot::String const& path);

   };
}