add PlaybackEngine
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
#include "miniaudio.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
|
||||
struct PlaybackState {
|
||||
ma_decoder decoder{};
|
||||
std::atomic<bool> 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;
|
||||
};
|
||||
@@ -0,0 +1,63 @@
|
||||
#include "../include/PlaybackEngine.h"
|
||||
#include "../include/miniaudio.h"
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
|
||||
|
||||
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<PlaybackState> state = std::unique_ptr<PlaybackState> ( static_cast<PlaybackState*>( 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_ );
|
||||
}
|
||||
Reference in New Issue
Block a user