feat: reduce buffers to 1024

This commit is contained in:
2026-03-22 07:49:05 +01:00
parent b0f6d6d5c9
commit 6382c57ccc
3 changed files with 32 additions and 38 deletions

View File

@@ -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.

View File

@@ -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<MusicProvider>(&stretcher));
mPlayer->setMusic(std::make_shared<MusicProvider>(&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

View File

@@ -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<bool> haveTimeRatio;
double timeRatio;
int playbackRate;
static size_t constexpr buf_size_samples = 1024;
void initRubberBand();
void closeRubberBand();
void closeMusicFile();