// // Created by david on 01.02.2026. // #define LOG_TAG "PlaybackEngine" #include "PlaybackEngine.h" #include "logging.h" #include "mpg123.h" #include "mp3file.h" #include /* allocated 2304 bytes buffer blanking the buffer ... filling 24543 num_samples readBuffer2() k=0 in readBuffer2() on mp3 != null: 1 in readBuffer2() remaining_samples=24543 offset=0 in readBuffer2() handle != null: 1 in readBuffer2() done=2304 copying 1152 samples, k=0 */ static inline int readBuffer2(MP3File* mp3) { //LOGI("in readBuffer2() on mp3 != null: %d", mp3 != nullptr); //if(mp3 == nullptr) return 0; //LOGI("in readBuffer2() remaining_samples=%d offset=%d", mp3->remaining_samples, mp3->offset); size_t done = 0; //LOGI("in readBuffer2() handle != null: %d", mp3->handle != nullptr); int err = mpg123_read(mp3->handle, mp3->buffer, mp3->buffer_size, &done); //LOGI("in readBuffer2() done=%d", done); mp3->remaining_samples -= done / sizeof(int16_t); mp3->offset = 0; if (err != MPG123_OK) LOGI("err=%d done=%d", err, done); // err=-12 if(err == MPG123_DONE) return done / sizeof(int16_t); return err != MPG123_OK ? 0 : done / sizeof(int16_t); } 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)! /* 2026-03-05 11:54:44.841 17486-17486 NDK at.lockstep I PlaybackEngine - allocated 2304 bytes buffer 2026-03-05 11:54:44.841 17486-17486 NDK at.lockstep I PlaybackEngine - blanking the buffer ... 2026-03-05 11:54:44.842 17486-17486 NDK at.lockstep I PlaybackEngine - filling 24543 num_samples copying 1152 samples, k=0 */ MP3File *mFile = mp3file_open(filename.c_str(), 0); // MPG123_ENC_FLOAT_32 (but does not seem to work) //LOGI("allocated %d bytes buffer", mFile->buffer_size); //LOGI("blanking the buffer ..."); memset(mFile->buffer, 0, mFile->buffer_size); //LOGI("filling %d num_samples", mFile->num_samples); bool ok1 = mFile != nullptr; int ok2 = true; int i = 0; //int k = 0; if(ok1) { samples.resize(mFile->num_samples); while (ok2 && mFile->remaining_samples > 0) { //LOGI("readBuffer2() k=%d", k); ok2 = readBuffer2(mFile); if (!ok2) break; // TODO: check if trailing bit is decoded correctly //LOGI("copying %d samples, k=%d", mFile->samples_per_frame, k); for (int j = 0; j < ok2 && i < mFile->num_samples; j++, i++) { int16_t *src = ((int16_t *) mFile->buffer) + j; samples[i] = (*src) / 32768.0f; } //k++; // debug only } } if(!ok2) { LOGI("ok2=false at i=%d", i); } /* if(ok1 && ok2) { // num_frames, num_samples, samples_per_frame LOGI("filling %d num_samples", mFile->num_samples); 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; // BUG! bool is_ok = read_mp3(mFilesDir + "/" + std::to_string(resid) + ".mp3", samples); LOGI("read_mp3() is_ok=%d", is_ok); // begin debug only /* // make sine wave (it works) int fps = 48000; float dur = 0.3; float f = 440; int N = (int) (dur * (float) fps); samples.resize(N); for(int n = 0; n < N; n++) samples[n] = (float) sin(2*M_PI * f * n / N); */ // end debug only 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(); }