diff --git a/Builds/MacOSX/juicysfplugin.xcodeproj/project.pbxproj b/Builds/MacOSX/juicysfplugin.xcodeproj/project.pbxproj index fa94fdd..bc59573 100644 --- a/Builds/MacOSX/juicysfplugin.xcodeproj/project.pbxproj +++ b/Builds/MacOSX/juicysfplugin.xcodeproj/project.pbxproj @@ -107,6 +107,7 @@ 358E45F122BEE5CE0087ED8D /* libgthread-2.0.0.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = 358E45BB22BEE53A0087ED8D /* libgthread-2.0.0.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; 358E45F222BEE5CE0087ED8D /* libFLAC.8.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = 358E45BC22BEE53A0087ED8D /* libFLAC.8.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; 358E45F322BEE5CE0087ED8D /* libogg.0.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = 358E45BD22BEE53A0087ED8D /* libogg.0.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; + 358E45FB22C80DCA0087ED8D /* SlidersComponent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 358E45F922C80DCA0087ED8D /* SlidersComponent.cpp */; }; 3793A7D5AC25576FAC8583E6 /* include_juce_graphics.mm in Sources */ = {isa = PBXBuildFile; fileRef = A6BC2528C1717DDC2B66215E /* include_juce_graphics.mm */; }; 42542EDC02B3DE845BCC21FE /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C1616112041466F7324D7E19 /* Accelerate.framework */; }; 458D25AB7460484F90B37A2F /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3C1910B48593DA5FACC7E122 /* IOKit.framework */; }; @@ -295,6 +296,8 @@ 358E45BC22BEE53A0087ED8D /* libFLAC.8.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libFLAC.8.dylib; sourceTree = ""; }; 358E45BD22BEE53A0087ED8D /* libogg.0.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libogg.0.dylib; sourceTree = ""; }; 358E45F422BFC00C0087ED8D /* MidiConstants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MidiConstants.h; path = ../../Source/MidiConstants.h; sourceTree = ""; }; + 358E45F922C80DCA0087ED8D /* SlidersComponent.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SlidersComponent.cpp; path = ../../Source/SlidersComponent.cpp; sourceTree = ""; }; + 358E45FA22C80DCA0087ED8D /* SlidersComponent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SlidersComponent.h; path = ../../Source/SlidersComponent.h; sourceTree = ""; }; 35D551D55292C9D0508A408A /* PluginEditor.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = PluginEditor.cpp; path = ../../Source/PluginEditor.cpp; sourceTree = SOURCE_ROOT; }; 373EF982A53046CE00BECE68 /* include_juce_events.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = include_juce_events.mm; path = ../../JuceLibraryCode/include_juce_events.mm; sourceTree = SOURCE_ROOT; }; 3909EE4609ED2DCCC6B6B290 /* juce_data_structures */ = {isa = PBXFileReference; lastKnownFileType = folder; name = juce_data_structures; path = /Applications/JUCE/modules/juce_data_structures; sourceTree = ""; }; @@ -547,6 +550,8 @@ 35D551D55292C9D0508A408A /* PluginEditor.cpp */, 8990F3EAFFBBD6A42247C663 /* PluginEditor.h */, 358E45F422BFC00C0087ED8D /* MidiConstants.h */, + 358E45F922C80DCA0087ED8D /* SlidersComponent.cpp */, + 358E45FA22C80DCA0087ED8D /* SlidersComponent.h */, ); name = Source; sourceTree = ""; @@ -945,6 +950,7 @@ E08B3A2AF85F9FCF991F1CA2 /* include_juce_audio_basics.mm in Sources */, C4D76C968347E2ACBAB5B6E7 /* include_juce_audio_devices.mm in Sources */, 51C9DBCA840E334DB1804133 /* include_juce_audio_formats.mm in Sources */, + 358E45FB22C80DCA0087ED8D /* SlidersComponent.cpp in Sources */, 5E5B833BBDD65F0D4271CA52 /* include_juce_audio_plugin_client_utils.cpp in Sources */, C59AF9E198C59F67039F12BB /* include_juce_audio_plugin_client_VST_utils.mm in Sources */, 5BEE82A710A5F9566FCF4FDA /* include_juce_audio_processors.mm in Sources */, diff --git a/Source/FluidSynthModel.cpp b/Source/FluidSynthModel.cpp index 594c3ef..7d3b309 100644 --- a/Source/FluidSynthModel.cpp +++ b/Source/FluidSynthModel.cpp @@ -55,6 +55,11 @@ void FluidSynthModel::initialise() { } fluid_synth_set_gain(synth, 2.0); + + for(int i{SOUND_CTRL1}; i <= SOUND_CTRL10; i++) + { + setControllerValue(i, 0); + } // fluid_synth_bank_select(synth, 0, 3); @@ -68,9 +73,14 @@ void FluidSynthModel::initialise() { // http://www.synthfont.com/SoundFont_NRPNs.PDF float env_amount(20000.0f); +// float env_amount(24000.0f); + + // note: fluid_chan.c#fluid_channel_init_ctrl() + // all SOUND_CTRL are inited with value of 64, not zero. + // "Just like panning, a value of 64 indicates no change for sound ctrls" fluid_mod_t *mod(new_fluid_mod()); - +// fluid_mod_set_source1(mod, static_cast(SOUND_CTRL2), // MIDI CC 71 Timbre/Harmonic Intensity (filter resonance) FLUID_MOD_CC @@ -92,6 +102,7 @@ void FluidSynthModel::initialise() { | FLUID_MOD_POSITIVE); fluid_mod_set_source2(mod, 0, 0); fluid_mod_set_dest(mod, GEN_VOLENVRELEASE); +// fluid_mod_set_amount(mod, 15200.0f); fluid_mod_set_amount(mod, env_amount); fluid_synth_add_default_mod(synth, mod, FLUID_SYNTH_ADD); delete_fluid_mod(mod); @@ -109,6 +120,7 @@ void FluidSynthModel::initialise() { fluid_synth_add_default_mod(synth, mod, FLUID_SYNTH_ADD); delete_fluid_mod(mod); + // soundfont spec says that if cutoff is >20kHz and resonance Q is 0, then no filtering occurs mod = new_fluid_mod(); fluid_mod_set_source1(mod, static_cast(SOUND_CTRL5), // MIDI CC 74 Brightness (cutoff frequency, FILTERFC) @@ -134,10 +146,36 @@ void FluidSynthModel::initialise() { fluid_mod_set_amount(mod, env_amount); fluid_synth_add_default_mod(synth, mod, FLUID_SYNTH_ADD); delete_fluid_mod(mod); + + mod = new_fluid_mod(); + fluid_mod_set_source1(mod, + static_cast(SOUND_CTRL10), // MIDI CC 79 undefined + FLUID_MOD_CC + | FLUID_MOD_UNIPOLAR + | FLUID_MOD_CONCAVE + | FLUID_MOD_POSITIVE); + fluid_mod_set_source2(mod, 0, 0); + fluid_mod_set_dest(mod, GEN_VOLENVSUSTAIN); + // fluice_voice.c#fluid_voice_update_param() + // clamps the range to between 0 and 1000, so we'll copy that + fluid_mod_set_amount(mod, 1000.0f); + fluid_synth_add_default_mod(synth, mod, FLUID_SYNTH_ADD); + delete_fluid_mod(mod); initialised = true; } +void FluidSynthModel::setControllerValue(int controller, int value) { + fluid_midi_event_t *midi_event(new_fluid_midi_event()); + fluid_midi_event_set_type(midi_event, static_cast(CONTROL_CHANGE)); + fluid_midi_event_set_channel(midi_event, channel); + fluid_midi_event_set_control(midi_event, controller); + fluid_midi_event_set_value(midi_event, value); + fluid_synth_handle_midi_event(synth, midi_event); + delete_fluid_midi_event(midi_event); + // fluid_channel_set_cc(channel, i, 0); +} + int FluidSynthModel::getChannel() { return channel; } diff --git a/Source/FluidSynthModel.h b/Source/FluidSynthModel.h index 11e7a49..a630cdf 100644 --- a/Source/FluidSynthModel.h +++ b/Source/FluidSynthModel.h @@ -31,6 +31,7 @@ public: int getChannel(); void onFileNameChanged(const String &absPath, int bank, int preset); + void setControllerValue(int controller, int value); //============================================================================== /** diff --git a/Source/MidiConstants.h b/Source/MidiConstants.h index a5fef83..f31a69a 100644 --- a/Source/MidiConstants.h +++ b/Source/MidiConstants.h @@ -97,15 +97,15 @@ enum fluid_midi_control_change LEGATO_SWITCH = 0x44, HOLD2_SWITCH = 0x45, SOUND_CTRL1 = 0x46, - SOUND_CTRL2 = 0x47, - SOUND_CTRL3 = 0x48, - SOUND_CTRL4 = 0x49, - SOUND_CTRL5 = 0x4A, - SOUND_CTRL6 = 0x4B, + SOUND_CTRL2 = 0x47, // MIDI CC 71 Timbre/Harmonic Intensity (filter resonance) + SOUND_CTRL3 = 0x48, // MIDI CC 72 Release time + SOUND_CTRL4 = 0x49, // MIDI CC 73 Attack time + SOUND_CTRL5 = 0x4A, // MIDI CC 74 Brightness (cutoff frequency, FILTERFC) + SOUND_CTRL6 = 0x4B, // MIDI CC 75 Decay Time SOUND_CTRL7 = 0x4C, SOUND_CTRL8 = 0x4D, SOUND_CTRL9 = 0x4E, - SOUND_CTRL10 = 0x4F, + SOUND_CTRL10 = 0x4F, // MIDI CC 79 undefined GPC5 = 0x50, GPC6 = 0x51, GPC7 = 0x52, diff --git a/Source/PluginEditor.cpp b/Source/PluginEditor.cpp index 7136e11..8edc3c4 100644 --- a/Source/PluginEditor.cpp +++ b/Source/PluginEditor.cpp @@ -17,10 +17,11 @@ JuicySFAudioProcessorEditor::JuicySFAudioProcessorEditor (JuicySFAudioProcessor& processor (p), midiKeyboard (p.keyboardState, SurjectiveMidiKeyboardComponent::horizontalKeyboard), tablesComponent(p.getFluidSynthModel()), - filePicker(p.getFluidSynthModel()) + filePicker(p.getFluidSynthModel()), + slidersComponent{p.getFluidSynthModel()} { // set resize limits for this plug-in - setResizeLimits (400, 300, 800, 600); + setResizeLimits (500, 300, 1900, 1000); setSize (p.lastUIWidth, p.lastUIHeight); @@ -34,8 +35,10 @@ JuicySFAudioProcessorEditor::JuicySFAudioProcessorEditor (JuicySFAudioProcessor& setWantsKeyboardFocus(true); addAndMakeVisible (midiKeyboard); + addAndMakeVisible(slidersComponent); addAndMakeVisible(tablesComponent); addAndMakeVisible(filePicker); + } JuicySFAudioProcessorEditor::~JuicySFAudioProcessorEditor() @@ -77,13 +80,23 @@ void JuicySFAudioProcessorEditor::paint (Graphics& g) void JuicySFAudioProcessorEditor::resized() { - const int padding = 8; - const int pianoHeight = 70; - const int filePickerHeight = 25; - Rectangle r (getLocalBounds()); + const int padding{8}; + const int pianoHeight{70}; + const int filePickerHeight{25}; + // const int slidersHeight{150}; + Rectangle r{getLocalBounds()}; filePicker.setBounds(r.removeFromTop(filePickerHeight + padding).reduced(padding, 0).withTrimmedTop(padding)); + + // Rectangle r2 (getLocalBounds()); + // slidersComponent.setBounds(r2.removeFromLeft(filePickerWidth + padding).reduced(padding, 0).withTrimmedLeft(padding)); + midiKeyboard.setBounds (r.removeFromBottom (pianoHeight).reduced(padding, 0)); - tablesComponent.setBounds(r.reduced(0, padding)); + + Rectangle rContent{r.reduced(0, padding)}; + slidersComponent.setBounds(rContent.removeFromRight(slidersComponent.getDesiredWidth() + padding).withTrimmedRight(padding)); + + tablesComponent.setBounds(rContent); + processor.lastUIWidth = getWidth(); processor.lastUIHeight = getHeight(); diff --git a/Source/PluginEditor.h b/Source/PluginEditor.h index 217516b..d0da863 100644 --- a/Source/PluginEditor.h +++ b/Source/PluginEditor.h @@ -18,6 +18,7 @@ #include "ExposesComponents.h" #include "FilePicker.h" #include "StateChangeSubscriber.h" +#include "SlidersComponent.h" //============================================================================== /** @@ -50,6 +51,7 @@ private: SurjectiveMidiKeyboardComponent midiKeyboard; TablesComponent tablesComponent; FilePicker filePicker; + SlidersComponent slidersComponent; bool focusInitialized; diff --git a/Source/PluginProcessor.cpp b/Source/PluginProcessor.cpp index d3c12b6..4777597 100644 --- a/Source/PluginProcessor.cpp +++ b/Source/PluginProcessor.cpp @@ -211,6 +211,14 @@ void JuicySFAudioProcessor::processBlock (AudioBuffer& buffer, MidiBuffer delete_fluid_midi_event(midi_event); } } + +// int pval; + // 73: 64 attack + // 75: decay + // 79: sustain + // 72: 64 release +// fluid_synth_get_cc(fluidSynth, 0, 73, &pval); +// Logger::outputDebugString ( juce::String::formatted("hey: %d\n", pval) ); // and now get our synth to process these midi events and generate its output. synth.renderNextBlock (buffer, midiMessages, 0, numSamples); diff --git a/Source/SlidersComponent.cpp b/Source/SlidersComponent.cpp new file mode 100644 index 0000000..4d008d5 --- /dev/null +++ b/Source/SlidersComponent.cpp @@ -0,0 +1,141 @@ +// +// SlidersComponent.cpp +// juicysfplugin - Shared Code +// +// Created by Alex Birch on 29/06/2019. +// Copyright © 2019 Birchlabs. All rights reserved. +// + +#include "SlidersComponent.h" +#include "FluidSynthModel.h" +#include "MidiConstants.h" + +std::function SlidersComponent::makeSliderListener(Slider& slider, int controller) { + return [this, controller, &slider]{ +// slider.setValue(slider.getValue(), NotificationType::dontSendNotification); + fluidSynthModel->setControllerValue(controller, slider.getValue()); + }; +} + +SlidersComponent::~SlidersComponent() +{ +} + +const int SlidersComponent::getDesiredWidth() { + const int envelopeSliders{4}; + const int filterSliders{2}; + const int groupXMargin{8}; + const int groupXPadding{8}; + const int sliderXMargin{3}; + const int sliderWidth{30}; + + return envelopeSliders * sliderWidth + (envelopeSliders-1) * sliderXMargin + 2 * groupXPadding + + filterSliders * sliderWidth + (filterSliders-1) * sliderXMargin + 2 * groupXPadding + groupXMargin; +} + +void SlidersComponent::resized() { + const int envelopeSliders{4}; + const int filterSliders{2}; + const int groupXMargin{8}; + const int groupXPadding{8}; + const int groupYPadding{9}; + const int sliderXMargin{3}; + const int labelHeight{25}; + const int sliderWidth{30}; + Rectangle r{getLocalBounds()}; + Rectangle rEnvelope{r.removeFromLeft(envelopeSliders * sliderWidth + (envelopeSliders-1) * sliderXMargin + 2 * groupXPadding)}; + Rectangle rFilter{r.removeFromLeft(filterSliders * sliderWidth + (filterSliders-1) * sliderXMargin + 2 * groupXPadding + groupXMargin).withTrimmedLeft(groupXMargin)}; + envelopeGroup.setBounds(rEnvelope); + filterGroup.setBounds(rFilter); + + rEnvelope.reduce(groupXPadding, groupYPadding); + rFilter.reduce(groupXPadding, groupYPadding); + attackSlider.setBounds(rEnvelope.removeFromLeft(sliderWidth).withTrimmedTop(labelHeight)); + decaySlider.setBounds(rEnvelope.removeFromLeft(sliderWidth + sliderXMargin).withTrimmedTop(labelHeight).withTrimmedLeft(sliderXMargin)); + sustainSlider.setBounds(rEnvelope.removeFromLeft(sliderWidth + sliderXMargin).withTrimmedTop(labelHeight).withTrimmedLeft(sliderXMargin)); + releaseSlider.setBounds(rEnvelope.removeFromLeft(sliderWidth + sliderXMargin).withTrimmedTop(labelHeight).withTrimmedLeft(sliderXMargin)); + filterCutOffSlider.setBounds(rFilter.removeFromLeft(sliderWidth).withTrimmedTop(labelHeight)); + filterResonanceSlider.setBounds(rFilter.removeFromLeft(sliderWidth + sliderXMargin).withTrimmedTop(labelHeight).withTrimmedLeft(sliderXMargin)); +} + +SlidersComponent::SlidersComponent(FluidSynthModel* fluidSynthModel) : +fluidSynthModel{fluidSynthModel}, +envelopeGroup{"envelopeGroup", "Envelope"}, +filterGroup{"filterGroup", "Filter"} +{ + const Slider::SliderStyle style{Slider::SliderStyle::LinearVertical}; + const double rangeMin(0); + const double rangeMax(127); + const double rangeStep(1); + + attackSlider.setSliderStyle(style); + attackSlider.setRange(rangeMin, rangeMax, rangeStep); + attackSlider.onValueChange = makeSliderListener(attackSlider, static_cast(SOUND_CTRL4)); + attackSlider.setTextBoxStyle(Slider::TextBoxBelow, true, attackSlider.getTextBoxWidth(), attackSlider.getTextBoxHeight()); + + decaySlider.setSliderStyle(style); + decaySlider.setRange(rangeMin, rangeMax, rangeStep); + decaySlider.onValueChange = makeSliderListener(decaySlider, static_cast(SOUND_CTRL6)); + decaySlider.setTextBoxStyle(Slider::TextBoxBelow, true, decaySlider.getTextBoxWidth(), decaySlider.getTextBoxHeight()); + + sustainSlider.setSliderStyle(style); + sustainSlider.setRange(rangeMin, rangeMax, rangeStep); + sustainSlider.onValueChange = makeSliderListener(sustainSlider, static_cast(SOUND_CTRL10)); + sustainSlider.setTextBoxStyle(Slider::TextBoxBelow, true, sustainSlider.getTextBoxWidth(), sustainSlider.getTextBoxHeight()); + + releaseSlider.setSliderStyle(style); + releaseSlider.setRange(rangeMin, rangeMax, rangeStep); + releaseSlider.onValueChange = makeSliderListener(releaseSlider, static_cast(SOUND_CTRL3)); + releaseSlider.setTextBoxStyle(Slider::TextBoxBelow, true, releaseSlider.getTextBoxWidth(), releaseSlider.getTextBoxHeight()); + + filterCutOffSlider.setSliderStyle(style); + filterCutOffSlider.setRange(rangeMin, rangeMax, rangeStep); + filterCutOffSlider.onValueChange = makeSliderListener(filterCutOffSlider, static_cast(SOUND_CTRL5)); + filterCutOffSlider.setTextBoxStyle(Slider::TextBoxBelow, true, filterCutOffSlider.getTextBoxWidth(), filterCutOffSlider.getTextBoxHeight()); + + filterResonanceSlider.setSliderStyle(style); + filterResonanceSlider.setRange(rangeMin, rangeMax, rangeStep); + filterResonanceSlider.onValueChange = makeSliderListener(filterResonanceSlider, static_cast(SOUND_CTRL2)); + filterResonanceSlider.setTextBoxStyle(Slider::TextBoxBelow, true, filterResonanceSlider.getTextBoxWidth(), filterResonanceSlider.getTextBoxHeight()); + + addAndMakeVisible(attackSlider); + addAndMakeVisible(decaySlider); + addAndMakeVisible(sustainSlider); + addAndMakeVisible(releaseSlider); + addAndMakeVisible(filterCutOffSlider); + addAndMakeVisible(filterResonanceSlider); + + attackLabel.setText("A", NotificationType::dontSendNotification); + attackLabel.setJustificationType(Justification::centredBottom); + attackLabel.attachToComponent(&attackSlider, false); + + decayLabel.setText("D", NotificationType::dontSendNotification); + decayLabel.setJustificationType(Justification::centredBottom); + decayLabel.attachToComponent(&decaySlider, false); + + sustainLabel.setText("S", NotificationType::dontSendNotification); + sustainLabel.setJustificationType(Justification::centredBottom); + sustainLabel.attachToComponent(&sustainSlider, false); + + releaseLabel.setText("R", NotificationType::dontSendNotification); + releaseLabel.setJustificationType(Justification::centredBottom); + releaseLabel.attachToComponent(&releaseSlider, false); + + filterCutOffLabel.setText("Cut", NotificationType::dontSendNotification); + filterCutOffLabel.setJustificationType(Justification::centredBottom); + filterCutOffLabel.attachToComponent(&filterCutOffSlider, false); + + filterResonanceLabel.setText("Res", NotificationType::dontSendNotification); + filterResonanceLabel.setJustificationType(Justification::centredBottom); + filterResonanceLabel.attachToComponent(&filterResonanceSlider, false); + + addAndMakeVisible(attackLabel); + addAndMakeVisible(decayLabel); + addAndMakeVisible(sustainLabel); + addAndMakeVisible(releaseLabel); + addAndMakeVisible(filterCutOffLabel); + addAndMakeVisible(filterResonanceLabel); + + addAndMakeVisible(envelopeGroup); + addAndMakeVisible(filterGroup); +} diff --git a/Source/SlidersComponent.h b/Source/SlidersComponent.h new file mode 100644 index 0000000..ede78d3 --- /dev/null +++ b/Source/SlidersComponent.h @@ -0,0 +1,46 @@ +# pragma once + +#include "../JuceLibraryCode/JuceHeader.h" +#include "FluidSynthModel.h" + +using namespace std; + +class SlidersComponent : public Component +{ +public: + SlidersComponent(FluidSynthModel* fluidSynthModel); + ~SlidersComponent(); + + void resized() override; + + const int getDesiredWidth(); + +private: + std::function makeSliderListener(Slider& slider, int controller); + + FluidSynthModel* fluidSynthModel; + + GroupComponent envelopeGroup; + + Slider attackSlider; + Label attackLabel; + + Slider decaySlider; + Label decayLabel; + + Slider sustainSlider; + Label sustainLabel; + + Slider releaseSlider; + Label releaseLabel; + + GroupComponent filterGroup; + + Slider filterCutOffSlider; + Label filterCutOffLabel; + + Slider filterResonanceSlider; + Label filterResonanceLabel; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SlidersComponent) +}; diff --git a/Source/SoundfontSynthVoice.cpp b/Source/SoundfontSynthVoice.cpp index 30b6afa..221fa70 100644 --- a/Source/SoundfontSynthVoice.cpp +++ b/Source/SoundfontSynthVoice.cpp @@ -24,6 +24,7 @@ void SoundfontSynthVoice::startNote( SynthesiserSound* sound, int /*currentPitchWheelPosition*/) { this->midiNoteNumber = midiNoteNumber; + Logger::outputDebugString ( juce::String::formatted("JUCE noteon: %d, %d\n", midiNoteNumber, velocity) ); fluid_synth_noteon(synth, 0, midiNoteNumber, static_cast(velocity * 127)); // currentAngle = 0.0; @@ -55,6 +56,7 @@ void SoundfontSynthVoice::stopNote (float /*velocity*/, bool allowTailOff) { // clearCurrentNote(); // angleDelta = 0.0; // } + Logger::outputDebugString ( juce::String("JUCE noteoff\n") ); clearCurrentNote(); fluid_synth_noteoff(synth, 0, this->midiNoteNumber); } diff --git a/Source/TableComponent.cpp b/Source/TableComponent.cpp index 978ecb2..75487e5 100644 --- a/Source/TableComponent.cpp +++ b/Source/TableComponent.cpp @@ -40,11 +40,12 @@ TableComponent::TableComponent( // Add some columns to the table header, based on the column list in our database.. for (auto &column : columns) // access by reference to avoid copying { + const int colWidth{ columnIx == 1 ? 30 : 200 }; table.getHeader().addColumn ( String(column), columnIx++, - 100, // column width - 50, // min width + colWidth, // column width + 30, // min width 400, // max width TableHeaderComponent::defaultFlags ); @@ -147,9 +148,12 @@ void TableComponent::sortOrderChanged ( // This is overloaded from TableListBoxModel, and should choose the best width for the specified // column. int TableComponent::getColumnAutoSizeWidth (int columnId) { - if (columnId == 5) - return 100; // (this is the ratings column, containing a custom combobox component) +// if (columnId == 5) +// return 100; // (this is the ratings column, containing a custom combobox component) + if (columnId == 1) + return 30; // (this is the ratings column, containing a custom combobox component) + int widest = 32; // find the widest bit of text in this column.. @@ -202,4 +206,4 @@ void TableComponent::selectedRowsChanged (int row) { bool TableComponent::keyPressed(const KeyPress &key) { return table.keyPressed(key); -} \ No newline at end of file +} diff --git a/Source/TablesComponent.cpp b/Source/TablesComponent.cpp index 6df4632..67f40de 100644 --- a/Source/TablesComponent.cpp +++ b/Source/TablesComponent.cpp @@ -30,7 +30,7 @@ TablesComponent::TablesComponent( }; presetTable = new TableComponent( - {"Preset", "Name"}, + {"#", "Name"}, mapPresets( banksToPresets, selectedBank @@ -184,4 +184,4 @@ void TablesComponent::fontChanged(FluidSynthModel *, const String &) { mapBanks(banksToPresets), selectedBank ); -} \ No newline at end of file +}