// // Created by david on 01.02.2026. // #define LOG_TAG "PlaybackEngine" #include "PlaybackEngine.h" #include "logging.h" #include "mpg123.h" #include "mp3file.h" #include static inline int readBuffer2(MP3File* mp3) { size_t done = 0; int err = mpg123_read(mp3->handle, mp3->buffer, mp3->buffer_size, &done); mp3->leftSamples = done / sizeof(int16_t); mp3->offset = 0; return err != MPG123_OK ? 0 : done; } static bool read_mp3(std::string filename, std::vector& samples) { // TODO: assumes 48000 Hz sampling rate of the file // note: our resource file is mono (1 channel = 1 samples_per_frame)! MP3File *mFile = mp3file_open(filename.c_str(), 0); // MPG123_ENC_FLOAT_32 (but does not seem to work) bool ok1 = mFile != nullptr; bool ok2 = readBuffer2(mFile) != 0; // once is enough (maybe the other one needs to pre-fill other buffers, in oboe etc.) if(ok1 && ok2) { // num_frames, num_samples, samples_per_frame samples.resize(mFile->num_samples); for(int i = 0; i < mFile->num_samples; i++) { int16_t *src = ((int16_t *) mFile->buffer) + i; samples[i] = (*src) / 32768.0f; } } if(mFile) mp3file_delete(mFile); return ok1 && ok2; } PlaybackEngine::PlaybackEngine(std::string filesDir, int resid): mFilesDir(filesDir) { LOGI("PlaybackEngine()"); LOGI("NDK LOG_LEVEL=%d", LOG_LEVEL); // NDK LOG_LEVEL=3 (DEBUG) std::vector samples; read_mp3(mFilesDir + "/" + std::to_string(resid) + ".mp3", samples); mPlayer = new MixingPlayer(samples); int32_t res = mPlayer->startAudio(); LOGI("startAudio() = %d", res); } PlaybackEngine::~PlaybackEngine() { LOGI("~PlaybackEngine()"); mPlayer->stopAudio(); delete mPlayer; mPlayer = nullptr; } void PlaybackEngine::playBeat() { if(mPlayer) mPlayer->setStartBeat(); }