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;