Search code examples
c++linuxaudiosdlsdl-mixer

No sound when using SDL_Mixer in C++/Linux


I'm trying to use SDL_mixer in C++ under Linux to play sounds asynchronously, but it somehow doesn't work. When I execute it, no sound is playing at all. I'm not quite familiar with SDL and classes though, so it would be very helpful if someone could detect where the error in my code is.

My header file (sample.h):

#pragma once
#include <string>
#include <memory>
#include "SDL_mixer.h"

class sample {
public:
    sample(const std::string &path, int volume);
    void play();
    void play(int times);
    void set_volume(int volume);

private:
    std::unique_ptr<Mix_Chunk, void (*)(Mix_Chunk *)> chunk;
};

My main program (.cpp):

#include "sample.h"
#include <iostream>

sample::sample(const std::string &path, int volume) : chunk(Mix_LoadWAV(path.c_str()), Mix_FreeChunk) {
    if (!chunk.get()) {
        std::cout << "Could not load audio sample: " << path << std::endl;
    }
    Mix_VolumeChunk(chunk.get(), volume);
}

void sample::play() {
    Mix_PlayChannel(-1, chunk.get(), 0);
}

void sample::play(int times) {
    Mix_PlayChannel(-1, chunk.get(), times - 1);
}

void sample::set_volume(int volume) {
    Mix_VolumeChunk(chunk.get(), volume);
}

int main() {
    if (Mix_Init(MIX_INIT_FLAC | MIX_INIT_MP3 | MIX_INIT_OGG) < 0) {
        return -1;
    }

    if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 1024) < 0) {
        std::cout << "Can not initialize mixer!" << std::endl;
        return -1;
    }

    // Amount of channels (Max amount of sounds playing at the same time)
    Mix_AllocateChannels(32);

    sample s("Snare-Drum-1.wav", MIX_MAX_VOLUME / 2);

    s.play();

    Mix_Quit();
    return 0;
}

Solution

  • Your binary runs and finishes before phaffing about long enough to render the audio so solution is to make the code remain running longer ... I got your code working by adding this

    s.play();
    
    std::chrono::milliseconds timespan(2000); // or whatever
    std::this_thread::sleep_for(timespan);
    

    in your header replace

    #include "SDL_mixer.h"
    

    with

    #include <SDL2/SDL_mixer.h>
    #include <chrono>
    #include <thread>
    

    so now its compiled using SDL2 and not SDL

    g++ -o sample sample.cpp -lSDL2   -lSDL2_mixer 
    

    So .... what is the real SDL2 solution ? well I would say a typical use case is SDL2 is part of a game which remains running hence the code base has an event loop which remains active long enough to hear the audio getting rendered. Another solution short of explicitly using a sleep or a gui is to put the code into a server ... SDL2 api itself must have their one-liner as well