diff --git a/CMakeLists.txt b/CMakeLists.txt index dae43e573..2d5730bdf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -495,7 +495,7 @@ ENDIF() # check for Fluidsynth IF(WANT_SF2) - find_package(FluidSynth 1.0.7) + find_package(FluidSynth 1.1.0) if(FluidSynth_FOUND) SET(LMMS_HAVE_FLUIDSYNTH TRUE) SET(STATUS_FLUIDSYNTH "OK") diff --git a/include/InstrumentTrack.h b/include/InstrumentTrack.h index 90cd25814..129969292 100644 --- a/include/InstrumentTrack.h +++ b/include/InstrumentTrack.h @@ -224,6 +224,11 @@ public: return &m_mixerChannelModel; } + BoolModel* useMasterPitchModel() + { + return &m_useMasterPitchModel; + } + void setPreviewMode( const bool ); bool isPreviewMode() const diff --git a/plugins/Sf2Player/Sf2Player.cpp b/plugins/Sf2Player/Sf2Player.cpp index bd9788bf1..ab3729f7d 100644 --- a/plugins/Sf2Player/Sf2Player.cpp +++ b/plugins/Sf2Player/Sf2Player.cpp @@ -181,6 +181,15 @@ Sf2Instrument::Sf2Instrument( InstrumentTrack * _instrument_track ) : connect( &m_chorusLevel, SIGNAL( dataChanged() ), this, SLOT( updateChorus() ) ); connect( &m_chorusSpeed, SIGNAL( dataChanged() ), this, SLOT( updateChorus() ) ); connect( &m_chorusDepth, SIGNAL( dataChanged() ), this, SLOT( updateChorus() ) ); + + // Microtuning + connect(Engine::getSong(), &Song::scaleListChanged, this, &Sf2Instrument::updateTuning); + connect(Engine::getSong(), &Song::keymapListChanged, this, &Sf2Instrument::updateTuning); + connect(instrumentTrack()->microtuner()->enabledModel(), &Model::dataChanged, this, &Sf2Instrument::updateTuning, Qt::DirectConnection); + connect(instrumentTrack()->microtuner()->scaleModel(), &Model::dataChanged, this, &Sf2Instrument::updateTuning, Qt::DirectConnection); + connect(instrumentTrack()->microtuner()->keymapModel(), &Model::dataChanged, this, &Sf2Instrument::updateTuning, Qt::DirectConnection); + connect(instrumentTrack()->microtuner()->keyRangeImportModel(), &Model::dataChanged, this, &Sf2Instrument::updateTuning, Qt::DirectConnection); + connect(instrumentTrack()->baseNoteModel(), &Model::dataChanged, this, &Sf2Instrument::updateTuning, Qt::DirectConnection); auto iph = new InstrumentPlayHandle(this, _instrument_track); Engine::audioEngine()->addPlayHandle( iph ); @@ -537,6 +546,38 @@ void Sf2Instrument::updateChorus() +void Sf2Instrument::updateTuning() +{ + if (instrumentTrack()->microtuner()->enabledModel()->value()) + { + auto centArray = std::array{}; + double lowestHz = pow(2., -69. / 12.) * 440.;// Frequency of MIDI note 0, which is approximately 8.175798916 Hz + for (int i = 0; i < 128; ++i) + { + // Get desired Hz of note + double noteHz = instrumentTrack()->microtuner()->keyToFreq(i, DefaultBaseKey); + // Convert Hz to cents + centArray[i] = noteHz == 0. ? 0. : 1200. * log2(noteHz / lowestHz); + } + + fluid_synth_activate_key_tuning(m_synth, 0, 0, "", centArray.data(), true); + for (int chan = 0; chan < 16; chan++) + { + fluid_synth_activate_tuning(m_synth, chan, 0, 0, true); + } + } + else + { + fluid_synth_activate_key_tuning(m_synth, 0, 0, "", nullptr, true); + for (int chan = 0; chan < 16; chan++) + { + fluid_synth_activate_tuning(m_synth, chan, 0, 0, true); + } + } +} + + + void Sf2Instrument::reloadSynth() { double tempRate; @@ -604,6 +645,7 @@ void Sf2Instrument::reloadSynth() updateReverbOn(); updateChorusOn(); updateGain(); + updateTuning(); // Reset last MIDI pitch properties, which will be set to the correct values // upon playing the next note @@ -622,18 +664,19 @@ void Sf2Instrument::playNote( NotePlayHandle * _n, sampleFrame * ) } const f_cnt_t tfp = _n->totalFramesPlayed(); + + int masterPitch = instrumentTrack()->useMasterPitchModel()->value() ? Engine::getSong()->masterPitch() : 0; + int baseNote = instrumentTrack()->baseNoteModel()->value(); + int midiNote = _n->midiKey() - baseNote + DefaultBaseKey + masterPitch; - if( tfp == 0 ) + // out of range? + if (midiNote < 0 || midiNote >= 128) { - const float LOG440 = 2.643452676f; + return; + } - int midiNote = (int)floor( 12.0 * ( log2( _n->unpitchedFrequency() ) - LOG440 ) - 4.0 ); - - // out of range? - if( midiNote <= 0 || midiNote >= 128 ) - { - return; - } + if (tfp == 0) + { const int baseVelocity = instrumentTrack()->midiPort()->baseVelocity(); auto pluginData = new Sf2PluginData; diff --git a/plugins/Sf2Player/Sf2Player.h b/plugins/Sf2Player/Sf2Player.h index 7cad284c0..5a88d0f95 100644 --- a/plugins/Sf2Player/Sf2Player.h +++ b/plugins/Sf2Player/Sf2Player.h @@ -111,7 +111,7 @@ public slots: void updateChorusOn(); void updateChorus(); void updateGain(); - + void updateTuning(); private: static QMutex s_fontsMutex;