fix(audio): 修复音频系统初始化及资源加载问题
- 修改音频系统初始化逻辑,增加备用初始化参数 - 优化音乐和音效加载方式,直接加载文件而非内存 - 增加错误日志输出,便于排查问题 - 更新MingW平台构建脚本,完善依赖DLL复制
This commit is contained in:
@@ -12,7 +12,7 @@ struct AudioConfig {
|
||||
int frequency = 44100;
|
||||
uint16_t format = 0x8010;
|
||||
int channels = 2;
|
||||
int chunksize = 2048;
|
||||
int chunksize = 4096;
|
||||
int maxSoundChannels = 32;
|
||||
};
|
||||
|
||||
|
||||
@@ -24,10 +24,16 @@ bool AudioSystem::init(const AudioConfig& config) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Mix_OpenAudio(config.frequency, config.format, config.channels, config.chunksize) < 0) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to open audio: %s", Mix_GetError());
|
||||
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
||||
return false;
|
||||
int frequency = config.frequency;
|
||||
uint16_t format = config.format;
|
||||
int channels = config.channels;
|
||||
|
||||
if (Mix_OpenAudio(frequency, format, channels, config.chunksize) < 0) {
|
||||
if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, config.chunksize) < 0) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to open audio: %s", Mix_GetError());
|
||||
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
maxChannels_ = config.maxSoundChannels;
|
||||
@@ -36,7 +42,6 @@ bool AudioSystem::init(const AudioConfig& config) {
|
||||
initialized_ = true;
|
||||
updateVolumes();
|
||||
|
||||
SDL_Log("Audio system initialized");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -51,7 +56,6 @@ void AudioSystem::shutdown() {
|
||||
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
||||
|
||||
initialized_ = false;
|
||||
SDL_Log("Audio system shutdown");
|
||||
}
|
||||
|
||||
void AudioSystem::setMasterVolume(float volume) {
|
||||
|
||||
@@ -9,17 +9,15 @@ namespace frostbite2D {
|
||||
|
||||
Ptr<Music> Music::loadFromFile(const std::string& path) {
|
||||
auto& asset = Asset::get();
|
||||
auto data = asset.readFileToBytes(path);
|
||||
if (!data) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to read music file: %s", path.c_str());
|
||||
std::string fullPath = asset.resolvePath(path);
|
||||
|
||||
Mix_Music* music = Mix_LoadMUS(fullPath.c_str());
|
||||
if (!music) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to load music from file %s: %s", fullPath.c_str(), Mix_GetError());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto music = loadFromMemory(data->data(), data->size());
|
||||
if (music) {
|
||||
music->path_ = path;
|
||||
}
|
||||
return music;
|
||||
return Ptr<Music>(new Music(music, path));
|
||||
}
|
||||
|
||||
Ptr<Music> Music::loadFromMemory(const uint8* data, size_t size) {
|
||||
@@ -51,6 +49,7 @@ Music::~Music() {
|
||||
|
||||
bool Music::play(int loops) {
|
||||
if (!music_) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Music is null");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -62,7 +61,12 @@ bool Music::play(int loops) {
|
||||
int vol = static_cast<int>(volume_ * AudioSystem::get().getMusicVolume() * AudioSystem::get().getMasterVolume() * MIX_MAX_VOLUME);
|
||||
Mix_VolumeMusic(vol);
|
||||
|
||||
return Mix_PlayMusic(music_, loops) == 0;
|
||||
if (Mix_PlayMusic(music_, loops) == 0) {
|
||||
return true;
|
||||
} else {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to play music: %s", Mix_GetError());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Music::fadeIn(int ms, int loops) {
|
||||
|
||||
@@ -9,17 +9,15 @@ namespace frostbite2D {
|
||||
|
||||
Ptr<Sound> Sound::loadFromFile(const std::string& path) {
|
||||
auto& asset = Asset::get();
|
||||
auto data = asset.readFileToBytes(path);
|
||||
if (!data) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to read sound file: %s", path.c_str());
|
||||
std::string fullPath = asset.resolvePath(path);
|
||||
|
||||
Mix_Chunk* chunk = Mix_LoadWAV(fullPath.c_str());
|
||||
if (!chunk) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to load sound from file %s: %s", fullPath.c_str(), Mix_GetError());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto sound = loadFromMemory(data->data(), data->size());
|
||||
if (sound) {
|
||||
sound->path_ = path;
|
||||
}
|
||||
return sound;
|
||||
return Ptr<Sound>(new Sound(chunk, path));
|
||||
}
|
||||
|
||||
Ptr<Sound> Sound::loadFromMemory(const uint8* data, size_t size) {
|
||||
@@ -51,6 +49,7 @@ Sound::~Sound() {
|
||||
|
||||
int Sound::play(int loops, int channel) {
|
||||
if (!chunk_) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Sound chunk is null");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -62,7 +61,11 @@ int Sound::play(int loops, int channel) {
|
||||
int vol = static_cast<int>(volume_ * AudioSystem::get().getSoundVolume() * AudioSystem::get().getMasterVolume() * MIX_MAX_VOLUME);
|
||||
Mix_VolumeChunk(chunk_, vol);
|
||||
|
||||
return Mix_PlayChannel(channel, chunk_, loops);
|
||||
int result = Mix_PlayChannel(channel, chunk_, loops);
|
||||
if (result == -1) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to play sound: %s", Mix_GetError());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void Sound::setVolume(float volume) {
|
||||
|
||||
@@ -103,7 +103,9 @@ int main(int argc, char **argv) {
|
||||
|
||||
auto bgMusic = Music::loadFromFile("assets/BackgroundMusic.mp3");
|
||||
if (bgMusic) {
|
||||
bgMusic->play();
|
||||
bgMusic->play();
|
||||
} else {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to load background music!");
|
||||
}
|
||||
|
||||
app.run();
|
||||
|
||||
@@ -33,15 +33,16 @@ target("Frostbite2D")
|
||||
print("Copy assets directory: " .. assets_dir .. " -> " .. target_assets_dir)
|
||||
end
|
||||
|
||||
-- 复制 SDL2 和 SDL2_mixer DLL (Windows 平台)
|
||||
-- 复制所有依赖的 DLL (Windows 平台)
|
||||
if is_plat("mingw") or is_plat("windows") then
|
||||
for _, pkg_name in ipairs({"libsdl2", "libsdl2_mixer"}) do
|
||||
-- 复制所有包的 DLL 文件
|
||||
local all_pkgs = {"libsdl2", "libsdl2_image", "libsdl2_mixer"}
|
||||
for _, pkg_name in ipairs(all_pkgs) do
|
||||
local pkg = target:pkg(pkg_name)
|
||||
if pkg then
|
||||
local libfiles = pkg:get("libfiles")
|
||||
if libfiles then
|
||||
for _, libfile in ipairs(libfiles) do
|
||||
-- 查找 DLL 文件
|
||||
if libfile:endswith(".dll") then
|
||||
local target_dll = path.join(output_dir, path.filename(libfile))
|
||||
os.cp(libfile, target_dll)
|
||||
@@ -52,21 +53,31 @@ target("Frostbite2D")
|
||||
end
|
||||
end
|
||||
|
||||
-- 尝试从 xmake 包目录复制 SDL2 和 SDL2_mixer DLL
|
||||
local dll_paths = {
|
||||
path.join(os.getenv("USERPROFILE") or "", ".xmake/packages/l/libsdl2/**/bin/SDL2.dll"),
|
||||
path.join(os.getenv("USERPROFILE") or "", ".xmake/packages/l/libsdl2/**/lib/SDL2.dll"),
|
||||
path.join(os.getenv("USERPROFILE") or "", ".xmake/packages/l/libsdl2_mixer/**/bin/SDL2_mixer.dll"),
|
||||
path.join(os.getenv("USERPROFILE") or "", ".xmake/packages/l/libsdl2_mixer/**/lib/SDL2_mixer.dll"),
|
||||
-- 从 xmake 包目录复制所有可能的依赖 DLL
|
||||
local user_profile = os.getenv("USERPROFILE") or ""
|
||||
local packages_dir = path.join(user_profile, ".xmake/packages/l")
|
||||
|
||||
local common_dll_patterns = {
|
||||
path.join(packages_dir, "libogg/**/*.dll"),
|
||||
path.join(packages_dir, "libvorbis/**/*.dll"),
|
||||
path.join(packages_dir, "libvorbisfile/**/*.dll"),
|
||||
path.join(packages_dir, "libmpg123/**/*.dll"),
|
||||
path.join(packages_dir, "libflac/**/*.dll"),
|
||||
path.join(packages_dir, "libsndfile/**/*.dll"),
|
||||
path.join(packages_dir, "libmodplug/**/*.dll"),
|
||||
path.join(packages_dir, "opus/**/*.dll"),
|
||||
path.join(packages_dir, "opusfile/**/*.dll"),
|
||||
path.join(packages_dir, "**/*.dll")
|
||||
}
|
||||
|
||||
for _, dll_pattern in ipairs(dll_paths) do
|
||||
for _, dll_pattern in ipairs(common_dll_patterns) do
|
||||
local dll_files = os.files(dll_pattern)
|
||||
for _, dll_file in ipairs(dll_files) do
|
||||
local target_dll = path.join(output_dir, path.filename(dll_file))
|
||||
local dll_name = path.filename(dll_file)
|
||||
local target_dll = path.join(output_dir, dll_name)
|
||||
if not os.isfile(target_dll) then
|
||||
os.cp(dll_file, target_dll)
|
||||
print("Copy DLL from: " .. dll_file)
|
||||
print("Copy dependency DLL: " .. dll_name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user