108 lines
3.1 KiB
C++
108 lines
3.1 KiB
C++
#include "synth.h"
|
|
|
|
#include <stdexcept>
|
|
|
|
Synth::Synth() {
|
|
try {
|
|
settings = new_fluid_settings();
|
|
if (settings == nullptr) {
|
|
throw new std::runtime_error("Unable to create fluid settings");
|
|
}
|
|
|
|
synth = new_fluid_synth(settings);
|
|
if (synth == nullptr) {
|
|
throw new std::runtime_error("Unable to create fluid synth");
|
|
}
|
|
|
|
adriver = new_fluid_audio_driver(settings, synth);
|
|
if (adriver == nullptr) {
|
|
throw new std::runtime_error("Unable to create audio driver");
|
|
}
|
|
}
|
|
catch (std::runtime_error& e) {
|
|
// Do a mem-safe cleanup and rethrow.
|
|
// TODO JMT: Do these handle receiving nullptr for deletes?
|
|
delete_fluid_audio_driver(adriver);
|
|
delete_fluid_synth(synth);
|
|
delete_fluid_settings(settings);
|
|
throw;
|
|
}
|
|
}
|
|
|
|
Synth::~Synth() {
|
|
// TODO JMT: Do I need to manually clear all of the soundfonts and programs I have handles for?
|
|
delete_fluid_audio_driver(adriver);
|
|
delete_fluid_synth(synth);
|
|
delete_fluid_settings(settings);
|
|
}
|
|
|
|
bool Synth::loadSoundfont(const std::string& filepath) {
|
|
int soundfontId = fluid_synth_sfload(synth, filepath.c_str(), 1);
|
|
if(soundfontId == FLUID_FAILED) {
|
|
return false;
|
|
}
|
|
|
|
fluid_sfont_t* soundfontHandle = fluid_synth_get_sfont_by_id(synth, soundfontId);
|
|
const std::string soundfontName{fluid_sfont_get_name(soundfontHandle)};
|
|
|
|
Synth::Soundfont soundfont{soundfontName, soundfontId};
|
|
soundfonts.push_back(soundfont);
|
|
|
|
fluid_preset_t* preset = nullptr;
|
|
fluid_sfont_iteration_start(soundfontHandle);
|
|
while ((preset = fluid_sfont_iteration_next(soundfontHandle)) != nullptr) {
|
|
const std::string presetName{fluid_preset_get_name(preset)};
|
|
const int bankNumber = fluid_preset_get_banknum(preset);
|
|
const int programNumber = fluid_preset_get_num(preset);
|
|
|
|
Synth::Program program {presetName, soundfontId, bankNumber, programNumber};
|
|
programs.push_back(program);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Synth::loadProgram(const Program& program) {
|
|
// TODO JMT: fix this
|
|
fluid_synth_program_select(synth, 0, program.soundfontId, program.bankNumber, program.programNumber);
|
|
fluid_synth_program_select(synth, 1, program.soundfontId, program.bankNumber, program.programNumber);
|
|
return true;
|
|
}
|
|
|
|
bool Synth::setTuning(const std::array<double, NUM_MIDI_NOTES>& pitches) {
|
|
int result = fluid_synth_activate_key_tuning(
|
|
synth,
|
|
0, 0,
|
|
"default",
|
|
pitches.data(),
|
|
1
|
|
);
|
|
|
|
if (result == FLUID_OK) {
|
|
result = fluid_synth_activate_tuning(synth, 0, 0, 0, 1);
|
|
result = fluid_synth_activate_tuning(synth, 1, 0, 0, 1);
|
|
}
|
|
|
|
return result == FLUID_OK;
|
|
}
|
|
|
|
bool Synth::resetTuning() {
|
|
int result = fluid_synth_activate_key_tuning(
|
|
synth,
|
|
0, 0,
|
|
"default",
|
|
nullptr,
|
|
1
|
|
);
|
|
|
|
return result == FLUID_OK;
|
|
}
|
|
|
|
const std::vector<Synth::Program>& Synth::getPrograms() const {
|
|
return programs;
|
|
}
|
|
|
|
fluid_synth_t* Synth::getSynth() {
|
|
return synth;
|
|
}
|