diff --git a/CMakeLists.txt b/CMakeLists.txt index 58dc4d8..67fa9a5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,7 +26,7 @@ if (POLICY CMP0153) endif() project( Drumstick - VERSION 2.11.1 + VERSION 2.11.2 LANGUAGES CXX DESCRIPTION "MIDI C++ Libraries for Qt" HOMEPAGE_URL "https://drumstick.sourceforge.io" @@ -37,7 +37,7 @@ include(SCMRevision) include(CTest) include(GNUInstallDirs) -set(RELEASE_DATE "August 22, 2026") +#set(RELEASE_DATE "August 22, 2026") set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib) diff --git a/ChangeLog b/ChangeLog index 2f63890..071c896 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2026-09-05 + * RT, Fluidsynth backend: default gain control option + * Widgets: update Fluidsynth configuration dialog + +2026-09-03 + * RT, sonivox backend: gain control option + * Widgets: update Sonivox configuration dialog + 2026-08-22 * Release 2.11.1 diff --git a/library/rt-backends/eassynth/synthcontroller.cpp b/library/rt-backends/eassynth/synthcontroller.cpp index 462e01f..8f5418a 100644 --- a/library/rt-backends/eassynth/synthcontroller.cpp +++ b/library/rt-backends/eassynth/synthcontroller.cpp @@ -183,5 +183,15 @@ QString SynthController::getSoundFont() return m_renderer->getSoundFont(); } +int SynthController::getDefaultGain() +{ + return m_renderer->defaultGain(); +} + +void SynthController::setDefaultGain(const int newValue) +{ + m_renderer->setDefaultGain(newValue); +} + } // namespace rt } // namespace drumstick diff --git a/library/rt-backends/eassynth/synthcontroller.h b/library/rt-backends/eassynth/synthcontroller.h index 809e21f..06d167c 100644 --- a/library/rt-backends/eassynth/synthcontroller.h +++ b/library/rt-backends/eassynth/synthcontroller.h @@ -37,6 +37,7 @@ namespace rt { Q_PROPERTY(bool status READ getStatus) Q_PROPERTY(QString libversion READ getLibVersion) Q_PROPERTY(QString soundfont READ getSoundFont) + Q_PROPERTY(int defaultGain READ getDefaultGain WRITE setDefaultGain) public: explicit SynthController(QObject *parent = nullptr); @@ -80,7 +81,8 @@ namespace rt { bool getStatus(); QString getLibVersion(); QString getSoundFont(); + int getDefaultGain(); + void setDefaultGain(const int newValue); }; - }} #endif // SYNTHCONTROLLER_H diff --git a/library/rt-backends/eassynth/synthrenderer.cpp b/library/rt-backends/eassynth/synthrenderer.cpp index 256734b..14f4463 100644 --- a/library/rt-backends/eassynth/synthrenderer.cpp +++ b/library/rt-backends/eassynth/synthrenderer.cpp @@ -43,6 +43,7 @@ const QString SynthRenderer::QSTR_CHORUSAMT = QStringLiteral("ChorusAmt"); const QString SynthRenderer::QSTR_SONIVOXEAS = QStringLiteral("SonivoxEAS"); const QString SynthRenderer::QSTR_SOUNDFONT = QStringLiteral("InstrumentsDefinition"); const QString SynthRenderer::QSTR_SYNTHLIB = QStringLiteral("SynthLib"); +const QString SynthRenderer::QSTR_GAIN = QStringLiteral("Gain"); const int SynthRenderer::DEF_BUFFERTIME = 60; const int SynthRenderer::DEF_REVERBTYPE = EAS_PARAM_REVERB_HALL; @@ -114,6 +115,14 @@ SynthRenderer::initEAS() } } + if ((m_gain >= 0) && (m_gain <= EAS_MAX_VOLUME)) { + eas_res = EAS_SetVolume(dataHandle, nullptr, m_gain); + if (eas_res != EAS_SUCCESS) { + m_diagnostics << QString("EAS_SetVolume(%1) error: %2").arg(m_gain).arg(eas_res); + return; + } + } + eas_res = EAS_OpenMIDIStream(dataHandle, &handle, nullptr); if (eas_res != EAS_SUCCESS) { m_diagnostics << QString("EAS_OpenMIDIStream error: %1").arg( eas_res ); @@ -200,8 +209,6 @@ SynthRenderer::~SynthRenderer() void SynthRenderer::initialize(QSettings *settings) { - //qDebug() << Q_FUNC_INFO; - settings->beginGroup(QSTR_PREFERENCES); m_bufferTime = settings->value(QSTR_BUFFERTIME, DEF_BUFFERTIME).toInt(); int reverbType = settings->value(QSTR_REVERBTYPE, DEF_REVERBTYPE).toInt(); @@ -210,8 +217,11 @@ SynthRenderer::initialize(QSettings *settings) int chorusAmt = settings->value(QSTR_CHORUSAMT, DEF_CHORUSAMT).toInt(); m_synthLib = settings->value(QSTR_SYNTHLIB, DEF_SYNTHLIB).toInt(); m_soundfont = settings->value(QSTR_SOUNDFONT, QString()).toString(); + m_gain = settings->value(QSTR_GAIN, m_defaultGain).toInt(); settings->endGroup(); + // qDebug() << Q_FUNC_INFO << "gain:" << m_gain; + initEAS(); initSoundfont(); initReverb(reverbType); @@ -278,6 +288,18 @@ SynthRenderer::run() Q_EMIT finished(); } +int SynthRenderer::defaultGain() const +{ + return m_defaultGain; +} + +void SynthRenderer::setDefaultGain(int newDefaultGain) +{ + if (m_defaultGain == newDefaultGain) + return; + m_defaultGain = newDefaultGain; +} + void SynthRenderer::writeMIDIData(const QByteArray& message) { @@ -353,6 +375,7 @@ void SynthRenderer::writeSettings(QSettings *settings) settings->setValue(QSTR_CHORUSAMT, m_chorusAmt); settings->setValue(QSTR_SOUNDFONT, m_soundfont); settings->setValue(QSTR_SYNTHLIB, m_synthLib); + settings->setValue(QSTR_GAIN, m_gain); settings->endGroup(); } } diff --git a/library/rt-backends/eassynth/synthrenderer.h b/library/rt-backends/eassynth/synthrenderer.h index a246ea7..599bb43 100644 --- a/library/rt-backends/eassynth/synthrenderer.h +++ b/library/rt-backends/eassynth/synthrenderer.h @@ -65,6 +65,7 @@ namespace drumstick { namespace rt { static const QString QSTR_SONIVOXEAS; static const QString QSTR_SOUNDFONT; static const QString QSTR_SYNTHLIB; + static const QString QSTR_GAIN; static const int DEF_BUFFERTIME; static const int DEF_REVERBTYPE; @@ -73,6 +74,9 @@ namespace drumstick { namespace rt { static const int DEF_CHORUSAMT; static const int DEF_SYNTHLIB; + int defaultGain() const; + void setDefaultGain(int newDefaultGain); + private: void initEAS(); void initPulse(); @@ -108,7 +112,8 @@ namespace drumstick { namespace rt { int m_chorusType{DEF_CHORUSTYPE}; int m_chorusAmt{DEF_CHORUSAMT}; int m_synthLib{DEF_SYNTHLIB}; + int m_defaultGain{EAS_REF_VOLUME}; + int m_gain{m_defaultGain}; }; - }} /* drumstick::rt */ #endif /*SYNTHRENDERER_H_*/ diff --git a/library/rt-backends/fluidsynth/fluidsynthengine.cpp b/library/rt-backends/fluidsynth/fluidsynthengine.cpp index f209d6f..5b5dac6 100644 --- a/library/rt-backends/fluidsynth/fluidsynthengine.cpp +++ b/library/rt-backends/fluidsynth/fluidsynthengine.cpp @@ -205,6 +205,16 @@ void FluidSynthEngine::retrieveDefaultSoundfont() } } +double FluidSynthEngine::getDefaultGain() const +{ + return default_gain; +} + +void FluidSynthEngine::setDefaultGain(double newDefault_gain) +{ + default_gain = newDefault_gain; +} + void FluidSynthEngine::initialize() { //qDebug() << Q_FUNC_INFO; diff --git a/library/rt-backends/fluidsynth/fluidsynthengine.h b/library/rt-backends/fluidsynth/fluidsynthengine.h index 3709cd6..636c337 100644 --- a/library/rt-backends/fluidsynth/fluidsynthengine.h +++ b/library/rt-backends/fluidsynth/fluidsynthengine.h @@ -69,6 +69,9 @@ class FluidSynthEngine : public QObject Q_INVOKABLE void writeSettings(QSettings *settings); + double getDefaultGain() const; + void setDefaultGain(double newDefault_gain); + static const QString QSTR_FLUIDSYNTH_VERSION; static const QString QSTR_FLUIDSYNTH; @@ -141,7 +144,8 @@ class FluidSynthEngine : public QObject double fs_sampleRate { DEFAULT_SAMPLERATE }; int fs_chorus { DEFAULT_CHORUS }; int fs_reverb { DEFAULT_REVERB }; - double fs_gain { DEFAULT_GAIN }; + double default_gain{DEFAULT_GAIN}; + double fs_gain{default_gain}; int fs_polyphony { DEFAULT_POLYPHONY }; qreal fs_reverb_damp{DEFAULT_REVERB_DAMP}; diff --git a/library/rt-backends/fluidsynth/fluidsynthoutput.cpp b/library/rt-backends/fluidsynth/fluidsynthoutput.cpp index dcfacbe..4582e95 100644 --- a/library/rt-backends/fluidsynth/fluidsynthoutput.cpp +++ b/library/rt-backends/fluidsynth/fluidsynthoutput.cpp @@ -81,6 +81,16 @@ QString FluidSynthOutput::getSoundFont() return m_synth->soundFont(); } +double FluidSynthOutput::getDefaultGain() +{ + return m_synth->getDefaultGain(); +} + +void FluidSynthOutput::setDefaultGain(const double newValue) +{ + m_synth->setDefaultGain(newValue); +} + void FluidSynthOutput::initialize(QSettings *settings) { //qDebug() << Q_FUNC_INFO; diff --git a/library/rt-backends/fluidsynth/fluidsynthoutput.h b/library/rt-backends/fluidsynth/fluidsynthoutput.h index d960c92..c4aebca 100644 --- a/library/rt-backends/fluidsynth/fluidsynthoutput.h +++ b/library/rt-backends/fluidsynth/fluidsynthoutput.h @@ -38,6 +38,7 @@ namespace rt { Q_PROPERTY(QString libversion READ getLibVersion) Q_PROPERTY(bool status READ getStatus) Q_PROPERTY(QString soundfont READ getSoundFont) + Q_PROPERTY(double defaultGain READ getDefaultGain WRITE setDefaultGain) public: explicit FluidSynthOutput(QObject *parent = nullptr); @@ -80,6 +81,8 @@ namespace rt { QString getLibVersion(); bool getStatus(); QString getSoundFont(); + double getDefaultGain(); + void setDefaultGain(const double newValue); }; }} // namespace drumstick::rt diff --git a/library/widgets/fluidsettingsdialog.cpp b/library/widgets/fluidsettingsdialog.cpp index 7f0a17b..6367c49 100644 --- a/library/widgets/fluidsettingsdialog.cpp +++ b/library/widgets/fluidsettingsdialog.cpp @@ -265,7 +265,10 @@ void FluidSettingsDialog::readSettings() ui->periodSize->setValue( settings->value(QSTR_PERIODSIZE, DEFAULT_PERIODSIZE).toInt() ); ui->periods->setValue( settings->value(QSTR_PERIODS, DEFAULT_PERIODS).toInt() ); ui->sampleRate->setCurrentText(settings->value(QSTR_SAMPLERATE, DEFAULT_SAMPLERATE).toString()); - ui->gain->setValue(settings->value(QSTR_GAIN, DEFAULT_GAIN).toDouble()); + ui->gain->setValue( + settings + ->value(QSTR_GAIN, m_driver ? m_driver->property("defaultGain").toReal() : DEFAULT_GAIN) + .toDouble()); ui->polyphony->setValue(settings->value(QSTR_POLYPHONY, DEFAULT_POLYPHONY).toInt()); ui->soundFont->setText( settings->value(QSTR_INSTRUMENTSDEFINITION, m_defSoundFont).toString() ); @@ -306,7 +309,7 @@ void FluidSettingsDialog::writeSettings() double sampleRate(DEFAULT_SAMPLERATE); int chorus(DEFAULT_CHORUS); int reverb(DEFAULT_REVERB); - double gain(DEFAULT_GAIN); + double gain(m_driver ? m_driver->property("defaultGain").toReal() : DEFAULT_GAIN); int polyphony(DEFAULT_POLYPHONY); double chorus_depth(DEFAULT_CHORUS_DEPTH); @@ -374,7 +377,7 @@ void FluidSettingsDialog::restoreDefaults() ui->periodSize->setValue(DEFAULT_PERIODSIZE); ui->periods->setValue(DEFAULT_PERIODS); ui->sampleRate->setCurrentText(QString::number(DEFAULT_SAMPLERATE)); - ui->gain->setValue(DEFAULT_GAIN); + ui->gain->setValue(m_driver ? m_driver->property("defaultGain").toReal() : DEFAULT_GAIN); ui->polyphony->setValue(DEFAULT_POLYPHONY); ui->soundFont->setText(m_defSoundFont); ui->chorus_depth->setValue(DEFAULT_CHORUS_DEPTH * CHORUS_REVERB_VALUE_SCALE); diff --git a/library/widgets/sonivoxsettingsdialog.cpp b/library/widgets/sonivoxsettingsdialog.cpp index 488e3e9..7696334 100644 --- a/library/widgets/sonivoxsettingsdialog.cpp +++ b/library/widgets/sonivoxsettingsdialog.cpp @@ -45,6 +45,7 @@ const QString SonivoxSettingsDialog::QSTR_SOUNDFONT = QStringLiteral("Instrument const QString SonivoxSettingsDialog::QSTR_DATADIR = QStringLiteral("soundfonts"); const QString SonivoxSettingsDialog::QSTR_DATADIR2 = QStringLiteral("sounds/sf2"); const QString SonivoxSettingsDialog::QSTR_SYNTHLIB = QStringLiteral("SynthLib"); +const QString SonivoxSettingsDialog::QSTR_GAIN = QStringLiteral("Gain"); const int SonivoxSettingsDialog::SYNTHLIB_WT = 1; const int SonivoxSettingsDialog::SYNTHLIB_FM = 2; @@ -129,6 +130,7 @@ void SonivoxSettingsDialog::readSettings() int chorusAmt = settings->value(QSTR_CHORUSAMT, 0).toInt(); int synthLib = settings->value(QSTR_SYNTHLIB, SYNTHLIB_WT).toInt(); QString soundfont = settings->value(QSTR_SOUNDFONT, QString()).toString(); + int gain = settings->value(QSTR_GAIN, m_driver ? m_driver->property("defaultGain") : 100).toInt(); settings->endGroup(); if (qEnvironmentVariableIsSet("PULSE_LATENCY_MSEC")) { @@ -155,6 +157,7 @@ void SonivoxSettingsDialog::readSettings() } ui->btn_soundfont->setEnabled(synthLib == 1); ui->soundfont_dls->setEnabled(synthLib == 1); + ui->sliderGain->setValue(gain); chkDriverProperties(settings.getQSettings()); } @@ -171,6 +174,7 @@ void SonivoxSettingsDialog::writeSettings() settings->setValue(QSTR_CHORUSAMT, ui->dial_Chorus->value()); settings->setValue(QSTR_SOUNDFONT, ui->soundfont_dls->text()); settings->setValue(QSTR_SYNTHLIB, ui->rbFM->isChecked() ? SYNTHLIB_FM : SYNTHLIB_WT); + settings->setValue(QSTR_GAIN, ui->sliderGain->value()); settings->endGroup(); settings->sync(); qputenv("PULSE_LATENCY_MSEC", QByteArray::number( ui->spnTime->value() )); @@ -206,6 +210,8 @@ void SonivoxSettingsDialog::restoreDefaults() ui->dial_Reverb->setValue(25800); ui->combo_Chorus->setCurrentIndex(4); ui->dial_Chorus->setValue(0); + ui->sliderGain->setValue(m_driver ? m_driver->property("defaultGain").toInt() : 100); + ui->rbWT->setChecked(true); } void SonivoxSettingsDialog::showFileDialog() diff --git a/library/widgets/sonivoxsettingsdialog.h b/library/widgets/sonivoxsettingsdialog.h index 903a9ef..a368109 100644 --- a/library/widgets/sonivoxsettingsdialog.h +++ b/library/widgets/sonivoxsettingsdialog.h @@ -62,6 +62,7 @@ namespace widgets { static const QString QSTR_DATADIR; static const QString QSTR_DATADIR2; static const QString QSTR_SYNTHLIB; + static const QString QSTR_GAIN; static const int SYNTHLIB_WT; static const int SYNTHLIB_FM; diff --git a/library/widgets/sonivoxsettingsdialog.ui b/library/widgets/sonivoxsettingsdialog.ui index c638519..6e6dc72 100644 --- a/library/widgets/sonivoxsettingsdialog.ui +++ b/library/widgets/sonivoxsettingsdialog.ui @@ -24,13 +24,6 @@ :/icon.png:/icon.png - - - - 32765 - - - @@ -41,50 +34,6 @@ - - - - 32765 - - - - - - - - - SoundFont: - - - Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter - - - soundfont_dls - - - - - - - true - - - - 0 - 0 - - - - - - - - ... - - - - - @@ -95,6 +44,19 @@ + + + + Qt::Orientation::Vertical + + + + 20 + 90 + + + + @@ -131,34 +93,76 @@ - - - - Qt::Orientation::Vertical - - - - 20 - 90 - - - - - - - - - + + - + + + SoundFont: + + + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter + + + soundfont_dls + + + + + + + true + - + 0 0 + + + + - Init. Status: + ... + + + + + + + + + + + + 32765 + + + + + + + 32765 + + + + + + + Qt::Orientation::Horizontal + + + QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok|QDialogButtonBox::StandardButton::RestoreDefaults + + + + + + + + + Gain: Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter @@ -166,28 +170,28 @@ - - - - 0 - 0 - + + + 196 + + + 100 + + + Qt::Orientation::Horizontal - - - - 0 - 0 - + + + 100 - + @@ -217,20 +221,10 @@ - - - - Qt::Orientation::Horizontal - - - QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok|QDialogButtonBox::StandardButton::RestoreDefaults - - - - + @@ -270,11 +264,52 @@ + + + + + + + 0 + 0 + + + + Init. Status: + + + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter + + + + + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + + + spnTime + sliderGain soundfont_dls btn_soundfont rbWT @@ -350,6 +385,22 @@ + + sliderGain + valueChanged(int) + lblGain + setNum(int) + + + 164 + 53 + + + 299 + 53 + + + diff --git a/utils/vpiano/connections.cpp b/utils/vpiano/connections.cpp index 896d574..4b7979e 100644 --- a/utils/vpiano/connections.cpp +++ b/utils/vpiano/connections.cpp @@ -17,10 +17,13 @@ */ #include +#include +#include + +#include "connections.h" +#include "vpianosettings.h" #include #include -#include "vpianosettings.h" -#include "connections.h" using namespace drumstick::rt; @@ -157,6 +160,35 @@ void Connections::reject() QDialog::reject(); } +void Connections::configureOutputDriverDefaults() +{ + const int DEF_SVOX_GAIN{99}; + const double DEF_FLUID_GAIN{0.99}; + if (m_midiOut != nullptr) { + bool ok = false; + auto metaObj = m_midiOut->metaObject(); + auto idx = metaObj->indexOfProperty("defaultGain"); + const QString cname = QString::fromLatin1(metaObj->className()); + if (idx != -1) { + QMetaProperty prop = metaObj->property(idx); + if (cname == "drumstick::rt::SynthController") { + int retVal = prop.read(m_midiOut).toInt(); + if (retVal != DEF_SVOX_GAIN) { + ok = prop.write(m_midiOut, DEF_SVOX_GAIN); + } + } else if (cname == "drumstick::rt::FluidSynthOutput") { + double retVal = prop.read(m_midiOut).toInt(); + if (retVal != DEF_FLUID_GAIN) { + ok = prop.write(m_midiOut, DEF_FLUID_GAIN); + } + } + if (!ok) { + qWarning() << Q_FUNC_INFO << cname << "property" << prop.name() << "write failed"; + } + } + } +} + void Connections::refresh() { if (m_midiIn != nullptr) { @@ -231,6 +263,7 @@ void Connections::configureOutputDriver() { QString driver = ui.m_outputBackends->currentText(); if (drumstick::widgets::outputDriverIsConfigurable(driver)) { + configureOutputDriverDefaults(); m_settingsChanged |= drumstick::widgets::configureOutputDriver(driver, this); } } diff --git a/utils/vpiano/connections.h b/utils/vpiano/connections.h index 871f15d..7449a07 100644 --- a/utils/vpiano/connections.h +++ b/utils/vpiano/connections.h @@ -49,6 +49,7 @@ public Q_SLOTS: void reopenDrivers(); void accept() override; void reject() override; + void configureOutputDriverDefaults(); private: bool m_settingsChanged;