open-story-teller/shared/audio_player.cpp

129 lines
2.7 KiB
C++

#include <functional>
#include <stdio.h>
#include "audio_player.h"
#include <SDL3_mixer/SDL_mixer.h>
#include <stdio.h>
static int audio_open = 0;
static Mix_Music *music = NULL;
static int next_track = 0;
SDL_AudioSpec spec;
static ThreadSafeQueue<AudioCommand> g_audioQueue;
void music_finished()
{
Mix_FreeMusic(music);
music = NULL;
g_audioQueue.push({"end", ""});
}
AudioPlayer::AudioPlayer(IAudioEvent &event)
: m_event(event)
{
m_audioThread = std::thread( std::bind(&AudioPlayer::AudioThread, this) );
}
void AudioPlayer::Initialize()
{
/* Initialize variables */
spec.freq = MIX_DEFAULT_FREQUENCY;
spec.format = MIX_DEFAULT_FORMAT;
spec.channels = MIX_DEFAULT_CHANNELS;
if (Mix_Init(MIX_INIT_FLAC | MIX_INIT_MP3 | MIX_INIT_OGG) < 0) {
return ;
}
if (Mix_OpenAudio(0, &spec) < 0) {
SDL_Log("Couldn't open audio: %s\n", SDL_GetError());
return;
} else {
Mix_QuerySpec(&spec.freq, &spec.format, &spec.channels);
SDL_Log("Opened audio at %d Hz %d bit%s %s audio buffer\n", spec.freq,
(spec.format&0xFF),
(SDL_AUDIO_ISFLOAT(spec.format) ? " (float)" : ""),
(spec.channels > 2) ? "surround" : (spec.channels > 1) ? "stereo" : "mono");
}
audio_open = 1;
Mix_HookMusicFinished(music_finished);
}
void AudioPlayer::Play(const std::string &filename)
{
// On coupe le son en cours
g_audioQueue.clear();
Mix_HaltMusic();
Mix_FreeMusic(music);
g_audioQueue.push({"play", filename});
}
AudioPlayer::~AudioPlayer()
{
// Quit audio thread
g_audioQueue.clear();
g_audioQueue.push({"quit", ""});
if (m_audioThread.joinable())
{
m_audioThread.join();
}
}
void AudioPlayer::Stop()
{
g_audioQueue.clear();
g_audioQueue.push({"end", ""});
}
#define AUDIO_STATE_WAIT_PLAY 1
#define AUDIO_STATE_WAIT_END 2
void AudioPlayer::AudioThread()
{
int state = AUDIO_STATE_WAIT_PLAY;
for (;;)
{
auto cmd = g_audioQueue.front();
g_audioQueue.pop();
if (cmd.order == "quit")
{
return;
}
else if (cmd.order == "play")
{
if (state == AUDIO_STATE_WAIT_PLAY)
{
state = AUDIO_STATE_WAIT_END;
music = Mix_LoadMUS(cmd.filename.c_str());
if (music)
{
Mix_PlayMusic(music, 0);
}
}
}
else if (cmd.order == "end")
{
if (state == AUDIO_STATE_WAIT_END)
{
state = AUDIO_STATE_WAIT_PLAY;
Mix_HaltMusic();
Mix_FreeMusic(music);
m_event.EndOfAudio();
}
}
}
}