BARE2D
AudioManager.cpp
Go to the documentation of this file.
1 #include "AudioManager.hpp"
2 
3 #include <SDL2/SDL_mixer.h>
4 
5 #include "BAREErrors.hpp"
6 
7 namespace BARE2D
8 {
9 
10  AudioManager* AudioManager::m_instance = nullptr;
11 
13  {
14  if(!m_instance) {
15  m_instance = new AudioManager();
16  }
17  return m_instance;
18  }
19 
21  {
22  if(m_instance) {
24  delete m_instance;
25  }
26  }
27 
29  {
30  }
31 
33  {
34  }
35 
36 
38  {
39  // Load all of the DLLs which may or may not exist on our system.
40  int initedFlags = Mix_Init(MIX_INIT_FLAC | MIX_INIT_MOD | MIX_INIT_MP3 | MIX_INIT_OGG);
41 
42  // Check each flag, and report if it couldn't be inited.
43  if(!(initedFlags & MIX_INIT_FLAC)) {
44  // Couldn't init .flac extension. report
46  }
47  if(!(initedFlags & MIX_INIT_MOD)) {
48  // Couldn't init .mod extension. report
50  }
51  if(!(initedFlags & MIX_INIT_MP3)) {
52  // Couldn't init .mp3 extension. report
54  }
55  if(!(initedFlags & MIX_INIT_OGG)) {
56  // Couldn't init .ogg extension. report
58  }
59 
60  // Now actually open the API and allow calls to the library
61  // The default frequency is a decent middleground for weaker and stronger CPUs but still sounds good
62  // The default format is "Signed 16-bit samples, in system byte order"
63  // There will be 2 output channels open (for stereo) - this is different than the mixer channels, which are what sounds are actually played in
64  // Each chunk will be of size 1024 - this is a decent size as our hooks will not be called too often, but audio won't skip either.
65  Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 2, 1024);
66 
67  // Arbitrarily allocate a bunch of channels.
68  Mix_AllocateChannels(32); // 32 is almost definitely going to be enough for anything reasonable. This can be jacked up, however.
69  }
70 
72  {
73  // Clean up SDL
74  // Get how many times we called Mix_OpenAudio (the dummies store the frequency, format, and the number of channels)
75  unsigned int numTimesOpened;
76  int dummyA, dummyC;
77  Uint16 dummyB;
78  numTimesOpened = Mix_QuerySpec(&dummyA, &dummyB, &dummyC);
79  // Check for errors
80  if(numTimesOpened == 0) {
82  }
83 
84  // Actually close each mixer.
85  for(unsigned int i = 0; i < numTimesOpened; i++)
86  Mix_CloseAudio();
87 
88  while(Mix_Init(0)) // This makes sure that no matter how many DLLs are loaded, we quit them all.
89  Mix_Quit();
90  }
91 
92  unsigned int AudioManager::playSound(Sound& sound, unsigned int fadeTime, unsigned int timeOut, int angle, unsigned char distance)
93  {
94  int channel = -1;
95  if(fadeTime > 0) {
96  if(timeOut > 0) {
97  // Fade + Timeout
98  // -1 represents the first available chunk
99  // It will loop 0 times
100  channel = Mix_FadeInChannelTimed(-1, sound.chunk, 0, fadeTime, timeOut);
101  } else {
102  // Just Fade - no timeout
103  // -1 represents the first available chunk
104  channel = Mix_FadeInChannel(-1, sound.chunk, 0, fadeTime);
105  }
106  } else {
107  if(timeOut > 0) {
108  channel = Mix_PlayChannelTimed(-1, sound.chunk, 0, timeOut);
109  } else {
110  channel = Mix_PlayChannel(-1, sound.chunk, 0);
111  }
112  }
113  if(channel == -1) {
114  throwFatalError(BAREError::SDL_MIXER_SOUND_FAILURE, "Failed to play sound: " + std::string(Mix_GetError()));
115  }
116  return (unsigned int)channel;
117  }
118 
119  void AudioManager::moveSound(unsigned int& soundID, int angle, unsigned char distance)
120  {
121  if(!Mix_SetPosition(soundID, angle, distance)) {
122  throwFatalError(BAREError::SDL_MIXER_SOUND_FAILURE, "Failed to move sound: " + std::string(Mix_GetError()));
123  }
124  }
125 
126  void AudioManager::stopSound(unsigned int& soundID, unsigned int fadeTime)
127  {
128  if(fadeTime > 0) {
129  Mix_FadeOutChannel(soundID, fadeTime);
130  } else {
131  Mix_HaltChannel(soundID);
132  }
133  }
134 
135  void AudioManager::pauseSound(unsigned int& soundID)
136  {
137  Mix_Pause(soundID);
138  }
139 
140  void AudioManager::resumeSound(unsigned int& soundID)
141  {
142  Mix_Resume(soundID);
143  }
144 
145  void AudioManager::playMusic(Music& music, unsigned int fadeTime)
146  {
147  int error = -1;
148  if(fadeTime > 0) {
149  // Never loops, fades.
150  error = Mix_FadeInMusic(music.music, 0, fadeTime);
151  } else {
152  // Never loops, doesn't fade.
153  error = Mix_PlayMusic(music.music, 0);
154  }
155  if(error == -1) {
156  throwFatalError(BAREError::SDL_MIXER_SOUND_FAILURE, "Failed to play music: " + std::string(Mix_GetError()));
157  }
158  }
159 
160  void AudioManager::stopMusic(unsigned int fadeTime)
161  {
162  if(fadeTime > 0) {
163  Mix_FadeOutMusic(fadeTime);
164  } else {
165  Mix_HaltMusic();
166  }
167  }
168 
170  {
171  Mix_PauseMusic();
172  }
173 
175  {
176  Mix_ResumeMusic();
177  }
178 
180  {
181  if(m_muted) return;
182 
183  // Get the original volumes and set the current volumes to 0 (muted)
184  m_soundVolume = Mix_Volume(-1, 0);
185  m_musicVolume = Mix_VolumeMusic(0);
186  m_muted = true;
187  }
188 
190  {
191  if(!m_muted) return;
192  m_muted = false;
193 
194  Mix_Volume(-1, m_soundVolume);
195  Mix_VolumeMusic(m_musicVolume);
196  }
197 
198  void AudioManager::setSoundVolume(unsigned char volumeLevel)
199  {
200  m_soundVolume = volumeLevel * m_masterVolume;
201  Mix_Volume(-1, m_soundVolume / (255 * 255) * 128); // Normalize the volume from 0-128 (that's the mixer max)
202  }
203 
204  void AudioManager::setMusicVolume(unsigned char volumeLevel)
205  {
206  m_musicVolume = volumeLevel * m_masterVolume;
207  Mix_VolumeMusic(m_musicVolume / (255 * 255) * 128); // Normalize the volume from 0-128 (that's the mixer max)
208  }
209 
210  void AudioManager::setMasterVolumeModifier(unsigned char masterLevel)
211  {
212  // First, get the oldl music and sound volumes before the master adjustment.
215 
216  m_masterVolume = masterLevel;
217 
218  // Now reset the new music and sound volumes
221  }
222 
224  {
225  return Mix_PlayingMusic();
226  }
227 
228 }
BARE2D::Sound
Definition: Sound.hpp:7
utf8::distance
std::iterator_traits< octet_iterator >::difference_type distance(octet_iterator first, octet_iterator last)
Definition: checked.h:198
BARE2D::AudioManager::resumeMusic
void resumeMusic()
Resumes the paused music.
Definition: AudioManager.cpp:174
BARE2D::AudioManager::m_masterVolume
unsigned char m_masterVolume
Definition: AudioManager.hpp:120
BARE2D::AudioManager::resumeSound
void resumeSound(unsigned int &soundID)
Resumes a paused sound.
Definition: AudioManager.cpp:140
BARE2D
Definition: App.cpp:13
BARE2D::BAREError::SDL_MIXER_FLAC_FAILURE
@ SDL_MIXER_FLAC_FAILURE
BARE2D::BAREError::SDL_MIXER_SOUND_FAILURE
@ SDL_MIXER_SOUND_FAILURE
BARE2D::AudioManager::playMusic
void playMusic(Music &music, unsigned int fadeTime=0)
Plays some music! Only one "music" can be played at a time.
Definition: AudioManager.cpp:145
BARE2D::AudioManager::m_instance
static AudioManager * m_instance
Definition: AudioManager.hpp:118
BARE2D::Music
Definition: Music.hpp:7
BARE2D::AudioManager::setMusicVolume
void setMusicVolume(unsigned char volumeLevel)
Sets the volume level of all music.
Definition: AudioManager.cpp:204
BARE2D::BAREError::SDL_MIXER_CLOSE_FAILURE
@ SDL_MIXER_CLOSE_FAILURE
BARE2D::BAREError::SDL_MIXER_OGG_FAILURE
@ SDL_MIXER_OGG_FAILURE
BARE2D::AudioManager::isMusicPlaying
bool isMusicPlaying()
Definition: AudioManager.cpp:223
BARE2D::AudioManager::setSoundVolume
void setSoundVolume(unsigned char volumeLevel)
Sets the volume level of all sounds.
Definition: AudioManager.cpp:198
AudioManager.hpp
The AudioManager acts as a friendly wrapper for the SDL_Mixer library. It basically just plays sounds...
BARE2D::AudioManager::pauseSound
void pauseSound(unsigned int &soundID)
Pauses a sound.
Definition: AudioManager.cpp:135
BAREErrors.hpp
BARE2D::AudioManager::~AudioManager
~AudioManager()
Definition: AudioManager.cpp:32
BARE2D::throwError
void throwError(BAREError err, std::string message)
Throws an error silently. Adds it to the pile.
Definition: BAREErrors.cpp:190
BARE2D::AudioManager::release
static void release()
Definition: AudioManager.cpp:20
BARE2D::AudioManager::init
void init()
Initializes all necessary bits and pieces.
Definition: AudioManager.cpp:37
BARE2D::AudioManager::pauseMusic
void pauseMusic()
Pauses the music.
Definition: AudioManager.cpp:169
BARE2D::AudioManager::unmute
void unmute()
Unmutes all sounds and music.
Definition: AudioManager.cpp:189
BARE2D::AudioManager::stopSound
void stopSound(unsigned int &soundID, unsigned int fadeTime=0)
Stops a sound.
Definition: AudioManager.cpp:126
BARE2D::Sound::chunk
Mix_Chunk * chunk
Definition: Sound.hpp:8
BARE2D::BAREError::SDL_MIXER_MP3_FAILURE
@ SDL_MIXER_MP3_FAILURE
BARE2D::AudioManager::playSound
unsigned int playSound(Sound &sound, unsigned int fadeTime=0, unsigned int timeOut=0, int angle=0, unsigned char distance=128)
Plays a sound at a position.
Definition: AudioManager.cpp:92
BARE2D::AudioManager::AudioManager
AudioManager()
Definition: AudioManager.cpp:28
BARE2D::AudioManager::getInstance
static AudioManager * getInstance()
Definition: AudioManager.cpp:12
BARE2D::AudioManager::setMasterVolumeModifier
void setMasterVolumeModifier(unsigned char masterLevel)
Sets the modifier of all sound levels - eg., if sounds were set at 40% and music at 60%,...
Definition: AudioManager.cpp:210
BARE2D::BAREError::SDL_MIXER_MOD_FAILURE
@ SDL_MIXER_MOD_FAILURE
BARE2D::AudioManager::stopMusic
void stopMusic(unsigned int fadeTime=0)
Stops the music.
Definition: AudioManager.cpp:160
BARE2D::AudioManager::m_muted
bool m_muted
Definition: AudioManager.hpp:121
BARE2D::AudioManager::m_soundVolume
unsigned char m_soundVolume
Definition: AudioManager.hpp:120
BARE2D::AudioManager
Definition: AudioManager.hpp:14
BARE2D::Music::music
Mix_Music * music
Definition: Music.hpp:8
BARE2D::AudioManager::mute
void mute()
Mutes all sounds and music.
Definition: AudioManager.cpp:179
BARE2D::throwFatalError
void throwFatalError(BAREError err, std::string message)
Throws an error (fatal). Also calls displayErrors and exits the program.
Definition: BAREErrors.cpp:178
BARE2D::AudioManager::destroy
void destroy()
Destroys/quits all necessary bits and pieces.
Definition: AudioManager.cpp:71
BARE2D::AudioManager::moveSound
void moveSound(unsigned int &soundID, int angle, unsigned char distance=128)
Resets the sound's position for positional audio.
Definition: AudioManager.cpp:119
BARE2D::AudioManager::m_musicVolume
unsigned char m_musicVolume
Definition: AudioManager.hpp:120