| name | tracktion-engine |
| description | Work with Tracktion Engine audio DAW framework. Use when creating/manipulating Edits, Tracks, Clips, Plugins, or Transport control. Covers the core model, playback, and plugin hosting patterns. |
Tracktion Engine
Tracktion Engine is the audio engine powering MAGDA. This skill covers core patterns for working with the API.
Core Object Hierarchy
Engine (singleton, app lifecycle)
└── Edit (project/session)
├── TrackList
│ ├── AudioTrack (contains clips + plugins)
│ ├── FolderTrack (groups other tracks)
│ ├── MasterTrack
│ └── TempoTrack, ChordTrack, MarkerTrack...
├── TransportControl (playback/recording)
├── PluginList (master plugins)
└── UndoManager
Quick Reference
Creating an Edit
#include <tracktion_engine/tracktion_engine.h>
namespace te = tracktion;
te::Engine engine("MAGDA");
auto edit = te::Edit::createSingleTrackEdit(engine);
te::Edit::Options options;
options.editState = valueTree;
options.engine = &engine;
auto edit = te::Edit::createEdit(options);
Working with Tracks
for (auto track : edit->getTrackList()) {
DBG(track->getName());
}
auto track = edit->insertNewAudioTrack(
te::TrackInsertPoint::getEndOfTracks(*edit),
nullptr,
true
);
for (auto audioTrack : te::getAudioTracks(*edit)) {
}
track->setName("Lead Vocal");
track->setMuted(true);
track->setSolo(true);
Working with Clips
auto midiClip = track->insertMIDIClip(
te::TimeRange { 0_tp, 8_tp },
nullptr
);
auto audioClip = track->insertWaveClip(
"My Audio",
juce::File("/path/to/audio.wav"),
te::ClipPosition { { 0_tp, 8_tp }, {} },
te::DeleteExistingClips::no
);
for (auto clip : track->getClips()) {
auto pos = clip->getPosition();
DBG("Clip: " + clip->getName() + " at " + juce::String(pos.getStart().inSeconds()));
}
clip->setPosition(te::ClipPosition { { 2_tp, 10_tp }, {} });
clip->setName("Verse 1");
clip->setMuted(true);
MIDI Editing
if (auto midiClip = dynamic_cast<te::MidiClip*>(clip)) {
auto& sequence = midiClip->getSequence();
sequence.addNote(
60,
0.0,
1.0,
100,
0,
nullptr
);
for (auto note : sequence.getNotes()) {
DBG("Note: " + juce::String(note->getNoteNumber()));
}
}
Transport Control
auto& transport = edit->getTransport();
transport.play(false);
transport.stop(false, false);
transport.playFromStart(false);
transport.setPosition(te::TimePosition::fromSeconds(10.0));
auto pos = transport.getPosition();
transport.record(false);
transport.stopRecording(false);
transport.setLoopRange(te::TimeRange { 0_tp, 16_tp });
if (transport.isPlaying()) { }
if (transport.isRecording()) { }
Plugin Management
auto& plugins = track->getPlugins();
if (auto vol = track->getVolumePlugin()) {
vol->setVolumeDb(-6.0f);
vol->setPan(-0.5f);
}
auto eqs = plugins.getPluginsOfType<te::EqualiserPlugin>();
for (auto plugin : plugins) {
if (plugin->isEnabled()) {
DBG("Plugin: " + plugin->getName());
}
}
for (auto param : plugin->getAutomatableParameters()) {
DBG("Param: " + param->getParameterName());
}
Important Patterns
RAII Helpers
{
te::TransportControl::ReallocationInhibitor inhibitor(transport);
}
{
te::Edit::UndoTransactionInhibitor inhibitor(*edit);
}
{
te::TransportControl::ScopedPlaybackRestarter restarter(transport);
transport.stop(false, false);
}
Time Types
te::TimePosition pos = te::TimePosition::fromSeconds(5.0);
te::TimePosition pos2 = 5_tp;
te::TimeDuration dur = te::TimeDuration::fromSeconds(2.0);
te::BeatPosition beat = te::BeatPosition::fromBeats(4.0);
te::TimeRange range { startPos, endPos };
Edit State & Undo
edit->undo();
edit->redo();
if (edit->hasChangedSinceSaved()) {
}
edit->resetChangedStatus();
edit->flushState();
juce::ValueTree state = edit->state;
Listeners
struct MyListener : te::TransportControl::Listener {
void playbackContextChanged() override { }
void recordingStarted(te::SyncPoint, std::optional<te::TimeRange>) override { }
void recordingFinished(te::InputDeviceInstance&, te::EditItemID, te::Clip::Array) override { }
};
transport.addListener(&myListener);
Common Pitfalls
- Always initialize Engine first - Before creating any Edit
- Don't block audio thread - Use AsyncUpdater for UI updates from audio callbacks
- Use inhibitors for batch operations - Prevents expensive graph rebuilds
- Check for nullptr -
getVolumePlugin() etc. can return nullptr
- TimePosition vs BeatPosition - They're different types, convert explicitly
File Locations
Key headers in third_party/tracktion_engine/modules/tracktion_engine/:
model/edit/tracktion_Edit.h - Edit class
model/tracks/tracktion_Track.h - Track base class
model/clips/tracktion_Clip.h - Clip base class
playback/tracktion_TransportControl.h - Transport
plugins/tracktion_Plugin.h - Plugin base class