Skip to content
Permalink
Browse files

Merge pull request #4908 from jthistle/287630-intsrument-expressive-p…

…atch

fix #287630: changing instrument doesn't switch patch to expressive
  • Loading branch information...
dmitrio95 committed Apr 20, 2019
2 parents 27c146f + 7bcfe21 commit 3c54040dcc4242f22e3fc6977539326de2d4c018

Large diffs are not rendered by default.

@@ -610,6 +610,19 @@ QStringList Fluid::soundFonts() const
return sf;
}

//---------------------------------------------------------
// soundFontsInfo
//---------------------------------------------------------

std::vector<SoundFontInfo> Fluid::soundFontsInfo() const
{
std::vector<SoundFontInfo> sl;
sl.reserve(sfonts.size());
for (SFont* f : sfonts)
sl.emplace_back(QFileInfo(f->get_name()).fileName(), f->fontName());
return sl;
}

//---------------------------------------------------------
// loadSoundFont
// return false on error
@@ -382,7 +382,8 @@ class Fluid : public Synthesizer {
virtual bool loadSoundFonts(const QStringList& s);
virtual bool addSoundFont(const QString& s);
virtual bool removeSoundFont(const QString& s);
virtual QStringList soundFonts() const;
QStringList soundFonts() const;
std::vector<SoundFontInfo> soundFontsInfo() const override;

void start_voice(Voice* voice);
Voice* alloc_voice(unsigned id, Sample* sample, int chan, int key, int vel, double vt);
@@ -908,6 +908,9 @@ void SFont::process_info(int size)
/* force terminate info item (don't forget uint8 info ID) */
*(item + chunk.size) = '\0';
infos.append(item);

if (id == INAM_ID)
_fontName = QString(reinterpret_cast<char*>(item + 1));
}
else
throw(QString("Invalid chunk id in INFO chunk"));
@@ -64,6 +64,7 @@ class SFont {

SFVersion _version; // sound font version
SFVersion romver; // ROM version
QString _fontName;
QList<unsigned char*> infos; // list of info strings (1st byte is ID)

void read_listchunk(SFChunk* chunk);
@@ -119,6 +120,7 @@ class SFont {
SFVersion version() const { return _version; }
int bankOffset() const { return _bankOffset; }
void setBankOffset(int val) { _bankOffset = val; }
QString fontName() const { return _fontName; }

friend class Preset;
};
@@ -21,9 +21,9 @@
#include "part.h"
#include "score.h"
#include "synthesizer/msynthesizer.h"
#include "synthesizer/synthesizer.h"
#include "synthesizer/midipatch.h"

#include <QList>
namespace Ms {

Instrument InstrumentList::defaultInstrument;
@@ -804,6 +804,13 @@ void Channel::switchExpressive(MasterSynthesizer* m, bool expressive, bool force
if ((_userBankController && !force) || !m)
return;

// Check that we're actually changing the MuseScore General soundfont
const auto& info = m->synthesizer("Fluid")->soundFontsInfo().front();
if (!info.fontName.contains("MuseScore_General")) {
qDebug().nospace() << "Soundfont '" << info.fontName << "' is not MuseScore General, cannot update expressive";
return;
}

// Work out where the new expressive patch will be
// All expressive instruments are +1 bank higher than the
// normal counterparts, except on bank 0, where they are placed on bank 17
@@ -831,25 +838,10 @@ void Channel::switchExpressive(MasterSynthesizer* m, bool expressive, bool force

// Floor bank num to multiple of 129 and add new num to get bank num of new patch
searchBankNum = (bank() / 129) * 129 + newBankNum;

// Now find the string that has to be contained in the patch name for it to be
// selected as the new patch.
const auto& pl = m->getPatchInfo();
QString containString;
if (expressive)
containString = QString("Expr.");
else {
for (const MidiPatch* p : pl) {
if (p->bank == bank() && p->prog == program() && p->synti == synti()) {
containString = QString(p->name).replace("Expr.", "").trimmed();
break;
}
}
}

for (const MidiPatch* p : pl) {
if (p->synti == "Fluid") {
if (searchBankNum == p->bank && program() == p->prog && p->name.contains(containString)) {
if (searchBankNum == p->bank && program() == p->prog) {
setBank(p->bank);
return;
}
@@ -4547,7 +4547,6 @@ void MasterScore::setLayout(const Fraction& t)

void MasterScore::updateExpressive(MasterSynthesizer* m)
{
qDebug("update expressive!");
SynthesizerState s = synthesizerState();
SynthesizerGroup g = s.group("master");

@@ -4589,7 +4588,22 @@ void MasterScore::updateExpressive(MasterSynthesizer* m, bool expressive, bool f
}
}

// Rebuild midi mappings to be safe
}

//---------------------------------------------------------
// rebuildAndUpdateExpressive
// implicitly rebuild midi mappings as well. Should be preferred over
// just updateExpressive, in most cases.
//---------------------------------------------------------

void MasterScore::rebuildAndUpdateExpressive(MasterSynthesizer* m)
{
// Rebuild midi mappings to make sure we have playback channels
rebuildMidiMapping();

updateExpressive(m);

// Rebuild midi mappings again to be safe
rebuildMidiMapping();
}

@@ -1319,6 +1319,7 @@ class MasterScore : public Score {
int getNextFreeDrumMidiMapping();
void enqueueMidiEvent(MidiInputEvent ev) { _midiInputQueue.enqueue(ev); }
void updateChannel();
void rebuildAndUpdateExpressive(MasterSynthesizer* m);
void updateExpressive(MasterSynthesizer* m);
void updateExpressive(MasterSynthesizer* m, bool expressive, bool force = false);
void setSoloMute();
@@ -190,7 +190,6 @@ void EditStaff::updateInstrument()
minPitchP->setText(midiCodeToStr(_minPitchP));
maxPitchP->setText(midiCodeToStr(_maxPitchP));
singleNoteDynamics->setChecked(instrument.singleNoteDynamics());
staff->score()->masterScore()->updateExpressive(synti);

// only show string data controls if instrument has strings
int numStr = instrument.stringData() ? instrument.stringData()->strings() : 0;
@@ -385,6 +384,7 @@ void EditStaff::apply()

score->update();
score->masterScore()->updateChannel();
staff->score()->masterScore()->rebuildAndUpdateExpressive(synti);
}

//---------------------------------------------------------
@@ -760,11 +760,11 @@ MasterScore* MuseScore::getNewFile()
if (!copyright.isEmpty())
score->setMetaTag("copyright", copyright);

score->rebuildMidiMapping();
if (synti)
score->setSynthesizerState(synti->state());

// We need a midi mapping to be able to update the expressive
score->updateExpressive(synti);
score->rebuildMidiMapping();
// Call this even if synti doesn't exist - we need to rebuild either way
score->rebuildAndUpdateExpressive(synti);

{
ScoreLoad sl;
@@ -2251,6 +2251,10 @@ Score::FileError readScore(MasterScore* score, QString name, bool ignoreVersionE
score->setName(info.completeBaseName());
score->setImportedFilePath(name);

// Set the default synthesizer state before we read
if (synti)
score->setSynthesizerState(synti->state());

if (suffix == "mscz" || suffix == "mscx") {
Score::FileError rv = score->loadMsc(name, ignoreVersionError);
if (score && score->masterScore()->fileInfo()->path().startsWith(":/"))
@@ -532,8 +532,7 @@ void MuseScore::editInstrList()

masterScore->setLayoutAll();
masterScore->endCmd();
masterScore->rebuildMidiMapping();
masterScore->updateExpressive(synti);
masterScore->rebuildAndUpdateExpressive(synti);
seq->initInstruments();
}

@@ -459,7 +459,7 @@ void SynthControl::updateGui()

void SynthControl::updateExpressivePatches()
{
_score->masterScore()->updateExpressive(synti);
_score->masterScore()->rebuildAndUpdateExpressive(synti);
updateMixer();
}

@@ -22,6 +22,18 @@ class PlayEvent;
class Synth;
class SynthesizerGui;

//---------------------------------------------------------
// SoundFontInfo
//---------------------------------------------------------

struct SoundFontInfo {
QString fileName;
QString fontName;

SoundFontInfo(QString _fileName) : fileName(_fileName), fontName(_fileName) {}
SoundFontInfo(QString _fileName, QString _fontName) : fileName(_fileName), fontName(_fontName) {}
};

//---------------------------------------------------------
// Synthesizer
//---------------------------------------------------------
@@ -48,7 +60,7 @@ class Synthesizer {
virtual bool addSoundFont(const QString&) { return false; }
virtual bool removeSoundFont(const QString&) { return false; }

virtual QStringList soundFonts() const = 0;
virtual std::vector<SoundFontInfo> soundFontsInfo() const = 0;

virtual void process(unsigned, float*, float*, float*) = 0;
virtual void play(const PlayEvent&) = 0;
@@ -326,6 +326,19 @@ QStringList Zerberus::soundFonts() const
return sl;
}

//---------------------------------------------------------
// soundFontsInfo
//---------------------------------------------------------

std::vector<Ms::SoundFontInfo> Zerberus::soundFontsInfo() const
{
std::vector<Ms::SoundFontInfo> sl;
sl.reserve(instruments.size());
for (ZInstrument* i : instruments)
sl.emplace_back(i->path());
return sl;
}

//---------------------------------------------------------
// addSoundFont
//---------------------------------------------------------
@@ -130,7 +130,8 @@ class Zerberus : public Ms::Synthesizer {
virtual bool removeSoundFont(const QString&);
virtual bool loadSoundFonts(const QStringList&);
virtual bool removeSoundFonts(const QStringList& fileNames);
virtual QStringList soundFonts() const;
QStringList soundFonts() const;
std::vector<Ms::SoundFontInfo> soundFontsInfo() const override;

virtual const QList<Ms::MidiPatch*>& getPatchInfo() const override { return patches; }

0 comments on commit 3c54040

Please sign in to comment.
You can’t perform that action at this time.