Fix fluidsynth backend
This commit is contained in:
parent
93ba23cd41
commit
39fcf9f280
2 changed files with 72 additions and 9 deletions
|
@ -49,10 +49,10 @@ void FluidSynthBackend::fluidsynth_get_property_list(const char *name, int type)
|
|||
fluidsynth_properties.push_back(property);
|
||||
}
|
||||
std::vector<Property> FluidSynthBackend::get_property_list() {
|
||||
return fluidsynth_properties;
|
||||
return fluidsynth_properties;
|
||||
}
|
||||
void FluidSynthBackend::load(const char *filename) {
|
||||
memset(&spec, 0, sizeof(spec));
|
||||
memset(&spec, 0, sizeof(spec));
|
||||
current_file = filename;
|
||||
spec.format = AUDIO_F32SYS;
|
||||
spec.samples = 100;
|
||||
|
@ -63,7 +63,7 @@ void FluidSynthBackend::load(const char *filename) {
|
|||
settings = new_fluid_settings();
|
||||
fluid_settings_setnum(settings, "synth.sample-rate", 96000.0);
|
||||
fluid_settings_setnum(settings, "synth.gain", 0.5);
|
||||
fluid_settings_foreach(settings, (void*)this, &fluidsynth_get_property_list_wrapper);
|
||||
fluid_settings_foreach(settings, (void*)this, &fluidsynth_get_property_list_wrapper);
|
||||
synth = new_fluid_synth(settings);
|
||||
player = new_fluid_player(synth);
|
||||
fs::path fpath(filename);
|
||||
|
@ -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;
|
||||
|
|
|
@ -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 { }
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue