我正在用C ++制作游戏,但是我遇到了一个问题,当涉及到声音时我无法弄清楚。我正在使用SDL_Mixer,Mix_Music用于音乐,Mix_Chunk用于音效,但出于某种原因,当我尝试使用MIX_LoadWAV加载声音效果文件时,它返回NULL。
问题是,当我使用MIX_LoadMUS加载相同的文件(加载为音乐而不是音效)时,它加载正常。
我找不到可以解释这个问题的任何差异;唯一的区别是Mix_LoadWAV而不是Mix_LoadMUS,但为什么呢? Mix_LoadMUS不适用于Mix_Chunk,否则我只是使用它,但......
在这里,我将向您展示我使用的声音管理器的代码。 MusicClip是Mix_Music,SoundClip是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;
}
这是MusicClip和SoundClip的代码;除了我将PlayOnce和fadeout添加到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;
}
这是我用来调用函数的代码。 (SoundManager在程序的早期初始化,以启动BGM。)因此,使用Mix_Chunk * SFX2,这将无效:
void GameState::playSFX(std::string FX)
{
SFX2 = soundManager.CreateSoundClip("../assets/sfx/sfx-bleep.wav");
SFX2->Volume(60);
SFX2->Play();
}
但出于某种原因,如果我将SFX2更改为Mix_Music *,则可以正常工作。
void GameState::playSFX(std::string FX)
{
SFX2 = soundManager.CreateMusicClip("../assets/sfx/sfx-bleep.wav");
SFX2->Volume(60);
SFX2->Play();
}
我该怎么办? Mix_GetError()也没有返回任何内容...如果我写错了路径它会返回“无法打开文件”,所以很明显它可以找到/打开文件,它只是......不会?我不能只使用Mix_Music作为我的音效,因为如果我这样做,他们会取消音乐。
顺便说一句,我不知道它是否相关,但Mix_LoadMUS不会加载非wav文件,即使它也应该支持.ogg和.mp3?