Skip to content

Commit 9ad49ca

Browse files
committed
Implement the concept of a 'drum track'
- Drum tracks are not transposed by pattern => transpose
1 parent c15e2b8 commit 9ad49ca

15 files changed

Lines changed: 118 additions & 3 deletions

CHANGELOG

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ Release date:
55

66
New features:
77

8+
* Implement the concept of a 'drum track'
9+
- Drum tracks are not transposed by pattern => transpose
10+
811
Bug fixes:
912

1013
Other:

src/application/models/track_settings_model.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ void TrackSettingsModel::setInstrumentData(const Instrument & instrument)
214214
setBankByteOrderSwapped(instrument.settings().bank->byteOrderSwapped);
215215
}
216216
setTranspose(instrument.settings().transpose);
217+
setDrumTrack(instrument.settings().drumTrack);
217218

218219
setSendMidiClock(instrument.settings().timing.sendMidiClock.has_value() && *instrument.settings().timing.sendMidiClock);
219220
setSendTransport(instrument.settings().timing.sendTransport.has_value() && *instrument.settings().timing.sendTransport);
@@ -277,6 +278,7 @@ TrackSettingsModel::InstrumentU TrackSettingsModel::toInstrument() const
277278
}
278279

279280
settings.transpose = m_instrumentSettings.transpose;
281+
settings.drumTrack = m_instrumentSettings.drumTrack;
280282

281283
settings.timing.sendMidiClock = m_timingSettings.sendMidiClock;
282284
settings.timing.sendTransport = m_timingSettings.sendTransport;
@@ -482,6 +484,21 @@ void TrackSettingsModel::setAutoNoteOffOffsetEnabled(bool enabled)
482484
}
483485
}
484486

487+
bool TrackSettingsModel::drumTrack() const
488+
{
489+
return m_instrumentSettings.drumTrack;
490+
}
491+
492+
void TrackSettingsModel::setDrumTrack(bool enabled)
493+
{
494+
juzzlin::L(TAG).debug() << "Setting drum track: " << static_cast<int>(enabled);
495+
496+
if (m_instrumentSettings.drumTrack != enabled) {
497+
m_instrumentSettings.drumTrack = enabled;
498+
emit drumTrackChanged();
499+
}
500+
}
501+
485502

486503
void TrackSettingsModel::pushApplyDisabled()
487504
{

src/application/models/track_settings_model.hpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525

2626
namespace noteahead {
2727

28-
class EditorService;
2928
class Instrument;
3029

3130
class TrackSettingsModel : public QObject
@@ -57,6 +56,7 @@ class TrackSettingsModel : public QObject
5756
Q_PROPERTY(int velocityKeyTrackOffset READ velocityKeyTrackOffset WRITE setVelocityKeyTrackOffset NOTIFY velocityKeyTrackOffsetChanged)
5857
Q_PROPERTY(int autoNoteOffOffset READ autoNoteOffOffset WRITE setAutoNoteOffOffset NOTIFY autoNoteOffOffsetChanged)
5958
Q_PROPERTY(bool autoNoteOffOffsetEnabled READ autoNoteOffOffsetEnabled WRITE setAutoNoteOffOffsetEnabled NOTIFY autoNoteOffOffsetEnabledChanged)
59+
Q_PROPERTY(bool drumTrack READ drumTrack WRITE setDrumTrack NOTIFY drumTrackChanged)
6060

6161
Q_PROPERTY(MidiCcSelectionModel* midiCcModel READ midiCcModel CONSTANT)
6262

@@ -129,6 +129,9 @@ class TrackSettingsModel : public QObject
129129
void setAutoNoteOffOffset(int autoNoteOffOffset);
130130
bool autoNoteOffOffsetEnabled() const;
131131
void setAutoNoteOffOffsetEnabled(bool enabled);
132+
133+
bool drumTrack() const;
134+
void setDrumTrack(bool enabled);
132135

133136
MidiCcSelectionModel* midiCcModel() const;
134137

@@ -173,6 +176,7 @@ class TrackSettingsModel : public QObject
173176
void velocityKeyTrackOffsetChanged();
174177
void autoNoteOffOffsetChanged();
175178
void autoNoteOffOffsetEnabledChanged();
179+
void drumTrackChanged();
176180

177181
private:
178182
void pushApplyDisabled();
@@ -189,6 +193,7 @@ class TrackSettingsModel : public QObject
189193
quint8 bankMsb { 0 };
190194
bool bankByteOrderSwapped { false };
191195
int transpose { 0 };
196+
bool drumTrack { false };
192197
};
193198

194199
InstrumentSettings m_instrumentSettings;
@@ -226,4 +231,4 @@ class TrackSettingsModel : public QObject
226231

227232
} // namespace noteahead
228233

229-
#endif // TRACK_SETTINGS_MODEL_HPP
234+
#endif // TRACK_SETTINGS_MODEL_HPP

src/application/service/editor_service.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -621,7 +621,7 @@ QString EditorService::trackName(quint64 trackIndex) const
621621

622622
void EditorService::setTrackName(quint64 trackIndex, QString name)
623623
{
624-
if (m_song->trackName(trackIndex) != name.toStdString()) {
624+
if (trackName(trackIndex) != name) {
625625
m_song->setTrackName(trackIndex, name.toStdString());
626626
emit trackNameChanged();
627627
setIsModified(true);

src/common/constants.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,11 @@ QString xmlKeyTranspose()
214214
return "transpose";
215215
}
216216

217+
QString xmlKeyDrumTrack()
218+
{
219+
return "drumTrack";
220+
}
221+
217222
QString xmlKeyVelocityJitter()
218223
{
219224
return "velocityJitter";

src/common/constants.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ QString xmlKeyCutoff();
7676

7777
QString xmlKeyDelay();
7878
QString xmlKeyTranspose();
79+
QString xmlKeyDrumTrack();
7980

8081
QString xmlKeyVelocityJitter();
8182
QString xmlKeyVelocityKeyTrack();

src/domain/instrument_settings.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ void InstrumentSettings::serializeToXml(QXmlStreamWriter & writer) const
4444
}
4545

4646
writer.writeAttribute(Constants::NahdXml::xmlKeyTranspose(), QString::number(transpose));
47+
writer.writeAttribute(Constants::NahdXml::xmlKeyDrumTrack(), drumTrack ? Constants::NahdXml::xmlValueTrue() : Constants::NahdXml::xmlValueFalse());
4748

4849
if (timing.sendMidiClock.has_value()) {
4950
writer.writeAttribute(Constants::NahdXml::xmlKeySendMidiClock(), timing.sendMidiClock.value() ? Constants::NahdXml::xmlValueTrue() : Constants::NahdXml::xmlValueFalse());
@@ -83,6 +84,7 @@ InstrumentSettings::InstrumentSettingsU InstrumentSettings::deserializeFromXml(Q
8384
}
8485

8586
settings->transpose = Utils::Xml::readIntAttribute(reader, Constants::NahdXml::xmlKeyTranspose(), false).value_or(0);
87+
settings->drumTrack = Utils::Xml::readBoolAttribute(reader, Constants::NahdXml::xmlKeyDrumTrack(), false).value_or(false);
8688

8789
// Migration: Read old standard MIDI CC settings and convert to generic MIDI CC settings
8890
if (const auto cutoff = Utils::Xml::readUIntAttribute(reader, Constants::NahdXml::xmlKeyCutoff(), false)) {

src/domain/instrument_settings.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ class InstrumentSettings : public EventData
4848

4949
int transpose { 0 };
5050

51+
bool drumTrack = false;
52+
5153
struct TimingSettings
5254
{
5355
std::optional<bool> sendMidiClock;

src/domain/pattern.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "../contrib/SimpleLogger/src/simple_logger.hpp"
2323
#include "../domain/note_data.hpp"
2424
#include "column_settings.hpp"
25+
#include "instrument.hpp"
2526
#include "track.hpp"
2627

2728
#include <QXmlStreamWriter>
@@ -375,6 +376,9 @@ NoteChangeList Pattern::transposePattern(const Position & position, int semitone
375376
{
376377
NoteChangeList changes;
377378
for (const auto & track : m_trackOrder) {
379+
if (track->instrument() && track->instrument()->settings().drumTrack) {
380+
continue;
381+
}
378382
auto trackPosition = position;
379383
trackPosition.track = track->index(); // Need to set track because these positions will be returned back as changed positions.
380384
auto trackChanges = track->transposeTrack(trackPosition, semitones);

src/unit_tests/song_test/song_test.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -908,6 +908,47 @@ void SongTest::test_renderToEvents_midiSideChain_shouldClampAttackEvents()
908908
QVERIFY(targetEventFound);
909909
}
910910

911+
void SongTest::test_transposePattern_drumTrackSet_shouldNotTransposeDrumTrack()
912+
{
913+
Song song;
914+
915+
// Setup Track 0 as Drum Track
916+
auto drumInstrument = std::make_shared<Instrument>("");
917+
auto drumSettings = drumInstrument->settings();
918+
drumSettings.drumTrack = true;
919+
drumInstrument->setSettings(drumSettings);
920+
song.setInstrument(0, drumInstrument);
921+
922+
// Setup Track 1 as normal track
923+
auto normalInstrument = std::make_shared<Instrument>("");
924+
song.setInstrument(1, normalInstrument);
925+
926+
// Add note to Track 0 (should NOT be transposed)
927+
const Position pos0 = { 0, 0, 0, 0, 0 };
928+
song.noteDataAtPosition(pos0)->setAsNoteOn(60, 100);
929+
930+
// Add note to Track 1 (should be transposed)
931+
const Position pos1 = { 0, 1, 0, 0, 0 };
932+
song.noteDataAtPosition(pos1)->setAsNoteOn(60, 100);
933+
934+
// Transpose pattern by 1 semitone
935+
const auto changes = song.transposePattern({ 0, 0, 0, 0, 0 }, 1);
936+
937+
// Check results
938+
// pos0 (Drum Track) should NOT be in changes
939+
const auto it0 = std::find_if(changes.begin(), changes.end(), [&](auto && change) {
940+
return change.position == pos0;
941+
});
942+
QVERIFY(it0 == changes.end());
943+
944+
// pos1 (Normal Track) SHOULD be in changes
945+
const auto it1 = std::find_if(changes.begin(), changes.end(), [&](auto && change) {
946+
return change.position == pos1;
947+
});
948+
QVERIFY(it1 != changes.end());
949+
QCOMPARE(it1->newNoteData.note().value(), 61);
950+
}
951+
911952
void SongTest::test_duration_skippedPattern_shouldReturnCorrectDuration()
912953
{
913954
Song song;

0 commit comments

Comments
 (0)