Fix fluidsynth backend

This commit is contained in:
Zachary Hall 2024-12-29 07:46:34 -08:00
parent 93ba23cd41
commit 39fcf9f280
2 changed files with 72 additions and 9 deletions

View file

@ -91,10 +91,34 @@ void FluidSynthBackend::load(const char *filename) {
delete file;
file_data = realloc(file_data, file_len);
fluid_player_add_mem(player, file_data, file_len);
fluid_player_set_loop(player, -1);
fluid_player_play(player);
size_t prev_pos = 0;
size_t cur_pos = 0;
size_t samples = 0;
sample_positions.push_back({0, 0});
float fakebuf;
fluid_player_seek(player, 0);
while (prev_pos <= cur_pos) {
size_t samples_to_add = std::floor((96000.0 * 60.0) / fluid_player_get_bpm(player));
fluid_synth_write_float(synth, samples_to_add, &fakebuf, 0, 0, &fakebuf, 0, 0);
samples += samples_to_add;
prev_pos = cur_pos;
while (prev_pos == cur_pos) {
cur_pos = fluid_player_get_current_tick(player);
if (prev_pos == cur_pos) {
fluid_synth_write_float(synth, 1, &fakebuf, 0, 0, &fakebuf, 0, 0);
samples++;
}
}
sample_positions.push_back({samples, cur_pos});
}
this->length = ((double)samples) / 96000.0;
}
extern SDL_AudioSpec obtained;
void FluidSynthBackend::switch_stream(int idx) {
fluid_player_play(player);
fluid_player_seek(player, 0);
open = true;
}
void FluidSynthBackend::cleanup() {
delete_fluid_player(player);
@ -106,14 +130,33 @@ void FluidSynthBackend::cleanup() {
file_len = 0;
free(file_data);
file_data = nullptr;
open = false;
}
size_t FluidSynthBackend::render(void *buf, size_t maxlen) {
size_t sample_type_len = sizeof(float);
maxlen /= sample_type_len * 2;
position += ((double)maxlen) / 96000.0;
maxlen *= sample_type_len * 2;
if (fluid_synth_write_float(synth, maxlen / 2 / sample_type_len, buf, 0, 2, buf, 1, 2) == FLUID_FAILED) {
return 0;
}
if (position >= length) {
int tick = fluid_player_get_current_tick(player);
int prev_sample = 0;
int cur_sample = 0;
for (auto &pair : sample_positions) {
prev_sample = cur_sample;
cur_sample = pair.first;
if (pair.second > tick) {
position = ((double)prev_sample) / 96000.0;
break;
} else if (pair.second == tick) {
position = ((double)cur_sample) / 96000.0;
break;
}
}
}
return maxlen;
}
bool FluidSynthBackend::is_fluidsynth_setting(std::string path) {
@ -122,10 +165,31 @@ bool FluidSynthBackend::is_fluidsynth_setting(std::string path) {
return path.substr(0, strlen(prefix)) == std::string(prefix);
}
void FluidSynthBackend::seek(double position) {
fluid_player_seek(player, position);
size_t tick = 0;
size_t sample = position * 96000;
size_t prev_sample = 0;
size_t next_sample = 0;
for (auto &pair : sample_positions) {
prev_sample = next_sample;
next_sample = pair.first;
if (next_sample > sample) {
tick = pair.second - 1;
this->position = ((double)prev_sample) / 96000.0;
break;
} else if (next_sample == sample) {
tick = pair.second;
this->position = ((double)next_sample) / 96000.0;
prev_sample = next_sample;
break;
}
}
fluid_player_seek(player, tick);
float fakebuf;
if (sample > prev_sample) fluid_synth_write_float(synth, sample - prev_sample, &fakebuf, 0, 0, &fakebuf, 0, 0);
this->position = position;
}
double FluidSynthBackend::get_position() {
return fluid_player_get_current_tick(player);
return position;
}
int FluidSynthBackend::get_stream_idx() {
return 0;

View file

@ -12,6 +12,7 @@
#include <SDL.h>
#include "file_backend.hpp"
#include <fluidsynth.h>
#include <vector>
class FluidSynthBackend : public PlaybackBackend {
void *file_data;
size_t file_len;
@ -20,6 +21,7 @@ class FluidSynthBackend : public PlaybackBackend {
fluid_settings_t *settings;
fluid_synth_t *synth;
fluid_player_t *player;
std::vector<std::pair<size_t, size_t>> sample_positions;
void fluidsynth_get_property_list(const char *name, int type);
public:
void set_fluidsynth_property_str(std::string path, std::string val);
@ -132,8 +134,5 @@ class FluidSynthBackend : public PlaybackBackend {
int get_stream_idx() override;
size_t render(void *buf, size_t maxlen) override;
double get_position() override;
inline double get_length() override {
return 0.0;
}
inline ~FluidSynthBackend() override { }
};