From 2130d95ed5765a332dedc3ffe583ad1a9e8bf974 Mon Sep 17 00:00:00 2001 From: fegger Date: Thu, 18 Jun 2026 14:44:18 +0200 Subject: [PATCH] add PlaybackEngine --- include/PlaybackEngine.h | 40 +++++++++++++++++++++++++ src/PlaybackEngine.cpp | 63 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 include/PlaybackEngine.h create mode 100644 src/PlaybackEngine.cpp diff --git a/include/PlaybackEngine.h b/include/PlaybackEngine.h new file mode 100644 index 0000000..3ac0e06 --- /dev/null +++ b/include/PlaybackEngine.h @@ -0,0 +1,40 @@ +#pragma once + +#include "miniaudio.h" + +#include +#include + +struct PlaybackState { + ma_decoder decoder{}; + std::atomic finished{ false }; +}; + +class PlaybackEngine { +public: + PlaybackEngine(); + ~PlaybackEngine(); + + static void data_callback( ma_device* pDevice, void* pOutput, const void*, ma_uint32 frameCount ); + void configureDevice(); + void configureDecoder(); + void initDevice(); + void initDecoder( const char* filePath ); + + void startPlayback(); + void stopPlayback(); + void pausePlayback() { stopPlayback(); }; + int isFinished() const; + +private: + + ma_device device_; + ma_format format_; + unsigned int channels_; + unsigned int sampleRate_; + PlaybackState state; + + //config + ma_decoder_config decoderConfig; + ma_device_config deviceConfig; +}; diff --git a/src/PlaybackEngine.cpp b/src/PlaybackEngine.cpp new file mode 100644 index 0000000..3a81844 --- /dev/null +++ b/src/PlaybackEngine.cpp @@ -0,0 +1,63 @@ +#include "../include/PlaybackEngine.h" +#include "../include/miniaudio.h" +#include +#include + + +using PE = PlaybackEngine; + +PE::PlaybackEngine(){ + configureDecoder(); + configureDevice(); +} + +PE::~PlaybackEngine() { + ma_device_uninit( &device_); + ma_decoder_uninit( &state.decoder ); +} + + void PE::data_callback( ma_device* pDevice, void* pOutput, const void*, ma_uint32 frameCount ){ + std::unique_ptr state = std::unique_ptr ( static_cast( pDevice->pUserData )); + ma_uint64 framesRead = 0; + ma_result result = ma_decoder_read_pcm_frames( &state->decoder, pOutput, frameCount, &framesRead ); + if ( result != MA_SUCCESS || framesRead < frameCount ) { state->finished.store(true); } + }; + + void PE::configureDevice() { + ma_device_config deviceConfig = ma_device_config_init( ma_device_type_playback ); + + deviceConfig.playback.format = state.decoder.outputFormat; + deviceConfig.playback.channels = state.decoder.outputChannels; + deviceConfig.sampleRate = state.decoder.outputSampleRate; + deviceConfig.dataCallback = PE::data_callback; + deviceConfig.pUserData = &state; + } + + void PE::configureDecoder(){ + ma_decoder_config decoderConfig = ma_decoder_config_init( format_, 0, sampleRate_ ); + } + + void PE::initDevice(){ + if ( ma_device_init( nullptr, &deviceConfig, &device_ ) != MA_SUCCESS ) { + throw std::runtime_error( "failed to open file."); + } + } + +void PE::initDecoder( const char* filePath ) { + if ( ma_decoder_init_file( filePath, &decoderConfig, &state.decoder) != MA_SUCCESS ){ + throw std::runtime_error( "Failed to open {filePath}."); + } +} + + void PE::startPlayback(){ + //ma_decoder_init_file( filePath, &decoderConfig, &decoder ); + if ( ma_device_start( &device_ ) != MA_SUCCESS ) { + throw std::runtime_error( "Failed to start playback device.\n"); + ma_device_uninit( &device_ ); + ma_decoder_uninit( &state.decoder ); + } + } + + void PE::stopPlayback() { + ma_device_stop( &device_ ); + }