1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295
|
#ifndef IMPORTMIDI_OPERATIONS_H
#define IMPORTMIDI_OPERATIONS_H
#include "importmidi_inner.h"
#include "importmidi_operation.h"
#include "midi/midifile.h"
namespace Ms {
class ReducedFraction;
class InstrumentTemplate;
namespace MidiCharset {
QString defaultCharset();
}
namespace Quantize {
MidiOperations::QuantValue defaultQuantValueFromPreferences();
}
namespace MidiOperations {
// operation types are in importmidi_operation.h
// to add an operation one need to add code also to:
// - importmidi_operation.h,
// - importmidi_opmodel.cpp (2 places),
// - importmidi_trmodel.cpp (2 places),
// and - other importmidi files where algorithm requires it
template<typename T>
class TrackOp
{
public:
explicit TrackOp(T defaultValue)
: _operation{{-1, defaultValue}}, _canRedefineDefaultLater(true)
{}
const T& value(int trackIndex) const
{
const auto it = _operation.find(trackIndex);
if (it == _operation.end())
return _operation.find(-1)->second;
return it->second;
}
void setValue(int trackIndex, T value)
{
Q_ASSERT_X(trackIndex >= 0, "TrackOperation", "Invalid track index");
if (value != this->value(trackIndex))
_operation[trackIndex] = value;
}
const T& defaultValue() const
{
return _operation.find(-1)->second;
}
bool canRedefineDefaultLater() const { return _canRedefineDefaultLater; }
void setDefaultValue(T value, bool canRedefineDefaultLater = true)
{
Q_ASSERT_X(_canRedefineDefaultLater, "TrackOp::setDefaultValue",
"Cannot set default value");
if (!_canRedefineDefaultLater)
return;
_operation[-1] = value;
_canRedefineDefaultLater = canRedefineDefaultLater;
}
void clear()
{
T defaultVal = defaultValue();
_operation.clear();
_operation[-1] = defaultVal;
}
private:
// <track index, operation value>
// if track index == -1 then it's default value (for all tracks)
std::map<int, T> _operation;
bool _canRedefineDefaultLater;
};
template<typename T>
class Op
{
public:
explicit Op(T defaultValue)
: _value(defaultValue), _valueWasSet(false),
_defaultValue{defaultValue}, _canRedefineDefaultLater(true)
{}
T value() const
{
if (!_valueWasSet)
return _defaultValue;
return _value;
}
void setValue(T value)
{
if (value != this->value()) {
_value = value;
_valueWasSet = true;
}
}
T defaultValue() const
{
return _defaultValue;
}
bool canRedefineDefaultLater() const { return _canRedefineDefaultLater; }
void setDefaultValue(T value, bool canRedefineDefaultLater = true)
{
Q_ASSERT_X(_canRedefineDefaultLater, "Op::setDefaultValue",
"Cannot set default value");
if (!_canRedefineDefaultLater)
return;
_defaultValue = value;
_canRedefineDefaultLater = canRedefineDefaultLater;
}
private:
T _value;
bool _valueWasSet;
T _defaultValue;
bool _canRedefineDefaultLater;
};
// values that can be changed
struct Opers
{
// data that cannot be changed by the user
TrackOp<int> channel = TrackOp<int>(int());
TrackOp<std::string> staffName = TrackOp<std::string>(std::string()); // will be converted to unicode later
TrackOp<QString> midiInstrName = TrackOp<QString>(QString());
TrackOp<std::vector<const InstrumentTemplate *> > msInstrList
= TrackOp<std::vector<const InstrumentTemplate *> >(
std::vector<const InstrumentTemplate *>());
TrackOp<bool> isDrumTrack = TrackOp<bool>(false);
// operations for all tracks
Op<bool> isHumanPerformance = Op<bool>(false);
Op<bool> searchPickupMeasure = Op<bool>(true);
Op<bool> measureCount2xLess = Op<bool>(false);
Op<bool> showTempoText = Op<bool>(true);
Op<bool> showChordNames = Op<bool>(true);
Op<TimeSigNumerator> timeSigNumerator = Op<TimeSigNumerator>(TimeSigNumerator::_4);
Op<TimeSigDenominator> timeSigDenominator = Op<TimeSigDenominator>(TimeSigDenominator::_4);
// operations for individual tracks
TrackOp<int> trackIndexAfterReorder = TrackOp<int>(0);
TrackOp<bool> doImport = TrackOp<bool>(true);
TrackOp<QuantValue> quantValue = TrackOp<QuantValue>(Quantize::defaultQuantValueFromPreferences());
TrackOp<bool> searchTuplets = TrackOp<bool>(true);
TrackOp<bool> search2plets = TrackOp<bool>(false);
TrackOp<bool> search3plets = TrackOp<bool>(true);
TrackOp<bool> search4plets = TrackOp<bool>(true);
TrackOp<bool> search5plets = TrackOp<bool>(true);
TrackOp<bool> search7plets = TrackOp<bool>(true);
TrackOp<bool> search9plets = TrackOp<bool>(true);
TrackOp<bool> useDots = TrackOp<bool>(true);
TrackOp<bool> simplifyDurations = TrackOp<bool>(true); // for drum tracks - remove rests and ties
TrackOp<bool> showStaccato = TrackOp<bool>(true);
TrackOp<bool> doStaffSplit = TrackOp<bool>(false); // for drum tracks - split by voices
TrackOp<VoiceCount> maxVoiceCount = TrackOp<VoiceCount>(VoiceCount::V_4);
TrackOp<bool> changeClef = TrackOp<bool>(true);
TrackOp<Swing> swing = TrackOp<Swing>(Swing::NONE);
TrackOp<bool> removeDrumRests = TrackOp<bool>(true);
TrackOp<int> lyricTrackIndex = TrackOp<int>(-1); // empty lyric
TrackOp<int> msInstrIndex = TrackOp<int>(-1); // for empty instrument list
};
struct HumanBeatData
{
std::set<ReducedFraction> beatSet;
// to adapt human beats to a different time sig, if necessary
int addedFirstBeats = 0;
int addedLastBeats = 0;
ReducedFraction firstChordTick;
ReducedFraction lastChordTick;
ReducedFraction timeSig;
bool measureCount2xLess = false;
};
struct FileData
{
MidiFile midiFile;
QList<MTrack> tracks;
int processingsOfOpenedFile = 0;
bool hasTempoText = false;
QByteArray HHeaderData;
QByteArray VHeaderData;
int trackCount = 0;
Opers trackOpers;
QString charset = MidiCharset::defaultCharset();
// after the user apply MIDI import operations
// this value should be set to false
// tracks of <tick, lyric fragment> from karaoke files
// QList of lyric tracks - there can be multiple lyric tracks,
// lyric track count != MIDI track count in general
QList<std::multimap<ReducedFraction, std::string>> lyricTracks;
std::multimap<ReducedFraction, QString> chordNames;
HumanBeatData humanBeatData;
};
class Data
{
public:
FileData* data();
const FileData* data() const;
void addNewMidiFile(const QString &fileName);
int currentTrack() const;
void setMidiFileData(const QString &fileName, const MidiFile &midiFile);
void excludeMidiFile(const QString &fileName);
bool hasMidiFile(const QString &fileName);
const MidiFile* midiFile(const QString &fileName);
QStringList allMidiFiles() const;
void setOperationsFile(const QString &fileName);
private:
friend class CurrentTrackSetter;
friend class CurrentMidiFileSetter;
QString _currentMidiFile;
QString _midiOperationsFile;
int _currentTrack = -1;
std::map<QString, FileData> _data; // <file name, tracks data>
};
// scoped setter of current track
class CurrentTrackSetter
{
public:
CurrentTrackSetter(Data &opers, int track)
: _opers(opers)
{
_oldValue = _opers._currentTrack;
_opers._currentTrack = track;
}
~CurrentTrackSetter()
{
_opers._currentTrack = _oldValue;
}
private:
Data &_opers;
int _oldValue;
// disallow heap allocation - for stack-only usage
void* operator new(size_t); // standard new
void* operator new(size_t, void*); // placement new
void* operator new[](size_t); // array new
void* operator new[](size_t, void*); // placement array new
};
// scoped setter of current MIDI file
class CurrentMidiFileSetter
{
public:
CurrentMidiFileSetter(Data &opers, const QString &fileName)
: _opers(opers)
{
_oldValue = _opers._currentMidiFile;
_opers._currentMidiFile = fileName;
}
~CurrentMidiFileSetter()
{
_opers._currentMidiFile = _oldValue;
}
private:
Data &_opers;
QString _oldValue;
// disallow heap allocation - for stack-only usage
void* operator new(size_t); // standard new
void* operator new(size_t, void*); // placement new
void* operator new[](size_t); // array new
void* operator new[](size_t, void*); // placement array new
};
} // namespace MidiOperations
extern MidiOperations::Data midiImportOperations;
} // namespace Ms
#endif // IMPORTMIDI_OPERATIONS_H
|