add sustain modulator. increase range of release to cover all positives (though there is still a range of negatives that are duplicated). set all sound controller CCs to 0. this breaks MIDI spec (64 = middle = no change) to accommodate soundfont spec (middle of range on envelope generators is far from 'no change')

This commit is contained in:
Alex Birch 2019-06-30 19:25:02 +01:00
parent 1d7fdc6860
commit 070f0d2a87
No known key found for this signature in database
GPG Key ID: 305EB1F98D44ACBA
3 changed files with 45 additions and 1 deletions

View File

@ -56,6 +56,18 @@ void FluidSynthModel::initialise() {
fluid_synth_set_gain(synth, 2.0); fluid_synth_set_gain(synth, 2.0);
for(int i{SOUND_CTRL1}; i <= SOUND_CTRL10; i++)
{
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, channel);
fluid_midi_event_set_control(midi_event, i);
fluid_midi_event_set_value(midi_event, 0);
fluid_synth_handle_midi_event(synth, midi_event);
delete_fluid_midi_event(midi_event);
// fluid_channel_set_cc(channel, i, 0);
}
// fluid_synth_bank_select(synth, 0, 3); // fluid_synth_bank_select(synth, 0, 3);
// fluid_handle_inst // fluid_handle_inst
@ -68,9 +80,14 @@ void FluidSynthModel::initialise() {
// http://www.synthfont.com/SoundFont_NRPNs.PDF // http://www.synthfont.com/SoundFont_NRPNs.PDF
float env_amount(20000.0f); 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_t *mod(new_fluid_mod());
//
fluid_mod_set_source1(mod, fluid_mod_set_source1(mod,
static_cast<int>(SOUND_CTRL2), // MIDI CC 71 Timbre/Harmonic Intensity (filter resonance) static_cast<int>(SOUND_CTRL2), // MIDI CC 71 Timbre/Harmonic Intensity (filter resonance)
FLUID_MOD_CC FLUID_MOD_CC
@ -92,6 +109,7 @@ void FluidSynthModel::initialise() {
| FLUID_MOD_POSITIVE); | FLUID_MOD_POSITIVE);
fluid_mod_set_source2(mod, 0, 0); fluid_mod_set_source2(mod, 0, 0);
fluid_mod_set_dest(mod, GEN_VOLENVRELEASE); fluid_mod_set_dest(mod, GEN_VOLENVRELEASE);
// fluid_mod_set_amount(mod, 15200.0f);
fluid_mod_set_amount(mod, env_amount); fluid_mod_set_amount(mod, env_amount);
fluid_synth_add_default_mod(synth, mod, FLUID_SYNTH_ADD); fluid_synth_add_default_mod(synth, mod, FLUID_SYNTH_ADD);
delete_fluid_mod(mod); delete_fluid_mod(mod);
@ -109,6 +127,7 @@ void FluidSynthModel::initialise() {
fluid_synth_add_default_mod(synth, mod, FLUID_SYNTH_ADD); fluid_synth_add_default_mod(synth, mod, FLUID_SYNTH_ADD);
delete_fluid_mod(mod); 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(); mod = new_fluid_mod();
fluid_mod_set_source1(mod, fluid_mod_set_source1(mod,
static_cast<int>(SOUND_CTRL5), // MIDI CC 74 Brightness (cutoff frequency, FILTERFC) static_cast<int>(SOUND_CTRL5), // MIDI CC 74 Brightness (cutoff frequency, FILTERFC)
@ -135,6 +154,21 @@ void FluidSynthModel::initialise() {
fluid_synth_add_default_mod(synth, mod, FLUID_SYNTH_ADD); fluid_synth_add_default_mod(synth, mod, FLUID_SYNTH_ADD);
delete_fluid_mod(mod); delete_fluid_mod(mod);
mod = new_fluid_mod();
fluid_mod_set_source1(mod,
static_cast<int>(SOUND_CTRL10), // MIDI CC 79 undefined
FLUID_MOD_CC
| FLUID_MOD_UNIPOLAR
| FLUID_MOD_LINEAR
| 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; initialised = true;
} }

View File

@ -212,6 +212,14 @@ void JuicySFAudioProcessor::processBlock (AudioBuffer<float>& buffer, MidiBuffer
} }
} }
// 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. // 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());

View File

@ -24,6 +24,7 @@ void SoundfontSynthVoice::startNote(
SynthesiserSound* sound, SynthesiserSound* sound,
int /*currentPitchWheelPosition*/) { int /*currentPitchWheelPosition*/) {
this->midiNoteNumber = midiNoteNumber; this->midiNoteNumber = midiNoteNumber;
Logger::outputDebugString ( juce::String::formatted("JUCE noteon: %d, %d\n", midiNoteNumber, velocity) );
fluid_synth_noteon(synth, 0, midiNoteNumber, static_cast<int>(velocity * 127)); fluid_synth_noteon(synth, 0, midiNoteNumber, static_cast<int>(velocity * 127));
// currentAngle = 0.0; // currentAngle = 0.0;
@ -55,6 +56,7 @@ void SoundfontSynthVoice::stopNote (float /*velocity*/, bool allowTailOff) {
// clearCurrentNote(); // clearCurrentNote();
// angleDelta = 0.0; // angleDelta = 0.0;
// } // }
Logger::outputDebugString ( juce::String("JUCE noteoff\n") );
clearCurrentNote(); clearCurrentNote();
fluid_synth_noteoff(synth, 0, this->midiNoteNumber); fluid_synth_noteoff(synth, 0, this->midiNoteNumber);
} }