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

A Track that contains audio waveform data. More...

#include <WaveTrack.h>

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

Classes

class  AllClipsConstIterator
 
class  AllClipsIterator
 
class  Interval
 
struct  Region
 Structure to hold region of a wavetrack and a comparison function for sortability. More...
 

Public Types

using Regions = std::vector< Region >
 
using Holder = std::shared_ptr< WaveTrack >
 
using ProgressReport = std::function< bool(double)>
 
using IntervalHolder = std::shared_ptr< Interval >
 
using IntervalConstHolder = std::shared_ptr< const Interval >
 
- Public Types inherited from Track
using AttachedObjects = ::AttachedTrackObjects
 Alias for my base type. More...
 
using Holder = std::shared_ptr< Track >
 
- 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 Types inherited from ChannelGroup
enum class  LinkType : int { None = 0 , Group = 2 , Aligned }
 For two tracks describes the type of the linkage. More...
 
using Attachments = ClientData::Site< ChannelGroupData, ClientData::Cloneable<>, ClientData::DeepCopying >
 
using Interval = WideChannelGroupInterval
 
- Public Types inherited from Channel
using Interval = ChannelInterval
 

Public Member Functions

 WaveTrack (const SampleBlockFactoryPtr &pFactory, sampleFormat format, double rate)
 
 WaveTrack (const WaveTrack &orig, ProtectedCreationArg &&, bool backup)
 Copied only in WaveTrack::Clone() ! More...
 
size_t GetWidth () const
 The width of every WaveClip in this track; for now always 1. More...
 
size_t NChannels () const override
 May report more than one only when this is a leader track. More...
 
auto GetChannel (size_t iChannel)
 
auto GetChannel (size_t iChannel) const
 
auto Channels ()
 
auto Channels () const
 
AudioGraph::ChannelType GetChannelType () const override
 Classify this channel. More...
 
void Reinit (const WaveTrack &orig)
 
virtual ~WaveTrack ()
 
void MoveTo (double o) override
 
bool LinkConsistencyFix (bool doFix) override
 Check consistency of channel groups, and maybe fix it. More...
 
double GetStartTime () const override
 Implement WideSampleSequence. More...
 
double GetEndTime () const override
 Implement WideSampleSequence. More...
 
double GetRate () const override
 
void SetRate (double newRate)
 
float GetGain () const
 
void SetGain (float newGain)
 
float GetPan () const
 
void SetPan (float newPan)
 
float GetChannelGain (int channel) const override
 Takes gain and pan into account. More...
 
int GetWaveColorIndex () const
 
void SetWaveColorIndex (int colorIndex)
 
sampleCount GetVisibleSampleCount () const
 
sampleCount GetSequenceSamplesCount () const
 
size_t CountBlocks () const
 
sampleFormat GetSampleFormat () const override
 
void ConvertToSampleFormat (sampleFormat format, const std::function< void(size_t)> &progressReport={})
 
TrackListHolder Cut (double t0, double t1) override
 Create tracks and modify this track. More...
 
Holder EmptyCopy (const SampleBlockFactoryPtr &pFactory={}, bool keepLink=true) const
 
TrackListHolder WideEmptyCopy (const SampleBlockFactoryPtr &pFactory={}, bool keepLink=true) const
 
TrackListHolder MonoToStereo ()
 
TrackListHolder Copy (double t0, double t1, bool forClipboard=true) const override
 Create new tracks and don't modify this track. More...
 
void Clear (double t0, double t1) override
 
void Paste (double t0, const Track &src) override
 
void ClearAndPaste (double t0, double t1, const WaveTrack &src, bool preserve=true, bool merge=true, const TimeWarper *effectWarper=nullptr, bool clearByTrimming=false)
 
void ClearAndPaste (double t0, double t1, const TrackList &src, bool preserve=true, bool merge=true, const TimeWarper *effectWarper=nullptr)
 
void Silence (double t0, double t1, ProgressReporter reportProgress) override
 
void InsertSilence (double t, double len) override
 
void Split (double t0, double t1)
 
void ClearAndAddCutLine (double t0, double t1)
 
TrackListHolder SplitCut (double t0, double t1)
 
void SplitDelete (double t0, double t1)
 
void Join (double t0, double t1, const ProgressReporter &reportProgress)
 
void Disjoin (double t0, double t1)
 
void Trim (double t0, double t1)
 
void ApplyPitchAndSpeed (std::optional< TimeInterval > interval, ProgressReporter reportProgress)
 
void SyncLockAdjust (double oldT1, double newT1) override
 
bool IsEmpty (double t0, double t1) const
 Returns true if there are no WaveClips in the specified region. More...
 
bool Append (constSamplePtr buffer, sampleFormat format, size_t len, unsigned int stride=1, sampleFormat effectiveFormat=widestSampleFormat, size_t iChannel=0) override
 
void Flush () override
 
bool IsLeader () const override
 
bool DoGet (size_t iChannel, size_t nBuffers, const samplePtr buffers[], sampleFormat format, sampleCount start, size_t len, bool backwards, fillFormat fill=FillFormat::fillZero, bool mayThrow=true, sampleCount *pNumWithinClips=nullptr) const override
 This fails if any clip overlapping the range has non-unit stretch ratio! More...
 
std::pair< size_t, size_t > GetFloatsCenteredAroundTime (double t, size_t iChannel, float *buffer, size_t numSideSamples, bool mayThrow) const
 Gets as many samples as it can, but no more than 2 * numSideSamples + 1, centered around t. Reads nothing if GetClipAtTime(t) == nullptr. Useful to access samples across clip boundaries, as it spreads the read to adjacent clips, i.e., not separated by silence from clip at t. More...
 
bool GetFloatAtTime (double t, size_t iChannel, float &value, bool mayThrow) const
 
void SetFloatsCenteredAroundTime (double t, size_t iChannel, const float *buffer, size_t numSideSamples, sampleFormat effectiveFormat)
 Similar to GetFloatsCenteredAroundTime, but for writing. Sets as many samples as it can according to the same rules as GetFloatsCenteredAroundTime. Leaves the other samples untouched. More...
 
void SetFloatAtTime (double t, size_t iChannel, float value, sampleFormat effectiveFormat)
 Sets sample nearest to t to value. Silently fails if GetClipAtTime(t) == nullptr. More...
 
void SetFloatsWithinTimeRange (double t0, double t1, size_t iChannel, const std::function< float(double sampleTime)> &producer, sampleFormat effectiveFormat)
 Provides a means of setting clip values as a function of time. Included are closest sample to t0 up to closest sample to t1, exclusively. If the given interval is empty, i.e., t0 >= t1, no action is taken. More...
 
ChannelGroupSampleView GetSampleView (double t0, double t1, bool mayThrow=true) const
 Request samples within [t0, t1), not knowing in advance how many this will be. More...
 
sampleFormat WidestEffectiveFormat () const override
 
bool HasTrivialEnvelope () const override
 
void GetEnvelopeValues (double *buffer, size_t bufferLen, double t0, bool backwards) const override
 
EnvelopeGetEnvelopeAtTime (double time)
 
const WaveClipGetClipAtTime (double time) const
 
WaveClipGetClipAtTime (double time)
 
WaveClipConstHolders GetClipsIntersecting (double t0, double t1) const
 
const WaveClipGetNextClip (const WaveClip &clip, PlaybackDirection searchDirection) const
 Returns clips next to clip in the given direction, or nullptr if there is none. More...
 
WaveClipGetNextClip (const WaveClip &clip, PlaybackDirection searchDirection)
 Returns clips next to clip in the given direction, or nullptr if there is none. More...
 
const WaveClipGetAdjacentClip (const WaveClip &clip, PlaybackDirection searchDirection) const
 Similar to GetNextClip, but returns nullptr if the neighbour clip is not adjacent. More...
 
WaveClipGetAdjacentClip (const WaveClip &clip, PlaybackDirection searchDirection)
 Similar to GetNextClip, but returns nullptr if the neighbour clip is not adjacent. More...
 
size_t GetBestBlockSize (sampleCount t) const
 
size_t GetMaxBlockSize () const
 
size_t GetIdealBlockSize ()
 
bool HandleXMLTag (const std::string_view &tag, const AttributesList &attrs) override
 
void HandleXMLEndTag (const std::string_view &tag) override
 
XMLTagHandlerHandleXMLChild (const std::string_view &tag) override
 
void WriteXML (XMLWriter &xmlFile) const override
 
std::optional< TranslatableStringGetErrorOpening () const override
 
bool CloseLock () noexcept
 Should be called upon project close. Not balanced by unlocking calls. More...
 
WaveClipHoldersGetClips ()
 
const WaveClipConstHoldersGetClips () const
 
const WaveClipGetLeftmostClip () const
 
const WaveClipGetRightmostClip () const
 
ClipHolders GetClipInterfaces () const
 Get access to the (visible) clips in the tracks, in unspecified order. More...
 
IteratorRange< AllClipsIteratorGetAllClips ()
 
IteratorRange< AllClipsConstIteratorGetAllClips () const
 
void CreateWideClip (double offset=.0, const wxString &name=wxEmptyString)
 
WaveClipCreateClip (double offset=.0, const wxString &name=wxEmptyString)
 Create new clip and add it to this track. More...
 
WaveClipNewestOrNewClip ()
 Get access to the most recently added clip, or create a clip, if there is not already one. THIS IS NOT NECESSARILY RIGHTMOST. More...
 
WaveClipRightmostOrNewClip ()
 Get access to the last (rightmost) clip, or create a clip, if there is not already one. More...
 
int GetClipIndex (const WaveClip *clip) const
 
WaveClipGetClipByIndex (int index)
 Get the nth clip in this WaveTrack (will return nullptr if not found). More...
 
const WaveClipGetClipByIndex (int index) const
 Get the nth clip in this WaveTrack (will return nullptr if not found). More...
 
int GetNumClips () const
 
int GetNumClips (double t0, double t1) const
 
WaveClipPointers SortedClipArray ()
 
WaveClipConstPointers SortedClipArray () const
 
bool HasHiddenData () const
 Whether any clips have hidden audio. More...
 
void DiscardTrimmed ()
 Remove hidden audio from all clips. More...
 
bool CanOffsetClips (const std::vector< WaveClip * > &clips, double amount, double *allowedAmount=nullptr)
 Decide whether the clips could be offset (and inserted) together without overlapping other clips. More...
 
bool CanInsertClip (const WaveClip &clip, double &slideBy, double tolerance) const
 
std::shared_ptr< WaveClipRemoveAndReturnClip (WaveClip *clip)
 
bool AddClip (const std::shared_ptr< WaveClip > &clip)
 
bool MergeClips (int clipidx1, int clipidx2)
 
void ExpandCutLine (double cutLinePosition, double *cutlineStart=nullptr, double *cutlineEnd=nullptr)
 
bool RemoveCutLine (double cutLinePosition)
 Remove cut line, without expanding the audio in it. More...
 
void Resample (int rate, BasicUI::ProgressDialog *progress=NULL)
 
bool Reverse (sampleCount start, sampleCount len, const ProgressReport &report={})
 
const TypeInfoGetTypeInfo () const override
 
IntervalConstHolder GetNextInterval (const Interval &interval, PlaybackDirection searchDirection) const
 
IntervalHolder GetNextInterval (const Interval &interval, PlaybackDirection searchDirection)
 
IntervalHolder GetIntervalAtTime (double t)
 
auto Intervals ()
 
auto Intervals () const
 
Track::Holder PasteInto (AudacityProject &project, TrackList &list) const override
 
const WaveClipFindClipByName (const wxString &name) const
 Returns nullptr if clip with such name was not found. More...
 
size_t NIntervals () const override
 used only during deserialization More...
 
void SetLegacyFormat (sampleFormat format)
 
void CopyClipEnvelopes ()
 
bool GetFloats (float *buffer, sampleCount start, size_t len, fillFormat fill=FillFormat::fillZero, bool mayThrow=true, sampleCount *pNumWithinClips=nullptr) const
 "narrow" overload fetches first channel only More...
 
bool GetFloats (size_t iChannel, size_t nBuffers, float *const buffers[], sampleCount start, size_t len, bool backwards=false, fillFormat fill=FillFormat::fillZero, bool mayThrow=true, sampleCount *pNumWithinClips=nullptr) const
 
virtual void Paste (double t, const Track &src)=0
 Weak precondition allows overrides to replicate one channel into many. More...
 
void Paste (double t, const TrackList &src)
 
PlayableSequence implementation
const ChannelGroupFindChannelGroup () const override
 Find associated ChannelGroup if any. More...
 
bool GetMute () const override
 May vary asynchronously. More...
 
bool GetSolo () const override
 May vary asynchronously. More...
 
- Public Member Functions inherited from WritableSampleTrack
 WritableSampleTrack ()
 
 WritableSampleTrack (const WritableSampleTrack &other, ProtectedCreationArg &&)
 
 ~WritableSampleTrack () override
 
const TypeInfoGetTypeInfo () const override
 
bool IsLeader () const override
 
virtual size_t NChannels () const=0
 Report the number of channels. More...
 
virtual double GetRate () const=0
 
- Public Member Functions inherited from SampleTrack
 SampleTrack ()
 
 SampleTrack (const SampleTrack &other, ProtectedCreationArg &&)
 
 ~SampleTrack () override
 
const TypeInfoGetTypeInfo () const override
 
virtual sampleFormat GetSampleFormat () const =0
 
bool GetFloats (float *buffer, sampleCount start, size_t len, fillFormat fill=FillFormat::fillZero, bool mayThrow=true, sampleCount *pNumWithinClips=nullptr) const
 "narrow" overload fetches first channel only More...
 
double GetStartTime () const
 Get the minimum of Start() values of intervals, or 0 when none. More...
 
double GetEndTime () const
 Get the maximum of End() values of intervals, or 0 when none. More...
 
bool IsLeader () const override
 
bool GetFloats (size_t iChannel, size_t nBuffers, float *const buffers[], sampleCount start, size_t len, bool backwards=false, fillFormat fill=FillFormat::fillZero, bool mayThrow=true, sampleCount *pNumWithinClips=nullptr) const
 
- Public Member Functions inherited from PlayableTrack
 PlayableTrack ()
 
 PlayableTrack (const PlayableTrack &orig, ProtectedCreationArg &&)
 
bool GetMute () const
 
bool GetSolo () const
 
bool GetNotMute () const
 
bool GetNotSolo () const
 
void SetMute (bool m)
 
void SetSolo (bool s)
 
void WriteXMLAttributes (XMLWriter &xmlFile) const
 
bool HandleXMLAttribute (const std::string_view &attr, const XMLAttributeValueView &value)
 
- 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 &project, TrackList &list) const =0
 
virtual bool LinkConsistencyFix (bool doFix=true)
 Check consistency of channel groups, and maybe fix it. More...
 
bool LinkConsistencyCheck ()
 Do the non-mutating part of consistency fix only and return status. More...
 
bool HasOwner () const
 
std::shared_ptr< TrackListGetOwner () const
 
TrackListGetHolder () const
 
LinkType GetLinkType () const noexcept
 
ChannelGroupDataGetGroupData ()
 
const ChannelGroupDataGetGroupData () const
 May make group data on demand, but consider that logically const. More...
 
 Track ()
 
 Track (const Track &orig, ProtectedCreationArg &&)
 
Trackoperator= (const Track &orig)=delete
 
virtual ~Track ()
 
void Init (const Track &orig)
 
virtual TrackListHolder Duplicate (DuplicateOptions={}) const
 public nonvirtual duplication function that invokes Clone() More...
 
void ReparentAllAttachments ()
 
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 OnProjectTempoChange (double newTempo)
 method to set project tempo on track More...
 
virtual TrackListHolder Cut (double t0, double t1)=0
 Create tracks and modify this track. More...
 
virtual TrackListHolder Copy (double t0, double t1, bool forClipboard=true) const =0
 Create new tracks and don't modify this track. More...
 
virtual void Clear (double t0, double t1)=0
 
virtual void Paste (double t, const Track &src)=0
 Weak precondition allows overrides to replicate one channel into many. More...
 
void Paste (double t, const TrackList &src)
 
virtual void SyncLockAdjust (double oldT1, double newT1)
 
virtual void Silence (double t0, double t1, ProgressReporter reportProgress={})=0
 
virtual void InsertSilence (double t, double len)=0
 
bool SameKindAs (const Track &track) const
 
template<typename R = void, typename ... Functions>
TypeSwitch (const Functions &...functions)
 
template<typename R = void, typename ... Functions>
TypeSwitch (const Functions &...functions) const
 
virtual void WriteXML (XMLWriter &xmlFile) const =0
 
virtual std::optional< TranslatableStringGetErrorOpening () const
 
void Notify (bool allChannels, int code=-1)
 
bool Any () const
 
bool IsSelected () const
 
bool IsLeader () const override
 
bool IsSelectedLeader () const
 
void AdjustPositions ()
 
void WriteCommonXMLAttributes (XMLWriter &xmlFile, bool includeNameAndSelected=true) const
 
bool HandleCommonXMLAttribute (const std::string_view &attr, const XMLAttributeValueView &valueView)
 
const std::optional< double > & GetProjectTempo () const
 
- 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...
 
- Public Member Functions inherited from ChannelGroup
virtual ~ChannelGroup ()
 
double GetStartTime () const
 Get the minimum of Start() values of intervals, or 0 when none. More...
 
double GetEndTime () const
 Get the maximum of End() values of intervals, or 0 when none. More...
 
void ShiftBy (double t)
 Change start time by given duration. More...
 
virtual void MoveTo (double o)=0
 Change start time to given time point. More...
 
virtual bool IsLeader () const =0
 
ChannelGroupDataGetGroupData ()
 Make attachment site on demand as needed. More...
 
const ChannelGroupDataGetGroupData () const
 
ChannelGroupDataFindGroupData ()
 Do not make attachment site on demand if absent. More...
 
const ChannelGroupDataFindGroupData () const
 Do not make attachment site on demand if absent. More...
 
void Init (const ChannelGroup &other)
 Copy, including cloning of attached objects. More...
 
void DestroyGroupData ()
 Leave all attachments null. More...
 
std::unique_ptr< ChannelGroupDataDetachGroupData ()
 Move attachments out. More...
 
void AssignGroupData (std::unique_ptr< ChannelGroupData > pGroupData)
 Replace any previous attachments. More...
 
template<typename ChannelType = Channel>
std::shared_ptr< ChannelType > GetChannel (size_t iChannel)
 Retrieve a channel, cast to the given type. More...
 
template<typename ChannelType = const Channel>
auto GetChannel (size_t iChannel) const -> std::enable_if_t< std::is_const_v< ChannelType >, std::shared_ptr< ChannelType > >
 
template<typename ChannelType = Channel>
IteratorRange< ChannelIterator< ChannelType > > Channels ()
 Get range of channels with mutative access. More...
 
template<typename ChannelType = const Channel>
auto Channels () const -> std::enable_if_t< std::is_const_v< ChannelType >, IteratorRange< ChannelIterator< ChannelType > > >
 Get range of channels with read-only access. More...
 
template<typename IntervalType = Interval>
std::shared_ptr< IntervalType > GetInterval (size_t iInterval)
 Retrieve an interval, cast to the given type. More...
 
template<typename IntervalType = const Interval>
auto GetInterval (size_t iInterval) const -> std::enable_if_t< std::is_const_v< IntervalType >, std::shared_ptr< IntervalType > >
 
template<typename IntervalType = Interval>
IteratorRange< IntervalIterator< IntervalType > > Intervals ()
 Get range of intervals with mutative access. More...
 
template<typename IntervalType = const Interval>
auto Intervals () const -> std::enable_if_t< std::is_const_v< IntervalType >, IteratorRange< IntervalIterator< IntervalType > > >
 Get range of intervals with read-only access. More...
 
- Public Member Functions inherited from PlayableSequence
 ~PlayableSequence () override
 
virtual const ChannelGroupFindChannelGroup () const =0
 Find associated ChannelGroup if any. More...
 
virtual bool GetSolo () const =0
 May vary asynchronously. More...
 
virtual bool GetMute () const =0
 May vary asynchronously. More...
 
- Public Member Functions inherited from WideSampleSequence
virtual ~WideSampleSequence ()
 
virtual size_t NChannels () const =0
 A constant property. More...
 
virtual float GetChannelGain (int channel) const =0
 
bool GetFloats (size_t iChannel, size_t nBuffers, float *const buffers[], sampleCount start, size_t len, bool backwards=false, fillFormat fill=FillFormat::fillZero, bool mayThrow=true, sampleCount *pNumWithinClips=nullptr) const
 
virtual bool DoGet (size_t iChannel, size_t nBuffers, const samplePtr buffers[], sampleFormat format, sampleCount start, size_t len, bool backward, fillFormat fill=FillFormat::fillZero, bool mayThrow=true, sampleCount *pNumWithinClips=nullptr) const =0
 
virtual double GetStartTime () const =0
 
virtual double GetEndTime () const =0
 
virtual double GetRate () const =0
 
sampleCount TimeToLongSamples (double t0) const
 
double LongSamplesToTime (sampleCount pos) const
 
double SnapToSample (double t) const
 
virtual sampleFormat WidestEffectiveFormat () const =0
 
virtual bool HasTrivialEnvelope () const =0
 
virtual void GetEnvelopeValues (double *buffer, size_t bufferLen, double t0, bool backwards) const =0
 
- Public Member Functions inherited from AudioGraph::Channel
virtual ~Channel ()
 
virtual ChannelType GetChannelType () const =0
 Classify this channel. More...
 
- Public Member Functions inherited from RecordableSequence
virtual ~RecordableSequence ()
 
virtual sampleFormat GetSampleFormat () const =0
 
virtual double GetRate () const =0
 
virtual size_t NChannels () const =0
 A constant property. More...
 
virtual bool Append (constSamplePtr buffer, sampleFormat format, size_t len, unsigned int stride, sampleFormat effectiveFormat, size_t iChannel=0)=0
 Append the sample data to the track. You must call Flush() after the last Append. More...
 
bool Append (constSamplePtr buffer, sampleFormat format, size_t len, size_t iChannel=0)
 
virtual bool IsLeader () const =0
 
virtual void Flush ()=0
 Flush of related leader must be called after last Append. More...
 
virtual void InsertSilence (double t, double len)=0
 
- Public Member Functions inherited from WaveChannel
 ~WaveChannel () override
 
WaveTrackGetTrack ()
 
const WaveTrackGetTrack () const
 
WaveTrackReallyGetTrack ()
 TODO wide wave tracks – remove this. More...
 
const WaveTrackReallyGetTrack () const
 TODO wide wave tracks – remove this. More...
 
auto GetInterval (size_t iInterval)
 
auto GetInterval (size_t iInterval) const
 
auto Intervals ()
 
auto Intervals () const
 
bool GetFloats (float *buffer, sampleCount start, size_t len, fillFormat fill=FillFormat::fillZero, bool mayThrow=true, sampleCount *pNumWithinClips=nullptr) const
 "narrow" overload fetches from the unique channel More...
 
ChannelSampleView GetSampleView (double t0, double t1, bool mayThrow) const
 Request channel samples within [t0, t1), not knowing in advance how many this will be. More...
 
bool Set (constSamplePtr buffer, sampleFormat format, sampleCount start, size_t len, sampleFormat effectiveFormat=widestSampleFormat)
 Random-access assignment of a range of samples. More...
 
bool AppendBuffer (constSamplePtr buffer, sampleFormat format, size_t len, unsigned stride, sampleFormat effectiveFormat)
 
bool Append (constSamplePtr buffer, sampleFormat format, size_t len)
 
std::pair< float, float > GetMinMax (double t0, double t1, bool mayThrow=true) const
 
float GetRMS (double t0, double t1, bool mayThrow=true) const
 Get root-mean-square. More...
 
size_t GetBestBlockSize (sampleCount t) const
 A hint for sizing of well aligned fetches. More...
 
size_t GetIdealBlockSize ()
 A hint for sizing of well aligned fetches. More...
 
size_t GetMaxBlockSize () const
 
bool GetFloats (size_t iChannel, size_t nBuffers, float *const buffers[], sampleCount start, size_t len, bool backwards=false, fillFormat fill=FillFormat::fillZero, bool mayThrow=true, sampleCount *pNumWithinClips=nullptr) const
 
- Public Member Functions inherited from Channel
virtual ~Channel ()
 
ChannelGroupGetChannelGroup ()
 Channel object's lifetime is assumed to be nested in its Track's. More...
 
const ChannelGroupGetChannelGroup () const
 Channel object's lifetime is assumed to be nested in its Track's. More...
 
size_t GetChannelIndex () const
 
size_t ReallyGetChannelIndex () const
 
size_t NIntervals () const
 Report the number of intervals. More...
 
template<typename IntervalType = Interval>
std::shared_ptr< IntervalType > GetInterval (size_t iInterval)
 Retrieve an interval, cast to the given type. More...
 
template<typename IntervalType = const Interval>
auto GetInterval (size_t iInterval) const -> std::enable_if_t< std::is_const_v< IntervalType >, std::shared_ptr< IntervalType > >
 
template<typename IntervalType = Interval>
IteratorRange< IntervalIterator< IntervalType > > Intervals ()
 Get range of intervals with mutative access. More...
 
template<typename IntervalType = const Interval>
auto Intervals () const -> std::enable_if_t< std::is_const_v< IntervalType >, IteratorRange< IntervalIterator< IntervalType > > >
 Get range of intervals with read-only access. More...
 

Static Public Member Functions

static wxString GetDefaultAudioTrackNamePreference ()
 
static double ProjectNyquistFrequency (const AudacityProject &project)
 
static WaveTrackNew (AudacityProject &project)
 
static const TypeInfoClassTypeInfo ()
 
- Static Public Member Functions inherited from WritableSampleTrack
static const TypeInfoClassTypeInfo ()
 
- Static Public Member Functions inherited from SampleTrack
static const TypeInfoClassTypeInfo ()
 
- Static Public Member Functions inherited from PlayableTrack
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 Public Member Functions inherited from ClientData::Site< Host, ClientData, ObjectCopyingPolicy, Pointer, ObjectLockingPolicy, RegistryLockingPolicy >
static size_t numFactories ()
 How many static factories have been registered with this specialization of Site. More...
 

Private Member Functions

void Init (const WaveTrack &orig)
 
TrackListHolder Clone (bool backup) const override
 
wxString MakeClipCopyName (const wxString &originalName) const
 
wxString MakeNewClipName () const
 
void FlushOne ()
 
void HandleClear (double t0, double t1, bool addCutLines, bool split, bool clearByTrimming=false)
 
void ClearAndPasteAtSameTempo (double t0, double t1, const WaveTrack &src, bool preserve, bool merge, const TimeWarper *effectWarper, bool clearByTrimming)
 
void SplitAt (double t)
 
void ExpandOneCutLine (double cutLinePosition, double *cutlineStart, double *cutlineEnd)
 
bool MergeOneClipPair (int clipidx1, int clipidx2)
 
void ApplyPitchAndSpeedOnIntervals (const std::vector< IntervalHolder > &intervals, const ProgressReporter &reportProgress)
 
void InsertInterval (const IntervalHolder &interval)
 
void RemoveInterval (const IntervalHolder &interval)
 
void ReplaceInterval (const IntervalHolder &oldOne, const IntervalHolder &newOne)
 
std::shared_ptr< WideChannelGroupIntervalDoGetInterval (size_t iInterval) override
 Retrieve an interval. More...
 
std::shared_ptr<::ChannelDoGetChannel (size_t iChannel) override
 Retrieve a channel. More...
 
ChannelGroupDoGetChannelGroup () const override
 Subclass must override. More...
 
ChannelGroupReallyDoGetChannelGroup () const override
 This is temporary! It defaults to call the above. More...
 
void DoSetRate (double newRate)
 
void SetClipRates (double newRate)
 
void DoOnProjectTempoChange (const std::optional< double > &oldTempo, double newTempo) override
 
TrackListHolder DuplicateWithOtherTempo (double newTempo, WaveTrack *&leader) const
 
bool GetOne (samplePtr buffer, sampleFormat format, sampleCount start, size_t len, bool backwards, fillFormat fill, bool mayThrow, sampleCount *pNumWithinClips) const
 
size_t GetFloatsFromTime (double t, size_t iChannel, float *buffer, size_t numSamples, bool mayThrow, PlaybackDirection direction) const
 Helper for GetFloatsCenteredAroundTime. If direction == PlaybackDirection::Backward, fetches samples to the left of t, excluding t, without reversing. More...
 
void SetFloatsFromTime (double t, size_t iChannel, const float *buffer, size_t numSamples, sampleFormat effectiveFormat, PlaybackDirection direction)
 Similar to GetFloatsFromTime, but for writing. Sets as many samples as it can according to the same rules as GetFloatsFromTime. Leaves the other samples untouched. More...
 
void DoSetPan (float value)
 
void DoSetGain (float value)
 
void PasteWaveTrack (double t0, const WaveTrack &other, bool merge)
 
void PasteWaveTrackAtSameTempo (double t0, const WaveTrack &other, bool merge)
 
bool RateConsistencyCheck () const
 Whether all clips of a leader track have a common rate. More...
 
bool FormatConsistencyCheck () const
 Whether all tracks in group and all clips have a common sample format. More...
 
bool InsertClip (WaveClipHolder clip, bool backup=false)
 Adds clip to the track. Clip should be not empty or to be a placeholder. More...
 
void ApplyPitchAndSpeedOne (double t0, double t1, const ProgressReporter &reportProgress)
 

Static Private Member Functions

static void ClearAndPasteOne (WaveTrack &track, double t0, double t1, double startTime, double endTime, const WaveTrack &src, bool preserve, bool merge, const TimeWarper *effectWarper, bool clearByTrimming)
 
static void JoinOne (WaveTrack &track, double t0, double t1)
 
static Holder CopyOne (const WaveTrack &track, double t0, double t1, bool forClipboard)
 
static void WriteOneXML (const WaveTrack &track, XMLWriter &xmlFile, size_t iChannel, size_t nChannels)
 
static bool ReverseOne (WaveTrack &track, sampleCount start, sampleCount len, const ProgressReport &report={})
 
static bool ReverseOneClip (WaveTrack &track, sampleCount start, sampleCount len, sampleCount originalStart, sampleCount originalEnd, const ProgressReport &report={})
 
static void PasteOne (WaveTrack &track, double t0, const WaveTrack &other, double startTime, double insertDuration, bool merge=true)
 

Private Attributes

WaveClipHolders mClips
 
int mLegacyRate { 0 }
 used only during deserialization More...
 
sampleFormat mLegacyFormat { undefinedSample }
 used only during deserialization More...
 
SampleBlockFactoryPtr mpFactory
 
wxCriticalSection mFlushCriticalSection
 
wxCriticalSection mAppendCriticalSection
 
double mLegacyProjectFileOffset
 
friend WaveChannel
 

Friends

class WaveTrackFactory
 

Additional Inherited Members

- Protected Member Functions inherited from PlayableTrack
bool DoGetMute () const
 
void DoSetMute (bool value)
 
bool DoGetSolo () const
 
void DoSetSolo (bool value)
 
- Protected Member Functions inherited from Track
void SetLinkType (LinkType linkType, bool completeList=true)
 
virtual void DoOnProjectTempoChange (const std::optional< double > &oldTempo, double newTempo)=0
 
- 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...
 
virtual std::shared_ptr< ChannelDoGetChannel (size_t iChannel)=0
 Retrieve a channel. More...
 
virtual std::shared_ptr< IntervalDoGetInterval (size_t iInterval)=0
 Retrieve an interval. More...
 
virtual ChannelGroupDoGetChannelGroup () const =0
 Subclass must override. More...
 
virtual ChannelGroupReallyDoGetChannelGroup () const
 This is temporary! It defaults to call the above. 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...
 

Detailed Description

A Track that contains audio waveform data.

Definition at line 223 of file WaveTrack.h.

Member Typedef Documentation

◆ Holder

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

Definition at line 303 of file WaveTrack.h.

◆ IntervalConstHolder

using WaveTrack::IntervalConstHolder = std::shared_ptr<const Interval>

Definition at line 1027 of file WaveTrack.h.

◆ IntervalHolder

using WaveTrack::IntervalHolder = std::shared_ptr<Interval>

Definition at line 1026 of file WaveTrack.h.

◆ ProgressReport

using WaveTrack::ProgressReport = std::function<bool(double)>

Argument is in (0, 1)

Returns
true if processing should continue

Definition at line 920 of file WaveTrack.h.

◆ Regions

using WaveTrack::Regions = std::vector < Region >

Definition at line 248 of file WaveTrack.h.

Constructor & Destructor Documentation

◆ WaveTrack() [1/2]

WaveTrack::WaveTrack ( const SampleBlockFactoryPtr pFactory,
sampleFormat  format,
double  rate 
)

Definition at line 811 of file WaveTrack.cpp.

813 : mpFactory(pFactory)
814{
816
817 WaveTrackData::Get(*this).SetSampleFormat(format);
818 DoSetRate(static_cast<int>(rate));
819}
SampleBlockFactoryPtr mpFactory
Definition: WaveTrack.h:1209
void DoSetRate(double newRate)
Definition: WaveTrack.cpp:1143
double mLegacyProjectFileOffset
Definition: WaveTrack.h:1213
Services * Get()
Fetch the global instance, or nullptr if none is yet installed.
Definition: BasicUI.cpp:196

References DoSetRate(), anonymous_namespace{ExportPCM.cpp}::format, BasicUI::Get(), and mLegacyProjectFileOffset.

Here is the call graph for this function:

◆ WaveTrack() [2/2]

WaveTrack::WaveTrack ( const WaveTrack orig,
ProtectedCreationArg &&  a,
bool  backup 
)

Copied only in WaveTrack::Clone() !

Definition at line 821 of file WaveTrack.cpp.

823 : WritableSampleTrack(orig, std::move(a))
824 , mpFactory( orig.mpFactory )
825{
827 for (const auto &clip : orig.mClips)
828 InsertClip(std::make_shared<WaveClip>(*clip, mpFactory, true), backup);
829}
bool InsertClip(WaveClipHolder clip, bool backup=false)
Adds clip to the track. Clip should be not empty or to be a placeholder.
Definition: WaveTrack.cpp:2381
WaveClipHolders mClips
Definition: WaveTrack.h:1122

References InsertClip(), mClips, mLegacyProjectFileOffset, and mpFactory.

Here is the call graph for this function:

◆ ~WaveTrack()

WaveTrack::~WaveTrack ( )
virtual

Definition at line 876 of file WaveTrack.cpp.

877{
878}

Member Function Documentation

◆ AddClip()

bool WaveTrack::AddClip ( const std::shared_ptr< WaveClip > &  clip)

Append a clip to the track; to succeed, must have the same block factory as this track, and this->GetWidth() == clip->GetWidth(); return success

Precondition
clip != nullptr
this->GetWidth() == clip->GetWidth()

Definition at line 1935 of file WaveTrack.cpp.

1936{
1937 assert(clip);
1938 if (clip->GetSequence(0)->GetFactory() != this->mpFactory)
1939 return false;
1940
1941 if (clip->GetWidth() != GetWidth())
1942 return false;
1943
1944 // Uncomment the following line after we correct the problem of zero-length clips
1945 //if (CanInsertClip(clip))
1946 InsertClip(clip); // transfer ownership
1947
1948 return true;
1949}
size_t GetWidth() const
The width of every WaveClip in this track; for now always 1.
Definition: WaveTrack.cpp:831

References GetWidth(), and InsertClip().

Referenced by ClearAndPasteOne(), and ReverseOne().

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

◆ Append()

bool WaveTrack::Append ( constSamplePtr  buffer,
sampleFormat  format,
size_t  len,
unsigned int  stride = 1,
sampleFormat  effectiveFormat = widestSampleFormat,
size_t  iChannel = 0 
)
overridevirtual

If there is an existing WaveClip in the WaveTrack, then the data are appended to that clip. If there are no WaveClips in the track, then a new one is created.

Returns
true if at least one complete block was created
Exception safety guarantee:
Partial – Some prefix (maybe none) of the buffer is appended, and no content already flushed to disk is lost.

Implements RecordableSequence.

Definition at line 2707 of file WaveTrack.cpp.

2710{
2711 // TODO wide wave tracks -- there will be only one clip, and its `Append`
2712 // (or an overload) must take iChannel
2713 auto pTrack = this;
2714 if (GetOwner() && iChannel == 1)
2715 pTrack = *TrackList::Channels(this).rbegin();
2716 constSamplePtr buffers[]{ buffer };
2717 return pTrack->RightmostOrNewClip()
2718 ->Append(buffers, format, len, stride, effectiveFormat);
2719}
const char * constSamplePtr
Definition: SampleFormat.h:58
std::shared_ptr< TrackList > GetOwner() const
Definition: Track.h:254
static auto Channels(TrackType *pTrack) -> TrackIterRange< TrackType >
Definition: Track.h:1164

References TrackList::Channels(), anonymous_namespace{ExportPCM.cpp}::format, Track::GetOwner(), and anonymous_namespace{StretchingSequenceIntegrationTest.cpp}::iChannel.

Referenced by WaveChannel::Append(), and WaveChannel::AppendBuffer().

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

◆ ApplyPitchAndSpeed()

void WaveTrack::ApplyPitchAndSpeed ( std::optional< TimeInterval interval,
ProgressReporter  reportProgress 
)

Definition at line 2394 of file WaveTrack.cpp.

2396{
2397 assert(IsLeader());
2398 // Assert that the interval is reasonable, but this function will be no-op
2399 // anyway if not
2400 assert(!interval.has_value() ||
2401 interval->first <= interval->second);
2402 if (GetNumClips() == 0)
2403 return;
2404 const auto startTime =
2405 interval ? std::max(SnapToSample(interval->first), GetStartTime()) :
2406 GetStartTime();
2407 const auto endTime =
2408 interval ? std::min(SnapToSample(interval->second), GetEndTime()) :
2409 GetEndTime();
2410 if (startTime >= endTime)
2411 return;
2412
2413 // Here we assume that left- and right clips are aligned.
2414 if (auto clipAtT0 = GetClipAtTime(startTime);
2415 clipAtT0 && clipAtT0->SplitsPlayRegion(startTime) &&
2416 clipAtT0->HasPitchOrSpeed())
2417 Split(startTime, startTime);
2418 if (auto clipAtT1 = GetClipAtTime(endTime);
2419 clipAtT1 && clipAtT1->SplitsPlayRegion(endTime) &&
2420 clipAtT1->HasPitchOrSpeed())
2421 Split(endTime, endTime);
2422
2423 std::vector<IntervalHolder> srcIntervals;
2424 auto clip = GetIntervalAtTime(startTime);
2425 while (clip && clip->GetPlayStartTime() < endTime)
2426 {
2427 if (clip->HasPitchOrSpeed())
2428 srcIntervals.push_back(clip);
2430 }
2431
2432 ApplyPitchAndSpeedOnIntervals(srcIntervals, reportProgress);
2433}
int min(int a, int b)
bool SplitsPlayRegion(double t) const
[ < t and t < ), such that if the track were split at t, it would split this clip in two of lengths >...
Definition: WaveClip.cpp:1446
const WaveClip * GetClipAtTime(double time) const
Definition: WaveTrack.cpp:3759
double GetStartTime() const override
Implement WideSampleSequence.
Definition: WaveTrack.cpp:3087
void ApplyPitchAndSpeedOnIntervals(const std::vector< IntervalHolder > &intervals, const ProgressReporter &reportProgress)
Definition: WaveTrack.cpp:4139
IntervalConstHolder GetNextInterval(const Interval &interval, PlaybackDirection searchDirection) const
Definition: WaveTrack.cpp:534
bool IsLeader() const override
Definition: WaveTrack.cpp:2820
void Split(double t0, double t1)
Definition: WaveTrack.cpp:3993
double GetEndTime() const override
Implement WideSampleSequence.
Definition: WaveTrack.cpp:3092
int GetNumClips() const
Definition: WaveTrack.cpp:3872
IntervalHolder GetIntervalAtTime(double t)
Definition: WaveTrack.cpp:563
double SnapToSample(double t) const

References ApplyPitchAndSpeedOnIntervals(), forward, GetClipAtTime(), GetEndTime(), GetIntervalAtTime(), GetNextInterval(), GetNumClips(), GetStartTime(), IsLeader(), min(), WideSampleSequence::SnapToSample(), Split(), and WaveClip::SplitsPlayRegion().

Referenced by Silence().

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

◆ ApplyPitchAndSpeedOne()

void WaveTrack::ApplyPitchAndSpeedOne ( double  t0,
double  t1,
const ProgressReporter reportProgress 
)
private

◆ ApplyPitchAndSpeedOnIntervals()

void WaveTrack::ApplyPitchAndSpeedOnIntervals ( const std::vector< IntervalHolder > &  intervals,
const ProgressReporter reportProgress 
)
private

Definition at line 4139 of file WaveTrack.cpp.

4142{
4143 std::vector<IntervalHolder> dstIntervals;
4144 dstIntervals.reserve(srcIntervals.size());
4145 std::transform(
4146 srcIntervals.begin(), srcIntervals.end(),
4147 std::back_inserter(dstIntervals), [&](const IntervalHolder& interval) {
4148 return interval->GetRenderedCopy(
4149 reportProgress, *this, mpFactory, GetSampleFormat());
4150 });
4151
4152 // If we reach this point it means that no error was thrown - we can replace
4153 // the source with the destination intervals.
4154 for (auto i = 0; i < srcIntervals.size(); ++i)
4155 ReplaceInterval(srcIntervals[i], dstIntervals[i]);
4156}
std::shared_ptr< Interval > IntervalHolder
Definition: WaveTrack.h:1026
void ReplaceInterval(const IntervalHolder &oldOne, const IntervalHolder &newOne)
Definition: WaveTrack.cpp:4183

References ReplaceInterval().

Referenced by ApplyPitchAndSpeed(), and Join().

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

◆ CanInsertClip()

bool WaveTrack::CanInsertClip ( const WaveClip clip,
double &  slideBy,
double  tolerance 
) const

Definition at line 3951 of file WaveTrack.cpp.

3953{
3954 if (mClips.empty())
3955 return true;
3956 // Find clip in this that overlaps most with `clip`:
3957 const auto candidateClipStartTime = candidateClip.GetPlayStartTime();
3958 const auto candidateClipEndTime = candidateClip.GetPlayEndTime();
3959 const auto t0 = SnapToSample(candidateClipStartTime + slideBy);
3960 const auto t1 = SnapToSample(candidateClipEndTime + slideBy);
3961 std::vector<double> overlaps;
3962 std::transform(
3963 mClips.begin(), mClips.end(), std::back_inserter(overlaps),
3964 [&](const auto& pClip) {
3965 return pClip->IntersectsPlayRegion(t0, t1) ?
3966 std::min(pClip->GetPlayEndTime(), t1) -
3967 std::max(pClip->GetPlayStartTime(), t0) :
3968 0.0;
3969 });
3970 const auto maxOverlap = std::max_element(overlaps.begin(), overlaps.end());
3971 if (*maxOverlap > tolerance)
3972 return false;
3973 const auto overlappedClip =
3974 mClips[std::distance(overlaps.begin(), maxOverlap)];
3975 const auto requiredOffset = slideBy +
3976 *maxOverlap * (overlappedClip->GetPlayStartTime() < t0 ? 1 : -1);
3977 // Brute-force check to see if there's another clip that'd be in the way.
3978 if (std::any_of(
3979 mClips.begin(), mClips.end(),
3980 [&](const auto& pClip)
3981 {
3982 const auto result = pClip->IntersectsPlayRegion(
3983 SnapToSample(candidateClipStartTime + requiredOffset),
3984 SnapToSample(candidateClipEndTime + requiredOffset));
3985 return result;
3986 }))
3987 return false;
3988 slideBy = requiredOffset;
3989 return true;
3990}

References WaveClip::GetPlayEndTime(), WaveClip::GetPlayStartTime(), mClips, and WideSampleSequence::SnapToSample().

Here is the call graph for this function:

◆ CanOffsetClips()

bool WaveTrack::CanOffsetClips ( const std::vector< WaveClip * > &  clips,
double  amount,
double *  allowedAmount = nullptr 
)

Decide whether the clips could be offset (and inserted) together without overlapping other clips.

Returns
true if possible to offset by (allowedAmount ? *allowedAmount : amount)
Parameters
clipsnot necessarily in this track
amountsigned
[out]allowedAmountif null, test exact amount only; else, largest (in magnitude) possible offset with same sign

Definition at line 3893 of file WaveTrack.cpp.

3897{
3898 if (allowedAmount)
3899 *allowedAmount = amount;
3900
3901 const auto &moving = [&](WaveClip *clip){
3902 // linear search might be improved, but expecting few moving clips
3903 // compared with the fixed clips
3904 return clips.end() != std::find( clips.begin(), clips.end(), clip );
3905 };
3906
3907 for (const auto &c: mClips) {
3908 if ( moving( c.get() ) )
3909 continue;
3910 for (const auto clip : clips) {
3911 if (c->GetPlayStartTime() < clip->GetPlayEndTime() + amount &&
3912 c->GetPlayEndTime() > clip->GetPlayStartTime() + amount)
3913 {
3914 if (!allowedAmount)
3915 return false; // clips overlap
3916
3917 if (amount > 0)
3918 {
3919 if (c->GetPlayStartTime() - clip->GetPlayEndTime() < *allowedAmount)
3920 *allowedAmount = c->GetPlayStartTime() - clip->GetPlayEndTime();
3921 if (*allowedAmount < 0)
3922 *allowedAmount = 0;
3923 } else
3924 {
3925 if (c->GetPlayEndTime() - clip->GetPlayStartTime() > *allowedAmount)
3926 *allowedAmount = c->GetPlayEndTime() - clip->GetPlayStartTime();
3927 if (*allowedAmount > 0)
3928 *allowedAmount = 0;
3929 }
3930 }
3931 }
3932 }
3933
3934 if (allowedAmount)
3935 {
3936 if (*allowedAmount == amount)
3937 return true;
3938
3939 // Check if the NEW calculated amount would not violate
3940 // any other constraint
3941 if (!CanOffsetClips(clips, *allowedAmount, nullptr)) {
3942 *allowedAmount = 0; // play safe and don't allow anything
3943 return false;
3944 }
3945 else
3946 return true;
3947 } else
3948 return true;
3949}
This allows multiple clips to be a part of one WaveTrack.
Definition: WaveClip.h:113
bool CanOffsetClips(const std::vector< WaveClip * > &clips, double amount, double *allowedAmount=nullptr)
Decide whether the clips could be offset (and inserted) together without overlapping other clips.
Definition: WaveTrack.cpp:3893

References CanOffsetClips(), and mClips.

Referenced by CanOffsetClips().

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

◆ Channels() [1/2]

auto WaveTrack::Channels ( )
inline

Definition at line 277 of file WaveTrack.h.

277 {
278 return this->ChannelGroup::Channels<WaveChannel>(); }

Referenced by EffectTruncSilence::Analyze(), CompareAudioCommand::Apply(), EffectTruncSilence::DoRemoval(), GetSampleView(), EffectLoudness::LoadBufferBlock(), PerTrackEffect::ProcessPass(), SetRate(), and EffectLoudness::StoreBufferBlock().

Here is the caller graph for this function:

◆ Channels() [2/2]

auto WaveTrack::Channels ( ) const
inline

Definition at line 279 of file WaveTrack.h.

279 {
280 return this->ChannelGroup::Channels<const WaveChannel>(); }

◆ ClassTypeInfo()

auto WaveTrack::ClassTypeInfo ( )
static

Definition at line 999 of file WaveTrack.cpp.

1000{
1001 return typeInfo();
1002}
static const Track::TypeInfo & typeInfo()
Definition: WaveTrack.cpp:986

References typeInfo().

Here is the call graph for this function:

◆ Clear()

void WaveTrack::Clear ( double  t0,
double  t1 
)
overridevirtual
Exception safety guarantee:
Strong

Implements Track.

Definition at line 1479 of file WaveTrack.cpp.

1480{
1481 assert(IsLeader());
1482 for (const auto pChannel : TrackList::Channels(this))
1483 pChannel->HandleClear(t0, t1, false, false);
1484}

References TrackList::Channels(), and IsLeader().

Referenced by Cut(), EffectTruncSilence::DoRemoval(), anonymous_namespace{LabelMenus.cpp}::OnCutLabels(), TrackSpectrumTransformer::PostProcess(), EffectStereoToMono::ProcessOne(), SyncLockAdjust(), and Trim().

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

◆ ClearAndAddCutLine()

void WaveTrack::ClearAndAddCutLine ( double  t0,
double  t1 
)

May assume precondition: t0 <= t1

Precondition
IsLeader()
Exception safety guarantee:
Strong

Definition at line 1487 of file WaveTrack.cpp.

1488{
1489 assert(IsLeader());
1490 for (const auto pChannel : TrackList::Channels(this))
1491 pChannel->HandleClear(t0, t1, true, false);
1492}

References TrackList::Channels(), and IsLeader().

Referenced by anonymous_namespace{LabelMenus.cpp}::OnCutLabels().

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

◆ ClearAndPaste() [1/2]

void WaveTrack::ClearAndPaste ( double  t0,
double  t1,
const TrackList src,
bool  preserve = true,
bool  merge = true,
const TimeWarper effectWarper = nullptr 
)
inline

Overload that takes a TrackList and passes its first wave track

Precondition
**src.Any<const WaveTrack>().begin() satisfies preconditions of the other overload for src

Definition at line 439 of file WaveTrack.h.

444 {
445 ClearAndPaste(t0, t1, **src.Any<const WaveTrack>().begin(),
446 preserve, merge, effectWarper);
447 }
auto Any() -> TrackIterRange< TrackType >
Definition: Track.h:1097
A Track that contains audio waveform data.
Definition: WaveTrack.h:227
void ClearAndPaste(double t0, double t1, const WaveTrack &src, bool preserve=true, bool merge=true, const TimeWarper *effectWarper=nullptr, bool clearByTrimming=false)
Definition: WaveTrack.cpp:1541

References TrackList::Any().

Here is the call graph for this function:

◆ ClearAndPaste() [2/2]

void WaveTrack::ClearAndPaste ( double  t0,
double  t1,
const WaveTrack src,
bool  preserve = true,
bool  merge = true,
const TimeWarper effectWarper = nullptr,
bool  clearByTrimming = false 
)

May assume precondition: t0 <= t1 If the source has one channel and this has more, then replicate source

Precondition
IsLeader()
src.IsLeader()
src.NChannels() == 1 || src.NChannels() == NChannels()
Exception safety guarantee:
Weak – This WaveTrack remains destructible in case of AudacityException. But some of its cutline clips may have been destroyed.

Definition at line 1541 of file WaveTrack.cpp.

1549{
1550 // Get a modifiable copy of `src` because it may come from another project
1551 // with different tempo, making boundary queries incorrect.
1552 const auto& tempo = GetProjectTempo();
1553 if (!tempo.has_value())
1555 WaveTrack* copy;
1556 const auto copyHolder = src.DuplicateWithOtherTempo(*tempo, copy);
1558 t0, t1, *copy, preserve, merge, effectWarper, clearByTrimming);
1559}
#define THROW_INCONSISTENCY_EXCEPTION
Throw InconsistencyException, using C++ preprocessor to identify the source code location.
const std::optional< double > & GetProjectTempo() const
Definition: Track.cpp:1369
void ClearAndPasteAtSameTempo(double t0, double t1, const WaveTrack &src, bool preserve, bool merge, const TimeWarper *effectWarper, bool clearByTrimming)
Definition: WaveTrack.cpp:1561
TrackListHolder DuplicateWithOtherTempo(double newTempo, WaveTrack *&leader) const
Definition: WaveTrack.cpp:903
void copy(const T *src, T *dst, int32_t n)
Definition: VectorOps.h:40

References ClearAndPasteAtSameTempo(), staffpad::vo::copy(), DuplicateWithOtherTempo(), Track::GetProjectTempo(), and THROW_INCONSISTENCY_EXCEPTION.

Referenced by EffectSBSMS::Finalize(), anonymous_namespace{EditMenus.cpp}::OnPaste(), and EffectNoiseRemoval::ProcessOne().

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

◆ ClearAndPasteAtSameTempo()

void WaveTrack::ClearAndPasteAtSameTempo ( double  t0,
double  t1,
const WaveTrack src,
bool  preserve,
bool  merge,
const TimeWarper effectWarper,
bool  clearByTrimming 
)
private

Definition at line 1561 of file WaveTrack.cpp.

1564{
1565 const auto srcNChannels = src.NChannels();
1566 assert(IsLeader());
1567 assert(src.IsLeader());
1568 assert(srcNChannels == 1 || srcNChannels == NChannels());
1569 assert(
1570 GetProjectTempo().has_value() &&
1571 GetProjectTempo() == src.GetProjectTempo());
1572
1573 t0 = SnapToSample(t0);
1574 t1 = SnapToSample(t1);
1575
1576 const auto startTime = src.GetStartTime();
1577 const auto endTime = src.GetEndTime();
1578 double dur = std::min(t1 - t0, endTime);
1579
1580 // If duration is 0, then it's just a plain paste
1581 if (dur == 0.0) {
1582 // use Weak-guarantee
1583 PasteWaveTrack(t0, src, merge);
1584 return;
1585 }
1586
1587 auto iter = TrackList::Channels(&src).begin();
1588 const auto myChannels = TrackList::Channels(this);
1589 for (const auto pChannel : myChannels) {
1591 *pChannel, t0, t1, startTime, endTime, **iter, preserve, merge,
1592 effectWarper, clearByTrimming);
1593 if (srcNChannels > 1)
1594 ++iter;
1595 }
1596}
static void ClearAndPasteOne(WaveTrack &track, double t0, double t1, double startTime, double endTime, const WaveTrack &src, bool preserve, bool merge, const TimeWarper *effectWarper, bool clearByTrimming)
Definition: WaveTrack.cpp:1598
size_t NChannels() const override
May report more than one only when this is a leader track.
Definition: WaveTrack.cpp:836
void PasteWaveTrack(double t0, const WaveTrack &other, bool merge)
Definition: WaveTrack.cpp:2143

References TrackList::Channels(), ClearAndPasteOne(), GetEndTime(), Track::GetProjectTempo(), GetStartTime(), IsLeader(), min(), NChannels(), PasteWaveTrack(), and WideSampleSequence::SnapToSample().

Referenced by ClearAndPaste().

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

◆ ClearAndPasteOne()

void WaveTrack::ClearAndPasteOne ( WaveTrack track,
double  t0,
double  t1,
double  startTime,
double  endTime,
const WaveTrack src,
bool  preserve,
bool  merge,
const TimeWarper effectWarper,
bool  clearByTrimming 
)
staticprivate

Definition at line 1598 of file WaveTrack.cpp.

1602{
1603 const auto pFactory = track.mpFactory;
1604
1605 std::vector<SplitInfo> splits;
1606 WaveClipHolders cuts;
1607
1608 //helper routine, that finds SplitInfo by time value,
1609 //or creates a new one if no one exists yet
1610 auto get_split = [&](double time) {
1611 auto it = std::find_if(splits.begin(), splits.end(),
1612 [time](const SplitInfo& split) { return split.time == time; });
1613 if(it == splits.end())
1614 it = splits.insert(
1615 splits.end(),
1616 { time, nullptr, nullptr, std::nullopt, std::nullopt }
1617 );
1618 return it;
1619 };
1620
1621 // If provided time warper was NULL, use a default one that does nothing
1622 IdentityTimeWarper localWarper;
1623 const TimeWarper *warper = (effectWarper ? effectWarper : &localWarper);
1624
1625 const auto roundTime = [&track](double t){
1626 return track.SnapToSample(t);
1627 };
1628
1629 // Align to a sample
1630 t0 = roundTime(t0);
1631 t1 = roundTime(t1);
1632
1633 // Save the cut/split lines whether preserving or not since merging
1634 // needs to know if a clip boundary is being crossed since Paste()
1635 // will add split lines around the pasted clip if so.
1636 for (const auto &clip : track.mClips) {
1637 double st;
1638
1639 // Remember clip boundaries as locations to split
1640 // we need to copy clips, trims and names, because the original ones
1641 // could be changed later during Clear/Paste routines
1642 st = roundTime(clip->GetPlayStartTime());
1643 if (st >= t0 && st <= t1) {
1644 auto it = get_split(st);
1645 if (clip->GetTrimLeft() != 0) {
1646 //keep only hidden left part
1647 it->right = std::make_shared<WaveClip>(*clip, pFactory, false);
1648 it->right->SetTrimLeft(.0);
1649 it->right->ClearRight(clip->GetPlayStartTime());
1650 }
1651 it->rightClipName = clip->GetName();
1652 }
1653
1654 st = roundTime(clip->GetPlayEndTime());
1655 if (st >= t0 && st <= t1) {
1656 auto it = get_split(st);
1657 if (clip->GetTrimRight() != 0) {
1658 //keep only hidden right part
1659 it->left = std::make_shared<WaveClip>(*clip, pFactory, false);
1660 it->left->SetTrimRight(.0);
1661 it->left->ClearLeft(clip->GetPlayEndTime());
1662 }
1663 it->leftClipName = clip->GetName();
1664 }
1665
1666 // Search for cut lines
1667 auto &cutlines = clip->GetCutLines();
1668 // May erase from cutlines, so don't use range-for
1669 for (auto it = cutlines.begin(); it != cutlines.end(); ) {
1670 WaveClip *cut = it->get();
1671 const double cs = roundTime(
1672 clip->GetSequenceStartTime() + cut->GetSequenceStartTime());
1673
1674 // Remember cut point
1675 if (cs >= t0 && cs <= t1) {
1676 // Remember the absolute offset and add to our cuts array.
1677 cut->SetSequenceStartTime(cs);
1678 cuts.push_back(std::move(*it)); // transfer ownership!
1679 it = cutlines.erase(it);
1680 }
1681 else
1682 ++it;
1683 }
1684 }
1685
1686 const auto tolerance = 2.0 / track.GetRate();
1687
1688 // This is not a split-cut operation.
1689 constexpr auto split = false;
1690
1691 // Now, clear the selection
1692 track.HandleClear(t0, t1, false, split, clearByTrimming);
1693
1694 // And paste in the new data
1695 PasteOne(track, t0, src, startTime, endTime, merge);
1696
1697 // First, merge the new clip(s) in with the existing clips
1698 if (merge && splits.size() > 0) {
1699 {
1700 // Now t1 represents the absolute end of the pasted data.
1701 t1 = t0 + endTime;
1702
1703 // Get a sorted array of the clips
1704 auto clips = track.SortedClipArray();
1705
1706 // Scan the sorted clips for the first clip whose start time
1707 // exceeds the pasted regions end time.
1708 {
1709 WaveClip *prev = nullptr;
1710 for (const auto clip : clips) {
1711 // Merge this clip and the previous clip if the end time
1712 // falls within it and this isn't the first clip in the track.
1713 if (fabs(t1 - clip->GetPlayStartTime()) < tolerance) {
1714 if (prev && clip->HasEqualPitchAndSpeed(*prev))
1715 track.MergeOneClipPair(track.GetClipIndex(prev),
1716 track.GetClipIndex(clip));
1717 break;
1718 }
1719 prev = clip;
1720 }
1721 }
1722 }
1723
1724 {
1725 // Refill the array since clips have changed.
1726 auto clips = track.SortedClipArray();
1727
1728 // Scan the sorted clips to look for the start of the pasted
1729 // region.
1730 WaveClip *prev = nullptr;
1731 for (const auto clip : clips) {
1732 if (prev) {
1733 // It must be that clip is what was pasted and it begins where
1734 // prev ends.
1735 // use Weak-guarantee
1736 if (clip->HasEqualPitchAndSpeed(*prev))
1737 track.MergeOneClipPair(
1738 track.GetClipIndex(prev), track.GetClipIndex(clip));
1739 break;
1740 }
1741 if (fabs(t0 - clip->GetPlayEndTime()) < tolerance)
1742 // Merge this clip and the next clip if the start time
1743 // falls within it and this isn't the last clip in the track.
1744 prev = clip;
1745 else
1746 prev = nullptr;
1747 }
1748 }
1749 }
1750
1751 // Restore cut/split lines
1752 if (preserve) {
1753 auto attachLeft = [](WaveClip& target, WaveClip& src) {
1754 // What this lambda does is restoring the left hidden data of `target`
1755 // that was cleared by `HandleClear`. Hence, `target` has no left
1756 // hidden data at this stage.
1757 assert(target.GetTrimLeft() == 0);
1758 if (target.GetTrimLeft() != 0)
1759 return;
1760
1761 // `src` was created by copy from `target`, so they have equal width,
1762 // pitch and speed.
1763 assert(target.GetWidth() == src.GetWidth());
1764 assert(target.HasEqualPitchAndSpeed(src));
1765
1766 auto trim = src.GetPlayEndTime() - src.GetPlayStartTime();
1767 auto success = target.Paste(target.GetPlayStartTime(), src);
1768 assert(success); // because of precondition above
1769 target.SetTrimLeft(trim);
1770 //Play start time needs to be adjusted after
1771 //prepending data to the sequence
1772 target.ShiftBy(-trim);
1773 };
1774
1775 auto attachRight = [](WaveClip &target, WaveClip &src)
1776 {
1777 // See `attachLeft` for rationale behind these asserts.
1778 assert(target.GetTrimRight() == 0);
1779 if (target.GetTrimRight() != 0)
1780 return;
1781 assert(target.GetWidth() == src.GetWidth());
1782 assert(target.HasEqualPitchAndSpeed(src));
1783
1784 auto trim = src.GetPlayEndTime() - src.GetPlayStartTime();
1785 auto success = target.Paste(target.GetPlayEndTime(), src);
1786 assert(success); // because of precondition above
1787 target.SetTrimRight(trim);
1788 };
1789
1790 // Restore the split lines and trims, transforming the position appropriately
1791 for (const auto& split: splits) {
1792 auto at = roundTime(warper->Warp(split.time));
1793 for (const auto& clip : track.GetClips()) {
1794 // Clips in split began as copies of a clip in the track,
1795 // therefore have the same width, satisfying preconditions to
1796 // attach
1797 if (clip->SplitsPlayRegion(at))//strictly inside
1798 {
1799 auto newClip =
1800 std::make_shared<WaveClip>(*clip, pFactory, true);
1801
1802 clip->ClearRight(at);
1803 newClip->ClearLeft(at);
1804 if (split.left)
1805 // clip was cleared right
1806 attachRight(*clip, *split.left);
1807 if (split.right)
1808 // new clip was cleared left
1809 attachLeft(*newClip, *split.right);
1810 bool success = track.AddClip(std::move(newClip));
1811 assert(success); // copied clip has same width and factory
1812 break;
1813 }
1814 else if (clip->GetPlayStartSample() ==
1815 track.TimeToLongSamples(at) && split.right) {
1816 // Satisfy the precondition of attachLeft first!
1817 const auto trim = clip->GetTrimLeft();
1818 const auto seqStartTime = clip->GetSequenceStartTime();
1819 clip->Clear(seqStartTime, seqStartTime + trim);
1820 // This clearing, although only removing the hidden part, moved
1821 // the clip leftwards. We don't want this in this case.
1822 clip->ShiftBy(trim);
1823 attachLeft(*clip, *split.right);
1824 break;
1825 }
1826 else if (clip->GetPlayEndSample() ==
1827 track.TimeToLongSamples(at) && split.left) {
1828 // Satisfy the precondition of attachRight first!
1829 clip->Clear(
1830 clip->GetPlayEndTime(), clip->GetSequenceEndTime());
1831 attachRight(*clip, *split.left);
1832 break;
1833 }
1834 }
1835 }
1836
1837 //Restore clip names
1838 for (const auto& split : splits)
1839 {
1840 auto s = track.TimeToLongSamples(warper->Warp(split.time));
1841 for (auto& clip : track.GetClips()) {
1842 if (split.rightClipName.has_value() && clip->GetPlayStartSample() == s)
1843 clip->SetName(*split.rightClipName);
1844 else if (split.leftClipName.has_value() && clip->GetPlayEndSample() == s)
1845 clip->SetName(*split.leftClipName);
1846 }
1847 }
1848
1849 // Restore the saved cut lines, also transforming if time altered
1850 for (const auto &clip : track.mClips) {
1851 double st;
1852 double et;
1853
1854 st = clip->GetPlayStartTime();
1855 et = clip->GetPlayEndTime();
1856
1857 // Scan the cuts for any that live within this clip
1858 for (auto it = cuts.begin(); it != cuts.end();) {
1859 WaveClip *cut = it->get();
1860 //cutlines in this array were orphaned previously
1861 double cs = cut->GetSequenceStartTime();
1862
1863 // Offset the cut from the start of the clip and add it to
1864 // this clips cutlines.
1865 if (cs >= st && cs <= et) {
1866 cut->SetSequenceStartTime(warper->Warp(cs) - st);
1867 clip->GetCutLines().push_back( std::move(*it) ); // transfer ownership!
1868 it = cuts.erase(it);
1869 }
1870 else
1871 ++it;
1872 }
1873 }
1874 }
1875}
std::vector< WaveClipHolder > WaveClipHolders
Definition: WaveClip.h:46
No change to time at all.
Definition: TimeWarper.h:69
Transforms one point in time to another point. For example, a time stretching effect might use one to...
Definition: TimeWarper.h:62
virtual double Warp(double originalTime) const =0
double GetSequenceStartTime() const noexcept
Definition: WaveClip.cpp:1415
void SetSequenceStartTime(double startTime)
Definition: WaveClip.cpp:1422
void ShiftBy(double delta) noexcept
Definition: WaveClip.cpp:1441
double GetTrimRight() const noexcept
Returns the play end offset in seconds from the ending of the underlying sequence.
Definition: WaveClip.cpp:1368
double GetPlayStartTime() const noexcept override
Definition: WaveClip.cpp:1305
double GetTrimLeft() const noexcept
Returns the play start offset in seconds from the beginning of the underlying sequence.
Definition: WaveClip.cpp:1358
double GetPlayEndTime() const override
Definition: WaveClip.cpp:1315
void SetTrimRight(double trim)
Sets the play end offset in seconds from the ending of the underlying sequence.
Definition: WaveClip.cpp:1363
bool HasEqualPitchAndSpeed(const WaveClip &other) const
Definition: WaveClip.cpp:368
void SetTrimLeft(double trim)
Sets the play start offset in seconds from the beginning of the underlying sequence.
Definition: WaveClip.cpp:1353
bool Paste(double t0, const WaveClip &other)
Definition: WaveClip.cpp:702
size_t GetWidth() const override
Definition: WaveClip.cpp:165
bool AddClip(const std::shared_ptr< WaveClip > &clip)
Definition: WaveTrack.cpp:1935
WaveClipPointers SortedClipArray()
Definition: WaveTrack.cpp:4412
static void PasteOne(WaveTrack &track, double t0, const WaveTrack &other, double startTime, double insertDuration, bool merge=true)
Definition: WaveTrack.cpp:2174
bool MergeOneClipPair(int clipidx1, int clipidx2)
Definition: WaveTrack.cpp:4115
int GetClipIndex(const WaveClip *clip) const
Definition: WaveTrack.cpp:3852
double GetRate() const override
Definition: WaveTrack.cpp:1128
WaveClipHolders & GetClips()
Definition: WaveTrack.h:699
void HandleClear(double t0, double t1, bool addCutLines, bool split, bool clearByTrimming=false)
Definition: WaveTrack.cpp:1952
sampleCount TimeToLongSamples(double t0) const

References AddClip(), GetClipIndex(), GetClips(), WaveClip::GetPlayEndTime(), WaveClip::GetPlayStartTime(), GetRate(), WaveClip::GetSequenceStartTime(), WaveClip::GetTrimLeft(), WaveClip::GetTrimRight(), GetWidth(), WaveClip::GetWidth(), HandleClear(), WaveClip::HasEqualPitchAndSpeed(), mClips, MergeOneClipPair(), mpFactory, WaveClip::Paste(), PasteOne(), WaveClip::SetSequenceStartTime(), WaveClip::SetTrimLeft(), WaveClip::SetTrimRight(), WaveClip::ShiftBy(), WideSampleSequence::SnapToSample(), SortedClipArray(), WideSampleSequence::TimeToLongSamples(), and TimeWarper::Warp().

Referenced by ClearAndPasteAtSameTempo().

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

◆ Clone()

TrackListHolder WaveTrack::Clone ( bool  backup) const
overrideprivatevirtual

Subclass responsibility implements only a part of Duplicate(), copying the track data proper (not associated data such as for groups and views)

Parameters
unstretchIntervalIf set, this time interval's stretching must be applied.
Precondition
!unstretchInterval.has_value() || unstretchInterval->first < unstretchInterval->second
IsLeader()
Parameters
backupwhether the duplication is for backup purposes while opening a project, instead of other editing operations
Postcondition
result: NChannels() == result->NChannels()

Implements Track.

Definition at line 1086 of file WaveTrack.cpp.

1087{
1088 assert(IsLeader());
1089 auto result = TrackList::Temporary(nullptr);
1090 const auto cloneOne = [&](const WaveTrack *pChannel){
1091 const auto pTrack =
1092 std::make_shared<WaveTrack>(*pChannel, ProtectedCreationArg{}, backup);
1093 pTrack->Init(*pChannel);
1094 result->Add(pTrack);
1095 };
1096 if (GetOwner())
1097 for (const auto pChannel : TrackList::Channels(this))
1098 cloneOne(pChannel);
1099 else
1100 cloneOne(this);
1101 return result;
1102}
static TrackListHolder Temporary(AudacityProject *pProject, const Track::Holder &left={}, const Track::Holder &right={})
Definition: Track.cpp:1418

References TrackList::Channels(), Track::GetOwner(), IsLeader(), and TrackList::Temporary().

Here is the call graph for this function:

◆ CloseLock()

bool WaveTrack::CloseLock ( )
noexcept

Should be called upon project close. Not balanced by unlocking calls.

Precondition
IsLeader()
Exception safety guarantee:
No-fail

Definition at line 3024 of file WaveTrack.cpp.

3025{
3026 assert(IsLeader());
3027 for (const auto pChannel : TrackList::Channels(this))
3028 for (const auto &clip : pChannel->mClips)
3029 clip->CloseLock();
3030
3031 return true;
3032}

References TrackList::Channels(), and IsLeader().

Here is the call graph for this function:

◆ ConvertToSampleFormat()

void WaveTrack::ConvertToSampleFormat ( sampleFormat  format,
const std::function< void(size_t)> &  progressReport = {} 
)
Precondition
IsLeader()
Exception safety guarantee:
Weak – Might complete on only some clips

Definition at line 1269 of file WaveTrack.cpp.

1271{
1272 assert(IsLeader());
1273 for (const auto pChannel : TrackList::Channels(this)) {
1274 for (const auto& clip : pChannel->mClips)
1275 clip->ConvertToSampleFormat(format, progressReport);
1276 }
1277 WaveTrackData::Get(*this).SetSampleFormat(format);
1278}

References TrackList::Channels(), anonymous_namespace{ExportPCM.cpp}::format, BasicUI::Get(), and IsLeader().

Here is the call graph for this function:

◆ Copy()

TrackListHolder WaveTrack::Copy ( double  t0,
double  t1,
bool  forClipboard = true 
) const
overridevirtual

Create new tracks and don't modify this track.

Returns
non-NULL or else throw Note that subclasses may want to distinguish tracks stored in a clipboard from those stored in a project May assume precondition: t0 <= t1 Should invoke Track::Init
Precondition
IsLeader
Postcondition
result: result->NChannels() == NChannels()

Implements Track.

Definition at line 1408 of file WaveTrack.cpp.

1409{
1410 if (t1 < t0)
1412
1413 auto list = TrackList::Create(nullptr);
1414 for (const auto pChannel : TrackList::Channels(this))
1415 list->Add(CopyOne(*pChannel, t0, t1, forClipboard));
1416 return list;
1417}
static TrackListHolder Create(AudacityProject *pOwner)
Definition: Track.cpp:365
static Holder CopyOne(const WaveTrack &track, double t0, double t1, bool forClipboard)
Definition: WaveTrack.cpp:1419

References TrackList::Channels(), CopyOne(), TrackList::Create(), and THROW_INCONSISTENCY_EXCEPTION.

Referenced by Cut(), anonymous_namespace{LabelMenus.cpp}::OnCopyLabels(), anonymous_namespace{LabelMenus.cpp}::OnCutLabels(), anonymous_namespace{EditMenus.cpp}::OnSplitCut(), anonymous_namespace{EditMenus.cpp}::OnSplitNew(), and SplitCut().

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

◆ CopyClipEnvelopes()

void WaveTrack::CopyClipEnvelopes ( )

Definition at line 2788 of file WaveTrack.cpp.

2789{
2790 const auto channels = TrackList::Channels(this);
2791 if (channels.size() != 2)
2792 return;
2793 // Assume correspondence of clips
2794 const auto left = *channels.begin();
2795 auto it = begin(left->mClips),
2796 last = end(left->mClips);
2797 const auto right = *channels.rbegin();
2798 auto it2 = begin(right->mClips),
2799 last2 = end(right->mClips);
2800 for (; it != last; ++it, ++it2) {
2801 if (it2 == last2) {
2802 assert(false);
2803 break;
2804 }
2805 (*it2)->SetEnvelope(std::make_unique<Envelope>(*(*it)->GetEnvelope()));
2806 }
2807}
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Definition: PackedArray.h:159
auto begin(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Definition: PackedArray.h:150

References PackedArray::begin(), TrackList::Channels(), and PackedArray::end().

Here is the call graph for this function:

◆ CopyOne()

auto WaveTrack::CopyOne ( const WaveTrack track,
double  t0,
double  t1,
bool  forClipboard 
)
staticprivate

Definition at line 1419 of file WaveTrack.cpp.

1421{
1422 const auto &pFactory = track.mpFactory;
1423 auto result = track.EmptyCopy();
1424 WaveTrack *newTrack = result.get();
1425
1426 // PRL: Why shouldn't cutlines be copied and pasted too? I don't know,
1427 // but that was the old behavior. But this function is also used by the
1428 // Duplicate command and I changed its behavior in that case.
1429
1430 for (const auto &clip : track.mClips) {
1431 if(clip->IsEmpty())
1432 continue;
1433
1434 if (t0 <= clip->GetPlayStartTime() && t1 >= clip->GetPlayEndTime()) {
1435 // Whole clip is in copy region
1436 //wxPrintf("copy: clip %i is in copy region\n", (int)clip);
1437
1438 newTrack->InsertClip(
1439 std::make_shared<WaveClip>(*clip, pFactory, !forClipboard));
1440 WaveClip *const newClip = newTrack->mClips.back().get();
1441 newClip->ShiftBy(-t0);
1442 }
1443 else if (clip->CountSamples(t0, t1) >= 1) {
1444 // Clip is affected by command
1445 //wxPrintf("copy: clip %i is affected by command\n", (int)clip);
1446
1447 auto newClip = std::make_shared<WaveClip>(
1448 *clip, pFactory, !forClipboard, t0, t1);
1449 newClip->SetName(clip->GetName());
1450
1451 newClip->ShiftBy(-t0);
1452 if (newClip->GetPlayStartTime() < 0)
1453 newClip->SetPlayStartTime(0);
1454
1455 newTrack->InsertClip(std::move(newClip)); // transfer ownership
1456 }
1457 }
1458
1459 // AWD, Oct 2009: If the selection ends in whitespace, create a
1460 // placeholder clip representing that whitespace
1461 // PRL: Only if we want the track for pasting into other tracks. Not if
1462 // it goes directly into a project as in the Duplicate command.
1463 if (forClipboard &&
1464 newTrack->GetEndTime() + 1.0 / newTrack->GetRate() < t1 - t0) {
1465 // TODO wide wave tracks -- match clip width of newTrack
1466 auto placeholder = std::make_shared<WaveClip>(1, pFactory,
1467 newTrack->GetSampleFormat(),
1468 static_cast<int>(newTrack->GetRate()),
1469 0 /*colourindex*/);
1470 placeholder->SetIsPlaceholder(true);
1471 placeholder->InsertSilence(0, (t1 - t0) - newTrack->GetEndTime());
1472 placeholder->ShiftBy(newTrack->GetEndTime());
1473 newTrack->InsertClip(std::move(placeholder)); // transfer ownership
1474 }
1475 return newTrack->SharedPointer<WaveTrack>();
1476}
std::shared_ptr< Subclass > SharedPointer()
Definition: Track.h:160
void SetPlayStartTime(double time)
Definition: WaveClip.cpp:1310
void SetName(const wxString &name)
Definition: WaveClip.cpp:1265
sampleFormat GetSampleFormat() const override
Definition: WaveTrack.cpp:1263
Holder EmptyCopy(const SampleBlockFactoryPtr &pFactory={}, bool keepLink=true) const
Definition: WaveTrack.cpp:1366

References GetEndTime(), GetRate(), GetSampleFormat(), InsertClip(), mClips, Track::SharedPointer(), and WaveClip::ShiftBy().

Referenced by Copy().

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

◆ CountBlocks()

size_t WaveTrack::CountBlocks ( ) const
Returns
the total number of blocks in all underlying sequences of all clips, across all channels (including hidden audio but not counting the cutlines)
Precondition
IsLeader()

Definition at line 1252 of file WaveTrack.cpp.

1253{
1254 assert(IsLeader());
1255 size_t result{};
1256 for (const auto pChannel : TrackList::Channels(this)) {
1257 for (auto& clip : pChannel->GetClips())
1258 result += clip->GetWidth() * clip->GetSequenceBlockArray(0)->size();
1259 }
1260 return result;
1261}

References TrackList::Channels(), and IsLeader().

Here is the call graph for this function:

◆ CreateClip()

WaveClip * WaveTrack::CreateClip ( double  offset = .0,
const wxString &  name = wxEmptyString 
)

Create new clip and add it to this track.

Returns a pointer to the newly created clip. Optionally initial offset and clip name may be provided

Postcondition
result: result->GetWidth() == GetWidth()

Definition at line 3801 of file WaveTrack.cpp.

3802{
3803 // TODO wide wave tracks -- choose clip width correctly for the track
3804 auto clip = std::make_shared<WaveClip>(1,
3806 clip->SetName(name);
3807 clip->SetSequenceStartTime(offset);
3808
3809 const auto& tempo = GetProjectTempo();
3810 if (tempo.has_value())
3811 clip->OnProjectTempoChange(std::nullopt, *tempo);
3812 mClips.push_back(std::move(clip));
3813
3814 auto result = mClips.back().get();
3815 // TODO wide wave tracks -- for now assertion is correct because widths are
3816 // always 1
3817 assert(result->GetWidth() == GetWidth());
3818 return result;
3819}
const TranslatableString name
Definition: Distortion.cpp:76
int GetWaveColorIndex() const
Definition: WaveTrack.cpp:1214

References Track::GetProjectTempo(), GetRate(), GetSampleFormat(), GetWaveColorIndex(), GetWidth(), mClips, mpFactory, and name.

Referenced by AUPImportFileHandle::HandleWaveClip(), JoinOne(), NewestOrNewClip(), and RightmostOrNewClip().

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

◆ CreateWideClip()

void WaveTrack::CreateWideClip ( double  offset = .0,
const wxString &  name = wxEmptyString 
)
Precondition
IsLeader()

Definition at line 3794 of file WaveTrack.cpp.

3795{
3796 assert(IsLeader());
3797 for(auto channel : TrackList::Channels(this))
3798 channel->CreateClip(offset, name);
3799}

References TrackList::Channels(), IsLeader(), and name.

Here is the call graph for this function:

◆ Cut()

TrackListHolder WaveTrack::Cut ( double  t0,
double  t1 
)
overridevirtual

Create tracks and modify this track.

Returns
non-NULL or else throw May assume precondition: t0 <= t1
Precondition
IsLeader()
Postcondition
result: result->NChannels() == NChannels()

Implements Track.

Definition at line 1303 of file WaveTrack.cpp.

1304{
1305 assert(IsLeader());
1306 if (t1 < t0)
1308
1309 auto result = Copy(t0, t1);
1310 Clear(t0, t1);
1311 return result;
1312}
void Clear(double t0, double t1) override
Definition: WaveTrack.cpp:1479
TrackListHolder Copy(double t0, double t1, bool forClipboard=true) const override
Create new tracks and don't modify this track.
Definition: WaveTrack.cpp:1408

References Clear(), Copy(), IsLeader(), and THROW_INCONSISTENCY_EXCEPTION.

Here is the call graph for this function:

◆ DiscardTrimmed()

void WaveTrack::DiscardTrimmed ( )

Remove hidden audio from all clips.

Precondition
IsLeader()

Definition at line 4432 of file WaveTrack.cpp.

4433{
4434 assert(IsLeader());
4435 for (const auto pChannel : TrackList::Channels(this)) {
4436 for (auto clip : pChannel->GetClips()) {
4437 if (clip->GetTrimLeft() != 0) {
4438 auto t0 = clip->GetPlayStartTime();
4439 clip->SetTrimLeft(0);
4440 clip->ClearLeft(t0);
4441 }
4442 if (clip->GetTrimRight() != 0) {
4443 auto t1 = clip->GetPlayEndTime();
4444 clip->SetTrimRight(0);
4445 clip->ClearRight(t1);
4446 }
4447 }
4448 }
4449}

References TrackList::Channels(), and IsLeader().

Here is the call graph for this function:

◆ Disjoin()

void WaveTrack::Disjoin ( double  t0,
double  t1 
)
Precondition
IsLeader()
Exception safety guarantee:
Weak

Definition at line 2520 of file WaveTrack.cpp.

2521{
2522 assert(IsLeader());
2524 const size_t maxAtOnce = 1048576;
2525 std::vector<float> buffer;
2526 std::vector<samplePtr> buffers;
2527 Regions regions;
2528
2529 const size_t width = NChannels();
2530
2531 for (const auto &interval : Intervals()) {
2532 double startTime = interval->Start();
2533 double endTime = interval->End();
2534
2535 if (endTime < t0 || startTime > t1)
2536 continue;
2537
2538 // Assume all clips will have the same width
2539 if (buffer.empty()) {
2540 buffer.resize(maxAtOnce * width);
2541 buffers.resize(width);
2542 auto pBuffer = buffer.data();
2543 for (size_t ii = 0; ii < width; ++ii, pBuffer += maxAtOnce)
2544 buffers[ii] = reinterpret_cast<samplePtr>(pBuffer);
2545 }
2546
2547 const auto allZeroesAt = [&](size_t i) {
2548 auto pData = buffer.data() + i;
2549 for (size_t ii = 0; ii < width; ++ii, pData += maxAtOnce) {
2550 if (*pData != 0.0)
2551 return false;
2552 }
2553 return true;
2554 };
2555
2556 // simply look for a sequence of zeroes (across all channels) and if the
2557 // sequence is longer than the minimum number, split-delete the region
2558
2559 sampleCount seqStart = -1;
2560 auto start = interval->TimeToSamples(std::max(.0, t0 - startTime));
2561 auto end = interval->TimeToSamples(std::min(endTime, t1) - startTime);
2562
2563 auto len = (end - start);
2564 for (decltype(len) done = 0; done < len; done += maxAtOnce) {
2565 auto numSamples = limitSampleBufferSize(maxAtOnce, len - done);
2566
2567 auto bufferIt = buffers.begin();
2568
2569 for (auto channel : interval->Channels())
2570 channel->GetSamples(
2571 *bufferIt++, floatSample, start + done, numSamples);
2572
2573 for (decltype(numSamples) i = 0; i < numSamples; ++i) {
2574 auto curSamplePos = start + done + i;
2575
2576 //start a NEW sequence
2577 if (seqStart == -1 && allZeroesAt(i))
2578 seqStart = curSamplePos;
2579 else if (curSamplePos == end - 1 || !allZeroesAt(i)) {
2580 if (seqStart != -1) {
2581 decltype(end) seqEnd;
2582
2583 //consider the end case, where selection ends in zeroes
2584 if (curSamplePos == end - 1 && allZeroesAt(i))
2585 seqEnd = end;
2586 else
2587 seqEnd = curSamplePos;
2588 if (seqEnd - seqStart + 1 > minSamples) {
2589 regions.push_back(
2590 Region(
2591 startTime + interval->SamplesToTime(seqStart),
2592 startTime + interval->SamplesToTime(seqEnd)
2593 )
2594 );
2595 }
2596 seqStart = -1;
2597 }
2598 }
2599 } // samples
2600 } // blocks
2601 } // finding regions
2602
2603 for (const auto &region : regions)
2604 SplitDelete(region.start, region.end);
2605}
WaveTrack::Regions Regions
Definition: LabelMenus.cpp:26
size_t limitSampleBufferSize(size_t bufferSize, sampleCount limit)
Definition: SampleCount.cpp:22
char * samplePtr
Definition: SampleFormat.h:57
WaveTrack::Region Region
#define WAVETRACK_MERGE_POINT_TOLERANCE
Definition: WaveTrack.h:61
void SplitDelete(double t0, double t1)
Definition: WaveTrack.cpp:1878
auto Intervals()
Definition: WaveTrack.h:1041
Positions or offsets within audio files need a wide type.
Definition: SampleCount.h:19

References PackedArray::end(), floatSample, Intervals(), IsLeader(), limitSampleBufferSize(), min(), NChannels(), SplitDelete(), WideSampleSequence::TimeToLongSamples(), and WAVETRACK_MERGE_POINT_TOLERANCE.

Referenced by anonymous_namespace{LabelMenus.cpp}::OnDisjoinLabels().

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

◆ DoGet()

bool WaveTrack::DoGet ( size_t  iChannel,
size_t  nBuffers,
const samplePtr  buffers[],
sampleFormat  format,
sampleCount  start,
size_t  len,
bool  backwards,
fillFormat  fill = FillFormat::fillZero,
bool  mayThrow = true,
sampleCount pNumWithinClips = nullptr 
) const
overridevirtual

This fails if any clip overlapping the range has non-unit stretch ratio!

MM: Now that each wave track can contain multiple clips, we don't have a continuous space of samples anymore, but we simulate it, because there are a lot of places (e.g. effects) using this interface. This interface makes much sense for modifying samples, but note that it is not time-accurate, because the "offset" is a double value and therefore can lie inbetween samples. But as long as you use the same value for "start" in both calls to "Set" and "Get" it is guaranteed that the same samples are affected.

an un-owned track should have reported one channel only

Implements WideSampleSequence.

Definition at line 3176 of file WaveTrack.cpp.

3180{
3181 const auto nChannels = NChannels();
3182 assert(iChannel + nBuffers <= nChannels); // precondition
3183 const auto pOwner = GetOwner();
3184 if (!pOwner) {
3186 assert(nChannels == 1);
3187 nBuffers = std::min<size_t>(nBuffers, 1);
3188 }
3189 std::optional<TrackIter<const WaveTrack>> iter;
3190 auto pTrack = this;
3191 if (pOwner) {
3192 const auto ppLeader = TrackList::Channels(this).first;
3193 iter.emplace(ppLeader.advance(IsLeader() ? iChannel : 1));
3194 pTrack = **iter;
3195 }
3196 return std::all_of(buffers, buffers + nBuffers, [&](samplePtr buffer) {
3197 const auto result = pTrack->GetOne(
3198 buffer, format, start, len, backwards, fill, mayThrow,
3199 pNumWithinClips);
3200 if (iter)
3201 pTrack = *(++ *iter);
3202 return result;
3203 });
3204}

References TrackList::Channels(), anonymous_namespace{ExportPCM.cpp}::format, Track::GetOwner(), anonymous_namespace{StretchingSequenceIntegrationTest.cpp}::iChannel, IsLeader(), and NChannels().

Here is the call graph for this function:

◆ DoGetChannel()

std::shared_ptr<::Channel > WaveTrack::DoGetChannel ( size_t  iChannel)
overrideprivatevirtual

Retrieve a channel.

Postcondition
result: !(iChannel < NChannels()) || result

Implements ChannelGroup.

Definition at line 1057 of file WaveTrack.cpp.

1058{
1059 auto nChannels = NChannels();
1060 if (iChannel >= nChannels)
1061 return {};
1062 auto pTrack = (iChannel == 0)
1063 ? this
1064 // TODO: more-than-two-channels
1065 : *TrackList::Channels(this).rbegin();
1066 // Use aliasing constructor of std::shared_ptr
1067 ::Channel *alias = pTrack;
1068 return { pTrack->shared_from_this(), alias };
1069}

References TrackList::Channels(), anonymous_namespace{StretchingSequenceIntegrationTest.cpp}::iChannel, and NChannels().

Here is the call graph for this function:

◆ DoGetChannelGroup()

ChannelGroup & WaveTrack::DoGetChannelGroup ( ) const
overrideprivatevirtual

Subclass must override.

Postcondition
result: for some ii less than result.NChannels(), this == result.GetChannel(ii).get()

Implements Channel.

Definition at line 1071 of file WaveTrack.cpp.

1072{
1073 const ChannelGroup &group = *this;
1074 return const_cast<ChannelGroup&>(group);
1075}

◆ DoGetInterval()

std::shared_ptr< WideChannelGroupInterval > WaveTrack::DoGetInterval ( size_t  iInterval)
overrideprivatevirtual

Retrieve an interval.

Postcondition
result: !(iInterval < NIntervals()) || result

Implements ChannelGroup.

Definition at line 1031 of file WaveTrack.cpp.

1032{
1033 if (iInterval < NIntervals()) {
1034 WaveClipHolder pClip = mClips[iInterval],
1035 pClip1;
1036 // TODO wide wave tracks
1037 // This assumed correspondence of clips may be wrong if they misalign
1038 if (auto right = ChannelGroup::GetChannel<WaveTrack>(1)
1039 ; right && iInterval < right->mClips.size()
1040 )
1041 pClip1 = right->mClips[iInterval];
1042 return std::make_shared<Interval>(*this, pClip, pClip1);
1043 }
1044 return {};
1045}
std::shared_ptr< WaveClip > WaveClipHolder
Definition: WaveClip.h:45
size_t NIntervals() const override
used only during deserialization
Definition: WaveTrack.cpp:1025

References mClips, and NIntervals().

Here is the call graph for this function:

◆ DoOnProjectTempoChange()

void WaveTrack::DoOnProjectTempoChange ( const std::optional< double > &  oldTempo,
double  newTempo 
)
overrideprivatevirtual
Precondition
IsLeader()

Implements Track.

Definition at line 893 of file WaveTrack.cpp.

895{
896 assert(IsLeader());
897 for (const auto pChannel : TrackList::Channels(this))
898 for (const auto& clip : pChannel->mClips)
899 clip->OnProjectTempoChange(oldTempo, newTempo);
900}

References TrackList::Channels(), and IsLeader().

Here is the call graph for this function:

◆ DoSetGain()

void WaveTrack::DoSetGain ( float  value)
private

Definition at line 1160 of file WaveTrack.cpp.

1161{
1162 WaveTrackData::Get(*this).SetGain(value);
1163}

References BasicUI::Get().

Referenced by HandleXMLTag(), and SetGain().

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

◆ DoSetPan()

void WaveTrack::DoSetPan ( float  value)
private

Definition at line 1178 of file WaveTrack.cpp.

1179{
1180 WaveTrackData::Get(*this).SetPan(value);
1181}

References BasicUI::Get().

Referenced by HandleXMLTag(), and SetPan().

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

◆ DoSetRate()

void WaveTrack::DoSetRate ( double  newRate)
private

Definition at line 1143 of file WaveTrack.cpp.

1144{
1145 auto &data = WaveTrackData::Get(*this);
1146 data.SetRate(static_cast<int>(newRate));
1147}

References BasicUI::Get().

Referenced by Resample(), SetRate(), and WaveTrack().

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

◆ DuplicateWithOtherTempo()

TrackListHolder WaveTrack::DuplicateWithOtherTempo ( double  newTempo,
WaveTrack *&  leader 
) const
private
Precondition
IsLeader()
Parameters
[out]leader

pre IsLeader()

Definition at line 903 of file WaveTrack.cpp.

904{
905 const auto srcCopyList = Duplicate();
906 leader = *srcCopyList->Any<WaveTrack>().begin();
907 leader->OnProjectTempoChange(newTempo);
908 return srcCopyList;
909}
virtual TrackListHolder Duplicate(DuplicateOptions={}) const
public nonvirtual duplication function that invokes Clone()
Definition: Track.cpp:86
void OnProjectTempoChange(double newTempo)
method to set project tempo on track
Definition: Track.cpp:1361
bool Any() const
Definition: Track.cpp:285

References Track::Any(), PackedArray::begin(), Track::Duplicate(), and Track::OnProjectTempoChange().

Referenced by ClearAndPaste(), and PasteWaveTrack().

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

◆ EmptyCopy()

WaveTrack::Holder WaveTrack::EmptyCopy ( const SampleBlockFactoryPtr pFactory = {},
bool  keepLink = true 
) const

Make another track copying format, rate, color, etc. but containing no clips; and always with a unique channel

It is important to pass the correct factory (that for the project which will own the copy) in the unusual case that a track is copied from another project or the clipboard. For copies within one project, the default will do.

Parameters
keepLinkif false, make the new track mono. But always preserve any other track group data.

Definition at line 1366 of file WaveTrack.cpp.

1368{
1369 const auto rate = GetRate();
1370 auto result = std::make_shared<WaveTrack>(pFactory, GetSampleFormat(), rate);
1371 result->Init(*this);
1372 // The previous line might have destroyed the rate information stored in
1373 // channel group data. The copy is not yet in a TrackList. Reassign rate
1374 // in case the track needs to make WaveClips before it is properly joined
1375 // with the opposite channel in a TrackList.
1376 // TODO wide wave tracks -- all of the comment above will be irrelevant!
1377 result->DoSetRate(rate);
1378 result->mpFactory = pFactory ? pFactory : mpFactory;
1379 if (!keepLink)
1380 result->SetLinkType(LinkType::None);
1381 WaveTrackData::Get(*result).SetOrigin(0);
1382 return result;
1383}

References BasicUI::Get(), GetRate(), GetSampleFormat(), mpFactory, and ChannelGroup::None.

Referenced by WaveTrackFactory::Create(), PasteInto(), EffectNoiseRemoval::ProcessOne(), and EffectStereoToMono::ProcessOne().

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

◆ ExpandCutLine()

void WaveTrack::ExpandCutLine ( double  cutLinePosition,
double *  cutlineStart = nullptr,
double *  cutlineEnd = nullptr 
)

Expand cut line (that is, re-insert audio, then delete audio saved in cut line)

Definition at line 4025 of file WaveTrack.cpp.

4027{
4028 assert(IsLeader());
4029 for (const auto pChannel : TrackList::Channels(this)) {
4030 pChannel->ExpandOneCutLine(cutLinePosition, cutlineStart, cutlineEnd);
4031 // Assign the out parameters at most once
4032 cutlineStart = cutlineEnd = nullptr;
4033 }
4034}

References TrackList::Channels(), and IsLeader().

Here is the call graph for this function:

◆ ExpandOneCutLine()

void WaveTrack::ExpandOneCutLine ( double  cutLinePosition,
double *  cutlineStart,
double *  cutlineEnd 
)
private
Exception safety guarantee:
Strong

Definition at line 4037 of file WaveTrack.cpp.

4039{
4040 bool editClipCanMove = GetEditClipsCanMove();
4041
4042 // Find clip which contains this cut line
4043 double start = 0, end = 0;
4044 auto pEnd = mClips.end();
4045 auto pClip = std::find_if( mClips.begin(), pEnd,
4046 [&](const WaveClipHolder &clip) {
4047 return clip->FindCutLine(cutLinePosition, &start, &end); } );
4048 if (pClip != pEnd)
4049 {
4050 auto &clip = *pClip;
4051 if (!editClipCanMove)
4052 {
4053 // We are not allowed to move the other clips, so see if there
4054 // is enough room to expand the cut line
4055 for (const auto &clip2: mClips)
4056 {
4057 if (clip2->GetPlayStartTime() > clip->GetPlayStartTime() &&
4058 clip->GetPlayEndTime() + end - start > clip2->GetPlayStartTime())
4059 // Strong-guarantee in case of this path
4062 XO("There is not enough room available to expand the cut line"),
4063 XO("Warning"),
4064 "Error:_Insufficient_space_in_track"
4065 };
4066 }
4067 }
4068
4069 clip->ExpandCutLine(cutLinePosition);
4070
4071 // Strong-guarantee provided that the following gives No-fail-guarantee
4072
4073 if (cutlineStart)
4074 *cutlineStart = start;
4075 if (cutlineEnd)
4076 *cutlineEnd = end;
4077
4078 // Move clips which are to the right of the cut line
4079 if (editClipCanMove)
4080 {
4081 for (const auto &clip2 : mClips)
4082 {
4083 if (clip2->GetPlayStartTime() > clip->GetPlayStartTime())
4084 clip2->ShiftBy(end - start);
4085 }
4086 }
4087 }
4088}
@ BadUserAction
Indicates that the user performed an action that is not allowed.
XO("Cut/Copy/Paste")
bool GetEditClipsCanMove()
Definition: WaveTrack.cpp:4578
A MessageBoxException that shows a given, unvarying string.

References BadUserAction, PackedArray::end(), GetEditClipsCanMove(), mClips, and XO().

Here is the call graph for this function:

◆ FindChannelGroup()

const ChannelGroup * WaveTrack::FindChannelGroup ( ) const
overridevirtual

Find associated ChannelGroup if any.

Implements PlayableSequence.

Definition at line 2825 of file WaveTrack.cpp.

2826{
2827 return this;
2828}

◆ FindClipByName()

const WaveClip * WaveTrack::FindClipByName ( const wxString &  name) const

Returns nullptr if clip with such name was not found.

Definition at line 1047 of file WaveTrack.cpp.

1048{
1049 for (const auto& clip : mClips)
1050 {
1051 if (clip->GetName() == name)
1052 return clip.get();
1053 }
1054 return nullptr;
1055}

References mClips, and name.

Referenced by MakeClipCopyName(), and MakeNewClipName().

Here is the caller graph for this function:

◆ Flush()

void WaveTrack::Flush ( )
overridevirtual
Exception safety guarantee:
Mixed
Exception safety guarantee:
No-fail – The rightmost clip will be in a flushed state.
Exception safety guarantee:
Partial – Some initial portion (maybe none) of the append buffer of the rightmost clip gets appended; no previously saved contents are lost.

Implements RecordableSequence.

Definition at line 2776 of file WaveTrack.cpp.

2777{
2778 assert(IsLeader());
2779 for (const auto pChannel : TrackList::Channels(this))
2780 pChannel->FlushOne();
2781}

References TrackList::Channels(), and IsLeader().

Referenced by WaveTrackSink::Flush(), TrackSpectrumTransformer::PostProcess(), and EffectSBSMS::Process().

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

◆ FlushOne()

void WaveTrack::FlushOne ( )
private
Exception safety guarantee:
Mixed
Exception safety guarantee:
No-fail – The rightmost clip will be in a flushed state.
Exception safety guarantee:
Partial – Some initial portion (maybe none) of the append buffer of the rightmost clip gets appended; no previously saved contents are lost.

Definition at line 2814 of file WaveTrack.cpp.

2815{
2816 // After appending, presumably. Do this to the clip that gets appended.
2818}
void Flush()
Flush must be called after last Append.
Definition: WaveClip.cpp:539
WaveClip * RightmostOrNewClip()
Get access to the last (rightmost) clip, or create a clip, if there is not already one.
Definition: WaveTrack.cpp:3831

References WaveClip::Flush(), and RightmostOrNewClip().

Here is the call graph for this function:

◆ FormatConsistencyCheck()

bool WaveTrack::FormatConsistencyCheck ( ) const
private

Whether all tracks in group and all clips have a common sample format.

Precondition
IsLeader()

Definition at line 2370 of file WaveTrack.cpp.

2371{
2372 assert(IsLeader());
2373
2374 const auto channels = TrackList::Channels(this);
2375 return std::all_of(channels.begin(), channels.end(),
2376 [&](const WaveTrack *pTrack){
2377 return pTrack && pTrack->mLegacyFormat == mLegacyFormat;
2378 });
2379}

References TrackList::Channels(), and IsLeader().

Referenced by LinkConsistencyFix().

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

◆ GetAdjacentClip() [1/2]

WaveClip * WaveTrack::GetAdjacentClip ( const WaveClip clip,
PlaybackDirection  searchDirection 
)

Similar to GetNextClip, but returns nullptr if the neighbour clip is not adjacent.

Definition at line 3716 of file WaveTrack.cpp.

3717{
3718 return const_cast<WaveClip*>(
3719 std::as_const(*this).GetAdjacentClip(clip, direction));
3720}

◆ GetAdjacentClip() [2/2]

const WaveClip * WaveTrack::GetAdjacentClip ( const WaveClip clip,
PlaybackDirection  searchDirection 
) const

Similar to GetNextClip, but returns nullptr if the neighbour clip is not adjacent.

Definition at line 3697 of file WaveTrack.cpp.

3699{
3700 const auto neighbour = GetNextClip(clip, direction);
3701 if (!neighbour)
3702 return nullptr;
3703 else if (direction == PlaybackDirection::forward)
3704 return std::abs(clip.GetPlayEndTime() - neighbour->GetPlayStartTime()) <
3705 1e-9 ?
3706 neighbour :
3707 nullptr;
3708 else
3709 return std::abs(clip.GetPlayStartTime() - neighbour->GetPlayEndTime()) <
3710 1e-9 ?
3711 neighbour :
3712 nullptr;
3713}
const WaveClip * GetNextClip(const WaveClip &clip, PlaybackDirection searchDirection) const
Returns clips next to clip in the given direction, or nullptr if there is none.
Definition: WaveTrack.cpp:3729

References forward, GetNextClip(), WaveClip::GetPlayEndTime(), and WaveClip::GetPlayStartTime().

Referenced by GetFloatsFromTime(), and SetFloatsFromTime().

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

◆ GetAllClips() [1/2]

IteratorRange< AllClipsIterator > WaveTrack::GetAllClips ( )
inline

Definition at line 794 of file WaveTrack.h.

795 {
796 return { AllClipsIterator{ *this }, AllClipsIterator{ } };
797 }

◆ GetAllClips() [2/2]

IteratorRange< AllClipsConstIterator > WaveTrack::GetAllClips ( ) const
inline

Definition at line 799 of file WaveTrack.h.

800 {
801 return { AllClipsConstIterator{ *this }, AllClipsConstIterator{ } };
802 }

◆ GetBestBlockSize()

size_t WaveTrack::GetBestBlockSize ( sampleCount  t) const

Definition at line 2721 of file WaveTrack.cpp.

2722{
2723 auto bestBlockSize = GetMaxBlockSize();
2724
2725 for (const auto &clip : mClips)
2726 {
2727 auto startSample = clip->GetPlayStartSample();
2728 auto endSample = clip->GetPlayEndSample();
2729 if (s >= startSample && s < endSample)
2730 {
2731 // ignore extra channels (this function will soon be removed)
2732 bestBlockSize = clip->GetSequence(0)
2733 ->GetBestBlockSize(s - clip->GetSequenceStartSample());
2734 break;
2735 }
2736 }
2737
2738 return bestBlockSize;
2739}
size_t GetMaxBlockSize() const
Definition: WaveTrack.cpp:2741

References GetMaxBlockSize(), and mClips.

Referenced by WaveChannel::GetBestBlockSize(), EffectNoiseRemoval::ProcessOne(), ReverseOneClip(), VoiceKey::TestDirectionChanges(), VoiceKey::TestEnergy(), and VoiceKey::TestSignChanges().

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

◆ GetChannel() [1/2]

auto WaveTrack::GetChannel ( size_t  iChannel)
inline

Definition at line 272 of file WaveTrack.h.

272 {
273 return this->ChannelGroup::GetChannel<WaveChannel>(iChannel); }

References anonymous_namespace{StretchingSequenceIntegrationTest.cpp}::iChannel.

Referenced by WaveTrackMenuTable::OnMergeStereo(), and WaveTrackMenuTable::SplitStereo().

Here is the caller graph for this function:

◆ GetChannel() [2/2]

auto WaveTrack::GetChannel ( size_t  iChannel) const
inline

Definition at line 274 of file WaveTrack.h.

274 {
275 return this->ChannelGroup::GetChannel<const WaveChannel>(iChannel); }

References anonymous_namespace{StretchingSequenceIntegrationTest.cpp}::iChannel.

◆ GetChannelGain()

float WaveTrack::GetChannelGain ( int  channel) const
overridevirtual

Takes gain and pan into account.

Implements WideSampleSequence.

Definition at line 1196 of file WaveTrack.cpp.

1197{
1198 float left = 1.0;
1199 float right = 1.0;
1200
1201 const auto pan = GetPan();
1202 if (pan < 0)
1203 right = (pan + 1.0);
1204 else if (pan > 0)
1205 left = 1.0 - pan;
1206
1207 const auto gain = GetGain();
1208 if ((channel%2) == 0)
1209 return left * gain;
1210 else
1211 return right * gain;
1212}
float GetPan() const
Definition: WaveTrack.cpp:1173
float GetGain() const
Definition: WaveTrack.cpp:1155

References GetGain(), and GetPan().

Referenced by EffectStereoToMono::ProcessOne().

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

◆ GetChannelType()

AudioGraph::ChannelType WaveTrack::GetChannelType ( ) const
overridevirtual

Classify this channel.

Implements AudioGraph::Channel.

Definition at line 847 of file WaveTrack.cpp.

848{
849 if (TrackList::NChannels(*this) == 1)
851 else if (IsLeader())
853 else
854 // TODO: more-than-two-channels
856}
size_t NChannels() const
Definition: Track.cpp:960

References IsLeader(), AudioGraph::LeftChannel, AudioGraph::MonoChannel, TrackList::NChannels(), and AudioGraph::RightChannel.

Here is the call graph for this function:

◆ GetClipAtTime() [1/2]

WaveClip * WaveTrack::GetClipAtTime ( double  time)

Definition at line 3724 of file WaveTrack.cpp.

3725{
3726 return const_cast<WaveClip*>(std::as_const(*this).GetClipAtTime(time));
3727}

◆ GetClipAtTime() [2/2]

const WaveClip * WaveTrack::GetClipAtTime ( double  time) const

Definition at line 3759 of file WaveTrack.cpp.

3760{
3761 const auto clips = SortedClipArray();
3762 auto p = std::find_if(
3763 clips.rbegin(), clips.rend(), [&](const WaveClip* const& clip) {
3764 return clip->WithinPlayRegion(time);
3765 });
3766
3767 // When two clips are immediately next to each other, the GetPlayEndTime() of the first clip
3768 // and the GetPlayStartTime() of the second clip may not be exactly equal due to rounding errors.
3769 // If "time" is the end time of the first of two such clips, and the end time is slightly
3770 // less than the start time of the second clip, then the first rather than the
3771 // second clip is found by the above code. So correct this.
3772 if (p != clips.rend() && p != clips.rbegin() &&
3773 time == (*p)->GetPlayEndTime() &&
3774 (*p)->SharesBoundaryWithNextClip(*(p-1))) {
3775 p--;
3776 }
3777
3778 return p != clips.rend() ? *p : nullptr;
3779}

References SortedClipArray().

Referenced by anonymous_namespace{SampleHandle.cpp}::adjustTime(), ApplyPitchAndSpeed(), SelectHandle::Click(), GetFloatAtTime(), GetFloatsFromTime(), PasteOne(), anonymous_namespace{WaveTrack.cpp}::RoundToNearestClipSample(), SetFloatsFromTime(), and SetFloatsWithinTimeRange().

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

◆ GetClipByIndex() [1/2]

WaveClip * WaveTrack::GetClipByIndex ( int  index)

Get the nth clip in this WaveTrack (will return nullptr if not found).

Use this only in special cases (like getting the linked clip), because it is much slower than GetClipIterator().

Definition at line 3859 of file WaveTrack.cpp.

3860{
3861 if(index < (int)mClips.size())
3862 return mClips[index].get();
3863 else
3864 return nullptr;
3865}

References mClips.

Referenced by GetClipByIndex(), MergeOneClipPair(), and PasteOne().

Here is the caller graph for this function:

◆ GetClipByIndex() [2/2]

const WaveClip * WaveTrack::GetClipByIndex ( int  index) const

Get the nth clip in this WaveTrack (will return nullptr if not found).

Use this only in special cases (like getting the linked clip), because it is much slower than GetClipIterator().

Definition at line 3867 of file WaveTrack.cpp.

3868{
3869 return const_cast<WaveTrack&>(*this).GetClipByIndex(index);
3870}
WaveClip * GetClipByIndex(int index)
Get the nth clip in this WaveTrack (will return nullptr if not found).
Definition: WaveTrack.cpp:3859

References GetClipByIndex().

Here is the call graph for this function:

◆ GetClipIndex()

int WaveTrack::GetClipIndex ( const WaveClip clip) const

Definition at line 3852 of file WaveTrack.cpp.

3853{
3854 int result;
3855 FindClip(mClips, clip, &result);
3856 return result;
3857}
WaveClipHolders::iterator FindClip(WaveClipHolders &list, const WaveClip *clip, int *distance=nullptr)
Definition: WaveTrack.cpp:1906

References anonymous_namespace{WaveTrack.cpp}::FindClip(), and mClips.

Referenced by ClearAndPasteOne().

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

◆ GetClipInterfaces()

ClipHolders WaveTrack::GetClipInterfaces ( ) const

Get access to the (visible) clips in the tracks, in unspecified order.

Precondition
IsLeader()

Definition at line 3056 of file WaveTrack.cpp.

3057{
3058 // We're constructing possibly wide clips here, and for this we need to have
3059 // access to the other channel-tracks.
3060 assert(IsLeader());
3061 const auto pOwner = GetOwner();
3062 ClipHolders wideClips;
3063 wideClips.reserve(mClips.size());
3064 for (auto clipIndex = 0u; clipIndex < mClips.size(); ++clipIndex)
3065 {
3066 const auto leftClip = mClips[clipIndex];
3067 WaveClipHolder rightClip;
3068 if (NChannels() == 2u && pOwner)
3069 {
3070 const auto& rightClips =
3071 (*TrackList::Channels(this).rbegin())->mClips;
3072 // This is known to have potential for failure for stereo tracks with
3073 // misaligned left/right clips - see
3074 // https://github.com/audacity/audacity/issues/4791.
3075 // If what you are trying to do is something else and this fails,
3076 // please report.
3077 assert(clipIndex < rightClips.size());
3078 if (clipIndex < rightClips.size())
3079 rightClip = rightClips[clipIndex];
3080 }
3081 wideClips.emplace_back(
3082 std::make_shared<WideClip>(leftClip, std::move(rightClip)));
3083 }
3084 return wideClips;
3085}
std::vector< std::shared_ptr< ClipInterface > > ClipHolders

References TrackList::Channels(), Track::GetOwner(), IsLeader(), mClips, and NChannels().

Here is the call graph for this function:

◆ GetClips() [1/2]

WaveClipHolders & WaveTrack::GetClips ( )
inline

Get access to the (visible) clips in the tracks, in unspecified order (not necessarily sequenced in time).

Postcondition
all pointers are non-null

Definition at line 699 of file WaveTrack.h.

699{ return mClips; }

Referenced by ClearAndPasteOne(), WaveTrackUtilities::HasPitchOrSpeed(), EffectAutoDuck::Process(), and ReverseOne().

Here is the caller graph for this function:

◆ GetClips() [2/2]

const WaveClipConstHolders & WaveTrack::GetClips ( ) const
inline

Get access to the (visible) clips in the tracks, in unspecified order (not necessarily sequenced in time).

Postcondition
all pointers are non-null

Definition at line 703 of file WaveTrack.h.

704 { return reinterpret_cast< const WaveClipConstHolders& >( mClips ); }
std::vector< std::shared_ptr< const WaveClip > > WaveClipConstHolders
Definition: WaveClip.h:47

◆ GetClipsIntersecting()

WaveClipConstHolders WaveTrack::GetClipsIntersecting ( double  t0,
double  t1 
) const

Definition at line 3742 of file WaveTrack.cpp.

3743{
3744 assert(t0 <= t1);
3745 WaveClipConstHolders intersectingClips;
3746 for (const auto& clip : mClips)
3747 if (clip->IntersectsPlayRegion(t0, t1))
3748 intersectingClips.push_back(clip);
3749 return intersectingClips;
3750}

References mClips.

Referenced by anonymous_namespace{EditMenus.cpp}::JoinClipsAvailableFlag(), and SelectActions::Handler::OnZeroCrossing().

Here is the caller graph for this function:

◆ GetDefaultAudioTrackNamePreference()

wxString WaveTrack::GetDefaultAudioTrackNamePreference ( )
static

Definition at line 743 of file WaveTrack.cpp.

744{
746
747 if (name.empty() || ( name == DefaultName.MSGID() ))
748 // When nothing was specified,
749 // the default-default is whatever translation of...
750 /* i18n-hint: The default name for an audio track. */
751 return DefaultName.Translation();
752 else
753 return name;
754}
static auto DefaultName
Definition: WaveTrack.cpp:739
StringSetting AudioTrackNameSetting
Definition: WaveTrack.cpp:4568
bool ReadWithDefault(T *pVar, const T &defaultValue) const
overload of ReadWithDefault returning a boolean that is true if the value was previously defined *‍/
Definition: Prefs.h:213

References AudioTrackNameSetting, DefaultName, TranslatableString::empty(), name, and Setting< T >::ReadWithDefault().

Referenced by TracksPrefs::Commit(), EffectBase::DoEffect(), ProjectAudioManager::DoRecord(), anonymous_namespace{WaveTrackMenuItems.cpp}::OnNewStereoTrack(), and anonymous_namespace{WaveTrackMenuItems.cpp}::OnNewWaveTrack().

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

◆ GetEndTime()

double WaveTrack::GetEndTime ( ) const
overridevirtual

Implement WideSampleSequence.

Implements WideSampleSequence.

Definition at line 3092 of file WaveTrack.cpp.

3093{
3094 return ChannelGroup::GetEndTime();
3095}
double GetEndTime() const
Get the maximum of End() values of intervals, or 0 when none.
Definition: Channel.cpp:135

References ChannelGroup::GetEndTime().

Referenced by AUPImportFileHandle::AddSilence(), EffectTruncSilence::Analyze(), ApplyPitchAndSpeed(), ClearAndPasteAtSameTempo(), CopyOne(), Effect::GetBounds(), PasteWaveTrackAtSameTempo(), TrackSpectrumTransformer::PostProcess(), EffectStereoToMono::ProcessOne(), GetInfoCommand::SendTracks(), RateMenuTable::SetRate(), SyncLockAdjust(), and Trim().

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

◆ GetEnvelopeAtTime()

Envelope * WaveTrack::GetEnvelopeAtTime ( double  time)

Definition at line 3781 of file WaveTrack.cpp.

3782{
3783 auto pTrack = this;
3784 if (GetOwner())
3785 // Substitute the leader track
3786 pTrack = *TrackList::Channels(this).begin();
3787 WaveClip* clip = pTrack->GetClipAtTime(time);
3788 if (clip)
3789 return clip->GetEnvelope();
3790 else
3791 return NULL;
3792}
Envelope * GetEnvelope()
Definition: WaveClip.h:411

References TrackList::Channels(), WaveClip::GetEnvelope(), and Track::GetOwner().

Here is the call graph for this function:

◆ GetEnvelopeValues()

void WaveTrack::GetEnvelopeValues ( double *  buffer,
size_t  bufferLen,
double  t0,
bool  backwards 
) const
overridevirtual

Fetch envelope values corresponding to uniformly separated sample times starting at the given time

Parameters
backwardsif true, fetch values in reverse order, from t0 to t0 - bufferLen / rate

Implements WideSampleSequence.

Definition at line 3621 of file WaveTrack.cpp.

3623{
3624 auto pTrack = this;
3625 if (GetOwner())
3626 // Substitute the leader track
3627 pTrack = *TrackList::Channels(this).begin();
3628
3629 if (backwards)
3630 t0 -= bufferLen / GetRate();
3631 // The output buffer corresponds to an unbroken span of time which the callers expect
3632 // to be fully valid. As clips are processed below, the output buffer is updated with
3633 // envelope values from any portion of a clip, start, end, middle, or none at all.
3634 // Since this does not guarantee that the entire buffer is filled with values we need
3635 // to initialize the entire buffer to a default value.
3636 //
3637 // This does mean that, in the cases where a usable clip is located, the buffer value will
3638 // be set twice. Unfortunately, there is no easy way around this since the clips are not
3639 // stored in increasing time order. If they were, we could just track the time as the
3640 // buffer is filled.
3641 for (decltype(bufferLen) i = 0; i < bufferLen; i++)
3642 {
3643 buffer[i] = 1.0;
3644 }
3645
3646 double startTime = t0;
3647 const auto rate = GetRate();
3648 auto tstep = 1.0 / rate;
3649 double endTime = t0 + tstep * bufferLen;
3650 for (const auto &clip: pTrack->mClips)
3651 {
3652 // IF clip intersects startTime..endTime THEN...
3653 auto dClipStartTime = clip->GetPlayStartTime();
3654 auto dClipEndTime = clip->GetPlayEndTime();
3655 if ((dClipStartTime < endTime) && (dClipEndTime > startTime))
3656 {
3657 auto rbuf = buffer;
3658 auto rlen = bufferLen;
3659 auto rt0 = t0;
3660
3661 if (rt0 < dClipStartTime)
3662 {
3663 // This is not more than the number of samples in
3664 // (endTime - startTime) which is bufferLen:
3665 auto nDiff = (sampleCount)floor((dClipStartTime - rt0) * rate + 0.5);
3666 auto snDiff = nDiff.as_size_t();
3667 rbuf += snDiff;
3668 wxASSERT(snDiff <= rlen);
3669 rlen -= snDiff;
3670 rt0 = dClipStartTime;
3671 }
3672
3673 if (rt0 + rlen*tstep > dClipEndTime)
3674 {
3675 auto nClipLen = clip->GetPlayEndSample() - clip->GetPlayStartSample();
3676
3677 if (nClipLen <= 0) // Testing for bug 641, this problem is consistently '== 0', but doesn't hurt to check <.
3678 return;
3679
3680 // This check prevents problem cited in http://bugzilla.audacityteam.org/show_bug.cgi?id=528#c11,
3681 // Gale's cross_fade_out project, which was already corrupted by bug 528.
3682 // This conditional prevents the previous write past the buffer end, in clip->GetEnvelope() call.
3683 // Never increase rlen here.
3684 // PRL bug 827: rewrote it again
3685 rlen = limitSampleBufferSize( rlen, nClipLen );
3686 rlen = std::min(rlen, size_t(floor(0.5 + (dClipEndTime - rt0) / tstep)));
3687 }
3688 // Samples are obtained for the purpose of rendering a wave track,
3689 // so quantize time
3690 clip->GetEnvelope()->GetValues(rbuf, rlen, rt0, tstep);
3691 }
3692 }
3693 if (backwards)
3694 std::reverse(buffer, buffer + bufferLen);
3695}

References TrackList::Channels(), Track::GetOwner(), GetRate(), limitSampleBufferSize(), and min().

Here is the call graph for this function:

◆ GetErrorOpening()

std::optional< TranslatableString > WaveTrack::GetErrorOpening ( ) const
overridevirtual

Returns nonempty if an error was encountered while trying to open the track from XML

May assume consistency of stereo channel grouping and examine other channels

Precondition
IsLeader()

Reimplemented from Track.

Definition at line 3012 of file WaveTrack.cpp.

3013{
3014 assert(IsLeader());
3015 for (const auto pChannel : TrackList::Channels(this))
3016 for (const auto &clip : pChannel->mClips)
3017 for (size_t ii = 0, width = clip->GetWidth(); ii < width; ++ii)
3018 if (clip->GetSequence(ii)->GetErrorOpening())
3019 return XO("A track has a corrupted sample sequence.");
3020
3021 return {};
3022}

References TrackList::Channels(), IsLeader(), and XO().

Here is the call graph for this function:

◆ GetFloatAtTime()

bool WaveTrack::GetFloatAtTime ( double  t,
size_t  iChannel,
float &  value,
bool  mayThrow 
) const
Returns
true if GetClipAtTime(t) != nullptr, false otherwise.

Definition at line 3309 of file WaveTrack.cpp.

3311{
3312 const auto clip = GetClipAtTime(t);
3313 if (!clip)
3314 return false;
3315 clip->GetFloatAtTime(
3316 t - clip->GetPlayStartTime(), iChannel, value, mayThrow);
3317 return true;
3318}

References GetClipAtTime(), and anonymous_namespace{StretchingSequenceIntegrationTest.cpp}::iChannel.

Here is the call graph for this function:

◆ GetFloats() [1/2]

bool SampleTrack::GetFloats ( float *  buffer,
sampleCount  start,
size_t  len,
fillFormat  fill = FillFormat::fillZero,
bool  mayThrow = true,
sampleCount pNumWithinClips = nullptr 
) const
inline

"narrow" overload fetches first channel only

Definition at line 46 of file SampleTrack.h.

49 {
50 constexpr auto backwards = false;
51 return GetFloats(
52 0, 1, &buffer, start, len, backwards, fill, mayThrow, pNumWithinClips);
53 }
bool GetFloats(float *buffer, sampleCount start, size_t len, fillFormat fill=FillFormat::fillZero, bool mayThrow=true, sampleCount *pNumWithinClips=nullptr) const
"narrow" overload fetches first channel only
Definition: SampleTrack.h:46

Referenced by VoiceKey::OffBackward(), VoiceKey::OffForward(), VoiceKey::OnBackward(), VoiceKey::OnForward(), ReverseOneClip(), SelectHandle::StartSnappingFreqSelection(), VoiceKey::TestDirectionChanges(), VoiceKey::TestEnergy(), and VoiceKey::TestSignChanges().

Here is the caller graph for this function:

◆ GetFloats() [2/2]

bool WideSampleSequence::GetFloats ( size_t  iChannel,
size_t  nBuffers,
float *const  buffers[],
sampleCount  start,
size_t  len,
bool  backwards = false,
fillFormat  fill = FillFormat::fillZero,
bool  mayThrow = true,
sampleCount pNumWithinClips = nullptr 
) const

Retrieve samples from a sequence in floating-point format, regardless of the storage format

Parameters
iChannelindex of first channel to fetch
nBufferscounts buffers
buffersreceive the samples
startstarting sample, relative to absolute time zero
lenhow many samples to get. buffers are assumed sufficiently large
fillhow to assign values for sample positions between clips
mayThrowif false, fill buffer with zeros when there is failure to retrieve samples; else throw
[out]pNumWithinClipsReport how many samples were copied from within clips, rather than filled according to fillFormat; but these were not necessarily one contiguous range.
Precondition
iChannel + nBuffers <= NChannels()
Returns
false when mayThrow is false and not all samples could be retrieved
Postcondition
if return value is false, buffers are zero-filled

Definition at line 43 of file WideSampleSequence.cpp.

34{
35 // Cast the pointers to pass them to DoGet() which handles multiple
36 // destination formats
37 const auto castBuffers = reinterpret_cast<const samplePtr*>(buffers);
38 const auto result = DoGet(
39 iChannel, nBuffers, castBuffers,
40 floatSample, start, len, backwards, fill, mayThrow, pNumWithinClips);
41 if (!result)
42 while (nBuffers--)
43 ClearSamples(castBuffers[nBuffers], floatSample, 0, len);
44 return result;
45}
void ClearSamples(samplePtr dst, sampleFormat format, size_t start, size_t len)
bool DoGet(size_t iChannel, size_t nBuffers, const samplePtr buffers[], sampleFormat format, sampleCount start, size_t len, bool backwards, fillFormat fill=FillFormat::fillZero, bool mayThrow=true, sampleCount *pNumWithinClips=nullptr) const override
This fails if any clip overlapping the range has non-unit stretch ratio!
Definition: WaveTrack.cpp:3176

◆ GetFloatsCenteredAroundTime()

std::pair< size_t, size_t > WaveTrack::GetFloatsCenteredAroundTime ( double  t,
size_t  iChannel,
float *  buffer,
size_t  numSideSamples,
bool  mayThrow 
) const

Gets as many samples as it can, but no more than 2 * numSideSamples + 1, centered around t. Reads nothing if GetClipAtTime(t) == nullptr. Useful to access samples across clip boundaries, as it spreads the read to adjacent clips, i.e., not separated by silence from clip at t.

Returns
The begin and end indices of the samples in the buffer where samples could actually be copied.

Definition at line 3217 of file WaveTrack.cpp.

3220{
3221 const auto numSamplesReadLeft = GetFloatsFromTime(
3222 t, iChannel, buffer, numSideSamples, mayThrow, PlaybackDirection::backward);
3223 const auto numSamplesReadRight = GetFloatsFromTime(
3224 t, iChannel, buffer + numSideSamples, numSideSamples + 1, mayThrow,
3226 return { numSideSamples - numSamplesReadLeft,
3227 numSideSamples + numSamplesReadRight };
3228}
size_t GetFloatsFromTime(double t, size_t iChannel, float *buffer, size_t numSamples, bool mayThrow, PlaybackDirection direction) const
Helper for GetFloatsCenteredAroundTime. If direction == PlaybackDirection::Backward,...
Definition: WaveTrack.cpp:3285

References backward, forward, GetFloatsFromTime(), and anonymous_namespace{StretchingSequenceIntegrationTest.cpp}::iChannel.

Here is the call graph for this function:

◆ GetFloatsFromTime()

size_t WaveTrack::GetFloatsFromTime ( double  t,
size_t  iChannel,
float *  buffer,
size_t  numSamples,
bool  mayThrow,
PlaybackDirection  direction 
) const
private

Helper for GetFloatsCenteredAroundTime. If direction == PlaybackDirection::Backward, fetches samples to the left of t, excluding t, without reversing.

See also
GetFloatsCenteredAroundTime
Returns
The number of samples actually copied.

Definition at line 3285 of file WaveTrack.cpp.

3288{
3289 RoundToNearestClipSample(*this, t);
3290 auto clip = GetClipAtTime(t);
3291 auto numSamplesRead = 0u;
3292 const auto forward = direction == PlaybackDirection::forward;
3293 while (clip)
3294 {
3295 const auto args = GetSampleAccessArgs(
3296 *clip, t, buffer, numSamples, numSamplesRead, forward);
3297 if (!clip->GetSamples(
3298 iChannel, args.offsetBuffer, floatSample, args.start, args.len,
3299 mayThrow))
3300 return 0u;
3301 numSamplesRead += args.len;
3302 if (numSamplesRead >= numSamples)
3303 break;
3304 clip = GetAdjacentClip(*clip, direction);
3305 }
3306 return numSamplesRead;
3307}
const WaveClip * GetAdjacentClip(const WaveClip &clip, PlaybackDirection searchDirection) const
Similar to GetNextClip, but returns nullptr if the neighbour clip is not adjacent.
Definition: WaveTrack.cpp:3697
void RoundToNearestClipSample(const WaveTrack &track, double &t)
Definition: WaveTrack.cpp:3207
SampleAccessArgs< BufferType > GetSampleAccessArgs(const WaveClip &clip, double startOrEndTime, BufferType buffer, size_t totalToRead, size_t alreadyRead, bool forward)
Definition: WaveTrack.cpp:3245

References floatSample, forward, GetAdjacentClip(), GetClipAtTime(), anonymous_namespace{WaveTrack.cpp}::GetSampleAccessArgs(), anonymous_namespace{StretchingSequenceIntegrationTest.cpp}::iChannel, and anonymous_namespace{WaveTrack.cpp}::RoundToNearestClipSample().

Referenced by GetFloatsCenteredAroundTime().

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

◆ GetGain()

float WaveTrack::GetGain ( ) const

Definition at line 1155 of file WaveTrack.cpp.

1156{
1157 return WaveTrackData::Get(*this).GetGain();
1158}

References BasicUI::Get().

Referenced by WaveTrackControls::GainSlider(), GetChannelGain(), GetInfoCommand::SendTracks(), SetGain(), and WriteOneXML().

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

◆ GetIdealBlockSize()

size_t WaveTrack::GetIdealBlockSize ( )

Definition at line 2763 of file WaveTrack.cpp.

2764{
2765 // ignore extra channels (this function will soon be removed)
2767}
size_t GetIdealBlockSize() const
Definition: Sequence.cpp:82
Sequence * GetSequence(size_t ii)
Definition: WaveClip.h:431
WaveClip * NewestOrNewClip()
Get access to the most recently added clip, or create a clip, if there is not already one....
Definition: WaveTrack.cpp:3821

References Sequence::GetIdealBlockSize(), WaveClip::GetSequence(), and NewestOrNewClip().

Referenced by WaveChannel::GetIdealBlockSize().

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

◆ GetIntervalAtTime()

WaveTrack::IntervalHolder WaveTrack::GetIntervalAtTime ( double  t)

Definition at line 563 of file WaveTrack.cpp.

564{
565 IntervalHolder result;
566 for (const auto& interval : Intervals())
567 if (interval->WithinPlayRegion(t))
568 return interval;
569 return nullptr;
570}

References Intervals().

Referenced by ApplyPitchAndSpeed().

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

◆ GetLeftmostClip()

const WaveClip * WaveTrack::GetLeftmostClip ( ) const

Definition at line 3034 of file WaveTrack.cpp.

3034 {
3035 if (mClips.empty())
3036 return nullptr;
3037 return std::min_element(
3038 mClips.begin(), mClips.end(),
3039 [](const auto& a, const auto b) {
3040 return a->GetPlayStartTime() < b->GetPlayStartTime();
3041 })
3042 ->get();
3043}

References mClips.

Referenced by PasteOne().

Here is the caller graph for this function:

◆ GetMaxBlockSize()

size_t WaveTrack::GetMaxBlockSize ( ) const

Definition at line 2741 of file WaveTrack.cpp.

2742{
2743 decltype(GetMaxBlockSize()) maxblocksize = 0;
2744 for (const auto &clip : mClips)
2745 for (size_t ii = 0, width = clip->GetWidth(); ii < width; ++ii)
2746 maxblocksize = std::max(maxblocksize,
2747 clip->GetSequence(ii)->GetMaxBlockSize());
2748
2749 if (maxblocksize == 0)
2750 {
2751 // We really need the maximum block size, so create a
2752 // temporary sequence to get it.
2753 maxblocksize =
2755 .GetMaxBlockSize();
2756 }
2757
2758 wxASSERT(maxblocksize > 0);
2759
2760 return maxblocksize;
2761}
Two sample formats, remembering format of original source and describing stored format.
Definition: SampleFormat.h:79
A WaveTrack contains WaveClip(s). A WaveClip contains a Sequence. A Sequence is primarily an interfac...
Definition: Sequence.h:53

References GetMaxBlockSize(), GetSampleFormat(), mClips, and mpFactory.

Referenced by EffectTruncSilence::Analyze(), CompareAudioCommand::Apply(), GetBestBlockSize(), WaveChannel::GetMaxBlockSize(), GetMaxBlockSize(), EffectCompressor::InitPass1(), EffectNoiseRemoval::ProcessOne(), EffectStereoToMono::ProcessOne(), PerTrackEffect::ProcessPass(), ReverseOneClip(), VoiceKey::TestDirectionChanges(), VoiceKey::TestEnergy(), and VoiceKey::TestSignChanges().

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

◆ GetMute()

bool WaveTrack::GetMute ( ) const
overridevirtual

May vary asynchronously.

Implements PlayableSequence.

Definition at line 2830 of file WaveTrack.cpp.

2831{
2832 return PlayableTrack::GetMute();
2833}
bool GetMute() const
Definition: PlayableTrack.h:47

References PlayableTrack::GetMute().

Referenced by ExportAudioDialog::DoExportSplitByTracks(), ExportUtils::FindExportWaveTracks(), anonymous_namespace{ExportAudioDialog.cpp}::GetNumExportChannels(), GetInfoCommand::SendTracks(), and ExportAudioDialog::UpdateTrackExportSettings().

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

◆ GetNextClip() [1/2]

WaveClip * WaveTrack::GetNextClip ( const WaveClip clip,
PlaybackDirection  searchDirection 
)

Returns clips next to clip in the given direction, or nullptr if there is none.

Definition at line 3753 of file WaveTrack.cpp.

3754{
3755 return const_cast<WaveClip*>(
3756 std::as_const(*this).GetNextClip(clip, direction));
3757}

◆ GetNextClip() [2/2]

const WaveClip * WaveTrack::GetNextClip ( const WaveClip clip,
PlaybackDirection  searchDirection 
) const

Returns clips next to clip in the given direction, or nullptr if there is none.

Definition at line 3729 of file WaveTrack.cpp.

3731{
3732 const auto clips = SortedClipArray();
3733 const auto p = std::find(clips.begin(), clips.end(), &clip);
3734 if (p == clips.end())
3735 return nullptr;
3736 else if (direction == PlaybackDirection::forward)
3737 return p == clips.end() - 1 ? nullptr : *(p + 1);
3738 else
3739 return p == clips.begin() ? nullptr : *(p - 1);
3740}

References forward, and SortedClipArray().

Referenced by GetAdjacentClip(), and SetFloatsWithinTimeRange().

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

◆ GetNextInterval() [1/2]

WaveTrack::IntervalHolder WaveTrack::GetNextInterval ( const Interval interval,
PlaybackDirection  searchDirection 
)

Returns
Interval that starts after(before) the beginning of the passed interval

Definition at line 556 of file WaveTrack.cpp.

558{
559 return std::const_pointer_cast<Interval>(
560 std::as_const(*this).GetNextInterval(interval, searchDirection));
561}

◆ GetNextInterval() [2/2]

std::shared_ptr< const WaveTrack::Interval > WaveTrack::GetNextInterval ( const Interval interval,
PlaybackDirection  searchDirection 
) const
Returns
Interval that starts after(before) the beginning of the passed interval

Definition at line 534 of file WaveTrack.cpp.

535{
536 std::shared_ptr<const Interval> result;
537 auto bestMatchTime = searchDirection == PlaybackDirection::forward
538 ? std::numeric_limits<double>::max()
539 : std::numeric_limits<double>::lowest();
540
541 for(const auto& other : Intervals())
542 {
543 if((searchDirection == PlaybackDirection::forward &&
544 (other->Start() > interval.Start() && other->Start() < bestMatchTime))
545 ||
546 (searchDirection == PlaybackDirection::backward &&
547 (other->Start() < interval.Start() && other->Start() > bestMatchTime)))
548 {
549 result = other;
550 bestMatchTime = other->Start();
551 }
552 }
553 return result;
554}
STL namespace.

References backward, forward, Intervals(), and ChannelGroupInterval::Start().

Referenced by ApplyPitchAndSpeed(), anonymous_namespace{WaveClipAdjustBorderHandle.cpp}::GetLeftAdjustLimit(), anonymous_namespace{WaveClipAdjustBorderHandle.cpp}::GetRightAdjustLimit(), and WaveTrackUtilities::SetClipStretchRatio().

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

◆ GetNumClips() [1/2]

int WaveTrack::GetNumClips ( ) const

Definition at line 3872 of file WaveTrack.cpp.

3873{
3874 return mClips.size();
3875}

References mClips.

Referenced by ApplyPitchAndSpeed(), and PasteOne().

Here is the caller graph for this function:

◆ GetNumClips() [2/2]

int WaveTrack::GetNumClips ( double  t0,
double  t1 
) const

Definition at line 3877 of file WaveTrack.cpp.

3878{
3879 const auto clips = SortedClipArray();
3880 // Find first position where the comparison is false
3881 const auto firstIn = std::lower_bound(clips.begin(), clips.end(), t0,
3882 [](const auto& clip, double t0) {
3883 return clip->GetPlayEndTime() <= t0;
3884 });
3885 // Find first position where the comparison is false
3886 const auto firstOut = std::lower_bound(firstIn, clips.end(), t1,
3887 [](const auto& clip, double t1) {
3888 return clip->GetPlayStartTime() < t1;
3889 });
3890 return std::distance(firstIn, firstOut);
3891}

References SortedClipArray().

Here is the call graph for this function:

◆ GetOne()

bool WaveTrack::GetOne ( samplePtr  buffer,
sampleFormat  format,
sampleCount  start,
size_t  len,
bool  backwards,
fillFormat  fill,
bool  mayThrow,
sampleCount pNumWithinClips 
) const
private

Definition at line 3401 of file WaveTrack.cpp.

3405{
3406 if (backwards)
3407 start -= len;
3408 // Simple optimization: When this buffer is completely contained within one clip,
3409 // don't clear anything (because we won't have to). Otherwise, just clear
3410 // everything to be on the safe side.
3411 bool doClear = true;
3412 bool result = true;
3413 sampleCount samplesCopied = 0;
3414 for (const auto &clip: mClips)
3415 {
3416 if (start >= clip->GetPlayStartSample() && start+len <= clip->GetPlayEndSample())
3417 {
3418 doClear = false;
3419 break;
3420 }
3421 }
3422 if (doClear)
3423 {
3424 // Usually we fill in empty space with zero
3425 if (fill == FillFormat::fillZero)
3426 ClearSamples(buffer, format, 0, len);
3427 // but we don't have to.
3428 else if (fill == FillFormat::fillTwo)
3429 {
3430 wxASSERT( format==floatSample );
3431 float * pBuffer = (float*)buffer;
3432 for(size_t i=0;i<len;i++)
3433 pBuffer[i]=2.0f;
3434 }
3435 else
3436 {
3437 wxFAIL_MSG(wxT("Invalid fill format"));
3438 }
3439 }
3440
3441 // Iterate the clips. They are not necessarily sorted by time.
3442 for (const auto &clip: mClips)
3443 {
3444 auto clipStart = clip->GetPlayStartSample();
3445 auto clipEnd = clip->GetPlayEndSample();
3446
3447 if (clipEnd > start && clipStart < start+len)
3448 {
3449 if (clip->HasPitchOrSpeed())
3450 return false;
3451
3452 // Clip sample region and Get/Put sample region overlap
3453 auto samplesToCopy =
3454 std::min( start+len - clipStart, clip->GetVisibleSampleCount() );
3455 auto startDelta = clipStart - start;
3456 decltype(startDelta) inclipDelta = 0;
3457 if (startDelta < 0)
3458 {
3459 inclipDelta = -startDelta; // make positive value
3460 samplesToCopy -= inclipDelta;
3461 // samplesToCopy is now either len or
3462 // (clipEnd - clipStart) - (start - clipStart)
3463 // == clipEnd - start > 0
3464 // samplesToCopy is not more than len
3465 //
3466 startDelta = 0;
3467 // startDelta is zero
3468 }
3469 else {
3470 // startDelta is nonnegative and less than len
3471 // samplesToCopy is positive and not more than len
3472 }
3473
3474 if (!clip->GetSamples(0,
3475 (samplePtr)(((char*)buffer) +
3476 startDelta.as_size_t() *
3478 format, inclipDelta, samplesToCopy.as_size_t(), mayThrow ))
3479 result = false;
3480 else
3481 samplesCopied += samplesToCopy;
3482 }
3483 }
3484 if( pNumWithinClips )
3485 *pNumWithinClips = samplesCopied;
3486 if (result == true && backwards)
3487 ReverseSamples(buffer, format, 0, len);
3488 return result;
3489}
wxT("CloseDown"))
void ReverseSamples(samplePtr dst, sampleFormat format, int start, int len)
#define SAMPLE_SIZE(SampleFormat)
Definition: SampleFormat.h:52

References ClearSamples(), fillTwo, fillZero, floatSample, anonymous_namespace{ExportPCM.cpp}::format, mClips, min(), ReverseSamples(), SAMPLE_SIZE, and wxT().

Here is the call graph for this function:

◆ GetPan()

float WaveTrack::GetPan ( ) const

Definition at line 1173 of file WaveTrack.cpp.

1174{
1175 return WaveTrackData::Get(*this).GetPan();
1176}

References BasicUI::Get().

Referenced by GetChannelGain(), WaveTrackControls::PanSlider(), GetInfoCommand::SendTracks(), SetPan(), and WriteOneXML().

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

◆ GetRate()

double WaveTrack::GetRate ( ) const
overridevirtual

Implements RecordableSequence.

Definition at line 1128 of file WaveTrack.cpp.

1129{
1130 return WaveTrackData::Get(*this).GetRate();
1131}

References BasicUI::Get().

Referenced by ProjectFileManager::AddImportedTracks(), SelectHandle::AdjustFreqSelection(), EffectTruncSilence::Analyze(), VoiceKey::CalibrateNoise(), ClearAndPasteOne(), CopyOne(), CreateClip(), SpectrumVRulerControls::DoHandleWheelRotation(), SpectrumVZoomHandle::DoZoom(), WaveformVZoomHandle::DoZoom(), EmptyCopy(), SpectrogramBounds::GetBounds(), GetEnvelopeValues(), anonymous_namespace{WaveClipAdjustBorderHandle.cpp}::GetLeftAdjustLimit(), anonymous_namespace{WaveClipAdjustBorderHandle.cpp}::GetRightAdjustLimit(), TranscriptionToolBar::GetSamples(), InsertSilence(), JoinOne(), SelectHandle::MoveSnappingFreqSelection(), VoiceKey::OffBackward(), VoiceKey::OffForward(), VoiceKey::OnBackward(), VoiceKey::OnForward(), WaveTrackMenuTable::OnMergeStereo(), PasteOne(), anonymous_namespace{BrushHandle.cpp}::PositionToFrequency(), anonymous_namespace{SelectHandle.cpp}::PositionToFrequency(), EffectPaulstretch::ProcessOne(), EffectStereoToMono::ProcessOne(), SpectralDataManager::Worker::ProcessOvertones(), PerTrackEffect::ProcessPass(), SpectralDataManager::Worker::ProcessSnapping(), ProjectNyquistFrequency(), SelectHandle::SnapCenterOnce(), SelectHandle::StartSnappingFreqSelection(), anonymous_namespace{WaveTrackControls.cpp}::Status1DrawFunction(), SyncLockAdjust(), and WriteOneXML().

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

◆ GetRightmostClip()

const WaveClip * WaveTrack::GetRightmostClip ( ) const

Definition at line 3045 of file WaveTrack.cpp.

3045 {
3046 if (mClips.empty())
3047 return nullptr;
3048 return std::max_element(
3049 mClips.begin(), mClips.end(),
3050 [](const auto& a, const auto b) {
3051 return a->GetPlayEndTime() < b->GetPlayEndTime();
3052 })
3053 ->get();
3054}

References mClips.

Referenced by ProjectAudioManager::DoRecord(), and PasteOne().

Here is the caller graph for this function:

◆ GetSampleFormat()

sampleFormat WaveTrack::GetSampleFormat ( ) const
overridevirtual

Implements RecordableSequence.

Definition at line 1263 of file WaveTrack.cpp.

1264{
1265 return WaveTrackData::Get(*this).GetSampleFormat();
1266}

References BasicUI::Get().

Referenced by CopyOne(), CreateClip(), EmptyCopy(), GetMaxBlockSize(), InsertSilence(), WaveTrackMenuTable::OnMergeStereo(), SyncLockAdjust(), and WriteOneXML().

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

◆ GetSampleView()

ChannelGroupSampleView WaveTrack::GetSampleView ( double  t0,
double  t1,
bool  mayThrow = true 
) const

Request samples within [t0, t1), not knowing in advance how many this will be.

The stretching of intersecting intervals influences the number of samples fitting into [t0, t1), i.e., half as many for twice as large a stretch ratio, due to a larger spacing of the raw samples.

Precondition
IsLeader()
Postcondition
result: result.size() == NChannels()
Precondition
samples in [t0, t1) can be counted with size_t

Definition at line 3492 of file WaveTrack.cpp.

3493{
3494 assert(IsLeader());
3496 for (const auto& channel : Channels()) {
3497 result.push_back(channel->GetSampleView(t0, t1, mayThrow));
3498 }
3499 return result;
3500}
std::vector< std::vector< AudioSegmentSampleView > > ChannelGroupSampleView
Definition: MixerBoard.h:35
auto Channels()
Definition: WaveTrack.h:277

References Channels(), and IsLeader().

Here is the call graph for this function:

◆ GetSequenceSamplesCount()

sampleCount WaveTrack::GetSequenceSamplesCount ( ) const
Returns
the total number of samples in all underlying sequences of all clips, across all channels (including hidden audio but not counting the cutlines)
Precondition
IsLeader()

Definition at line 1240 of file WaveTrack.cpp.

1241{
1242 assert(IsLeader());
1243 sampleCount result{ 0 };
1244
1245 for (const auto pChannel : TrackList::Channels(this))
1246 for (const auto& clip : pChannel->mClips)
1247 result += clip->GetSequenceSamplesCount();
1248
1249 return result;
1250}

References TrackList::Channels(), and IsLeader().

Here is the call graph for this function:

◆ GetSolo()

bool WaveTrack::GetSolo ( ) const
overridevirtual

May vary asynchronously.

Implements PlayableSequence.

Definition at line 2835 of file WaveTrack.cpp.

2836{
2837 return PlayableTrack::GetSolo();
2838}
bool GetSolo() const
Definition: PlayableTrack.h:48

References PlayableTrack::GetSolo().

Referenced by ExportAudioDialog::DoExportSplitByTracks(), ExportUtils::FindExportWaveTracks(), anonymous_namespace{ExportAudioDialog.cpp}::GetNumExportChannels(), GetInfoCommand::SendTracks(), and ExportAudioDialog::UpdateTrackExportSettings().

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

◆ GetStartTime()

double WaveTrack::GetStartTime ( ) const
overridevirtual

Implement WideSampleSequence.

Implements WideSampleSequence.

Definition at line 3087 of file WaveTrack.cpp.

3088{
3090}
double GetStartTime() const
Get the minimum of Start() values of intervals, or 0 when none.
Definition: Channel.cpp:124

References ChannelGroup::GetStartTime().

Referenced by ApplyPitchAndSpeed(), ClearAndPasteAtSameTempo(), Effect::GetBounds(), TranscriptionToolBar::GetSamples(), MoveTo(), PasteWaveTrackAtSameTempo(), EffectStereoToMono::ProcessOne(), GetInfoCommand::SendTracks(), and Trim().

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

◆ GetTypeInfo()

auto WaveTrack::GetTypeInfo ( ) const
overridevirtual

Reimplemented from WritableSampleTrack.

Definition at line 994 of file WaveTrack.cpp.

995{
996 return typeInfo();
997}

References typeInfo().

Here is the call graph for this function:

◆ GetVisibleSampleCount()

sampleCount WaveTrack::GetVisibleSampleCount ( ) const

Definition at line 1230 of file WaveTrack.cpp.

1231{
1232 sampleCount result{ 0 };
1233
1234 for (const auto& clip : mClips)
1235 result += clip->GetVisibleSampleCount();
1236
1237 return result;
1238}

References mClips.

◆ GetWaveColorIndex()

int WaveTrack::GetWaveColorIndex ( ) const

Definition at line 1214 of file WaveTrack.cpp.

1215{
1216 return WaveTrackData::Get(*this).GetWaveColorIndex();
1217}

References BasicUI::Get().

Referenced by CreateClip(), HandleXMLChild(), InsertSilence(), and WriteOneXML().

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

◆ GetWidth()

size_t WaveTrack::GetWidth ( ) const

The width of every WaveClip in this track; for now always 1.

Definition at line 831 of file WaveTrack.cpp.

832{
833 return 1;
834}

Referenced by AddClip(), ClearAndPasteOne(), and CreateClip().

Here is the caller graph for this function:

◆ HandleClear()

void WaveTrack::HandleClear ( double  t0,
double  t1,
bool  addCutLines,
bool  split,
bool  clearByTrimming = false 
)
private
Exception safety guarantee:
Strong

Definition at line 1952 of file WaveTrack.cpp.

1954{
1955 // For debugging, use an ASSERT so that we stop
1956 // closer to the problem.
1957 wxASSERT( t1 >= t0 );
1958 if (t1 < t0)
1960
1961 t0 = SnapToSample(t0);
1962 t1 = SnapToSample(t1);
1963
1964 WaveClipPointers clipsToDelete;
1965 WaveClipHolders clipsToAdd;
1966
1967 // We only add cut lines when deleting in the middle of a single clip
1968 // The cut line code is not really prepared to handle other situations
1969 if (addCutLines)
1970 {
1971 for (const auto &clip : mClips)
1972 {
1973 if (clip->PartlyWithinPlayRegion(t0, t1))
1974 {
1975 addCutLines = false;
1976 break;
1977 }
1978 }
1979 }
1980
1981 for (const auto &clip : mClips)
1982 {
1983 if (clip->CoversEntirePlayRegion(t0, t1))
1984 {
1985 // Whole clip must be deleted - remember this
1986 clipsToDelete.push_back(clip.get());
1987 }
1988 else if (clip->IntersectsPlayRegion(t0, t1))
1989 {
1990 // Clip data is affected by command
1991 if (addCutLines)
1992 {
1993 // Don't modify this clip in place, because we want a strong
1994 // guarantee, and might modify another clip
1995 clipsToDelete.push_back( clip.get() );
1996 auto newClip =
1997 std::make_shared<WaveClip>(*clip, mpFactory, true);
1998 newClip->ClearAndAddCutLine( t0, t1 );
1999 clipsToAdd.push_back( std::move( newClip ) );
2000 }
2001 else
2002 {
2003 if (split || clearByTrimming) {
2004 // Three cases:
2005
2006 if (clip->BeforePlayRegion(t0)) {
2007 // Delete from the left edge
2008
2009 // Don't modify this clip in place, because we want a strong
2010 // guarantee, and might modify another clip
2011 clipsToDelete.push_back( clip.get() );
2012 auto newClip =
2013 std::make_shared<WaveClip>(*clip, mpFactory, true);
2014 newClip->TrimLeft(t1 - clip->GetPlayStartTime());
2015 if (!split)
2016 // If this is not a split-cut, where things are left in
2017 // place, we need to reposition the clip.
2018 newClip->ShiftBy(t0 - t1);
2019 clipsToAdd.push_back( std::move( newClip ) );
2020 }
2021 else if (clip->AfterPlayRegion(t1)) {
2022 // Delete to right edge
2023
2024 // Don't modify this clip in place, because we want a strong
2025 // guarantee, and might modify another clip
2026 clipsToDelete.push_back( clip.get() );
2027 auto newClip =
2028 std::make_shared<WaveClip>(*clip, mpFactory, true);
2029 newClip->TrimRight(clip->GetPlayEndTime() - t0);
2030
2031 clipsToAdd.push_back( std::move( newClip ) );
2032 }
2033 else {
2034 // Delete in the middle of the clip...we actually create two
2035 // NEW clips out of the left and right halves...
2036
2037 auto leftClip =
2038 std::make_shared<WaveClip>(*clip, mpFactory, true);
2039 leftClip->TrimRight(clip->GetPlayEndTime() - t0);
2040 clipsToAdd.push_back(std::move(leftClip));
2041
2042 auto rightClip =
2043 std::make_shared<WaveClip>(*clip, mpFactory, true);
2044 rightClip->TrimLeft(t1 - clip->GetPlayStartTime());
2045 if (!split)
2046 // If this is not a split-cut, where things are left in
2047 // place, we need to reposition the clip.
2048 rightClip->ShiftBy(t0 - t1);
2049 clipsToAdd.push_back(std::move(rightClip));
2050
2051 clipsToDelete.push_back(clip.get());
2052 }
2053 }
2054 else {
2055 // (We are not doing a split cut)
2056
2057 // Don't modify this clip in place, because we want a strong
2058 // guarantee, and might modify another clip
2059 clipsToDelete.push_back( clip.get() );
2060 auto newClip =
2061 std::make_shared<WaveClip>(*clip, mpFactory, true);
2062
2063 // clip->Clear keeps points < t0 and >= t1 via Envelope::CollapseRegion
2064 newClip->Clear(t0,t1);
2065
2066 clipsToAdd.push_back( std::move( newClip ) );
2067 }
2068 }
2069 }
2070 }
2071
2072 // Only now, change the contents of this track
2073 // use No-fail-guarantee for the rest
2074
2075 const auto moveClipsLeft = !split && GetEditClipsCanMove();
2076 if (moveClipsLeft)
2077 // Clip is "behind" the region -- offset it unless we're splitting
2078 // or we're using the "don't move other clips" mode
2079 for (const auto& clip : mClips)
2080 if (clip->AtOrBeforePlayRegion(t1))
2081 clip->ShiftBy(-(t1 - t0));
2082
2083 for (const auto &clip: clipsToDelete)
2084 {
2085 auto myIt = FindClip(mClips, clip);
2086 if (myIt != mClips.end())
2087 mClips.erase(myIt); // deletes the clip!
2088 else
2089 wxASSERT(false);
2090 }
2091
2092 for (auto &clip: clipsToAdd)
2093 InsertClip(std::move(clip)); // transfer ownership
2094}
std::vector< WaveClip * > WaveClipPointers
Definition: WaveTrack.h:49

References anonymous_namespace{WaveTrack.cpp}::FindClip(), GetEditClipsCanMove(), InsertClip(), mClips, mpFactory, WideSampleSequence::SnapToSample(), and THROW_INCONSISTENCY_EXCEPTION.

Referenced by ClearAndPasteOne().

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

◆ HandleXMLChild()

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

Implements XMLTagHandler.

Definition at line 2907 of file WaveTrack.cpp.

2908{
2909 if ( auto pChild = WaveTrackIORegistry::Get()
2910 .CallObjectAccessor(tag, *this) )
2911 return pChild;
2912
2913 //
2914 // This is legacy code (1.2 and previous) and is not called for NEW projects!
2915 //
2916 if (tag == "sequence" || tag == "envelope")
2917 {
2918 // This is a legacy project, so set the cached offset
2920
2921 // Legacy project file tracks are imported as one single wave clip
2922 if (tag == "sequence")
2923 return NewestOrNewClip()->GetSequence(0);
2924 else if (tag == "envelope")
2925 return NewestOrNewClip()->GetEnvelope();
2926 }
2927
2928 // JKC... for 1.1.0, one step better than what we had, but still badly broken.
2929 // If we see a waveblock at this level, we'd better generate a sequence.
2930 if (tag == "waveblock")
2931 {
2932 // This is a legacy project, so set the cached offset
2934 Sequence *pSeq = NewestOrNewClip()->GetSequence(0);
2935 return pSeq;
2936 }
2937
2938 //
2939 // This is for the NEW file format (post-1.2)
2940 //
2941 if (tag == "waveclip")
2942 {
2943 // Make clips (which don't serialize the rate) consistent with channel rate,
2944 // though the consistency check of channels with each other remains to do.
2945 // Not all `WaveTrackData` fields are properly initialized by now,
2946 // use deserialization helpers.
2947 auto clip = std::make_shared<WaveClip>(1,
2949 const auto xmlHandler = clip.get();
2950 mClips.push_back(std::move(clip));
2951 return xmlHandler;
2952 }
2953
2954 return nullptr;
2955}
int mLegacyRate
used only during deserialization
Definition: WaveTrack.h:1124
sampleFormat mLegacyFormat
used only during deserialization
Definition: WaveTrack.h:1125
static XMLMethodRegistry & Get()
Get the unique instance.

References XMLMethodRegistry< Host >::Get(), WaveClip::GetEnvelope(), WaveClip::GetSequence(), GetWaveColorIndex(), mClips, mLegacyFormat, mLegacyProjectFileOffset, mLegacyRate, mpFactory, NewestOrNewClip(), and WaveClip::SetSequenceStartTime().

Here is the call graph for this function:

◆ HandleXMLEndTag()

void WaveTrack::HandleXMLEndTag ( const std::string_view &  tag)
override

Definition at line 2895 of file WaveTrack.cpp.

2896{
2897#if 0
2898 // In case we opened a pre-multiclip project, we need to
2899 // simulate closing the waveclip tag.
2900 NewestOrNewClip()->HandleXMLEndTag("waveclip");
2901#else
2902 // File compatibility breaks have intervened long since, and the line above
2903 // would now have undesirable side effects
2904#endif
2905}
void HandleXMLEndTag(const std::string_view &tag) override
Definition: WaveClip.cpp:630

References WaveClip::HandleXMLEndTag(), and NewestOrNewClip().

Here is the call graph for this function:

◆ HandleXMLTag()

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

Implements XMLTagHandler.

Definition at line 2840 of file WaveTrack.cpp.

2841{
2842 if (tag == "wavetrack") {
2843 double dblValue;
2844 long nValue;
2845
2846 for (const auto& pair : attrs)
2847 {
2848 const auto& attr = pair.first;
2849 const auto& value = pair.second;
2850
2851 if (attr == "rate")
2852 {
2853 // mRate is an int, but "rate" in the project file is a float.
2854 if (!value.TryGet(dblValue) ||
2855 (dblValue < 1.0) || (dblValue > 1000000.0)) // allow a large range to be read
2856 return false;
2857
2858 // Defer the setting of rate until LinkConsistencyFix
2859 mLegacyRate = lrint(dblValue);
2860 }
2861 else if (attr == "offset" && value.TryGet(dblValue))
2862 {
2863 // Offset is only relevant for legacy project files. The value
2864 // is cached until the actual WaveClip containing the legacy
2865 // track is created.
2866 mLegacyProjectFileOffset = dblValue;
2867 }
2868 else if (this->WritableSampleTrack::HandleXMLAttribute(attr, value))
2869 {}
2870 else if (this->Track::HandleCommonXMLAttribute(attr, value))
2871 ;
2872 else if (attr == "gain" && value.TryGet(dblValue))
2873 DoSetGain(dblValue);
2874 else if (attr == "pan" && value.TryGet(dblValue) &&
2875 (dblValue >= -1.0) && (dblValue <= 1.0))
2876 DoSetPan(dblValue);
2877 else if (attr == "linked" && value.TryGet(nValue))
2878 SetLinkType(ToLinkType(nValue), false);
2879 else if (attr == "colorindex" && value.TryGet(nValue))
2880 // Don't use SetWaveColorIndex as it sets the clips too.
2881 WaveTrackData::Get(*this).SetWaveColorIndex(nValue);
2882 else if (attr == "sampleformat" && value.TryGet(nValue) &&
2884 {
2885 //Remember sample format until consistency check is performed.
2886 SetLegacyFormat(static_cast<sampleFormat>(nValue));
2887 }
2888 } // while
2889 return true;
2890 }
2891
2892 return false;
2893}
sampleFormat
The ordering of these values with operator < agrees with the order of increasing bit width.
Definition: SampleFormat.h:30
bool HandleXMLAttribute(const std::string_view &attr, const XMLAttributeValueView &value)
static bool IsValidSampleFormat(const int nValue)
true if nValue is one of the sampleFormat enum values
Definition: Sequence.cpp:1875
void SetLinkType(LinkType linkType, bool completeList=true)
Definition: Track.cpp:140
bool HandleCommonXMLAttribute(const std::string_view &attr, const XMLAttributeValueView &valueView)
Definition: Track.cpp:1235
void DoSetPan(float value)
Definition: WaveTrack.cpp:1178
void SetLegacyFormat(sampleFormat format)
Definition: WaveTrack.cpp:2783
void DoSetGain(float value)
Definition: WaveTrack.cpp:1160
#define lrint(dbl)
Definition: float_cast.h:169
Track::LinkType ToLinkType(int value)
Definition: WaveTrack.cpp:720

References DoSetGain(), DoSetPan(), BasicUI::Get(), Track::HandleCommonXMLAttribute(), PlayableTrack::HandleXMLAttribute(), Sequence::IsValidSampleFormat(), lrint, mLegacyProjectFileOffset, mLegacyRate, SetLegacyFormat(), Track::SetLinkType(), and anonymous_namespace{WaveTrack.cpp}::ToLinkType().

Here is the call graph for this function:

◆ HasHiddenData()

bool WaveTrack::HasHiddenData ( ) const

Whether any clips have hidden audio.

Precondition
IsLeader()

Definition at line 4422 of file WaveTrack.cpp.

4423{
4424 assert(IsLeader());
4425 for (const auto pChannel : TrackList::Channels(this))
4426 for (const auto& clip : pChannel->GetClips())
4427 if (clip->GetTrimLeft() != 0 || clip->GetTrimRight() != 0)
4428 return true;
4429 return false;
4430}

References TrackList::Channels(), and IsLeader().

Here is the call graph for this function:

◆ HasTrivialEnvelope()

bool WaveTrack::HasTrivialEnvelope ( ) const
overridevirtual
Returns
whether envelope values are all unit

Implements WideSampleSequence.

Definition at line 3610 of file WaveTrack.cpp.

3611{
3612 auto pTrack = this;
3613 if (GetOwner())
3614 // Substitute the leader track
3615 pTrack = *TrackList::Channels(this).begin();
3616 auto &clips = pTrack->GetClips();
3617 return std::all_of(clips.begin(), clips.end(),
3618 [](const auto &pClip){ return pClip->GetEnvelope()->IsTrivial(); });
3619}

References TrackList::Channels(), and Track::GetOwner().

Here is the call graph for this function:

◆ Init()

void WaveTrack::Init ( const WaveTrack orig)
private

Definition at line 859 of file WaveTrack.cpp.

860{
862 mpFactory = orig.mpFactory;
863}
void Init(const Track &orig)
Definition: Track.cpp:50

References Track::Init(), and mpFactory.

Here is the call graph for this function:

◆ InsertClip()

bool WaveTrack::InsertClip ( WaveClipHolder  clip,
bool  backup = false 
)
private

Adds clip to the track. Clip should be not empty or to be a placeholder.

Sets project tempo on clip upon push. Use this instead of mClips.push_back

Returns
true on success
Parameters
backupwhether the duplication is for backup purposes while opening a project, instead of other editing operations

Definition at line 2381 of file WaveTrack.cpp.

2382{
2383 if(!backup && !clip->GetIsPlaceholder() && clip->IsEmpty())
2384 return false;
2385
2386 const auto& tempo = GetProjectTempo();
2387 if (tempo.has_value())
2388 clip->OnProjectTempoChange(std::nullopt, *tempo);
2389 mClips.push_back(std::move(clip));
2390
2391 return true;
2392}

References Track::GetProjectTempo(), and mClips.

Referenced by AddClip(), CopyOne(), HandleClear(), PasteOne(), SplitAt(), and WaveTrack().

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

◆ InsertInterval()

void WaveTrack::InsertInterval ( const IntervalHolder interval)
private
Precondition
IsLeader()

Definition at line 4158 of file WaveTrack.cpp.

4159{
4160 assert(IsLeader());
4161 auto channel = 0;
4162 for (const auto pChannel : TrackList::Channels(this))
4163 {
4164 const auto clip = interval->GetClip(channel++);
4165 if (clip)
4166 pChannel->InsertClip(clip);
4167 }
4168}

References TrackList::Channels(), and IsLeader().

Referenced by ReplaceInterval().

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

◆ InsertSilence()

void WaveTrack::InsertSilence ( double  t,
double  len 
)
overridevirtual
Exception safety guarantee:
Strong

Implements RecordableSequence.

Definition at line 2477 of file WaveTrack.cpp.

2478{
2479 assert(IsLeader());
2480 // Nothing to do, if length is zero.
2481 // Fixes Bug 1626
2482 if (len == 0)
2483 return;
2484 if (len <= 0)
2486
2487 for (const auto pChannel : TrackList::Channels(this)) {
2488 auto &clips = pChannel->mClips;
2489 if (clips.empty()) {
2490 // Special case if there is no clip yet
2491 // TODO wide wave tracks -- match clip width
2492 auto clip = std::make_shared<WaveClip>(1,
2494 clip->InsertSilence(0, len);
2495 // use No-fail-guarantee
2496 pChannel->InsertClip(move(clip));
2497 }
2498 else
2499 {
2500 // Assume at most one clip contains t
2501 const auto end = clips.end();
2502 const auto it = std::find_if(clips.begin(), end,
2503 [&](const WaveClipHolder &clip) { return clip->SplitsPlayRegion(t); } );
2504
2505 // use Strong-guarantee
2506 if (it != end)
2507 it->get()->InsertSilence(t, len);
2508
2509 // use No-fail-guarantee
2510 for (const auto &clip : clips)
2511 if (clip->BeforePlayRegion(t))
2512 clip->ShiftBy(len);
2513 }
2514 }
2515}

References TrackList::Channels(), PackedArray::end(), GetRate(), GetSampleFormat(), GetWaveColorIndex(), IsLeader(), mpFactory, and THROW_INCONSISTENCY_EXCEPTION.

Referenced by AUPImportFileHandle::AddSilence().

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

◆ Intervals() [1/2]

auto WaveTrack::Intervals ( )
inline

Definition at line 1041 of file WaveTrack.h.

1041{ return ChannelGroup::Intervals<Interval>(); }

Referenced by ProjectFileManager::AddImportedTracks(), SetClipCommand::Apply(), Disjoin(), GetIntervalAtTime(), GetNextInterval(), Join(), and WaveTrackMenuTable::OnMergeStereo().

Here is the caller graph for this function:

◆ Intervals() [2/2]

auto WaveTrack::Intervals ( ) const
inline

Definition at line 1042 of file WaveTrack.h.

1042{ return ChannelGroup::Intervals<const Interval>(); }

◆ IsEmpty()

bool WaveTrack::IsEmpty ( double  t0,
double  t1 
) const

Returns true if there are no WaveClips in the specified region.

Returns
true if no clips in the track overlap the specified time range, false otherwise.

Definition at line 1281 of file WaveTrack.cpp.

1282{
1283 if (t0 > t1)
1284 return true;
1285
1286 //wxPrintf("Searching for overlap in %.6f...%.6f\n", t0, t1);
1287 for (const auto &clip : mClips)
1288 {
1289 if (clip->IntersectsPlayRegion(t0, t1)) {
1290 //wxPrintf("Overlapping clip: %.6f...%.6f\n",
1291 // clip->GetStartTime(),
1292 // clip->GetEndTime());
1293 // We found a clip that overlaps this region
1294 return false;
1295 }
1296 }
1297 //wxPrintf("No overlap found\n");
1298
1299 // Otherwise, no clips overlap this region
1300 return true;
1301}

References mClips.

Referenced by PasteOne(), and SyncLockAdjust().

Here is the caller graph for this function:

◆ IsLeader()

bool WaveTrack::IsLeader ( ) const
overridevirtual

◆ Join()

void WaveTrack::Join ( double  t0,
double  t1,
const ProgressReporter reportProgress 
)
Precondition
IsLeader()
Exception safety guarantee:
Weak

Definition at line 2608 of file WaveTrack.cpp.

2610{
2611 assert(IsLeader());
2612 // Merge all WaveClips overlapping selection into one
2613 const auto intervals = Intervals();
2614 std::vector<IntervalHolder> intervalsToJoin;
2615 for (auto interval : intervals)
2616 if (interval->IntersectsPlayRegion(t0, t1))
2617 intervalsToJoin.push_back(interval);
2618 if (intervalsToJoin.size() < 2u)
2619 return;
2620 if (std::any_of(
2621 intervalsToJoin.begin() + 1, intervalsToJoin.end(),
2622 [first = intervalsToJoin[0]](const auto& interval) {
2623 return !first->HasEqualPitchAndSpeed(*interval);
2624 }))
2625 ApplyPitchAndSpeedOnIntervals(intervalsToJoin, reportProgress);
2626
2627 for (const auto pChannel : TrackList::Channels(this))
2628 JoinOne(*pChannel, t0, t1);
2629}
static void JoinOne(WaveTrack &track, double t0, double t1)
Definition: WaveTrack.cpp:2631

References ApplyPitchAndSpeedOnIntervals(), TrackList::Channels(), Intervals(), IsLeader(), and JoinOne().

Referenced by anonymous_namespace{LabelMenus.cpp}::OnJoinLabels().

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

◆ JoinOne()

void WaveTrack::JoinOne ( WaveTrack track,
double  t0,
double  t1 
)
staticprivate
Precondition
All clips intersecting [t0, t1) have unit stretch ratio

Definition at line 2631 of file WaveTrack.cpp.

2633{
2634 WaveClipPointers clipsToDelete;
2635 WaveClip* newClip{};
2636
2637 const auto rate = track.GetRate();
2638 auto &clips = track.mClips;
2639 for (const auto &clip: clips) {
2640 if (clip->IntersectsPlayRegion(t0, t1)) {
2641 // Put in sorted order
2642 auto it = clipsToDelete.begin(), end = clipsToDelete.end();
2643 for (; it != end; ++it)
2644 if ((*it)->GetPlayStartTime() > clip->GetPlayStartTime())
2645 break;
2646 //wxPrintf("Insert clip %.6f at position %d\n", clip->GetStartTime(), i);
2647 clipsToDelete.insert(it, clip.get());
2648 }
2649 }
2650
2651 //if there are no clips to DELETE, nothing to do
2652 if (clipsToDelete.empty())
2653 return;
2654
2655 auto t = clipsToDelete[0]->GetPlayStartTime();
2656 //preserve left trim data if any
2657 newClip = track.CreateClip(clipsToDelete[0]->GetSequenceStartTime(),
2658 clipsToDelete[0]->GetName());
2659
2660 for (auto clip : clipsToDelete) {
2661 // wxPrintf("t=%.6f adding clip (offset %.6f, %.6f ... %.6f)\n",
2662 // t, clip->GetOffset(), clip->GetStartTime(),
2663 // clip->GetEndTime());
2664
2665 if (clip->GetPlayStartTime() - t > (1.0 / rate))
2666 {
2667 double addedSilence = (clip->GetPlayStartTime() - t);
2668 // wxPrintf("Adding %.6f seconds of silence\n");
2669 auto offset = clip->GetPlayStartTime();
2670 auto value = clip->GetEnvelope()->GetValue(offset);
2671 newClip->AppendSilence(addedSilence, value);
2672 t += addedSilence;
2673 }
2674
2675 // wxPrintf("Pasting at %.6f\n", t);
2676 bool success = newClip->Paste(t, *clip);
2677 assert(success); // promise of CreateClip
2678
2679 t = newClip->GetPlayEndTime();
2680
2681 auto it = FindClip(clips, clip);
2682 clips.erase(it); // deletes the clip
2683 }
2684}
const wxString & GetName() const
Name is always the same for all channels of a group.
Definition: Track.cpp:56
WaveClip * CreateClip(double offset=.0, const wxString &name=wxEmptyString)
Create new clip and add it to this track.
Definition: WaveTrack.cpp:3801

References CreateClip(), PackedArray::end(), anonymous_namespace{WaveTrack.cpp}::FindClip(), Track::GetName(), WaveClip::GetPlayStartTime(), GetRate(), and mClips.

Referenced by Join().

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

◆ LinkConsistencyFix()

bool WaveTrack::LinkConsistencyFix ( bool  doFix)
overridevirtual

Check consistency of channel groups, and maybe fix it.

Parameters
doFixwhether to make any changes to correct inconsistencies
Precondition
!doFix || IsLeader()
Returns
true if no inconsistencies were found

Reimplemented from Track.

Definition at line 911 of file WaveTrack.cpp.

912{
913 assert(!doFix || IsLeader());
914
915
916 const auto removeZeroClips = [](WaveClipHolders& clips) {
917 // Check for zero-length clips and remove them
918 for (auto it = clips.begin(); it != clips.end();)
919 {
920 if ((*it)->IsEmpty())
921 it = clips.erase(it);
922 else
923 ++it;
924 }
925 };
926
928
929 const auto linkType = GetLinkType();
930 if (linkType != LinkType::None) {
931 auto next = *TrackList::Channels(this).first.advance(1);
932 if (next == nullptr) {
933 //next track is absent or not a wave track, fix and report error
934 if (doFix) {
935 wxLogWarning(L"Right track %s is expected to be a WaveTrack."
936 "\n Removing link from left wave track %s.",
937 next->GetName(), GetName());
939 }
940 err = true;
941 }
942 else if (doFix) {
943 // non-error upgrades happen here
944 if (!AreAligned(SortedClipArray(), next->SortedClipArray()) ||
946 {
948 }
949 else
950 {
952 // Be sure to lose any right channel group data that might
953 // have been made during during deserialization of the channel
954 // before joining it
955 next->DestroyGroupData();
956 //clean up zero clips only after alignment check has completed
957 //this can't break alignment as there should be a "twin"
958 //in the right channel which will also be removed, otherwise
959 //track will be unlinked
960 removeZeroClips(next->mClips);
961 }
962 }
963 }
964 if (doFix) {
965 // More non-error upgrading
966 // Set the common channel group rate from the leader's rate
967 if (mLegacyRate > 0)
968 {
969 WaveTrack *next{};
970 if (linkType != LinkType::None)
971 next = *TrackList::Channels(this).first.advance(1);
973 mLegacyRate = 0;
974 if (next)
975 next->mLegacyRate = 0;
977 WaveTrackData::Get(*this).SetSampleFormat(mLegacyFormat);
978 if (next && next->mLegacyFormat != undefinedSample)
979 WaveTrackData::Get(*next).SetSampleFormat(mLegacyFormat);
980 }
981 removeZeroClips(mClips);
982 }
983 return !err;
984}
@ Aligned
Tracks are grouped and changes should be synchronized.
virtual bool LinkConsistencyFix(bool doFix=true)
Check consistency of channel groups, and maybe fix it.
Definition: Track.cpp:299
LinkType GetLinkType() const noexcept
Definition: Track.cpp:1280
void SetRate(double newRate)
Definition: WaveTrack.cpp:1133
bool FormatConsistencyCheck() const
Whether all tracks in group and all clips have a common sample format.
Definition: WaveTrack.cpp:2370
bool RateConsistencyCheck() const
Whether all clips of a leader track have a common rate.
Definition: WaveTrack.cpp:2349
bool AreAligned(const WaveClipPointers &a, const WaveClipPointers &b)
Definition: WaveTrack.cpp:701

References ChannelGroup::Aligned, anonymous_namespace{WaveTrack.cpp}::AreAligned(), TrackList::Channels(), FormatConsistencyCheck(), BasicUI::Get(), Track::GetLinkType(), Track::GetName(), IsLeader(), Track::LinkConsistencyFix(), mClips, mLegacyFormat, mLegacyRate, ChannelGroup::None, RateConsistencyCheck(), Track::SetLinkType(), SetRate(), SortedClipArray(), and undefinedSample.

Here is the call graph for this function:

◆ MakeClipCopyName()

wxString WaveTrack::MakeClipCopyName ( const wxString &  originalName) const
private

Definition at line 1104 of file WaveTrack.cpp.

1105{
1106 auto name = originalName;
1107 for (auto i = 1;; ++i)
1108 {
1109 if (FindClipByName(name) == nullptr)
1110 return name;
1111 //i18n-hint Template for clip name generation on copy-paste
1112 name = XC("%s.%i", "clip name template").Format(originalName, i).Translation();
1113 }
1114}
#define XC(s, c)
Definition: Internat.h:37
const WaveClip * FindClipByName(const wxString &name) const
Returns nullptr if clip with such name was not found.
Definition: WaveTrack.cpp:1047

References FindClipByName(), name, and XC.

Referenced by PasteOne().

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

◆ MakeNewClipName()

wxString WaveTrack::MakeNewClipName ( ) const
private

Definition at line 1116 of file WaveTrack.cpp.

1117{
1118 auto name = GetName();
1119 for (auto i = 1;; ++i)
1120 {
1121 if (FindClipByName(name) == nullptr)
1122 return name;
1123 //i18n-hint Template for clip name generation on inserting new empty clip
1124 name = XC("%s %i", "clip name template").Format(GetName(), i).Translation();
1125 }
1126}

References FindClipByName(), Track::GetName(), name, and XC.

Referenced by NewestOrNewClip(), PasteOne(), and RightmostOrNewClip().

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

◆ MergeClips()

bool WaveTrack::MergeClips ( int  clipidx1,
int  clipidx2 
)

Definition at line 4106 of file WaveTrack.cpp.

4107{
4108 const auto channels = TrackList::Channels(this);
4109 return std::all_of(channels.begin(), channels.end(),
4110 [&](const auto pChannel){
4111 return pChannel->MergeOneClipPair(clipidx1, clipidx2); });
4112}

References TrackList::Channels().

Here is the call graph for this function:

◆ MergeOneClipPair()

bool WaveTrack::MergeOneClipPair ( int  clipidx1,
int  clipidx2 
)
private
Exception safety guarantee:
Strong

Definition at line 4115 of file WaveTrack.cpp.

4116{
4117 WaveClip* clip1 = GetClipByIndex(clipidx1);
4118 WaveClip* clip2 = GetClipByIndex(clipidx2);
4119
4120 if (!clip1 || !clip2) // Could happen if one track of a linked pair had a split and the other didn't.
4121 return false; // Don't throw, just do nothing.
4122
4123 if (!clip1->HasEqualPitchAndSpeed(*clip2))
4124 return false;
4125
4126 // Append data from second clip to first clip
4127 // use Strong-guarantee
4128 bool success = clip1->Paste(clip1->GetPlayEndTime(), *clip2);
4129 assert(success); // assuming clips of the same track must have same width
4130
4131 // use No-fail-guarantee for the rest
4132 // Delete second clip
4133 auto it = FindClip(mClips, clip2);
4134 mClips.erase(it);
4135
4136 return true;
4137}

References anonymous_namespace{WaveTrack.cpp}::FindClip(), GetClipByIndex(), WaveClip::GetPlayEndTime(), WaveClip::HasEqualPitchAndSpeed(), mClips, and WaveClip::Paste().

Referenced by ClearAndPasteOne().

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

◆ MonoToStereo()

TrackListHolder WaveTrack::MonoToStereo ( )
Precondition
!GetOwner()

Definition at line 1398 of file WaveTrack.cpp.

1399{
1400 assert(!GetOwner());
1401
1402 auto result = Duplicate();
1403 result->MakeMultiChannelTrack(**result->begin(), 2);
1404
1405 return result;
1406}

References Track::Duplicate(), and Track::GetOwner().

Here is the call graph for this function:

◆ MoveTo()

void WaveTrack::MoveTo ( double  origin)
overridevirtual
Exception safety guarantee:
No-fail

Implements ChannelGroup.

Definition at line 881 of file WaveTrack.cpp.

882{
883 double delta = origin - GetStartTime();
884 assert(IsLeader());
885 for (const auto pChannel : TrackList::Channels(this)) {
886 for (const auto &clip : pChannel->mClips)
887 // assume No-fail-guarantee
888 clip->ShiftBy(delta);
889 }
890 WaveTrackData::Get(*this).SetOrigin(origin);
891}

References TrackList::Channels(), BasicUI::Get(), GetStartTime(), and IsLeader().

Here is the call graph for this function:

◆ NChannels()

size_t WaveTrack::NChannels ( ) const
overridevirtual

May report more than one only when this is a leader track.

Implements RecordableSequence.

Definition at line 836 of file WaveTrack.cpp.

837{
838 if (IsLeader() && GetOwner()) {
839 auto result = TrackList::NChannels(*this);
840 assert(result > 0);
841 return result;
842 }
843 else
844 return 1;
845}

References Track::GetOwner(), IsLeader(), and TrackList::NChannels().

Referenced by WaveTrack::Interval::Append(), ProjectAudioManager::ChooseExistingRecordingTracks(), ClearAndPasteAtSameTempo(), WaveTrack::Interval::ClearLeft(), WaveTrack::Interval::ClearRight(), EffectBase::CountWaveTracks(), DEFINE_ATTACHED_VIRTUAL_OVERRIDE(), Disjoin(), DoGet(), WaveTrack::Interval::DoGetChannel(), DoGetChannel(), anonymous_namespace{TrackMenus.cpp}::DoMixAndRender(), EffectSBSMS::Finalize(), WaveTrack::Interval::ForEachClip(), GetClipInterfaces(), WaveTrack::Interval::GetRenderedCopy(), PasteWaveTrackAtSameTempo(), NyquistEffect::Process(), EffectReverse::Process(), Reinit(), WaveTrack::Interval::SetCentShift(), WaveTrack::Interval::SetTrimLeft(), WaveTrack::Interval::SetTrimRight(), WaveTrack::Interval::StretchBy(), WaveTrack::Interval::StretchLeftTo(), WaveTrack::Interval::StretchRightTo(), WaveTrack::Interval::TrimLeftTo(), and WaveTrack::Interval::TrimRightTo().

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

◆ New()

WaveTrack * WaveTrack::New ( AudacityProject project)
static

Definition at line 802 of file WaveTrack.cpp.

803{
804 auto &trackFactory = WaveTrackFactory::Get( project );
805 auto &tracks = TrackList::Get( project );
806 auto result = tracks.Add(trackFactory.Create());
807 result->AttachedTrackObjects::BuildAll();
808 return result;
809}
const auto tracks
const auto project
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:347
static WaveTrackFactory & Get(AudacityProject &project)
Definition: WaveTrack.cpp:4516

References TrackList::Get(), WaveTrackFactory::Get(), project, and tracks.

Here is the call graph for this function:

◆ NewestOrNewClip()

WaveClip * WaveTrack::NewestOrNewClip ( )

Get access to the most recently added clip, or create a clip, if there is not already one. THIS IS NOT NECESSARILY RIGHTMOST.

Returns
a pointer to the most recently added WaveClip

Definition at line 3821 of file WaveTrack.cpp.

3822{
3823 if (mClips.empty()) {
3824 return CreateClip(WaveTrackData::Get(*this).GetOrigin(), MakeNewClipName());
3825 }
3826 else
3827 return mClips.back().get();
3828}
wxString MakeNewClipName() const
Definition: WaveTrack.cpp:1116

References CreateClip(), BasicUI::Get(), MakeNewClipName(), and mClips.

Referenced by GetIdealBlockSize(), HandleXMLChild(), and HandleXMLEndTag().

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

◆ NIntervals()

size_t WaveTrack::NIntervals ( ) const
overridevirtual

used only during deserialization

Implements ChannelGroup.

Definition at line 1025 of file WaveTrack.cpp.

1026{
1027 return mClips.size();
1028}

References mClips.

Referenced by WaveformView::DoDraw(), and DoGetInterval().

Here is the caller graph for this function:

◆ Paste() [1/3]

virtual void Track::Paste ( double  t,
const Track src 
)
virtual

Weak precondition allows overrides to replicate one channel into many.

Precondition
IsLeader()
SameKindAs(src)
src.NChannels() == 1 || src.NChannels() == NChannels()

Implements Track.

◆ Paste() [2/3]

void Track::Paste ( double  t,
const TrackList src 
)

Non-virtual overload that passes the first track of a given list

Precondition
IsLeader()
SameKindAs(**src.begin()).NChannels()
NChannels == (**src.begin()).NChannels()

Definition at line 380 of file Track.cpp.

265{
266 Paste(t, **src.begin());
267}
iterator begin()
Definition: Track.h:1050
void Paste(double t0, const Track &src) override
Definition: WaveTrack.cpp:2436

◆ Paste() [3/3]

void WaveTrack::Paste ( double  t0,
const Track src 
)
overridevirtual
Exception safety guarantee:
Weak

Implements Track.

Definition at line 2436 of file WaveTrack.cpp.

2437{
2438 assert(IsLeader()); // pre of Track::Paste
2439 if (const auto other = dynamic_cast<const WaveTrack*>(&src))
2440 {
2441 // Currently `Paste` isn't used by code that wants the newer "don't merge
2442 // when copy/pasting" behaviour ...
2443 constexpr auto merge = true;
2444 PasteWaveTrack(t0, *other, merge);
2445 }
2446 else
2447 // THROW_INCONSISTENCY_EXCEPTION; // ?
2448 (void)0;// Empty if intentional.
2449}

References IsLeader(), and PasteWaveTrack().

Referenced by EffectStereoToMono::ProcessOne().

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

◆ PasteInto()

Track::Holder WaveTrack::PasteInto ( AudacityProject project,
TrackList list 
) const
overridevirtual

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

Precondition
IsLeader()
Parameters
listto which any newly created tracks are added; but left unchanged if an existing track is found in the project instead
Returns
A smart pointer to a leader track

Implements Track.

Definition at line 1004 of file WaveTrack.cpp.

1006{
1007 assert(IsLeader());
1008 auto &trackFactory = WaveTrackFactory::Get(project);
1009 auto &pSampleBlockFactory = trackFactory.GetSampleBlockFactory();
1010 Track::Holder pFirstTrack;
1011 const WaveTrack *pFirstChannel{};
1012 for (const auto pChannel : TrackList::Channels(this)) {
1013 auto pNewTrack = pChannel->EmptyCopy(pSampleBlockFactory);
1014 list.Add(pNewTrack);
1015 assert(pNewTrack->IsLeader() == pChannel->IsLeader());
1016 if (!pFirstTrack) {
1017 pFirstTrack = pNewTrack;
1018 pFirstChannel = pChannel;
1019 }
1020 }
1021 pFirstTrack->Paste(0.0, *pFirstChannel);
1022 return pFirstTrack;
1023}
std::shared_ptr< Track > Holder
Definition: Track.h:225
TrackKind * Add(const std::shared_ptr< TrackKind > &t)
Definition: Track.h:1201

References TrackList::Add(), TrackList::Channels(), EmptyCopy(), WaveTrackFactory::Get(), IsLeader(), and project.

Here is the call graph for this function:

◆ PasteOne()

void WaveTrack::PasteOne ( WaveTrack track,
double  t0,
const WaveTrack other,
double  startTime,
double  insertDuration,
bool  merge = true 
)
staticprivate

Definition at line 2174 of file WaveTrack.cpp.

2177{
2178 //
2179 // Pasting is a bit complicated, because with the existence of multiclip mode,
2180 // we must guess the behaviour the user wants.
2181 //
2182 // Currently, two modes are implemented:
2183 //
2184 // - If a single clip should be pasted, and it should be pasted inside another
2185 // clip, no NEW clips are generated. The audio is simply inserted.
2186 // This resembles the old (pre-multiclip support) behaviour. However, if
2187 // the clip is pasted outside of any clip, a NEW clip is generated. This is
2188 // the only behaviour which is different to what was done before, but it
2189 // shouldn't confuse users too much.
2190 //
2191 // - If multiple clips should be pasted, or a single clip that does not fill
2192 // the duration of the pasted track, these are always pasted as single
2193 // clips, and the current clip is split, when necessary. This may seem
2194 // strange at first, but it probably is better than trying to auto-merge
2195 // anything. The user can still merge the clips by hand (which should be a
2196 // simple command reachable by a hotkey or single mouse click).
2197 //
2198
2199 if (other.GetNumClips() == 0)
2200 return;
2201
2202 t0 = track.SnapToSample(t0);
2203
2204 //wxPrintf("paste: we have at least one clip\n");
2205
2206 const auto clipAtT0 = track.GetClipAtTime(t0);
2207 const auto otherFirstClip = other.GetLeftmostClip();
2208 const auto otherLastClip = other.GetRightmostClip();
2209 const auto pitchAndSpeedMatch =
2210 !clipAtT0 || (clipAtT0->HasEqualPitchAndSpeed(*otherFirstClip) &&
2211 clipAtT0->HasEqualPitchAndSpeed(*otherLastClip));
2212
2213 // `singleClipMode` will try to merge. Only allow this if clips on both ends
2214 // of the selection have equal stretch ratio.
2215 const bool singleClipMode =
2216 other.GetNumClips() == 1 &&
2217 std::abs(startTime) < track.LongSamplesToTime(1) * 0.5 &&
2218 pitchAndSpeedMatch && merge;
2219
2220 const auto rate = track.GetRate();
2221 if (insertDuration != 0 && insertDuration < 1.0 / rate)
2222 // PRL: I added this check to avoid violations of preconditions in other WaveClip and Sequence
2223 // methods, but allow the value 0 so I don't subvert the purpose of commit
2224 // 739422ba70ceb4be0bb1829b6feb0c5401de641e which causes append-recording always to make
2225 // a new clip.
2226 return;
2227
2228 //wxPrintf("Check if we need to make room for the pasted data\n");
2229
2230 auto pastingFromTempTrack = !other.GetOwner();
2231 bool editClipCanMove = GetEditClipsCanMove();
2232
2233 const SimpleMessageBoxException notEnoughSpaceException {
2235 XO("There is not enough room available to paste the selection"),
2236 XO("Warning"), "Error:_Insufficient_space_in_track"
2237 };
2238
2239 // Make room for the pasted data
2240 if (editClipCanMove) {
2241 if (!singleClipMode) {
2242 // We need to insert multiple clips, so split the current clip and ...
2243 track.SplitAt(t0);
2244 }
2245 //else if there is a clip at t0 insert new clip inside it and ...
2246
2247 // ... move everything to the right
2248 for (const auto& clip : track.mClips)
2249 if (clip->GetPlayStartTime() > t0 - (1.0 / rate))
2250 clip->ShiftBy(insertDuration);
2251 }
2252 else
2253 {
2254 if (!merge)
2255 track.SplitAt(t0);
2256 const auto clipAtT0 = track.GetClipAtTime(t0);
2257 const auto t = clipAtT0 ? clipAtT0->GetPlayEndTime() : t0;
2258 if (!track.IsEmpty(t, t + insertDuration))
2259 throw notEnoughSpaceException;
2260 }
2261
2262 // See if the clipboard data is one clip only and if it should be merged. If
2263 // edit-clip-can-move mode is checked, merging happens only if the pasting
2264 // point splits a clip. If it isn't, merging also happens when the pasting
2265 // point is at the exact beginning of a clip.
2266 if (singleClipMode && merge) {
2267 // Single clip mode
2268 // wxPrintf("paste: checking for single clip mode!\n");
2269
2270 WaveClip* insideClip = nullptr;
2271 for (const auto& clip : track.mClips) {
2272 if (editClipCanMove) {
2273 if (clip->SplitsPlayRegion(t0)) {
2274 //wxPrintf("t0=%.6f: inside clip is %.6f ... %.6f\n",
2275 // t0, clip->GetStartTime(), clip->GetEndTime());
2276 insideClip = clip.get();
2277 break;
2278 }
2279 }
2280 else {
2281 // If clips are immovable we also allow prepending to clips
2282 if (clip->WithinPlayRegion(t0))
2283 {
2284 insideClip = clip.get();
2285 break;
2286 }
2287 }
2288 }
2289
2290 if (insideClip) {
2291 // Exhibit traditional behaviour
2292 //wxPrintf("paste: traditional behaviour\n");
2293 if (!editClipCanMove) {
2294 // We did not move other clips out of the way already, so
2295 // check if we can paste without having to move other clips
2296 for (const auto& clip : track.mClips) {
2297 if (clip->GetPlayStartTime() > insideClip->GetPlayStartTime() &&
2298 insideClip->GetPlayEndTime() + insertDuration >
2299 clip->GetPlayStartTime())
2300 // Strong-guarantee in case of this path
2301 // not that it matters.
2302 throw notEnoughSpaceException;
2303 }
2304 }
2305 if (auto *pClip = other.GetClipByIndex(0)) {
2306 // This branch only gets executed in `singleClipMode` - we've
2307 // already made sure that stretch ratios are equal, satisfying
2308 // `WaveClip::Paste`'s precondition.
2309 bool success = insideClip->Paste(t0, *pClip);
2310 // TODO wide wave tracks -- prove success, or propagate failure,
2311 // or we might throw a MessageBoxException
2312 // (which would require a change in base class Track)
2313 // for now it would be quiet failure if clip widths mismatched
2314 // Can't yet assert(success);
2315 }
2316 return;
2317 }
2318 // Just fall through and exhibit NEW behaviour
2319 }
2320
2321 // Insert NEW clips
2322 //wxPrintf("paste: multi clip mode!\n");
2323
2324 if (!editClipCanMove &&
2325 !track.IsEmpty(t0, t0 + insertDuration - 1.0 / rate))
2326 // Strong-guarantee in case of this path
2327 // not that it matters.
2328 throw notEnoughSpaceException;
2329
2330 for (const auto& clip : other.mClips) {
2331 // AWD Oct. 2009: Don't actually paste in placeholder clips
2332 if (!clip->GetIsPlaceholder()) {
2333 auto newClip =
2334 std::make_shared<WaveClip>(*clip, track.mpFactory, true);
2335 newClip->Resample(rate);
2336 newClip->ShiftBy(t0);
2337 newClip->MarkChanged();
2338 if (pastingFromTempTrack)
2339 //Clips from the tracks which aren't bound to any TrackList are
2340 //considered to be new entities, thus named using "new" name template
2341 newClip->SetName(track.MakeNewClipName());
2342 else
2343 newClip->SetName(track.MakeClipCopyName(clip->GetName()));
2344 track.InsertClip(std::move(newClip)); // transfer ownership
2345 }
2346 }
2347}
void SplitAt(double t)
Definition: WaveTrack.cpp:4004
bool IsEmpty(double t0, double t1) const
Returns true if there are no WaveClips in the specified region.
Definition: WaveTrack.cpp:1281
const WaveClip * GetRightmostClip() const
Definition: WaveTrack.cpp:3045
const WaveClip * GetLeftmostClip() const
Definition: WaveTrack.cpp:3034
wxString MakeClipCopyName(const wxString &originalName) const
Definition: WaveTrack.cpp:1104
double LongSamplesToTime(sampleCount pos) const

References BadUserAction, GetClipAtTime(), GetClipByIndex(), GetEditClipsCanMove(), GetLeftmostClip(), GetNumClips(), Track::GetOwner(), WaveClip::GetPlayEndTime(), WaveClip::GetPlayStartTime(), GetRate(), GetRightmostClip(), InsertClip(), IsEmpty(), WideSampleSequence::LongSamplesToTime(), MakeClipCopyName(), MakeNewClipName(), mClips, mpFactory, WaveClip::Paste(), WideSampleSequence::SnapToSample(), SplitAt(), and XO().

Referenced by ClearAndPasteOne(), PasteWaveTrackAtSameTempo(), and SyncLockAdjust().

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

◆ PasteWaveTrack()

void WaveTrack::PasteWaveTrack ( double  t0,
const WaveTrack other,
bool  merge 
)
private

Definition at line 2143 of file WaveTrack.cpp.

2144{
2145 // Get a modifiable copy of `src` because it may come from another project
2146 // with different tempo, making boundary queries incorrect.
2147 const auto& tempo = GetProjectTempo();
2148 if (!tempo.has_value())
2150 WaveTrack* copy;
2151 const auto copyHolder = other.DuplicateWithOtherTempo(*tempo, copy);
2152 PasteWaveTrackAtSameTempo(t0, *copy, merge);
2153}
void PasteWaveTrackAtSameTempo(double t0, const WaveTrack &other, bool merge)
Definition: WaveTrack.cpp:2155

References staffpad::vo::copy(), DuplicateWithOtherTempo(), Track::GetProjectTempo(), PasteWaveTrackAtSameTempo(), and THROW_INCONSISTENCY_EXCEPTION.

Referenced by ClearAndPasteAtSameTempo(), and Paste().

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

◆ PasteWaveTrackAtSameTempo()

void WaveTrack::PasteWaveTrackAtSameTempo ( double  t0,
const WaveTrack other,
bool  merge 
)
private

Definition at line 2155 of file WaveTrack.cpp.

2157{
2158 assert(IsLeader());
2159 const auto otherNChannels = other.NChannels();
2160 assert(otherNChannels == 1 || otherNChannels == NChannels());
2161 assert(
2162 GetProjectTempo().has_value() &&
2163 GetProjectTempo() == other.GetProjectTempo());
2164 const auto startTime = other.GetStartTime();
2165 const auto endTime = other.GetEndTime();
2166 auto iter = TrackList::Channels(&other).begin();
2167 for (const auto pChannel : TrackList::Channels(this)) {
2168 PasteOne(*pChannel, t0, **iter, startTime, endTime, merge);
2169 if (otherNChannels > 1)
2170 ++iter;
2171 }
2172}

References TrackList::Channels(), GetEndTime(), Track::GetProjectTempo(), GetStartTime(), IsLeader(), NChannels(), and PasteOne().

Referenced by PasteWaveTrack().

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

◆ ProjectNyquistFrequency()

double WaveTrack::ProjectNyquistFrequency ( const AudacityProject project)
static

Definition at line 731 of file WaveTrack.cpp.

732{
734 return std::max(ProjectRate::Get(project).GetRate(),
735 tracks.Any<const WaveTrack>().max(&WaveTrack::GetRate))
736 / 2.0;
737}
static ProjectRate & Get(AudacityProject &project)
Definition: ProjectRate.cpp:28

References ProjectRate::Get(), TrackList::Get(), GetRate(), project, and tracks.

Referenced by SelectFrequenciesCommand::Apply().

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

◆ RateConsistencyCheck()

bool WaveTrack::RateConsistencyCheck ( ) const
private

Whether all clips of a leader track have a common rate.

Precondition
IsLeader()

Definition at line 2349 of file WaveTrack.cpp.

2350{
2351 assert(IsLeader());
2352
2353 // The channels and all clips in them should have the same sample rate.
2354 std::optional<double> oRate;
2355 auto channels = TrackList::Channels(this);
2356 return std::all_of(channels.begin(), channels.end(),
2357 [&](const WaveTrack *pTrack){
2358 if (!pTrack)
2359 return false;
2360
2361 const auto rate = pTrack->mLegacyRate;
2362 if (!oRate)
2363 oRate = rate;
2364 else if (*oRate != rate)
2365 return false;
2366 return true;
2367 });
2368}

References TrackList::Channels(), and IsLeader().

Referenced by LinkConsistencyFix().

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

◆ ReallyDoGetChannelGroup()

ChannelGroup & WaveTrack::ReallyDoGetChannelGroup ( ) const
overrideprivatevirtual

This is temporary! It defaults to call the above.

Reimplemented from Channel.

Definition at line 1077 of file WaveTrack.cpp.

1078{
1079 const Track *pTrack = this;
1080 if (const auto pOwner = GetHolder())
1081 pTrack = *pOwner->Find(this);
1082 const ChannelGroup &group = *pTrack;
1083 return const_cast<ChannelGroup&>(group);
1084}
Subclass * Find(const RegisteredFactory &key)
Get a (bare) pointer to an attachment, or null, down-cast it to Subclass *; will not create on demand...
Definition: ClientData.h:341
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:122
TrackList * GetHolder() const
Definition: Track.h:1480

References ClientData::Site< Host, ClientData, ObjectCopyingPolicy, Pointer, ObjectLockingPolicy, RegistryLockingPolicy >::Find(), and Track::GetHolder().

Here is the call graph for this function:

◆ Reinit()

void WaveTrack::Reinit ( const WaveTrack orig)

Overwrite data excluding the sample sequence but including display settings

Precondition
IsLeader()
orig.IsLeader()
NChannels() == orig.NChannels()

Definition at line 865 of file WaveTrack.cpp.

866{
867 assert(IsLeader());
868 assert(orig.IsLeader());
869 assert(NChannels() == orig.NChannels());
870 const auto channels = TrackList::Channels(this);
871 auto iter = TrackList::Channels(&orig).begin();
872 for (const auto pChannel : channels)
873 pChannel->Init(**iter++);
874}

References TrackList::Channels(), IsLeader(), and NChannels().

Referenced by ProjectAudioManager::DoRecord().

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

◆ RemoveAndReturnClip()

std::shared_ptr< WaveClip > WaveTrack::RemoveAndReturnClip ( WaveClip clip)

Definition at line 1922 of file WaveTrack.cpp.

1923{
1924 // Be clear about who owns the clip!!
1925 auto it = FindClip(mClips, clip);
1926 if (it != mClips.end()) {
1927 auto result = std::move(*it); // Array stops owning the clip, before we shrink it
1928 mClips.erase(it);
1929 return result;
1930 }
1931 else
1932 return {};
1933}

References anonymous_namespace{WaveTrack.cpp}::FindClip(), and mClips.

Referenced by ReverseOne().

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

◆ RemoveCutLine()

bool WaveTrack::RemoveCutLine ( double  cutLinePosition)

Remove cut line, without expanding the audio in it.

Definition at line 4090 of file WaveTrack.cpp.

4091{
4092 assert(IsLeader());
4093
4094 bool removed = false;
4095 for (const auto pChannel : TrackList::Channels(this))
4096 for (const auto &clip : pChannel->mClips)
4097 if (clip->RemoveCutLine(cutLinePosition)) {
4098 removed = true;
4099 break;
4100 }
4101
4102 return removed;
4103}

References TrackList::Channels(), and IsLeader().

Here is the call graph for this function:

◆ RemoveInterval()

void WaveTrack::RemoveInterval ( const IntervalHolder interval)
private
Precondition
IsLeader()

Definition at line 4170 of file WaveTrack.cpp.

4171{
4172 assert(IsLeader());
4173 auto channel = 0;
4174 for (const auto pChannel : TrackList::Channels(this))
4175 {
4176 const auto clip = interval->GetClip(channel);
4177 if (clip)
4178 pChannel->RemoveAndReturnClip(clip.get());
4179 ++channel;
4180 }
4181}

References TrackList::Channels(), and IsLeader().

Referenced by ReplaceInterval().

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

◆ ReplaceInterval()

void WaveTrack::ReplaceInterval ( const IntervalHolder oldOne,
const IntervalHolder newOne 
)
private
Precondition
IsLeader()
oldOne->NChannels() == newOne->NChannels()

Definition at line 4183 of file WaveTrack.cpp.

4185{
4186 assert(IsLeader());
4187 assert(oldOne->NChannels() == newOne->NChannels());
4188 RemoveInterval(oldOne);
4189 InsertInterval(newOne);
4190 newOne->SetName(oldOne->GetName());
4191}
void InsertInterval(const IntervalHolder &interval)
Definition: WaveTrack.cpp:4158
void RemoveInterval(const IntervalHolder &interval)
Definition: WaveTrack.cpp:4170

References InsertInterval(), IsLeader(), and RemoveInterval().

Referenced by ApplyPitchAndSpeedOnIntervals().

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

◆ Resample()

void WaveTrack::Resample ( int  rate,
BasicUI::ProgressDialog progress = NULL 
)
Exception safety guarantee:
Weak – Partial completion may leave clips at differing sample rates!

Definition at line 4195 of file WaveTrack.cpp.

4196{
4197 for (const auto pChannel : TrackList::Channels(this)) {
4198 for (const auto &clip : pChannel->mClips)
4199 clip->Resample(rate, progress);
4200 }
4201 DoSetRate(rate);
4202}

References TrackList::Channels(), and DoSetRate().

Here is the call graph for this function:

◆ Reverse()

bool WaveTrack::Reverse ( sampleCount  start,
sampleCount  len,
const ProgressReport report = {} 
)

Definition at line 4204 of file WaveTrack.cpp.

4206{
4207 size_t count = 0;
4208 const auto range = TrackList::Channels(this);
4209 const auto myProgress = [&](double fraction){
4210 return progress((count + fraction) / range.size());
4211 };
4212 for (const auto pChannel : range) {
4213 if (!ReverseOne(*pChannel, start, len, myProgress))
4214 return false;
4215 ++count;
4216 }
4217 return true;
4218}
static bool ReverseOne(WaveTrack &track, sampleCount start, sampleCount len, const ProgressReport &report={})
Definition: WaveTrack.cpp:4220

References TrackList::Channels(), and ReverseOne().

Referenced by EffectReverse::Process().

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

◆ ReverseOne()

bool WaveTrack::ReverseOne ( WaveTrack track,
sampleCount  start,
sampleCount  len,
const ProgressReport report = {} 
)
staticprivate

Definition at line 4220 of file WaveTrack.cpp.

4223{
4224 bool rValue = true; // return value
4225
4226 // start, end, len refer to the selected reverse region
4227 auto end = start + len;
4228
4229 // STEP 1:
4230 // If a reverse selection begins and/or ends at the inside of a clip
4231 // perform a split at the start and/or end of the reverse selection
4232 const auto &clips = track.GetClips();
4233 // Beware, the array grows as we loop over it. Use integer subscripts, not
4234 // iterators.
4235 for (size_t ii = 0; ii < clips.size(); ++ii) {
4236 const auto &clip = clips[ii].get();
4237 auto clipStart = clip->GetPlayStartSample();
4238 auto clipEnd = clip->GetPlayEndSample();
4239 if (clipStart < start && clipEnd > start && clipEnd <= end) {
4240 // the reverse selection begins at the inside of a clip
4241 double splitTime = track.LongSamplesToTime(start);
4242 track.SplitAt(splitTime);
4243 }
4244 else if (clipStart >= start && clipStart < end && clipEnd > end) {
4245 // the reverse selection ends at the inside of a clip
4246 double splitTime = track.LongSamplesToTime(end);
4247 track.SplitAt(splitTime);
4248 }
4249 else if (clipStart < start && clipEnd > end) {
4250 // the selection begins AND ends at the inside of a clip
4251 double splitTime = track.LongSamplesToTime(start);
4252 track.SplitAt(splitTime);
4253 splitTime = track.LongSamplesToTime(end);
4254 track.SplitAt(splitTime);
4255 }
4256 }
4257
4258 //STEP 2:
4259 // Individually reverse each clip inside the selected region
4260 // and apply the appropriate offset after detaching them from the track
4261
4262 bool checkedFirstClip = false;
4263
4264 // used in calculating the offset of clips to rearrange
4265 // holds the new end position of the current clip
4266 auto currentEnd = end;
4267
4268 // holds the reversed clips
4269 WaveClipHolders revClips;
4270 // holds the clips that appear after the reverse selection region
4271 WaveClipHolders otherClips;
4272 auto clipArray = track.SortedClipArray();
4273 for (size_t i = 0; i < clipArray.size(); ++i) {
4274 WaveClip *clip = clipArray[i];
4275 auto clipStart = clip->GetPlayStartSample();
4276 auto clipEnd = clip->GetPlayEndSample();
4277
4278 if (clipStart >= start && clipEnd <= end) {
4279 // if the clip is inside the selected region
4280 // this is used to check if the selected region begins with a
4281 // whitespace. If yes then clipStart (of the first clip) and start are
4282 // not the same. Adjust currentEnd accordingly and set endMerge to
4283 // false
4284 if (!checkedFirstClip && clipStart > start) {
4285 checkedFirstClip = true;
4286 if (i > 0) {
4287 if (clipArray[i - 1]->GetPlayEndSample() <= start)
4288 currentEnd -= (clipStart - start);
4289 }
4290 else
4291 currentEnd -= (clipStart - start);
4292 }
4293
4294 auto revStart = std::max(clipStart, start);
4295 auto revEnd = std::min(end, clipEnd);
4296 auto revLen = revEnd - revStart;
4297 if (revEnd >= revStart) {
4298 // reverse the clip
4299 if (!ReverseOneClip(track, revStart, revLen, start, end, progress))
4300 {
4301 rValue = false;
4302 break;
4303 }
4304
4305 // calculate the offset required
4306 auto clipOffsetStart = currentEnd - (clipEnd - clipStart);
4307 double offsetStartTime = track.LongSamplesToTime(clipOffsetStart);
4308 if (i + 1 < clipArray.size()) {
4309 // update currentEnd if there is a clip to process next
4310 auto nextClipStart = clipArray[i + 1]->GetPlayStartSample();
4311 currentEnd = currentEnd -
4312 (clipEnd - clipStart) - (nextClipStart - clipEnd);
4313 }
4314
4315 // detach the clip from track
4316 revClips.push_back(track.RemoveAndReturnClip(clip));
4317 // align time to a sample and set offset
4318 revClips.back()->SetPlayStartTime(
4319 track.SnapToSample(offsetStartTime));
4320 }
4321 }
4322 else if (clipStart >= end) {
4323 // clip is after the selection region
4324 // simply remove and append to otherClips
4325 otherClips.push_back(track.RemoveAndReturnClip(clip));
4326 }
4327 }
4328
4329 // STEP 3: Append the clips from
4330 // revClips and otherClips back to the track
4331 // the last clip of revClips is appended to the track first
4332 // PRL: I don't think that matters, the sequence of storage of clips in the
4333 // track is not elsewhere assumed to be by time
4334 for (auto it = revClips.rbegin(), revEnd = revClips.rend();
4335 rValue && it != revEnd; ++it)
4336 rValue = track.AddClip(*it);
4337
4338 if (!rValue)
4339 return false;
4340
4341 for (auto &clip : otherClips)
4342 if (!(rValue = track.AddClip(clip)))
4343 break;
4344
4345 return rValue;
4346}
sampleCount GetPlayEndSample() const
Real end time of the clip, quantized to raw sample rate (track's rate)
Definition: WaveClip.cpp:1342
sampleCount GetPlayStartSample() const
Real start time of the clip, quantized to raw sample rate (track's rate)
Definition: WaveClip.cpp:1337
std::shared_ptr< WaveClip > RemoveAndReturnClip(WaveClip *clip)
Definition: WaveTrack.cpp:1922
static bool ReverseOneClip(WaveTrack &track, sampleCount start, sampleCount len, sampleCount originalStart, sampleCount originalEnd, const ProgressReport &report={})
Definition: WaveTrack.cpp:4348

References AddClip(), PackedArray::end(), GetClips(), WaveClip::GetPlayEndSample(), WaveClip::GetPlayStartSample(), WideSampleSequence::LongSamplesToTime(), min(), RemoveAndReturnClip(), ReverseOneClip(), WideSampleSequence::SnapToSample(), SortedClipArray(), and SplitAt().

Referenced by Reverse().

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

◆ ReverseOneClip()

bool WaveTrack::ReverseOneClip ( WaveTrack track,
sampleCount  start,
sampleCount  len,
sampleCount  originalStart,
sampleCount  originalEnd,
const ProgressReport report = {} 
)
staticprivate

Definition at line 4348 of file WaveTrack.cpp.

4352{
4353 bool rc = true;
4354 // keep track of two blocks whose data we will swap
4355 auto first = start;
4356
4357 auto blockSize = track.GetMaxBlockSize();
4358 Floats buffer1{ blockSize };
4359 const auto pBuffer1 = buffer1.get();
4360 Floats buffer2{ blockSize };
4361 const auto pBuffer2 = buffer2.get();
4362
4363 auto originalLen = originalEnd - originalStart;
4364
4365 while (len > 1) {
4366 auto block =
4367 limitSampleBufferSize(track.GetBestBlockSize(first), len / 2);
4368 auto second = first + (len - block);
4369
4370 track.GetFloats(buffer1.get(), first, block);
4371 std::reverse(pBuffer1, pBuffer1 + block);
4372 track.GetFloats(buffer2.get(), second, block);
4373 std::reverse(pBuffer2, pBuffer2 + block);
4374 // Don't dither on later rendering if only reversing samples
4375 const bool success =
4376 track.Set((samplePtr)buffer2.get(), floatSample, first, block,
4378 &&
4379 track.Set((samplePtr)buffer1.get(), floatSample, second, block,
4381 if (!success)
4382 return false;
4383
4384 len -= 2 * block;
4385 first += block;
4386
4387 if (!report(
4388 2 * (first - originalStart).as_double() / originalLen.as_double()
4389 )) {
4390 rc = false;
4391 break;
4392 }
4393 }
4394
4395 return rc;
4396}
@ narrowestSampleFormat
Two synonyms for previous values that might change if more values were added.
bool Set(constSamplePtr buffer, sampleFormat format, sampleCount start, size_t len, sampleFormat effectiveFormat=widestSampleFormat)
Random-access assignment of a range of samples.
Definition: WaveTrack.cpp:3547
size_t GetBestBlockSize(sampleCount t) const
Definition: WaveTrack.cpp:2721

References floatSample, GetBestBlockSize(), GetFloats(), GetMaxBlockSize(), limitSampleBufferSize(), narrowestSampleFormat, and WaveChannel::Set().

Referenced by ReverseOne().

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

◆ RightmostOrNewClip()

WaveClip * WaveTrack::RightmostOrNewClip ( )

Get access to the last (rightmost) clip, or create a clip, if there is not already one.

Returns
a pointer to a WaveClip at the end of the track
Exception safety guarantee:
No-fail

Definition at line 3831 of file WaveTrack.cpp.

3832{
3833 if (mClips.empty()) {
3834 return CreateClip(WaveTrackData::Get(*this).GetOrigin(), MakeNewClipName());
3835 }
3836 else
3837 {
3838 auto it = mClips.begin();
3839 WaveClip *rightmost = (*it++).get();
3840 double maxOffset = rightmost->GetPlayStartTime();
3841 for (auto end = mClips.end(); it != end; ++it)
3842 {
3843 WaveClip *clip = it->get();
3844 double offset = clip->GetPlayStartTime();
3845 if (maxOffset < offset)
3846 maxOffset = offset, rightmost = clip;
3847 }
3848 return rightmost;
3849 }
3850}

References CreateClip(), PackedArray::end(), BasicUI::Get(), WaveClip::GetPlayStartTime(), MakeNewClipName(), and mClips.

Referenced by AUPImportFileHandle::AddSamples(), FlushOne(), and AUPImportFileHandle::HandleEnvelope().

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

◆ SetClipRates()

void WaveTrack::SetClipRates ( double  newRate)
private

Definition at line 1149 of file WaveTrack.cpp.

1150{
1151 for (const auto &clip : mClips)
1152 clip->SetRate(static_cast<int>(newRate));
1153}

References mClips.

◆ SetFloatAtTime()

void WaveTrack::SetFloatAtTime ( double  t,
size_t  iChannel,
float  value,
sampleFormat  effectiveFormat 
)

Sets sample nearest to t to value. Silently fails if GetClipAtTime(t) == nullptr.

Definition at line 3357 of file WaveTrack.cpp.

3359{
3360 SetFloatsCenteredAroundTime(t, iChannel, &value, 0u, effectiveFormat);
3361}
void SetFloatsCenteredAroundTime(double t, size_t iChannel, const float *buffer, size_t numSideSamples, sampleFormat effectiveFormat)
Similar to GetFloatsCenteredAroundTime, but for writing. Sets as many samples as it can according to ...
Definition: WaveTrack.cpp:3320

References anonymous_namespace{StretchingSequenceIntegrationTest.cpp}::iChannel, and SetFloatsCenteredAroundTime().

Here is the call graph for this function:

◆ SetFloatsCenteredAroundTime()

void WaveTrack::SetFloatsCenteredAroundTime ( double  t,
size_t  iChannel,
const float *  buffer,
size_t  numSideSamples,
sampleFormat  effectiveFormat 
)

Similar to GetFloatsCenteredAroundTime, but for writing. Sets as many samples as it can according to the same rules as GetFloatsCenteredAroundTime. Leaves the other samples untouched.

See also
GetFloatsCenteredAroundTime

Definition at line 3320 of file WaveTrack.cpp.

3323{
3325 t, iChannel, buffer, numSideSamples, effectiveFormat,
3328 t, iChannel, buffer + numSideSamples, numSideSamples + 1, effectiveFormat,
3330}
void SetFloatsFromTime(double t, size_t iChannel, const float *buffer, size_t numSamples, sampleFormat effectiveFormat, PlaybackDirection direction)
Similar to GetFloatsFromTime, but for writing. Sets as many samples as it can according to the same r...
Definition: WaveTrack.cpp:3332

References backward, forward, anonymous_namespace{StretchingSequenceIntegrationTest.cpp}::iChannel, and SetFloatsFromTime().

Referenced by SetFloatAtTime().

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

◆ SetFloatsFromTime()

void WaveTrack::SetFloatsFromTime ( double  t,
size_t  iChannel,
const float *  buffer,
size_t  numSamples,
sampleFormat  effectiveFormat,
PlaybackDirection  direction 
)
private

Similar to GetFloatsFromTime, but for writing. Sets as many samples as it can according to the same rules as GetFloatsFromTime. Leaves the other samples untouched.

See also
GetFloatsFromTime

Definition at line 3332 of file WaveTrack.cpp.

3335{
3336 RoundToNearestClipSample(*this, t);
3337 auto clip = GetClipAtTime(t);
3338 auto numSamplesWritten = 0u;
3339 const auto forward = direction == PlaybackDirection::forward;
3340 while (clip)
3341 {
3342 const auto args = GetSampleAccessArgs(
3343 *clip, t, buffer, numSamples, numSamplesWritten, forward);
3344 if (args.len > 0u)
3345 {
3346 clip->SetSamples(
3347 iChannel, args.offsetBuffer, floatSample, args.start, args.len,
3348 effectiveFormat);
3349 numSamplesWritten += args.len;
3350 if (numSamplesWritten >= numSamples)
3351 break;
3352 }
3353 clip = GetAdjacentClip(*clip, direction);
3354 }
3355}

References floatSample, forward, GetAdjacentClip(), GetClipAtTime(), anonymous_namespace{WaveTrack.cpp}::GetSampleAccessArgs(), anonymous_namespace{StretchingSequenceIntegrationTest.cpp}::iChannel, and anonymous_namespace{WaveTrack.cpp}::RoundToNearestClipSample().

Referenced by SetFloatsCenteredAroundTime().

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

◆ SetFloatsWithinTimeRange()

void WaveTrack::SetFloatsWithinTimeRange ( double  t0,
double  t1,
size_t  iChannel,
const std::function< float(double sampleTime)> &  producer,
sampleFormat  effectiveFormat 
)

Provides a means of setting clip values as a function of time. Included are closest sample to t0 up to closest sample to t1, exclusively. If the given interval is empty, i.e., t0 >= t1, no action is taken.

Parameters
producera function taking sample (absolute, not clip-relative) time and returning the desired value for the sample at that time.

Definition at line 3363 of file WaveTrack.cpp.

3367{
3368 if (t0 >= t1)
3369 return;
3370 const auto sortedClips = SortedClipArray();
3371 if (sortedClips.empty())
3372 return;
3373 t0 = std::max(t0, (*sortedClips.begin())->GetPlayStartTime());
3374 t1 = std::min(t1, (*sortedClips.rbegin())->GetPlayEndTime());
3375 auto clip = GetClipAtTime(t0);
3376 while (clip) {
3377 const auto clipStartTime = clip->GetPlayStartTime();
3378 const auto clipEndTime = clip->GetPlayEndTime();
3379 const auto sampsPerSec = clip->GetRate() / clip->GetStretchRatio();
3380 const auto roundedT0 =
3381 std::round((t0 - clipStartTime) * sampsPerSec) / sampsPerSec +
3382 clipStartTime;
3383 const auto roundedT1 =
3384 std::round((t1 - clipStartTime) * sampsPerSec) / sampsPerSec +
3385 clipStartTime;
3386 if (clipStartTime > roundedT1)
3387 break;
3388 const auto tt0 = std::max(clipStartTime, roundedT0);
3389 const auto tt1 = std::min(clipEndTime, roundedT1);
3390 const size_t numSamples = (tt1 - tt0) * sampsPerSec + .5;
3391 std::vector<float> values(numSamples);
3392 for (auto i = 0u; i < numSamples; ++i)
3393 values[i] = producer(tt0 + clip->SamplesToTime(i));
3394 clip->SetFloatsFromTime(
3395 tt0 - clipStartTime, iChannel, values.data(), numSamples,
3396 effectiveFormat);
3398 }
3399}
const wxChar * values
fastfloat_really_inline void round(adjusted_mantissa &am, callback cb) noexcept
Definition: fast_float.h:2512

References forward, GetClipAtTime(), GetNextClip(), anonymous_namespace{StretchingSequenceIntegrationTest.cpp}::iChannel, min(), fast_float::round(), SortedClipArray(), and values.

Here is the call graph for this function:

◆ SetGain()

void WaveTrack::SetGain ( float  newGain)

Definition at line 1165 of file WaveTrack.cpp.

1166{
1167 if (GetGain() != newGain) {
1168 DoSetGain(newGain);
1169 Notify(true);
1170 }
1171}
void Notify(bool allChannels, int code=-1)
Definition: Track.cpp:257

References DoSetGain(), GetGain(), and Track::Notify().

Referenced by MixerTrackCluster::HandleSliderGain(), and anonymous_namespace{TrackMenus.cpp}::SetTrackGain().

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

◆ SetLegacyFormat()

void WaveTrack::SetLegacyFormat ( sampleFormat  format)

Definition at line 2783 of file WaveTrack.cpp.

2784{
2786}

References anonymous_namespace{ExportPCM.cpp}::format, and mLegacyFormat.

Referenced by AUPImportFileHandle::HandleXMLEndTag(), and HandleXMLTag().

Here is the caller graph for this function:

◆ SetPan()

void WaveTrack::SetPan ( float  newPan)

Definition at line 1183 of file WaveTrack.cpp.

1184{
1185 if (newPan > 1.0)
1186 newPan = 1.0;
1187 else if (newPan < -1.0)
1188 newPan = -1.0;
1189
1190 if ( GetPan() != newPan ) {
1191 DoSetPan(newPan);
1192 Notify(true);
1193 }
1194}

References DoSetPan(), GetPan(), and Track::Notify().

Referenced by MixerTrackCluster::HandleSliderPan(), MixAndRender(), WaveTrackMenuTable::OnMergeStereo(), and anonymous_namespace{TrackMenus.cpp}::SetTrackPan().

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

◆ SetRate()

void WaveTrack::SetRate ( double  newRate)

!brief Sets the new rate for the track without resampling it pre newRate > 0

Definition at line 1133 of file WaveTrack.cpp.

1134{
1135 assert( newRate > 0 );
1136 newRate = std::max( 1.0, newRate );
1137 DoSetRate(newRate);
1138
1139 for(const auto& channel : Channels())
1140 channel->GetTrack().SetClipRates(newRate);
1141}

References Channels(), and DoSetRate().

Referenced by LinkConsistencyFix(), and RateMenuTable::SetRate().

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

◆ SetWaveColorIndex()

void WaveTrack::SetWaveColorIndex ( int  colorIndex)
Precondition
IsLeader()
Exception safety guarantee:
Strong

Definition at line 1220 of file WaveTrack.cpp.

1221{
1222 assert(IsLeader());
1223 for (const auto pChannel : TrackList::Channels(this)) {
1224 for (const auto &clip : pChannel->mClips)
1225 clip->SetColourIndex(colorIndex);
1226 }
1227 WaveTrackData::Get(*this).SetWaveColorIndex(colorIndex);
1228}

References TrackList::Channels(), BasicUI::Get(), and IsLeader().

Referenced by SetTrackVisualsCommand::ApplyInner().

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

◆ Silence()

void WaveTrack::Silence ( double  t0,
double  t1,
ProgressReporter  reportProgress 
)
overridevirtual
Precondition
IsLeader()

Implements Track.

Definition at line 2451 of file WaveTrack.cpp.

2452{
2453 assert(IsLeader());
2454 if (t1 < t0)
2456
2457 ApplyPitchAndSpeed({ { t0, t1 } }, std::move(reportProgress));
2458
2459 auto start = TimeToLongSamples(t0);
2460 auto end = TimeToLongSamples(t1);
2461
2462 for (const auto pChannel : TrackList::Channels(this)) {
2463 for (const auto &clip : pChannel->mClips) {
2464 auto clipStart = clip->GetPlayStartSample();
2465 auto clipEnd = clip->GetPlayEndSample();
2466 if (clipEnd > start && clipStart < end) {
2467 auto offset = std::max(start - clipStart, sampleCount(0));
2468 // Clip sample region and Get/Put sample region overlap
2469 auto length = std::min(end, clipEnd) - (clipStart + offset);
2470 clip->SetSilence(offset, length);
2471 }
2472 }
2473 }
2474}
void ApplyPitchAndSpeed(std::optional< TimeInterval > interval, ProgressReporter reportProgress)
Definition: WaveTrack.cpp:2394

References ApplyPitchAndSpeed(), TrackList::Channels(), PackedArray::end(), IsLeader(), min(), THROW_INCONSISTENCY_EXCEPTION, and WideSampleSequence::TimeToLongSamples().

Referenced by anonymous_namespace{LabelMenus.cpp}::OnSilenceLabels(), anonymous_namespace{EditMenus.cpp}::OnSplitCut(), and anonymous_namespace{LabelMenus.cpp}::OnSplitDeleteLabels().

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

◆ SortedClipArray() [1/2]

WaveClipPointers WaveTrack::SortedClipArray ( )

◆ SortedClipArray() [2/2]

WaveClipConstPointers WaveTrack::SortedClipArray ( ) const

Definition at line 4417 of file WaveTrack.cpp.

4418{
4419 return FillSortedClipArray<WaveClipConstPointers>(mClips);
4420}

References mClips.

◆ Split()

void WaveTrack::Split ( double  t0,
double  t1 
)
Precondition
IsLeader()
Exception safety guarantee:
Weak

Definition at line 3993 of file WaveTrack.cpp.

3994{
3995 assert(IsLeader());
3996 for (const auto pChannel : TrackList::Channels(this)) {
3997 pChannel->SplitAt(t0);
3998 if (t0 != t1)
3999 pChannel->SplitAt(t1);
4000 }
4001}

References TrackList::Channels(), and IsLeader().

Referenced by ApplyPitchAndSpeed(), and anonymous_namespace{LabelMenus.cpp}::OnSplitLabels().

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

◆ SplitAt()

void WaveTrack::SplitAt ( double  t)
private
Exception safety guarantee:
Weak

Definition at line 4004 of file WaveTrack.cpp.

4005{
4006 for (const auto &c : mClips)
4007 {
4008 if (c->SplitsPlayRegion(t))
4009 {
4010 t = SnapToSample(t);
4011 auto newClip = std::make_shared<WaveClip>(*c, mpFactory, true);
4012 c->TrimRightTo(t);// put t on a sample
4013 newClip->TrimLeftTo(t);
4014
4015 // This could invalidate the iterators for the loop! But we return
4016 // at once so it's okay
4017 InsertClip(std::move(newClip)); // transfer ownership
4018 return;
4019 }
4020 }
4021}

References InsertClip(), mClips, mpFactory, and WideSampleSequence::SnapToSample().

Referenced by PasteOne(), and ReverseOne().

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

◆ SplitCut()

TrackListHolder WaveTrack::SplitCut ( double  t0,
double  t1 
)
Precondition
IsLeader()
Postcondition
result: result->NChannels() == NChannels()
Exception safety guarantee:
Strong

Definition at line 1315 of file WaveTrack.cpp.

1316{
1317 assert(IsLeader());
1318 if (t1 < t0)
1320
1321 // SplitCut is the same as 'Copy', then 'SplitDelete'
1322 auto result = Copy(t0, t1);
1323 SplitDelete(t0, t1);
1324 return result;
1325}

References Copy(), IsLeader(), SplitDelete(), and THROW_INCONSISTENCY_EXCEPTION.

Referenced by anonymous_namespace{EditMenus.cpp}::OnSplitCut(), and anonymous_namespace{LabelMenus.cpp}::OnSplitCutLabels().

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

◆ SplitDelete()

void WaveTrack::SplitDelete ( double  t0,
double  t1 
)
Precondition
IsLeader()
Exception safety guarantee:
Strong

Definition at line 1878 of file WaveTrack.cpp.

1879{
1880 assert(IsLeader());
1881 bool addCutLines = false;
1882 bool split = true;
1883 for (const auto pChannel : TrackList::Channels(this))
1884 pChannel->HandleClear(t0, t1, addCutLines, split);
1885}

References TrackList::Channels(), and IsLeader().

Referenced by Disjoin(), EffectSBSMS::Finalize(), anonymous_namespace{EditMenus.cpp}::OnSplitDelete(), anonymous_namespace{LabelMenus.cpp}::OnSplitDeleteLabels(), anonymous_namespace{EditMenus.cpp}::OnSplitNew(), SplitCut(), and Trim().

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

◆ SyncLockAdjust()

void WaveTrack::SyncLockAdjust ( double  oldT1,
double  newT1 
)
overridevirtual

This can be used to adjust a sync-lock selected track when the selection is replaced by one of a different length.

Precondition
IsLeader()

Reimplemented from Track.

Definition at line 2096 of file WaveTrack.cpp.

2097{
2098 assert(IsLeader());
2099 const auto endTime = GetEndTime();
2100 if (newT1 > oldT1 &&
2101 // JKC: This is a rare case where using >= rather than > on a float matters.
2102 // GetEndTime() looks through the clips and may give us EXACTLY the same
2103 // value as T1, when T1 was set to be at the end of one of those clips.
2104 oldT1 >= endTime)
2105 return;
2106 const auto channels = TrackList::Channels(this);
2107 if (newT1 > oldT1) {
2108 // Insert space within the track
2109
2110 // If track is empty at oldT1 insert whitespace; otherwise, silence
2111 if (IsEmpty(oldT1, oldT1)) {
2112 // Check if clips can move
2113 if (EditClipsCanMove.Read()) {
2114 const auto offset = newT1 - oldT1;
2115 const auto rate = GetRate();
2116 for (const auto pChannel : channels)
2117 for (const auto& clip : pChannel->mClips)
2118 if (clip->GetPlayStartTime() > oldT1 - (1.0 / rate))
2119 clip->ShiftBy(offset);
2120 }
2121 return;
2122 }
2123 else {
2124 // AWD: Could just use InsertSilence() on its own here, but it doesn't
2125 // follow EditClipCanMove rules (Paste() does it right)
2126 const auto duration = newT1 - oldT1;
2127 for (const auto pChannel : channels) {
2128 auto tmp = std::make_shared<WaveTrack>(
2130 // tmpList exists only to fix assertion crashes in usage of tmp
2131 auto tmpList = TrackList::Temporary(nullptr, tmp, nullptr);
2132 assert(tmp->IsLeader()); // It is not yet owned by a TrackList
2133 tmp->InsertSilence(0.0, duration);
2134 tmp->FlushOne();
2135 PasteOne(*pChannel, oldT1, *tmp, 0.0, duration);
2136 }
2137 }
2138 }
2139 else if (newT1 < oldT1)
2140 Clear(newT1, oldT1);
2141}
BoolSetting EditClipsCanMove
Definition: WaveTrack.cpp:4587
bool Read(T *pVar) const
overload of Read returning a boolean that is true if the value was previously defined *‍/
Definition: Prefs.h:207

References TrackList::Channels(), Clear(), EditClipsCanMove, GetEndTime(), GetRate(), GetSampleFormat(), IsEmpty(), IsLeader(), mpFactory, PasteOne(), Setting< T >::Read(), and TrackList::Temporary().

Here is the call graph for this function:

◆ Trim()

void WaveTrack::Trim ( double  t0,
double  t1 
)
Precondition
IsLeader()
Exception safety guarantee:
Weak

Definition at line 1330 of file WaveTrack.cpp.

1331{
1332 assert(IsLeader());
1333 bool inside0 = false;
1334 bool inside1 = false;
1335
1336 const auto range = TrackList::Channels(this);
1337 for (auto pChannel : range) {
1338 for (const auto &clip : pChannel->mClips) {
1339 if (t1 > clip->GetPlayStartTime() && t1 < clip->GetPlayEndTime()) {
1340 clip->SetTrimRight(
1341 clip->GetTrimRight() + clip->GetPlayEndTime() - t1);
1342 inside1 = true;
1343 }
1344
1345 if (t0 > clip->GetPlayStartTime() && t0 < clip->GetPlayEndTime()) {
1346 clip->SetTrimLeft(
1347 clip->GetTrimLeft() + t0 - clip->GetPlayStartTime());
1348 inside0 = true;
1349 }
1350 }
1351 }
1352
1353 //if inside0 is false, then the left selector was between
1354 //clips, so DELETE everything to its left.
1355 if (const auto endTime = GetEndTime()
1356 ; !inside1 && t1 < endTime
1357 )
1358 Clear(t1, endTime);
1359
1360 if (const auto startTime = GetStartTime()
1361 ; !inside0 && t0 > startTime
1362 )
1363 SplitDelete(startTime, t0);
1364}

References TrackList::Channels(), Clear(), GetEndTime(), GetStartTime(), IsLeader(), and SplitDelete().

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

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

◆ WideEmptyCopy()

TrackListHolder WaveTrack::WideEmptyCopy ( const SampleBlockFactoryPtr pFactory = {},
bool  keepLink = true 
) const

Make another channel group copying format, rate, color, etc. but containing no clips; with as many channels as in this

It is important to pass the correct factory (that for the project which will own the copy) in the unusual case that a track is copied from another project or the clipboard. For copies within one project, the default will do.

Parameters
keepLinkif false, make the new track mono. But always preserve any other track group data.
Precondition
IsLeader()

Definition at line 1385 of file WaveTrack.cpp.

1387{
1388 assert(IsLeader());
1389 auto result = TrackList::Temporary(nullptr);
1390 for (const auto pChannel : TrackList::Channels(this)) {
1391 const auto pNewTrack =
1392 result->Add(pChannel->EmptyCopy(pFactory, keepLink));
1393 assert(!keepLink || pNewTrack->IsLeader() == pChannel->IsLeader());
1394 }
1395 return result;
1396}

References TrackList::Channels(), IsLeader(), and TrackList::Temporary().

Here is the call graph for this function:

◆ WidestEffectiveFormat()

sampleFormat WaveTrack::WidestEffectiveFormat ( ) const
overridevirtual
Returns
widest effective SampleFormat in any part of the track

Implements WideSampleSequence.

Definition at line 3592 of file WaveTrack.cpp.

3593{
3594 auto result = narrowestSampleFormat;
3595 const auto accumulate = [&](const WaveTrack &track) {
3596 for (const auto &pClip : track.GetClips())
3597 for (size_t ii = 0, width = pClip->GetWidth(); ii < width; ++ii)
3598 result = std::max(result,
3599 pClip->GetSequence(ii)->GetSampleFormats().Effective());
3600 };
3601 if (auto pOwner = GetOwner()) {
3602 for (auto channel : TrackList::Channels(this))
3603 accumulate(*channel);
3604 }
3605 else
3606 accumulate(*this);
3607 return result;
3608}

References TrackList::Channels(), Track::GetOwner(), and narrowestSampleFormat.

Here is the call graph for this function:

◆ WriteOneXML()

void WaveTrack::WriteOneXML ( const WaveTrack track,
XMLWriter xmlFile,
size_t  iChannel,
size_t  nChannels 
)
staticprivate

Definition at line 2968 of file WaveTrack.cpp.

2971{
2972 xmlFile.StartTag(wxT("wavetrack"));
2973 track.Track::WriteCommonXMLAttributes(xmlFile);
2974
2975 // Write the "channel" attribute so earlier versions can interpret stereo
2976 // tracks, but this version doesn't read it
2977 {
2978 enum ChannelType {
2979 LeftChannel = 0,
2980 RightChannel = 1,
2981 MonoChannel = 2
2982 };
2983 const auto channelType = (nChannels == 0)
2984 ? MonoChannel
2985 : (iChannel == 0)
2986 ? LeftChannel
2987 : RightChannel;
2988 xmlFile.WriteAttr(wxT("channel"), channelType);
2989 }
2990
2991 xmlFile.WriteAttr(wxT("linked"), static_cast<int>(track.GetLinkType()));
2992 track.WritableSampleTrack::WriteXMLAttributes(xmlFile);
2993 xmlFile.WriteAttr(wxT("rate"), track.GetRate());
2994
2995 // Some values don't vary independently in channels but have been written
2996 // redundantly for each channel. Keep doing this in 3.4 and later in case
2997 // a project is opened in an earlier version.
2998 xmlFile.WriteAttr(wxT("gain"), static_cast<double>(track.GetGain()));
2999 xmlFile.WriteAttr(wxT("pan"), static_cast<double>(track.GetPan()));
3000 xmlFile.WriteAttr(wxT("colorindex"), track.GetWaveColorIndex());
3001
3002 xmlFile.WriteAttr(wxT("sampleformat"), static_cast<long>(track.GetSampleFormat()));
3003
3004 WaveTrackIORegistry::Get().CallWriters(track, xmlFile);
3005
3006 for (const auto &clip : track.mClips)
3007 clip->WriteXML(xmlFile);
3008
3009 xmlFile.EndTag(wxT("wavetrack"));
3010}
void CallWriters(const Host &host, XMLWriter &writer)
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
ChannelType
Mutually exclusive channel classifications.

References XMLMethodRegistry< Host >::CallWriters(), XMLWriter::EndTag(), XMLMethodRegistry< Host >::Get(), GetGain(), Track::GetLinkType(), GetPan(), GetRate(), GetSampleFormat(), GetWaveColorIndex(), anonymous_namespace{StretchingSequenceIntegrationTest.cpp}::iChannel, AudioGraph::LeftChannel, mClips, AudioGraph::MonoChannel, AudioGraph::RightChannel, XMLWriter::StartTag(), XMLWriter::WriteAttr(), and wxT().

Here is the call graph for this function:

◆ WriteXML()

void WaveTrack::WriteXML ( XMLWriter xmlFile) const
overridevirtual

Implements Track.

Definition at line 2957 of file WaveTrack.cpp.

2959{
2960 assert(IsLeader());
2961 const auto channels = TrackList::Channels(this);
2962 size_t iChannel = 0,
2963 nChannels = channels.size();
2964 for (const auto pChannel : channels)
2965 WriteOneXML(*pChannel, xmlFile, iChannel++, nChannels);
2966}
static void WriteOneXML(const WaveTrack &track, XMLWriter &xmlFile, size_t iChannel, size_t nChannels)
Definition: WaveTrack.cpp:2968

References TrackList::Channels(), and anonymous_namespace{StretchingSequenceIntegrationTest.cpp}::iChannel.

Here is the call graph for this function:

Friends And Related Function Documentation

◆ WaveTrackFactory

friend class WaveTrackFactory
friend

Definition at line 297 of file WaveTrack.h.

Member Data Documentation

◆ mAppendCriticalSection

wxCriticalSection WaveTrack::mAppendCriticalSection
private

Definition at line 1212 of file WaveTrack.h.

◆ mClips

WaveClipHolders WaveTrack::mClips
private

◆ mFlushCriticalSection

wxCriticalSection WaveTrack::mFlushCriticalSection
private

Definition at line 1211 of file WaveTrack.h.

◆ mLegacyFormat

sampleFormat WaveTrack::mLegacyFormat { undefinedSample }
private

used only during deserialization

Definition at line 1125 of file WaveTrack.h.

Referenced by HandleXMLChild(), LinkConsistencyFix(), and SetLegacyFormat().

◆ mLegacyProjectFileOffset

double WaveTrack::mLegacyProjectFileOffset
private

Definition at line 1213 of file WaveTrack.h.

Referenced by HandleXMLChild(), HandleXMLTag(), and WaveTrack().

◆ mLegacyRate

int WaveTrack::mLegacyRate { 0 }
mutableprivate

used only during deserialization

Definition at line 1124 of file WaveTrack.h.

Referenced by HandleXMLChild(), HandleXMLTag(), and LinkConsistencyFix().

◆ mpFactory

SampleBlockFactoryPtr WaveTrack::mpFactory
private

◆ WaveChannel

friend WaveTrack::WaveChannel
private

Definition at line 1215 of file WaveTrack.h.


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