c++sdlsdl-mixer

SDL Mixer sounds not playing with PlayChannel()


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.


Solution

  • 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