Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion include/BBTrackContainer.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class EXPORT BBTrackContainer : public TrackContainer
return "bbtrackcontainer";
}

tact_t lengthOfBB( int _bb );
tact_t lengthOfBB( int _bb ) const;
inline tact_t lengthOfCurrentBB()
{
return lengthOfBB( currentBB() );
Expand All @@ -62,6 +62,7 @@ class EXPORT BBTrackContainer : public TrackContainer
void fixIncorrectPositions();
void createTCOsForBB( int _bb );

AutomatedValueMap automatedValuesAt(MidiTime time, int tcoNum) const override;

public slots:
void play();
Expand Down
5 changes: 3 additions & 2 deletions include/Song.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,8 @@ class EXPORT Song : public TrackContainer
return m_globalAutomationTrack;
}

static AutomatedValueMap automatedValuesAt(const Track::tcoVector& tcos, MidiTime time);
//TODO: Add Q_DECL_OVERRIDE when Qt4 is dropped
AutomatedValueMap automatedValuesAt(MidiTime time, int tcoNum = -1) const;

// file management
void createNewProject();
Expand Down Expand Up @@ -326,7 +327,7 @@ private slots:

void removeAllControllers();

void processAutomations(const TrackList& tracks, MidiTime timeStart, fpp_t frames, int tcoNum);
void processAutomations(const TrackList& tracks, MidiTime timeStart, fpp_t frames);

AutomationTrack * m_globalAutomationTrack;

Expand Down
3 changes: 3 additions & 0 deletions include/TrackContainer.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,14 @@ class EXPORT TrackContainer : public Model, public JournallingObject
return m_TrackContainerType;
}

virtual AutomatedValueMap automatedValuesAt(MidiTime time, int tcoNum = -1) const;

signals:
void trackAdded( Track * _track );

protected:
static AutomatedValueMap automatedValuesFromTracks(const TrackList &tracks, MidiTime timeStart, int tcoNum = -1);

mutable QReadWriteLock m_tracksMutex;

private:
Expand Down
16 changes: 15 additions & 1 deletion src/core/BBTrackContainer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ void BBTrackContainer::updateAfterTrackAdd()



tact_t BBTrackContainer::lengthOfBB( int _bb )
tact_t BBTrackContainer::lengthOfBB( int _bb ) const
{
MidiTime max_length = MidiTime::ticksPerTact();

Expand Down Expand Up @@ -239,6 +239,20 @@ void BBTrackContainer::createTCOsForBB( int _bb )
}
}

AutomatedValueMap BBTrackContainer::automatedValuesAt(MidiTime time, int tcoNum) const
{
Q_ASSERT(tcoNum >= 0);
Q_ASSERT(time.getTicks() >= 0);

auto length_tacts = lengthOfBB(tcoNum);
auto length_ticks = length_tacts * MidiTime::ticksPerTact();
if (time > length_ticks) {
time = length_ticks;
}

return TrackContainer::automatedValuesAt(time + (MidiTime::ticksPerTact() * tcoNum), tcoNum);
}




Expand Down
102 changes: 32 additions & 70 deletions src/core/Song.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@ void Song::processNextBuffer()

if( ( f_cnt_t ) currentFrame == 0 )
{
processAutomations(trackList, m_playPos[m_playMode], framesToPlay, tcoNum);
processAutomations(trackList, m_playPos[m_playMode], framesToPlay);

// loop through all tracks and play them
for( int i = 0; i < trackList.size(); ++i )
Expand All @@ -401,58 +401,45 @@ void Song::processNextBuffer()
}
}

void Song::processAutomations(const TrackList &tracklist, MidiTime timeStart, fpp_t frames, int tcoNum)

void Song::processAutomations(const TrackList &tracklist, MidiTime timeStart, fpp_t)
{
QVector<AutomationTrack*> tracks;
AutomatedValueMap values;

if(m_playMode == Mode_PlaySong)
{
tracks << m_globalAutomationTrack;
}
for( Track* track : tracklist)
{
if (track->type() == Track::AutomationTrack || track->type() == Track::HiddenAutomationTrack)
{
tracks << dynamic_cast<AutomationTrack*>(track);
}
}
std::remove_if(tracks.begin(), tracks.end(), std::mem_fn(&Track::isMuted));
QSet<const AutomatableModel*> recordedModels;

Track::tcoVector tcos;
AutomatedValueMap values;
TrackContainer* container = this;
int tcoNum = -1;

if (tcoNum < 0)
switch (m_playMode)
{
// Collect all relevant patterns, sorted by start position
MidiTime timeEnd = timeStart + static_cast<int>(frames / Engine::framesPerTick());
for (AutomationTrack* track: tracks)
{
track->getTCOsInRange(tcos, 0, timeEnd);
}

values = automatedValuesAt(tcos, timeStart);
}
else
case Mode_PlaySong:
break;
case Mode_PlayBB:
{
if (tracklist.size() != 1)
{
qWarning() << "processAutomations called with specified tcoNum but not exactly one track";
}
Q_ASSERT(tracklist.size() == 1);
Q_ASSERT(tracklist.at(0)->type() == Track::BBTrack);
auto bbTrack = dynamic_cast<BBTrack*>(tracklist.at(0));
auto bbContainer = Engine::getBBTrackContainer();
container = bbContainer;
tcoNum = bbTrack->index();
}
break;
default:
return;
}

for (AutomationTrack* track: tracks)
{
TrackContentObject* tco = track->getTCO(tcoNum);
auto p = dynamic_cast<AutomationPattern *>(tco);
values = container->automatedValuesAt(timeStart, tcoNum);
TrackList tracks = container->tracks();

for (AutomatableModel* object : p->objects())
{
values[object] = p->valueAt(timeStart);
}
tcos << tco;
Track::tcoVector tcos;
for (Track* track : tracks)
{
if (track->type() == Track::AutomationTrack) {
track->getTCOsInRange(tcos, 0, timeStart);
}
}

QSet<const AutomatableModel*> recordedModels;
// Process recording
for (TrackContentObject* tco : tcos)
{
Expand Down Expand Up @@ -849,35 +836,10 @@ AutomationPattern * Song::tempoAutomationPattern()
return AutomationPattern::globalAutomationPattern( &m_tempoModel );
}

AutomatedValueMap Song::automatedValuesAt(const Track::tcoVector &tcos, MidiTime time)
{
AutomatedValueMap valueMap;

for(TrackContentObject* tco : tcos)
{
if (tco->isMuted() || tco->startPosition() > time) {
continue;
}
AutomationPattern* p = dynamic_cast<AutomationPattern *>(tco);
if (!p) {
qCritical() << "automatedValuesAt: tco passed is not an automation pattern";
continue;
}

if (! p->hasAutomation()) {
continue;
}

MidiTime relTime = time - p->startPosition();
float value = p->valueAt(relTime);

for (AutomatableModel* model : p->objects())
{
valueMap[model] = value;
}
}

return valueMap;
AutomatedValueMap Song::automatedValuesAt(MidiTime time, int tcoNum) const
{
return TrackContainer::automatedValuesFromTracks(TrackList(tracks()) << m_globalAutomationTrack, time, tcoNum);
}


Expand Down
87 changes: 85 additions & 2 deletions src/core/TrackContainer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,16 @@
#include <QDomElement>
#include <QWriteLocker>

#include "AutomationPattern.h"
#include "AutomationTrack.h"
#include "BBTrack.h"
#include "BBTrackContainer.h"
#include "TrackContainer.h"
#include "InstrumentTrack.h"
#include "GuiApplication.h"
#include "MainWindow.h"
#include "Song.h"

#include "GuiApplication.h"
#include "MainWindow.h"

TrackContainer::TrackContainer() :
Model( NULL ),
Expand Down Expand Up @@ -234,6 +238,85 @@ bool TrackContainer::isEmpty() const



AutomatedValueMap TrackContainer::automatedValuesAt(MidiTime time, int tcoNum) const
{
return automatedValuesFromTracks(tracks(), time, tcoNum);
}


AutomatedValueMap TrackContainer::automatedValuesFromTracks(const TrackList &tracks, MidiTime time, int tcoNum)
{
Track::tcoVector tcos;

for (Track* track: tracks)
{
if (track->isMuted()) {
continue;
}

switch(track->type())
{
case Track::AutomationTrack:
case Track::HiddenAutomationTrack:
case Track::BBTrack:
if (tcoNum < 0) {
track->getTCOsInRange(tcos, 0, time);
} else {
Q_ASSERT(track->numOfTCOs() > tcoNum);
tcos << track->getTCO(tcoNum);
}
default:
break;
}
}

AutomatedValueMap valueMap;

Q_ASSERT(std::is_sorted(tcos.begin(), tcos.end(), TrackContentObject::comparePosition));

for(TrackContentObject* tco : tcos)
{
if (tco->isMuted() || tco->startPosition() > time) {
continue;
}

if (auto* p = dynamic_cast<AutomationPattern *>(tco))
{
if (! p->hasAutomation()) {
continue;
}
MidiTime relTime = time - p->startPosition();
float value = p->valueAt(relTime);

for (AutomatableModel* model : p->objects())
{
valueMap[model] = value;
}
}
else if (auto* bb = dynamic_cast<BBTCO *>(tco))
{
auto bbIndex = dynamic_cast<class BBTrack*>(bb->getTrack())->index();
auto bbContainer = Engine::getBBTrackContainer();

MidiTime bbTime = time - tco->startPosition();
bbTime = std::min(bbTime, tco->length());
bbTime = bbTime % (bbContainer->lengthOfBB(bbIndex) * MidiTime::ticksPerTact());

auto bbValues = bbContainer->automatedValuesAt(bbTime, bbIndex);
for (auto it=bbValues.begin(); it != bbValues.end(); it++)
{
// override old values, bb track with the highest index takes precedence
valueMap[it.key()] = it.value();
}
}
else
{
continue;
}
}

return valueMap;
};



Expand Down
Loading