2

I'm making a game in C++, but I've been running into an issue I just can't figure out when it comes to the sound. I'm using SDL_Mixer, with Mix_Music for the music and Mix_Chunk for the sound effects, but for some reason when I try to load a sound effect file using MIX_LoadWAV it returns NULL.

The thing is, when I load the same file using MIX_LoadMUS (loading as music instead of sound effect), it loads fine.

I can't find any differences that would explain the issue; the only difference is Mix_LoadWAV instead of Mix_LoadMUS, but why? Mix_LoadMUS doesn't work for Mix_Chunk, or else I'd just use that, but ...

Here, I'll show you the code for the sound manager I use. MusicClip being a Mix_Music and SoundClip being a Mix_Chunk.

#include "stdafx.h"
#include "SoundManager.h"
#include "MusicClip.h"
#include "SoundClip.h"

SoundManager::SoundManager()
{
}

SoundManager::~SoundManager()
{
    Shutdown();
}

bool SoundManager::Initialize()
{
    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0)
    {
        printf("SDL could not initialize! SDL Error: %s\n", SDL_GetError());
    }

    if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048) < 0)
    {
        printf(" SDL_mixer :: Msx_OpenAudio %s\n", Mix_GetError());
        return false;
    }

    return true;
}

void SoundManager::Shutdown()
{
    for (unsigned int i = 0; i < m_axSoundClips.size(); i++)
    {
        delete m_axSoundClips[i];
        m_axSoundClips[i] = nullptr;
    }
    m_axSoundClips.clear();

    for (unsigned int i = 0; i < m_axMusicClips.size(); i++)
    {
        delete m_axMusicClips[i];
        m_axMusicClips[i] = nullptr;
    }
    m_axMusicClips.clear();

    {
        std::map<std::string, Mix_Chunk*>::iterator it = m_axSounds.begin();
        while (it != m_axSounds.end())
        {
            Mix_FreeChunk(it->second);
            it->second = nullptr;
            it++;
        }
        m_axSounds.clear();
    }

    {
        std::map<std::string, Mix_Music*>::iterator it = m_axMusic.begin();
        while (it != m_axMusic.end())
        {
            Mix_FreeMusic(it->second);
            it->second = nullptr;
            it++;
        }
        m_axMusic.clear();
    }

    Mix_CloseAudio();
}

MusicClip *SoundManager::CreateMusicClip(std::string p_sFilename)
{
    MusicClip *Ret = nullptr;

    std::map<std::string, Mix_Music*>::iterator it = m_axMusic.find(p_sFilename);
    if (it == m_axMusic.end())
    {
        Mix_Music* Music = Mix_LoadMUS(p_sFilename.c_str());
        if (Music == NULL) {
            printf("Error; music will not play\n");
            printf(p_sFilename.c_str());
            printf("\n");
            printf(Mix_GetError());
        }
        std::pair<std::string, Mix_Music*> Pair;
        Pair = std::make_pair(p_sFilename, Music);
        Ret = new MusicClip(Music);
    }
    else
        Ret = new MusicClip(it->second);

    m_axMusicClips.push_back(Ret);

    return Ret;
}

SoundClip *SoundManager::CreateSoundClip(std::string p_sFilename)
{
    SoundClip *Ret = nullptr;
    std::map<std::string, Mix_Chunk*>::iterator it = m_axSounds.find(p_sFilename);

    if (it == m_axSounds.end())
    {

        Mix_Chunk* Sound = Mix_LoadWAV(p_sFilename.c_str());

        if (Sound == NULL) {
            printf("\nError; sound will not play\n");
            printf(p_sFilename.c_str());
            printf("\n");
            printf(Mix_GetError());
        }
        std::pair<std::string, Mix_Chunk*> Pair;
        Pair = std::make_pair(p_sFilename, Sound);
        Ret = new SoundClip(Sound);
    }
    else
        Ret = new SoundClip(it->second);

    m_axSoundClips.push_back(Ret);

    return Ret;
}

Here's the code for MusicClip and SoundClip; They seem identical aside from me adding PlayOnce and fadeout to MusicClip.

#include "stdafx.h"
#include "SoundClip.h"

SoundClip::SoundClip()
{
    m_pxClip = nullptr;
    m_iChannel = -1;
}

SoundClip::~SoundClip()
{
    m_pxClip = nullptr;
}

SoundClip::SoundClip(Mix_Chunk* p_pxClip)
{
    m_pxClip = p_pxClip;
    m_iChannel = -1;
}

void SoundClip::Play()
{
    m_iChannel = Mix_PlayChannel(-1, m_pxClip, 0);
}

void SoundClip::Stop()
{
    if (m_iChannel == -1)
        return;

    Mix_HaltChannel(m_iChannel);
    m_iChannel = -1;
}

void SoundClip::Volume(int p_iVolume)
{
    if (m_iChannel == -1)
        return;

    Mix_Volume(m_iChannel, p_iVolume);
}

void SoundClip::Pause()
{
    if (m_iChannel == -1)
        return;

    if (Mix_Paused(m_iChannel))
    {
        Mix_Resume(m_iChannel);
    }
    else
    {
        Mix_Pause(m_iChannel);
    }
}

-

// MusicClip.cpp
#include "stdafx.h" 
#include "MusicClip.h"

MusicClip::MusicClip()
{
    m_xClip = nullptr;
    m_iChannel = -1;
}

MusicClip::~MusicClip()
{
    m_xClip = nullptr;
    m_iChannel = -1;
}

MusicClip::MusicClip(Mix_Music* p_xClip)
{
    m_xClip = p_xClip;
    m_iChannel = -1;
}

void MusicClip::Play()
{
    m_iChannel = Mix_PlayMusic(m_xClip, -1);
}

void MusicClip::PlayOnce()
{
    m_iChannel = Mix_PlayMusic(m_xClip, 1);
}

void MusicClip::Pause()
{
    if (m_iChannel == -1)
        return;

    if ( Mix_PausedMusic() )
        Mix_ResumeMusic();
    else
        Mix_Pause(m_iChannel);
}

void MusicClip::Volume(int p_iVolume)
{
    Mix_VolumeMusic(p_iVolume);
    oldVolume = p_iVolume;
}

void MusicClip::FadeOut()
{
    if (oldVolume>0)
        oldVolume--;
    Mix_VolumeMusic(oldVolume);
}

void MusicClip::Stop()
{
    if (m_iChannel == -1)
             return;

    Mix_HaltChannel(m_iChannel);
    m_iChannel = -1;
}

And this is the code I use to call on the functions. (The soundManager was initialized earlier in the program to start up the BGM.) So this, using the Mix_Chunk* SFX2, won't work:

void GameState::playSFX(std::string FX)
{
    SFX2 = soundManager.CreateSoundClip("../assets/sfx/sfx-bleep.wav");
    SFX2->Volume(60);
    SFX2->Play();
}

But for some reason, if I change SFX2 to a Mix_Music*, this DOES work.

void GameState::playSFX(std::string FX)
{
SFX2 = soundManager.CreateMusicClip("../assets/sfx/sfx-bleep.wav");
    SFX2->Volume(60);
    SFX2->Play();
}

What do I do? Mix_GetError() doesn't return anything either... If I write the path wrong it returns "couldn't open file", so clearly it can find/open the file, it just... won't? I can't just use Mix_Music for my sound effects either, because if I do they cancel out the music.

By the way, I don't know if it's related, but Mix_LoadMUS won't load non-wav files even though it's supposed to support .ogg and .mp3 too?

genpfault
  • 51,148
  • 11
  • 85
  • 139
CuteCat
  • 21
  • 3

0 Answers0