add store/recall global synthesizer settings; connect tuning settings

This commit is contained in:
ws 2013-04-19 17:15:30 +02:00
parent 725882fcdb
commit 2deb49be5a
17 changed files with 314 additions and 146 deletions

View file

@ -51,7 +51,10 @@ void EffectGui::init(QUrl& url)
void EffectGui::valueChanged(const QString& msg, qreal val) void EffectGui::valueChanged(const QString& msg, qreal val)
{ {
if (_effect->value(msg) != val) {
_effect->setValue(msg, val); _effect->setValue(msg, val);
emit valueChanged();
}
} }
//--------------------------------------------------------- //---------------------------------------------------------

View file

@ -23,6 +23,9 @@ class EffectGui : public QDeclarativeView {
Q_OBJECT Q_OBJECT
Effect* _effect; Effect* _effect;
signals:
void valueChanged();
public slots: public slots:
void valueChanged(const QString& name, qreal); void valueChanged(const QString& name, qreal);

View file

@ -199,6 +199,7 @@ void FluidGui::soundFontAddClicked()
else { else {
soundFonts->insertItem(0, sfName); soundFonts->insertItem(0, sfName);
emit sfChanged(); emit sfChanged();
emit valueChanged();
} }
} }
updateUpDownButtons(); updateUpDownButtons();

View file

@ -40,7 +40,9 @@ class SynthesizerGroup : public std::list<IdValue> {
public: public:
const QString& name() const { return _name; } const QString& name() const { return _name; }
void setName(const QString& s) { _name = s; } void setName(const QString& s) { _name = s; }
SynthesizerGroup() : std::list<IdValue>() {} SynthesizerGroup() : std::list<IdValue>() {}
SynthesizerGroup(const char* n, std::list<IdValue> l) : std::list<IdValue>(l), _name(n) {}
}; };
//--------------------------------------------------------- //---------------------------------------------------------
@ -50,7 +52,11 @@ class SynthesizerGroup : public std::list<IdValue> {
class SynthesizerState : public std::list<SynthesizerGroup> { class SynthesizerState : public std::list<SynthesizerGroup> {
public: public:
SynthesizerState(std::initializer_list<SynthesizerGroup> l) {
insert(end(), l.begin(), l.end());
}
SynthesizerState() : std::list<SynthesizerGroup>() {} SynthesizerState() : std::list<SynthesizerGroup>() {}
void write(Xml&) const; void write(Xml&) const;
void read(XmlReader&); void read(XmlReader&);
}; };

View file

@ -2171,25 +2171,12 @@ MasterSynthesizer* synthesizerFactory()
FluidS::Fluid* fluid = new FluidS::Fluid(); FluidS::Fluid* fluid = new FluidS::Fluid();
ms->registerSynthesizer(fluid); ms->registerSynthesizer(fluid);
if (!preferences.defaultSf.isEmpty()) {
QStringList sfl;
sfl.append(preferences.defaultSf);
fluid->loadSoundFonts(sfl);
fluid->gui()->synthesizerChanged();
}
#ifdef AEOLUS #ifdef AEOLUS
ms->registerSynthesizer(new Aeolus()); ms->registerSynthesizer(new Aeolus());
#endif #endif
#ifdef ZERBERUS #ifdef ZERBERUS
Zerberus* zerberus = new Zerberus(); ms->registerSynthesizer(new Zerberus);
ms->registerSynthesizer(zerberus);
if (!preferences.defaultSfz.isEmpty()) {
QStringList sfz;
sfz.append(preferences.defaultSfz);
zerberus->loadSoundFonts(sfz);
zerberus->gui()->synthesizerChanged();
}
#endif #endif
ms->registerEffect(0, new NoEffect); ms->registerEffect(0, new NoEffect);
ms->registerEffect(0, new ZitaReverb); ms->registerEffect(0, new ZitaReverb);
@ -2450,6 +2437,7 @@ int main(int argc, char* av[])
synti = synthesizerFactory(); synti = synthesizerFactory();
MScore::sampleRate = driver->sampleRate(); MScore::sampleRate = driver->sampleRate();
synti->setSampleRate(MScore::sampleRate); synti->setSampleRate(MScore::sampleRate);
synti->init();
seq->setDriver(driver); seq->setDriver(driver);
seq->setMasterSynthesizer(synti); seq->setMasterSynthesizer(synti);

View file

@ -218,9 +218,6 @@ void Preferences::init()
sfPath = QDir(QString("%1%2;%3/%4").arg(mscoreGlobalShare).arg("sound").arg(wd).arg(QCoreApplication::translate("soundfonts_directory", "Soundfonts"))).absolutePath(); sfPath = QDir(QString("%1%2;%3/%4").arg(mscoreGlobalShare).arg("sound").arg(wd).arg(QCoreApplication::translate("soundfonts_directory", "Soundfonts"))).absolutePath();
sfzPath = QDir(QString("%1/%2").arg(wd).arg(QCoreApplication::translate("sfz_files_directory", "SfzFiles"))).absolutePath(); sfzPath = QDir(QString("%1/%2").arg(wd).arg(QCoreApplication::translate("sfz_files_directory", "SfzFiles"))).absolutePath();
defaultSf = "fluid.sf3";
defaultSfz = "";
nudgeStep10 = 1.0; // Ctrl + cursor key (default 1.0) nudgeStep10 = 1.0; // Ctrl + cursor key (default 1.0)
nudgeStep50 = 5.0; // Alt + cursor key (default 5.0) nudgeStep50 = 5.0; // Alt + cursor key (default 5.0)
@ -268,8 +265,6 @@ void Preferences::write()
s.setValue("enableMidiInput", enableMidiInput); s.setValue("enableMidiInput", enableMidiInput);
s.setValue("playNotes", playNotes); s.setValue("playNotes", playNotes);
s.setValue("defaultSf", defaultSf);
s.setValue("defaultSfz", defaultSfz);
s.setValue("lPort", lPort); s.setValue("lPort", lPort);
s.setValue("rPort", rPort); s.setValue("rPort", rPort);
s.setValue("showNavigator", showNavigator); s.setValue("showNavigator", showNavigator);
@ -430,8 +425,6 @@ void Preferences::read()
lPort = s.value("lPort", lPort).toString(); lPort = s.value("lPort", lPort).toString();
rPort = s.value("rPort", rPort).toString(); rPort = s.value("rPort", rPort).toString();
defaultSf = s.value("defaultSf", defaultSf).toString();
defaultSfz = s.value("defaultSfz", defaultSfz).toString();
showNavigator = s.value("showNavigator", showNavigator).toBool(); showNavigator = s.value("showNavigator", showNavigator).toBool();
showStatusBar = s.value("showStatusBar", showStatusBar).toBool(); showStatusBar = s.value("showStatusBar", showStatusBar).toBool();
showPlayPanel = s.value("showPlayPanel", showPlayPanel).toBool(); showPlayPanel = s.value("showPlayPanel", showPlayPanel).toBool();
@ -856,18 +849,6 @@ void PreferenceDialog::updateValues()
jackLPort->setEnabled(false); jackLPort->setEnabled(false);
} }
QFileInfoList l = FluidS::Fluid::sfFiles();
defaultSf->addItem("", "");
foreach (const QFileInfo& fi, l)
defaultSf->addItem(fi.fileName(), fi.fileName());
defaultSf->setCurrentIndex(defaultSf->findData(prefs.defaultSf));
l = Zerberus::sfzFiles();
defaultSfz->addItem("", "");
foreach (const QFileInfo& fi, l)
defaultSfz->addItem(fi.fileName(), fi.fileName());
defaultSfz->setCurrentIndex(defaultSfz->findData(prefs.defaultSfz));
navigatorShow->setChecked(prefs.showNavigator); navigatorShow->setChecked(prefs.showNavigator);
playPanelShow->setChecked(prefs.showPlayPanel); playPanelShow->setChecked(prefs.showPlayPanel);
webPanelShow->setChecked(prefs.showWebPanel); webPanelShow->setChecked(prefs.showWebPanel);
@ -1299,8 +1280,6 @@ void PreferenceDialog::apply()
prefs.lPort = jackLPort->currentText(); prefs.lPort = jackLPort->currentText();
prefs.rPort = jackRPort->currentText(); prefs.rPort = jackRPort->currentText();
} }
prefs.defaultSf = defaultSf->itemData(defaultSf->currentIndex()).toString();
prefs.defaultSfz = defaultSfz->itemData(defaultSfz->currentIndex()).toString();
prefs.showNavigator = navigatorShow->isChecked(); prefs.showNavigator = navigatorShow->isChecked();
prefs.showPlayPanel = playPanelShow->isChecked(); prefs.showPlayPanel = playPanelShow->isChecked();
prefs.showWebPanel = webPanelShow->isChecked(); prefs.showWebPanel = webPanelShow->isChecked();

View file

@ -168,8 +168,6 @@ struct Preferences {
QString sfPath; QString sfPath;
QString sfzPath; QString sfzPath;
QString defaultSf;
QString defaultSfz;
double nudgeStep10; // Ctrl + cursor key (default 1.0) double nudgeStep10; // Ctrl + cursor key (default 1.0)
double nudgeStep50; // Alt + cursor key (default 5.0) double nudgeStep50; // Alt + cursor key (default 5.0)

View file

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>845</width> <width>873</width>
<height>624</height> <height>641</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">
@ -75,7 +75,7 @@
<string/> <string/>
</property> </property>
<property name="currentIndex"> <property name="currentIndex">
<number>0</number> <number>5</number>
</property> </property>
<widget class="QWidget" name="tab"> <widget class="QWidget" name="tab">
<property name="accessibleName"> <property name="accessibleName">
@ -2087,49 +2087,6 @@
</layout> </layout>
</widget> </widget>
</item> </item>
<item>
<widget class="QGroupBox" name="groupBox_14">
<property name="title">
<string>Default SoundFont</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_11">
<item>
<widget class="QLabel" name="label_23">
<property name="text">
<string>Soundfont:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="defaultSf">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_29">
<property name="text">
<string>SFZ:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="defaultSfz">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item> <item>
<widget class="QGroupBox" name="portmidiDriverInput"> <widget class="QGroupBox" name="portmidiDriverInput">
<property name="sizePolicy"> <property name="sizePolicy">

View file

@ -1,21 +1,13 @@
//============================================================================= //=============================================================================
// MuseScore // MuseScore
// Linux Music Score Editor // Music Composition & Notation
// $Id: select.cpp 2054 2009-08-28 16:15:01Z wschweer $
// //
// Copyright (C) 2002-2010 Werner Schweer and others // Copyright (C) 2002-2013 Werner Schweer
// //
// This program is free software; you can redistribute it and/or modify // This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2. // it under the terms of the GNU General Public License version 2
// // as published by the Free Software Foundation and appearing in
// This program is distributed in the hope that it will be useful, // the file LICENCE.GPL
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//============================================================================= //=============================================================================
#include "synthcontrol.h" #include "synthcontrol.h"
@ -31,6 +23,7 @@
#include "icons.h" #include "icons.h"
#include "libmscore/score.h" #include "libmscore/score.h"
#include "libmscore/mscore.h" #include "libmscore/mscore.h"
#include "libmscore/xml.h"
#include "libmscore/undo.h" #include "libmscore/undo.h"
#include "effects/effectgui.h" #include "effects/effectgui.h"
@ -52,8 +45,10 @@ SynthControl::SynthControl(QWidget* parent)
setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint); setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint);
int idx = 0; int idx = 0;
for (Synthesizer* s : synti->synthesizer()) for (Synthesizer* s : synti->synthesizer()) {
tabWidget->insertTab(idx++, s->gui(), tr(s->name())); tabWidget->insertTab(idx++, s->gui(), tr(s->name()));
connect(s->gui(), SIGNAL(valueChanged()), SLOT(setDirty()));
}
// effectA combo box // effectA combo box
// effectStackA widget stack // effectStackA widget stack
@ -62,12 +57,14 @@ SynthControl::SynthControl(QWidget* parent)
for (Effect* e : synti->effectList(0)) { for (Effect* e : synti->effectList(0)) {
effectA->addItem(tr(e->name())); effectA->addItem(tr(e->name()));
effectStackA->addWidget(e->gui()); effectStackA->addWidget(e->gui());
connect(e->gui(), SIGNAL(valueChanged()), SLOT(setDirty()));
} }
effectB->clear(); effectB->clear();
for (Effect* e : synti->effectList(1)) { for (Effect* e : synti->effectList(1)) {
effectB->addItem(tr(e->name())); effectB->addItem(tr(e->name()));
effectStackB->addWidget(e->gui()); effectStackB->addWidget(e->gui());
connect(e->gui(), SIGNAL(valueChanged()), SLOT(setDirty()));
} }
if (!useFactorySettings) { if (!useFactorySettings) {
@ -81,13 +78,20 @@ SynthControl::SynthControl(QWidget* parent)
updateSyntiValues(); updateSyntiValues();
tabWidget->setCurrentIndex(0); tabWidget->setCurrentIndex(0);
storeButton->setEnabled(false);
recallButton->setEnabled(false);
changeTuningButton->setEnabled(false);
connect(effectA, SIGNAL(currentIndexChanged(int)), SLOT(effectAChanged(int))); connect(effectA, SIGNAL(currentIndexChanged(int)), SLOT(effectAChanged(int)));
connect(effectB, SIGNAL(currentIndexChanged(int)), SLOT(effectBChanged(int))); connect(effectB, SIGNAL(currentIndexChanged(int)), SLOT(effectBChanged(int)));
connect(gain, SIGNAL(valueChanged(double,int)), SLOT(gainChanged(double,int))); connect(gain, SIGNAL(valueChanged(double,int)), SLOT(gainChanged(double,int)));
connect(masterTuning, SIGNAL(valueChanged(double)), SLOT(masterTuningChanged(double))); connect(masterTuning, SIGNAL(valueChanged(double)), SLOT(masterTuningChanged(double)));
connect(changeTuningButton, SIGNAL(clicked()), SLOT(changeMasterTuning()));
connect(loadButton, SIGNAL(clicked()), SLOT(loadButtonClicked())); connect(loadButton, SIGNAL(clicked()), SLOT(loadButtonClicked()));
connect(saveButton, SIGNAL(clicked()), SLOT(saveButtonClicked())); connect(saveButton, SIGNAL(clicked()), SLOT(saveButtonClicked()));
connect(storeButton, SIGNAL(clicked()), SLOT(storeButtonClicked()));
connect(recallButton, SIGNAL(clicked()), SLOT(recallButtonClicked()));
connect(gain, SIGNAL(valueChanged(double,int)), SLOT(setDirty()));
} }
//--------------------------------------------------------- //---------------------------------------------------------
@ -175,7 +179,18 @@ void SynthControl::gainChanged(double val, int)
void SynthControl::masterTuningChanged(double val) void SynthControl::masterTuningChanged(double val)
{ {
synti->setMasterTuning(val); changeTuningButton->setEnabled(true);
}
//---------------------------------------------------------
// changeMasterTuning
//---------------------------------------------------------
void SynthControl::changeMasterTuning()
{
synti->setMasterTuning(masterTuning->value());
changeTuningButton->setEnabled(false);
setDirty();
} }
//--------------------------------------------------------- //---------------------------------------------------------
@ -225,8 +240,15 @@ void SynthControl::effectBChanged(int idx)
void SynthControl::loadButtonClicked() void SynthControl::loadButtonClicked()
{ {
if (!_score)
return;
synti->setState(_score->synthesizerState()); synti->setState(_score->synthesizerState());
updateSyntiValues(); updateSyntiValues();
loadButton->setEnabled(false);
saveButton->setEnabled(false);
storeButton->setEnabled(true);
recallButton->setEnabled(true);
changeTuningButton->setEnabled(false);
} }
//--------------------------------------------------------- //---------------------------------------------------------
@ -236,12 +258,79 @@ void SynthControl::loadButtonClicked()
void SynthControl::saveButtonClicked() void SynthControl::saveButtonClicked()
{ {
if (_score && synti) { if (!_score)
return;
_score->startCmd(); _score->startCmd();
_score->undo()->push(new ChangeSynthesizerState(_score, synti->state())); _score->undo()->push(new ChangeSynthesizerState(_score, synti->state()));
_score->endCmd(); _score->endCmd();
mscore->endCmd(); mscore->endCmd();
loadButton->setEnabled(false);
saveButton->setEnabled(false);
storeButton->setEnabled(true);
recallButton->setEnabled(true);
} }
//---------------------------------------------------------
// recallButtonClicked
// load stored synthesizer settings
//---------------------------------------------------------
void SynthControl::recallButtonClicked()
{
if (!_score) {
qDebug("no score");
return;
}
SynthesizerState state;
QString s(dataPath + "/synthesizer.xml");
QFile f(s);
if (!f.open(QIODevice::ReadOnly)) {
qDebug("cannot read synthesizer settings <%s>", qPrintable(s));
return;
}
XmlReader e(&f);
while (e.readNextStartElement()) {
if (e.name() == "Synthesizer")
state.read(e);
else
e.unknown();
}
synti->setState(state);
updateSyntiValues();
storeButton->setEnabled(false);
recallButton->setEnabled(false);
loadButton->setEnabled(true);
saveButton->setEnabled(true);
changeTuningButton->setEnabled(false);
}
//---------------------------------------------------------
// storeButtonClicked
// save synthesizer settings
//---------------------------------------------------------
void SynthControl::storeButtonClicked()
{
if (!_score) {
qDebug("no score");
return;
}
QString s(dataPath + "/synthesizer.xml");
QFile f(s);
if (!f.open(QIODevice::WriteOnly)) {
qDebug("cannot write synthesizer settings <%s>", qPrintable(s));
return;
}
Xml xml(&f);
xml.header();
synti->state().write(xml);
storeButton->setEnabled(false);
recallButton->setEnabled(false);
} }
//--------------------------------------------------------- //---------------------------------------------------------
@ -264,3 +353,15 @@ void SynthControl::updateSyntiValues()
effectStackB->setCurrentIndex(idx); effectStackB->setCurrentIndex(idx);
} }
//---------------------------------------------------------
// setDirty
//---------------------------------------------------------
void SynthControl::setDirty()
{
loadButton->setEnabled(true);
saveButton->setEnabled(true);
storeButton->setEnabled(true);
recallButton->setEnabled(true);
}

View file

@ -40,10 +40,14 @@ class SynthControl : public QWidget, Ui::SynthControl {
private slots: private slots:
void gainChanged(double, int); void gainChanged(double, int);
void masterTuningChanged(double); void masterTuningChanged(double);
void changeMasterTuning();
void effectAChanged(int); void effectAChanged(int);
void effectBChanged(int); void effectBChanged(int);
void loadButtonClicked(); void loadButtonClicked();
void saveButtonClicked(); void saveButtonClicked();
void storeButtonClicked();
void recallButtonClicked();
void setDirty();
signals: signals:
void closed(bool); void closed(bool);

View file

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>594</width> <width>616</width>
<height>269</height> <height>281</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -16,13 +16,20 @@
<layout class="QGridLayout" name="gridLayout_2"> <layout class="QGridLayout" name="gridLayout_2">
<item row="1" column="0"> <item row="1" column="0">
<layout class="QGridLayout" name="gridLayout_4"> <layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="1"> <item row="0" column="3">
<widget class="QPushButton" name="loadButton"> <widget class="QPushButton" name="storeButton">
<property name="text">
<string>Store</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QPushButton" name="saveButton">
<property name="toolTip"> <property name="toolTip">
<string>Load from Score</string> <string>Save to Score</string>
</property> </property>
<property name="text"> <property name="text">
<string>Load</string> <string>Save</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -39,39 +46,20 @@
</property> </property>
</spacer> </spacer>
</item> </item>
<item row="0" column="3"> <item row="0" column="1">
<widget class="QLabel" name="label_39"> <widget class="QPushButton" name="loadButton">
<property name="toolTip">
<string>Load from Score</string>
</property>
<property name="text"> <property name="text">
<string>Master Tuning</string> <string>Load</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="4"> <item row="0" column="4">
<widget class="QDoubleSpinBox" name="masterTuning"> <widget class="QPushButton" name="recallButton">
<property name="suffix">
<string extracomment="Frequency Herz">Hz</string>
</property>
<property name="decimals">
<number>1</number>
</property>
<property name="minimum">
<double>300.000000000000000</double>
</property>
<property name="maximum">
<double>600.000000000000000</double>
</property>
<property name="value">
<double>440.000000000000000</double>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QPushButton" name="saveButton">
<property name="toolTip">
<string>Save to Score</string>
</property>
<property name="text"> <property name="text">
<string>Save</string> <string>Recall</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -110,7 +98,7 @@
<item row="0" column="0"> <item row="0" column="0">
<widget class="QTabWidget" name="tabWidget"> <widget class="QTabWidget" name="tabWidget">
<property name="currentIndex"> <property name="currentIndex">
<number>0</number> <number>1</number>
</property> </property>
<widget class="QWidget" name="masterEffectsTab"> <widget class="QWidget" name="masterEffectsTab">
<attribute name="title"> <attribute name="title">
@ -179,6 +167,72 @@
</item> </item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="tab">
<attribute name="title">
<string>Tuning</string>
</attribute>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_39">
<property name="text">
<string>Master Tuning</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QDoubleSpinBox" name="masterTuning">
<property name="suffix">
<string extracomment="Frequency Herz">Hz</string>
</property>
<property name="decimals">
<number>1</number>
</property>
<property name="minimum">
<double>300.000000000000000</double>
</property>
<property name="maximum">
<double>600.000000000000000</double>
</property>
<property name="value">
<double>440.000000000000000</double>
</property>
</widget>
</item>
<item row="0" column="2">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>275</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>127</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="0">
<widget class="QPushButton" name="changeTuningButton">
<property name="text">
<string>Change Tuning</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget> </widget>
</item> </item>
</layout> </layout>

View file

@ -18,6 +18,31 @@
#include "libmscore/xml.h" #include "libmscore/xml.h"
#include "midipatch.h" #include "midipatch.h"
extern QString dataPath;
//---------------------------------------------------------
// default buildin SynthesizerState
// used if synthesizer.xml does not exist or is not
// readable
//---------------------------------------------------------
static SynthesizerState defaultState = {
{ "master", {
{ 0, "Zita1" },
{ 2, "1.0" },
{ 3, "440" }
},
},
{ "Fluid", {
{ 0, "FluidR3.SF2" },
},
},
// { "Zerberus", {
// { 0, "SalamanderGrandPiano.sfz" },
// },
// },
};
//--------------------------------------------------------- //---------------------------------------------------------
// MasterSynthesizer // MasterSynthesizer
//--------------------------------------------------------- //---------------------------------------------------------
@ -29,10 +54,35 @@ MasterSynthesizer::MasterSynthesizer()
lock2 = true; lock2 = true;
_synthesizer.reserve(4); _synthesizer.reserve(4);
_gain = 1.0; _gain = 1.0;
_masterTuning = 440.0;
for (int i = 0; i < MAX_EFFECTS; ++i) for (int i = 0; i < MAX_EFFECTS; ++i)
_effect[i] = 0; _effect[i] = 0;
} }
//---------------------------------------------------------
// init
//---------------------------------------------------------
void MasterSynthesizer::init()
{
SynthesizerState state;
QString s(dataPath + "/synthesizer.xml");
QFile f(s);
if (!f.open(QIODevice::ReadOnly)) {
qDebug("cannot read synthesizer settings <%s>", qPrintable(s));
// setState(defaultState);
return;
}
XmlReader e(&f);
while (e.readNextStartElement()) {
if (e.name() == "Synthesizer")
state.read(e);
else
e.unknown();
}
setState(state);
}
//--------------------------------------------------------- //---------------------------------------------------------
// MasterSynthesizer // MasterSynthesizer
//--------------------------------------------------------- //---------------------------------------------------------
@ -286,6 +336,9 @@ void MasterSynthesizer::setState(const SynthesizerState& ss)
setGain(f); setGain(f);
} }
break; break;
case 3:
setMasterTuning(v.data.toDouble());
break;
} }
} }
} }
@ -313,9 +366,10 @@ SynthesizerState MasterSynthesizer::state() const
SynthesizerState ss; SynthesizerState ss;
SynthesizerGroup g; SynthesizerGroup g;
g.setName("master"); g.setName("master");
g.push_back(IdValue(0, QString("%1").arg(_effect[0] ? _effect[0]->name() : "none"))); g.push_back(IdValue(0, QString("%1").arg(_effect[0] ? _effect[0]->name() : "NoEffect")));
g.push_back(IdValue(1, QString("%1").arg(_effect[1] ? _effect[1]->name() : "none"))); g.push_back(IdValue(1, QString("%1").arg(_effect[1] ? _effect[1]->name() : "NoEffect")));
g.push_back(IdValue(2, QString("%1").arg(gain()))); g.push_back(IdValue(2, QString("%1").arg(gain())));
g.push_back(IdValue(3, QString("%1").arg(masterTuning())));
ss.push_back(g); ss.push_back(g);
for (Synthesizer* s : _synthesizer) for (Synthesizer* s : _synthesizer)
ss.push_back(s->state()); ss.push_back(s->state());
@ -338,3 +392,14 @@ void MasterSynthesizer::setGain(float f)
} }
} }
//---------------------------------------------------------
// setMasterTuning
//---------------------------------------------------------
void MasterSynthesizer::setMasterTuning(double val)
{
_masterTuning = val;
for (Synthesizer* s : _synthesizer)
s->setMasterTuning(_masterTuning);
}

View file

@ -32,6 +32,7 @@ class MasterSynthesizer : public QObject {
Q_OBJECT Q_OBJECT
float _gain; float _gain;
double _masterTuning;
public: public:
static const int MAX_BUFFERSIZE = 4096; static const int MAX_BUFFERSIZE = 4096;
@ -48,7 +49,6 @@ class MasterSynthesizer : public QObject {
float effect1Buffer[MAX_BUFFERSIZE]; float effect1Buffer[MAX_BUFFERSIZE];
float effect2Buffer[MAX_BUFFERSIZE]; float effect2Buffer[MAX_BUFFERSIZE];
void init();
int indexOfEffect(int ab, const QString& name); int indexOfEffect(int ab, const QString& name);
public slots: public slots:
@ -64,14 +64,16 @@ class MasterSynthesizer : public QObject {
~MasterSynthesizer(); ~MasterSynthesizer();
void registerSynthesizer(Synthesizer*); void registerSynthesizer(Synthesizer*);
void init();
float sampleRate() { return _sampleRate; } float sampleRate() { return _sampleRate; }
void setSampleRate(float val); void setSampleRate(float val);
void process(unsigned, float*); void process(unsigned, float*);
void play(const Event&, unsigned); void play(const Event&, unsigned);
void setMasterTuning(double) {} void setMasterTuning(double val);
double masterTuning() const { return 440.0; } double masterTuning() const { return _masterTuning; }
int index(const QString&) const; int index(const QString&) const;
QString name(unsigned) const; QString name(unsigned) const;

View file

@ -25,6 +25,7 @@ class SynthesizerGui : public QWidget {
signals: signals:
void sfChanged(); void sfChanged();
void valueChanged();
public slots: public slots:
virtual void synthesizerChanged() {} virtual void synthesizerChanged() {}

View file

@ -115,7 +115,7 @@ void Voice::start(Channel* c, int key, int v, const Zone* z)
phase.set(0); phase.set(0);
double sr = double(s->sampleRate()) / 44100.0; double sr = double(s->sampleRate()) / 44100.0;
phaseIncr.set(Zerberus::ct2hz(key * 100 + z->tune) * sr/Zerberus::ct2hz(z->keyBase * 100.0)); phaseIncr.set(_zerberus->ct2hz(key * 100 + z->tune) * sr/_zerberus->ct2hz(z->keyBase * 100.0));
fres = 13500.0; fres = 13500.0;
last_fres = -1.0; last_fres = -1.0;
@ -217,7 +217,7 @@ void Voice::process(int frames, float* p)
float modlfo_to_fc = 0.0; float modlfo_to_fc = 0.0;
float modenv_to_fc = 0.0; float modenv_to_fc = 0.0;
float _fres = Zerberus::ct2hz(fres float _fres = _zerberus->ct2hz(fres
+ modlfo_val * modlfo_to_fc + modlfo_val * modlfo_to_fc
+ modenv_val * modenv_to_fc); + modenv_val * modenv_to_fc);

View file

@ -70,6 +70,7 @@ class Zerberus : public QObject, public Synthesizer {
static bool initialized; static bool initialized;
static std::list<ZInstrument*> globalInstruments; static std::list<ZInstrument*> globalInstruments;
double _masterTuning = 440.0;
std::atomic<bool> busy; std::atomic<bool> busy;
std::list<ZInstrument*> instruments; std::list<ZInstrument*> instruments;
@ -102,7 +103,10 @@ class Zerberus : public QObject, public Synthesizer {
Channel* channel(int n) { return _channel[n]; } Channel* channel(int n) { return _channel[n]; }
int loadProgress() { return _loadProgress; } int loadProgress() { return _loadProgress; }
static double ct2hz(float c) { return 8.176 * pow(2.0, (double)c / 1200.0); } virtual void setMasterTuning(double val) { _masterTuning = val; }
virtual double masterTuning() const { return _masterTuning; }
double ct2hz(double c) { return pow(2.0, (c-6900.0) / 1200.0) * _masterTuning; }
virtual const char* name() const; virtual const char* name() const;
virtual const QList<MidiPatch*>& getPatchInfo() const; virtual const QList<MidiPatch*>& getPatchInfo() const;

View file

@ -188,6 +188,7 @@ void ZerberusGui::onSoundFontLoaded()
else { else {
files->insertItem(0, _loadedSfName); files->insertItem(0, _loadedSfName);
} }
emit valueChanged();
} }
//--------------------------------------------------------- //---------------------------------------------------------
@ -201,6 +202,7 @@ void ZerberusGui::removeClicked()
QString s(files->item(row)->text()); QString s(files->item(row)->text());
zerberus()->removeSoundFont(s); zerberus()->removeSoundFont(s);
delete files->takeItem(row); delete files->takeItem(row);
emit valueChanged();
} }
} }