3#define MINIAUDIO_IMPLEMENTATION
41 ma_engine_config engine_config;
42 ma_device_id deviceID;
43 ma_device_config deviceConfig;
44 ma_sound_config soundConfig;
48 uint64_t pausePosition;
49 std::thread playbackThread,
51 std::mutex mtx, devicesMutex;
52 std::vector<AudioDevice> devices;
62 MiniAudioPlayer() : isPlaying(false), wasPaused(false), pausePosition(0), deviceSet(false)
64 engine_config = ma_engine_config_init();
65 if (ma_engine_init(&engine_config, &engine) != MA_SUCCESS)
67 throw std::runtime_error(
"Failed to initialize MiniAudio engine.");
70 deviceConfig = ma_device_config_init(ma_device_type_playback);
71 if (ma_context_init(
nullptr, 0,
nullptr, &context) != MA_SUCCESS)
73 throw std::runtime_error(
"Failed to initialize audio context.");
76 if (ma_device_init(
nullptr, &deviceConfig, &device) != MA_SUCCESS)
78 throw std::runtime_error(
"Failed to initialize playback device.");
81 if (ma_device_start(&device) != MA_SUCCESS)
83 ma_device_uninit(&device);
84 throw std::runtime_error(
"Failed to start playback device.");
97 ma_device_uninit(&device);
98 ma_context_uninit(&context);
99 ma_engine_uninit(&engine);
104 std::vector<AudioDevice> localDevices;
106 audioDeviceThread = std::thread(
107 [
this, &localDevices]()
111 ma_device_info* playbackDevices;
112 ma_uint32 playbackDeviceCount;
115 ma_result result = ma_context_get_devices(&context, &playbackDevices,
116 &playbackDeviceCount,
nullptr,
nullptr);
117 if (result != MA_SUCCESS)
119 throw std::runtime_error(
"Failed to enumerate playback devices.");
124 std::lock_guard<std::mutex> lock(devicesMutex);
126 for (ma_uint32 i = 0; i < playbackDeviceCount; ++i)
128 devices.push_back({playbackDevices[i].name, playbackDevices[i].id});
130 localDevices = devices;
133 catch (
const std::exception& e)
135 std::cerr <<
"Error in enumerateDevices thread: " << e.what() <<
"\n";
139 if (audioDeviceThread.joinable())
140 audioDeviceThread.join();
183 auto loadFileAsync(
const std::string& filePath,
bool reloadNextFile) -> std::future<int>
185 return std::async(std::launch::async,
186 [
this, filePath, reloadNextFile]()
188 std::unique_lock<std::mutex> lock(mtx);
204 ma_sound_uninit(&sound);
209 deviceConfig.playback.pDeviceID = &deviceID;
212 if (ma_sound_init_from_file(&engine, filePath.c_str(), MA_SOUND_FLAG_STREAM,
213 nullptr,
nullptr, &sound) != MA_SUCCESS)
215 throw std::runtime_error(
"Failed to load audio file: " + filePath);
232 std::unique_lock<std::mutex> lock(mtx);
233 deviceConfig.playback.pDeviceID = &deviceID;
236 if (ma_sound_start(&sound) != MA_SUCCESS)
238 throw std::runtime_error(
"Failed to play the sound.");
242 if (playbackThread.joinable())
243 playbackThread.join();
246 playbackThread = std::thread(
251 if (!ma_sound_is_playing(&sound))
253 std::unique_lock<std::mutex> lock(mtx);
257 std::this_thread::sleep_for(std::chrono::milliseconds(50));
274 std::unique_lock<std::mutex> lock(mtx);
278 pausePosition = ma_sound_get_time_in_pcm_frames(&sound);
280 if (ma_sound_stop(&sound) != MA_SUCCESS)
282 throw std::runtime_error(
"Failed to pause the sound.");
287 if (playbackThread.joinable())
289 playbackThread.join();
294 throw std::runtime_error(
"No song is playing...");
309 ma_sound_seek_to_pcm_frame(&sound, pausePosition);
323 std::unique_lock<std::mutex> lock(mtx);
326 if (ma_sound_stop(&sound) != MA_SUCCESS)
328 throw std::runtime_error(
"Failed to stop the sound.");
331 ma_sound_seek_to_pcm_frame(&sound, 0);
334 if (playbackThread.joinable())
336 playbackThread.join();
351 if (volume < 0.0f || volume > 1.0f)
353 throw std::invalid_argument(
"Volume must be between 0.0 and 1.0.");
355 ma_sound_set_volume(&sound, volume);
365 [[nodiscard]]
auto getVolume() const ->
float {
return ma_sound_get_volume(&sound); }
376 std::unique_lock<std::mutex> lock(mtx);
390 return std::async(std::launch::async,
393 std::unique_lock<std::mutex> lock(mtx);
394 if (ma_sound_get_time_in_milliseconds(&sound) != MA_SUCCESS)
396 throw std::runtime_error(
"Failed to get sound duration.");
399 float duration = 0.0f;
400 ma_result result = ma_sound_get_length_in_seconds(&sound, &duration);
401 if (result != MA_SUCCESS)
403 throw std::runtime_error(
"Failed to get sound duration. Result: " +
404 std::to_string(result));
423 std::unique_lock<std::mutex> lock(mtx);
426 ma_uint32 sampleRate = ma_engine_get_sample_rate(&engine);
429 ma_uint64 totalFrames;
430 ma_result result = ma_sound_get_length_in_pcm_frames(&sound, &totalFrames);
431 if (result != MA_SUCCESS)
433 std::cerr <<
"Failed to get total PCM frames." << std::endl;
437 ma_uint64 currentFrames = ma_sound_get_time_in_pcm_frames(&sound);
441 static_cast<ma_int64
>(currentFrames) +
static_cast<ma_int64
>(seconds) * sampleRate;
445 newFrames = seconds = 0;
446 if (
static_cast<ma_uint64
>(newFrames) > totalFrames)
447 newFrames = totalFrames;
449 result = ma_sound_seek_to_pcm_frame(&sound,
static_cast<ma_uint64
>(newFrames));
450 if (result != MA_SUCCESS)
452 std::cerr <<
"Failed to seek sound." << std::endl;
455 return (
double)seconds;
459 throw std::runtime_error(
"-- Audio is not playing, cannot seek time");
473 std::vector<std::string> details;
476 ma_uint32 sampleRate = ma_engine_get_sample_rate(&engine);
479 details.emplace_back(
"WARNING: Could not detect sample rate, using default 44100 Hz");
484 ma_uint32 channels = deviceConfig.playback.channels;
487 details.emplace_back(
"WARNING: Could not detect channels, using default stereo");
492 ma_format format = deviceConfig.playback.format;
493 if (format == ma_format_unknown)
495 details.emplace_back(
"WARNING: Could not detect format, using default f32");
496 format = ma_format_f32;
500 details.emplace_back(
"=== Audio Playback Details ===");
503 details.emplace_back(
"\nAudio Configuration:");
505 std::ostringstream oss;
506 oss <<
" Sample Rate: " << sampleRate <<
" Hz";
507 details.emplace_back(oss.str());
511 details.emplace_back(oss.str());
515 details.emplace_back(oss.str());
519 details.emplace_back(
"\nPlayback State:");
521 std::ostringstream oss;
523 details.emplace_back(oss.str());
525 oss <<
" Looping: " << (soundConfig.isLooping ?
"Yes" :
"No");
526 details.emplace_back(oss.str());
544 return "Quadraphonic";
555 std::ostringstream oss;
556 oss << channels <<
" channels";
567 return "32-bit float";
569 return "16-bit signed PCM";
571 return "8-bit unsigned PCM";
573 return "24-bit signed PCM";
575 return "32-bit signed PCM";
577 return "Unknown format";
auto enumerateDevices() -> std::vector< AudioDevice >
Definition audio_playback.hpp:102
auto getChannelLayoutString(ma_uint32 channels) const -> std::string
Definition audio_playback.hpp:533
auto getPlaybackStateString() const -> std::string
Definition audio_playback.hpp:600
auto isCurrentlyPlaying() -> bool
Checks if the sound is currently playing.
Definition audio_playback.hpp:374
auto loadFileAsync(const std::string &filePath, bool reloadNextFile) -> std::future< int >
Sets the device ID for playback.
Definition audio_playback.hpp:183
auto seekTime(int seconds) -> double
Seeks to a specific time in the audio (in seconds).
Definition audio_playback.hpp:419
void resume()
Resumes playback from the last paused position.
Definition audio_playback.hpp:304
auto getBitsPerSample(ma_format format) const -> uint32_t
Definition audio_playback.hpp:581
void stop()
Stops the playback and resets the playback position.
Definition audio_playback.hpp:321
auto getDurationAsync() -> std::future< float >
Gets the total duration of the sound in seconds. (async function)
Definition audio_playback.hpp:388
auto getFormatString(ma_format format) const -> std::string
Definition audio_playback.hpp:562
void pause()
Pauses the current audio playback.
Definition audio_playback.hpp:272
void setVolume(float volume)
Sets the volume of the audio playback.
Definition audio_playback.hpp:349
auto getVolume() const -> float
Gets the current volume of the audio playback.
Definition audio_playback.hpp:365
MiniAudioPlayer()
Constructs a MiniAudioPlayer object and initializes the MiniAudio engine.
Definition audio_playback.hpp:62
~MiniAudioPlayer()
Destroys the MiniAudioPlayer object, stopping any playback and cleaning up resources.
Definition audio_playback.hpp:94
void play()
Starts playback of the loaded audio file.
Definition audio_playback.hpp:230
auto getAudioPlaybackDetails() const -> std::vector< std::string >
Gets detailed information about the current audio playback configuration.
Definition audio_playback.hpp:471
A structure representing an audio playback device.
Definition audio_playback.hpp:20
std::string name
Definition audio_playback.hpp:21
ma_device_id id
Definition audio_playback.hpp:22