Audacity 3.2.0
Public Types | Public Member Functions | Static Public Member Functions | Private Types | Private Member Functions | Private Attributes | Static Private Attributes | List of all members
NoteTrack Class Referencefinal

A Track that is used for Midi notes. (Somewhat old code). More...

#include <NoteTrack.h>

Inheritance diagram for NoteTrack:
[legend]
Collaboration diagram for NoteTrack:
[legend]

Public Types

using Holder = std::shared_ptr< NoteTrack >
 
- Public Types inherited from Track
enum class  LinkType : int { None = 0 , Group = 2 , Aligned }
 For two tracks describes the type of the linkage. More...
 
using ChannelGroupAttachments = ClientData::Site< ChannelGroupData, ClientData::Cloneable<>, ClientData::DeepCopying >
 Hosting of objects attached by higher level code. More...
 
using AttachedObjects = ::AttachedTrackObjects
 Alias for my base type. More...
 
using IntervalData = TrackIntervalData
 
using Interval = TrackInterval
 
using Intervals = std::vector< Interval >
 
using ConstInterval = ConstTrackInterval
 
using ConstIntervals = std::vector< ConstInterval >
 
using Holder = std::shared_ptr< Track >
 
template<typename R = void>
using Continuation = std::function< R() >
 Type of arguments passed as optional second parameter to TypeSwitch() cases. More...
 
using Fallthrough = Continuation<>
 Type of arguments passed as optional second parameter to TypeSwitch<void>() cases. More...
 
- Public Types inherited from ClientData::Site< Host, ClientData, ObjectCopyingPolicy, Pointer, ObjectLockingPolicy, RegistryLockingPolicy >
using DataType = ClientData
 
using DataPointer = Pointer< ClientData >
 
using DataFactory = std::function< DataPointer(Host &) >
 Type of function from which RegisteredFactory is constructed; it builds attachments. More...
 

Public Member Functions

 NoteTrack ()
 
 NoteTrack (const NoteTrack &orig, ProtectedCreationArg &&)=delete
 Copy construction hasn't been necessary yet. More...
 
virtual ~NoteTrack ()
 
double GetOffset () const override
 
double GetStartTime () const override
 
double GetEndTime () const override
 
Alg_seq & GetSeq () const
 
void WarpAndTransposeNotes (double t0, double t1, const TimeWarper &warper, double semitones)
 
int FindChannel (const wxRect &rect, int mx, int my)
 
bool LabelClick (const wxRect &rect, int x, int y, bool right)
 
void SetSequence (std::unique_ptr< Alg_seq > &&seq)
 
void PrintSequence ()
 
Alg_seq * MakeExportableSeq (std::unique_ptr< Alg_seq > &cleanup) const
 
bool ExportMIDI (const wxString &f) const
 
bool ExportAllegro (const wxString &f) const
 
Track::Holder Cut (double t0, double t1) override
 
Track::Holder Copy (double t0, double t1, bool forClipboard=true) const override
 
bool Trim (double t0, double t1)
 
void Clear (double t0, double t1) override
 
void Paste (double t, const Track *src) override
 
void Silence (double t0, double t1) override
 
void InsertSilence (double t, double len) override
 
bool Shift (double t)
 
QuantizedTimeAndBeat NearestBeatTime (double time) const
 
bool StretchRegion (QuantizedTimeAndBeat t0, QuantizedTimeAndBeat t1, double newDur)
 
int GetBottomNote () const
 Gets the current bottom note (a pitch) More...
 
int GetTopNote () const
 Gets the current top note (a pitch) More...
 
void SetBottomNote (int note)
 Sets the bottom note (a pitch), making sure that it is never greater than the top note. More...
 
void SetTopNote (int note)
 Sets the top note (a pitch), making sure that it is never less than the bottom note. More...
 
void SetNoteRange (int note1, int note2)
 Sets the top and bottom note (both pitches) automatically, swapping them if needed. More...
 
void ZoomAllNotes ()
 Zooms so that all notes are visible. More...
 
void ZoomMaxExtent ()
 Zooms so that the entire track is visible. More...
 
void ShiftNoteRange (int offset)
 Shifts all notes vertically by the given pitch. More...
 
void ZoomOut (const wxRect &rect, int y)
 Zooms out a constant factor (subject to zoom limits) More...
 
void ZoomIn (const wxRect &rect, int y)
 Zooms in a constant factor (subject to zoom limits) More...
 
void Zoom (const wxRect &rect, int y, float multiplier, bool center)
 
void ZoomTo (const wxRect &rect, int start, int end)
 
bool HandleXMLTag (const std::string_view &tag, const AttributesList &attrs) override
 
XMLTagHandlerHandleXMLChild (const std::string_view &tag) override
 
void WriteXML (XMLWriter &xmlFile) const override
 
unsigned GetVisibleChannels () const
 
void SetVisibleChannels (unsigned value)
 
bool IsVisibleChan (int c) const
 
void SetVisibleChan (int c)
 
void ClearVisibleChan (int c)
 
void ToggleVisibleChan (int c)
 
void SoloVisibleChan (int c)
 
const TypeInfoGetTypeInfo () const override
 
Track::Holder PasteInto (AudacityProject &) const override
 Find or create the destination track for a paste, maybe in a different project. More...
 
ConstIntervals GetIntervals () const override
 Report times on the track where important intervals begin and end, for UI to snap to. More...
 
Intervals GetIntervals () override
 
- Public Member Functions inherited from AudioTrack
 AudioTrack ()
 
 AudioTrack (const Track &orig, ProtectedCreationArg &&a)
 
void WriteXMLAttributes (XMLWriter &WXUNUSED(xmlFile)) const
 
bool HandleXMLAttribute (const std::string_view &, const XMLAttributeValueView &)
 
- Public Member Functions inherited from Track
TrackId GetId () const
 
template<typename Subclass = Track>
std::shared_ptr< Subclass > SharedPointer ()
 
template<typename Subclass = const Track>
auto SharedPointer () const -> std::enable_if_t< std::is_const_v< Subclass >, std::shared_ptr< Subclass > >
 
std::shared_ptr< TrackSubstitutePendingChangedTrack ()
 
std::shared_ptr< const TrackSubstitutePendingChangedTrack () const
 
std::shared_ptr< const TrackSubstituteOriginalTrack () const
 
virtual const TypeInfoGetTypeInfo () const =0
 
virtual const TypeNamesGetTypeNames () const
 
virtual bool SupportsBasicEditing () const
 Whether this track type implements cut-copy-paste; by default, true. More...
 
virtual Holder PasteInto (AudacityProject &) const =0
 Find or create the destination track for a paste, maybe in a different project. More...
 
virtual ConstIntervals GetIntervals () const
 Report times on the track where important intervals begin and end, for UI to snap to. More...
 
virtual Intervals GetIntervals ()
 
virtual bool LinkConsistencyFix (bool doFix=true, bool completeList=true)
 Check consistency of channel groups, and maybe fix it. More...
 
bool LinkConsistencyCheck (bool completeList)
 Do the non-mutating part of consistency fix only and return status. More...
 
bool HasOwner () const
 
std::shared_ptr< TrackListGetOwner () const
 
LinkType GetLinkType () const noexcept
 
bool IsAlignedWithLeader () const
 Returns true if the leader track has link type LinkType::Aligned. More...
 
ChannelGroupDataGetGroupData ()
 
const ChannelGroupDataGetGroupData () const
 
 Track ()
 
 Track (const Track &orig, ProtectedCreationArg &&)
 
Trackoperator= (const Track &orig)=delete
 
virtual ~Track ()
 
void Init (const Track &orig)
 
virtual Holder Duplicate () const
 
const wxString & GetName () const
 Name is always the same for all channels of a group. More...
 
void SetName (const wxString &n)
 
bool GetSelected () const
 Selectedness is always the same for all channels of a group. More...
 
virtual void SetSelected (bool s)
 
void EnsureVisible (bool modifyState=false)
 
virtual double GetOffset () const =0
 
void Offset (double t)
 
virtual void SetOffset (double o)
 
virtual Holder Cut (double WXUNUSED(t0), double WXUNUSED(t1))=0
 
virtual Holder Copy (double WXUNUSED(t0), double WXUNUSED(t1), bool forClipboard=true) const =0
 
virtual void Clear (double WXUNUSED(t0), double WXUNUSED(t1))=0
 
virtual void Paste (double WXUNUSED(t), const Track *WXUNUSED(src))=0
 
virtual void SyncLockAdjust (double oldT1, double newT1)
 
virtual void Silence (double WXUNUSED(t0), double WXUNUSED(t1))=0
 
virtual void InsertSilence (double WXUNUSED(t), double WXUNUSED(len))=0
 
bool SameKindAs (const Track &track) const
 
template<typename R = void, typename ... Functions>
TypeSwitch (const Functions &...functions)
 Use this function rather than testing track type explicitly and making down-casts. More...
 
template<typename R = void, typename ... Functions>
TypeSwitch (const Functions &...functions) const
 Use this function rather than testing track type explicitly and making down-casts. More...
 
virtual void WriteXML (XMLWriter &xmlFile) const =0
 
virtual bool GetErrorOpening ()
 
virtual double GetStartTime () const =0
 
virtual double GetEndTime () const =0
 
void Notify (bool allChannels, int code=-1)
 
bool Any () const
 
bool IsSelected () const
 
bool IsLeader () const
 
bool IsSelectedLeader () const
 
void AdjustPositions ()
 
void WriteCommonXMLAttributes (XMLWriter &xmlFile, bool includeNameAndSelected=true) const
 
bool HandleCommonXMLAttribute (const std::string_view &attr, const XMLAttributeValueView &valueView)
 
- Public Member Functions inherited from XMLTagHandler
 XMLTagHandler ()
 
virtual ~XMLTagHandler ()
 
virtual bool HandleXMLTag (const std::string_view &tag, const AttributesList &attrs)=0
 
virtual void HandleXMLEndTag (const std::string_view &WXUNUSED(tag))
 
virtual void HandleXMLContent (const std::string_view &WXUNUSED(content))
 
virtual XMLTagHandlerHandleXMLChild (const std::string_view &tag)=0
 
void ReadXMLEndTag (const char *tag)
 
void ReadXMLContent (const char *s, int len)
 
XMLTagHandlerReadXMLChild (const char *tag)
 
- Public Member Functions inherited from ClientData::Site< Host, ClientData, ObjectCopyingPolicy, Pointer, ObjectLockingPolicy, RegistryLockingPolicy >
 ~Site ()
 
 Site ()
 
 Site (const Site &other)
 
Siteoperator= (const Site &other)
 
 Site (Site &&other)
 
Siteoperator= (Site &&other)
 
size_t size () const
 How many attachment pointers are in the Site. More...
 
template<typename Subclass = ClientData>
Subclass & Get (const RegisteredFactory &key)
 Get reference to an attachment, creating on demand if not present, down-cast it to Subclass. More...
 
template<typename Subclass = const ClientData>
auto Get (const RegisteredFactory &key) const -> std::enable_if_t< std::is_const< Subclass >::value, Subclass & >
 Get reference to an attachment, creating on demand if not present, down-cast it to Subclass. More...
 
template<typename Subclass = ClientData>
Subclass * Find (const RegisteredFactory &key)
 Get a (bare) pointer to an attachment, or null, down-cast it to Subclass *; will not create on demand. More...
 
template<typename Subclass = const ClientData>
auto Find (const RegisteredFactory &key) const -> std::enable_if_t< std::is_const< Subclass >::value, Subclass * >
 Get a (bare) pointer to an attachment, or null, down-cast it to Subclass *; will not create on demand. More...
 
template<typename ReplacementPointer >
void Assign (const RegisteredFactory &key, ReplacementPointer &&replacement)
 Reassign Site's pointer to ClientData. More...
 

Static Public Member Functions

static NoteTrackNew (AudacityProject &project)
 
static void DrawLabelControls (const NoteTrack *pTrack, wxDC &dc, const wxRect &rect, int highlightedChannel=-1)
 
static const TypeInfoClassTypeInfo ()
 
- Static Public Member Functions inherited from AudioTrack
static const TypeInfoClassTypeInfo ()
 
- Static Public Member Functions inherited from Track
template<typename Subclass = Track>
static std::shared_ptr< Subclass > SharedPointer (Track *pTrack)
 
template<typename Subclass = const Track>
static std::shared_ptr< Subclass > SharedPointer (const Track *pTrack)
 
static const TypeInfoClassTypeInfo ()
 
static void FinishCopy (const Track *n, Track *dest)
 
template<typename TrackType >
static void checkTrackType ()
 
template<typename R , typename TrackType , typename... Functions>
static R CallExecutor (R *, std::tuple<> *, TrackType &, const Functions &...)
 
template<typename R , typename TrackType , typename... Functions, typename Executor , typename... Executors>
static R CallExecutor (R *, std::tuple< Executor, Executors... > *, TrackType &track, const Functions &...functions)
 
template<typename ... Executors>
static constexpr unsigned UsedCases (std::tuple< Executors... > *)
 
template<typename Tag , bool IsConst, typename R , typename ... TrackTypes, typename ... Functions>
static R DoTypeSwitch (std::conditional_t< IsConst, const Track, Track > &track, TypeList::List< TrackTypes... >, const Functions &...functions)
 Deduce two packs from arguments. More...
 
- Static Public Member Functions inherited from ClientData::Site< Host, ClientData, ObjectCopyingPolicy, Pointer, ObjectLockingPolicy, RegistryLockingPolicy >
static size_t slots ()
 How many static factories have been registered with this specialization of Site. More...
 

Private Types

enum  { MinPitch = 0 , MaxPitch = 127 }
 

Private Member Functions

Track::Holder Clone () const override
 
void AddToDuration (double delta)
 

Private Attributes

std::unique_ptr< Alg_seq > mSeq
 
std::unique_ptr< char[]> mSerializationBuffer
 
long mSerializationLength
 
int mBottomNote
 
int mTopNote
 
float mPitchHeight
 
std::atomic< unsigned > mVisibleChannels { ALL_CHANNELS }
 A bit set; atomic because it may be read by worker threads in playback. More...
 
std::weak_ptr< StretchHandlemStretchHandle
 

Static Private Attributes

static const float ZoomStep = powf( 2.0f, 0.25f )
 

Additional Inherited Members

- Public Attributes inherited from Track
std::pair< int, int > vrulerSize
 
- Protected Member Functions inherited from Track
void SetLinkType (LinkType linkType, bool completeList=true)
 
- Protected Member Functions inherited from ClientData::Site< Host, ClientData, ObjectCopyingPolicy, Pointer, ObjectLockingPolicy, RegistryLockingPolicy >
template<typename Function >
void ForEach (const Function &function)
 Invoke function on each ClientData object that has been created in this. More...
 
template<typename Function >
void ForEach (const Function &function) const
 Invoke function on each ClientData object that has been created in this. More...
 
template<typename Function >
ClientData * FindIf (const Function &function)
 Return pointer to first attachment in this that is not null and satisfies a predicate, or nullptr. More...
 
template<typename Function >
const ClientData * FindIf (const Function &function) const
 Return pointer to first attachment in this that is not null and satisfies a predicate, or nullptr. More...
 
void BuildAll ()
 For each RegisteredFactory, if the corresponding attachment is absent in this, build and store it. More...
 
- Protected Attributes inherited from Track
std::weak_ptr< TrackListmList
 
TrackNodePointer mNode {}
 Holds iterator to self, so that TrackList::Find can be constant-time. More...
 
int mIndex
 0-based position of this track in its TrackList More...
 
double mOffset
 

Detailed Description

A Track that is used for Midi notes. (Somewhat old code).

Definition at line 61 of file NoteTrack.h.

Member Typedef Documentation

◆ Holder

using NoteTrack::Holder = std::shared_ptr<NoteTrack>

Definition at line 73 of file NoteTrack.h.

Member Enumeration Documentation

◆ anonymous enum

anonymous enum
private
Enumerator
MinPitch 
MaxPitch 

Definition at line 240 of file NoteTrack.h.

240{ MinPitch = 0, MaxPitch = 127 };

Constructor & Destructor Documentation

◆ NoteTrack() [1/2]

NoteTrack::NoteTrack ( )

Definition at line 122 of file NoteTrack.cpp.

123 : NoteTrackBase()
124{
125 SetName(_("Note Track"));
126
127 mSeq = NULL;
129
132}
#define _(s)
Definition: Internat.h:73
AudioTrack NoteTrackBase
Definition: NoteTrack.h:54
int mTopNote
Definition: NoteTrack.h:230
std::unique_ptr< Alg_seq > mSeq
Definition: NoteTrack.h:221
int mBottomNote
Definition: NoteTrack.h:230
long mSerializationLength
Definition: NoteTrack.h:223
void SetName(const wxString &n)
Definition: Track.cpp:69

References _, MaxPitch, mBottomNote, MinPitch, mSeq, mSerializationLength, mTopNote, and Track::SetName().

Here is the call graph for this function:

◆ NoteTrack() [2/2]

NoteTrack::NoteTrack ( const NoteTrack orig,
ProtectedCreationArg &&   
)
delete

Copy construction hasn't been necessary yet.

◆ ~NoteTrack()

NoteTrack::~NoteTrack ( )
virtual

Definition at line 134 of file NoteTrack.cpp.

135{
136}

Member Function Documentation

◆ AddToDuration()

void NoteTrack::AddToDuration ( double  delta)
private

Definition at line 726 of file NoteTrack.cpp.

727{
728 auto &seq = GetSeq();
729#if 0
730 // PRL: Would this be better ?
731 seq.set_real_dur( seq.get_real_dur() + delta );
732#else
733 seq.convert_to_seconds();
734 seq.set_dur( seq.get_dur() + delta );
735#endif
736}
Alg_seq & GetSeq() const
Definition: NoteTrack.cpp:138

References GetSeq().

Referenced by Paste(), and StretchRegion().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ClassTypeInfo()

auto NoteTrack::ClassTypeInfo ( )
static

Definition at line 699 of file NoteTrack.cpp.

700{
701 return typeInfo();
702}
static const Track::TypeInfo & typeInfo()
Definition: NoteTrack.cpp:686

References typeInfo().

Here is the call graph for this function:

◆ Clear()

void NoteTrack::Clear ( double  t0,
double  t1 
)
override

Definition at line 520 of file NoteTrack.cpp.

521{
522 if (t1 < t0)
524
525 double len = t1-t0;
526
527 auto &seq = GetSeq();
528
529 auto offset = GetOffset();
530 auto start = t0 - offset;
531 if (start < 0.0) {
532 // AlgSeq::clear will shift the cleared interval, not changing len, if
533 // start is negative. That's not what we want to happen.
534 if (len > -start) {
535 seq.clear(0, len + start, false);
536 SetOffset(t0);
537 }
538 else
539 SetOffset(offset - len);
540 }
541 else {
542 //auto delta = -(
543 //( std::min( t1, GetEndTime() ) ) - ( std::max( t0, GetStartTime() ) )
544 //);
545 seq.clear(start, len, false);
546
547 // Not needed
548 // Alg_seq::clear seems to handle this
549 // AddToDuration( delta );
550 }
551}
#define THROW_INCONSISTENCY_EXCEPTION
Throw InconsistencyException, using C++ preprocessor to identify the source code location.
double GetOffset() const override
Definition: NoteTrack.cpp:201
virtual void SetOffset(double o)
Definition: Track.h:404

References GetOffset(), GetSeq(), Track::SetOffset(), and THROW_INCONSISTENCY_EXCEPTION.

Referenced by anonymous_namespace{EditMenus.cpp}::OnCut().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ClearVisibleChan()

void NoteTrack::ClearVisibleChan ( int  c)
inline

Definition at line 187 of file NoteTrack.h.

187 {
188 mVisibleChannels.fetch_and(~CHANNEL_BIT(c), std::memory_order_relaxed); }
#define CHANNEL_BIT(c)
Definition: NoteTrack.h:175
std::atomic< unsigned > mVisibleChannels
A bit set; atomic because it may be read by worker threads in playback.
Definition: NoteTrack.h:244

References CHANNEL_BIT.

◆ Clone()

Track::Holder NoteTrack::Clone ( ) const
overrideprivatevirtual

Implements Track.

Definition at line 160 of file NoteTrack.cpp.

161{
162 auto duplicate = std::make_shared<NoteTrack>();
163 duplicate->Init(*this);
164 // The duplicate begins life in serialized state. Often the duplicate is
165 // pushed on the Undo stack. Then we want to un-serialize it (or a further
166 // copy) only on demand after an Undo.
167 if (mSeq) {
169 wxASSERT(!mSerializationBuffer);
170 // serialize from this to duplicate's mSerializationBuffer
171 void *buffer;
172 mSeq->serialize(&buffer,
173 &duplicate->mSerializationLength);
174 duplicate->mSerializationBuffer.reset( (char*)buffer );
176 }
177 else if (mSerializationBuffer) {
178 // Copy already serialized data.
179 wxASSERT(!mSeq);
180 duplicate->mSerializationLength = this->mSerializationLength;
181 duplicate->mSerializationBuffer.reset
182 ( safenew char[ this->mSerializationLength ] );
183 memcpy( duplicate->mSerializationBuffer.get(),
184 this->mSerializationBuffer.get(), this->mSerializationLength );
185 }
186 else {
187 // We are duplicating a default-constructed NoteTrack, and that's okay
188 }
189 // copy some other fields here
190 duplicate->SetBottomNote(mBottomNote);
191 duplicate->SetTopNote(mTopNote);
192 duplicate->SetVisibleChannels(GetVisibleChannels());
193 duplicate->SetOffset(GetOffset());
194#ifdef EXPERIMENTAL_MIDI_OUT
195 duplicate->SetVelocity(GetVelocity());
196#endif
197 return duplicate;
198}
#define safenew
Definition: MemoryX.h:10
#define SonifyEndSerialize()
Definition: NoteTrack.h:312
#define SonifyBeginSerialize()
Definition: NoteTrack.h:311
std::unique_ptr< char[]> mSerializationBuffer
Definition: NoteTrack.h:222
unsigned GetVisibleChannels() const
Definition: NoteTrack.h:176

References GetOffset(), GetVisibleChannels(), mBottomNote, mSeq, mSerializationBuffer, mSerializationLength, mTopNote, safenew, SonifyBeginSerialize, and SonifyEndSerialize.

Here is the call graph for this function:

◆ Copy()

Track::Holder NoteTrack::Copy ( double  t0,
double  t1,
bool  forClipboard = true 
) const
override

Definition at line 473 of file NoteTrack.cpp.

474{
475 if (t1 < t0)
477
478 double len = t1-t0;
479
480 auto newTrack = std::make_shared<NoteTrack>();
481
482 newTrack->Init(*this);
483
484 auto &seq = GetSeq();
485 seq.convert_to_seconds();
486 newTrack->mSeq.reset(seq.copy(t0 - GetOffset(), len, false));
487 newTrack->SetOffset(0);
488
489 // What should be done with the rest of newTrack's members?
490 // (mBottomNote, mSerializationBuffer,
491 // mSerializationLength, mVisibleChannels)
492
493 return newTrack;
494}

References GetOffset(), GetSeq(), and THROW_INCONSISTENCY_EXCEPTION.

Referenced by anonymous_namespace{EditMenus.cpp}::OnCut().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Cut()

Track::Holder NoteTrack::Cut ( double  t0,
double  t1 
)
override

Definition at line 443 of file NoteTrack.cpp.

444{
445 if (t1 < t0)
447
448 double len = t1-t0;
449 //auto delta = -(
450 //( std::min( t1, GetEndTime() ) ) - ( std::max( t0, GetStartTime() ) )
451 //);
452
453 auto newTrack = std::make_shared<NoteTrack>();
454
455 newTrack->Init(*this);
456
457 auto &seq = GetSeq();
458 seq.convert_to_seconds();
459 newTrack->mSeq.reset(seq.cut(t0 - GetOffset(), len, false));
460 newTrack->SetOffset(0);
461
462 // Not needed
463 // Alg_seq::cut seems to handle this
464 //AddToDuration( delta );
465
466 // What should be done with the rest of newTrack's members?
467 //(mBottomNote,
468 // mSerializationBuffer, mSerializationLength, mVisibleChannels)
469
470 return newTrack;
471}

References GetOffset(), GetSeq(), and THROW_INCONSISTENCY_EXCEPTION.

Referenced by anonymous_namespace{EditMenus.cpp}::OnCut().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ DrawLabelControls()

void NoteTrack::DrawLabelControls ( const NoteTrack pTrack,
wxDC &  dc,
const wxRect &  rect,
int  highlightedChannel = -1 
)
static

Definition at line 254 of file NoteTrack.cpp.

256{
257 dc.SetTextForeground(theTheme.Colour(clrLabelTrackText));
258 wxASSERT_MSG(rect.width % 4 == 0, "Midi channel control rect width must be divisible by 4");
259 wxASSERT_MSG(rect.height % 4 == 0, "Midi channel control rect height must be divisible by 4");
260
261 auto cellWidth = rect.width / 4;
262 auto cellHeight = rect.height / 4;
263
264 wxRect box;
265 for (int row = 0; row < 4; row++) {
266 for (int col = 0; col < 4; col++) {
267 // chanName is the "external" channel number (1-16)
268 // used by AColor and button labels
269 int chanName = row * 4 + col + 1;
270
271 box.x = rect.x + col * cellWidth;
272 box.y = rect.y + row * cellHeight;
273 box.width = cellWidth;
274 box.height = cellHeight;
275
276 bool visible = pTrack ? pTrack->IsVisibleChan(chanName - 1) : true;
277 if (visible) {
278 // highlightedChannel counts 0 based
279 if ( chanName == highlightedChannel + 1 )
280 AColor::LightMIDIChannel(&dc, chanName);
281 else
282 AColor::MIDIChannel(&dc, chanName);
283 dc.DrawRectangle(box);
284// two choices: channel is enabled (to see and play) when button is in
285// "up" position (original Audacity style) or in "down" position
286//
287#define CHANNEL_ON_IS_DOWN 1
288#if CHANNEL_ON_IS_DOWN
289 AColor::DarkMIDIChannel(&dc, chanName);
290#else
291 AColor::LightMIDIChannel(&dc, chanName);
292#endif
293 AColor::Line(dc, box.x, box.y, box.x + box.width - 1, box.y);
294 AColor::Line(dc, box.x, box.y, box.x, box.y + box.height - 1);
295
296#if CHANNEL_ON_IS_DOWN
297 AColor::LightMIDIChannel(&dc, chanName);
298#else
299 AColor::DarkMIDIChannel(&dc, chanName);
300#endif
301 AColor::Line(dc,
302 box.x + box.width - 1, box.y,
303 box.x + box.width - 1, box.y + box.height - 1);
304 AColor::Line(dc,
305 box.x, box.y + box.height - 1,
306 box.x + box.width - 1, box.y + box.height - 1);
307 } else {
308 if ( chanName == highlightedChannel + 1 )
309 AColor::LightMIDIChannel(&dc, chanName);
310 else
311 AColor::MIDIChannel(&dc, 0);
312 dc.DrawRectangle(box);
313#if CHANNEL_ON_IS_DOWN
315#else
317#endif
318 AColor::Line(dc, box.x, box.y, box.x + box.width - 1, box.y);
319 AColor::Line(dc, box.x, box.y, box.x, box.y + box.height - 1);
320
321#if CHANNEL_ON_IS_DOWN
323#else
325#endif
326 AColor::Line(dc,
327 box.x + box.width - 1, box.y,
328 box.x + box.width - 1, box.y + box.height - 1);
329 AColor::Line(dc,
330 box.x, box.y + box.height - 1,
331 box.x + box.width - 1, box.y + box.height - 1);
332
333 }
334
335 wxString text;
336 wxCoord w;
337 wxCoord h;
338
339 text.Printf(wxT("%d"), chanName);
340 dc.GetTextExtent(text, &w, &h);
341
342 dc.DrawText(text, box.x + (box.width - w) / 2, box.y + (box.height - h) / 2);
343 }
344 }
345 dc.SetTextForeground(theTheme.Colour(clrTrackPanelText));
346 AColor::MIDIChannel(&dc, 0); // always return with gray color selected
347}
wxT("CloseDown"))
THEME_API Theme theTheme
Definition: Theme.cpp:82
static void Line(wxDC &dc, wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
Definition: AColor.cpp:187
static void LightMIDIChannel(wxDC *dc, int channel)
Definition: AColor.cpp:681
static void MIDIChannel(wxDC *dc, int channel)
Definition: AColor.cpp:665
static void DarkMIDIChannel(wxDC *dc, int channel)
Definition: AColor.cpp:699
bool IsVisibleChan(int c) const
Definition: NoteTrack.h:182
wxColour & Colour(int iIndex)

References ThemeBase::Colour(), AColor::DarkMIDIChannel(), IsVisibleChan(), AColor::LightMIDIChannel(), AColor::Line(), AColor::MIDIChannel(), theTheme, and wxT().

Referenced by anonymous_namespace{NoteTrackControls.cpp}::MidiControlsDrawFunction().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ExportAllegro()

bool NoteTrack::ExportAllegro ( const wxString &  f) const

Definition at line 891 of file NoteTrack.cpp.

892{
893 double offset = GetOffset();
895 auto &seq = GetSeq();
896 if (in_seconds) {
897 seq.convert_to_seconds();
898 } else {
899 seq.convert_to_beats();
900 }
901 return seq.write(f.mb_str(), offset);
902}
Enum ReadEnum() const
Definition: Prefs.h:527
static EnumSetting< bool > AllegroStyleSetting

References ImportExportPrefs::AllegroStyleSetting, GetOffset(), GetSeq(), and EnumSetting< Enum >::ReadEnum().

Here is the call graph for this function:

◆ ExportMIDI()

bool NoteTrack::ExportMIDI ( const wxString &  f) const

Definition at line 883 of file NoteTrack.cpp.

884{
885 std::unique_ptr<Alg_seq> cleanup;
886 auto seq = MakeExportableSeq(cleanup);
887 bool rslt = seq->smf_write(f.mb_str());
888 return rslt;
889}
Alg_seq * MakeExportableSeq(std::unique_ptr< Alg_seq > &cleanup) const
Definition: NoteTrack.cpp:760

References MakeExportableSeq().

Here is the call graph for this function:

◆ FindChannel()

int NoteTrack::FindChannel ( const wxRect &  rect,
int  mx,
int  my 
)

Definition at line 349 of file NoteTrack.cpp.

350{
351 wxASSERT_MSG(rect.width % 4 == 0, "Midi channel control rect width must be divisible by 4");
352 wxASSERT_MSG(rect.height % 4 == 0, "Midi channel control rect height must be divisible by 4");
353
354 auto cellWidth = rect.width / 4;
355 auto cellHeight = rect.height / 4;
356
357 int col = (mx - rect.x) / cellWidth;
358 int row = (my - rect.y) / cellHeight;
359
360 return row * 4 + col;
361}

Referenced by LabelClick().

Here is the caller graph for this function:

◆ GetBottomNote()

int NoteTrack::GetBottomNote ( ) const
inline

Gets the current bottom note (a pitch)

Definition at line 122 of file NoteTrack.h.

122{ return mBottomNote; }

Referenced by NoteTrackDisplayData::NoteTrackDisplayData().

Here is the caller graph for this function:

◆ GetEndTime()

double NoteTrack::GetEndTime ( ) const
overridevirtual

Implements Track.

Definition at line 211 of file NoteTrack.cpp.

212{
213 return GetStartTime() + GetSeq().get_real_dur();
214}
double GetStartTime() const override
Definition: NoteTrack.cpp:206

References GetSeq(), and GetStartTime().

Referenced by GetIntervals(), and Paste().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetIntervals() [1/2]

auto NoteTrack::GetIntervals ( ) const
overridevirtual

Report times on the track where important intervals begin and end, for UI to snap to.

Some intervals may be empty, and no ordering of the intervals is assumed.

Reimplemented from Track.

Definition at line 712 of file NoteTrack.cpp.

713{
714 ConstIntervals results;
715 results.emplace_back( GetStartTime(), GetEndTime() );
716 return results;
717}
double GetEndTime() const override
Definition: NoteTrack.cpp:211
std::vector< ConstInterval > ConstIntervals
Definition: Track.h:264

References GetEndTime(), and GetStartTime().

Here is the call graph for this function:

◆ GetIntervals() [2/2]

auto NoteTrack::GetIntervals ( )
overridevirtual

This overload exposes the extra data of the intervals as non-const This overload exposes the extra data of the intervals as non-const

Reimplemented from Track.

Definition at line 719 of file NoteTrack.cpp.

720{
721 Intervals results;
722 results.emplace_back( GetStartTime(), GetEndTime() );
723 return results;
724}
std::vector< Interval > Intervals
Definition: Track.h:262

◆ GetOffset()

double NoteTrack::GetOffset ( ) const
overridevirtual

Implements Track.

Definition at line 201 of file NoteTrack.cpp.

202{
203 return mOffset;
204}
double mOffset
Definition: Track.h:372

References Track::mOffset.

Referenced by Clear(), Clone(), Copy(), Cut(), anonymous_namespace{NoteTrackView.cpp}::DrawNoteBackground(), anonymous_namespace{NoteTrackView.cpp}::DrawNoteTrack(), ExportAllegro(), GetStartTime(), InsertSilence(), MakeExportableSeq(), NearestBeatTime(), Paste(), Silence(), Trim(), WarpAndTransposeNotes(), and WriteXML().

Here is the caller graph for this function:

◆ GetSeq()

Alg_seq & NoteTrack::GetSeq ( ) const

Definition at line 138 of file NoteTrack.cpp.

139{
140 if (!mSeq) {
142 mSeq = std::make_unique<Alg_seq>();
143 else {
144 std::unique_ptr<Alg_track> alg_track
145 { Alg_seq::unserialize
147 wxASSERT(alg_track->get_type() == 's');
148 mSeq.reset( static_cast<Alg_seq*>(alg_track.release()) );
149
150 // Preserve the invariant that at most one of the representations is
151 // valid
152 mSerializationBuffer.reset();
154 }
155 }
156 wxASSERT(mSeq);
157 return *mSeq;
158}

References mSeq, mSerializationBuffer, and mSerializationLength.

Referenced by AddToDuration(), Clear(), Copy(), Cut(), anonymous_namespace{NoteTrackView.cpp}::DrawNoteBackground(), anonymous_namespace{NoteTrackView.cpp}::DrawNoteTrack(), ExportAllegro(), GetEndTime(), InsertSilence(), MakeExportableSeq(), NearestBeatTime(), Paste(), Shift(), Silence(), StretchRegion(), Trim(), WarpAndTransposeNotes(), WriteXML(), and ZoomAllNotes().

Here is the caller graph for this function:

◆ GetStartTime()

double NoteTrack::GetStartTime ( ) const
overridevirtual

Implements Track.

Definition at line 206 of file NoteTrack.cpp.

207{
208 return GetOffset();
209}

References GetOffset().

Referenced by GetEndTime(), and GetIntervals().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetTopNote()

int NoteTrack::GetTopNote ( ) const
inline

Gets the current top note (a pitch)

Definition at line 124 of file NoteTrack.h.

124{ return mTopNote; }

Referenced by NoteTrackDisplayData::NoteTrackDisplayData().

Here is the caller graph for this function:

◆ GetTypeInfo()

auto NoteTrack::GetTypeInfo ( ) const
overridevirtual

Implements Track.

Definition at line 694 of file NoteTrack.cpp.

695{
696 return typeInfo();
697}

References typeInfo().

Here is the call graph for this function:

◆ GetVisibleChannels()

unsigned NoteTrack::GetVisibleChannels ( ) const
inline

Definition at line 176 of file NoteTrack.h.

176 {
177 return mVisibleChannels.load(std::memory_order_relaxed);
178 }

Referenced by Clone(), and WriteXML().

Here is the caller graph for this function:

◆ HandleXMLChild()

XMLTagHandler * NoteTrack::HandleXMLChild ( const std::string_view &  tag)
overridevirtual

Implements XMLTagHandler.

Definition at line 953 of file NoteTrack.cpp.

954{
955 return NULL;
956}

◆ HandleXMLTag()

bool NoteTrack::HandleXMLTag ( const std::string_view &  tag,
const AttributesList attrs 
)
overridevirtual

Implements XMLTagHandler.

Definition at line 912 of file NoteTrack.cpp.

913{
914 if (tag == "notetrack") {
915 for (auto pair : attrs)
916 {
917 auto attr = pair.first;
918 auto value = pair.second;
919
920 long nValue;
921 double dblValue;
922 if (this->Track::HandleCommonXMLAttribute(attr, value))
923 ;
924 else if (this->NoteTrackBase::HandleXMLAttribute(attr, value))
925 {}
926 else if (attr == "offset" && value.TryGet(dblValue))
927 SetOffset(dblValue);
928 else if (attr == "visiblechannels") {
929 if (!value.TryGet(nValue) ||
930 !IsValidVisibleChannels(nValue))
931 return false;
932 SetVisibleChannels(nValue);
933 }
934#ifdef EXPERIMENTAL_MIDI_OUT
935 else if (attr == "velocity" && value.TryGet(dblValue))
936 DoSetVelocity(static_cast<float>(dblValue));
937#endif
938 else if (attr == "bottomnote" && value.TryGet(nValue))
939 SetBottomNote(nValue);
940 else if (attr == "topnote" && value.TryGet(nValue))
941 SetTopNote(nValue);
942 else if (attr == "data") {
943 std::string s(value.ToWString());
944 std::istringstream data(s);
945 mSeq = std::make_unique<Alg_seq>(data, false);
946 }
947 } // while
948 return true;
949 }
950 return false;
951}
bool HandleXMLAttribute(const std::string_view &, const XMLAttributeValueView &)
Definition: PlayableTrack.h:32
void SetVisibleChannels(unsigned value)
Definition: NoteTrack.h:179
void SetTopNote(int note)
Sets the top note (a pitch), making sure that it is never less than the bottom note.
Definition: NoteTrack.cpp:1000
void SetBottomNote(int note)
Sets the bottom note (a pitch), making sure that it is never greater than the top note.
Definition: NoteTrack.cpp:988
bool HandleCommonXMLAttribute(const std::string_view &attr, const XMLAttributeValueView &valueView)
Definition: Track.cpp:1165
bool IsValidVisibleChannels(const int nValue)
Definition: NoteTrack.cpp:906

References Track::HandleCommonXMLAttribute(), AudioTrack::HandleXMLAttribute(), anonymous_namespace{NoteTrack.cpp}::IsValidVisibleChannels(), mSeq, SetBottomNote(), Track::SetOffset(), SetTopNote(), and SetVisibleChannels().

Here is the call graph for this function:

◆ InsertSilence()

void NoteTrack::InsertSilence ( double  t,
double  len 
)
override

Definition at line 618 of file NoteTrack.cpp.

619{
620 if (len < 0)
622
623 auto &seq = GetSeq();
624 seq.convert_to_seconds();
625 seq.insert_silence(t - GetOffset(), len);
626
627 // is this needed?
628 // AddToDuration( len );
629}

References GetOffset(), GetSeq(), and THROW_INCONSISTENCY_EXCEPTION.

Referenced by Paste().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ IsVisibleChan()

bool NoteTrack::IsVisibleChan ( int  c) const
inline

Definition at line 182 of file NoteTrack.h.

182 {
183 return (GetVisibleChannels() & CHANNEL_BIT(c)) != 0;
184 }

References CHANNEL_BIT.

Referenced by DrawLabelControls(), anonymous_namespace{NoteTrackView.cpp}::DrawNoteTrack(), and anonymous_namespace{MIDIPlay.h}::Iterator::Unmuted().

Here is the caller graph for this function:

◆ LabelClick()

bool NoteTrack::LabelClick ( const wxRect &  rect,
int  x,
int  y,
bool  right 
)

Definition at line 368 of file NoteTrack.cpp.

369{
370 auto channel = FindChannel(rect, mx, my);
371 if (right)
372 SoloVisibleChan(channel);
373 else
374 ToggleVisibleChan(channel);
375
376 return true;
377}
int FindChannel(const wxRect &rect, int mx, int my)
Definition: NoteTrack.cpp:349
void ToggleVisibleChan(int c)
Definition: NoteTrack.h:189
void SoloVisibleChan(int c)
Definition: NoteTrack.h:193

References FindChannel(), SoloVisibleChan(), and ToggleVisibleChan().

Here is the call graph for this function:

◆ MakeExportableSeq()

Alg_seq * NoteTrack::MakeExportableSeq ( std::unique_ptr< Alg_seq > &  cleanup) const

Definition at line 760 of file NoteTrack.cpp.

761{
762 cleanup.reset();
763 double offset = GetOffset();
764 if (offset == 0)
765 return &GetSeq();
766 // make a copy, deleting events that are shifted before time 0
767 double start = -offset;
768 if (start < 0) start = 0;
769 // notes that begin before "start" are not included even if they
770 // extend past "start" (because "all" parameter is set to false)
771 cleanup.reset( GetSeq().copy(start, GetSeq().get_dur() - start, false) );
772 auto seq = cleanup.get();
773 if (offset > 0) {
774 {
775 // swap cleanup and mSeq so that Shift operates on the NEW copy
776 swap( this->mSeq, cleanup );
777 auto cleanup2 = finally( [&] { swap( this->mSeq, cleanup ); } );
778
779 const_cast< NoteTrack *>( this )->Shift(offset);
780 }
781#ifdef OLD_CODE
782 // now shift events by offset. This must be done with an integer
783 // number of measures, so first, find the beats-per-measure
784 double beats_per_measure = 4.0;
785 Alg_time_sig_ptr tsp = NULL;
786 if (seq->time_sig.length() > 0 && seq->time_sig[0].beat < ALG_EPS) {
787 // there is an initial time signature
788 tsp = &(seq->time_sig[0]);
789 beats_per_measure = (tsp->num * 4) / tsp->den;
790 }
791 // also need the initial tempo
792 double bps = ALG_DEFAULT_BPM / 60;
793 Alg_time_map_ptr map = seq->get_time_map();
794 Alg_beat_ptr bp = &(map->beats[0]);
795 if (bp->time < ALG_EPS) { // tempo change at time 0
796 if (map->beats.len > 1) { // compute slope to get tempo
797 bps = (map->beats[1].beat - map->beats[0].beat) /
798 (map->beats[1].time - map->beats[0].time);
799 } else if (seq->get_time_map()->last_tempo_flag) {
800 bps = seq->get_time_map()->last_tempo;
801 }
802 }
803 // find closest number of measures to fit in the gap
804 // number of measures is offset / measure_time
805 double measure_time = beats_per_measure / bps; // seconds per measure
806 int n = ROUND(offset / measure_time);
807 if (n == 0) n = 1;
808 // we will insert n measures. Compute the desired duration of each.
809 measure_time = offset / n;
810 bps = beats_per_measure / measure_time;
811 // insert integer multiple of measures at beginning
812 seq->convert_to_beats();
813 seq->insert_silence(0, beats_per_measure * n);
814 // make sure time signature at 0 is correct
815 if (tsp) {
816 seq->set_time_sig(0, tsp->num, tsp->den);
817 }
818 // adjust tempo to match offset
819 seq->set_tempo(bps * 60.0, 0, beats_per_measure * n);
820#endif
821 } else {
822 auto &mySeq = GetSeq();
823 // if offset is negative, it might not be a multiple of beats, but
824 // we want to preserve the relative positions of measures. I.e. we
825 // should shift barlines and time signatures as well as notes.
826 // Insert a time signature at the first bar-line if necessary.
827
828 // Translate start from seconds to beats and call it beat:
829 double beat = mySeq.get_time_map()->time_to_beat(start);
830 // Find the time signature in mySeq in effect at start (beat):
831 int i = mySeq.time_sig.find_beat(beat);
832 // i is where you would insert a NEW time sig at beat,
833 // Case 1: beat coincides with a time sig at i. Time signature
834 // at beat means that there is a barline at beat, so when beat
835 // is shifted to 0, the relative barline positions are preserved
836 if (mySeq.time_sig.length() > 0 &&
837 within(beat, mySeq.time_sig[i].beat, ALG_EPS)) {
838 // beat coincides with time signature change, so offset must
839 // be a multiple of beats
840 /* do nothing */ ;
841 // Case 2: there is no time signature before beat.
842 } else if (i == 0 && (mySeq.time_sig.length() == 0 ||
843 mySeq.time_sig[i].beat > beat)) {
844 // If beat does not fall on an implied barline, we need to
845 // insert a time signature.
846 double measures = beat / 4.0;
847 double imeasures = ROUND(measures);
848 if (!within(measures, imeasures, ALG_EPS)) {
849 double bar_offset = ((int)(measures) + 1) * 4.0 - beat;
850 seq->set_time_sig(bar_offset, 4, 4);
851 }
852 // This case should never be true because if i == 0, either there
853 // are no time signatures before beat (Case 2),
854 // or there is one time signature at beat (Case 1)
855 } else if (i == 0) {
856 /* do nothing (might be good to assert(false)) */ ;
857 // Case 3: i-1 must be the effective time sig position
858 } else {
859 i -= 1; // index the time signature in effect at beat
860 Alg_time_sig_ptr tsp = &(mySeq.time_sig[i]);
861 double beats_per_measure = (tsp->num * 4) / tsp->den;
862 double measures = (beat - tsp->beat) / beats_per_measure;
863 int imeasures = ROUND(measures);
864 if (!within(measures, imeasures, ALG_EPS)) {
865 // beat is not on a measure, so we need to insert a time sig
866 // to force a bar line at the first measure location after
867 // beat
868 double bar = tsp->beat + beats_per_measure * ((int)(measures) + 1);
869 double bar_offset = bar - beat;
870 // insert NEW time signature at bar_offset in NEW sequence
871 // It will have the same time signature, but the position will
872 // force a barline to match the barlines in mSeq
873 seq->set_time_sig(bar_offset, tsp->num, tsp->den);
874 }
875 // else beat coincides with a barline, so no need for an extra
876 // time signature to force barline alignment
877 }
878 }
879 return seq;
880}
#define ROUND(x)
Definition: NoteTrack.cpp:32
bool within(A a, B b, DIST d)
Definition: TrackPanel.cpp:167
A Track that is used for Midi notes. (Somewhat old code).
Definition: NoteTrack.h:63
bool Shift(double t)
Definition: NoteTrack.cpp:648
void swap(std::unique_ptr< Alg_seq > &a, std::unique_ptr< Alg_seq > &b)
Definition: NoteTrack.cpp:752
void copy(const T *src, T *dst, int32_t n)
Definition: VectorOps.h:32

References staffpad::vo::copy(), GetOffset(), GetSeq(), mSeq, ROUND, Shift(), anonymous_namespace{NoteTrack.cpp}::swap(), and within().

Referenced by ExportMIDI().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ NearestBeatTime()

QuantizedTimeAndBeat NoteTrack::NearestBeatTime ( double  time) const

Definition at line 675 of file NoteTrack.cpp.

676{
677 // Alg_seq knows nothing about offset, so remove offset time
678 double seq_time = time - GetOffset();
679 double beat;
680 auto &seq = GetSeq();
681 seq_time = seq.nearest_beat_time(seq_time, &beat);
682 // add the offset back in to get "actual" audacity track time
683 return { seq_time + GetOffset(), beat };
684}

References GetOffset(), and GetSeq().

Here is the call graph for this function:

◆ New()

NoteTrack * NoteTrack::New ( AudacityProject project)
static

Definition at line 114 of file NoteTrack.cpp.

115{
116 auto &tracks = TrackList::Get( project );
117 auto result = tracks.Add( std::make_shared<NoteTrack>());
118 result->AttachedTrackObjects::BuildAll();
119 return result;
120}
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:360

References TrackList::Get().

Here is the call graph for this function:

◆ Paste()

void NoteTrack::Paste ( double  t,
const Track src 
)
override

Definition at line 553 of file NoteTrack.cpp.

554{
555 // Paste inserts src at time t. If src has a positive offset,
556 // the offset is treated as silence which is also inserted. If
557 // the offset is negative, the offset is ignored and the ENTIRE
558 // src is inserted (otherwise, we would either lose data from
559 // src by not inserting things at negative times, or inserting
560 // things at negative times could overlap things already in
561 // the destination track).
562
563 //Check that src is a non-NULL NoteTrack
564 bool bOk = src && src->TypeSwitch< bool >( [&](const NoteTrack *other) {
565
566 auto myOffset = this->GetOffset();
567 if (t < myOffset) {
568 // workaround strange behavior described at
569 // http://bugzilla.audacityteam.org/show_bug.cgi?id=1735#c3
570 SetOffset(t);
571 InsertSilence(t, myOffset - t);
572 }
573
574 double delta = 0.0;
575 auto &seq = GetSeq();
576 auto offset = other->GetOffset();
577 if ( offset > 0 ) {
578 seq.convert_to_seconds();
579 seq.insert_silence( t - GetOffset(), offset );
580 t += offset;
581 // Is this needed or does Alg_seq::insert_silence take care of it?
582 //delta += offset;
583 }
584
585 // This seems to be needed:
586 delta += std::max( 0.0, t - GetEndTime() );
587
588 // This, not:
589 //delta += other->GetSeq().get_real_dur();
590
591 seq.paste(t - GetOffset(), &other->GetSeq());
592
593 AddToDuration( delta );
594
595 return true;
596 });
597
598 if ( !bOk )
599 // THROW_INCONSISTENCY_EXCEPTION; // ?
600 (void)0;// intentionally do nothing
601}
void AddToDuration(double delta)
Definition: NoteTrack.cpp:726
void InsertSilence(double t, double len) override
Definition: NoteTrack.cpp:618
R TypeSwitch(const Functions &...functions)
Use this function rather than testing track type explicitly and making down-casts.
Definition: Track.h:755

References AddToDuration(), GetEndTime(), GetOffset(), GetSeq(), InsertSilence(), Track::SetOffset(), and Track::TypeSwitch().

Here is the call graph for this function:

◆ PasteInto()

Track::Holder NoteTrack::PasteInto ( AudacityProject ) const
overridevirtual

Find or create the destination track for a paste, maybe in a different project.

Returns
A smart pointer to the track; its use_count() can tell whether it is new

Implements Track.

Definition at line 704 of file NoteTrack.cpp.

705{
706 auto pNewTrack = std::make_shared<NoteTrack>();
707 pNewTrack->Init(*this);
708 pNewTrack->Paste(0.0, this);
709 return pNewTrack;
710}

◆ PrintSequence()

void NoteTrack::PrintSequence ( )

Definition at line 384 of file NoteTrack.cpp.

385{
386 FILE *debugOutput;
387
388 debugOutput = fopen("debugOutput.txt", "wt");
389 wxFprintf(debugOutput, "Importing MIDI...\n");
390
391 // This is called for debugging purposes. Do not compute mSeq on demand
392 // with GetSeq()
393 if (mSeq) {
394 int i = 0;
395
396 while(i < mSeq->length()) {
397 wxFprintf(debugOutput, "--\n");
398 wxFprintf(debugOutput, "type: %c\n",
399 ((Alg_event_ptr)mSeq->track_list.tracks[i])->get_type());
400 wxFprintf(debugOutput, "time: %f\n",
401 ((Alg_event_ptr)mSeq->track_list.tracks[i])->time);
402 wxFprintf(debugOutput, "channel: %li\n",
403 ((Alg_event_ptr)mSeq->track_list.tracks[i])->chan);
404
405 if(((Alg_event_ptr)mSeq->track_list.tracks[i])->get_type() == wxT('n'))
406 {
407 wxFprintf(debugOutput, "pitch: %f\n",
408 ((Alg_note_ptr)mSeq->track_list.tracks[i])->pitch);
409 wxFprintf(debugOutput, "duration: %f\n",
410 ((Alg_note_ptr)mSeq->track_list.tracks[i])->dur);
411 wxFprintf(debugOutput, "velocity: %f\n",
412 ((Alg_note_ptr)mSeq->track_list.tracks[i])->loud);
413 }
414 else if(((Alg_event_ptr)mSeq->track_list.tracks[i])->get_type() == wxT('n'))
415 {
416 wxFprintf(debugOutput, "key: %li\n", ((Alg_update_ptr)mSeq->track_list.tracks[i])->get_identifier());
417 wxFprintf(debugOutput, "attribute type: %c\n", ((Alg_update_ptr)mSeq->track_list.tracks[i])->parameter.attr_type());
418 wxFprintf(debugOutput, "attribute: %s\n", ((Alg_update_ptr)mSeq->track_list.tracks[i])->parameter.attr_name());
419
420 if(((Alg_update_ptr)mSeq->track_list.tracks[i])->parameter.attr_type() == wxT('r'))
421 {
422 wxFprintf(debugOutput, "value: %f\n", ((Alg_update_ptr)mSeq->track_list.tracks[i])->parameter.r);
423 }
424 else if(((Alg_update_ptr)mSeq->track_list.tracks[i])->parameter.attr_type() == wxT('i')) {
425 wxFprintf(debugOutput, "value: %li\n", ((Alg_update_ptr)mSeq->track_list.tracks[i])->parameter.i);
426 }
427 else if(((Alg_update_ptr)mSeq->track_list.tracks[i])->parameter.attr_type() == wxT('s')) {
428 wxFprintf(debugOutput, "value: %s\n", ((Alg_update_ptr)mSeq->track_list.tracks[i])->parameter.s);
429 }
430 else {}
431 }
432
433 i++;
434 }
435 }
436 else {
437 wxFprintf(debugOutput, "No sequence defined!\n");
438 }
439
440 fclose(debugOutput);
441}

References mSeq, and wxT().

Here is the call graph for this function:

◆ SetBottomNote()

void NoteTrack::SetBottomNote ( int  note)

Sets the bottom note (a pitch), making sure that it is never greater than the top note.

Definition at line 988 of file NoteTrack.cpp.

989{
990 if (note < MinPitch)
991 note = MinPitch;
992 else if (note > 96)
993 note = 96;
994
995 wxCHECK(note <= mTopNote, );
996
997 mBottomNote = note;
998}

References mBottomNote, MinPitch, and mTopNote.

Referenced by HandleXMLTag().

Here is the caller graph for this function:

◆ SetNoteRange()

void NoteTrack::SetNoteRange ( int  note1,
int  note2 
)

Sets the top and bottom note (both pitches) automatically, swapping them if needed.

Definition at line 1010 of file NoteTrack.cpp.

1011{
1012 // Bounds check
1013 if (note1 > MaxPitch)
1014 note1 = MaxPitch;
1015 else if (note1 < MinPitch)
1016 note1 = MinPitch;
1017 if (note2 > MaxPitch)
1018 note2 = MaxPitch;
1019 else if (note2 < MinPitch)
1020 note2 = MinPitch;
1021 // Swap to ensure ordering
1022 if (note2 < note1) { auto tmp = note1; note1 = note2; note2 = tmp; }
1023
1024 mBottomNote = note1;
1025 mTopNote = note2;
1026}

References MaxPitch, mBottomNote, MinPitch, and mTopNote.

Referenced by Zoom(), ZoomAllNotes(), and ZoomTo().

Here is the caller graph for this function:

◆ SetSequence()

void NoteTrack::SetSequence ( std::unique_ptr< Alg_seq > &&  seq)

Definition at line 379 of file NoteTrack.cpp.

380{
381 mSeq = std::move(seq);
382}

References mSeq.

Referenced by ImportMIDI().

Here is the caller graph for this function:

◆ SetTopNote()

void NoteTrack::SetTopNote ( int  note)

Sets the top note (a pitch), making sure that it is never less than the bottom note.

Definition at line 1000 of file NoteTrack.cpp.

1001{
1002 if (note > MaxPitch)
1003 note = MaxPitch;
1004
1005 wxCHECK(note >= mBottomNote, );
1006
1007 mTopNote = note;
1008}

References MaxPitch, mBottomNote, and mTopNote.

Referenced by HandleXMLTag().

Here is the caller graph for this function:

◆ SetVisibleChan()

void NoteTrack::SetVisibleChan ( int  c)
inline

Definition at line 185 of file NoteTrack.h.

185 {
186 mVisibleChannels.fetch_or(CHANNEL_BIT(c), std::memory_order_relaxed); }

References CHANNEL_BIT.

◆ SetVisibleChannels()

void NoteTrack::SetVisibleChannels ( unsigned  value)
inline

Definition at line 179 of file NoteTrack.h.

179 {
180 mVisibleChannels.store(value, std::memory_order_relaxed);
181 }

Referenced by HandleXMLTag().

Here is the caller graph for this function:

◆ Shift()

bool NoteTrack::Shift ( double  t)

Definition at line 648 of file NoteTrack.cpp.

649{
650 if (t > 0) {
651 auto &seq = GetSeq();
652 // insert an even number of measures
653 seq.convert_to_beats();
654 // get initial tempo
655 double tempo = seq.get_tempo(0.0);
656 double beats_per_measure = seq.get_bar_len(0.0);
657 int m = ROUND(t * tempo / beats_per_measure);
658 // need at least 1 measure, so if we rounded down to zero, fix it
659 if (m == 0) m = 1;
660 // compute NEW tempo so that m measures at NEW tempo take t seconds
661 tempo = beats_per_measure * m / t; // in beats per second
662 seq.insert_silence(0.0, beats_per_measure * m);
663 seq.set_tempo(tempo * 60.0 /* bpm */, 0.0, beats_per_measure * m);
664 seq.write("afterShift.gro");
665 } else if (t < 0) {
666 auto &seq = GetSeq();
667 seq.convert_to_seconds();
668 seq.clear(0, t, true);
669 } else { // offset is zero, no modifications
670 return false;
671 }
672 return true;
673}

References GetSeq(), and ROUND.

Referenced by MakeExportableSeq().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ShiftNoteRange()

void NoteTrack::ShiftNoteRange ( int  offset)

Shifts all notes vertically by the given pitch.

Definition at line 1028 of file NoteTrack.cpp.

1029{
1030 // Ensure everything stays in bounds
1031 if (mBottomNote + offset < MinPitch || mTopNote + offset > MaxPitch)
1032 return;
1033
1034 mBottomNote += offset;
1035 mTopNote += offset;
1036}

References MaxPitch, mBottomNote, and mTopNote.

Referenced by NoteTrackMenuTable::OnChangeOctave().

Here is the caller graph for this function:

◆ Silence()

void NoteTrack::Silence ( double  t0,
double  t1 
)
override

Definition at line 603 of file NoteTrack.cpp.

604{
605 if (t1 < t0)
607
608 auto len = t1 - t0;
609
610 auto &seq = GetSeq();
611 seq.convert_to_seconds();
612 // XXX: do we want to set the all param?
613 // If it's set, then it seems like notes are silenced if they start or end in the range,
614 // otherwise only if they start in the range. --Poke
615 seq.silence(t0 - GetOffset(), len, false);
616}

References GetOffset(), GetSeq(), and THROW_INCONSISTENCY_EXCEPTION.

Here is the call graph for this function:

◆ SoloVisibleChan()

void NoteTrack::SoloVisibleChan ( int  c)
inline

Definition at line 193 of file NoteTrack.h.

193 {
194 auto visibleChannels = 0u;
196 visibleChannels = ALL_CHANNELS;
197 else
198 visibleChannels = CHANNEL_BIT(c);
199 mVisibleChannels.store(visibleChannels, std::memory_order_relaxed);
200 }
#define ALL_CHANNELS
Definition: NoteTrack.h:174

References ALL_CHANNELS, and CHANNEL_BIT.

Referenced by LabelClick().

Here is the caller graph for this function:

◆ StretchRegion()

bool NoteTrack::StretchRegion ( QuantizedTimeAndBeat  t0,
QuantizedTimeAndBeat  t1,
double  newDur 
)

Definition at line 738 of file NoteTrack.cpp.

740{
741 auto &seq = GetSeq();
742 bool result = seq.stretch_region( t0.second, t1.second, newDur );
743 if (result) {
744 const auto oldDur = t1.first - t0.first;
745 AddToDuration( newDur - oldDur );
746 }
747 return result;
748}

References AddToDuration(), and GetSeq().

Referenced by StretchHandle::Stretch().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ToggleVisibleChan()

void NoteTrack::ToggleVisibleChan ( int  c)
inline

Definition at line 189 of file NoteTrack.h.

189 {
190 mVisibleChannels.fetch_xor(CHANNEL_BIT(c), std::memory_order_relaxed); }

References CHANNEL_BIT.

Referenced by LabelClick().

Here is the caller graph for this function:

◆ Trim()

bool NoteTrack::Trim ( double  t0,
double  t1 
)

Definition at line 496 of file NoteTrack.cpp.

497{
498 if (t1 < t0)
499 return false;
500 auto &seq = GetSeq();
501 //auto delta = -(
502 //( GetEndTime() - std::min( GetEndTime(), t1 ) ) +
503 //( std::max(t0, GetStartTime()) - GetStartTime() )
504 //);
505 seq.convert_to_seconds();
506 // DELETE way beyond duration just in case something is out there:
507 seq.clear(t1 - GetOffset(), seq.get_dur() + 10000.0, false);
508 // Now that stuff beyond selection is cleared, clear before selection:
509 seq.clear(0.0, t0 - GetOffset(), false);
510 // want starting time to be t0
511 SetOffset(t0);
512
513 // Not needed
514 // Alg_seq::clear seems to handle this
515 //AddToDuration( delta );
516
517 return true;
518}

References GetOffset(), GetSeq(), and Track::SetOffset().

Here is the call graph for this function:

◆ WarpAndTransposeNotes()

void NoteTrack::WarpAndTransposeNotes ( double  t0,
double  t1,
const TimeWarper warper,
double  semitones 
)

Definition at line 216 of file NoteTrack.cpp.

219{
220 double offset = this->GetOffset(); // track is shifted this amount
221 auto &seq = GetSeq();
222 seq.convert_to_seconds(); // make sure time units are right
223 t1 -= offset; // adjust time range to compensate for track offset
224 t0 -= offset;
225 if (t1 > seq.get_dur()) { // make sure t0, t1 are within sequence
226 t1 = seq.get_dur();
227 if (t0 >= t1) return;
228 }
229 Alg_iterator iter(mSeq.get(), false);
230 iter.begin();
231 Alg_event_ptr event;
232 while (0 != (event = iter.next()) && event->time < t1) {
233 if (event->is_note() && event->time >= t0) {
234 event->set_pitch(event->get_pitch() + semitones);
235 }
236 }
237 iter.end();
238 // now, use warper to warp the tempo map
239 seq.convert_to_beats(); // beats remain the same
240 Alg_time_map_ptr map = seq.get_time_map();
241 map->insert_beat(t0, map->time_to_beat(t0));
242 map->insert_beat(t1, map->time_to_beat(t1));
243 int i, len = map->length();
244 for (i = 0; i < len; i++) {
245 Alg_beat &beat = map->beats[i];
246 beat.time = warper.Warp(beat.time + offset) - offset;
247 }
248 // about to redisplay, so might as well convert back to time now
249 seq.convert_to_seconds();
250}
virtual double Warp(double originalTime) const =0

References GetOffset(), GetSeq(), mSeq, and TimeWarper::Warp().

Here is the call graph for this function:

◆ WriteXML()

void NoteTrack::WriteXML ( XMLWriter xmlFile) const
overridevirtual

Implements Track.

Definition at line 958 of file NoteTrack.cpp.

960{
961 std::ostringstream data;
962 Track::Holder holder;
963 const NoteTrack *saveme = this;
964 if (!mSeq) {
965 // replace saveme with an (unserialized) duplicate, which is
966 // destroyed at end of function.
967 holder = Clone();
968 saveme = static_cast<NoteTrack*>(holder.get());
969 }
970 saveme->GetSeq().write(data, true);
971 xmlFile.StartTag(wxT("notetrack"));
972 saveme->Track::WriteCommonXMLAttributes( xmlFile );
974 xmlFile.WriteAttr(wxT("offset"), saveme->GetOffset());
975 xmlFile.WriteAttr(wxT("visiblechannels"),
976 static_cast<int>(saveme->GetVisibleChannels()));
977
978#ifdef EXPERIMENTAL_MIDI_OUT
979 xmlFile.WriteAttr(wxT("velocity"),
980 static_cast<double>(saveme->GetVelocity()));
981#endif
982 xmlFile.WriteAttr(wxT("bottomnote"), saveme->mBottomNote);
983 xmlFile.WriteAttr(wxT("topnote"), saveme->mTopNote);
984 xmlFile.WriteAttr(wxT("data"), wxString(data.str().c_str(), wxConvUTF8));
985 xmlFile.EndTag(wxT("notetrack"));
986}
void WriteXMLAttributes(XMLWriter &WXUNUSED(xmlFile)) const
Definition: PlayableTrack.h:29
Track::Holder Clone() const override
Definition: NoteTrack.cpp:160
std::shared_ptr< Track > Holder
Definition: Track.h:295
virtual void StartTag(const wxString &name)
Definition: XMLWriter.cpp:79
void WriteAttr(const wxString &name, const Identifier &value)
Definition: XMLWriter.h:36
virtual void EndTag(const wxString &name)
Definition: XMLWriter.cpp:102

References GetOffset(), GetSeq(), GetVisibleChannels(), mBottomNote, mTopNote, AudioTrack::WriteXMLAttributes(), and wxT().

Here is the call graph for this function:

◆ Zoom()

void NoteTrack::Zoom ( const wxRect &  rect,
int  y,
float  multiplier,
bool  center 
)

Zoom the note track around y. If center is true, the result will be centered at y.

Definition at line 1052 of file NoteTrack.cpp.

1053{
1054 NoteTrackDisplayData data = NoteTrackDisplayData(this, rect);
1055 int clickedPitch = data.YToIPitch(y);
1056 int extent = mTopNote - mBottomNote + 1;
1057 int newExtent = (int) (extent / multiplier);
1058 float position;
1059 if (center) {
1060 // center the pitch that the user clicked on
1061 position = .5;
1062 } else {
1063 // align to keep the pitch that the user clicked on in the same place
1064 position = extent / (clickedPitch - mBottomNote);
1065 }
1066 int newBottomNote = clickedPitch - (newExtent * position);
1067 int newTopNote = clickedPitch + (newExtent * (1 - position));
1068 SetNoteRange(newBottomNote, newTopNote);
1069}
Data used to display a note track.
Definition: NoteTrack.h:250
int YToIPitch(int y) const
Definition: NoteTrack.cpp:1159
void SetNoteRange(int note1, int note2)
Sets the top and bottom note (both pitches) automatically, swapping them if needed.
Definition: NoteTrack.cpp:1010

References mBottomNote, mTopNote, SetNoteRange(), and NoteTrackDisplayData::YToIPitch().

Referenced by ZoomTo().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ZoomAllNotes()

void NoteTrack::ZoomAllNotes ( )

Zooms so that all notes are visible.

Definition at line 1087 of file NoteTrack.cpp.

1088{
1089 Alg_iterator iterator( &GetSeq(), false );
1090 iterator.begin();
1091 Alg_event_ptr evt;
1092
1093 // Go through all of the notes, finding the minimum and maximum value pitches.
1094 bool hasNotes = false;
1095 int minPitch = MaxPitch;
1096 int maxPitch = MinPitch;
1097
1098 while (NULL != (evt = iterator.next())) {
1099 if (evt->is_note()) {
1100 int pitch = (int) evt->get_pitch();
1101 hasNotes = true;
1102 if (pitch < minPitch)
1103 minPitch = pitch;
1104 if (pitch > maxPitch)
1105 maxPitch = pitch;
1106 }
1107 }
1108
1109 if (!hasNotes) {
1110 // Semi-arbitrary default values:
1111 minPitch = 48;
1112 maxPitch = 72;
1113 }
1114
1115 SetNoteRange(minPitch, maxPitch);
1116}

References GetSeq(), MaxPitch, MinPitch, and SetNoteRange().

Referenced by ImportMIDI().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ZoomIn()

void NoteTrack::ZoomIn ( const wxRect &  rect,
int  y 
)
inline

Zooms in a constant factor (subject to zoom limits)

Definition at line 142 of file NoteTrack.h.

142{ Zoom(rect, y, ZoomStep, true); }
void Zoom(const wxRect &rect, int y, float multiplier, bool center)
Definition: NoteTrack.cpp:1052
static const float ZoomStep
Definition: NoteTrack.h:241

Referenced by NoteTrackVRulerControls::HandleWheelRotation().

Here is the caller graph for this function:

◆ ZoomMaxExtent()

void NoteTrack::ZoomMaxExtent ( )
inline

Zooms so that the entire track is visible.

Definition at line 135 of file NoteTrack.h.

◆ ZoomOut()

void NoteTrack::ZoomOut ( const wxRect &  rect,
int  y 
)
inline

Zooms out a constant factor (subject to zoom limits)

Definition at line 140 of file NoteTrack.h.

140{ Zoom(rect, y, 1.0f / ZoomStep, true); }

◆ ZoomTo()

void NoteTrack::ZoomTo ( const wxRect &  rect,
int  start,
int  end 
)

Definition at line 1072 of file NoteTrack.cpp.

1073{
1074 wxRect trackRect(0, rect.GetY(), 1, rect.GetHeight());
1075 NoteTrackDisplayData data = NoteTrackDisplayData(this, trackRect);
1076 int pitch1 = data.YToIPitch(start);
1077 int pitch2 = data.YToIPitch(end);
1078 if (pitch1 == pitch2) {
1079 // Just zoom in instead of zooming to show only one note
1080 Zoom(rect, start, 1, true);
1081 return;
1082 }
1083 // It's fine for this to be in either order
1084 SetNoteRange(pitch1, pitch2);
1085}
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Definition: PackedArray.h:159

References PackedArray::end(), SetNoteRange(), NoteTrackDisplayData::YToIPitch(), and Zoom().

Here is the call graph for this function:

Member Data Documentation

◆ mBottomNote

int NoteTrack::mBottomNote
private

◆ mPitchHeight

float NoteTrack::mPitchHeight
private

Definition at line 238 of file NoteTrack.h.

◆ mSeq

std::unique_ptr<Alg_seq> NoteTrack::mSeq
mutableprivate

◆ mSerializationBuffer

std::unique_ptr<char[]> NoteTrack::mSerializationBuffer
mutableprivate

Definition at line 222 of file NoteTrack.h.

Referenced by Clone(), and GetSeq().

◆ mSerializationLength

long NoteTrack::mSerializationLength
mutableprivate

Definition at line 223 of file NoteTrack.h.

Referenced by Clone(), GetSeq(), and NoteTrack().

◆ mStretchHandle

std::weak_ptr<StretchHandle> NoteTrack::mStretchHandle
private

Definition at line 246 of file NoteTrack.h.

◆ mTopNote

int NoteTrack::mTopNote
private

◆ mVisibleChannels

std::atomic<unsigned> NoteTrack::mVisibleChannels { ALL_CHANNELS }
private

A bit set; atomic because it may be read by worker threads in playback.

Definition at line 244 of file NoteTrack.h.

◆ ZoomStep

const float NoteTrack::ZoomStep = powf( 2.0f, 0.25f )
staticprivate

Definition at line 241 of file NoteTrack.h.


The documentation for this class was generated from the following files: