drumstick
1.0.2
|
00001 /* 00002 Drumstick RT (realtime MIDI In/Out) 00003 Copyright (C) 2009-2015 Pedro Lopez-Cabanillas <plcl@users.sf.net> 00004 00005 This program is free software; you can redistribute it and/or modify 00006 it under the terms of the GNU General Public License as published by 00007 the Free Software Foundation; either version 3 of the License, or 00008 (at your option) any later version. 00009 00010 This program is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU General Public License for more details. 00014 00015 You should have received a copy of the GNU General Public License along 00016 with this program; If not, see <http://www.gnu.org/licenses/>. 00017 */ 00018 00019 #include <QDir> 00020 #include <QFileInfo> 00021 #include <QSettings> 00022 #include <QStandardPaths> 00023 #include <QCoreApplication> 00024 #include <QDebug> 00025 #include "synthengine.h" 00026 00027 const QString QSTR_PREFERENCES("FluidSynth"); 00028 const QString QSTR_INSTRUMENTSDEFINITION("InstrumentsDefinition"); 00029 const QString QSTR_DATADIR("soundfonts"); 00030 const QString QSTR_SOUNDFONT("default.sf2"); 00031 00032 const QString QSTR_AUDIODRIVER("AudioDriver"); 00033 const QString QSTR_PERIODSIZE("PeriodSize"); 00034 const QString QSTR_PERIODS("Periods"); 00035 const QString QSTR_SAMPLERATE("SampleRate"); 00036 const QString QSTR_CHORUS("Chorus"); 00037 const QString QSTR_REVERB("Reverb"); 00038 const QString QSTR_GAIN("Gain"); 00039 const QString QSTR_POLYPHONY("Polyphony"); 00040 00041 const QString QSTR_DEFAULT_AUDIODRIVER = 00042 #if defined(Q_OS_LINUX) 00043 QLatin1Literal("alsa"); 00044 #elif defined(Q_OS_WIN) 00045 QLatin1Literal("dsound"); 00046 #elif defined(Q_OS_OSX) 00047 QLatin1Literal("coreaudio"); 00048 #else 00049 QLatin1Literal("oss"); 00050 #endif 00051 const int DEFAULT_PERIODS = 00052 #if defined(Q_OS_WIN) 00053 4; 00054 #else 00055 3; 00056 #endif 00057 const int DEFAULT_PERIODSIZE = 512; 00058 const double DEFAULT_SAMPLERATE = 48000.0; 00059 const int DEFAULT_CHORUS = 0; 00060 const int DEFAULT_REVERB = 0; 00061 const double DEFAULT_GAIN = .4; 00062 const int DEFAULT_POLYPHONY = 32; 00063 00064 SynthEngine::SynthEngine(QObject *parent) 00065 : QObject(parent), 00066 m_settings(0), 00067 m_synth(0), 00068 m_driver(0) 00069 { } 00070 00071 SynthEngine::~SynthEngine() 00072 { 00073 uninitialize(); 00074 } 00075 00076 void SynthEngine::uninitialize() 00077 { 00078 if (m_driver != 0) { 00079 ::delete_fluid_audio_driver(m_driver); 00080 m_driver = 0; 00081 } 00082 if (m_synth != 0) { 00083 ::delete_fluid_synth(m_synth); 00084 m_synth = 0; 00085 } 00086 if (m_settings != 0) { 00087 ::delete_fluid_settings(m_settings); 00088 m_settings = 0; 00089 } 00090 } 00091 00092 void SynthEngine::initializeSynth(QSettings* settings) 00093 { 00094 QString fs_audiodriver = QSTR_DEFAULT_AUDIODRIVER; 00095 int fs_periodSize = DEFAULT_PERIODSIZE; 00096 int fs_periods = DEFAULT_PERIODS; 00097 double fs_sampleRate = DEFAULT_SAMPLERATE; 00098 int fs_chorus = DEFAULT_CHORUS; 00099 int fs_reverb = DEFAULT_REVERB; 00100 double fs_gain = DEFAULT_GAIN; 00101 int fs_polyphony = DEFAULT_POLYPHONY; 00102 if (settings != 0) { 00103 settings->beginGroup(QSTR_PREFERENCES); 00104 fs_audiodriver = settings->value(QSTR_AUDIODRIVER, QSTR_DEFAULT_AUDIODRIVER).toString(); 00105 fs_periodSize = settings->value(QSTR_PERIODSIZE, DEFAULT_PERIODSIZE).toInt(); 00106 fs_periods = settings->value(QSTR_PERIODS, DEFAULT_PERIODS).toInt(); 00107 fs_sampleRate = settings->value(QSTR_SAMPLERATE, DEFAULT_SAMPLERATE).toDouble(); 00108 fs_chorus = settings->value(QSTR_CHORUS, DEFAULT_CHORUS).toInt(); 00109 fs_reverb = settings->value(QSTR_REVERB, DEFAULT_REVERB).toInt(); 00110 fs_gain = settings->value(QSTR_GAIN, DEFAULT_GAIN).toDouble(); 00111 fs_polyphony = settings->value(QSTR_POLYPHONY, DEFAULT_POLYPHONY).toInt(); 00112 settings->endGroup(); 00113 } 00114 uninitialize(); 00115 m_settings = ::new_fluid_settings(); 00116 ::fluid_settings_setstr(m_settings, "audio.driver", qPrintable(fs_audiodriver)); 00117 ::fluid_settings_setint(m_settings, "audio.period-size", fs_periodSize); 00118 ::fluid_settings_setint(m_settings, "audio.periods", fs_periods); 00119 ::fluid_settings_setnum(m_settings, "synth.sample-rate", fs_sampleRate); 00120 ::fluid_settings_setint(m_settings, "synth.chorus.active", fs_chorus); 00121 ::fluid_settings_setint(m_settings, "synth.reverb.active", fs_reverb); 00122 ::fluid_settings_setnum(m_settings, "synth.gain", fs_gain); 00123 ::fluid_settings_setint(m_settings, "synth.polyphony", fs_polyphony); 00124 m_synth = ::new_fluid_synth(m_settings); 00125 m_driver = ::new_fluid_audio_driver(m_settings, m_synth); 00126 } 00127 00128 void SynthEngine::setInstrument(int channel, int pgm) 00129 { 00130 ::fluid_synth_program_change(m_synth, channel, pgm); 00131 } 00132 00133 void SynthEngine::noteOn(int channel, int midiNote, int velocity) 00134 { 00135 ::fluid_synth_noteon(m_synth, channel, midiNote, velocity); 00136 } 00137 00138 void SynthEngine::noteOff(int channel, int midiNote, int /*velocity*/) 00139 { 00140 ::fluid_synth_noteoff(m_synth, channel, midiNote); 00141 } 00142 00143 void SynthEngine::loadSoundFont() 00144 { 00145 if (m_sfid != -1) { 00146 ::fluid_synth_sfunload(m_synth, unsigned(m_sfid), 1); 00147 } 00148 m_sfid = ::fluid_synth_sfload(m_synth, qPrintable(m_soundFont), 1); 00149 } 00150 00151 void SynthEngine::initialize(QSettings *settings) 00152 { 00153 initializeSynth(settings); 00154 scanSoundFonts(); 00155 loadSoundFont(); 00156 if (m_sfid < 0) { 00157 m_soundFont = m_defSoundFont; 00158 loadSoundFont(); 00159 } 00160 } 00161 00162 void SynthEngine::panic() 00163 { 00164 ::fluid_synth_system_reset(m_synth); 00165 } 00166 00167 void SynthEngine::controlChange(const int channel, const int midiCtl, const int value) 00168 { 00169 ::fluid_synth_cc(m_synth, channel, midiCtl, value); 00170 } 00171 00172 void SynthEngine::bender(const int channel, const int value) 00173 { 00174 ::fluid_synth_pitch_bend(m_synth, channel, value + 8192); 00175 } 00176 00177 void SynthEngine::setSoundFont(const QString &value) 00178 { 00179 if (value != m_soundFont) { 00180 m_soundFont = value; 00181 loadSoundFont(); 00182 } 00183 } 00184 00185 void SynthEngine::scanSoundFonts(const QDir &initialDir) 00186 { 00187 QDir dir(initialDir); 00188 dir.setFilter(QDir::Files | QDir::AllDirs | QDir::NoDotAndDotDot); 00189 dir.setSorting(QDir::Name); 00190 QStringList filters; 00191 filters << "*.sf2" << "*.SF2"; 00192 QFileInfoList entries= dir.entryInfoList(filters); 00193 foreach(const QFileInfo &info, entries) { 00194 QString name = info.absoluteFilePath(); 00195 if (info.isFile()) { 00196 m_soundFontsList << name; 00197 } else if (info.isDir()){ 00198 scanSoundFonts(name); 00199 } 00200 } 00201 } 00202 00203 void SynthEngine::scanSoundFonts() 00204 { 00205 m_soundFontsList.clear(); 00206 QStringList paths = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation); 00207 #if defined(Q_OS_OSX) 00208 paths << (QCoreApplication::applicationDirPath() + QLatin1Literal("../Resources")); 00209 #endif 00210 foreach(const QString& p, paths) { 00211 QDir d(p + QDir::separator() + QSTR_DATADIR); 00212 if (d.exists()) { 00213 scanSoundFonts(d); 00214 } 00215 } 00216 } 00217 00218 void SynthEngine::readSettings(QSettings *settings) 00219 { 00220 QDir dir; 00221 #if defined(Q_OS_OSX) 00222 dir = QDir(QCoreApplication::applicationDirPath() + QLatin1Literal("/../Resources")); 00223 #elif defined(Q_OS_UNIX) 00224 dir = QDir(QCoreApplication::applicationDirPath() + QLatin1Literal("/../share/soundfonts/")); 00225 #else 00226 dir = QDir(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QSTR_DATADIR, QStandardPaths::LocateDirectory)); 00227 #endif 00228 QFileInfo sf2(dir, QSTR_SOUNDFONT); 00229 if (sf2.exists()) { 00230 m_defSoundFont = sf2.absoluteFilePath(); 00231 } 00232 m_sfid = -1; 00233 qDebug() << "defSoundFont:" << m_defSoundFont; 00234 settings->beginGroup(QSTR_PREFERENCES); 00235 m_soundFont = settings->value(QSTR_INSTRUMENTSDEFINITION, m_defSoundFont).toString(); 00236 settings->endGroup(); 00237 } 00238 00239 void SynthEngine::close() 00240 { 00241 m_currentConnection.clear(); 00242 uninitialize(); 00243 } 00244 00245 void SynthEngine::open() 00246 { 00247 m_currentConnection = QSTR_FLUIDSYNTH; 00248 } 00249