I'm creating a class to interface with SDL Mixer in C++ so I can play sounds in my application. However, it looks like my sounds do not finish playing and I can't hear them at all.
Here's what my class looks like:
//Standard libraries used
#include<unordered_map>
#include<vector>
//Include classes for the library
#include "classes/s_soundData.h"
#include "classes/s_soundController.h"
#include "classes/s_soundPlaylist.h"
//SDL
#include<SDL2/SDL.h>
#include<SDL2/SDL_mixer.h>
class mySoundClass
{
public:
/*** Member variables ***/
unordered_map<std::string, unordered_map<std::string, s_soundData> > sounds; //Container of all sounds
unordered_map<std::string, s_soundPlaylist> playlists; //Contains all of the playlists created with the stevensSound library
unordered_map<std::string, s_soundController> soundControllers; //Container of all sound controllers. Controls volume and playback settings for sounds.
/*** Constructors ***/
//Default constructor
mySoundClass()
{
//Initialize SDL
if( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_AUDIO ) < 0 )
{
printf( "SDL could not initialize! SDL Error: %s\n", SDL_GetError() );
}
//Initialize SDL_mixer
if( Mix_OpenAudio( 44100, MIX_DEFAULT_FORMAT, 2, 2048 ) < 0 )
{
printf( "SDL_mixer could not initialize! SDL_mixer Error: %s\n", Mix_GetError() );
}
//Create music, sfx, and default sound controllers
soundControllers = { {"music", s_soundController("music",1)},
{"sfx", s_soundController("sfx",1)},
{"default", s_soundController()} };
//With no parameters, we just initialize our sound container to be empty
sounds = {};
//Also initialize our playlists container to be empty
playlists = {};
}
/*** Destructor ***/
~ mySoundClass()
{
//Quit SDL subsystems on destruction
Mix_Quit();
SDL_Quit();
}
/*** Methods ***/
void playSound( std::string soundName,
std::string category )
/*
Plays a sound effect using the SDL library's functions
*/
{
//Get the sound's data and its controller
s_soundData soundData = sounds[category][soundName];
s_soundController soundController = soundControllers[soundData.controllerId];
//Load the sound file into memory
Mix_Chunk* sound = NULL;
sound = Mix_LoadWAV(soundData.filePath);
//Control the playback
Mix_VolumeChunk(sound, (int)round(128 * soundController.volume));
//Play the sound
Mix_PlayChannel( -1, sound, 0 );
}
};
I used this tutorial to guide myself in setting up SDL: https://lazyfoo.net/tutorials/SDL/21_sound_effects_and_music/index.php
I'm calling the playSound()
method from my main.cpp file. I have made sure that the sound is loaded correctly and that the volume is set to maximum by printing the MixChunk's member variables to stdout.
Other posts here said to run usleep()
or SDL_Delay()
until the sound is finished playing in the function to have the sound actually play in-full, but I have tried this and it seems to produce the same result of not having the sound play each time.
One thing I do notice though is that SDL appears in my audio mixer as an application for a split-second whenever I try to call playSound()
.
Also, an earlier iteration of this program did work, but it was when all the functions were defined at the global scope instead of the scope of just this individual class.
What worked to fix this problem was calling SDL_Init()
Mix_OpenAudio()
functions outside of the constructor function in this library. Instead, I called these functions from a function defined at the global scope before the construction of the mySoundClass
object. For some reason unstated in the documentation, calling these functions inside of an object constructor causes problems.
Documentation for Mix_OpenAudio()
: https://wiki.libsdl.org/SDL2_mixer/Mix_OpenAudio
Documentation for SDL_Init()
: https://wiki.libsdl.org/SDL2/SDL_Init