tracktion-engine 3.0-10-g034fdde4aa5
Tracktion Engine — High level data model for audio applications

« « « Anklang Documentation
Loading...
Searching...
No Matches
tracktion_MidiClip.h
Go to the documentation of this file.
1 /*
2 ,--. ,--. ,--. ,--.
3 ,-' '-.,--.--.,--,--.,---.| |,-.,-' '-.`--' ,---. ,--,--, Copyright 2024
4 '-. .-'| .--' ,-. | .--'| /'-. .-',--.| .-. || \ Tracktion Software
5 | | | | \ '-' \ `--.| \ \ | | | |' '-' '| || | Corporation
6 `---' `--' `--`--'`---'`--'`--' `---' `--' `---' `--''--' www.tracktion.com
7
8 Tracktion Engine uses a GPL/commercial licence - see LICENCE.md for details.
9*/
10
11namespace tracktion { inline namespace engine
12{
13
14//==============================================================================
17class MidiClip : public Clip
18{
19public:
20 //==============================================================================
21 MidiClip() = delete;
23 ~MidiClip() override;
24
26
27 void cloneFrom (Clip*) override;
28
29 AudioTrack* getAudioTrack() const;
30
31 //==============================================================================
32 MidiList& getSequence() const noexcept;
33 MidiList& getSequenceLooped();
34 std::unique_ptr<MidiList> createSequenceLooped (MidiList& sourceSequence);
35
36 const SelectedMidiEvents* getSelectedEvents() const { return selectedEvents; }
37
38 //==============================================================================
43 void setUsesProxy (bool canUseProxy) noexcept { proxyAllowed = canUseProxy; }
44
46 bool canUseProxy() const noexcept { return proxyAllowed; }
47
48 //==============================================================================
52 void setUsesGlobalLaunchQuatisation (bool useGlobal) override { useClipLaunchQuantisation = ! useGlobal; }
54 bool usesGlobalLaunchQuatisation() override { return ! useClipLaunchQuantisation; }
58 FollowActions* getFollowActions() override;
59
60 //==============================================================================
61 void scaleVerticallyToFit();
62
63 bool hasValidSequence() const noexcept { return channelSequence.size() > 0; }
64
65 MidiChannel getMidiChannel() const { return hasValidSequence() ? getSequence().getMidiChannel() : MidiChannel(); }
66 void setMidiChannel (MidiChannel newChannel) { getSequence().setMidiChannel (newChannel); }
67
69 void setMPEMode (bool shouldUseMPE) { mpeMode = shouldUseMPE; }
70 bool getMPEMode() const noexcept { return mpeMode; }
71
73 bool isRhythm() const noexcept { return getMidiChannel().getChannelNumber() == 10; }
74
75 //==============================================================================
76 QuantisationType& getQuantisation() const noexcept { return *quantisation; }
77 void setQuantisation (const QuantisationType& newType);
78
79 juce::String getGrooveTemplate() const noexcept { return grooveTemplate; }
80 void setGrooveTemplate (const juce::String& templateName) { grooveTemplate = templateName; }
81
82 bool usesGrooveStrength() const;
83
84 float getGrooveStrength() const { return grooveStrength; }
85 void setGrooveStrength (float g) { grooveStrength = juce::jlimit (0.0f, 1.0f, g); }
86
87 //==============================================================================
89
91
93 void extendStart (TimePosition newStartTime);
94
95 void trimBeyondEnds (bool beyondStart, bool beyondEnd, juce::UndoManager*);
96
102 void legatoNote (MidiNote& note, const juce::Array<MidiNote*>& notesToUse,
103 BeatPosition maxEndBeat, juce::UndoManager&);
104
105 //==============================================================================
106 float getVolumeDb() const { return level->dbGain.get(); }
107 void setVolumeDb (float v) { level->dbGain = juce::jlimit (-100.0f, 0.0f, v); }
108
109 bool isSendingBankChanges() const noexcept { return sendBankChange; }
110 void setSendingBankChanges (bool sendBank);
111
112 bool isMuted() const override { return level->mute.get(); }
113 void setMuted (bool m) override { level->mute = m; }
114
115 LiveClipLevel getLiveClipLevel();
116
117 //==============================================================================
118 void initialise() override;
119 bool isMidi() const override { return true; }
120 void rescale (TimePosition pivotTimeInEdit, double factor) override;
121 bool canBeAddedTo (ClipOwner&) override;
123 juce::Colour getDefaultColour() const override;
124
125 void clearTakes() override;
126 bool hasAnyTakes() const override { return channelSequence.size() > 1; }
127 int getNumTakes (bool includeComps) override;
128 juce::StringArray getTakeDescriptions() const override;
129 void setCurrentTake (int takeIndex) override;
130 int getCurrentTake() const override { return currentTake; }
131 bool isCurrentTakeComp() override;
132 void deleteAllUnusedTakesConfirmingWithUser();
133 Clip::Array unpackTakes (bool toNewTracks) override;
134 MidiList* getTakeSequence (int takeIndex) const { return channelSequence[takeIndex]; }
135
136 bool canLoop() const override { return true; }
137 bool isLooping() const override { return loopLengthBeats > BeatDuration(); }
138 bool beatBasedLooping() const override { return isLooping(); }
139 void setNumberOfLoops (int) override;
140 void disableLooping() override;
141 void setLoopRange (TimeRange) override;
142 void setLoopRangeBeats (BeatRange) override;
143 BeatPosition getLoopStartBeats() const override { return loopStartBeats; }
144 BeatDuration getLoopLengthBeats() const override { return loopLengthBeats; }
145 TimePosition getLoopStart() const override;
146 TimeDuration getLoopLength() const override;
147
153
154 juce::CachedValue<LoopedSequenceType> loopedSequenceType;
155
156 MidiCompManager& getCompManager();
157
158 //==============================================================================
160 void pitchTempoTrackChanged() override;
161
162 //==============================================================================
173
174protected:
175 void valueTreePropertyChanged (juce::ValueTree&, const juce::Identifier&) override;
176 void valueTreeChildAdded (juce::ValueTree&, juce::ValueTree&) override;
177 void valueTreeChildRemoved (juce::ValueTree&, juce::ValueTree&, int) override;
178
179private:
180 //==============================================================================
181 friend class MidiNote;
182
183 //==============================================================================
184 juce::OwnedArray<MidiList> channelSequence;
187 juce::CachedValue<bool> useClipLaunchQuantisation;
188 std::unique_ptr<LaunchQuantisation> launchQuantisation;
189 std::unique_ptr<FollowActions> followActions;
190
191 juce::CachedValue<int> proxyAllowed, currentTake;
192 juce::CachedValue<float> grooveStrength;
193 juce::CachedValue<BeatPosition> loopStartBeats;
194 juce::CachedValue<BeatDuration> loopLengthBeats, originalLength;
196 juce::CachedValue<bool> sendPatch, sendBankChange, mpeMode;
197 juce::CachedValue<juce::String> grooveTemplate;
198
199 bool shouldWarnAboutMultiChannel = false;
200 SelectedMidiEvents* selectedEvents = nullptr;
201
202 mutable std::unique_ptr<MidiList> cachedLoopedSequence;
203 MidiCompManager::Ptr midiCompManager;
204
205 //==============================================================================
206 void setSelectedEvents (SelectedMidiEvents* events) { selectedEvents = events; }
207
208 //==============================================================================
209 MidiList* getMidiListForState (const juce::ValueTree&);
210 void clearCachedLoopSequence();
211
212 //==============================================================================
214};
215
216
217//==============================================================================
218//==============================================================================
226void mergeInMidiSequence (MidiClip&, juce::MidiMessageSequence, TimeDuration offsetToApply,
228
229
230}} // namespace tracktion { inline namespace engine
231
232namespace juce
233{
234 template <>
235 struct VariantConverter<tracktion::engine::MidiClip::LoopedSequenceType>
236 {
237 static tracktion::engine::MidiClip::LoopedSequenceType fromVar (const var& v) { return (tracktion::engine::MidiClip::LoopedSequenceType) static_cast<int> (v); }
238 static var toVar (tracktion::engine::MidiClip::LoopedSequenceType v) { return static_cast<int> (v); }
239 };
240}
Base class for items that can contain clips.
A clip in an edit.
bool usesGlobalLaunchQuatisation() override
Some clip types can be launched, if that's possible, this returns whether the clip's quantisation or ...
void pitchTempoTrackChanged() override
Called when there are pitch or tempo changes made which might require clips to adjust timing informat...
TimeDuration getLoopLength() const override
Returns the length of loop in seconds.
BeatPosition getLoopStartBeats() const override
Returns the beat position of the loop start point.
PatternGenerator * getPatternGenerator() override
Returns the PatternGenerator for this clip if it has one.
TimePosition getLoopStart() const override
Returns the start time of the loop start point.
@ loopRangeDefinesAllRepetitions
The looped sequence is the same for all repetitions including the first.
@ loopRangeDefinesSubsequentRepetitions
The first section is the whole sequence, subsequent repitions are determined by the loop range.
bool isMuted() const override
Returns true if the clip is muted.
BeatDuration getLoopLengthBeats() const override
Returns the length of loop in beats.
LaunchQuantisation * getLaunchQuantisation() override
Some clip types can be launched, if that's possible, this returns a quantisation that can be used for...
void setLoopRange(TimeRange) override
Sets the loop range the clip should use in seconds.
int getNumTakes(bool includeComps) override
Returns the total number of takes.
void setUsesProxy(bool canUseProxy) noexcept
Can be used to disable proxy sequence generation for this clip.
void extendStart(TimePosition newStartTime)
This will extend the start time backwards, moving the notes along if this takes the offset below 0....
juce::Colour getDefaultColour() const override
Returns the default colour for this clip.
bool isLooping() const override
Returns true if this clip is currently looping.
void setMuted(bool m) override
Mutes or unmutes the clip.
void initialise() override
Initialises the Clip.
void clearTakes() override
Clears any takes this clip has.
bool canLoop() const override
Returns true if this clip is capable of looping.
void rescale(TimePosition pivotTimeInEdit, double factor) override
stretches and scales this clip relative to a fixed point in the edit.
int getCurrentTake() const override
Returns the current take index.
void setMPEMode(bool shouldUseMPE)
Sets whether the clip should send MPE MIDI rather than single channel.
bool isRhythm() const noexcept
Returns true if this clip represents a rhythm instrument (e.g.
FollowActions * getFollowActions() override
Some clip types can be launched, if that's possible, this can be used to determine the action to perf...
bool isMidi() const override
Returns true if this is a MidiClip.
void disableLooping() override
Disables all looping.
void setUsesGlobalLaunchQuatisation(bool useGlobal) override
Some clip types can be launched, if that's possible, this sets whether the clip's quantisation or the...
std::shared_ptr< LaunchHandle > getLaunchHandle() override
Some clip types can be launched, if that's possible, this returns a handle to trigger starting/stoppi...
bool canBeAddedTo(ClipOwner &) override
Tests whether this clip can go on the given parent.
bool canUseProxy() const noexcept
Retuns true if this clip can use a proxy sequence.
void cloneFrom(Clip *) override
Clones the given clip to this clip.
Clip::Array unpackTakes(bool toNewTracks) override
Attempts to unpack the takes to new clips.
void setLoopRangeBeats(BeatRange) override
Sets the loop range the clip should use in beats.
bool beatBasedLooping() const override
Returns true if this clip's looping is based on beats or false if absolute time.
void legatoNote(MidiNote &note, const juce::Array< MidiNote * > &notesToUse, BeatPosition maxEndBeat, juce::UndoManager &)
Lengthens or shortens a note to match the start of the next note in the given array.
juce::StringArray getTakeDescriptions() const override
Returns the descriptions of any takes.
juce::String getSelectableDescription() override
Subclasses must return a description of what they are.
void setCurrentTake(int takeIndex) override
Sets a given take index to be the current take.
bool isCurrentTakeComp() override
Returns true if the current take is a comp.
void setNumberOfLoops(int) override
Sets the clip looping a number of times.
bool hasAnyTakes() const override
Returns true if this clip has any takes.
MidiChannel getMidiChannel() const
Gets the list's midi channel number.
void setMidiChannel(MidiChannel chanNum)
Gives the list a channel number that it'll use when generating real midi messages.
Represents a set of selected MIDI notes.
T is_pointer_v
#define JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(className)
Type jlimit(Type lowerLimit, Type upperLimit, Type valueToConstrain) noexcept
void mergeInMidiSequence(MidiClip &mc, juce::MidiMessageSequence ms, TimeDuration startTime, MidiList::NoteAutomationType automationType)
Copies a zero-time origin based MIDI sequence in to a MidiClip.
Represents a duration in beats.
Represents a position in beats.
Represents a duration in real-life time.
Represents a position in real-life time.
ID for objects of type EditElement - e.g.
Provides a thread-safe way to share a clip's levels with an audio engine without worrying about the C...
Represents a MIDI channel 1-16, and also contains extra ID bits to encode info about the event's orig...
Temporarily limits the notes to use.