added music
This commit is contained in:
1 parent
a1dda3fd50
commit
b5bcd3a812
9 files changed
+306
-92
No files matched your search
+131
-57
@@ -1,7 +1,5 @@
|
||||
#ifdef AUDIO
|
||||
|
||||
#include "AudioPlayerAsync.h"
|
||||
|
||||
#include "AudioPlayerAsync.h"
|
||||
#include <iostream>
|
||||
|
||||
AudioPlayerAsync::AudioPlayerAsync() : worker(&AudioPlayerAsync::workerThread, this) {}
|
||||
|
||||
@@ -11,62 +9,144 @@ AudioPlayerAsync::~AudioPlayerAsync() {
|
||||
stop = true;
|
||||
cv.notify_all();
|
||||
}
|
||||
worker.join();
|
||||
if (worker.joinable())
|
||||
worker.join();
|
||||
shutdown();
|
||||
}
|
||||
|
||||
void AudioPlayerAsync::stopAsync() {
|
||||
std::unique_lock<std::mutex> lock(mtx);
|
||||
taskQueue.push([this]() {
|
||||
//audioPlayerMutex.lock();
|
||||
audioPlayer->stop();
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
//audioPlayerMutex.unlock();
|
||||
});
|
||||
cv.notify_one();
|
||||
bool AudioPlayerAsync::init() {
|
||||
if (initialized) return true;
|
||||
|
||||
if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
|
||||
std::cerr << "SDL_InitSubSystem(SDL_INIT_AUDIO) failed: " << SDL_GetError() << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048) < 0) {
|
||||
std::cerr << "Mix_OpenAudio failed: " << Mix_GetError() << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
Mix_AllocateChannels(16);
|
||||
|
||||
initialized = true;
|
||||
std::cout << "AudioPlayerAsync initialized with SDL2_mixer" << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
void AudioPlayerAsync::resetAsync() {
|
||||
std::unique_lock<std::mutex> lock(mtx);
|
||||
taskQueue.push([this]() {
|
||||
//audioPlayerMutex.lock();
|
||||
audioPlayer.reset();
|
||||
audioPlayer = std::make_unique<AudioPlayer>();
|
||||
|
||||
//audioPlayerMutex.unlock();
|
||||
});
|
||||
cv.notify_one();
|
||||
}
|
||||
void AudioPlayerAsync::shutdown() {
|
||||
if (!initialized) return;
|
||||
|
||||
void AudioPlayerAsync::playSoundAsync(std::string soundName) {
|
||||
|
||||
soundNameMutex.lock();
|
||||
latestSoundName = soundName;
|
||||
soundNameMutex.unlock();
|
||||
|
||||
std::unique_lock<std::mutex> lock(mtx);
|
||||
taskQueue.push([this]() {
|
||||
//audioPlayerMutex.lock();
|
||||
if (audioPlayer) {
|
||||
audioPlayer->playSound(latestSoundName);
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(soundCacheMutex);
|
||||
for (auto& pair : soundCache) {
|
||||
Mix_FreeChunk(pair.second);
|
||||
}
|
||||
soundCache.clear();
|
||||
}
|
||||
|
||||
Mix_CloseAudio();
|
||||
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
||||
initialized = false;
|
||||
std::cout << "AudioPlayerAsync shutdown" << std::endl;
|
||||
}
|
||||
|
||||
void AudioPlayerAsync::playSoundAsync(const std::string& filePath, int loops, int channel) {
|
||||
if (!initialized) {
|
||||
std::cerr << "AudioPlayerAsync not initialized" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
std::unique_lock<std::mutex> lock(mtx);
|
||||
taskQueue.push([this, filePath, loops, channel]() {
|
||||
Mix_Chunk* sound = nullptr;
|
||||
{
|
||||
std::lock_guard<std::mutex> cacheLock(soundCacheMutex);
|
||||
auto it = soundCache.find(filePath);
|
||||
if (it != soundCache.end()) {
|
||||
sound = it->second;
|
||||
}
|
||||
}
|
||||
|
||||
if (!sound) {
|
||||
sound = Mix_LoadWAV(filePath.c_str());
|
||||
if (!sound) {
|
||||
std::cerr << "Failed to load sound " << filePath << ": " << Mix_GetError() << std::endl;
|
||||
return;
|
||||
}
|
||||
std::lock_guard<std::mutex> cacheLock(soundCacheMutex);
|
||||
soundCache[filePath] = sound;
|
||||
}
|
||||
|
||||
int result = Mix_PlayChannel(channel, sound, loops);
|
||||
if (result == -1) {
|
||||
std::cerr << "Mix_PlayChannel failed: " << Mix_GetError() << std::endl;
|
||||
}
|
||||
//audioPlayerMutex.unlock();
|
||||
});
|
||||
cv.notify_one();
|
||||
}
|
||||
|
||||
void AudioPlayerAsync::playMusicAsync(std::string musicName) {
|
||||
|
||||
musicNameMutex.lock();
|
||||
latestMusicName = musicName;
|
||||
musicNameMutex.unlock();
|
||||
void AudioPlayerAsync::playMusicAsync(const std::string& filePath, int loops) {
|
||||
if (!initialized) return;
|
||||
|
||||
std::unique_lock<std::mutex> lock(mtx);
|
||||
taskQueue.push([this]() {
|
||||
//audioPlayerMutex.lock();
|
||||
if (audioPlayer) {
|
||||
audioPlayer->playMusic(latestMusicName);
|
||||
taskQueue.push([this, filePath, loops]() {
|
||||
Mix_Music* music = Mix_LoadMUS(filePath.c_str());
|
||||
if (!music) {
|
||||
std::cerr << "Failed to load music " << filePath << ": " << Mix_GetError() << std::endl;
|
||||
return;
|
||||
}
|
||||
//audioPlayerMutex.unlock();
|
||||
if (Mix_PlayMusic(music, loops) == -1) {
|
||||
std::cerr << "Mix_PlayMusic failed: " << Mix_GetError() << std::endl;
|
||||
Mix_FreeMusic(music);
|
||||
}
|
||||
});
|
||||
cv.notify_one();
|
||||
}
|
||||
|
||||
void AudioPlayerAsync::stopMusicAsync() {
|
||||
if (!initialized) return;
|
||||
std::unique_lock<std::mutex> lock(mtx);
|
||||
taskQueue.push([]() {
|
||||
Mix_HaltMusic();
|
||||
});
|
||||
cv.notify_one();
|
||||
}
|
||||
|
||||
void AudioPlayerAsync::pauseMusicAsync() {
|
||||
if (!initialized) return;
|
||||
std::unique_lock<std::mutex> lock(mtx);
|
||||
taskQueue.push([]() {
|
||||
Mix_PauseMusic();
|
||||
});
|
||||
cv.notify_one();
|
||||
}
|
||||
|
||||
void AudioPlayerAsync::resumeMusicAsync() {
|
||||
if (!initialized) return;
|
||||
std::unique_lock<std::mutex> lock(mtx);
|
||||
taskQueue.push([]() {
|
||||
Mix_ResumeMusic();
|
||||
});
|
||||
cv.notify_one();
|
||||
}
|
||||
|
||||
void AudioPlayerAsync::setMusicVolume(int volume) {
|
||||
if (!initialized) return;
|
||||
volume = std::max(0, std::min(128, volume));
|
||||
std::unique_lock<std::mutex> lock(mtx);
|
||||
taskQueue.push([volume]() {
|
||||
Mix_VolumeMusic(volume);
|
||||
});
|
||||
cv.notify_one();
|
||||
}
|
||||
|
||||
void AudioPlayerAsync::setSoundVolume(int volume) {
|
||||
if (!initialized) return;
|
||||
volume = std::max(0, std::min(128, volume));
|
||||
std::unique_lock<std::mutex> lock(mtx);
|
||||
taskQueue.push([volume]() {
|
||||
Mix_Volume(-1, volume); // все каналы
|
||||
});
|
||||
cv.notify_one();
|
||||
}
|
||||
@@ -76,18 +156,12 @@ void AudioPlayerAsync::workerThread() {
|
||||
std::function<void()> task;
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mtx);
|
||||
cv.wait(lock, [this]() { return !taskQueue.empty() || stop; });
|
||||
|
||||
if (stop && taskQueue.empty()) {
|
||||
cv.wait(lock, [this] { return !taskQueue.empty() || stop; });
|
||||
if (stop && taskQueue.empty())
|
||||
break;
|
||||
}
|
||||
|
||||
task = taskQueue.front();
|
||||
task = std::move(taskQueue.front());
|
||||
taskQueue.pop();
|
||||
}
|
||||
|
||||
task();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
+23
-31
@@ -1,53 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef AUDIO
|
||||
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
#include <SDL2/SDL_mixer.h>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <queue>
|
||||
#include <thread>
|
||||
#include <condition_variable>
|
||||
#include <functional>
|
||||
#include "cmakeaudioplayer/include/AudioPlayer.hpp"
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
class AudioPlayerAsync {
|
||||
public:
|
||||
AudioPlayerAsync();
|
||||
~AudioPlayerAsync();
|
||||
|
||||
void resetAsync();
|
||||
bool init();
|
||||
void shutdown();
|
||||
|
||||
void playSoundAsync(std::string soundName);
|
||||
void playSoundAsync(const std::string& filePath, int loops = 0, int channel = -1);
|
||||
void playMusicAsync(const std::string& filePath, int loops = -1);
|
||||
void stopMusicAsync();
|
||||
void pauseMusicAsync();
|
||||
void resumeMusicAsync();
|
||||
void setMusicVolume(int volume); // 0..128
|
||||
void setSoundVolume(int volume); // 0..128
|
||||
|
||||
void playMusicAsync(std::string musicName);
|
||||
|
||||
void stopAsync();
|
||||
|
||||
void exit()
|
||||
{
|
||||
stop = true;
|
||||
}
|
||||
|
||||
std::thread worker;
|
||||
void exit() { stop = true; }
|
||||
|
||||
private:
|
||||
std::unique_ptr<AudioPlayer> audioPlayer;
|
||||
//std::mutex audioPlayerMutex;
|
||||
|
||||
std::mutex soundNameMutex;
|
||||
std::mutex musicNameMutex;
|
||||
|
||||
std::string latestSoundName;
|
||||
std::string latestMusicName;
|
||||
void workerThread();
|
||||
|
||||
std::thread worker;
|
||||
std::mutex mtx;
|
||||
std::condition_variable cv;
|
||||
std::queue<std::function<void()>> taskQueue;
|
||||
bool stop = false;
|
||||
|
||||
void workerThread();
|
||||
std::unordered_map<std::string, Mix_Chunk*> soundCache;
|
||||
std::mutex soundCacheMutex;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
bool initialized = false;
|
||||
};
|
||||
+21
-2
@@ -55,6 +55,7 @@ namespace ZL
|
||||
: newTickCount(0)
|
||||
, lastTickCount(0)
|
||||
, menuManager(renderer)
|
||||
, audioPlayer(std::make_unique<AudioPlayerAsync>())
|
||||
{
|
||||
}
|
||||
|
||||
@@ -211,6 +212,15 @@ namespace ZL
|
||||
|
||||
loadingCompleted = true;
|
||||
|
||||
if (audioPlayer->init()) {
|
||||
audioPlayer->setMusicVolume(100);
|
||||
audioPlayer->setSoundVolume(80);
|
||||
std::cout << "Audio initialized successfully" << std::endl;
|
||||
}
|
||||
else {
|
||||
std::cout << "Audio initialization failed" << std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Game::drawUI()
|
||||
@@ -472,12 +482,21 @@ namespace ZL
|
||||
}
|
||||
}
|
||||
|
||||
if (event.type == SDL_KEYDOWN/* && dialogueSystem.handleKeyDown(event.key.keysym.sym)*/) {
|
||||
/*if (event.type == SDL_KEYDOWN/* && dialogueSystem.handleKeyDown(event.key.keysym.sym)) {
|
||||
continue;
|
||||
}
|
||||
}*/
|
||||
|
||||
if (event.type == SDL_KEYDOWN && event.key.repeat == 0) {
|
||||
switch (event.key.keysym.sym) {
|
||||
case SDLK_1:
|
||||
if (audioPlayer) audioPlayer->playSoundAsync("resources/sounds/background.wav");
|
||||
break;
|
||||
case SDLK_2:
|
||||
if (audioPlayer) audioPlayer->playMusicAsync("resources/sounds/lullaby-music-vol20-186394--online-audio-convert.com.ogg");
|
||||
break;
|
||||
case SDLK_3:
|
||||
if (audioPlayer) audioPlayer->stopMusicAsync();
|
||||
break;
|
||||
case SDLK_f:
|
||||
currentLocation->dialogueSystem.startDialogue("test_cutscene_pan_dialogue_silent");
|
||||
break;
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include "Location.h"
|
||||
#include "AudioPlayerAsync.h"
|
||||
|
||||
namespace ZL {
|
||||
|
||||
@@ -56,6 +57,7 @@ namespace ZL {
|
||||
bool rightMouseDown = false;
|
||||
int lastMouseX = 0;
|
||||
int lastMouseY = 0;
|
||||
std::unique_ptr<AudioPlayerAsync> audioPlayer;
|
||||
|
||||
int64_t getSyncTimeMs();
|
||||
void processTickCount();
|
||||
|
||||
Reference in new issue
Block a user