prefer references where owner will definitely outlive recipient. replace some fluidsynth raw pointers with smart pointers.
This commit is contained in:
parent
7582fbcc9e
commit
6d2267e23a
|
@ -6,24 +6,26 @@
|
||||||
#include "MyColours.h"
|
#include "MyColours.h"
|
||||||
|
|
||||||
FilePicker::FilePicker(
|
FilePicker::FilePicker(
|
||||||
FluidSynthModel* fluidSynthModel
|
AudioProcessorValueTreeState& valueTreeState,
|
||||||
|
FluidSynthModel& fluidSynthModel
|
||||||
)
|
)
|
||||||
: fileChooser(
|
: fileChooser{
|
||||||
"File",
|
"File",
|
||||||
File(),
|
File(),
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
"*.sf2;*.sf3",
|
"*.sf2;*.sf3",
|
||||||
String(),
|
String(),
|
||||||
"Choose a Soundfont file to load into the synthesizer"
|
"Choose a Soundfont file to load into the synthesizer"}
|
||||||
),
|
, valueTreeState{valueTreeState}
|
||||||
fluidSynthModel(fluidSynthModel),
|
, fluidSynthModel{fluidSynthModel}
|
||||||
currentPath() {
|
// , currentPath{}
|
||||||
|
{
|
||||||
// faster (rounded edges introduce transparency)
|
// faster (rounded edges introduce transparency)
|
||||||
setOpaque (true);
|
setOpaque (true);
|
||||||
|
|
||||||
setDisplayedFilePath(fluidSynthModel->getCurrentSoundFontAbsPath());
|
setDisplayedFilePath(fluidSynthModel.getCurrentSoundFontAbsPath());
|
||||||
|
|
||||||
addAndMakeVisible (fileChooser);
|
addAndMakeVisible (fileChooser);
|
||||||
fileChooser.addListener (this);
|
fileChooser.addListener (this);
|
||||||
|
@ -47,7 +49,7 @@ void FilePicker::paint(Graphics& g)
|
||||||
|
|
||||||
void FilePicker::filenameComponentChanged (FilenameComponent*) {
|
void FilePicker::filenameComponentChanged (FilenameComponent*) {
|
||||||
currentPath = fileChooser.getCurrentFile().getFullPathName();
|
currentPath = fileChooser.getCurrentFile().getFullPathName();
|
||||||
fluidSynthModel->onFileNameChanged(fileChooser.getCurrentFile().getFullPathName(), -1, -1);
|
fluidSynthModel.onFileNameChanged(fileChooser.getCurrentFile().getFullPathName(), -1, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FilePicker::setDisplayedFilePath(const String& path) {
|
void FilePicker::setDisplayedFilePath(const String& path) {
|
||||||
|
|
|
@ -14,7 +14,8 @@ class FilePicker: public Component,
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FilePicker(
|
FilePicker(
|
||||||
FluidSynthModel* fluidSynthModel
|
AudioProcessorValueTreeState& valueTreeState,
|
||||||
|
FluidSynthModel& fluidSynthModel
|
||||||
);
|
);
|
||||||
~FilePicker();
|
~FilePicker();
|
||||||
|
|
||||||
|
@ -25,7 +26,8 @@ public:
|
||||||
private:
|
private:
|
||||||
FilenameComponent fileChooser;
|
FilenameComponent fileChooser;
|
||||||
|
|
||||||
FluidSynthModel* fluidSynthModel;
|
AudioProcessorValueTreeState& valueTreeState;
|
||||||
|
FluidSynthModel& fluidSynthModel;
|
||||||
|
|
||||||
String currentPath;
|
String currentPath;
|
||||||
|
|
||||||
|
|
|
@ -3,33 +3,46 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <fluidsynth.h>
|
||||||
#include "FluidSynthModel.h"
|
#include "FluidSynthModel.h"
|
||||||
#include "MidiConstants.h"
|
#include "MidiConstants.h"
|
||||||
|
#include "Util.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
FluidSynthModel::FluidSynthModel(shared_ptr<SharesParams> sharedParams)
|
FluidSynthModel::FluidSynthModel(
|
||||||
: sharedParams{sharedParams},
|
AudioProcessorValueTreeState& valueTreeState,
|
||||||
synth{nullptr},
|
SharesParams& sharedParams
|
||||||
settings{nullptr},
|
)
|
||||||
currentSoundFontAbsPath{},
|
: valueTreeState{valueTreeState}
|
||||||
currentSampleRate{44100},
|
, sharedParams{sharedParams}
|
||||||
initialised{false},
|
//, synth{nullptr}
|
||||||
sfont_id{0},
|
, settings{nullptr, nullptr}
|
||||||
channel{0}/*,
|
, currentSoundFontAbsPath{}
|
||||||
mod(nullptr)*/
|
, currentSampleRate{44100}
|
||||||
|
, initialised{false}
|
||||||
|
, sfont_id{0}
|
||||||
|
, channel{0}/*,
|
||||||
|
mod(nullptr)*/
|
||||||
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
FluidSynthModel::~FluidSynthModel() {
|
// FluidSynthModel::~FluidSynthModel() {
|
||||||
if (initialised) {
|
// if (initialised) {
|
||||||
// delete_fluid_audio_driver(driver);
|
// delete_fluid_audio_driver(driver);
|
||||||
delete_fluid_synth(synth);
|
// delete_fluid_synth(synth);
|
||||||
delete_fluid_settings(settings);
|
// delete_fluid_settings(settings);
|
||||||
// delete driver;
|
// delete driver;
|
||||||
// delete settings;
|
// delete settings;
|
||||||
// delete_fluid_mod(mod);
|
// delete_fluid_mod(mod);
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
int FluidSynthModel::handleMidiEvent(void* data, fluid_midi_event_t* event)
|
||||||
|
{
|
||||||
|
// DEBUG_PRINT(fluid_midi_event_get_type(event));
|
||||||
|
// printf("event type: %d\n", fluid_midi_event_get_type(event));
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FluidSynthModel::initialise() {
|
void FluidSynthModel::initialise() {
|
||||||
|
@ -37,26 +50,47 @@ void FluidSynthModel::initialise() {
|
||||||
// delete_fluid_synth(synth);
|
// delete_fluid_synth(synth);
|
||||||
// delete_fluid_settings(settings);
|
// delete_fluid_settings(settings);
|
||||||
// }
|
// }
|
||||||
|
settings = { new_fluid_settings(), delete_fluid_settings };
|
||||||
|
|
||||||
// deactivate all audio drivers in fluidsynth to avoid FL Studio deadlock when initialising CoreAudio
|
// deactivate all audio drivers in fluidsynth to avoid FL Studio deadlock when initialising CoreAudio
|
||||||
// after all: we only use fluidsynth to render blocks of audio. it doesn't output to audio driver.
|
// after all: we only use fluidsynth to render blocks of audio. it doesn't output to audio driver.
|
||||||
const char *DRV[] = {NULL};
|
const char *DRV[] {NULL};
|
||||||
fluid_audio_driver_register(DRV);
|
fluid_audio_driver_register(DRV);
|
||||||
|
|
||||||
|
// handle_midi_event_func_t handler = [](void* data, fluid_midi_event_t* event) -> int {
|
||||||
|
//
|
||||||
|
// };
|
||||||
|
|
||||||
|
// midiDriver = unique_ptr<fluid_midi_driver_t, decltype(&delete_fluid_midi_driver)>(
|
||||||
|
// new_fluid_midi_driver(
|
||||||
|
// settings.get(),
|
||||||
|
// [](void* data, fluid_midi_event_t* event) -> int {
|
||||||
|
//
|
||||||
|
// },
|
||||||
|
// nullptr),
|
||||||
|
// delete_fluid_midi_driver);
|
||||||
|
|
||||||
settings = new_fluid_settings();
|
|
||||||
// https://sourceforge.net/p/fluidsynth/wiki/FluidSettings/
|
// https://sourceforge.net/p/fluidsynth/wiki/FluidSettings/
|
||||||
#if JUCE_DEBUG
|
#if JUCE_DEBUG
|
||||||
fluid_settings_setint(settings, "synth.verbose", 1);
|
fluid_settings_setint(settings.get(), "synth.verbose", 1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
synth = new_fluid_synth(settings);
|
synth = { new_fluid_synth(settings.get()), delete_fluid_synth };
|
||||||
fluid_synth_set_sample_rate(synth, currentSampleRate);
|
fluid_synth_set_sample_rate(synth.get(), currentSampleRate);
|
||||||
|
|
||||||
if (sharedParams->getSoundFontPath().isNotEmpty()) {
|
valueTreeState.getParameter("soundFontPath")->getValue();
|
||||||
loadFont(sharedParams->getSoundFontPath());
|
// RangedAudioParameter *param {valueTreeState.getParameter("release")};
|
||||||
changePreset(sharedParams->getBank(), sharedParams->getPreset());
|
// jassert(dynamic_cast<AudioParameterInt*> (param) != nullptr);
|
||||||
|
// AudioParameterInt* castParam {dynamic_cast<AudioParameterInt*> (param)};
|
||||||
|
// *castParam = m.getControllerValue();
|
||||||
|
|
||||||
|
if (sharedParams.getSoundFontPath().isNotEmpty()) {
|
||||||
|
loadFont(sharedParams.getSoundFontPath());
|
||||||
|
// changePreset(sharedParams->getBank(), sharedParams->getPreset());
|
||||||
}
|
}
|
||||||
|
|
||||||
fluid_synth_set_gain(synth, 2.0);
|
fluid_synth_set_gain(synth.get(), 2.0);
|
||||||
|
|
||||||
for(int i{SOUND_CTRL1}; i <= SOUND_CTRL10; i++)
|
for(int i{SOUND_CTRL1}; i <= SOUND_CTRL10; i++)
|
||||||
{
|
{
|
||||||
|
@ -81,90 +115,84 @@ void FluidSynthModel::initialise() {
|
||||||
// all SOUND_CTRL are inited with value of 64, not zero.
|
// all SOUND_CTRL are inited with value of 64, not zero.
|
||||||
// "Just like panning, a value of 64 indicates no change for sound ctrls"
|
// "Just like panning, a value of 64 indicates no change for sound ctrls"
|
||||||
|
|
||||||
fluid_mod_t *mod(new_fluid_mod());
|
unique_ptr<fluid_mod_t, decltype(&delete_fluid_mod)> mod{new_fluid_mod(), delete_fluid_mod};
|
||||||
//
|
//
|
||||||
fluid_mod_set_source1(mod,
|
fluid_mod_set_source1(mod.get(),
|
||||||
static_cast<int>(SOUND_CTRL2), // MIDI CC 71 Timbre/Harmonic Intensity (filter resonance)
|
static_cast<int>(SOUND_CTRL2), // MIDI CC 71 Timbre/Harmonic Intensity (filter resonance)
|
||||||
FLUID_MOD_CC
|
FLUID_MOD_CC
|
||||||
| FLUID_MOD_UNIPOLAR
|
| FLUID_MOD_UNIPOLAR
|
||||||
| FLUID_MOD_CONCAVE
|
| FLUID_MOD_CONCAVE
|
||||||
| FLUID_MOD_POSITIVE);
|
| FLUID_MOD_POSITIVE);
|
||||||
fluid_mod_set_source2(mod, 0, 0);
|
fluid_mod_set_source2(mod.get(), 0, 0);
|
||||||
fluid_mod_set_dest(mod, GEN_FILTERQ);
|
fluid_mod_set_dest(mod.get(), GEN_FILTERQ);
|
||||||
fluid_mod_set_amount(mod, FLUID_PEAK_ATTENUATION);
|
fluid_mod_set_amount(mod.get(), FLUID_PEAK_ATTENUATION);
|
||||||
fluid_synth_add_default_mod(synth, mod, FLUID_SYNTH_ADD);
|
fluid_synth_add_default_mod(synth.get(), mod.get(), FLUID_SYNTH_ADD);
|
||||||
delete_fluid_mod(mod);
|
|
||||||
|
|
||||||
mod = new_fluid_mod();
|
mod = {new_fluid_mod(), delete_fluid_mod};
|
||||||
fluid_mod_set_source1(mod,
|
fluid_mod_set_source1(mod.get(),
|
||||||
static_cast<int>(SOUND_CTRL3), // MIDI CC 72 Release time
|
static_cast<int>(SOUND_CTRL3), // MIDI CC 72 Release time
|
||||||
FLUID_MOD_CC
|
FLUID_MOD_CC
|
||||||
| FLUID_MOD_UNIPOLAR
|
| FLUID_MOD_UNIPOLAR
|
||||||
| FLUID_MOD_LINEAR
|
| FLUID_MOD_LINEAR
|
||||||
| FLUID_MOD_POSITIVE);
|
| FLUID_MOD_POSITIVE);
|
||||||
fluid_mod_set_source2(mod, 0, 0);
|
fluid_mod_set_source2(mod.get(), 0, 0);
|
||||||
fluid_mod_set_dest(mod, GEN_VOLENVRELEASE);
|
fluid_mod_set_dest(mod.get(), GEN_VOLENVRELEASE);
|
||||||
// fluid_mod_set_amount(mod, 15200.0f);
|
// fluid_mod_set_amount(mod.get(), 15200.0f);
|
||||||
fluid_mod_set_amount(mod, env_amount);
|
fluid_mod_set_amount(mod.get(), env_amount);
|
||||||
fluid_synth_add_default_mod(synth, mod, FLUID_SYNTH_ADD);
|
fluid_synth_add_default_mod(synth.get(), mod.get(), FLUID_SYNTH_ADD);
|
||||||
delete_fluid_mod(mod);
|
|
||||||
|
|
||||||
mod = new_fluid_mod();
|
mod = {new_fluid_mod(), delete_fluid_mod};
|
||||||
fluid_mod_set_source1(mod,
|
fluid_mod_set_source1(mod.get(),
|
||||||
static_cast<int>(SOUND_CTRL4), // MIDI CC 73 Attack time
|
static_cast<int>(SOUND_CTRL4), // MIDI CC 73 Attack time
|
||||||
FLUID_MOD_CC
|
FLUID_MOD_CC
|
||||||
| FLUID_MOD_UNIPOLAR
|
| FLUID_MOD_UNIPOLAR
|
||||||
| FLUID_MOD_LINEAR
|
| FLUID_MOD_LINEAR
|
||||||
| FLUID_MOD_POSITIVE);
|
| FLUID_MOD_POSITIVE);
|
||||||
fluid_mod_set_source2(mod, 0, 0);
|
fluid_mod_set_source2(mod.get(), 0, 0);
|
||||||
fluid_mod_set_dest(mod, GEN_VOLENVATTACK);
|
fluid_mod_set_dest(mod.get(), GEN_VOLENVATTACK);
|
||||||
fluid_mod_set_amount(mod, env_amount);
|
fluid_mod_set_amount(mod.get(), env_amount);
|
||||||
fluid_synth_add_default_mod(synth, mod, FLUID_SYNTH_ADD);
|
fluid_synth_add_default_mod(synth.get(), mod.get(), FLUID_SYNTH_ADD);
|
||||||
delete_fluid_mod(mod);
|
|
||||||
|
|
||||||
// soundfont spec says that if cutoff is >20kHz and resonance Q is 0, then no filtering occurs
|
// soundfont spec says that if cutoff is >20kHz and resonance Q is 0, then no filtering occurs
|
||||||
mod = new_fluid_mod();
|
mod = {new_fluid_mod(), delete_fluid_mod};
|
||||||
fluid_mod_set_source1(mod,
|
fluid_mod_set_source1(mod.get(),
|
||||||
static_cast<int>(SOUND_CTRL5), // MIDI CC 74 Brightness (cutoff frequency, FILTERFC)
|
static_cast<int>(SOUND_CTRL5), // MIDI CC 74 Brightness (cutoff frequency, FILTERFC)
|
||||||
FLUID_MOD_CC
|
FLUID_MOD_CC
|
||||||
| FLUID_MOD_LINEAR
|
| FLUID_MOD_LINEAR
|
||||||
| FLUID_MOD_UNIPOLAR
|
| FLUID_MOD_UNIPOLAR
|
||||||
| FLUID_MOD_POSITIVE);
|
| FLUID_MOD_POSITIVE);
|
||||||
fluid_mod_set_source2(mod, 0, 0);
|
fluid_mod_set_source2(mod.get(), 0, 0);
|
||||||
fluid_mod_set_dest(mod, GEN_FILTERFC);
|
fluid_mod_set_dest(mod.get(), GEN_FILTERFC);
|
||||||
fluid_mod_set_amount(mod, -2400.0f);
|
fluid_mod_set_amount(mod.get(), -2400.0f);
|
||||||
fluid_synth_add_default_mod(synth, mod, FLUID_SYNTH_ADD);
|
fluid_synth_add_default_mod(synth.get(), mod.get(), FLUID_SYNTH_ADD);
|
||||||
delete_fluid_mod(mod);
|
|
||||||
|
|
||||||
mod = new_fluid_mod();
|
mod = {new_fluid_mod(), delete_fluid_mod};
|
||||||
fluid_mod_set_source1(mod,
|
fluid_mod_set_source1(mod.get(),
|
||||||
static_cast<int>(SOUND_CTRL6), // MIDI CC 75 Decay Time
|
static_cast<int>(SOUND_CTRL6), // MIDI CC 75 Decay Time
|
||||||
FLUID_MOD_CC
|
FLUID_MOD_CC
|
||||||
| FLUID_MOD_UNIPOLAR
|
| FLUID_MOD_UNIPOLAR
|
||||||
| FLUID_MOD_LINEAR
|
| FLUID_MOD_LINEAR
|
||||||
| FLUID_MOD_POSITIVE);
|
| FLUID_MOD_POSITIVE);
|
||||||
fluid_mod_set_source2(mod, 0, 0);
|
fluid_mod_set_source2(mod.get(), 0, 0);
|
||||||
fluid_mod_set_dest(mod, GEN_VOLENVDECAY);
|
fluid_mod_set_dest(mod.get(), GEN_VOLENVDECAY);
|
||||||
fluid_mod_set_amount(mod, env_amount);
|
fluid_mod_set_amount(mod.get(), env_amount);
|
||||||
fluid_synth_add_default_mod(synth, mod, FLUID_SYNTH_ADD);
|
fluid_synth_add_default_mod(synth.get(), mod.get(), FLUID_SYNTH_ADD);
|
||||||
delete_fluid_mod(mod);
|
|
||||||
|
|
||||||
mod = new_fluid_mod();
|
mod = {new_fluid_mod(), delete_fluid_mod};
|
||||||
fluid_mod_set_source1(mod,
|
fluid_mod_set_source1(mod.get(),
|
||||||
static_cast<int>(SOUND_CTRL10), // MIDI CC 79 undefined
|
static_cast<int>(SOUND_CTRL10), // MIDI CC 79 undefined
|
||||||
FLUID_MOD_CC
|
FLUID_MOD_CC
|
||||||
| FLUID_MOD_UNIPOLAR
|
| FLUID_MOD_UNIPOLAR
|
||||||
| FLUID_MOD_CONCAVE
|
| FLUID_MOD_CONCAVE
|
||||||
| FLUID_MOD_POSITIVE);
|
| FLUID_MOD_POSITIVE);
|
||||||
fluid_mod_set_source2(mod, 0, 0);
|
fluid_mod_set_source2(mod.get(), 0, 0);
|
||||||
fluid_mod_set_dest(mod, GEN_VOLENVSUSTAIN);
|
fluid_mod_set_dest(mod.get(), GEN_VOLENVSUSTAIN);
|
||||||
// fluice_voice.c#fluid_voice_update_param()
|
// fluice_voice.c#fluid_voice_update_param()
|
||||||
// clamps the range to between 0 and 1000, so we'll copy that
|
// clamps the range to between 0 and 1000, so we'll copy that
|
||||||
fluid_mod_set_amount(mod, 1000.0f);
|
fluid_mod_set_amount(mod.get(), 1000.0f);
|
||||||
fluid_synth_add_default_mod(synth, mod, FLUID_SYNTH_ADD);
|
fluid_synth_add_default_mod(synth.get(), mod.get(), FLUID_SYNTH_ADD);
|
||||||
delete_fluid_mod(mod);
|
|
||||||
|
|
||||||
initialised = true;
|
// initialised = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FluidSynthModel::setControllerValue(int controller, int value) {
|
void FluidSynthModel::setControllerValue(int controller, int value) {
|
||||||
|
@ -173,7 +201,7 @@ void FluidSynthModel::setControllerValue(int controller, int value) {
|
||||||
fluid_midi_event_set_channel(midi_event, channel);
|
fluid_midi_event_set_channel(midi_event, channel);
|
||||||
fluid_midi_event_set_control(midi_event, controller);
|
fluid_midi_event_set_control(midi_event, controller);
|
||||||
fluid_midi_event_set_value(midi_event, value);
|
fluid_midi_event_set_value(midi_event, value);
|
||||||
fluid_synth_handle_midi_event(synth, midi_event);
|
fluid_synth_handle_midi_event(synth.get(), midi_event);
|
||||||
delete_fluid_midi_event(midi_event);
|
delete_fluid_midi_event(midi_event);
|
||||||
// fluid_channel_set_cc(channel, i, 0);
|
// fluid_channel_set_cc(channel, i, 0);
|
||||||
}
|
}
|
||||||
|
@ -189,16 +217,16 @@ void FluidSynthModel::changePreset(int bank, int preset) {
|
||||||
preset = bankAndPreset->getPreset();
|
preset = bankAndPreset->getPreset();
|
||||||
}
|
}
|
||||||
changePresetImpl(bank, preset);
|
changePresetImpl(bank, preset);
|
||||||
sharedParams->setPreset(preset);
|
// sharedParams->setPreset(preset);
|
||||||
sharedParams->setBank(bank);
|
// sharedParams->setBank(bank);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FluidSynthModel::changePresetImpl(int bank, int preset) {
|
void FluidSynthModel::changePresetImpl(int bank, int preset) {
|
||||||
fluid_synth_program_select(synth, channel, sfont_id, static_cast<unsigned int>(bank), static_cast<unsigned int>(preset));
|
fluid_synth_program_select(synth.get(), channel, sfont_id, static_cast<unsigned int>(bank), static_cast<unsigned int>(preset));
|
||||||
}
|
}
|
||||||
|
|
||||||
fluid_preset_t* FluidSynthModel::getFirstPreset() {
|
fluid_preset_t* FluidSynthModel::getFirstPreset() {
|
||||||
fluid_sfont_t* sfont = fluid_synth_get_sfont_by_id(synth, sfont_id);
|
fluid_sfont_t* sfont = fluid_synth_get_sfont_by_id(synth.get(), sfont_id);
|
||||||
|
|
||||||
jassert(sfont != nullptr);
|
jassert(sfont != nullptr);
|
||||||
fluid_sfont_iteration_start(sfont);
|
fluid_sfont_iteration_start(sfont);
|
||||||
|
@ -209,7 +237,7 @@ fluid_preset_t* FluidSynthModel::getFirstPreset() {
|
||||||
unique_ptr<BankAndPreset> FluidSynthModel::getFirstBankAndPreset() {
|
unique_ptr<BankAndPreset> FluidSynthModel::getFirstBankAndPreset() {
|
||||||
fluid_preset_t* preset = getFirstPreset();
|
fluid_preset_t* preset = getFirstPreset();
|
||||||
|
|
||||||
int offset = fluid_synth_get_bank_offset(synth, sfont_id);
|
int offset = fluid_synth_get_bank_offset(synth.get(), sfont_id);
|
||||||
|
|
||||||
return make_unique<BankAndPreset>(fluid_preset_get_banknum(preset) + offset, fluid_preset_get_num(preset));
|
return make_unique<BankAndPreset>(fluid_preset_get_banknum(preset) + offset, fluid_preset_get_num(preset));
|
||||||
};
|
};
|
||||||
|
@ -217,7 +245,7 @@ unique_ptr<BankAndPreset> FluidSynthModel::getFirstBankAndPreset() {
|
||||||
void FluidSynthModel::selectFirstPreset() {
|
void FluidSynthModel::selectFirstPreset() {
|
||||||
fluid_preset_t* preset = getFirstPreset();
|
fluid_preset_t* preset = getFirstPreset();
|
||||||
|
|
||||||
int offset = fluid_synth_get_bank_offset(synth, sfont_id);
|
int offset = fluid_synth_get_bank_offset(synth.get(), sfont_id);
|
||||||
|
|
||||||
changePreset(fluid_preset_get_banknum(preset) + offset, fluid_preset_get_num(preset));
|
changePreset(fluid_preset_get_banknum(preset) + offset, fluid_preset_get_num(preset));
|
||||||
}
|
}
|
||||||
|
@ -225,14 +253,14 @@ void FluidSynthModel::selectFirstPreset() {
|
||||||
BanksToPresets FluidSynthModel::getBanks() {
|
BanksToPresets FluidSynthModel::getBanks() {
|
||||||
BanksToPresets banksToPresets;
|
BanksToPresets banksToPresets;
|
||||||
|
|
||||||
int soundfontCount = fluid_synth_sfcount(synth);
|
int soundfontCount = fluid_synth_sfcount(synth.get());
|
||||||
|
|
||||||
if (soundfontCount == 0) {
|
if (soundfontCount == 0) {
|
||||||
// no soundfont selected
|
// no soundfont selected
|
||||||
return banksToPresets;
|
return banksToPresets;
|
||||||
}
|
}
|
||||||
|
|
||||||
fluid_sfont_t* sfont = fluid_synth_get_sfont_by_id(synth, sfont_id);
|
fluid_sfont_t* sfont = fluid_synth_get_sfont_by_id(synth.get(), sfont_id);
|
||||||
if(sfont == nullptr) {
|
if(sfont == nullptr) {
|
||||||
// no soundfont found by that ID
|
// no soundfont found by that ID
|
||||||
// the above guard (soundfontCount) protects us for the
|
// the above guard (soundfontCount) protects us for the
|
||||||
|
@ -240,7 +268,7 @@ BanksToPresets FluidSynthModel::getBanks() {
|
||||||
return banksToPresets;
|
return banksToPresets;
|
||||||
}
|
}
|
||||||
|
|
||||||
int offset = fluid_synth_get_bank_offset(synth, sfont_id);
|
int offset = fluid_synth_get_bank_offset(synth.get(), sfont_id);
|
||||||
|
|
||||||
fluid_sfont_iteration_start(sfont);
|
fluid_sfont_iteration_start(sfont);
|
||||||
|
|
||||||
|
@ -259,7 +287,7 @@ BanksToPresets FluidSynthModel::getBanks() {
|
||||||
return banksToPresets;
|
return banksToPresets;
|
||||||
}
|
}
|
||||||
|
|
||||||
fluid_synth_t* FluidSynthModel::getSynth() {
|
shared_ptr<fluid_synth_t> FluidSynthModel::getSynth() {
|
||||||
// https://msdn.microsoft.com/en-us/library/hh279669.aspx
|
// https://msdn.microsoft.com/en-us/library/hh279669.aspx
|
||||||
// You can pass a shared_ptr to another function in the following ways:
|
// You can pass a shared_ptr to another function in the following ways:
|
||||||
// Pass the shared_ptr by value. This invokes the copy constructor, increments the reference count, and makes the callee an owner.
|
// Pass the shared_ptr by value. This invokes the copy constructor, increments the reference count, and makes the callee an owner.
|
||||||
|
@ -272,14 +300,14 @@ void FluidSynthModel::onFileNameChanged(const String &absPath, int bank, int pre
|
||||||
}
|
}
|
||||||
unloadAndLoadFont(absPath);
|
unloadAndLoadFont(absPath);
|
||||||
changePreset(bank, preset);
|
changePreset(bank, preset);
|
||||||
sharedParams->setSoundFontPath(absPath);
|
sharedParams.setSoundFontPath(absPath);
|
||||||
eventListeners.call(&FluidSynthModel::Listener::fontChanged, this, absPath);
|
eventListeners.call(&FluidSynthModel::Listener::fontChanged, this, absPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FluidSynthModel::unloadAndLoadFont(const String &absPath) {
|
void FluidSynthModel::unloadAndLoadFont(const String &absPath) {
|
||||||
// in the base case, there is no font loaded
|
// in the base case, there is no font loaded
|
||||||
if (fluid_synth_sfcount(synth) > 0) {
|
if (fluid_synth_sfcount(synth.get()) > 0) {
|
||||||
fluid_synth_sfunload(synth, sfont_id, 1);
|
fluid_synth_sfunload(synth.get(), sfont_id, 1);
|
||||||
}
|
}
|
||||||
loadFont(absPath);
|
loadFont(absPath);
|
||||||
}
|
}
|
||||||
|
@ -287,7 +315,7 @@ void FluidSynthModel::unloadAndLoadFont(const String &absPath) {
|
||||||
void FluidSynthModel::loadFont(const String &absPath) {
|
void FluidSynthModel::loadFont(const String &absPath) {
|
||||||
currentSoundFontAbsPath = absPath;
|
currentSoundFontAbsPath = absPath;
|
||||||
sfont_id++;
|
sfont_id++;
|
||||||
fluid_synth_sfload(synth, absPath.toStdString().c_str(), 1);
|
fluid_synth_sfload(synth.get(), absPath.toStdString().c_str(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
FluidSynthModel::Listener::~Listener() {
|
FluidSynthModel::Listener::~Listener() {
|
||||||
|
@ -323,9 +351,11 @@ void FluidSynthModel::removeListener (FluidSynthModel::Listener* const listener)
|
||||||
|
|
||||||
void FluidSynthModel::setSampleRate(float sampleRate) {
|
void FluidSynthModel::setSampleRate(float sampleRate) {
|
||||||
currentSampleRate = sampleRate;
|
currentSampleRate = sampleRate;
|
||||||
if (!initialised) {
|
// https://stackoverflow.com/a/40856043/5257399
|
||||||
|
// test if a smart pointer is null
|
||||||
|
if (!synth) {
|
||||||
// don't worry; we'll do this in initialise phase regardless
|
// don't worry; we'll do this in initialise phase regardless
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fluid_synth_set_sample_rate(synth, sampleRate);
|
fluid_synth_set_sample_rate(synth.get(), sampleRate);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,10 +19,13 @@ using namespace std;
|
||||||
|
|
||||||
class FluidSynthModel {
|
class FluidSynthModel {
|
||||||
public:
|
public:
|
||||||
FluidSynthModel(shared_ptr<SharesParams> sharedParams);
|
FluidSynthModel(
|
||||||
~FluidSynthModel();
|
AudioProcessorValueTreeState& valueTreeState,
|
||||||
|
SharesParams& sharedParams
|
||||||
|
);
|
||||||
|
// ~FluidSynthModel();
|
||||||
|
|
||||||
fluid_synth_t* getSynth();
|
shared_ptr<fluid_synth_t> getSynth();
|
||||||
void initialise();
|
void initialise();
|
||||||
|
|
||||||
BanksToPresets getBanks();
|
BanksToPresets getBanks();
|
||||||
|
@ -65,11 +68,14 @@ public:
|
||||||
const String& getCurrentSoundFontAbsPath();
|
const String& getCurrentSoundFontAbsPath();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
shared_ptr<SharesParams> sharedParams;
|
int handleMidiEvent(void* data, fluid_midi_event_t* event);
|
||||||
|
|
||||||
fluid_synth_t* synth;
|
AudioProcessorValueTreeState& valueTreeState;
|
||||||
fluid_settings_t* settings;
|
SharesParams& sharedParams;
|
||||||
// fluid_audio_driver_t* driver;
|
|
||||||
|
shared_ptr<fluid_synth_t> synth;
|
||||||
|
unique_ptr<fluid_settings_t, decltype(&delete_fluid_settings)> settings;
|
||||||
|
// unique_ptr<fluid_midi_driver_t, decltype(&delete_fluid_midi_driver)> midiDriver;
|
||||||
|
|
||||||
String currentSoundFontAbsPath;
|
String currentSoundFontAbsPath;
|
||||||
|
|
||||||
|
|
|
@ -14,73 +14,73 @@
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
Params::Params() noexcept :
|
Params::Params() noexcept
|
||||||
uiWidth{GuiConstants::minWidth},
|
: uiWidth{GuiConstants::minWidth}
|
||||||
uiHeight{GuiConstants::minHeight},
|
, uiHeight{GuiConstants::minHeight}
|
||||||
soundFontPath{String()},
|
, soundFontPath{String()}
|
||||||
preset{-1},
|
// , preset{-1}
|
||||||
bank{-1},
|
// , bank{-1}
|
||||||
attack{0},
|
// , attack{0}
|
||||||
decay{0},
|
// , decay{0}
|
||||||
sustain{0},
|
// , sustain{0}
|
||||||
release{0},
|
// , release{0}
|
||||||
filterCutOff{0},
|
// , filterCutOff{0}
|
||||||
filterResonance{0}
|
// .filterResonance{0}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Params::setAttributesOnXml(XmlElement& xml) {
|
void Params::setAttributesOnXml(shared_ptr<XmlElement> xml) {
|
||||||
xml.setAttribute("uiWidth", uiWidth);
|
xml->setAttribute("uiWidth", uiWidth);
|
||||||
xml.setAttribute("uiHeight", uiHeight);
|
xml->setAttribute("uiHeight", uiHeight);
|
||||||
xml.setAttribute("soundFontPath", soundFontPath);
|
xml->setAttribute("soundFontPath", soundFontPath);
|
||||||
xml.setAttribute("preset", preset);
|
// xml.setAttribute("preset", preset);
|
||||||
xml.setAttribute("bank", bank);
|
// xml.setAttribute("bank", bank);
|
||||||
xml.setAttribute("attack", attack);
|
// xml.setAttribute("attack", attack);
|
||||||
xml.setAttribute("decay", decay);
|
// xml.setAttribute("decay", decay);
|
||||||
xml.setAttribute("sustain", sustain);
|
// xml.setAttribute("sustain", sustain);
|
||||||
xml.setAttribute("release", release);
|
// xml.setAttribute("release", release);
|
||||||
xml.setAttribute("filterCutOff", filterCutOff);
|
// xml.setAttribute("filterCutOff", filterCutOff);
|
||||||
xml.setAttribute("filterResonance", filterResonance);
|
// xml.setAttribute("filterResonance", filterResonance);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Params::loadAttributesFromXml(shared_ptr<XmlElement> xmlState) {
|
void Params::loadAttributesFromXml(shared_ptr<XmlElement> xmlState) {
|
||||||
uiWidth = jmin(jmax(xmlState->getIntAttribute("uiWidth", uiWidth), GuiConstants::minWidth), GuiConstants::maxWidth);
|
uiWidth = jmin(jmax(xmlState->getIntAttribute("uiWidth", uiWidth), GuiConstants::minWidth), GuiConstants::maxWidth);
|
||||||
uiHeight = jmin(jmax(xmlState->getIntAttribute("uiHeight", uiHeight), GuiConstants::minHeight), GuiConstants::maxHeight);
|
uiHeight = jmin(jmax(xmlState->getIntAttribute("uiHeight", uiHeight), GuiConstants::minHeight), GuiConstants::maxHeight);
|
||||||
soundFontPath = xmlState->getStringAttribute("soundFontPath", soundFontPath);
|
soundFontPath = xmlState->getStringAttribute("soundFontPath", soundFontPath);
|
||||||
preset = xmlState->getIntAttribute("preset", preset);
|
// preset = xmlState->getIntAttribute("preset", preset);
|
||||||
bank = xmlState->getIntAttribute("bank", bank);
|
// bank = xmlState->getIntAttribute("bank", bank);
|
||||||
attack = jmin(jmax(xmlState->getIntAttribute("attack", attack), MidiConstants::midiMinValue), MidiConstants::midiMaxValue);
|
// attack = jmin(jmax(xmlState->getIntAttribute("attack", attack), MidiConstants::midiMinValue), MidiConstants::midiMaxValue);
|
||||||
decay = jmin(jmax(xmlState->getIntAttribute("decay", decay), MidiConstants::midiMinValue), MidiConstants::midiMaxValue);
|
// decay = jmin(jmax(xmlState->getIntAttribute("decay", decay), MidiConstants::midiMinValue), MidiConstants::midiMaxValue);
|
||||||
sustain = jmin(jmax(xmlState->getIntAttribute("sustain", sustain), MidiConstants::midiMinValue), MidiConstants::midiMaxValue);
|
// sustain = jmin(jmax(xmlState->getIntAttribute("sustain", sustain), MidiConstants::midiMinValue), MidiConstants::midiMaxValue);
|
||||||
release = jmin(jmax(xmlState->getIntAttribute("release", release), MidiConstants::midiMinValue), MidiConstants::midiMaxValue);
|
// release = jmin(jmax(xmlState->getIntAttribute("release", release), MidiConstants::midiMinValue), MidiConstants::midiMaxValue);
|
||||||
filterCutOff = jmin(jmax(xmlState->getIntAttribute("filterCutOff", filterCutOff), MidiConstants::midiMinValue), MidiConstants::midiMaxValue);
|
// filterCutOff = jmin(jmax(xmlState->getIntAttribute("filterCutOff", filterCutOff), MidiConstants::midiMinValue), MidiConstants::midiMaxValue);
|
||||||
filterResonance = jmin(jmax(xmlState->getIntAttribute("filterResonance", filterResonance), MidiConstants::midiMinValue), MidiConstants::midiMaxValue);
|
// filterResonance = jmin(jmax(xmlState->getIntAttribute("filterResonance", filterResonance), MidiConstants::midiMinValue), MidiConstants::midiMaxValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Params::acceptMidiControlEvent(int controller, int value) {
|
//void Params::acceptMidiControlEvent(int controller, int value) {
|
||||||
switch(static_cast<fluid_midi_control_change>(controller)) {
|
// switch(static_cast<fluid_midi_control_change>(controller)) {
|
||||||
case SOUND_CTRL2: // MIDI CC 71 Timbre/Harmonic Intensity (filter resonance)
|
// case SOUND_CTRL2: // MIDI CC 71 Timbre/Harmonic Intensity (filter resonance)
|
||||||
filterResonance = value;
|
// filterResonance = value;
|
||||||
break;
|
// break;
|
||||||
case SOUND_CTRL3: // MIDI CC 72 Release time
|
// case SOUND_CTRL3: // MIDI CC 72 Release time
|
||||||
release = value;
|
// release = value;
|
||||||
break;
|
// break;
|
||||||
case SOUND_CTRL4: // MIDI CC 73 Attack time
|
// case SOUND_CTRL4: // MIDI CC 73 Attack time
|
||||||
attack = value;
|
// attack = value;
|
||||||
break;
|
// break;
|
||||||
case SOUND_CTRL5: // MIDI CC 74 Brightness (cutoff frequency, FILTERFC)
|
// case SOUND_CTRL5: // MIDI CC 74 Brightness (cutoff frequency, FILTERFC)
|
||||||
filterCutOff = value;
|
// filterCutOff = value;
|
||||||
break;
|
// break;
|
||||||
case SOUND_CTRL6: // MIDI CC 75 Decay Time
|
// case SOUND_CTRL6: // MIDI CC 75 Decay Time
|
||||||
decay = value;
|
// decay = value;
|
||||||
break;
|
// break;
|
||||||
case SOUND_CTRL10: // MIDI CC 79 undefined
|
// case SOUND_CTRL10: // MIDI CC 79 undefined
|
||||||
sustain = value;
|
// sustain = value;
|
||||||
break;
|
// break;
|
||||||
default:
|
// default:
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
||||||
void Params::setSoundFontPath(const String& value) {
|
void Params::setSoundFontPath(const String& value) {
|
||||||
soundFontPath = value;
|
soundFontPath = value;
|
||||||
|
@ -89,64 +89,64 @@ void Params::setSoundFontPath(const String& value) {
|
||||||
String& Params::getSoundFontPath() {
|
String& Params::getSoundFontPath() {
|
||||||
return soundFontPath;
|
return soundFontPath;
|
||||||
}
|
}
|
||||||
int Params::getPreset() {
|
//int Params::getPreset() {
|
||||||
return preset;
|
// return preset;
|
||||||
}
|
//}
|
||||||
int Params::getBank() {
|
//int Params::getBank() {
|
||||||
return bank;
|
// return bank;
|
||||||
}
|
//}
|
||||||
int Params::getUiWidth() {
|
int Params::getUiWidth() {
|
||||||
return uiWidth;
|
return uiWidth;
|
||||||
}
|
}
|
||||||
int Params::getUiHeight() {
|
int Params::getUiHeight() {
|
||||||
return uiHeight;
|
return uiHeight;
|
||||||
}
|
}
|
||||||
int Params::getAttack() {
|
//int Params::getAttack() {
|
||||||
return attack;
|
// return attack;
|
||||||
}
|
//}
|
||||||
int Params::getDecay() {
|
//int Params::getDecay() {
|
||||||
return decay;
|
// return decay;
|
||||||
}
|
//}
|
||||||
int Params::getSustain() {
|
//int Params::getSustain() {
|
||||||
return sustain;
|
// return sustain;
|
||||||
}
|
//}
|
||||||
int Params::getRelease() {
|
//int Params::getRelease() {
|
||||||
return release;
|
// return release;
|
||||||
}
|
//}
|
||||||
int Params::getFilterCutOff() {
|
//int Params::getFilterCutOff() {
|
||||||
return filterCutOff;
|
// return filterCutOff;
|
||||||
}
|
//}
|
||||||
int Params::getFilterResonance() {
|
//int Params::getFilterResonance() {
|
||||||
return filterResonance;
|
// return filterResonance;
|
||||||
}
|
//}
|
||||||
|
|
||||||
void Params::setPreset(int value) {
|
//void Params::setPreset(int value) {
|
||||||
preset = value;
|
// preset = value;
|
||||||
}
|
//}
|
||||||
void Params::setBank(int value) {
|
//void Params::setBank(int value) {
|
||||||
bank = value;
|
// bank = value;
|
||||||
}
|
//}
|
||||||
void Params::setUiWidth(int value) {
|
void Params::setUiWidth(int value) {
|
||||||
uiWidth = value;
|
uiWidth = value;
|
||||||
}
|
}
|
||||||
void Params::setUiHeight(int value) {
|
void Params::setUiHeight(int value) {
|
||||||
uiHeight = value;
|
uiHeight = value;
|
||||||
}
|
}
|
||||||
void Params::setAttack(int value) {
|
//void Params::setAttack(int value) {
|
||||||
attack = value;
|
// attack = value;
|
||||||
}
|
//}
|
||||||
void Params::setDecay(int value) {
|
//void Params::setDecay(int value) {
|
||||||
decay = value;
|
// decay = value;
|
||||||
}
|
//}
|
||||||
void Params::setSustain(int value) {
|
//void Params::setSustain(int value) {
|
||||||
sustain = value;
|
// sustain = value;
|
||||||
}
|
//}
|
||||||
void Params::setRelease(int value) {
|
//void Params::setRelease(int value) {
|
||||||
release = value;
|
// release = value;
|
||||||
}
|
//}
|
||||||
void Params::setFilterCutOff(int value) {
|
//void Params::setFilterCutOff(int value) {
|
||||||
filterCutOff = value;
|
// filterCutOff = value;
|
||||||
}
|
//}
|
||||||
void Params::setFilterResonance(int value) {
|
//void Params::setFilterResonance(int value) {
|
||||||
filterResonance = value;
|
// filterResonance = value;
|
||||||
}
|
//}
|
||||||
|
|
|
@ -9,51 +9,51 @@ class Params: public SharesParams {
|
||||||
public:
|
public:
|
||||||
Params() noexcept;
|
Params() noexcept;
|
||||||
|
|
||||||
virtual void setAttributesOnXml(XmlElement& xml) override;
|
virtual void setAttributesOnXml(shared_ptr<XmlElement> xml) override;
|
||||||
virtual void loadAttributesFromXml(shared_ptr<XmlElement> xmlState) override;
|
virtual void loadAttributesFromXml(shared_ptr<XmlElement> xmlState) override;
|
||||||
virtual void acceptMidiControlEvent(int controller, int value) override;
|
// virtual void acceptMidiControlEvent(int controller, int value) override;
|
||||||
|
|
||||||
virtual void setSoundFontPath(const String& value) override;
|
virtual void setSoundFontPath(const String& value) override;
|
||||||
virtual String& getSoundFontPath() override;
|
virtual String& getSoundFontPath() override;
|
||||||
virtual int getPreset() override;
|
// virtual int getPreset() override;
|
||||||
virtual void setPreset(int value) override;
|
// virtual void setPreset(int value) override;
|
||||||
virtual int getBank() override;
|
// virtual int getBank() override;
|
||||||
virtual void setBank(int value) override;
|
// virtual void setBank(int value) override;
|
||||||
|
|
||||||
virtual int getUiWidth() override;
|
virtual int getUiWidth() override;
|
||||||
virtual void setUiWidth(int value) override;
|
virtual void setUiWidth(int value) override;
|
||||||
virtual int getUiHeight() override;
|
virtual int getUiHeight() override;
|
||||||
virtual void setUiHeight(int value) override;
|
virtual void setUiHeight(int value) override;
|
||||||
|
|
||||||
virtual int getAttack() override;
|
// virtual int getAttack() override;
|
||||||
virtual void setAttack(int value) override;
|
// virtual void setAttack(int value) override;
|
||||||
virtual int getDecay() override;
|
// virtual int getDecay() override;
|
||||||
virtual void setDecay(int value) override;
|
// virtual void setDecay(int value) override;
|
||||||
virtual int getSustain() override;
|
// virtual int getSustain() override;
|
||||||
virtual void setSustain(int value) override;
|
// virtual void setSustain(int value) override;
|
||||||
virtual int getRelease() override;
|
// virtual int getRelease() override;
|
||||||
virtual void setRelease(int value) override;
|
// virtual void setRelease(int value) override;
|
||||||
|
|
||||||
virtual int getFilterCutOff() override;
|
// virtual int getFilterCutOff() override;
|
||||||
virtual void setFilterCutOff(int value) override;
|
// virtual void setFilterCutOff(int value) override;
|
||||||
virtual int getFilterResonance() override;
|
// virtual int getFilterResonance() override;
|
||||||
virtual void setFilterResonance(int value) override;
|
// virtual void setFilterResonance(int value) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int uiWidth;
|
int uiWidth;
|
||||||
int uiHeight;
|
int uiHeight;
|
||||||
|
|
||||||
String soundFontPath;
|
String soundFontPath;
|
||||||
int preset;
|
// int preset;
|
||||||
int bank;
|
// int bank;
|
||||||
|
|
||||||
int attack;
|
// int attack;
|
||||||
int decay;
|
// int decay;
|
||||||
int sustain;
|
// int sustain;
|
||||||
int release;
|
// int release;
|
||||||
|
|
||||||
int filterCutOff;
|
// int filterCutOff;
|
||||||
int filterResonance;
|
// int filterResonance;
|
||||||
|
|
||||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Params)
|
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Params)
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,11 +17,11 @@ JuicySFAudioProcessorEditor::JuicySFAudioProcessorEditor(JuicySFAudioProcessor&
|
||||||
: AudioProcessorEditor{&p},
|
: AudioProcessorEditor{&p},
|
||||||
processor{p},
|
processor{p},
|
||||||
valueTreeState{valueTreeState},
|
valueTreeState{valueTreeState},
|
||||||
sharedParams{p.sharedParams},
|
sharedParams{p.getSharedParams()},
|
||||||
midiKeyboard{p.keyboardState, SurjectiveMidiKeyboardComponent::horizontalKeyboard},
|
midiKeyboard{p.keyboardState, SurjectiveMidiKeyboardComponent::horizontalKeyboard},
|
||||||
tablesComponent{p.getFluidSynthModel()},
|
tablesComponent{valueTreeState, p.getFluidSynthModel()},
|
||||||
filePicker{p.getFluidSynthModel()},
|
filePicker{valueTreeState, p.getFluidSynthModel()},
|
||||||
slidersComponent{p.sharedParams, valueTreeState, p.getFluidSynthModel()}
|
slidersComponent{p.getSharedParams(), valueTreeState, p.getFluidSynthModel()}
|
||||||
{
|
{
|
||||||
// set resize limits for this plug-in
|
// set resize limits for this plug-in
|
||||||
setResizeLimits(
|
setResizeLimits(
|
||||||
|
@ -30,7 +30,7 @@ JuicySFAudioProcessorEditor::JuicySFAudioProcessorEditor(JuicySFAudioProcessor&
|
||||||
GuiConstants::maxWidth,
|
GuiConstants::maxWidth,
|
||||||
GuiConstants::maxHeight);
|
GuiConstants::maxHeight);
|
||||||
|
|
||||||
setSize(sharedParams->getUiWidth(), sharedParams->getUiHeight());
|
setSize(sharedParams.getUiWidth(), sharedParams.getUiHeight());
|
||||||
|
|
||||||
// processor.subscribeToStateChanges(this);
|
// processor.subscribeToStateChanges(this);
|
||||||
|
|
||||||
|
@ -104,8 +104,8 @@ void JuicySFAudioProcessorEditor::resized()
|
||||||
|
|
||||||
tablesComponent.setBounds(rContent);
|
tablesComponent.setBounds(rContent);
|
||||||
|
|
||||||
sharedParams->setUiWidth(getWidth());
|
sharedParams.setUiWidth(getWidth());
|
||||||
sharedParams->setUiHeight(getHeight());
|
sharedParams.setUiHeight(getHeight());
|
||||||
|
|
||||||
// Rectangle<int> r2 (getLocalBounds());
|
// Rectangle<int> r2 (getLocalBounds());
|
||||||
// r2.reduce(0, padding);
|
// r2.reduce(0, padding);
|
||||||
|
|
|
@ -28,7 +28,10 @@ class JuicySFAudioProcessorEditor : public AudioProcessorEditor,
|
||||||
public StateChangeSubscriber*/
|
public StateChangeSubscriber*/
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
JuicySFAudioProcessorEditor (JuicySFAudioProcessor&, AudioProcessorValueTreeState& state);
|
JuicySFAudioProcessorEditor(
|
||||||
|
JuicySFAudioProcessor&,
|
||||||
|
AudioProcessorValueTreeState& state
|
||||||
|
);
|
||||||
~JuicySFAudioProcessorEditor();
|
~JuicySFAudioProcessorEditor();
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
@ -50,7 +53,7 @@ private:
|
||||||
JuicySFAudioProcessor& processor;
|
JuicySFAudioProcessor& processor;
|
||||||
|
|
||||||
AudioProcessorValueTreeState& valueTreeState;
|
AudioProcessorValueTreeState& valueTreeState;
|
||||||
shared_ptr<SharesParams> sharedParams;
|
SharesParams& sharedParams;
|
||||||
|
|
||||||
SurjectiveMidiKeyboardComponent midiKeyboard;
|
SurjectiveMidiKeyboardComponent midiKeyboard;
|
||||||
TablesComponent tablesComponent;
|
TablesComponent tablesComponent;
|
||||||
|
|
|
@ -26,14 +26,16 @@ AudioProcessor* JUCE_CALLTYPE createPluginFilter();
|
||||||
|
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
//, sharedParams{static_pointer_cast<SharesParams>(make_shared<Params>())}
|
||||||
JuicySFAudioProcessor::JuicySFAudioProcessor()
|
JuicySFAudioProcessor::JuicySFAudioProcessor()
|
||||||
: AudioProcessor{getBusesProperties()}
|
: AudioProcessor{getBusesProperties()}
|
||||||
, sharedParams{static_pointer_cast<SharesParams>(make_shared<Params>())}
|
, sharedParams{}
|
||||||
, valueTreeState{*this, nullptr,
|
, valueTreeState{
|
||||||
{ "PARAMETERS" /* MYPLUGINSETTINGS */ },
|
*this,
|
||||||
createParameterLayout()
|
nullptr,
|
||||||
}
|
{ "MYPLUGINSETTINGS" },
|
||||||
, fluidSynthModel{sharedParams}
|
createParameterLayout()}
|
||||||
|
, fluidSynthModel{valueTreeState, sharedParams}
|
||||||
//, fluidSynthModel{*this}
|
//, fluidSynthModel{*this}
|
||||||
//, pluginEditor(nullptr)
|
//, pluginEditor(nullptr)
|
||||||
{
|
{
|
||||||
|
@ -45,9 +47,15 @@ AudioProcessorValueTreeState::ParameterLayout JuicySFAudioProcessor::createParam
|
||||||
|
|
||||||
// for (int i = 1; i < 9; ++i)
|
// for (int i = 1; i < 9; ++i)
|
||||||
// params.push_back (std::make_unique<AudioParameterInt> (String (i), String (i), 0, i, 0));
|
// params.push_back (std::make_unique<AudioParameterInt> (String (i), String (i), 0, i, 0));
|
||||||
|
|
||||||
|
|
||||||
|
// make_unique<AudioParameter>("soundfontPath", "filepath to soundfont", 0, 127, 0, "A" ),
|
||||||
|
|
||||||
// https://stackoverflow.com/a/8469002/5257399
|
// https://stackoverflow.com/a/8469002/5257399
|
||||||
unique_ptr<AudioParameterInt> params[] {
|
unique_ptr<AudioParameterInt> params[] {
|
||||||
|
make_unique<AudioParameterInt>("bank", "which bank is selected in the soundfont", 0, 127, 0, "Bank" ),
|
||||||
|
// note: banks may be sparse, and lack a 0th preset. so defend against this.
|
||||||
|
make_unique<AudioParameterInt>("preset", "which patch (aka patch, program, instrument) is selected in the soundfont", 0, 127, 0, "Preset" ),
|
||||||
make_unique<AudioParameterInt>("attack", "volume envelope attack time", 0, 127, 0, "A" ),
|
make_unique<AudioParameterInt>("attack", "volume envelope attack time", 0, 127, 0, "A" ),
|
||||||
make_unique<AudioParameterInt>("decay", "volume envelope sustain attentuation", 0, 127, 0, "D" ),
|
make_unique<AudioParameterInt>("decay", "volume envelope sustain attentuation", 0, 127, 0, "D" ),
|
||||||
make_unique<AudioParameterInt>("sustain", "volume envelope decay time", 0, 127, 0, "S" ),
|
make_unique<AudioParameterInt>("sustain", "volume envelope decay time", 0, 127, 0, "S" ),
|
||||||
|
@ -70,7 +78,7 @@ JuicySFAudioProcessor::~JuicySFAudioProcessor()
|
||||||
void JuicySFAudioProcessor::initialiseSynth() {
|
void JuicySFAudioProcessor::initialiseSynth() {
|
||||||
fluidSynthModel.initialise();
|
fluidSynthModel.initialise();
|
||||||
|
|
||||||
fluidSynth = fluidSynthModel.getSynth();
|
// fluidSynth = fluidSynthModel.getSynth();
|
||||||
|
|
||||||
const int numVoices = 8;
|
const int numVoices = 8;
|
||||||
|
|
||||||
|
@ -352,8 +360,11 @@ void JuicySFAudioProcessor::getStateInformation (MemoryBlock& destData)
|
||||||
// as intermediaries to make it easy to save and load complex data.
|
// as intermediaries to make it easy to save and load complex data.
|
||||||
|
|
||||||
// Create an outer XML element..
|
// Create an outer XML element..
|
||||||
XmlElement xml{"MYPLUGINSETTINGS"};
|
// XmlElement xml{"MYPLUGINSETTINGS"};
|
||||||
sharedParams->setAttributesOnXml(xml);
|
// sharedParams->setAttributesOnXml(xml);
|
||||||
|
auto state{valueTreeState.copyState()};
|
||||||
|
shared_ptr<XmlElement> xml{state.createXml()};
|
||||||
|
sharedParams.setAttributesOnXml(xml);
|
||||||
|
|
||||||
// list<StateChangeSubscriber*>::iterator p;
|
// list<StateChangeSubscriber*>::iterator p;
|
||||||
// for(p = stateChangeSubscribers.begin(); p != stateChangeSubscribers.end(); p++) {
|
// for(p = stateChangeSubscribers.begin(); p != stateChangeSubscribers.end(); p++) {
|
||||||
|
@ -361,12 +372,12 @@ void JuicySFAudioProcessor::getStateInformation (MemoryBlock& destData)
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// Store the values of all our parameters, using their param ID as the XML attribute
|
// Store the values of all our parameters, using their param ID as the XML attribute
|
||||||
for (auto* param : getParameters())
|
// for (auto* param : getParameters())
|
||||||
if (auto* p = dynamic_cast<AudioProcessorParameterWithID*> (param))
|
// if (auto* p = dynamic_cast<AudioProcessorParameterWithID*> (param))
|
||||||
xml.setAttribute (p->paramID, p->getValue());
|
// xml->setAttribute (p->paramID, p->getValue());
|
||||||
|
|
||||||
// then use this helper function to stuff it into the binary blob and return it..
|
// then use this helper function to stuff it into the binary blob and return it..
|
||||||
copyXmlToBinary (xml, destData);
|
copyXmlToBinary (*xml, destData);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JuicySFAudioProcessor::setStateInformation (const void* data, int sizeInBytes)
|
void JuicySFAudioProcessor::setStateInformation (const void* data, int sizeInBytes)
|
||||||
|
@ -375,40 +386,42 @@ void JuicySFAudioProcessor::setStateInformation (const void* data, int sizeInByt
|
||||||
// whose contents will have been created by the getStateInformation() call.
|
// whose contents will have been created by the getStateInformation() call.
|
||||||
// This getXmlFromBinary() helper function retrieves our XML from the binary blob..
|
// This getXmlFromBinary() helper function retrieves our XML from the binary blob..
|
||||||
shared_ptr<XmlElement> xmlState{getXmlFromBinary(data, sizeInBytes)};
|
shared_ptr<XmlElement> xmlState{getXmlFromBinary(data, sizeInBytes)};
|
||||||
|
// unique_ptr<XmlElement> xmlState{getXmlFromBinary(data, sizeInBytes)};
|
||||||
|
|
||||||
if (xmlState != nullptr)
|
if (xmlState.get() != nullptr) {
|
||||||
{
|
|
||||||
// make sure that it's actually our type of XML object..
|
// make sure that it's actually our type of XML object..
|
||||||
if (xmlState->hasTagName ("MYPLUGINSETTINGS"))
|
// if (xmlState->hasTagName ("MYPLUGINSETTINGS")) {
|
||||||
{
|
if (xmlState->hasTagName(valueTreeState.state.getType())) {
|
||||||
|
valueTreeState.replaceState(ValueTree::fromXml(*xmlState));
|
||||||
// list<StateChangeSubscriber*>::iterator p;
|
// list<StateChangeSubscriber*>::iterator p;
|
||||||
// for(p = stateChangeSubscribers.begin(); p != stateChangeSubscribers.end(); p++) {
|
// for(p = stateChangeSubscribers.begin(); p != stateChangeSubscribers.end(); p++) {
|
||||||
// (*p)->setStateInformation(xmlState);
|
// (*p)->setStateInformation(xmlState);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// ok, now pull out our last window size..
|
// ok, now pull out our last window size..
|
||||||
sharedParams->loadAttributesFromXml(xmlState);
|
sharedParams.loadAttributesFromXml(xmlState);
|
||||||
|
|
||||||
// Now reload our parameters..
|
// Now reload our parameters..
|
||||||
for (auto* param : getParameters())
|
|
||||||
if (auto* p = dynamic_cast<AudioProcessorParameterWithID*> (param))
|
// for (auto* param : getParameters())
|
||||||
p->setValue ((float) xmlState->getDoubleAttribute (p->paramID, p->getValue()));
|
// if (auto* p = dynamic_cast<AudioProcessorParameterWithID*> (param))
|
||||||
|
// p->setValue ((float) xmlState->getDoubleAttribute (p->paramID, p->getValue()));
|
||||||
fluidSynthModel.onFileNameChanged(
|
//
|
||||||
sharedParams->getSoundFontPath(),
|
// fluidSynthModel.onFileNameChanged(
|
||||||
sharedParams->getBank(),
|
// sharedParams->getSoundFontPath(),
|
||||||
sharedParams->getPreset());
|
// sharedParams->getBank(),
|
||||||
|
// sharedParams->getPreset());
|
||||||
AudioProcessorEditor* editor{getActiveEditor()};
|
//
|
||||||
if (editor != nullptr) {
|
// AudioProcessorEditor* editor{getActiveEditor()};
|
||||||
editor->setSize(
|
// if (editor != nullptr) {
|
||||||
sharedParams->getUiWidth(),
|
// editor->setSize(
|
||||||
sharedParams->getUiHeight());
|
// sharedParams->getUiWidth(),
|
||||||
|
// sharedParams->getUiHeight());
|
||||||
jassert(dynamic_cast<ExposesComponents*> (editor) != nullptr);
|
//
|
||||||
ExposesComponents* exposesComponents = dynamic_cast<ExposesComponents*> (editor);
|
// jassert(dynamic_cast<ExposesComponents*> (editor) != nullptr);
|
||||||
exposesComponents->getFilePicker().setDisplayedFilePath(sharedParams->getSoundFontPath());
|
// ExposesComponents* exposesComponents = dynamic_cast<ExposesComponents*> (editor);
|
||||||
}
|
// exposesComponents->getFilePicker().setDisplayedFilePath(sharedParams->getSoundFontPath());
|
||||||
|
// }
|
||||||
|
|
||||||
// const String& currentSoundFontAbsPath = fluidSynthModel->getCurrentSoundFontAbsPath();
|
// const String& currentSoundFontAbsPath = fluidSynthModel->getCurrentSoundFontAbsPath();
|
||||||
// if (currentSoundFontAbsPath.isNotEmpty()) {
|
// if (currentSoundFontAbsPath.isNotEmpty()) {
|
||||||
|
@ -431,8 +444,12 @@ bool JuicySFAudioProcessor::supportsDoublePrecisionProcessing() const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
FluidSynthModel* JuicySFAudioProcessor::getFluidSynthModel() {
|
FluidSynthModel& JuicySFAudioProcessor::getFluidSynthModel() {
|
||||||
return &fluidSynthModel;
|
return fluidSynthModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
SharesParams& JuicySFAudioProcessor::getSharedParams() {
|
||||||
|
return sharedParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "FluidSynthModel.h"
|
#include "FluidSynthModel.h"
|
||||||
#include "StateChangeSubscriber.h"
|
#include "StateChangeSubscriber.h"
|
||||||
#include "SharesParams.h"
|
#include "SharesParams.h"
|
||||||
|
#include "Params.h"
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -62,18 +63,18 @@ public:
|
||||||
|
|
||||||
bool supportsDoublePrecisionProcessing() const override;
|
bool supportsDoublePrecisionProcessing() const override;
|
||||||
|
|
||||||
FluidSynthModel* getFluidSynthModel();
|
FluidSynthModel& getFluidSynthModel();
|
||||||
|
SharesParams& getSharedParams();
|
||||||
|
|
||||||
MidiKeyboardState keyboardState;
|
MidiKeyboardState keyboardState;
|
||||||
|
|
||||||
shared_ptr<SharesParams> sharedParams;
|
|
||||||
|
|
||||||
// void subscribeToStateChanges(StateChangeSubscriber* subscriber);
|
// void subscribeToStateChanges(StateChangeSubscriber* subscriber);
|
||||||
// void unsubscribeFromStateChanges(StateChangeSubscriber* subscriber);
|
// void unsubscribeFromStateChanges(StateChangeSubscriber* subscriber);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void initialiseSynth();
|
void initialiseSynth();
|
||||||
|
|
||||||
|
Params sharedParams;
|
||||||
AudioProcessorValueTreeState valueTreeState;
|
AudioProcessorValueTreeState valueTreeState;
|
||||||
|
|
||||||
FluidSynthModel fluidSynthModel;
|
FluidSynthModel fluidSynthModel;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//
|
// http://www.synthfont.com/Tutorial6.html
|
||||||
// Created by Alex Birch on 17/09/2017.
|
// a bank can hold many (128) presets
|
||||||
//
|
// bank 128 is reserved for percussion
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
|
|
@ -13,35 +13,35 @@ class SharesParams {
|
||||||
public:
|
public:
|
||||||
virtual ~SharesParams() {}
|
virtual ~SharesParams() {}
|
||||||
|
|
||||||
virtual void setAttributesOnXml(XmlElement& xml) = 0;
|
virtual void setAttributesOnXml(shared_ptr<XmlElement> xml) = 0;
|
||||||
virtual void loadAttributesFromXml(shared_ptr<XmlElement> xmlState) = 0;
|
virtual void loadAttributesFromXml(shared_ptr<XmlElement> xmlState) = 0;
|
||||||
virtual void acceptMidiControlEvent(int controller, int value) = 0;
|
// virtual void acceptMidiControlEvent(int controller, int value) = 0;
|
||||||
|
|
||||||
virtual void setSoundFontPath(const String& value) = 0;
|
virtual void setSoundFontPath(const String& value) = 0;
|
||||||
virtual String& getSoundFontPath() = 0;
|
virtual String& getSoundFontPath() = 0;
|
||||||
virtual int getPreset() = 0;
|
// virtual int getPreset() = 0;
|
||||||
virtual void setPreset(int value) = 0;
|
// virtual void setPreset(int value) = 0;
|
||||||
virtual int getBank() = 0;
|
// virtual int getBank() = 0;
|
||||||
virtual void setBank(int value) = 0;
|
// virtual void setBank(int value) = 0;
|
||||||
|
|
||||||
virtual int getUiWidth() = 0;
|
virtual int getUiWidth() = 0;
|
||||||
virtual void setUiWidth(int value) = 0;
|
virtual void setUiWidth(int value) = 0;
|
||||||
virtual int getUiHeight() = 0;
|
virtual int getUiHeight() = 0;
|
||||||
virtual void setUiHeight(int value) = 0;
|
virtual void setUiHeight(int value) = 0;
|
||||||
|
|
||||||
virtual int getAttack() = 0;
|
// virtual int getAttack() = 0;
|
||||||
virtual void setAttack(int value) = 0;
|
// virtual void setAttack(int value) = 0;
|
||||||
virtual int getDecay() = 0;
|
// virtual int getDecay() = 0;
|
||||||
virtual void setDecay(int value) = 0;
|
// virtual void setDecay(int value) = 0;
|
||||||
virtual int getSustain() = 0;
|
// virtual int getSustain() = 0;
|
||||||
virtual void setSustain(int value) = 0;
|
// virtual void setSustain(int value) = 0;
|
||||||
virtual int getRelease() = 0;
|
// virtual int getRelease() = 0;
|
||||||
virtual void setRelease(int value) = 0;
|
// virtual void setRelease(int value) = 0;
|
||||||
|
|
||||||
virtual int getFilterCutOff() = 0;
|
// virtual int getFilterCutOff() = 0;
|
||||||
virtual void setFilterCutOff(int value) = 0;
|
// virtual void setFilterCutOff(int value) = 0;
|
||||||
virtual int getFilterResonance() = 0;
|
// virtual int getFilterResonance() = 0;
|
||||||
virtual void setFilterResonance(int value) = 0;
|
// virtual void setFilterResonance(int value) = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ std::function<void()> SlidersComponent::makeSliderListener(Slider& slider, int c
|
||||||
s << slider.getComponentID() << ", controller " << controller << ", value " << slider.getValue() << ", xmlReleaseValue " << value;
|
s << slider.getComponentID() << ", controller " << controller << ", value " << slider.getValue() << ", xmlReleaseValue " << value;
|
||||||
DEBUG_PRINT(s);
|
DEBUG_PRINT(s);
|
||||||
// slider.setValue(slider.getValue(), NotificationType::dontSendNotification);
|
// slider.setValue(slider.getValue(), NotificationType::dontSendNotification);
|
||||||
fluidSynthModel->setControllerValue(controller, slider.getValue());
|
fluidSynthModel.setControllerValue(controller, slider.getValue());
|
||||||
// callback();
|
// callback();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -115,9 +115,9 @@ void SlidersComponent::acceptMidiControlEvent(int controller, int value) {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
SlidersComponent::SlidersComponent(
|
SlidersComponent::SlidersComponent(
|
||||||
shared_ptr<SharesParams> sharedParams,
|
SharesParams& sharedParams,
|
||||||
AudioProcessorValueTreeState& valueTreeState,
|
AudioProcessorValueTreeState& valueTreeState,
|
||||||
FluidSynthModel* fluidSynthModel)
|
FluidSynthModel& fluidSynthModel)
|
||||||
: sharedParams{sharedParams}
|
: sharedParams{sharedParams}
|
||||||
, valueTreeState{valueTreeState}
|
, valueTreeState{valueTreeState}
|
||||||
, fluidSynthModel{fluidSynthModel}
|
, fluidSynthModel{fluidSynthModel}
|
||||||
|
|
|
@ -13,9 +13,9 @@ class SlidersComponent : public Component,
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SlidersComponent(
|
SlidersComponent(
|
||||||
shared_ptr<SharesParams> sharedParams,
|
SharesParams& sharedParams,
|
||||||
AudioProcessorValueTreeState& valueTreeState,
|
AudioProcessorValueTreeState& valueTreeState,
|
||||||
FluidSynthModel* fluidSynthModel);
|
FluidSynthModel& fluidSynthModel);
|
||||||
~SlidersComponent();
|
~SlidersComponent();
|
||||||
|
|
||||||
void resized() override;
|
void resized() override;
|
||||||
|
@ -35,9 +35,9 @@ public:
|
||||||
private:
|
private:
|
||||||
std::function<void()> makeSliderListener(Slider& slider, int controller);
|
std::function<void()> makeSliderListener(Slider& slider, int controller);
|
||||||
|
|
||||||
shared_ptr<SharesParams> sharedParams;
|
SharesParams& sharedParams;
|
||||||
AudioProcessorValueTreeState& valueTreeState;
|
AudioProcessorValueTreeState& valueTreeState;
|
||||||
FluidSynthModel* fluidSynthModel;
|
FluidSynthModel& fluidSynthModel;
|
||||||
|
|
||||||
GroupComponent envelopeGroup;
|
GroupComponent envelopeGroup;
|
||||||
|
|
||||||
|
|
|
@ -6,13 +6,15 @@
|
||||||
#include "SoundfontSynthSound.h"
|
#include "SoundfontSynthSound.h"
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
|
|
||||||
SoundfontSynthVoice::SoundfontSynthVoice(fluid_synth_t* synth)
|
using namespace std;
|
||||||
: tailOff (0.0),
|
|
||||||
level(0.0),
|
SoundfontSynthVoice::SoundfontSynthVoice(shared_ptr<fluid_synth_t> synth)
|
||||||
currentAngle(0.0),
|
: tailOff(0.0)
|
||||||
angleDelta(0.0),
|
, level(0.0)
|
||||||
midiNoteNumber(0),
|
, currentAngle(0.0)
|
||||||
synth(synth)
|
, angleDelta(0.0)
|
||||||
|
, midiNoteNumber(0)
|
||||||
|
, synth(synth)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,7 +28,7 @@ void SoundfontSynthVoice::startNote(
|
||||||
int /*currentPitchWheelPosition*/) {
|
int /*currentPitchWheelPosition*/) {
|
||||||
this->midiNoteNumber = midiNoteNumber;
|
this->midiNoteNumber = midiNoteNumber;
|
||||||
DEBUG_PRINT ( juce::String::formatted("JUCE noteon: %d, %d\n", midiNoteNumber, velocity) );
|
DEBUG_PRINT ( juce::String::formatted("JUCE noteon: %d, %d\n", midiNoteNumber, velocity) );
|
||||||
fluid_synth_noteon(synth, 0, midiNoteNumber, static_cast<int>(velocity * 127));
|
fluid_synth_noteon(synth.get(), 0, midiNoteNumber, static_cast<int>(velocity * 127));
|
||||||
|
|
||||||
// currentAngle = 0.0;
|
// currentAngle = 0.0;
|
||||||
// level = velocity * 0.15;
|
// level = velocity * 0.15;
|
||||||
|
@ -59,7 +61,7 @@ void SoundfontSynthVoice::stopNote (float /*velocity*/, bool allowTailOff) {
|
||||||
// }
|
// }
|
||||||
DEBUG_PRINT ( juce::String("JUCE noteoff\n") );
|
DEBUG_PRINT ( juce::String("JUCE noteoff\n") );
|
||||||
clearCurrentNote();
|
clearCurrentNote();
|
||||||
fluid_synth_noteoff(synth, 0, this->midiNoteNumber);
|
fluid_synth_noteoff(synth.get(), 0, this->midiNoteNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
// receives input as MIDI 0 to 16383, with 8192 being center
|
// receives input as MIDI 0 to 16383, with 8192 being center
|
||||||
|
|
|
@ -8,11 +8,11 @@
|
||||||
#include<fluidsynth.h>
|
#include<fluidsynth.h>
|
||||||
#include "../JuceLibraryCode/JuceHeader.h"
|
#include "../JuceLibraryCode/JuceHeader.h"
|
||||||
|
|
||||||
using std::shared_ptr;
|
using namespace std;
|
||||||
|
|
||||||
class SoundfontSynthVoice : public SynthesiserVoice {
|
class SoundfontSynthVoice : public SynthesiserVoice {
|
||||||
public:
|
public:
|
||||||
SoundfontSynthVoice(fluid_synth_t* synth);
|
SoundfontSynthVoice(shared_ptr<fluid_synth_t> synth);
|
||||||
|
|
||||||
bool canPlaySound (SynthesiserSound* sound) override;
|
bool canPlaySound (SynthesiserSound* sound) override;
|
||||||
void startNote (
|
void startNote (
|
||||||
|
@ -35,5 +35,5 @@ private:
|
||||||
double angleDelta;
|
double angleDelta;
|
||||||
int midiNoteNumber;
|
int midiNoteNumber;
|
||||||
|
|
||||||
fluid_synth_t* synth;
|
shared_ptr<fluid_synth_t> synth;
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,10 +8,13 @@ using namespace std;
|
||||||
using namespace placeholders;
|
using namespace placeholders;
|
||||||
|
|
||||||
TablesComponent::TablesComponent(
|
TablesComponent::TablesComponent(
|
||||||
FluidSynthModel* fluidSynthModel
|
AudioProcessorValueTreeState& valueTreeState,
|
||||||
) : fluidSynthModel(fluidSynthModel),
|
FluidSynthModel& fluidSynthModel
|
||||||
banksToPresets(fluidSynthModel->getBanks()),
|
)
|
||||||
initialised(false)
|
: valueTreeState{valueTreeState}
|
||||||
|
, fluidSynthModel{fluidSynthModel}
|
||||||
|
, banksToPresets{fluidSynthModel.getBanks()}
|
||||||
|
, initialised{false}
|
||||||
{
|
{
|
||||||
fluid_preset_t* currentPreset = getCurrentPreset();
|
fluid_preset_t* currentPreset = getCurrentPreset();
|
||||||
selectedBank = -1;
|
selectedBank = -1;
|
||||||
|
@ -59,13 +62,13 @@ TablesComponent::TablesComponent(
|
||||||
|
|
||||||
initialised = true;
|
initialised = true;
|
||||||
|
|
||||||
fluidSynthModel->addListener(this);
|
fluidSynthModel.addListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
fluid_preset_t* TablesComponent::getCurrentPreset() {
|
fluid_preset_t* TablesComponent::getCurrentPreset() {
|
||||||
fluid_synth_t* synth = fluidSynthModel->getSynth();
|
shared_ptr<fluid_synth_t> synth {fluidSynthModel.getSynth()};
|
||||||
|
|
||||||
return fluid_synth_get_channel_preset(synth, fluidSynthModel->getChannel());
|
return fluid_synth_get_channel_preset(synth.get(), fluidSynthModel.getChannel());
|
||||||
}
|
}
|
||||||
|
|
||||||
Preset TablesComponent::getFirstPresetInBank(int bank) {
|
Preset TablesComponent::getFirstPresetInBank(int bank) {
|
||||||
|
@ -108,13 +111,13 @@ void TablesComponent::onPresetSelected(int preset) {
|
||||||
}
|
}
|
||||||
cout << "Preset " << preset << endl;
|
cout << "Preset " << preset << endl;
|
||||||
// selectedPreset = preset;
|
// selectedPreset = preset;
|
||||||
fluidSynthModel->changePreset(selectedBank, preset);
|
fluidSynthModel.changePreset(selectedBank, preset);
|
||||||
}
|
}
|
||||||
|
|
||||||
TablesComponent::~TablesComponent() {
|
TablesComponent::~TablesComponent() {
|
||||||
delete presetTable;
|
delete presetTable;
|
||||||
delete banks;
|
delete banks;
|
||||||
fluidSynthModel->removeListener(this);
|
fluidSynthModel.removeListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<string> TablesComponent::mapBanks(const BanksToPresets &banksToPresets) {
|
vector<string> TablesComponent::mapBanks(const BanksToPresets &banksToPresets) {
|
||||||
|
@ -165,7 +168,7 @@ bool TablesComponent::keyPressed(const KeyPress &key) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TablesComponent::fontChanged(FluidSynthModel *, const String &) {
|
void TablesComponent::fontChanged(FluidSynthModel *, const String &) {
|
||||||
banksToPresets = fluidSynthModel->getBanks();
|
banksToPresets = fluidSynthModel.getBanks();
|
||||||
|
|
||||||
fluid_preset_t* currentPreset = getCurrentPreset();
|
fluid_preset_t* currentPreset = getCurrentPreset();
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,8 @@ class TablesComponent : public Component,
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TablesComponent(
|
TablesComponent(
|
||||||
FluidSynthModel* fluidSynthModel
|
AudioProcessorValueTreeState& valueTreeState,
|
||||||
|
FluidSynthModel& fluidSynthModel
|
||||||
);
|
);
|
||||||
~TablesComponent();
|
~TablesComponent();
|
||||||
|
|
||||||
|
@ -30,7 +31,8 @@ public:
|
||||||
void fontChanged(FluidSynthModel *, const String &) override;
|
void fontChanged(FluidSynthModel *, const String &) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FluidSynthModel* fluidSynthModel;
|
AudioProcessorValueTreeState& valueTreeState;
|
||||||
|
FluidSynthModel& fluidSynthModel;
|
||||||
int selectedBank;
|
int selectedBank;
|
||||||
|
|
||||||
Pills* banks;
|
Pills* banks;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user