@ -30,7 +30,8 @@ trap 'error ${LINENO}' ERR
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
####
 | 
					####
 | 
				
			||||||
 | 
					
 | 
				
			||||||
declare -a BUILDS=("Debug" "Release")
 | 
					# declare -a BUILDS=("Debug" "Release")
 | 
				
			||||||
 | 
					declare -a BUILDS=("Release")
 | 
				
			||||||
for BUILD in "${BUILDS[@]}"
 | 
					for BUILD in "${BUILDS[@]}"
 | 
				
			||||||
do
 | 
					do
 | 
				
			||||||
  BUILDROOT="$MYDIR/build"
 | 
					  BUILDROOT="$MYDIR/build"
 | 
				
			||||||
 | 
				
			|||||||
@ -294,6 +294,7 @@
 | 
				
			|||||||
		358E45BB22BEE53A0087ED8D /* libgthread-2.0.0.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = "libgthread-2.0.0.dylib"; sourceTree = "<group>"; };
 | 
							358E45BB22BEE53A0087ED8D /* libgthread-2.0.0.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = "libgthread-2.0.0.dylib"; sourceTree = "<group>"; };
 | 
				
			||||||
		358E45BC22BEE53A0087ED8D /* libFLAC.8.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libFLAC.8.dylib; sourceTree = "<group>"; };
 | 
							358E45BC22BEE53A0087ED8D /* libFLAC.8.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libFLAC.8.dylib; sourceTree = "<group>"; };
 | 
				
			||||||
		358E45BD22BEE53A0087ED8D /* libogg.0.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libogg.0.dylib; sourceTree = "<group>"; };
 | 
							358E45BD22BEE53A0087ED8D /* libogg.0.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libogg.0.dylib; sourceTree = "<group>"; };
 | 
				
			||||||
 | 
							358E45F422BFC00C0087ED8D /* MidiConstants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MidiConstants.h; path = ../../Source/MidiConstants.h; sourceTree = "<group>"; };
 | 
				
			||||||
		35D551D55292C9D0508A408A /* PluginEditor.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = PluginEditor.cpp; path = ../../Source/PluginEditor.cpp; sourceTree = SOURCE_ROOT; };
 | 
							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; };
 | 
							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 = "<absolute>"; };
 | 
							3909EE4609ED2DCCC6B6B290 /* juce_data_structures */ = {isa = PBXFileReference; lastKnownFileType = folder; name = juce_data_structures; path = /Applications/JUCE/modules/juce_data_structures; sourceTree = "<absolute>"; };
 | 
				
			||||||
@ -545,6 +546,7 @@
 | 
				
			|||||||
				420DCC01988E65E68562F9DC /* PluginProcessor.h */,
 | 
									420DCC01988E65E68562F9DC /* PluginProcessor.h */,
 | 
				
			||||||
				35D551D55292C9D0508A408A /* PluginEditor.cpp */,
 | 
									35D551D55292C9D0508A408A /* PluginEditor.cpp */,
 | 
				
			||||||
				8990F3EAFFBBD6A42247C663 /* PluginEditor.h */,
 | 
									8990F3EAFFBBD6A42247C663 /* PluginEditor.h */,
 | 
				
			||||||
 | 
									358E45F422BFC00C0087ED8D /* MidiConstants.h */,
 | 
				
			||||||
			);
 | 
								);
 | 
				
			||||||
			name = Source;
 | 
								name = Source;
 | 
				
			||||||
			sourceTree = "<group>";
 | 
								sourceTree = "<group>";
 | 
				
			||||||
 | 
				
			|||||||
@ -4,6 +4,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <iostream>
 | 
					#include <iostream>
 | 
				
			||||||
#include "FluidSynthModel.h"
 | 
					#include "FluidSynthModel.h"
 | 
				
			||||||
 | 
					#include "MidiConstants.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using namespace std;
 | 
					using namespace std;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -15,8 +16,8 @@ FluidSynthModel::FluidSynthModel(SharesParams& p)
 | 
				
			|||||||
          currentSampleRate(44100),
 | 
					          currentSampleRate(44100),
 | 
				
			||||||
          initialised(false),
 | 
					          initialised(false),
 | 
				
			||||||
          sfont_id(0),
 | 
					          sfont_id(0),
 | 
				
			||||||
          channel(0),
 | 
					          channel(0)/*,
 | 
				
			||||||
          mod(nullptr)
 | 
					          mod(nullptr)*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{}
 | 
					{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -27,7 +28,7 @@ FluidSynthModel::~FluidSynthModel() {
 | 
				
			|||||||
        delete_fluid_settings(settings);
 | 
					        delete_fluid_settings(settings);
 | 
				
			||||||
//        delete driver;
 | 
					//        delete driver;
 | 
				
			||||||
//        delete settings;
 | 
					//        delete settings;
 | 
				
			||||||
        delete_fluid_mod(mod);
 | 
					//        delete_fluid_mod(mod);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -43,7 +44,7 @@ void FluidSynthModel::initialise() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    settings = new_fluid_settings();
 | 
					    settings = new_fluid_settings();
 | 
				
			||||||
    // https://sourceforge.net/p/fluidsynth/wiki/FluidSettings/
 | 
					    // https://sourceforge.net/p/fluidsynth/wiki/FluidSettings/
 | 
				
			||||||
//    fluid_settings_setint(settings, "synth.verbose", 1);
 | 
					    fluid_settings_setint(settings, "synth.verbose", 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    synth = new_fluid_synth(settings);
 | 
					    synth = new_fluid_synth(settings);
 | 
				
			||||||
    fluid_synth_set_sample_rate(synth, currentSampleRate);
 | 
					    fluid_synth_set_sample_rate(synth, currentSampleRate);
 | 
				
			||||||
@ -63,36 +64,73 @@ void FluidSynthModel::initialise() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
//    changePreset(128, 13);
 | 
					//    changePreset(128, 13);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    float env_amount(12700.0f);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    fluid_mod_t *mod(new_fluid_mod());
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
//    mod = new_fluid_mod();
 | 
					    fluid_mod_set_source1(mod,
 | 
				
			||||||
//
 | 
					                          static_cast<int>(SOUND_CTRL2), // MIDI CC 71 Timbre/Harmonic Intensity (filter resonance)
 | 
				
			||||||
//    // modulator's primary source controller and flags
 | 
					                          FLUID_MOD_CC
 | 
				
			||||||
//    // fluid_mod_src:
 | 
					                          | FLUID_MOD_UNIPOLAR
 | 
				
			||||||
//    // https://github.com/FluidSynth/fluidsynth/blob/master/include/fluidsynth/mod.h#L61
 | 
					                          | FLUID_MOD_CONCAVE
 | 
				
			||||||
//    // fluid_mod_flags:
 | 
					                          | FLUID_MOD_NEGATIVE);
 | 
				
			||||||
//    // https://github.com/FluidSynth/fluidsynth/blob/master/include/fluidsynth/mod.h#L41
 | 
					    fluid_mod_set_source2(mod, 0, 0);
 | 
				
			||||||
//    // diagrams showing what negative and concave mean:
 | 
					    fluid_mod_set_dest(mod, GEN_FILTERQ);
 | 
				
			||||||
//    // https://musescore.org/en/user/527826/blog/2016/05/23/volume-fluidsynth
 | 
					    fluid_mod_set_amount(mod, FLUID_PEAK_ATTENUATION);
 | 
				
			||||||
//    // fluid_gen_type:
 | 
					    fluid_synth_add_default_mod(synth, mod, FLUID_SYNTH_ADD);
 | 
				
			||||||
//    // https://github.com/FluidSynth/fluidsynth/blob/master/include/fluidsynth/gen.h#L36
 | 
					    delete_fluid_mod(mod);
 | 
				
			||||||
//    // https://github.com/FluidSynth/fluidsynth/blob/master/src/synth/fluid_gen.c#L27
 | 
					 | 
				
			||||||
//    fluid_mod_set_source1(mod,
 | 
					 | 
				
			||||||
//            FLUID_MOD_KEYPRESSURE,
 | 
					 | 
				
			||||||
//            FLUID_MOD_CC |
 | 
					 | 
				
			||||||
//                    FLUID_MOD_POSITIVE |
 | 
					 | 
				
			||||||
//                    FLUID_MOD_UNIPOLAR |
 | 
					 | 
				
			||||||
//                    FLUID_MOD_CONCAVE);
 | 
					 | 
				
			||||||
//    // modulator's secondary source controller and flags
 | 
					 | 
				
			||||||
//    // MIDI CC 74
 | 
					 | 
				
			||||||
//    fluid_mod_set_source2(mod, 74, FLUID_MOD_CC);
 | 
					 | 
				
			||||||
//    // generator for filter cutoff
 | 
					 | 
				
			||||||
//    fluid_mod_set_dest(mod, GEN_FILTERFC);
 | 
					 | 
				
			||||||
//    fluid_mod_set_amount(mod, 13500.0f);
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
//    fluid_synth_add_default_mod(synth, mod, FLUID_SYNTH_ADD);
 | 
					 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    mod = new_fluid_mod();
 | 
				
			||||||
 | 
					    fluid_mod_set_source1(mod,
 | 
				
			||||||
 | 
					                          static_cast<int>(SOUND_CTRL3), // MIDI CC 72 Release time
 | 
				
			||||||
 | 
					                          FLUID_MOD_CC
 | 
				
			||||||
 | 
					                          | FLUID_MOD_BIPOLAR
 | 
				
			||||||
 | 
					                          | FLUID_MOD_CONCAVE
 | 
				
			||||||
 | 
					                          | FLUID_MOD_POSITIVE);
 | 
				
			||||||
 | 
					    fluid_mod_set_source2(mod, 0, 0);
 | 
				
			||||||
 | 
					    fluid_mod_set_dest(mod, GEN_VOLENVRELEASE);
 | 
				
			||||||
 | 
					    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<int>(SOUND_CTRL4), // MIDI CC 73 Attack time
 | 
				
			||||||
 | 
					                          FLUID_MOD_CC
 | 
				
			||||||
 | 
					                          | FLUID_MOD_BIPOLAR
 | 
				
			||||||
 | 
					                          | FLUID_MOD_CONCAVE
 | 
				
			||||||
 | 
					                          | FLUID_MOD_POSITIVE);
 | 
				
			||||||
 | 
					    fluid_mod_set_source2(mod, 0, 0);
 | 
				
			||||||
 | 
					    fluid_mod_set_dest(mod, GEN_VOLENVATTACK);
 | 
				
			||||||
 | 
					    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<int>(SOUND_CTRL5), // MIDI CC 74 Brightness (cutoff frequency, FILTERFC)
 | 
				
			||||||
 | 
					                          FLUID_MOD_CC
 | 
				
			||||||
 | 
					                          | FLUID_MOD_SWITCH
 | 
				
			||||||
 | 
					                          | FLUID_MOD_UNIPOLAR
 | 
				
			||||||
 | 
					                          | FLUID_MOD_POSITIVE);
 | 
				
			||||||
 | 
					    fluid_mod_set_source2(mod, 0, 0);
 | 
				
			||||||
 | 
					    fluid_mod_set_dest(mod, GEN_FILTERFC);
 | 
				
			||||||
 | 
					    fluid_mod_set_amount(mod, -2400.0f);
 | 
				
			||||||
 | 
					    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<int>(SOUND_CTRL6), // MIDI CC 75 Decay Time
 | 
				
			||||||
 | 
					                          FLUID_MOD_CC
 | 
				
			||||||
 | 
					                          | FLUID_MOD_BIPOLAR
 | 
				
			||||||
 | 
					                          | FLUID_MOD_CONCAVE
 | 
				
			||||||
 | 
					                          | FLUID_MOD_POSITIVE);
 | 
				
			||||||
 | 
					    fluid_mod_set_source2(mod, 0, 0);
 | 
				
			||||||
 | 
					    fluid_mod_set_dest(mod, GEN_VOLENVDECAY);
 | 
				
			||||||
 | 
					    fluid_mod_set_amount(mod, env_amount);
 | 
				
			||||||
 | 
					    fluid_synth_add_default_mod(synth, mod, FLUID_SYNTH_ADD);
 | 
				
			||||||
 | 
					    delete_fluid_mod(mod);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    initialised = true;
 | 
					    initialised = true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -88,7 +88,7 @@ private:
 | 
				
			|||||||
    unsigned int sfont_id;
 | 
					    unsigned int sfont_id;
 | 
				
			||||||
    unsigned int channel;
 | 
					    unsigned int channel;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fluid_mod_t* mod;
 | 
					//    fluid_mod_t* mod;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ListenerList<Listener> eventListeners;
 | 
					    ListenerList<Listener> eventListeners;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										164
									
								
								Source/MidiConstants.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										164
									
								
								Source/MidiConstants.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,164 @@
 | 
				
			|||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Taken from:
 | 
				
			||||||
 | 
					 * fluidsynth/src/midi/fluid_midi.h
 | 
				
			||||||
 | 
					 * fluidsynth/src/utils/fluid_conv_tables.h
 | 
				
			||||||
 | 
					 * https://github.com/FluidSynth/fluidsynth/blob/master/src/midi/fluid_midi.h
 | 
				
			||||||
 | 
					 * https://github.com/FluidSynth/fluidsynth/blob/master/src/utils/fluid_conv_tables.h
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * FluidSynth - A Software Synthesizer
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2003  Peter Hanappe and others.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This library is free software; you can redistribute it and/or
 | 
				
			||||||
 | 
					 * modify it under the terms of the GNU Lesser General Public License
 | 
				
			||||||
 | 
					 * as published by the Free Software Foundation; either version 2.1 of
 | 
				
			||||||
 | 
					 * the License, or (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This library is distributed in the hope that it will be useful, but
 | 
				
			||||||
 | 
					 * WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
				
			||||||
 | 
					 * Lesser General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU Lesser General Public
 | 
				
			||||||
 | 
					 * License along with this library; if not, write to the Free
 | 
				
			||||||
 | 
					 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | 
				
			||||||
 | 
					 * 02110-1301, USA
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum fluid_midi_event_type
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /* channel messages */
 | 
				
			||||||
 | 
					    NOTE_OFF = 0x80,
 | 
				
			||||||
 | 
					    NOTE_ON = 0x90,
 | 
				
			||||||
 | 
					    KEY_PRESSURE = 0xa0,
 | 
				
			||||||
 | 
					    CONTROL_CHANGE = 0xb0,
 | 
				
			||||||
 | 
					    PROGRAM_CHANGE = 0xc0,
 | 
				
			||||||
 | 
					    CHANNEL_PRESSURE = 0xd0,
 | 
				
			||||||
 | 
					    PITCH_BEND = 0xe0,
 | 
				
			||||||
 | 
					    /* system exclusive */
 | 
				
			||||||
 | 
					    MIDI_SYSEX = 0xf0,
 | 
				
			||||||
 | 
					    /* system common - never in midi files */
 | 
				
			||||||
 | 
					    MIDI_TIME_CODE = 0xf1,
 | 
				
			||||||
 | 
					    MIDI_SONG_POSITION = 0xf2,
 | 
				
			||||||
 | 
					    MIDI_SONG_SELECT = 0xf3,
 | 
				
			||||||
 | 
					    MIDI_TUNE_REQUEST = 0xf6,
 | 
				
			||||||
 | 
					    MIDI_EOX = 0xf7,
 | 
				
			||||||
 | 
					    /* system real-time - never in midi files */
 | 
				
			||||||
 | 
					    MIDI_SYNC = 0xf8,
 | 
				
			||||||
 | 
					    MIDI_TICK = 0xf9,
 | 
				
			||||||
 | 
					    MIDI_START = 0xfa,
 | 
				
			||||||
 | 
					    MIDI_CONTINUE = 0xfb,
 | 
				
			||||||
 | 
					    MIDI_STOP = 0xfc,
 | 
				
			||||||
 | 
					    MIDI_ACTIVE_SENSING = 0xfe,
 | 
				
			||||||
 | 
					    MIDI_SYSTEM_RESET = 0xff,
 | 
				
			||||||
 | 
					    /* meta event - for midi files only */
 | 
				
			||||||
 | 
					    MIDI_META_EVENT = 0xff
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum fluid_midi_control_change
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    BANK_SELECT_MSB = 0x00,
 | 
				
			||||||
 | 
					    MODULATION_MSB = 0x01,
 | 
				
			||||||
 | 
					    BREATH_MSB = 0x02,
 | 
				
			||||||
 | 
					    FOOT_MSB = 0x04,
 | 
				
			||||||
 | 
					    PORTAMENTO_TIME_MSB = 0x05,
 | 
				
			||||||
 | 
					    DATA_ENTRY_MSB = 0x06,
 | 
				
			||||||
 | 
					    VOLUME_MSB = 0x07,
 | 
				
			||||||
 | 
					    BALANCE_MSB = 0x08,
 | 
				
			||||||
 | 
					    PAN_MSB = 0x0A,
 | 
				
			||||||
 | 
					    EXPRESSION_MSB = 0x0B,
 | 
				
			||||||
 | 
					    EFFECTS1_MSB = 0x0C,
 | 
				
			||||||
 | 
					    EFFECTS2_MSB = 0x0D,
 | 
				
			||||||
 | 
					    GPC1_MSB = 0x10, /* general purpose controller */
 | 
				
			||||||
 | 
					    GPC2_MSB = 0x11,
 | 
				
			||||||
 | 
					    GPC3_MSB = 0x12,
 | 
				
			||||||
 | 
					    GPC4_MSB = 0x13,
 | 
				
			||||||
 | 
					    BANK_SELECT_LSB = 0x20,
 | 
				
			||||||
 | 
					    MODULATION_WHEEL_LSB = 0x21,
 | 
				
			||||||
 | 
					    BREATH_LSB = 0x22,
 | 
				
			||||||
 | 
					    FOOT_LSB = 0x24,
 | 
				
			||||||
 | 
					    PORTAMENTO_TIME_LSB = 0x25,
 | 
				
			||||||
 | 
					    DATA_ENTRY_LSB = 0x26,
 | 
				
			||||||
 | 
					    VOLUME_LSB = 0x27,
 | 
				
			||||||
 | 
					    BALANCE_LSB = 0x28,
 | 
				
			||||||
 | 
					    PAN_LSB = 0x2A,
 | 
				
			||||||
 | 
					    EXPRESSION_LSB = 0x2B,
 | 
				
			||||||
 | 
					    EFFECTS1_LSB = 0x2C,
 | 
				
			||||||
 | 
					    EFFECTS2_LSB = 0x2D,
 | 
				
			||||||
 | 
					    GPC1_LSB = 0x30,
 | 
				
			||||||
 | 
					    GPC2_LSB = 0x31,
 | 
				
			||||||
 | 
					    GPC3_LSB = 0x32,
 | 
				
			||||||
 | 
					    GPC4_LSB = 0x33,
 | 
				
			||||||
 | 
					    SUSTAIN_SWITCH = 0x40,
 | 
				
			||||||
 | 
					    PORTAMENTO_SWITCH = 0x41,
 | 
				
			||||||
 | 
					    SOSTENUTO_SWITCH = 0x42,
 | 
				
			||||||
 | 
					    SOFT_PEDAL_SWITCH = 0x43,
 | 
				
			||||||
 | 
					    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_CTRL7 = 0x4C,
 | 
				
			||||||
 | 
					    SOUND_CTRL8 = 0x4D,
 | 
				
			||||||
 | 
					    SOUND_CTRL9 = 0x4E,
 | 
				
			||||||
 | 
					    SOUND_CTRL10 = 0x4F,
 | 
				
			||||||
 | 
					    GPC5 = 0x50,
 | 
				
			||||||
 | 
					    GPC6 = 0x51,
 | 
				
			||||||
 | 
					    GPC7 = 0x52,
 | 
				
			||||||
 | 
					    GPC8 = 0x53,
 | 
				
			||||||
 | 
					    PORTAMENTO_CTRL = 0x54,
 | 
				
			||||||
 | 
					    EFFECTS_DEPTH1 = 0x5B,
 | 
				
			||||||
 | 
					    EFFECTS_DEPTH2 = 0x5C,
 | 
				
			||||||
 | 
					    EFFECTS_DEPTH3 = 0x5D,
 | 
				
			||||||
 | 
					    EFFECTS_DEPTH4 = 0x5E,
 | 
				
			||||||
 | 
					    EFFECTS_DEPTH5 = 0x5F,
 | 
				
			||||||
 | 
					    DATA_ENTRY_INCR = 0x60,
 | 
				
			||||||
 | 
					    DATA_ENTRY_DECR = 0x61,
 | 
				
			||||||
 | 
					    NRPN_LSB = 0x62,
 | 
				
			||||||
 | 
					    NRPN_MSB = 0x63,
 | 
				
			||||||
 | 
					    RPN_LSB = 0x64,
 | 
				
			||||||
 | 
					    RPN_MSB = 0x65,
 | 
				
			||||||
 | 
					    ALL_SOUND_OFF = 0x78,
 | 
				
			||||||
 | 
					    ALL_CTRL_OFF = 0x79,
 | 
				
			||||||
 | 
					    LOCAL_CONTROL = 0x7A,
 | 
				
			||||||
 | 
					    ALL_NOTES_OFF = 0x7B,
 | 
				
			||||||
 | 
					    OMNI_OFF = 0x7C,
 | 
				
			||||||
 | 
					    OMNI_ON = 0x7D,
 | 
				
			||||||
 | 
					    POLY_OFF = 0x7E,
 | 
				
			||||||
 | 
					    POLY_ON = 0x7F
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 Attenuation range in centibels.
 | 
				
			||||||
 | 
					 Attenuation range is the dynamic range of the volume envelope generator
 | 
				
			||||||
 | 
					 from 0 to the end of attack segment.
 | 
				
			||||||
 | 
					 fluidsynth is a 24 bit synth, it could (should??) be 144 dB of attenuation.
 | 
				
			||||||
 | 
					 However the spec makes no distinction between 16 or 24 bit synths, so use
 | 
				
			||||||
 | 
					 96 dB here.
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 Note about usefulness of 24 bits:
 | 
				
			||||||
 | 
					 1)Even fluidsynth is a 24 bit synth, this format is only relevant if
 | 
				
			||||||
 | 
					 the sample format coming from the soundfont is 24 bits and the audio sample format
 | 
				
			||||||
 | 
					 choosen by the application (audio.sample.format) is not 16 bits.
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 2)When the sample soundfont is 16 bits, the internal 24 bits number have
 | 
				
			||||||
 | 
					 16 bits msb and lsb to 0. Consequently, at the DAC output, the dynamic range of
 | 
				
			||||||
 | 
					 this 24 bit sample is reduced to the the dynamic of a 16 bits sample (ie 90 db)
 | 
				
			||||||
 | 
					 even if this sample is produced by the audio driver using an audio sample format
 | 
				
			||||||
 | 
					 compatible for a 24 bit DAC.
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 3)When the audio sample format settings is 16 bits (audio.sample.format), the
 | 
				
			||||||
 | 
					 audio driver will make use of a 16 bit DAC, and the dynamic will be reduced to 96 dB
 | 
				
			||||||
 | 
					 even if the initial sample comes from a 24 bits soundfont.
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 In both cases (2) or (3), the real dynamic range is only 96 dB.
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 Other consideration for FLUID_NOISE_FLOOR related to case (1),(2,3):
 | 
				
			||||||
 | 
					 - for case (1), FLUID_NOISE_FLOOR should be the noise floor for 24 bits (i.e -138 dB).
 | 
				
			||||||
 | 
					 - for case (2) or (3), FLUID_NOISE_FLOOR should be the noise floor for 16 bits (i.e -90 dB).
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define FLUID_PEAK_ATTENUATION  960.0f
 | 
				
			||||||
@ -13,6 +13,7 @@
 | 
				
			|||||||
#include "SoundfontSynthVoice.h"
 | 
					#include "SoundfontSynthVoice.h"
 | 
				
			||||||
#include "SoundfontSynthSound.h"
 | 
					#include "SoundfontSynthSound.h"
 | 
				
			||||||
#include "ExposesComponents.h"
 | 
					#include "ExposesComponents.h"
 | 
				
			||||||
 | 
					#include "MidiConstants.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
AudioProcessor* JUCE_CALLTYPE createPluginFilter();
 | 
					AudioProcessor* JUCE_CALLTYPE createPluginFilter();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -154,6 +155,63 @@ void JuicySFAudioProcessor::processBlock (AudioBuffer<float>& buffer, MidiBuffer
 | 
				
			|||||||
    // 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, numSamples, true);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    MidiBuffer processedMidi;
 | 
				
			||||||
 | 
					    int time;
 | 
				
			||||||
 | 
					    MidiMessage m;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // TODO: factor into a MidiCollector
 | 
				
			||||||
 | 
					    for (MidiBuffer::Iterator i (midiMessages); i.getNextEvent (m, time);) {
 | 
				
			||||||
 | 
					        Logger::outputDebugString ( m.getDescription() );
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        // explicitly not handling note_on/off, or pitch_bend, because these are (for better or worse)
 | 
				
			||||||
 | 
					        // responsibilities of SoundfontSynthVoice.
 | 
				
			||||||
 | 
					        // well, by that logic maybe I should move program change onto Voice. but it doesn't feel like a per-voice concern.
 | 
				
			||||||
 | 
					        if (m.isController()) {
 | 
				
			||||||
 | 
					            fluid_midi_event_t *midi_event(new_fluid_midi_event());
 | 
				
			||||||
 | 
					            fluid_midi_event_set_type(midi_event, static_cast<int>(CONTROL_CHANGE));
 | 
				
			||||||
 | 
					            fluid_midi_event_set_channel(midi_event, fluidSynthModel.getChannel());
 | 
				
			||||||
 | 
					            fluid_midi_event_set_control(midi_event, m.getControllerNumber());
 | 
				
			||||||
 | 
					            fluid_midi_event_set_value(midi_event, m.getControllerValue());
 | 
				
			||||||
 | 
					            fluid_synth_handle_midi_event(fluidSynth, midi_event);
 | 
				
			||||||
 | 
					            delete_fluid_midi_event(midi_event);
 | 
				
			||||||
 | 
					        } else if (m.isProgramChange()) {
 | 
				
			||||||
 | 
					            fluid_midi_event_t *midi_event(new_fluid_midi_event());
 | 
				
			||||||
 | 
					            fluid_midi_event_set_type(midi_event, static_cast<int>(PROGRAM_CHANGE));
 | 
				
			||||||
 | 
					            fluid_midi_event_set_channel(midi_event, fluidSynthModel.getChannel());
 | 
				
			||||||
 | 
					            fluid_midi_event_set_program(midi_event, m.getProgramChangeNumber());
 | 
				
			||||||
 | 
					            fluid_synth_handle_midi_event(fluidSynth, midi_event);
 | 
				
			||||||
 | 
					            delete_fluid_midi_event(midi_event);
 | 
				
			||||||
 | 
					        } else if (m.isChannelPressure()) {
 | 
				
			||||||
 | 
					            fluid_midi_event_t *midi_event(new_fluid_midi_event());
 | 
				
			||||||
 | 
					            fluid_midi_event_set_type(midi_event, static_cast<int>(CHANNEL_PRESSURE));
 | 
				
			||||||
 | 
					            fluid_midi_event_set_channel(midi_event, fluidSynthModel.getChannel());
 | 
				
			||||||
 | 
					            fluid_midi_event_set_program(midi_event, m.getChannelPressureValue());
 | 
				
			||||||
 | 
					            fluid_synth_handle_midi_event(fluidSynth, midi_event);
 | 
				
			||||||
 | 
					            delete_fluid_midi_event(midi_event);
 | 
				
			||||||
 | 
					        } else if (m.isAftertouch()) {
 | 
				
			||||||
 | 
					            fluid_midi_event_t *midi_event(new_fluid_midi_event());
 | 
				
			||||||
 | 
					            fluid_midi_event_set_type(midi_event, static_cast<int>(KEY_PRESSURE));
 | 
				
			||||||
 | 
					            fluid_midi_event_set_channel(midi_event, fluidSynthModel.getChannel());
 | 
				
			||||||
 | 
					            fluid_midi_event_set_key(midi_event, m.getNoteNumber());
 | 
				
			||||||
 | 
					            fluid_midi_event_set_value(midi_event, m.getAfterTouchValue());
 | 
				
			||||||
 | 
					            fluid_synth_handle_midi_event(fluidSynth, midi_event);
 | 
				
			||||||
 | 
					            delete_fluid_midi_event(midi_event);
 | 
				
			||||||
 | 
					        } else if (m.isMetaEvent()) {
 | 
				
			||||||
 | 
					            fluid_midi_event_t *midi_event(new_fluid_midi_event());
 | 
				
			||||||
 | 
					            fluid_midi_event_set_type(midi_event, static_cast<int>(MIDI_SYSTEM_RESET));
 | 
				
			||||||
 | 
					            fluid_synth_handle_midi_event(fluidSynth, midi_event);
 | 
				
			||||||
 | 
					            delete_fluid_midi_event(midi_event);
 | 
				
			||||||
 | 
					        } else if (m.isSysEx()) {
 | 
				
			||||||
 | 
					            fluid_midi_event_t *midi_event(new_fluid_midi_event());
 | 
				
			||||||
 | 
					            fluid_midi_event_set_type(midi_event, static_cast<int>(MIDI_SYSEX));
 | 
				
			||||||
 | 
					            // I assume that the MidiMessage's sysex buffer would be freed anyway when MidiMessage is destroyed, so set dynamic=false
 | 
				
			||||||
 | 
					            // to ensure that fluidsynth does not attempt to free the sysex buffer during delete_fluid_midi_event()
 | 
				
			||||||
 | 
					            fluid_midi_event_set_sysex(midi_event, const_cast<juce::uint8*>(m.getSysExData()), m.getSysExDataSize(), static_cast<int>(false));
 | 
				
			||||||
 | 
					            fluid_synth_handle_midi_event(fluidSynth, midi_event);
 | 
				
			||||||
 | 
					            delete_fluid_midi_event(midi_event);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // and now get our synth to process these midi events and generate its output.
 | 
					    // and now get our synth to process these midi events and generate its output.
 | 
				
			||||||
    synth.renderNextBlock (buffer, midiMessages, 0, numSamples);
 | 
					    synth.renderNextBlock (buffer, midiMessages, 0, numSamples);
 | 
				
			||||||
    fluid_synth_process(fluidSynth, numSamples, 0, nullptr, buffer.getNumChannels(), buffer.getArrayOfWritePointers());
 | 
					    fluid_synth_process(fluidSynth, numSamples, 0, nullptr, buffer.getNumChannels(), buffer.getArrayOfWritePointers());
 | 
				
			||||||
 | 
				
			|||||||
@ -58,12 +58,17 @@ void SoundfontSynthVoice::stopNote (float /*velocity*/, bool allowTailOff) {
 | 
				
			|||||||
    clearCurrentNote();
 | 
					    clearCurrentNote();
 | 
				
			||||||
    fluid_synth_noteoff(synth, 0, this->midiNoteNumber);
 | 
					    fluid_synth_noteoff(synth, 0, this->midiNoteNumber);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
void SoundfontSynthVoice::pitchWheelMoved (int /*newValue*/) {
 | 
					
 | 
				
			||||||
    // who cares?
 | 
					// receives input as MIDI 0 to 16383, with 8192 being center
 | 
				
			||||||
 | 
					// this is also exactly the input fluidsynth requires
 | 
				
			||||||
 | 
					void SoundfontSynthVoice::pitchWheelMoved (int newValue) {
 | 
				
			||||||
 | 
					    Logger::outputDebugString ( juce::String::formatted("Pitch wheel: %d\n", newValue) );
 | 
				
			||||||
 | 
					    fluid_synth_pitch_bend(synth, 0, newValue);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void SoundfontSynthVoice::controllerMoved (int /*controllerNumber*/, int /*newValue*/) {
 | 
					void SoundfontSynthVoice::controllerMoved (int controllerNumber, int newValue) {
 | 
				
			||||||
    // what's a controller?
 | 
					    // this seems to be "program change" event
 | 
				
			||||||
 | 
					    Logger::outputDebugString ( juce::String::formatted("Controller moved: %d, %d\n", controllerNumber, newValue) );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void SoundfontSynthVoice::renderNextBlock (AudioBuffer<float>& outputBuffer, int startSample, int numSamples) {
 | 
					void SoundfontSynthVoice::renderNextBlock (AudioBuffer<float>& outputBuffer, int startSample, int numSamples) {
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user