remove shared access to fluidsynth instance

This commit is contained in:
Alex Birch 2019-07-28 22:51:51 +01:00
parent d4a060b769
commit 39f9d86bd1
No known key found for this signature in database
GPG Key ID: 305EB1F98D44ACBA
9 changed files with 81 additions and 333 deletions

View File

@ -33,7 +33,6 @@
21AC354419419A4D80ADE43A /* include_juce_audio_plugin_client_AU_2.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7E47C0A828016F7D0D63C0D6 /* include_juce_audio_plugin_client_AU_2.mm */; }; 21AC354419419A4D80ADE43A /* include_juce_audio_plugin_client_AU_2.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7E47C0A828016F7D0D63C0D6 /* include_juce_audio_plugin_client_AU_2.mm */; };
2918F46AFD2AB89F9FA847DC /* include_juce_events.mm in Sources */ = {isa = PBXBuildFile; fileRef = 373EF982A53046CE00BECE68 /* include_juce_events.mm */; }; 2918F46AFD2AB89F9FA847DC /* include_juce_events.mm in Sources */ = {isa = PBXBuildFile; fileRef = 373EF982A53046CE00BECE68 /* include_juce_events.mm */; };
2E77C6FAF1BCDB9EB29D20B9 /* PluginProcessor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D53CAB963D5051C786D3A52D /* PluginProcessor.cpp */; }; 2E77C6FAF1BCDB9EB29D20B9 /* PluginProcessor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D53CAB963D5051C786D3A52D /* PluginProcessor.cpp */; };
305606C42BB0F2A12D382D34 /* SoundfontSynthVoice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B5A057FEC371053E83A73E47 /* SoundfontSynthVoice.cpp */; };
35099D9322CAA87D00CD4523 /* Params.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 35099D9122CAA87D00CD4523 /* Params.cpp */; }; 35099D9322CAA87D00CD4523 /* Params.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 35099D9122CAA87D00CD4523 /* Params.cpp */; };
358E458C22BEE5090087ED8D /* RecentFilesMenuTemplate.nib in Resources */ = {isa = PBXBuildFile; fileRef = 78CC5234CCFE3B170585DDAD /* RecentFilesMenuTemplate.nib */; }; 358E458C22BEE5090087ED8D /* RecentFilesMenuTemplate.nib in Resources */ = {isa = PBXBuildFile; fileRef = 78CC5234CCFE3B170585DDAD /* RecentFilesMenuTemplate.nib */; };
358E458D22BEE5090087ED8D /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C1616112041466F7324D7E19 /* Accelerate.framework */; }; 358E458D22BEE5090087ED8D /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C1616112041466F7324D7E19 /* Accelerate.framework */; };
@ -128,7 +127,6 @@
9C107CE4B586E4B097D9D04E /* SurjectiveMidiKeyboardComponent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4119A8200AC54674C00EFE66 /* SurjectiveMidiKeyboardComponent.cpp */; }; 9C107CE4B586E4B097D9D04E /* SurjectiveMidiKeyboardComponent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4119A8200AC54674C00EFE66 /* SurjectiveMidiKeyboardComponent.cpp */; };
9C2580F953071AD611EB6166 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 28CA077CDD21D0FEC66FC290 /* AudioToolbox.framework */; }; 9C2580F953071AD611EB6166 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 28CA077CDD21D0FEC66FC290 /* AudioToolbox.framework */; };
AC5E4EF988D864A298E3650D /* TablesComponent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0DD5458189C039F5A4FAD62D /* TablesComponent.cpp */; }; AC5E4EF988D864A298E3650D /* TablesComponent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0DD5458189C039F5A4FAD62D /* TablesComponent.cpp */; };
B66EBD76F6051D97D56C97AB /* SoundfontSynthSound.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7D7B71BE20CA213D2FCD7FEE /* SoundfontSynthSound.cpp */; };
B92F6EAB1D5ACC13AF0CD750 /* CoreAudioKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A67D09546C4E4831438F7DBD /* CoreAudioKit.framework */; }; B92F6EAB1D5ACC13AF0CD750 /* CoreAudioKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A67D09546C4E4831438F7DBD /* CoreAudioKit.framework */; };
BB7C2221DA61425A1AC65694 /* include_juce_gui_extra.mm in Sources */ = {isa = PBXBuildFile; fileRef = 44FB953DA425CBBA8AC21417 /* include_juce_gui_extra.mm */; }; BB7C2221DA61425A1AC65694 /* include_juce_gui_extra.mm in Sources */ = {isa = PBXBuildFile; fileRef = 44FB953DA425CBBA8AC21417 /* include_juce_gui_extra.mm */; };
BFD9EF2D67067FC1E5BA3546 /* MyColours.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 29F2CE1B40FAE1467C7876C5 /* MyColours.cpp */; }; BFD9EF2D67067FC1E5BA3546 /* MyColours.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 29F2CE1B40FAE1467C7876C5 /* MyColours.cpp */; };
@ -331,11 +329,9 @@
6FA795817D2F3B3119FDD754 /* juce_core */ = {isa = PBXFileReference; lastKnownFileType = folder; name = juce_core; path = /Applications/JUCE/modules/juce_core; sourceTree = "<absolute>"; }; 6FA795817D2F3B3119FDD754 /* juce_core */ = {isa = PBXFileReference; lastKnownFileType = folder; name = juce_core; path = /Applications/JUCE/modules/juce_core; sourceTree = "<absolute>"; };
6FEF19AE08ED1DC1E3D9DF43 /* AppConfig.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AppConfig.h; path = ../../JuceLibraryCode/AppConfig.h; sourceTree = SOURCE_ROOT; }; 6FEF19AE08ED1DC1E3D9DF43 /* AppConfig.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AppConfig.h; path = ../../JuceLibraryCode/AppConfig.h; sourceTree = SOURCE_ROOT; };
706FF998202761F30811FA6B /* juce_audio_devices */ = {isa = PBXFileReference; lastKnownFileType = folder; name = juce_audio_devices; path = /Applications/JUCE/modules/juce_audio_devices; sourceTree = "<absolute>"; }; 706FF998202761F30811FA6B /* juce_audio_devices */ = {isa = PBXFileReference; lastKnownFileType = folder; name = juce_audio_devices; path = /Applications/JUCE/modules/juce_audio_devices; sourceTree = "<absolute>"; };
76724E30D8976FC4C2EE56FF /* SoundfontSynthSound.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SoundfontSynthSound.h; path = ../../Source/SoundfontSynthSound.h; sourceTree = SOURCE_ROOT; };
78CC5234CCFE3B170585DDAD /* RecentFilesMenuTemplate.nib */ = {isa = PBXFileReference; lastKnownFileType = file.nib; path = RecentFilesMenuTemplate.nib; sourceTree = SOURCE_ROOT; }; 78CC5234CCFE3B170585DDAD /* RecentFilesMenuTemplate.nib */ = {isa = PBXFileReference; lastKnownFileType = file.nib; path = RecentFilesMenuTemplate.nib; sourceTree = SOURCE_ROOT; };
7C699A8B65F3F9FB5004F22D /* juce_gui_extra */ = {isa = PBXFileReference; lastKnownFileType = folder; name = juce_gui_extra; path = /Applications/JUCE/modules/juce_gui_extra; sourceTree = "<absolute>"; }; 7C699A8B65F3F9FB5004F22D /* juce_gui_extra */ = {isa = PBXFileReference; lastKnownFileType = folder; name = juce_gui_extra; path = /Applications/JUCE/modules/juce_gui_extra; sourceTree = "<absolute>"; };
7D2457AD994644752178FC82 /* include_juce_audio_plugin_client_VST_utils.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = include_juce_audio_plugin_client_VST_utils.mm; path = ../../JuceLibraryCode/include_juce_audio_plugin_client_VST_utils.mm; sourceTree = SOURCE_ROOT; }; 7D2457AD994644752178FC82 /* include_juce_audio_plugin_client_VST_utils.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = include_juce_audio_plugin_client_VST_utils.mm; path = ../../JuceLibraryCode/include_juce_audio_plugin_client_VST_utils.mm; sourceTree = SOURCE_ROOT; };
7D7B71BE20CA213D2FCD7FEE /* SoundfontSynthSound.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SoundfontSynthSound.cpp; path = ../../Source/SoundfontSynthSound.cpp; sourceTree = SOURCE_ROOT; };
7E47C0A828016F7D0D63C0D6 /* include_juce_audio_plugin_client_AU_2.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = include_juce_audio_plugin_client_AU_2.mm; path = ../../JuceLibraryCode/include_juce_audio_plugin_client_AU_2.mm; sourceTree = SOURCE_ROOT; }; 7E47C0A828016F7D0D63C0D6 /* include_juce_audio_plugin_client_AU_2.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = include_juce_audio_plugin_client_AU_2.mm; path = ../../JuceLibraryCode/include_juce_audio_plugin_client_AU_2.mm; sourceTree = SOURCE_ROOT; };
88ADEBF51BD04FEA9422D276 /* FilePickerFragment.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FilePickerFragment.h; path = ../../Source/FilePickerFragment.h; sourceTree = SOURCE_ROOT; }; 88ADEBF51BD04FEA9422D276 /* FilePickerFragment.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FilePickerFragment.h; path = ../../Source/FilePickerFragment.h; sourceTree = SOURCE_ROOT; };
8990F3EAFFBBD6A42247C663 /* PluginEditor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PluginEditor.h; path = ../../Source/PluginEditor.h; sourceTree = SOURCE_ROOT; }; 8990F3EAFFBBD6A42247C663 /* PluginEditor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PluginEditor.h; path = ../../Source/PluginEditor.h; sourceTree = SOURCE_ROOT; };
@ -348,8 +344,6 @@
ADC93C26314F163B963461E2 /* include_juce_audio_utils.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = include_juce_audio_utils.mm; path = ../../JuceLibraryCode/include_juce_audio_utils.mm; sourceTree = SOURCE_ROOT; }; ADC93C26314F163B963461E2 /* include_juce_audio_utils.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = include_juce_audio_utils.mm; path = ../../JuceLibraryCode/include_juce_audio_utils.mm; sourceTree = SOURCE_ROOT; };
AE397302E7E3F3A14A0C5F3C /* Preset.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Preset.h; path = ../../Source/Preset.h; sourceTree = SOURCE_ROOT; }; AE397302E7E3F3A14A0C5F3C /* Preset.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Preset.h; path = ../../Source/Preset.h; sourceTree = SOURCE_ROOT; };
B000E7A360C0C86ADD3C911D /* BankAndPreset.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = BankAndPreset.h; path = ../../Source/BankAndPreset.h; sourceTree = SOURCE_ROOT; }; B000E7A360C0C86ADD3C911D /* BankAndPreset.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = BankAndPreset.h; path = ../../Source/BankAndPreset.h; sourceTree = SOURCE_ROOT; };
B40B7F24646CBA708718DE82 /* SoundfontSynthVoice.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SoundfontSynthVoice.h; path = ../../Source/SoundfontSynthVoice.h; sourceTree = SOURCE_ROOT; };
B5A057FEC371053E83A73E47 /* SoundfontSynthVoice.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SoundfontSynthVoice.cpp; path = ../../Source/SoundfontSynthVoice.cpp; sourceTree = SOURCE_ROOT; };
B6D37AD919F9E83688578941 /* SurjectiveMidiKeyboardComponent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SurjectiveMidiKeyboardComponent.h; path = ../../Source/SurjectiveMidiKeyboardComponent.h; sourceTree = SOURCE_ROOT; }; B6D37AD919F9E83688578941 /* SurjectiveMidiKeyboardComponent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SurjectiveMidiKeyboardComponent.h; path = ../../Source/SurjectiveMidiKeyboardComponent.h; sourceTree = SOURCE_ROOT; };
BFB39134DE6876F9005CFA61 /* Pills.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Pills.h; path = ../../Source/Pills.h; sourceTree = SOURCE_ROOT; }; BFB39134DE6876F9005CFA61 /* Pills.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Pills.h; path = ../../Source/Pills.h; sourceTree = SOURCE_ROOT; };
BFF57868318157F12F087F07 /* Info-AU.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-AU.plist"; sourceTree = SOURCE_ROOT; }; BFF57868318157F12F087F07 /* Info-AU.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-AU.plist"; sourceTree = SOURCE_ROOT; };
@ -543,10 +537,6 @@
59F9FEC807012C10B8A1FA07 /* Preset.cpp */, 59F9FEC807012C10B8A1FA07 /* Preset.cpp */,
AE397302E7E3F3A14A0C5F3C /* Preset.h */, AE397302E7E3F3A14A0C5F3C /* Preset.h */,
69DB3A0FB3D21F87D1E4B0C1 /* PresetsToBanks.h */, 69DB3A0FB3D21F87D1E4B0C1 /* PresetsToBanks.h */,
7D7B71BE20CA213D2FCD7FEE /* SoundfontSynthSound.cpp */,
76724E30D8976FC4C2EE56FF /* SoundfontSynthSound.h */,
B5A057FEC371053E83A73E47 /* SoundfontSynthVoice.cpp */,
B40B7F24646CBA708718DE82 /* SoundfontSynthVoice.h */,
4119A8200AC54674C00EFE66 /* SurjectiveMidiKeyboardComponent.cpp */, 4119A8200AC54674C00EFE66 /* SurjectiveMidiKeyboardComponent.cpp */,
B6D37AD919F9E83688578941 /* SurjectiveMidiKeyboardComponent.h */, B6D37AD919F9E83688578941 /* SurjectiveMidiKeyboardComponent.h */,
CE8C41308A31A71A1177D0D5 /* TableComponent.cpp */, CE8C41308A31A71A1177D0D5 /* TableComponent.cpp */,
@ -953,8 +943,6 @@
BFD9EF2D67067FC1E5BA3546 /* MyColours.cpp in Sources */, BFD9EF2D67067FC1E5BA3546 /* MyColours.cpp in Sources */,
8502F736BECFB9CB752AC72F /* Pills.cpp in Sources */, 8502F736BECFB9CB752AC72F /* Pills.cpp in Sources */,
DF84F5E7E386AF7A38854939 /* Preset.cpp in Sources */, DF84F5E7E386AF7A38854939 /* Preset.cpp in Sources */,
B66EBD76F6051D97D56C97AB /* SoundfontSynthSound.cpp in Sources */,
305606C42BB0F2A12D382D34 /* SoundfontSynthVoice.cpp in Sources */,
9C107CE4B586E4B097D9D04E /* SurjectiveMidiKeyboardComponent.cpp in Sources */, 9C107CE4B586E4B097D9D04E /* SurjectiveMidiKeyboardComponent.cpp in Sources */,
4AE057561AEA78489D9E50F0 /* TableComponent.cpp in Sources */, 4AE057561AEA78489D9E50F0 /* TableComponent.cpp in Sources */,
AC5E4EF988D864A298E3650D /* TablesComponent.cpp in Sources */, AC5E4EF988D864A298E3650D /* TablesComponent.cpp in Sources */,

View File

@ -675,9 +675,9 @@ void FluidSynthModel::processBlock(AudioBuffer<float>& buffer, MidiBuffer& midiM
break; break;
} }
case SOUND_CTRL10: { // MIDI CC 79 undefined case SOUND_CTRL10: { // MIDI CC 79 undefined
RangedAudioParameter *param {valueTreeState.getParameter("sustain")}; RangedAudioParameter *param{valueTreeState.getParameter("sustain")};
jassert(dynamic_cast<AudioParameterInt*>(param) != nullptr); jassert(dynamic_cast<AudioParameterInt*>(param) != nullptr);
AudioParameterInt* castParam {dynamic_cast<AudioParameterInt*> (param)}; AudioParameterInt* castParam{dynamic_cast<AudioParameterInt*>(param)};
*castParam = m.getControllerValue(); *castParam = m.getControllerValue();
break; break;
} }
@ -692,8 +692,8 @@ void FluidSynthModel::processBlock(AudioBuffer<float>& buffer, MidiBuffer& midiM
m.getProgramChangeNumber())}; m.getProgramChangeNumber())};
if (result == FLUID_OK) { if (result == FLUID_OK) {
RangedAudioParameter *param{valueTreeState.getParameter("preset")}; RangedAudioParameter *param{valueTreeState.getParameter("preset")};
jassert(dynamic_cast<AudioParameterInt*> (param) != nullptr); jassert(dynamic_cast<AudioParameterInt*>(param) != nullptr);
AudioParameterInt* castParam {dynamic_cast<AudioParameterInt*> (param)}; AudioParameterInt* castParam{dynamic_cast<AudioParameterInt*>(param)};
*castParam = m.getProgramChangeNumber(); *castParam = m.getProgramChangeNumber();
} }
} else if (m.isPitchWheel()) { } else if (m.isPitchWheel()) {
@ -740,3 +740,63 @@ void FluidSynthModel::processBlock(AudioBuffer<float>& buffer, MidiBuffer& midiM
buffer.getNumChannels(), buffer.getNumChannels(),
buffer.getArrayOfWritePointers()); buffer.getArrayOfWritePointers());
} }
int FluidSynthModel::getNumPrograms()
{
return 128; // NB: some hosts don't cope very well if you tell them there are 0 programs,
// so this should be at least 1, even if you're not really implementing programs.
}
int FluidSynthModel::getCurrentProgram()
{
RangedAudioParameter *param{valueTreeState.getParameter("preset")};
jassert(dynamic_cast<AudioParameterInt*>(param) != nullptr);
AudioParameterInt* castParam{dynamic_cast<AudioParameterInt*>(param)};
return castParam->get();
}
void FluidSynthModel::setCurrentProgram(int index)
{
RangedAudioParameter *param{valueTreeState.getParameter("preset")};
jassert(dynamic_cast<AudioParameterInt*>(param) != nullptr);
AudioParameterInt* castParam{dynamic_cast<AudioParameterInt*>(param)};
*castParam = index;
}
const String FluidSynthModel::getProgramName(int index)
{
fluid_sfont_t* sfont{
sfont_id == -1
? nullptr
: fluid_synth_get_sfont_by_id(synth.get(), sfont_id)
};
if (!sfont) {
return {};
}
int bank, presetNum;
{
RangedAudioParameter *param {valueTreeState.getParameter("bank")};
jassert(dynamic_cast<AudioParameterInt*> (param) != nullptr);
AudioParameterInt* castParam {dynamic_cast<AudioParameterInt*> (param)};
bank = castParam->get();
}
{
RangedAudioParameter *param {valueTreeState.getParameter("preset")};
jassert(dynamic_cast<AudioParameterInt*> (param) != nullptr);
AudioParameterInt* castParam {dynamic_cast<AudioParameterInt*> (param)};
presetNum = castParam->get();
}
fluid_preset_t *preset{fluid_sfont_get_preset(
sfont,
bank,
presetNum)};
if (!preset) {
return {};
}
return {fluid_preset_get_name(preset)};
}
void FluidSynthModel::changeProgramName(int index, const String& newName)
{
// no-op; we don't support modifying the soundfont, so let's not support modification of preset names.
}

View File

@ -11,10 +11,6 @@
#include "BankAndPreset.h" #include "BankAndPreset.h"
#include "PresetsToBanks.h" #include "PresetsToBanks.h"
// https://stackoverflow.com/a/13446565/5257399
//using std::shared_ptr;
using namespace std; using namespace std;
class FluidSynthModel class FluidSynthModel
@ -23,55 +19,21 @@ class FluidSynthModel
public: public:
FluidSynthModel( FluidSynthModel(
AudioProcessorValueTreeState& valueTreeState AudioProcessorValueTreeState& valueTreeState
// SharesParams& sharedParams
// ValueTree& valueTree
); );
~FluidSynthModel(); ~FluidSynthModel();
shared_ptr<fluid_synth_t> getSynth();
void initialise(); void initialise();
// BanksToPresets getBanks();
// void changePreset(int bank, int preset);
int getChannel(); int getChannel();
// void onFileNameChanged(const String &absPath, int bank, int preset);
void setControllerValue(int controller, int value); void setControllerValue(int controller, int value);
void processBlock(AudioBuffer<float>& buffer, MidiBuffer& midiMessages); void processBlock(AudioBuffer<float>& buffer, MidiBuffer& midiMessages);
//==============================================================================
/**
Used to receive callbacks when a button is clicked.
@see Button::addListener, Button::removeListener
*/
// class Listener
// {
// public:
// /** Destructor. */
// virtual ~Listener();
// /** Called when the button is clicked. */
// virtual void fontChanged (FluidSynthModel*, const String &absPath);
// };
/** Registers a listener to receive events when this button's state changes.
If the listener is already registered, this will not register it again.
@see removeListener
*/
// void addListener (Listener* newListener);
/** Removes a previously-registered button listener
@see addListener
*/
// void removeListener (Listener* listener);
void setSampleRate(float sampleRate); void setSampleRate(float sampleRate);
// const String& getCurrentSoundFontAbsPath();
//==============================================================================
virtual void parameterChanged (const String& parameterID, float newValue) override; virtual void parameterChanged (const String& parameterID, float newValue) override;
virtual void valueTreePropertyChanged (ValueTree& treeWhosePropertyHasChanged, virtual void valueTreePropertyChanged (ValueTree& treeWhosePropertyHasChanged,
@ -86,35 +48,18 @@ public:
inline virtual void valueTreeParentChanged (ValueTree& treeWhoseParentHasChanged) override {}; inline virtual void valueTreeParentChanged (ValueTree& treeWhoseParentHasChanged) override {};
inline virtual void valueTreeRedirected (ValueTree& treeWhichHasBeenChanged) override {}; inline virtual void valueTreeRedirected (ValueTree& treeWhichHasBeenChanged) override {};
private: //==============================================================================
// class ValueTreeListener: public ValueTree::Listener { int getNumPrograms();
// public: int getCurrentProgram();
//// ValueTreeListener(); void setCurrentProgram(int index);
//// ~ValueTreeListener(); const String getProgramName(int index);
// virtual void valueTreePropertyChanged (ValueTree& treeWhosePropertyHasChanged, void changeProgramName(int index, const String& newName);
// const Identifier& property) override;
// inline virtual void valueTreeChildAdded (ValueTree& parentTree,
// ValueTree& childWhichHasBeenAdded) override {};
// inline virtual void valueTreeChildRemoved (ValueTree& parentTree,
// ValueTree& childWhichHasBeenRemoved,
// int indexFromWhichChildWasRemoved) override {};
// inline virtual void valueTreeChildOrderChanged (ValueTree& parentTreeWhoseChildrenHaveMoved,
// int oldIndex, int newIndex) override {};
// inline virtual void valueTreeParentChanged (ValueTree& treeWhoseParentHasChanged) override {};
// inline virtual void valueTreeRedirected (ValueTree& treeWhichHasBeenChanged) override {};
// JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ValueTreeListener)
// };
private:
int handleMidiEvent(void* data, fluid_midi_event_t* event); int handleMidiEvent(void* data, fluid_midi_event_t* event);
void refreshBanks(); void refreshBanks();
// void refreshPresets();
// void refreshBanksAndPresets();
// ValueTreeListener valueTreeListener;
AudioProcessorValueTreeState& valueTreeState; AudioProcessorValueTreeState& valueTreeState;
// SharesParams& sharedParams;
// ValueTree& valueTree;
// https://stackoverflow.com/questions/38980315/is-stdunique-ptr-deletion-order-guaranteed // https://stackoverflow.com/questions/38980315/is-stdunique-ptr-deletion-order-guaranteed
// members are destroyed in reverse of the order they're declared // members are destroyed in reverse of the order they're declared
@ -125,8 +70,6 @@ private:
shared_ptr<fluid_synth_t> synth; shared_ptr<fluid_synth_t> synth;
// unique_ptr<fluid_midi_driver_t, decltype(&delete_fluid_midi_driver)> midiDriver; // unique_ptr<fluid_midi_driver_t, decltype(&delete_fluid_midi_driver)> midiDriver;
// String currentSoundFontAbsPath;
float currentSampleRate; float currentSampleRate;
fluid_preset_t* getFirstPreset(); fluid_preset_t* getFirstPreset();
@ -135,17 +78,11 @@ private:
void unloadAndLoadFont(const String &absPath); void unloadAndLoadFont(const String &absPath);
void loadFont(const String &absPath); void loadFont(const String &absPath);
// bool shouldLoadFont(const String &absPath);
void changePresetImpl(int bank, int preset); void changePresetImpl(int bank, int preset);
// bool initialised;
int sfont_id; int sfont_id;
unsigned int channel; unsigned int channel;
// fluid_mod_t* mod;
// ListenerList<Listener> eventListeners;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FluidSynthModel) JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FluidSynthModel)
}; };

View File

@ -10,8 +10,6 @@
#include "PluginProcessor.h" #include "PluginProcessor.h"
#include "PluginEditor.h" #include "PluginEditor.h"
#include "SoundfontSynthVoice.h"
#include "SoundfontSynthSound.h"
#include "ExposesComponents.h" #include "ExposesComponents.h"
#include "MidiConstants.h" #include "MidiConstants.h"
#include "Util.h" #include "Util.h"
@ -26,18 +24,14 @@ AudioProcessor* JUCE_CALLTYPE createPluginFilter();
//============================================================================== //==============================================================================
//, sharedParams{static_pointer_cast<SharesParams>(make_shared<Params>())}
JuicySFAudioProcessor::JuicySFAudioProcessor() JuicySFAudioProcessor::JuicySFAudioProcessor()
: AudioProcessor{getBusesProperties()} : AudioProcessor{getBusesProperties()}
// , sharedParams{}
, valueTreeState{ , valueTreeState{
*this, *this,
nullptr, nullptr,
"MYPLUGINSETTINGS", "MYPLUGINSETTINGS",
createParameterLayout()} createParameterLayout()}
, fluidSynthModel{valueTreeState} , fluidSynthModel{valueTreeState}
//, fluidSynthModel{*this}
//, pluginEditor(nullptr)
{ {
valueTreeState.state.appendChild({ "uiState", { valueTreeState.state.appendChild({ "uiState", {
{ "width", GuiConstants::minWidth }, { "width", GuiConstants::minWidth },
@ -47,32 +41,14 @@ JuicySFAudioProcessor::JuicySFAudioProcessor()
{ "path", "" }, { "path", "" },
}, {} }, nullptr); }, {} }, nullptr);
// no properties, no subtrees (yet) // no properties, no subtrees (yet)
// valueTreeState.state.appendChild({ "presets", {}, {} }, nullptr);
// no properties, no subtrees (yet)
valueTreeState.state.appendChild({ "banks", {}, {} }, nullptr); valueTreeState.state.appendChild({ "banks", {}, {} }, nullptr);
// valueTreeState.state.setProperty("soundFontPath", "", nullptr);
// valueTreeState.state.appendChild({ "soundFontPath", {} }, nullptr);
initialiseSynth(); initialiseSynth();
} }
AudioProcessorValueTreeState::ParameterLayout JuicySFAudioProcessor::createParameterLayout() { AudioProcessorValueTreeState::ParameterLayout JuicySFAudioProcessor::createParameterLayout() {
// std::vector<std::unique_ptr<AudioParameterInt>> params;
// for (int i = 1; i < 9; ++i)
// 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>("uiWidthPersist", "width of this plugin's GUI. Editor listens for changes (e.g. on load)", GuiConstants::minWidth, GuiConstants::maxWidth, GuiConstants::minWidth, "UI Width Persist" ),
// make_unique<AudioParameterInt>("uiHeightPersist", "height of this plugin's GUI. Editor listens for changes (e.g. on load)", GuiConstants::minHeight, GuiConstants::maxHeight, GuiConstants::minHeight, "UI Height Persist" ),
// make_unique<AudioParameterInt>("uiWidthTemp", "width of this plugin's GUI. Editor writes here on change (e.g. on window resize). Processor copies this into Persist before any save.", GuiConstants::minWidth, GuiConstants::maxWidth, GuiConstants::minWidth, "UI Width Temp" ),
// make_unique<AudioParameterInt>("uiHeightTemp", "height of this plugin's GUI. Editor writes here on change (e.g. on window resize). Processor copies this into Persist before any save.", GuiConstants::minHeight, GuiConstants::maxHeight, GuiConstants::minHeight, "UI Height Temp" ),
// make_unique<AudioParameterInt>("uiWidth", "width of this plugin's GUI", GuiConstants::minWidth, GuiConstants::maxWidth, GuiConstants::minWidth, "UI Width" ),
// make_unique<AudioParameterInt>("uiHeight", "height of this plugin's GUI", GuiConstants::minHeight, GuiConstants::maxHeight, GuiConstants::minHeight, "UI Height" ),
// SoundFont 2.4 spec section 7.2: zero through 127, or 128. // SoundFont 2.4 spec section 7.2: zero through 127, or 128.
make_unique<AudioParameterInt>("bank", "which bank is selected in the soundfont", MidiConstants::midiMinValue, 128, MidiConstants::midiMinValue, "Bank" ), make_unique<AudioParameterInt>("bank", "which bank is selected in the soundfont", MidiConstants::midiMinValue, 128, MidiConstants::midiMinValue, "Bank" ),
// note: banks may be sparse, and lack a 0th preset. so defend against this. // note: banks may be sparse, and lack a 0th preset. so defend against this.
@ -93,22 +69,10 @@ AudioProcessorValueTreeState::ParameterLayout JuicySFAudioProcessor::createParam
JuicySFAudioProcessor::~JuicySFAudioProcessor() JuicySFAudioProcessor::~JuicySFAudioProcessor()
{ {
// delete fluidSynthModel;
} }
void JuicySFAudioProcessor::initialiseSynth() { void JuicySFAudioProcessor::initialiseSynth() {
fluidSynthModel.initialise(); fluidSynthModel.initialise();
// fluidSynth = fluidSynthModel.getSynth();
// const int numVoices = 8;
// Add some voices...
// for (int i = numVoices; --i >= 0;)
// synth.addVoice(new SoundfontSynthVoice(fluidSynthModel.getSynth()));
// ..and give the synth a sound to play
// synth.addSound(new SoundfontSynthSound());
} }
//============================================================================== //==============================================================================
@ -142,22 +106,23 @@ double JuicySFAudioProcessor::getTailLengthSeconds() const
int JuicySFAudioProcessor::getNumPrograms() int JuicySFAudioProcessor::getNumPrograms()
{ {
return 1; // NB: some hosts don't cope very well if you tell them there are 0 programs, return fluidSynthModel.getNumPrograms(); // NB: some hosts don't cope very well if you tell them there are 0 programs,
// so this should be at least 1, even if you're not really implementing programs. // so this should be at least 1, even if you're not really implementing programs.
} }
int JuicySFAudioProcessor::getCurrentProgram() int JuicySFAudioProcessor::getCurrentProgram()
{ {
return 0; return fluidSynthModel.getCurrentProgram();
} }
void JuicySFAudioProcessor::setCurrentProgram (int index) void JuicySFAudioProcessor::setCurrentProgram(int index)
{ {
fluidSynthModel.setCurrentProgram(index);
} }
const String JuicySFAudioProcessor::getProgramName (int index) const String JuicySFAudioProcessor::getProgramName(int index)
{ {
return {}; return fluidSynthModel.getProgramName(index);
} }
void JuicySFAudioProcessor::changeProgramName (int index, const String& newName) void JuicySFAudioProcessor::changeProgramName (int index, const String& newName)
@ -208,11 +173,10 @@ AudioProcessor::BusesProperties JuicySFAudioProcessor::getBusesProperties() {
void JuicySFAudioProcessor::processBlock(AudioBuffer<float>& buffer, MidiBuffer& midiMessages) { void JuicySFAudioProcessor::processBlock(AudioBuffer<float>& buffer, MidiBuffer& midiMessages) {
jassert (!isUsingDoublePrecision()); jassert (!isUsingDoublePrecision());
const int numSamples{buffer.getNumSamples()};
// Now pass any incoming midi messages to our keyboard state object, and let it // Now pass any incoming midi messages to our keyboard state object, and let it
// add messages to the buffer if the user is clicking on the on-screen keys // add messages to the buffer if the user is clicking on the on-screen keys
keyboardState.processNextMidiBuffer(midiMessages, 0, numSamples, true); keyboardState.processNextMidiBuffer(midiMessages, 0, buffer.getNumSamples(), true);
fluidSynthModel.processBlock(buffer, midiMessages); fluidSynthModel.processBlock(buffer, midiMessages);
@ -418,14 +382,6 @@ void JuicySFAudioProcessor::setStateInformation (const void* data, int sizeInByt
} }
} }
//void JuicySFAudioProcessor::subscribeToStateChanges(StateChangeSubscriber* subscriber) {
// stateChangeSubscribers.push_back(subscriber);
//}
//
//void JuicySFAudioProcessor::unsubscribeFromStateChanges(StateChangeSubscriber* subscriber) {
// stateChangeSubscribers.remove(subscriber);
//}
// FluidSynth only supports float in its process function, so that's all we can support. // FluidSynth only supports float in its process function, so that's all we can support.
bool JuicySFAudioProcessor::supportsDoublePrecisionProcessing() const { bool JuicySFAudioProcessor::supportsDoublePrecisionProcessing() const {
return false; return false;
@ -435,10 +391,6 @@ FluidSynthModel& JuicySFAudioProcessor::getFluidSynthModel() {
return fluidSynthModel; return fluidSynthModel;
} }
//SharesParams& JuicySFAudioProcessor::getSharedParams() {
// return sharedParams;
//}
//============================================================================== //==============================================================================
// This creates new instances of the plugin.. // This creates new instances of the plugin..
AudioProcessor* JUCE_CALLTYPE createPluginFilter() AudioProcessor* JUCE_CALLTYPE createPluginFilter()

View File

@ -64,34 +64,21 @@ public:
bool supportsDoublePrecisionProcessing() const override; bool supportsDoublePrecisionProcessing() const override;
FluidSynthModel& getFluidSynthModel(); FluidSynthModel& getFluidSynthModel();
// SharesParams& getSharedParams();
MidiKeyboardState keyboardState; MidiKeyboardState keyboardState;
// void subscribeToStateChanges(StateChangeSubscriber* subscriber);
// void unsubscribeFromStateChanges(StateChangeSubscriber* subscriber);
private: private:
void initialiseSynth(); void initialiseSynth();
// Params sharedParams;
AudioProcessorValueTreeState valueTreeState; AudioProcessorValueTreeState valueTreeState;
// ValueTree valueTree;
FluidSynthModel fluidSynthModel; FluidSynthModel fluidSynthModel;
// fluid_synth_t* fluidSynth;
Synthesiser synth; Synthesiser synth;
// // just a raw pointer; we do not own
// AudioProcessorEditor* pluginEditor;
// list<StateChangeSubscriber*> stateChangeSubscribers;
AudioProcessorValueTreeState::ParameterLayout createParameterLayout(); AudioProcessorValueTreeState::ParameterLayout createParameterLayout();
static BusesProperties getBusesProperties(); static BusesProperties getBusesProperties();
// Model* model;
//============================================================================== //==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JuicySFAudioProcessor) JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JuicySFAudioProcessor)
}; };

View File

@ -1,13 +0,0 @@
//
// Created by Alex Birch on 07/09/2017.
//
#include "SoundfontSynthSound.h"
bool SoundfontSynthSound::appliesToChannel(int) {
return true;
}
bool SoundfontSynthSound::appliesToNote(int) {
return true;
}

View File

@ -1,13 +0,0 @@
//
// Created by Alex Birch on 07/09/2017.
//
#pragma once
#include "../JuceLibraryCode/JuceHeader.h"
class SoundfontSynthSound : public SynthesiserSound {
public:
bool appliesToNote (int /*midiNoteNumber*/) override;
bool appliesToChannel (int /*midiChannel*/) override;
};

View File

@ -1,111 +0,0 @@
//
// Created by Alex Birch on 07/09/2017.
//
#include "SoundfontSynthVoice.h"
#include "SoundfontSynthSound.h"
#include "Util.h"
using namespace std;
SoundfontSynthVoice::SoundfontSynthVoice(shared_ptr<fluid_synth_t> synth)
: tailOff(0.0)
, level(0.0)
, currentAngle(0.0)
, angleDelta(0.0)
, midiNoteNumber(0)
, synth(synth)
{
}
bool SoundfontSynthVoice::canPlaySound(SynthesiserSound* sound) {
return dynamic_cast<SoundfontSynthSound*> (sound) != nullptr;
}
void SoundfontSynthVoice::startNote(
int midiNoteNumber,
float velocity,
SynthesiserSound* sound,
int /*currentPitchWheelPosition*/) {
this->midiNoteNumber = midiNoteNumber;
DEBUG_PRINT ( juce::String::formatted("JUCE noteon: %d, %d\n", midiNoteNumber, velocity) );
fluid_synth_noteon(synth.get(), 0, midiNoteNumber, static_cast<int>(velocity * 127));
// currentAngle = 0.0;
// level = velocity * 0.15;
// tailOff = 0.0;
//
// double cyclesPerSecond = MidiMessage::getMidiNoteInHertz (midiNoteNumber);
// double cyclesPerSample = cyclesPerSecond / getSampleRate();
//
// angleDelta = cyclesPerSample * 2.0 * double_Pi;
// jassert(dynamic_cast<SoundfontSynthSound*> (sound) != nullptr);
// SoundfontSynthSound* sfsynth = dynamic_cast<SoundfontSynthSound*> (sound);
}
void SoundfontSynthVoice::stopNote (float /*velocity*/, bool allowTailOff) {
// if (allowTailOff) {
// // start a tail-off by setting this flag. The render callback will pick up on
// // this and do a fade out, calling clearCurrentNote() when it's finished.
//
// // we only need to begin a tail-off if it's not already doing so - the
// if (tailOff == 0.0) {
// // stopNote method could be called more than once.
// tailOff = 1.0;
// }
// } else {
// // we're being told to stop playing immediately, so reset everything..
//
// clearCurrentNote();
// angleDelta = 0.0;
// }
DEBUG_PRINT ( juce::String("JUCE noteoff\n") );
clearCurrentNote();
fluid_synth_noteoff(synth.get(), 0, this->midiNoteNumber);
}
// receives input as MIDI 0 to 16383, with 8192 being center
// this is also exactly the input fluidsynth requires
void SoundfontSynthVoice::pitchWheelMoved (int newValue) {
// fluid_synth_pitch_bend(synth, 0, newValue);
// int ppitch_bend;
// fluid_synth_get_pitch_bend(synth, 0, &ppitch_bend);
// int ppitch_bend_sens;
// fluid_synth_get_pitch_wheel_sens(synth, 0, &ppitch_bend_sens);
// Logger::outputDebugString ( juce::String::formatted("Pitch wheel: %d %d %d\n", newValue, ppitch_bend, ppitch_bend_sens) );
}
void SoundfontSynthVoice::controllerMoved (int controllerNumber, int newValue) {
// this seems to be "program change" event
DEBUG_PRINT ( juce::String::formatted("Controller moved: %d, %d\n", controllerNumber, newValue) );
}
void SoundfontSynthVoice::renderNextBlock (AudioBuffer<float>& outputBuffer, int startSample, int numSamples) {
//fluid_synth_process(synth.get(), numSamples, 1, nullptr, outputBuffer.getNumChannels(), outputBuffer.getArrayOfWritePointers());
}
//void SoundfontSynthVoice::renderBlock (AudioBuffer<float>& outputBuffer, int startSample, int numSamples) {
// fluid_synth_process(synth.get(), numSamples, 1, nullptr, outputBuffer.getNumChannels(), outputBuffer.getArrayOfWritePointers());
// if (angleDelta == 0.0) {
// return;
// }
// while (--numSamples >= 0) {
// double qualifiedTailOff = tailOff > 0 ? tailOff : 1.0;
// auto currentSample = static_cast<FloatType> (std::sin (currentAngle) * level * qualifiedTailOff);
// for (int i = outputBuffer.getNumChannels(); --i >= 0;)
// outputBuffer.addSample (i, startSample, currentSample);
//
// currentAngle += angleDelta;
// ++startSample;
//
// if (tailOff > 0) {
// tailOff *= 0.99;
//
// if (tailOff <= 0.005) {
// clearCurrentNote();
// angleDelta = 0.0;
// break;
// }
// }
// }
//}

View File

@ -1,39 +0,0 @@
//
// Created by Alex Birch on 07/09/2017.
//
#pragma once
#include<memory>
#include<fluidsynth.h>
#include "../JuceLibraryCode/JuceHeader.h"
using namespace std;
class SoundfontSynthVoice : public SynthesiserVoice {
public:
SoundfontSynthVoice(shared_ptr<fluid_synth_t> synth);
bool canPlaySound (SynthesiserSound* sound) override;
void startNote (
int midiNoteNumber,
float velocity,
SynthesiserSound* /*sound*/,
int /*currentPitchWheelPosition*/) override;
void stopNote (float /*velocity*/, bool allowTailOff) override;
void pitchWheelMoved (int /*newValue*/) override;
void controllerMoved (int /*controllerNumber*/, int /*newValue*/) override;
void renderNextBlock (AudioBuffer<float>& outputBuffer, int startSample, int numSamples) override;
private:
double tailOff;
double level;
double currentAngle;
double angleDelta;
int midiNoteNumber;
shared_ptr<fluid_synth_t> synth;
};