From 6382c57ccc9103658200d122c40b722b71ebbd8c Mon Sep 17 00:00:00 2001 From: David Madl Date: Sun, 22 Mar 2026 07:49:05 +0100 Subject: [PATCH] feat: reduce buffers to 1024 --- app/src/main/cpp/MixingPlayer.h | 2 + app/src/main/cpp/PlaybackEngine.cpp | 62 ++++++++++++----------------- app/src/main/cpp/PlaybackEngine.h | 6 ++- 3 files changed, 32 insertions(+), 38 deletions(-) diff --git a/app/src/main/cpp/MixingPlayer.h b/app/src/main/cpp/MixingPlayer.h index 29bc6b3..77a78c7 100644 --- a/app/src/main/cpp/MixingPlayer.h +++ b/app/src/main/cpp/MixingPlayer.h @@ -55,6 +55,8 @@ public: return (int32_t) result; } + int getRate() { return kSampleRate; } + // Call this from Activity onPause() void stopAudio() { // Stop, close and delete in case not already closed. diff --git a/app/src/main/cpp/PlaybackEngine.cpp b/app/src/main/cpp/PlaybackEngine.cpp index f56f656..f894bf9 100644 --- a/app/src/main/cpp/PlaybackEngine.cpp +++ b/app/src/main/cpp/PlaybackEngine.cpp @@ -82,7 +82,8 @@ PlaybackEngine::PlaybackEngine(std::string filesDir, int resid): exitMusicFeedThread(false), android_fd(0), haveTimeRatio(false), - timeRatio(1.0) + timeRatio(1.0), + playbackRate(48000) { LOGI("PlaybackEngine()"); LOGI("NDK LOG_LEVEL=%d", LOG_LEVEL); @@ -92,6 +93,7 @@ PlaybackEngine::PlaybackEngine(std::string filesDir, int resid): LOGI("read_mp3() is_ok=%d", is_ok); mPlayer = new MixingPlayer(samples); int32_t res = mPlayer->startAudio(); + playbackRate = mPlayer->getRate(); LOGI("startAudio() = %d", res); initRubberBand(); } @@ -150,15 +152,14 @@ void PlaybackEngine::closeMusicFile() { } void PlaybackEngine::musicFeedThread() { - // refactor: rename to 'num_buf_samples' - size_t num_pad = 48000; // hack! how much to actually reserve? is getPreferredStartPad() always < getSamplesRequired()? - size_t buf_stride = num_pad; - float* buf = (float*) malloc(num_pad*2*sizeof(float)); - float* buf_ptr[] {buf, buf + num_pad}; - memset(buf, 0, num_pad*2*sizeof(float)); - unsigned char* cbuf = (unsigned char*) malloc(num_pad*2*sizeof(int16_t)); - memset(cbuf, 0, num_pad*2*sizeof(int16_t)); - size_t cbuf_size_bytes = num_pad*2*sizeof(int16_t); + size_t num_buf_samples = buf_size_samples; + size_t buf_stride = num_buf_samples; + float* buf = (float*) malloc(num_buf_samples * 2 * sizeof(float)); + float* buf_ptr[] {buf, buf + num_buf_samples}; + memset(buf, 0, num_buf_samples * 2 * sizeof(float)); + unsigned char* cbuf = (unsigned char*) malloc(num_buf_samples * 2 * sizeof(int16_t)); + memset(cbuf, 0, num_buf_samples * 2 * sizeof(int16_t)); + size_t cbuf_size_bytes = num_buf_samples * 2 * sizeof(int16_t); int idebug = 0; @@ -185,8 +186,8 @@ void PlaybackEngine::musicFeedThread() { continue; } - if (num_samples > num_pad) { - LOGE("wanted %d samples but buf is only %d samples", num_samples, num_pad); + if (num_samples > num_buf_samples) { + LOGE("wanted %d samples but buf is only %d samples", num_samples, num_buf_samples); continue; } @@ -226,7 +227,8 @@ void PlaybackEngine::musicFeedThread() { } size_t num_decoded_samples = done / sizeof(int16_t) / 2; // 2 channels - TODO: actually use mp3 channels!! below, too. 2. - LOGI("num_decoded_samples = %d", num_decoded_samples); + //LOGD("num_decoded_samples = %d", num_decoded_samples); + // convert interleaved int16 to de-interleaved float [-1.0, 1.0] format for(size_t i = 0; i < num_decoded_samples; i++) { for(size_t j = 0; j < 2; j++) { @@ -234,7 +236,7 @@ void PlaybackEngine::musicFeedThread() { } } - LOGI("calling stretcher.process()"); + //LOGD("calling stretcher.process()"); stretcher.process(buf_ptr, num_decoded_samples, false); } } @@ -253,35 +255,23 @@ void PlaybackEngine::playBeat() { void PlaybackEngine::playMusic(int fd) { if(!mPlayer) return; - // TODO: fetch sampling rate from mp3 file, and use librubberband to correct for it - // MixingPlayer::kSampleRate (48000) - // mp3->rate - - // feed samples to librubberband - // fetch resamples out of librubberband - - //if(mPlayer) mPlayer->playMusic(); - // TODO: fd is opened; dispose of fd when stopping or being discarded ... LOGI("PlaybackEngine::playMusic(fd=%d)", fd); - //close(fd); // for now, nothing is implemented. we just close it again. - // we will use mp3file_open_fd() later. - android_fd = fd; musicFile.reset(mp3file_open_fd(android_fd, 0)); if(musicFile) { - timeRatio = ((double) 48000) / ((double) musicFile->rate); + timeRatio = ((double) playbackRate) / ((double) musicFile->rate); haveTimeRatio.store(true); } haveMusicFile.store(true); - mPlayer->setMusic(std::make_shared(&stretcher)); + mPlayer->setMusic(std::make_shared(&stretcher, buf_size_samples)); } -MusicProvider::MusicProvider(RubberBand::RubberBandStretcher *stretcher) : stretcher(stretcher), idebug(0) { - // refactor: rename to 'num_buf_samples' - // TODO: for cache-friendliness, it would be better to have smaller 'num_buf_samples' - // hack! how much to actually reserve? is getPreferredStartPad() always < getSamplesRequired()? - //size_t buf_stride = num_pad; - buf = (float*) malloc(num_buf_samples*2*sizeof(float)); +MusicProvider::MusicProvider(RubberBand::RubberBandStretcher *stretcher, size_t buf_size_samples) : + stretcher(stretcher), + idebug(0), + buf_size_samples(buf_size_samples) +{ + buf = (float*) malloc(buf_size_samples*2*sizeof(float)); //float* buf_ptr[] {buf, buf + num_pad}; } @@ -296,8 +286,8 @@ void MusicProvider::onAudioReady(float *data, int32_t frames) { } // 1. read from oboe into our temp de-interleaved buffer 'buf' - size_t num_frames = std::min((size_t) frames, num_buf_samples); - float* buf_ptr[] {buf, buf + num_buf_samples}; + size_t num_frames = std::min((size_t) frames, buf_size_samples); + float* buf_ptr[] {buf, buf + buf_size_samples}; stretcher->retrieve(buf_ptr, num_frames); // 2. convert to add samples to interleaved *data diff --git a/app/src/main/cpp/PlaybackEngine.h b/app/src/main/cpp/PlaybackEngine.h index a743a3a..093f804 100644 --- a/app/src/main/cpp/PlaybackEngine.h +++ b/app/src/main/cpp/PlaybackEngine.h @@ -18,16 +18,16 @@ /** Provides music through a regular callback to oboe. Called from separate oboe thread. */ class MusicProvider : public AudioCallbackProvider { public: - explicit MusicProvider(RubberBand::RubberBandStretcher *stretcher); + explicit MusicProvider(RubberBand::RubberBandStretcher *stretcher, size_t buf_size_samples); ~MusicProvider() override; /** Called from separate oboe thread. */ void onAudioReady(float *data, int32_t frames) override; private: - const size_t num_buf_samples = 48000; RubberBand::RubberBandStretcher *stretcher; float *buf; int idebug; + size_t buf_size_samples; }; class PlaybackEngine : public StepListener { @@ -48,6 +48,8 @@ private: int android_fd; std::atomic haveTimeRatio; double timeRatio; + int playbackRate; + static size_t constexpr buf_size_samples = 1024; void initRubberBand(); void closeRubberBand(); void closeMusicFile();