20c0f9744f
Replace Metadata.h with Containers.h, introducing a HashTable implementation with SIMD acceleration and specialized track tracking. Cleanup PlayerEngine logic by merging it into the playback flow and refactoring several internal API signatures.
76 lines
2.4 KiB
C++
76 lines
2.4 KiB
C++
#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::uninitDecoder() {
|
|
ma_decoder_uninit( &state.decoder );
|
|
}
|
|
|
|
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_ ); }
|
|
|
|
void PE::seek ( ma_uint64 frame ) {
|
|
auto decoder = state.decoder;
|
|
ma_decoder_seek_to_pcm_frame ( &state.decoder, frame );
|
|
}
|
|
|
|
uint64_t PE::getPosition () {
|
|
ma_decoder_get_cursor_in_pcm_frames ( &state.decoder, &cursor_ );
|
|
return cursor_;
|
|
}
|