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 &&)
 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 ApplyStretchRatio (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
 
ClipConstHolders 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 () const
 public nonvirtual duplication function that invokes Clone() More...
 
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
 
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 () 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 ApplyStretchRatioOnIntervals (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)
 
void ApplyStretchRatioOne (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 218 of file WaveTrack.h.

Member Typedef Documentation

◆ Holder

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

Definition at line 298 of file WaveTrack.h.

◆ IntervalConstHolder

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

Definition at line 1012 of file WaveTrack.h.

◆ IntervalHolder

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

Definition at line 1011 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 915 of file WaveTrack.h.

◆ Regions

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

Definition at line 243 of file WaveTrack.h.

Constructor & Destructor Documentation

◆ WaveTrack() [1/2]

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

Definition at line 776 of file WaveTrack.cpp.

778 : mpFactory(pFactory)
779{
781
782 WaveTrackData::Get(*this).SetSampleFormat(format);
783 DoSetRate(static_cast<int>(rate));
784}
SampleBlockFactoryPtr mpFactory
Definition: WaveTrack.h:1191
void DoSetRate(double newRate)
Definition: WaveTrack.cpp:1100
double mLegacyProjectFileOffset
Definition: WaveTrack.h:1195
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 
)

Copied only in WaveTrack::Clone() !

Definition at line 786 of file WaveTrack.cpp.

787 : WritableSampleTrack(orig, std::move(a))
788 , mpFactory( orig.mpFactory )
789{
791 for (const auto &clip : orig.mClips)
792 InsertClip(std::make_shared<WaveClip>(*clip, mpFactory, true));
793}
bool InsertClip(WaveClipHolder clip)
Definition: WaveTrack.cpp:2338
WaveClipHolders mClips
Definition: WaveTrack.h:1107

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

Here is the call graph for this function:

◆ ~WaveTrack()

WaveTrack::~WaveTrack ( )
virtual

Definition at line 840 of file WaveTrack.cpp.

841{
842}

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 1892 of file WaveTrack.cpp.

1893{
1894 assert(clip);
1895 if (clip->GetSequence(0)->GetFactory() != this->mpFactory)
1896 return false;
1897
1898 if (clip->GetWidth() != GetWidth())
1899 return false;
1900
1901 // Uncomment the following line after we correct the problem of zero-length clips
1902 //if (CanInsertClip(clip))
1903 InsertClip(clip); // transfer ownership
1904
1905 return true;
1906}
size_t GetWidth() const
The width of every WaveClip in this track; for now always 1.
Definition: WaveTrack.cpp:795

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 2665 of file WaveTrack.cpp.

2668{
2669 // TODO wide wave tracks -- there will be only one clip, and its `Append`
2670 // (or an overload) must take iChannel
2671 auto pTrack = this;
2672 if (GetOwner() && iChannel == 1)
2673 pTrack = *TrackList::Channels(this).rbegin();
2674 constSamplePtr buffers[]{ buffer };
2675 return pTrack->RightmostOrNewClip()
2676 ->Append(buffers, format, len, stride, effectiveFormat);
2677}
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:1146

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:

◆ ApplyStretchRatio()

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

Definition at line 2351 of file WaveTrack.cpp.

2353{
2354 assert(IsLeader());
2355 // Assert that the interval is reasonable, but this function will be no-op
2356 // anyway if not
2357 assert(!interval.has_value() ||
2358 interval->first <= interval->second);
2359 if (GetNumClips() == 0)
2360 return;
2361 const auto startTime =
2362 interval ? std::max(SnapToSample(interval->first), GetStartTime()) :
2363 GetStartTime();
2364 const auto endTime =
2365 interval ? std::min(SnapToSample(interval->second), GetEndTime()) :
2366 GetEndTime();
2367 if (startTime >= endTime)
2368 return;
2369
2370 // Here we assume that left- and right clips are aligned.
2371 if (auto clipAtT0 = GetClipAtTime(startTime);
2372 clipAtT0 && clipAtT0->SplitsPlayRegion(startTime) &&
2373 !clipAtT0->StretchRatioEquals(1))
2374 Split(startTime, startTime);
2375 if (auto clipAtT1 = GetClipAtTime(endTime);
2376 clipAtT1 && clipAtT1->SplitsPlayRegion(endTime) &&
2377 !clipAtT1->StretchRatioEquals(1))
2378 Split(endTime, endTime);
2379
2380 std::vector<IntervalHolder> srcIntervals;
2381 auto clip = GetIntervalAtTime(startTime);
2382 while (clip && clip->GetPlayStartTime() < endTime)
2383 {
2384 if (clip->GetStretchRatio() != 1)
2385 srcIntervals.push_back(clip);
2387 }
2388
2389 ApplyStretchRatioOnIntervals(srcIntervals, reportProgress);
2390}
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:1379
const WaveClip * GetClipAtTime(double time) const
Definition: WaveTrack.cpp:3718
double GetStartTime() const override
Implement WideSampleSequence.
Definition: WaveTrack.cpp:3045
IntervalConstHolder GetNextInterval(const Interval &interval, PlaybackDirection searchDirection) const
Definition: WaveTrack.cpp:499
void ApplyStretchRatioOnIntervals(const std::vector< IntervalHolder > &intervals, const ProgressReporter &reportProgress)
Definition: WaveTrack.cpp:4099
bool IsLeader() const override
Definition: WaveTrack.cpp:2778
void Split(double t0, double t1)
Definition: WaveTrack.cpp:3952
double GetEndTime() const override
Implement WideSampleSequence.
Definition: WaveTrack.cpp:3050
int GetNumClips() const
Definition: WaveTrack.cpp:3831
IntervalHolder GetIntervalAtTime(double t)
Definition: WaveTrack.cpp:528
double SnapToSample(double t) const

References ApplyStretchRatioOnIntervals(), 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:

◆ ApplyStretchRatioOne()

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

◆ ApplyStretchRatioOnIntervals()

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

Definition at line 4099 of file WaveTrack.cpp.

4102{
4103 std::vector<IntervalHolder> dstIntervals;
4104 dstIntervals.reserve(srcIntervals.size());
4105 std::transform(
4106 srcIntervals.begin(), srcIntervals.end(),
4107 std::back_inserter(dstIntervals), [&](const IntervalHolder& interval) {
4108 return interval->GetStretchRenderedCopy(
4109 reportProgress, *this, mpFactory, GetSampleFormat());
4110 });
4111
4112 // If we reach this point it means that no error was thrown - we can replace
4113 // the source with the destination intervals.
4114 for (auto i = 0; i < srcIntervals.size(); ++i)
4115 ReplaceInterval(srcIntervals[i], dstIntervals[i]);
4116}
std::shared_ptr< Interval > IntervalHolder
Definition: WaveTrack.h:1011
void ReplaceInterval(const IntervalHolder &oldOne, const IntervalHolder &newOne)
Definition: WaveTrack.cpp:4143

References ReplaceInterval().

Referenced by ApplyStretchRatio(), 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 3910 of file WaveTrack.cpp.

3912{
3913 if (mClips.empty())
3914 return true;
3915 // Find clip in this that overlaps most with `clip`:
3916 const auto candidateClipStartTime = candidateClip.GetPlayStartTime();
3917 const auto candidateClipEndTime = candidateClip.GetPlayEndTime();
3918 const auto t0 = SnapToSample(candidateClipStartTime + slideBy);
3919 const auto t1 = SnapToSample(candidateClipEndTime + slideBy);
3920 std::vector<double> overlaps;
3921 std::transform(
3922 mClips.begin(), mClips.end(), std::back_inserter(overlaps),
3923 [&](const auto& pClip) {
3924 return pClip->IntersectsPlayRegion(t0, t1) ?
3925 std::min(pClip->GetPlayEndTime(), t1) -
3926 std::max(pClip->GetPlayStartTime(), t0) :
3927 0.0;
3928 });
3929 const auto maxOverlap = std::max_element(overlaps.begin(), overlaps.end());
3930 if (*maxOverlap > tolerance)
3931 return false;
3932 const auto overlappedClip =
3933 mClips[std::distance(overlaps.begin(), maxOverlap)];
3934 const auto requiredOffset = slideBy +
3935 *maxOverlap * (overlappedClip->GetPlayStartTime() < t0 ? 1 : -1);
3936 // Brute-force check to see if there's another clip that'd be in the way.
3937 if (std::any_of(
3938 mClips.begin(), mClips.end(),
3939 [&](const auto& pClip)
3940 {
3941 const auto result = pClip->IntersectsPlayRegion(
3942 SnapToSample(candidateClipStartTime + requiredOffset),
3943 SnapToSample(candidateClipEndTime + requiredOffset));
3944 return result;
3945 }))
3946 return false;
3947 slideBy = requiredOffset;
3948 return true;
3949}

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 3852 of file WaveTrack.cpp.

3856{
3857 if (allowedAmount)
3858 *allowedAmount = amount;
3859
3860 const auto &moving = [&](WaveClip *clip){
3861 // linear search might be improved, but expecting few moving clips
3862 // compared with the fixed clips
3863 return clips.end() != std::find( clips.begin(), clips.end(), clip );
3864 };
3865
3866 for (const auto &c: mClips) {
3867 if ( moving( c.get() ) )
3868 continue;
3869 for (const auto clip : clips) {
3870 if (c->GetPlayStartTime() < clip->GetPlayEndTime() + amount &&
3871 c->GetPlayEndTime() > clip->GetPlayStartTime() + amount)
3872 {
3873 if (!allowedAmount)
3874 return false; // clips overlap
3875
3876 if (amount > 0)
3877 {
3878 if (c->GetPlayStartTime() - clip->GetPlayEndTime() < *allowedAmount)
3879 *allowedAmount = c->GetPlayStartTime() - clip->GetPlayEndTime();
3880 if (*allowedAmount < 0)
3881 *allowedAmount = 0;
3882 } else
3883 {
3884 if (c->GetPlayEndTime() - clip->GetPlayStartTime() > *allowedAmount)
3885 *allowedAmount = c->GetPlayEndTime() - clip->GetPlayStartTime();
3886 if (*allowedAmount > 0)
3887 *allowedAmount = 0;
3888 }
3889 }
3890 }
3891 }
3892
3893 if (allowedAmount)
3894 {
3895 if (*allowedAmount == amount)
3896 return true;
3897
3898 // Check if the NEW calculated amount would not violate
3899 // any other constraint
3900 if (!CanOffsetClips(clips, *allowedAmount, nullptr)) {
3901 *allowedAmount = 0; // play safe and don't allow anything
3902 return false;
3903 }
3904 else
3905 return true;
3906 } else
3907 return true;
3908}
This allows multiple clips to be a part of one WaveTrack.
Definition: WaveClip.h:103
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:3852

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 272 of file WaveTrack.h.

272 {
273 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 274 of file WaveTrack.h.

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

◆ ClassTypeInfo()

auto WaveTrack::ClassTypeInfo ( )
static

Definition at line 956 of file WaveTrack.cpp.

957{
958 return typeInfo();
959}
static const Track::TypeInfo & typeInfo()
Definition: WaveTrack.cpp:943

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 1436 of file WaveTrack.cpp.

1437{
1438 assert(IsLeader());
1439 for (const auto pChannel : TrackList::Channels(this))
1440 pChannel->HandleClear(t0, t1, false, false);
1441}

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 1444 of file WaveTrack.cpp.

1445{
1446 assert(IsLeader());
1447 for (const auto pChannel : TrackList::Channels(this))
1448 pChannel->HandleClear(t0, t1, true, false);
1449}

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 434 of file WaveTrack.h.

439 {
440 ClearAndPaste(t0, t1, **src.Any<const WaveTrack>().begin(),
441 preserve, merge, effectWarper);
442 }
auto Any() -> TrackIterRange< TrackType >
Definition: Track.h:1079
A Track that contains audio waveform data.
Definition: WaveTrack.h:222
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:1498

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 1498 of file WaveTrack.cpp.

1506{
1507 // Get a modifiable copy of `src` because it may come from another project
1508 // with different tempo, making boundary queries incorrect.
1509 const auto& tempo = GetProjectTempo();
1510 if (!tempo.has_value())
1512 WaveTrack* copy;
1513 const auto copyHolder = src.DuplicateWithOtherTempo(*tempo, copy);
1515 t0, t1, *copy, preserve, merge, effectWarper, clearByTrimming);
1516}
#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:1518
TrackListHolder DuplicateWithOtherTempo(double newTempo, WaveTrack *&leader) const
Definition: WaveTrack.cpp:867
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 1518 of file WaveTrack.cpp.

1521{
1522 const auto srcNChannels = src.NChannels();
1523 assert(IsLeader());
1524 assert(src.IsLeader());
1525 assert(srcNChannels == 1 || srcNChannels == NChannels());
1526 assert(
1527 GetProjectTempo().has_value() &&
1528 GetProjectTempo() == src.GetProjectTempo());
1529
1530 t0 = SnapToSample(t0);
1531 t1 = SnapToSample(t1);
1532
1533 const auto startTime = src.GetStartTime();
1534 const auto endTime = src.GetEndTime();
1535 double dur = std::min(t1 - t0, endTime);
1536
1537 // If duration is 0, then it's just a plain paste
1538 if (dur == 0.0) {
1539 // use Weak-guarantee
1540 PasteWaveTrack(t0, src, merge);
1541 return;
1542 }
1543
1544 auto iter = TrackList::Channels(&src).begin();
1545 const auto myChannels = TrackList::Channels(this);
1546 for (const auto pChannel : myChannels) {
1548 *pChannel, t0, t1, startTime, endTime, **iter, preserve, merge,
1549 effectWarper, clearByTrimming);
1550 if (srcNChannels > 1)
1551 ++iter;
1552 }
1553}
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:1555
size_t NChannels() const override
May report more than one only when this is a leader track.
Definition: WaveTrack.cpp:800
void PasteWaveTrack(double t0, const WaveTrack &other, bool merge)
Definition: WaveTrack.cpp:2100

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 1555 of file WaveTrack.cpp.

1559{
1560 const auto pFactory = track.mpFactory;
1561
1562 std::vector<SplitInfo> splits;
1563 WaveClipHolders cuts;
1564
1565 //helper routine, that finds SplitInfo by time value,
1566 //or creates a new one if no one exists yet
1567 auto get_split = [&](double time) {
1568 auto it = std::find_if(splits.begin(), splits.end(),
1569 [time](const SplitInfo& split) { return split.time == time; });
1570 if(it == splits.end())
1571 it = splits.insert(
1572 splits.end(),
1573 { time, nullptr, nullptr, std::nullopt, std::nullopt }
1574 );
1575 return it;
1576 };
1577
1578 // If provided time warper was NULL, use a default one that does nothing
1579 IdentityTimeWarper localWarper;
1580 const TimeWarper *warper = (effectWarper ? effectWarper : &localWarper);
1581
1582 const auto roundTime = [&track](double t){
1583 return track.SnapToSample(t);
1584 };
1585
1586 // Align to a sample
1587 t0 = roundTime(t0);
1588 t1 = roundTime(t1);
1589
1590 // Save the cut/split lines whether preserving or not since merging
1591 // needs to know if a clip boundary is being crossed since Paste()
1592 // will add split lines around the pasted clip if so.
1593 for (const auto &clip : track.mClips) {
1594 double st;
1595
1596 // Remember clip boundaries as locations to split
1597 // we need to copy clips, trims and names, because the original ones
1598 // could be changed later during Clear/Paste routines
1599 st = roundTime(clip->GetPlayStartTime());
1600 if (st >= t0 && st <= t1) {
1601 auto it = get_split(st);
1602 if (clip->GetTrimLeft() != 0) {
1603 //keep only hidden left part
1604 it->right = std::make_shared<WaveClip>(*clip, pFactory, false);
1605 it->right->SetTrimLeft(.0);
1606 it->right->ClearRight(clip->GetPlayStartTime());
1607 }
1608 it->rightClipName = clip->GetName();
1609 }
1610
1611 st = roundTime(clip->GetPlayEndTime());
1612 if (st >= t0 && st <= t1) {
1613 auto it = get_split(st);
1614 if (clip->GetTrimRight() != 0) {
1615 //keep only hidden right part
1616 it->left = std::make_shared<WaveClip>(*clip, pFactory, false);
1617 it->left->SetTrimRight(.0);
1618 it->left->ClearLeft(clip->GetPlayEndTime());
1619 }
1620 it->leftClipName = clip->GetName();
1621 }
1622
1623 // Search for cut lines
1624 auto &cutlines = clip->GetCutLines();
1625 // May erase from cutlines, so don't use range-for
1626 for (auto it = cutlines.begin(); it != cutlines.end(); ) {
1627 WaveClip *cut = it->get();
1628 const double cs = roundTime(
1629 clip->GetSequenceStartTime() + cut->GetSequenceStartTime());
1630
1631 // Remember cut point
1632 if (cs >= t0 && cs <= t1) {
1633 // Remember the absolute offset and add to our cuts array.
1634 cut->SetSequenceStartTime(cs);
1635 cuts.push_back(std::move(*it)); // transfer ownership!
1636 it = cutlines.erase(it);
1637 }
1638 else
1639 ++it;
1640 }
1641 }
1642
1643 const auto tolerance = 2.0 / track.GetRate();
1644
1645 // This is not a split-cut operation.
1646 constexpr auto split = false;
1647
1648 // Now, clear the selection
1649 track.HandleClear(t0, t1, false, split, clearByTrimming);
1650
1651 // And paste in the new data
1652 PasteOne(track, t0, src, startTime, endTime, merge);
1653
1654 // First, merge the new clip(s) in with the existing clips
1655 if (merge && splits.size() > 0) {
1656 {
1657 // Now t1 represents the absolute end of the pasted data.
1658 t1 = t0 + endTime;
1659
1660 // Get a sorted array of the clips
1661 auto clips = track.SortedClipArray();
1662
1663 // Scan the sorted clips for the first clip whose start time
1664 // exceeds the pasted regions end time.
1665 {
1666 WaveClip *prev = nullptr;
1667 for (const auto clip : clips) {
1668 // Merge this clip and the previous clip if the end time
1669 // falls within it and this isn't the first clip in the track.
1670 if (fabs(t1 - clip->GetPlayStartTime()) < tolerance) {
1671 if (prev && clip->HasEqualStretchRatio(*prev))
1672 track.MergeOneClipPair(track.GetClipIndex(prev),
1673 track.GetClipIndex(clip));
1674 break;
1675 }
1676 prev = clip;
1677 }
1678 }
1679 }
1680
1681 {
1682 // Refill the array since clips have changed.
1683 auto clips = track.SortedClipArray();
1684
1685 // Scan the sorted clips to look for the start of the pasted
1686 // region.
1687 WaveClip *prev = nullptr;
1688 for (const auto clip : clips) {
1689 if (prev) {
1690 // It must be that clip is what was pasted and it begins where
1691 // prev ends.
1692 // use Weak-guarantee
1693 if (clip->HasEqualStretchRatio(*prev))
1694 track.MergeOneClipPair(
1695 track.GetClipIndex(prev), track.GetClipIndex(clip));
1696 break;
1697 }
1698 if (fabs(t0 - clip->GetPlayEndTime()) < tolerance)
1699 // Merge this clip and the next clip if the start time
1700 // falls within it and this isn't the last clip in the track.
1701 prev = clip;
1702 else
1703 prev = nullptr;
1704 }
1705 }
1706 }
1707
1708 // Restore cut/split lines
1709 if (preserve) {
1710 auto attachLeft = [](WaveClip& target, WaveClip& src) {
1711 // What this lambda does is restoring the left hidden data of `target`
1712 // that was cleared by `HandleClear`. Hence, `target` has no left
1713 // hidden data at this stage.
1714 assert(target.GetTrimLeft() == 0);
1715 if (target.GetTrimLeft() != 0)
1716 return;
1717
1718 // `src` was created by copy from `target`, so they have equal width
1719 // and stretch ratio.
1720 assert(target.GetWidth() == src.GetWidth());
1721 assert(target.GetStretchRatio() == src.GetStretchRatio());
1722
1723 auto trim = src.GetPlayEndTime() - src.GetPlayStartTime();
1724 auto success = target.Paste(target.GetPlayStartTime(), src);
1725 assert(success); // because of precondition above
1726 target.SetTrimLeft(trim);
1727 //Play start time needs to be adjusted after
1728 //prepending data to the sequence
1729 target.ShiftBy(-trim);
1730 };
1731
1732 auto attachRight = [](WaveClip &target, WaveClip &src)
1733 {
1734 // See `attachLeft` for rationale behind these asserts.
1735 assert(target.GetTrimRight() == 0);
1736 if (target.GetTrimRight() != 0)
1737 return;
1738 assert(target.GetWidth() == src.GetWidth());
1739 assert(target.GetStretchRatio() == src.GetStretchRatio());
1740
1741 auto trim = src.GetPlayEndTime() - src.GetPlayStartTime();
1742 auto success = target.Paste(target.GetPlayEndTime(), src);
1743 assert(success); // because of precondition above
1744 target.SetTrimRight(trim);
1745 };
1746
1747 // Restore the split lines and trims, transforming the position appropriately
1748 for (const auto& split: splits) {
1749 auto at = roundTime(warper->Warp(split.time));
1750 for (const auto& clip : track.GetClips()) {
1751 // Clips in split began as copies of a clip in the track,
1752 // therefore have the same width, satisfying preconditions to
1753 // attach
1754 if (clip->SplitsPlayRegion(at))//strictly inside
1755 {
1756 auto newClip =
1757 std::make_shared<WaveClip>(*clip, pFactory, true);
1758
1759 clip->ClearRight(at);
1760 newClip->ClearLeft(at);
1761 if (split.left)
1762 // clip was cleared right
1763 attachRight(*clip, *split.left);
1764 if (split.right)
1765 // new clip was cleared left
1766 attachLeft(*newClip, *split.right);
1767 bool success = track.AddClip(std::move(newClip));
1768 assert(success); // copied clip has same width and factory
1769 break;
1770 }
1771 else if (clip->GetPlayStartSample() ==
1772 track.TimeToLongSamples(at) && split.right) {
1773 // Satisfy the precondition of attachLeft first!
1774 const auto trim = clip->GetTrimLeft();
1775 const auto seqStartTime = clip->GetSequenceStartTime();
1776 clip->Clear(seqStartTime, seqStartTime + trim);
1777 // This clearing, although only removing the hidden part, moved
1778 // the clip leftwards. We don't want this in this case.
1779 clip->ShiftBy(trim);
1780 attachLeft(*clip, *split.right);
1781 break;
1782 }
1783 else if (clip->GetPlayEndSample() ==
1784 track.TimeToLongSamples(at) && split.left) {
1785 // Satisfy the precondition of attachRight first!
1786 clip->Clear(
1787 clip->GetPlayEndTime(), clip->GetSequenceEndTime());
1788 attachRight(*clip, *split.left);
1789 break;
1790 }
1791 }
1792 }
1793
1794 //Restore clip names
1795 for (const auto& split : splits)
1796 {
1797 auto s = track.TimeToLongSamples(warper->Warp(split.time));
1798 for (auto& clip : track.GetClips()) {
1799 if (split.rightClipName.has_value() && clip->GetPlayStartSample() == s)
1800 clip->SetName(*split.rightClipName);
1801 else if (split.leftClipName.has_value() && clip->GetPlayEndSample() == s)
1802 clip->SetName(*split.leftClipName);
1803 }
1804 }
1805
1806 // Restore the saved cut lines, also transforming if time altered
1807 for (const auto &clip : track.mClips) {
1808 double st;
1809 double et;
1810
1811 st = clip->GetPlayStartTime();
1812 et = clip->GetPlayEndTime();
1813
1814 // Scan the cuts for any that live within this clip
1815 for (auto it = cuts.begin(); it != cuts.end();) {
1816 WaveClip *cut = it->get();
1817 //cutlines in this array were orphaned previously
1818 double cs = cut->GetSequenceStartTime();
1819
1820 // Offset the cut from the start of the clip and add it to
1821 // this clips cutlines.
1822 if (cs >= st && cs <= et) {
1823 cut->SetSequenceStartTime(warper->Warp(cs) - st);
1824 clip->GetCutLines().push_back( std::move(*it) ); // transfer ownership!
1825 it = cuts.erase(it);
1826 }
1827 else
1828 ++it;
1829 }
1830 }
1831 }
1832}
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 GetStretchRatio() const override
Definition: WaveClip.cpp:340
double GetSequenceStartTime() const noexcept
Definition: WaveClip.cpp:1348
void SetSequenceStartTime(double startTime)
Definition: WaveClip.cpp:1355
void ShiftBy(double delta) noexcept
Definition: WaveClip.cpp:1374
double GetTrimRight() const noexcept
Returns the play end offset in seconds from the ending of the underlying sequence.
Definition: WaveClip.cpp:1320
double GetPlayStartTime() const noexcept override
Definition: WaveClip.cpp:1257
double GetTrimLeft() const noexcept
Returns the play start offset in seconds from the beginning of the underlying sequence.
Definition: WaveClip.cpp:1310
double GetPlayEndTime() const override
Definition: WaveClip.cpp:1267
void SetTrimRight(double trim)
Sets the play end offset in seconds from the ending of the underlying sequence.
Definition: WaveClip.cpp:1315
void SetTrimLeft(double trim)
Sets the play start offset in seconds from the beginning of the underlying sequence.
Definition: WaveClip.cpp:1305
bool Paste(double t0, const WaveClip &other)
Definition: WaveClip.cpp:670
size_t GetWidth() const override
Definition: WaveClip.cpp:163
bool AddClip(const std::shared_ptr< WaveClip > &clip)
Definition: WaveTrack.cpp:1892
WaveClipPointers SortedClipArray()
Definition: WaveTrack.cpp:4372
static void PasteOne(WaveTrack &track, double t0, const WaveTrack &other, double startTime, double insertDuration, bool merge=true)
Definition: WaveTrack.cpp:2131
bool MergeOneClipPair(int clipidx1, int clipidx2)
Definition: WaveTrack.cpp:4074
int GetClipIndex(const WaveClip *clip) const
Definition: WaveTrack.cpp:3811
double GetRate() const override
Definition: WaveTrack.cpp:1085
WaveClipHolders & GetClips()
Definition: WaveTrack.h:694
void HandleClear(double t0, double t1, bool addCutLines, bool split, bool clearByTrimming=false)
Definition: WaveTrack.cpp:1909
sampleCount TimeToLongSamples(double t0) const

References AddClip(), GetClipIndex(), GetClips(), WaveClip::GetPlayEndTime(), WaveClip::GetPlayStartTime(), GetRate(), WaveClip::GetSequenceStartTime(), WaveClip::GetStretchRatio(), WaveClip::GetTrimLeft(), WaveClip::GetTrimRight(), GetWidth(), WaveClip::GetWidth(), HandleClear(), WaveClip::HasEqualStretchRatio(), 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 ( ) 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()
Postcondition
result: NChannels() == result->NChannels()

Implements Track.

Definition at line 1043 of file WaveTrack.cpp.

1044{
1045 assert(IsLeader());
1046 auto result = TrackList::Temporary(nullptr);
1047 const auto cloneOne = [&](const WaveTrack *pChannel){
1048 const auto pTrack =
1049 std::make_shared<WaveTrack>(*pChannel, ProtectedCreationArg{});
1050 pTrack->Init(*pChannel);
1051 result->Add(pTrack);
1052 };
1053 if (GetOwner())
1054 for (const auto pChannel : TrackList::Channels(this))
1055 cloneOne(pChannel);
1056 else
1057 cloneOne(this);
1058 return result;
1059}
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 2982 of file WaveTrack.cpp.

2983{
2984 assert(IsLeader());
2985 for (const auto pChannel : TrackList::Channels(this))
2986 for (const auto &clip : pChannel->mClips)
2987 clip->CloseLock();
2988
2989 return true;
2990}

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 1226 of file WaveTrack.cpp.

1228{
1229 assert(IsLeader());
1230 for (const auto pChannel : TrackList::Channels(this)) {
1231 for (const auto& clip : pChannel->mClips)
1232 clip->ConvertToSampleFormat(format, progressReport);
1233 }
1234 WaveTrackData::Get(*this).SetSampleFormat(format);
1235}

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 1365 of file WaveTrack.cpp.

1366{
1367 if (t1 < t0)
1369
1370 auto list = TrackList::Create(nullptr);
1371 for (const auto pChannel : TrackList::Channels(this))
1372 list->Add(CopyOne(*pChannel, t0, t1, forClipboard));
1373 return list;
1374}
static TrackListHolder Create(AudacityProject *pOwner)
Definition: Track.cpp:365
static Holder CopyOne(const WaveTrack &track, double t0, double t1, bool forClipboard)
Definition: WaveTrack.cpp:1376

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 2746 of file WaveTrack.cpp.

2747{
2748 const auto channels = TrackList::Channels(this);
2749 if (channels.size() != 2)
2750 return;
2751 // Assume correspondence of clips
2752 const auto left = *channels.begin();
2753 auto it = begin(left->mClips),
2754 last = end(left->mClips);
2755 const auto right = *channels.rbegin();
2756 auto it2 = begin(right->mClips),
2757 last2 = end(right->mClips);
2758 for (; it != last; ++it, ++it2) {
2759 if (it2 == last2) {
2760 assert(false);
2761 break;
2762 }
2763 (*it2)->SetEnvelope(std::make_unique<Envelope>(*(*it)->GetEnvelope()));
2764 }
2765}
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 1376 of file WaveTrack.cpp.

1378{
1379 const auto &pFactory = track.mpFactory;
1380 auto result = track.EmptyCopy();
1381 WaveTrack *newTrack = result.get();
1382
1383 // PRL: Why shouldn't cutlines be copied and pasted too? I don't know,
1384 // but that was the old behavior. But this function is also used by the
1385 // Duplicate command and I changed its behavior in that case.
1386
1387 for (const auto &clip : track.mClips) {
1388 if(clip->IsEmpty())
1389 continue;
1390
1391 if (t0 <= clip->GetPlayStartTime() && t1 >= clip->GetPlayEndTime()) {
1392 // Whole clip is in copy region
1393 //wxPrintf("copy: clip %i is in copy region\n", (int)clip);
1394
1395 newTrack->InsertClip(
1396 std::make_shared<WaveClip>(*clip, pFactory, !forClipboard));
1397 WaveClip *const newClip = newTrack->mClips.back().get();
1398 newClip->ShiftBy(-t0);
1399 }
1400 else if (clip->CountSamples(t0, t1) >= 1) {
1401 // Clip is affected by command
1402 //wxPrintf("copy: clip %i is affected by command\n", (int)clip);
1403
1404 auto newClip = std::make_shared<WaveClip>(
1405 *clip, pFactory, !forClipboard, t0, t1);
1406 newClip->SetName(clip->GetName());
1407
1408 newClip->ShiftBy(-t0);
1409 if (newClip->GetPlayStartTime() < 0)
1410 newClip->SetPlayStartTime(0);
1411
1412 newTrack->InsertClip(std::move(newClip)); // transfer ownership
1413 }
1414 }
1415
1416 // AWD, Oct 2009: If the selection ends in whitespace, create a
1417 // placeholder clip representing that whitespace
1418 // PRL: Only if we want the track for pasting into other tracks. Not if
1419 // it goes directly into a project as in the Duplicate command.
1420 if (forClipboard &&
1421 newTrack->GetEndTime() + 1.0 / newTrack->GetRate() < t1 - t0) {
1422 // TODO wide wave tracks -- match clip width of newTrack
1423 auto placeholder = std::make_shared<WaveClip>(1, pFactory,
1424 newTrack->GetSampleFormat(),
1425 static_cast<int>(newTrack->GetRate()),
1426 0 /*colourindex*/);
1427 placeholder->SetIsPlaceholder(true);
1428 placeholder->InsertSilence(0, (t1 - t0) - newTrack->GetEndTime());
1429 placeholder->ShiftBy(newTrack->GetEndTime());
1430 newTrack->InsertClip(std::move(placeholder)); // transfer ownership
1431 }
1432 return newTrack->SharedPointer<WaveTrack>();
1433}
std::shared_ptr< Subclass > SharedPointer()
Definition: Track.h:160
void SetPlayStartTime(double time)
Definition: WaveClip.cpp:1262
void SetName(const wxString &name)
Definition: WaveClip.cpp:1217
sampleFormat GetSampleFormat() const override
Definition: WaveTrack.cpp:1220
Holder EmptyCopy(const SampleBlockFactoryPtr &pFactory={}, bool keepLink=true) const
Definition: WaveTrack.cpp:1323

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 1209 of file WaveTrack.cpp.

1210{
1211 assert(IsLeader());
1212 size_t result{};
1213 for (const auto pChannel : TrackList::Channels(this)) {
1214 for (auto& clip : pChannel->GetClips())
1215 result += clip->GetWidth() * clip->GetSequenceBlockArray(0)->size();
1216 }
1217 return result;
1218}

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 3760 of file WaveTrack.cpp.

3761{
3762 // TODO wide wave tracks -- choose clip width correctly for the track
3763 auto clip = std::make_shared<WaveClip>(1,
3765 clip->SetName(name);
3766 clip->SetSequenceStartTime(offset);
3767
3768 const auto& tempo = GetProjectTempo();
3769 if (tempo.has_value())
3770 clip->OnProjectTempoChange(std::nullopt, *tempo);
3771 mClips.push_back(std::move(clip));
3772
3773 auto result = mClips.back().get();
3774 // TODO wide wave tracks -- for now assertion is correct because widths are
3775 // always 1
3776 assert(result->GetWidth() == GetWidth());
3777 return result;
3778}
const TranslatableString name
Definition: Distortion.cpp:76
int GetWaveColorIndex() const
Definition: WaveTrack.cpp:1171

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 3753 of file WaveTrack.cpp.

3754{
3755 assert(IsLeader());
3756 for(auto channel : TrackList::Channels(this))
3757 channel->CreateClip(offset, name);
3758}

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 1260 of file WaveTrack.cpp.

1261{
1262 assert(IsLeader());
1263 if (t1 < t0)
1265
1266 auto result = Copy(t0, t1);
1267 Clear(t0, t1);
1268 return result;
1269}
void Clear(double t0, double t1) override
Definition: WaveTrack.cpp:1436
TrackListHolder Copy(double t0, double t1, bool forClipboard=true) const override
Create new tracks and don't modify this track.
Definition: WaveTrack.cpp:1365

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 4392 of file WaveTrack.cpp.

4393{
4394 assert(IsLeader());
4395 for (const auto pChannel : TrackList::Channels(this)) {
4396 for (auto clip : pChannel->GetClips()) {
4397 if (clip->GetTrimLeft() != 0) {
4398 auto t0 = clip->GetPlayStartTime();
4399 clip->SetTrimLeft(0);
4400 clip->ClearLeft(t0);
4401 }
4402 if (clip->GetTrimRight() != 0) {
4403 auto t1 = clip->GetPlayEndTime();
4404 clip->SetTrimRight(0);
4405 clip->ClearRight(t1);
4406 }
4407 }
4408 }
4409}

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 2477 of file WaveTrack.cpp.

2478{
2479 assert(IsLeader());
2481 const size_t maxAtOnce = 1048576;
2482 std::vector<float> buffer;
2483 std::vector<samplePtr> buffers;
2484 Regions regions;
2485
2486 const size_t width = NChannels();
2487
2488 for (const auto &interval : Intervals()) {
2489 double startTime = interval->Start();
2490 double endTime = interval->End();
2491
2492 if (endTime < t0 || startTime > t1)
2493 continue;
2494
2495 // Assume all clips will have the same width
2496 if (buffer.empty()) {
2497 buffer.resize(maxAtOnce * width);
2498 buffers.resize(width);
2499 auto pBuffer = buffer.data();
2500 for (size_t ii = 0; ii < width; ++ii, pBuffer += maxAtOnce)
2501 buffers[ii] = reinterpret_cast<samplePtr>(pBuffer);
2502 }
2503
2504 const auto allZeroesAt = [&](size_t i) {
2505 auto pData = buffer.data() + i;
2506 for (size_t ii = 0; ii < width; ++ii, pData += maxAtOnce) {
2507 if (*pData != 0.0)
2508 return false;
2509 }
2510 return true;
2511 };
2512
2513 // simply look for a sequence of zeroes (across all channels) and if the
2514 // sequence is longer than the minimum number, split-delete the region
2515
2516 sampleCount seqStart = -1;
2517 auto start = interval->TimeToSamples(std::max(.0, t0 - startTime));
2518 auto end = interval->TimeToSamples(std::min(endTime, t1) - startTime);
2519
2520 auto len = (end - start);
2521 for (decltype(len) done = 0; done < len; done += maxAtOnce) {
2522 auto numSamples = limitSampleBufferSize(maxAtOnce, len - done);
2523
2524 auto bufferIt = buffers.begin();
2525
2526 for (auto channel : interval->Channels())
2527 channel->GetSamples(
2528 *bufferIt++, floatSample, start + done, numSamples);
2529
2530 for (decltype(numSamples) i = 0; i < numSamples; ++i) {
2531 auto curSamplePos = start + done + i;
2532
2533 //start a NEW sequence
2534 if (seqStart == -1 && allZeroesAt(i))
2535 seqStart = curSamplePos;
2536 else if (curSamplePos == end - 1 || !allZeroesAt(i)) {
2537 if (seqStart != -1) {
2538 decltype(end) seqEnd;
2539
2540 //consider the end case, where selection ends in zeroes
2541 if (curSamplePos == end - 1 && allZeroesAt(i))
2542 seqEnd = end;
2543 else
2544 seqEnd = curSamplePos;
2545 if (seqEnd - seqStart + 1 > minSamples) {
2546 regions.push_back(
2547 Region(
2548 startTime + interval->SamplesToTime(seqStart),
2549 startTime + interval->SamplesToTime(seqEnd)
2550 )
2551 );
2552 }
2553 seqStart = -1;
2554 }
2555 }
2556 } // samples
2557 } // blocks
2558 } // finding regions
2559
2560 for (const auto &region : regions)
2561 SplitDelete(region.start, region.end);
2562}
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:1835
auto Intervals()
Definition: WaveTrack.h:1026
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 3134 of file WaveTrack.cpp.

3138{
3139 const auto nChannels = NChannels();
3140 assert(iChannel + nBuffers <= nChannels); // precondition
3141 const auto pOwner = GetOwner();
3142 if (!pOwner) {
3144 assert(nChannels == 1);
3145 nBuffers = std::min<size_t>(nBuffers, 1);
3146 }
3147 std::optional<TrackIter<const WaveTrack>> iter;
3148 auto pTrack = this;
3149 if (pOwner) {
3150 const auto ppLeader = TrackList::Channels(this).first;
3151 iter.emplace(ppLeader.advance(IsLeader() ? iChannel : 1));
3152 pTrack = **iter;
3153 }
3154 return std::all_of(buffers, buffers + nBuffers, [&](samplePtr buffer) {
3155 const auto result = pTrack->GetOne(
3156 buffer, format, start, len, backwards, fill, mayThrow,
3157 pNumWithinClips);
3158 if (iter)
3159 pTrack = *(++ *iter);
3160 return result;
3161 });
3162}

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 1014 of file WaveTrack.cpp.

1015{
1016 auto nChannels = NChannels();
1017 if (iChannel >= nChannels)
1018 return {};
1019 auto pTrack = (iChannel == 0)
1020 ? this
1021 // TODO: more-than-two-channels
1022 : *TrackList::Channels(this).rbegin();
1023 // Use aliasing constructor of std::shared_ptr
1024 ::Channel *alias = pTrack;
1025 return { pTrack->shared_from_this(), alias };
1026}

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 1028 of file WaveTrack.cpp.

1029{
1030 const ChannelGroup &group = *this;
1031 return const_cast<ChannelGroup&>(group);
1032}

◆ DoGetInterval()

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

Retrieve an interval.

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

Implements ChannelGroup.

Definition at line 988 of file WaveTrack.cpp.

989{
990 if (iInterval < NIntervals()) {
991 WaveClipHolder pClip = mClips[iInterval],
992 pClip1;
993 // TODO wide wave tracks
994 // This assumed correspondence of clips may be wrong if they misalign
995 if (auto right = ChannelGroup::GetChannel<WaveTrack>(1)
996 ; right && iInterval < right->mClips.size()
997 )
998 pClip1 = right->mClips[iInterval];
999 return std::make_shared<Interval>(*this, pClip, pClip1);
1000 }
1001 return {};
1002}
std::shared_ptr< WaveClip > WaveClipHolder
Definition: WaveClip.h:45
size_t NIntervals() const override
used only during deserialization
Definition: WaveTrack.cpp:982

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 857 of file WaveTrack.cpp.

859{
860 assert(IsLeader());
861 for (const auto pChannel : TrackList::Channels(this))
862 for (const auto& clip : pChannel->mClips)
863 clip->OnProjectTempoChange(oldTempo, newTempo);
864}

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

Here is the call graph for this function:

◆ DoSetGain()

void WaveTrack::DoSetGain ( float  value)
private

Definition at line 1117 of file WaveTrack.cpp.

1118{
1119 WaveTrackData::Get(*this).SetGain(value);
1120}

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 1135 of file WaveTrack.cpp.

1136{
1137 WaveTrackData::Get(*this).SetPan(value);
1138}

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 1100 of file WaveTrack.cpp.

1101{
1102 auto &data = WaveTrackData::Get(*this);
1103 data.SetRate(static_cast<int>(newRate));
1104}

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 867 of file WaveTrack.cpp.

868{
869 const auto srcCopyList = Duplicate();
870 leader = *srcCopyList->Any<WaveTrack>().begin();
871 leader->OnProjectTempoChange(newTempo);
872 return srcCopyList;
873}
virtual TrackListHolder Duplicate() 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 1323 of file WaveTrack.cpp.

1325{
1326 const auto rate = GetRate();
1327 auto result = std::make_shared<WaveTrack>(pFactory, GetSampleFormat(), rate);
1328 result->Init(*this);
1329 // The previous line might have destroyed the rate information stored in
1330 // channel group data. The copy is not yet in a TrackList. Reassign rate
1331 // in case the track needs to make WaveClips before it is properly joined
1332 // with the opposite channel in a TrackList.
1333 // TODO wide wave tracks -- all of the comment above will be irrelevant!
1334 result->DoSetRate(rate);
1335 result->mpFactory = pFactory ? pFactory : mpFactory;
1336 if (!keepLink)
1337 result->SetLinkType(LinkType::None);
1338 WaveTrackData::Get(*result).SetOrigin(0);
1339 return result;
1340}

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 3984 of file WaveTrack.cpp.

3986{
3987 assert(IsLeader());
3988 for (const auto pChannel : TrackList::Channels(this)) {
3989 pChannel->ExpandOneCutLine(cutLinePosition, cutlineStart, cutlineEnd);
3990 // Assign the out parameters at most once
3991 cutlineStart = cutlineEnd = nullptr;
3992 }
3993}

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 3996 of file WaveTrack.cpp.

3998{
3999 bool editClipCanMove = GetEditClipsCanMove();
4000
4001 // Find clip which contains this cut line
4002 double start = 0, end = 0;
4003 auto pEnd = mClips.end();
4004 auto pClip = std::find_if( mClips.begin(), pEnd,
4005 [&](const WaveClipHolder &clip) {
4006 return clip->FindCutLine(cutLinePosition, &start, &end); } );
4007 if (pClip != pEnd)
4008 {
4009 auto &clip = *pClip;
4010 if (!editClipCanMove)
4011 {
4012 // We are not allowed to move the other clips, so see if there
4013 // is enough room to expand the cut line
4014 for (const auto &clip2: mClips)
4015 {
4016 if (clip2->GetPlayStartTime() > clip->GetPlayStartTime() &&
4017 clip->GetPlayEndTime() + end - start > clip2->GetPlayStartTime())
4018 // Strong-guarantee in case of this path
4021 XO("There is not enough room available to expand the cut line"),
4022 XO("Warning"),
4023 "Error:_Insufficient_space_in_track"
4024 };
4025 }
4026 }
4027
4028 clip->ExpandCutLine(cutLinePosition);
4029
4030 // Strong-guarantee provided that the following gives No-fail-guarantee
4031
4032 if (cutlineStart)
4033 *cutlineStart = start;
4034 if (cutlineEnd)
4035 *cutlineEnd = end;
4036
4037 // Move clips which are to the right of the cut line
4038 if (editClipCanMove)
4039 {
4040 for (const auto &clip2 : mClips)
4041 {
4042 if (clip2->GetPlayStartTime() > clip->GetPlayStartTime())
4043 clip2->ShiftBy(end - start);
4044 }
4045 }
4046 }
4047}
@ BadUserAction
Indicates that the user performed an action that is not allowed.
XO("Cut/Copy/Paste")
bool GetEditClipsCanMove()
Definition: WaveTrack.cpp:4538
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 2783 of file WaveTrack.cpp.

2784{
2785 return this;
2786}

◆ FindClipByName()

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

Returns nullptr if clip with such name was not found.

Definition at line 1004 of file WaveTrack.cpp.

1005{
1006 for (const auto& clip : mClips)
1007 {
1008 if (clip->GetName() == name)
1009 return clip.get();
1010 }
1011 return nullptr;
1012}

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 2734 of file WaveTrack.cpp.

2735{
2736 assert(IsLeader());
2737 for (const auto pChannel : TrackList::Channels(this))
2738 pChannel->FlushOne();
2739}

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 2772 of file WaveTrack.cpp.

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

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 2327 of file WaveTrack.cpp.

2328{
2329 assert(IsLeader());
2330
2331 const auto channels = TrackList::Channels(this);
2332 return std::all_of(channels.begin(), channels.end(),
2333 [&](const WaveTrack *pTrack){
2334 return pTrack && pTrack->mLegacyFormat == mLegacyFormat;
2335 });
2336}

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 3675 of file WaveTrack.cpp.

3676{
3677 return const_cast<WaveClip*>(
3678 std::as_const(*this).GetAdjacentClip(clip, direction));
3679}

◆ 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 3656 of file WaveTrack.cpp.

3658{
3659 const auto neighbour = GetNextClip(clip, direction);
3660 if (!neighbour)
3661 return nullptr;
3662 else if (direction == PlaybackDirection::forward)
3663 return std::abs(clip.GetPlayEndTime() - neighbour->GetPlayStartTime()) <
3664 1e-9 ?
3665 neighbour :
3666 nullptr;
3667 else
3668 return std::abs(clip.GetPlayStartTime() - neighbour->GetPlayEndTime()) <
3669 1e-9 ?
3670 neighbour :
3671 nullptr;
3672}
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:3688

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 789 of file WaveTrack.h.

790 {
791 return { AllClipsIterator{ *this }, AllClipsIterator{ } };
792 }

◆ GetAllClips() [2/2]

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

Definition at line 794 of file WaveTrack.h.

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

◆ GetBestBlockSize()

size_t WaveTrack::GetBestBlockSize ( sampleCount  t) const

Definition at line 2679 of file WaveTrack.cpp.

2680{
2681 auto bestBlockSize = GetMaxBlockSize();
2682
2683 for (const auto &clip : mClips)
2684 {
2685 auto startSample = clip->GetPlayStartSample();
2686 auto endSample = clip->GetPlayEndSample();
2687 if (s >= startSample && s < endSample)
2688 {
2689 // ignore extra channels (this function will soon be removed)
2690 bestBlockSize = clip->GetSequence(0)
2691 ->GetBestBlockSize(s - clip->GetSequenceStartSample());
2692 break;
2693 }
2694 }
2695
2696 return bestBlockSize;
2697}
size_t GetMaxBlockSize() const
Definition: WaveTrack.cpp:2699

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 267 of file WaveTrack.h.

267 {
268 return this->ChannelGroup::GetChannel<WaveChannel>(iChannel); }

References anonymous_namespace{StretchingSequenceIntegrationTest.cpp}::iChannel.

Referenced by WaveTrackMenuTable::SplitStereo().

Here is the caller graph for this function:

◆ GetChannel() [2/2]

auto WaveTrack::GetChannel ( size_t  iChannel) const
inline

Definition at line 269 of file WaveTrack.h.

269 {
270 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 1153 of file WaveTrack.cpp.

1154{
1155 float left = 1.0;
1156 float right = 1.0;
1157
1158 const auto pan = GetPan();
1159 if (pan < 0)
1160 right = (pan + 1.0);
1161 else if (pan > 0)
1162 left = 1.0 - pan;
1163
1164 const auto gain = GetGain();
1165 if ((channel%2) == 0)
1166 return left * gain;
1167 else
1168 return right * gain;
1169}
float GetPan() const
Definition: WaveTrack.cpp:1130
float GetGain() const
Definition: WaveTrack.cpp:1112

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 811 of file WaveTrack.cpp.

812{
813 if (TrackList::NChannels(*this) == 1)
815 else if (IsLeader())
817 else
818 // TODO: more-than-two-channels
820}
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 3683 of file WaveTrack.cpp.

3684{
3685 return const_cast<WaveClip*>(std::as_const(*this).GetClipAtTime(time));
3686}

◆ GetClipAtTime() [2/2]

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

Definition at line 3718 of file WaveTrack.cpp.

3719{
3720 const auto clips = SortedClipArray();
3721 auto p = std::find_if(
3722 clips.rbegin(), clips.rend(), [&](const WaveClip* const& clip) {
3723 return clip->WithinPlayRegion(time);
3724 });
3725
3726 // When two clips are immediately next to each other, the GetPlayEndTime() of the first clip
3727 // and the GetPlayStartTime() of the second clip may not be exactly equal due to rounding errors.
3728 // If "time" is the end time of the first of two such clips, and the end time is slightly
3729 // less than the start time of the second clip, then the first rather than the
3730 // second clip is found by the above code. So correct this.
3731 if (p != clips.rend() && p != clips.rbegin() &&
3732 time == (*p)->GetPlayEndTime() &&
3733 (*p)->SharesBoundaryWithNextClip(*(p-1))) {
3734 p--;
3735 }
3736
3737 return p != clips.rend() ? *p : nullptr;
3738}

References SortedClipArray().

Referenced by anonymous_namespace{SampleHandle.cpp}::adjustTime(), ApplyStretchRatio(), 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 3818 of file WaveTrack.cpp.

3819{
3820 if(index < (int)mClips.size())
3821 return mClips[index].get();
3822 else
3823 return nullptr;
3824}

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 3826 of file WaveTrack.cpp.

3827{
3828 return const_cast<WaveTrack&>(*this).GetClipByIndex(index);
3829}
WaveClip * GetClipByIndex(int index)
Get the nth clip in this WaveTrack (will return nullptr if not found).
Definition: WaveTrack.cpp:3818

References GetClipByIndex().

Here is the call graph for this function:

◆ GetClipIndex()

int WaveTrack::GetClipIndex ( const WaveClip clip) const

Definition at line 3811 of file WaveTrack.cpp.

3812{
3813 int result;
3814 FindClip(mClips, clip, &result);
3815 return result;
3816}
WaveClipHolders::iterator FindClip(WaveClipHolders &list, const WaveClip *clip, int *distance=nullptr)
Definition: WaveTrack.cpp:1863

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()

ClipConstHolders WaveTrack::GetClipInterfaces ( ) const

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

Precondition
IsLeader()

Definition at line 3014 of file WaveTrack.cpp.

3015{
3016 // We're constructing possibly wide clips here, and for this we need to have
3017 // access to the other channel-tracks.
3018 assert(IsLeader());
3019 const auto pOwner = GetOwner();
3020 ClipConstHolders wideClips;
3021 wideClips.reserve(mClips.size());
3022 for (auto clipIndex = 0u; clipIndex < mClips.size(); ++clipIndex)
3023 {
3024 const auto leftClip = mClips[clipIndex];
3025 WaveClipHolder rightClip;
3026 if (NChannels() == 2u && pOwner)
3027 {
3028 const auto& rightClips =
3029 (*TrackList::Channels(this).rbegin())->mClips;
3030 // This is known to have potential for failure for stereo tracks with
3031 // misaligned left/right clips - see
3032 // https://github.com/audacity/audacity/issues/4791.
3033 // If what you are trying to do is something else and this fails,
3034 // please report.
3035 assert(clipIndex < rightClips.size());
3036 if (clipIndex < rightClips.size())
3037 rightClip = rightClips[clipIndex];
3038 }
3039 wideClips.emplace_back(
3040 std::make_shared<WideClip>(leftClip, std::move(rightClip)));
3041 }
3042 return wideClips;
3043}
std::vector< std::shared_ptr< const ClipInterface > > ClipConstHolders

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 694 of file WaveTrack.h.

694{ return mClips; }

Referenced by ClearAndPasteOne(), WaveTrackUtilities::HasStretch(), 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 698 of file WaveTrack.h.

699 { 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 3701 of file WaveTrack.cpp.

3702{
3703 assert(t0 <= t1);
3704 WaveClipConstHolders intersectingClips;
3705 for (const auto& clip : mClips)
3706 if (clip->IntersectsPlayRegion(t0, t1))
3707 intersectingClips.push_back(clip);
3708 return intersectingClips;
3709}

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 708 of file WaveTrack.cpp.

709{
711
712 if (name.empty() || ( name == DefaultName.MSGID() ))
713 // When nothing was specified,
714 // the default-default is whatever translation of...
715 /* i18n-hint: The default name for an audio track. */
716 return DefaultName.Translation();
717 else
718 return name;
719}
static auto DefaultName
Definition: WaveTrack.cpp:704
StringSetting AudioTrackNameSetting
Definition: WaveTrack.cpp:4528
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:211

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 3050 of file WaveTrack.cpp.

3051{
3052 return ChannelGroup::GetEndTime();
3053}
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(), ApplyStretchRatio(), 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 3740 of file WaveTrack.cpp.

3741{
3742 auto pTrack = this;
3743 if (GetOwner())
3744 // Substitute the leader track
3745 pTrack = *TrackList::Channels(this).begin();
3746 WaveClip* clip = pTrack->GetClipAtTime(time);
3747 if (clip)
3748 return clip->GetEnvelope();
3749 else
3750 return NULL;
3751}
Envelope * GetEnvelope()
Definition: WaveClip.h:388

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 3580 of file WaveTrack.cpp.

3582{
3583 auto pTrack = this;
3584 if (GetOwner())
3585 // Substitute the leader track
3586 pTrack = *TrackList::Channels(this).begin();
3587
3588 if (backwards)
3589 t0 -= bufferLen / GetRate();
3590 // The output buffer corresponds to an unbroken span of time which the callers expect
3591 // to be fully valid. As clips are processed below, the output buffer is updated with
3592 // envelope values from any portion of a clip, start, end, middle, or none at all.
3593 // Since this does not guarantee that the entire buffer is filled with values we need
3594 // to initialize the entire buffer to a default value.
3595 //
3596 // This does mean that, in the cases where a usable clip is located, the buffer value will
3597 // be set twice. Unfortunately, there is no easy way around this since the clips are not
3598 // stored in increasing time order. If they were, we could just track the time as the
3599 // buffer is filled.
3600 for (decltype(bufferLen) i = 0; i < bufferLen; i++)
3601 {
3602 buffer[i] = 1.0;
3603 }
3604
3605 double startTime = t0;
3606 const auto rate = GetRate();
3607 auto tstep = 1.0 / rate;
3608 double endTime = t0 + tstep * bufferLen;
3609 for (const auto &clip: pTrack->mClips)
3610 {
3611 // IF clip intersects startTime..endTime THEN...
3612 auto dClipStartTime = clip->GetPlayStartTime();
3613 auto dClipEndTime = clip->GetPlayEndTime();
3614 if ((dClipStartTime < endTime) && (dClipEndTime > startTime))
3615 {
3616 auto rbuf = buffer;
3617 auto rlen = bufferLen;
3618 auto rt0 = t0;
3619
3620 if (rt0 < dClipStartTime)
3621 {
3622 // This is not more than the number of samples in
3623 // (endTime - startTime) which is bufferLen:
3624 auto nDiff = (sampleCount)floor((dClipStartTime - rt0) * rate + 0.5);
3625 auto snDiff = nDiff.as_size_t();
3626 rbuf += snDiff;
3627 wxASSERT(snDiff <= rlen);
3628 rlen -= snDiff;
3629 rt0 = dClipStartTime;
3630 }
3631
3632 if (rt0 + rlen*tstep > dClipEndTime)
3633 {
3634 auto nClipLen = clip->GetPlayEndSample() - clip->GetPlayStartSample();
3635
3636 if (nClipLen <= 0) // Testing for bug 641, this problem is consistently '== 0', but doesn't hurt to check <.
3637 return;
3638
3639 // This check prevents problem cited in http://bugzilla.audacityteam.org/show_bug.cgi?id=528#c11,
3640 // Gale's cross_fade_out project, which was already corrupted by bug 528.
3641 // This conditional prevents the previous write past the buffer end, in clip->GetEnvelope() call.
3642 // Never increase rlen here.
3643 // PRL bug 827: rewrote it again
3644 rlen = limitSampleBufferSize( rlen, nClipLen );
3645 rlen = std::min(rlen, size_t(floor(0.5 + (dClipEndTime - rt0) / tstep)));
3646 }
3647 // Samples are obtained for the purpose of rendering a wave track,
3648 // so quantize time
3649 clip->GetEnvelope()->GetValues(rbuf, rlen, rt0, tstep);
3650 }
3651 }
3652 if (backwards)
3653 std::reverse(buffer, buffer + bufferLen);
3654}

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 2970 of file WaveTrack.cpp.

2971{
2972 assert(IsLeader());
2973 for (const auto pChannel : TrackList::Channels(this))
2974 for (const auto &clip : pChannel->mClips)
2975 for (size_t ii = 0, width = clip->GetWidth(); ii < width; ++ii)
2976 if (clip->GetSequence(ii)->GetErrorOpening())
2977 return XO("A track has a corrupted sample sequence.");
2978
2979 return {};
2980}

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 3267 of file WaveTrack.cpp.

3269{
3270 const auto clip = GetClipAtTime(t);
3271 if (!clip)
3272 return false;
3273 clip->GetFloatAtTime(
3274 t - clip->GetPlayStartTime(), iChannel, value, mayThrow);
3275 return true;
3276}

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:3134

◆ 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 3175 of file WaveTrack.cpp.

3178{
3179 const auto numSamplesReadLeft = GetFloatsFromTime(
3180 t, iChannel, buffer, numSideSamples, mayThrow, PlaybackDirection::backward);
3181 const auto numSamplesReadRight = GetFloatsFromTime(
3182 t, iChannel, buffer + numSideSamples, numSideSamples + 1, mayThrow,
3184 return { numSideSamples - numSamplesReadLeft,
3185 numSideSamples + numSamplesReadRight };
3186}
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:3243

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 3243 of file WaveTrack.cpp.

3246{
3247 RoundToNearestClipSample(*this, t);
3248 auto clip = GetClipAtTime(t);
3249 auto numSamplesRead = 0u;
3250 const auto forward = direction == PlaybackDirection::forward;
3251 while (clip)
3252 {
3253 const auto args = GetSampleAccessArgs(
3254 *clip, t, buffer, numSamples, numSamplesRead, forward);
3255 if (!clip->GetSamples(
3256 iChannel, args.offsetBuffer, floatSample, args.start, args.len,
3257 mayThrow))
3258 return 0u;
3259 numSamplesRead += args.len;
3260 if (numSamplesRead >= numSamples)
3261 break;
3262 clip = GetAdjacentClip(*clip, direction);
3263 }
3264 return numSamplesRead;
3265}
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:3656
void RoundToNearestClipSample(const WaveTrack &track, double &t)
Definition: WaveTrack.cpp:3165
SampleAccessArgs< BufferType > GetSampleAccessArgs(const WaveClip &clip, double startOrEndTime, BufferType buffer, size_t totalToRead, size_t alreadyRead, bool forward)
Definition: WaveTrack.cpp:3203

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 1112 of file WaveTrack.cpp.

1113{
1114 return WaveTrackData::Get(*this).GetGain();
1115}

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 2721 of file WaveTrack.cpp.

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

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 528 of file WaveTrack.cpp.

529{
530 IntervalHolder result;
531 for (const auto& interval : Intervals())
532 if (interval->WithinPlayRegion(t))
533 return interval;
534 return nullptr;
535}

References Intervals().

Referenced by ApplyStretchRatio().

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 2992 of file WaveTrack.cpp.

2992 {
2993 if (mClips.empty())
2994 return nullptr;
2995 return std::min_element(
2996 mClips.begin(), mClips.end(),
2997 [](const auto& a, const auto b) {
2998 return a->GetPlayStartTime() < b->GetPlayStartTime();
2999 })
3000 ->get();
3001}

References mClips.

Referenced by PasteOne().

Here is the caller graph for this function:

◆ GetMaxBlockSize()

size_t WaveTrack::GetMaxBlockSize ( ) const

Definition at line 2699 of file WaveTrack.cpp.

2700{
2701 decltype(GetMaxBlockSize()) maxblocksize = 0;
2702 for (const auto &clip : mClips)
2703 for (size_t ii = 0, width = clip->GetWidth(); ii < width; ++ii)
2704 maxblocksize = std::max(maxblocksize,
2705 clip->GetSequence(ii)->GetMaxBlockSize());
2706
2707 if (maxblocksize == 0)
2708 {
2709 // We really need the maximum block size, so create a
2710 // temporary sequence to get it.
2711 maxblocksize =
2713 .GetMaxBlockSize();
2714 }
2715
2716 wxASSERT(maxblocksize > 0);
2717
2718 return maxblocksize;
2719}
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 2788 of file WaveTrack.cpp.

2789{
2790 return PlayableTrack::GetMute();
2791}
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 3712 of file WaveTrack.cpp.

3713{
3714 return const_cast<WaveClip*>(
3715 std::as_const(*this).GetNextClip(clip, direction));
3716}

◆ 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 3688 of file WaveTrack.cpp.

3690{
3691 const auto clips = SortedClipArray();
3692 const auto p = std::find(clips.begin(), clips.end(), &clip);
3693 if (p == clips.end())
3694 return nullptr;
3695 else if (direction == PlaybackDirection::forward)
3696 return p == clips.end() - 1 ? nullptr : *(p + 1);
3697 else
3698 return p == clips.begin() ? nullptr : *(p - 1);
3699}

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 521 of file WaveTrack.cpp.

523{
524 return std::const_pointer_cast<Interval>(
525 std::as_const(*this).GetNextInterval(interval, searchDirection));
526}

◆ 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 499 of file WaveTrack.cpp.

500{
501 std::shared_ptr<const Interval> result;
502 auto bestMatchTime = searchDirection == PlaybackDirection::forward
503 ? std::numeric_limits<double>::max()
504 : std::numeric_limits<double>::lowest();
505
506 for(const auto& other : Intervals())
507 {
508 if((searchDirection == PlaybackDirection::forward &&
509 (other->Start() > interval.Start() && other->Start() < bestMatchTime))
510 ||
511 (searchDirection == PlaybackDirection::backward &&
512 (other->Start() < interval.Start() && other->Start() > bestMatchTime)))
513 {
514 result = other;
515 bestMatchTime = other->Start();
516 }
517 }
518 return result;
519}
STL namespace.

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

Referenced by ApplyStretchRatio(), anonymous_namespace{WaveClipAdjustBorderHandle.cpp}::GetLeftAdjustLimit(), anonymous_namespace{WaveClipAdjustBorderHandle.cpp}::GetRightAdjustLimit(), and ChangeClipSpeedDialog::SetClipSpeedFromDialog().

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 3831 of file WaveTrack.cpp.

3832{
3833 return mClips.size();
3834}

References mClips.

Referenced by ApplyStretchRatio(), and PasteOne().

Here is the caller graph for this function:

◆ GetNumClips() [2/2]

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

Definition at line 3836 of file WaveTrack.cpp.

3837{
3838 const auto clips = SortedClipArray();
3839 // Find first position where the comparison is false
3840 const auto firstIn = std::lower_bound(clips.begin(), clips.end(), t0,
3841 [](const auto& clip, double t0) {
3842 return clip->GetPlayEndTime() <= t0;
3843 });
3844 // Find first position where the comparison is false
3845 const auto firstOut = std::lower_bound(firstIn, clips.end(), t1,
3846 [](const auto& clip, double t1) {
3847 return clip->GetPlayStartTime() < t1;
3848 });
3849 return std::distance(firstIn, firstOut);
3850}

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 3359 of file WaveTrack.cpp.

3363{
3364 if (backwards)
3365 start -= len;
3366 // Simple optimization: When this buffer is completely contained within one clip,
3367 // don't clear anything (because we won't have to). Otherwise, just clear
3368 // everything to be on the safe side.
3369 bool doClear = true;
3370 bool result = true;
3371 sampleCount samplesCopied = 0;
3372 for (const auto &clip: mClips)
3373 {
3374 if (start >= clip->GetPlayStartSample() && start+len <= clip->GetPlayEndSample())
3375 {
3376 doClear = false;
3377 break;
3378 }
3379 }
3380 if (doClear)
3381 {
3382 // Usually we fill in empty space with zero
3383 if (fill == FillFormat::fillZero)
3384 ClearSamples(buffer, format, 0, len);
3385 // but we don't have to.
3386 else if (fill == FillFormat::fillTwo)
3387 {
3388 wxASSERT( format==floatSample );
3389 float * pBuffer = (float*)buffer;
3390 for(size_t i=0;i<len;i++)
3391 pBuffer[i]=2.0f;
3392 }
3393 else
3394 {
3395 wxFAIL_MSG(wxT("Invalid fill format"));
3396 }
3397 }
3398
3399 // Iterate the clips. They are not necessarily sorted by time.
3400 for (const auto &clip: mClips)
3401 {
3402 auto clipStart = clip->GetPlayStartSample();
3403 auto clipEnd = clip->GetPlayEndSample();
3404
3405 if (clipEnd > start && clipStart < start+len)
3406 {
3407 // Yes, exact comparison
3408 if (clip->GetStretchRatio() != 1.0)
3409 return false;
3410
3411 // Clip sample region and Get/Put sample region overlap
3412 auto samplesToCopy =
3413 std::min( start+len - clipStart, clip->GetVisibleSampleCount() );
3414 auto startDelta = clipStart - start;
3415 decltype(startDelta) inclipDelta = 0;
3416 if (startDelta < 0)
3417 {
3418 inclipDelta = -startDelta; // make positive value
3419 samplesToCopy -= inclipDelta;
3420 // samplesToCopy is now either len or
3421 // (clipEnd - clipStart) - (start - clipStart)
3422 // == clipEnd - start > 0
3423 // samplesToCopy is not more than len
3424 //
3425 startDelta = 0;
3426 // startDelta is zero
3427 }
3428 else {
3429 // startDelta is nonnegative and less than len
3430 // samplesToCopy is positive and not more than len
3431 }
3432
3433 if (!clip->GetSamples(0,
3434 (samplePtr)(((char*)buffer) +
3435 startDelta.as_size_t() *
3437 format, inclipDelta, samplesToCopy.as_size_t(), mayThrow ))
3438 result = false;
3439 else
3440 samplesCopied += samplesToCopy;
3441 }
3442 }
3443 if( pNumWithinClips )
3444 *pNumWithinClips = samplesCopied;
3445 if (result == true && backwards)
3446 ReverseSamples(buffer, format, 0, len);
3447 return result;
3448}
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 1130 of file WaveTrack.cpp.

1131{
1132 return WaveTrackData::Get(*this).GetPan();
1133}

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 1085 of file WaveTrack.cpp.

1086{
1087 return WaveTrackData::Get(*this).GetRate();
1088}

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(), 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 3003 of file WaveTrack.cpp.

3003 {
3004 if (mClips.empty())
3005 return nullptr;
3006 return std::max_element(
3007 mClips.begin(), mClips.end(),
3008 [](const auto& a, const auto b) {
3009 return a->GetPlayEndTime() < b->GetPlayEndTime();
3010 })
3011 ->get();
3012}

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 1220 of file WaveTrack.cpp.

1221{
1222 return WaveTrackData::Get(*this).GetSampleFormat();
1223}

References BasicUI::Get().

Referenced by CopyOne(), CreateClip(), EmptyCopy(), GetMaxBlockSize(), InsertSilence(), 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 3451 of file WaveTrack.cpp.

3452{
3453 assert(IsLeader());
3455 for (const auto& channel : Channels()) {
3456 result.push_back(channel->GetSampleView(t0, t1, mayThrow));
3457 }
3458 return result;
3459}
std::vector< std::vector< AudioSegmentSampleView > > ChannelGroupSampleView
Definition: MixerBoard.h:35
auto Channels()
Definition: WaveTrack.h:272

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 1197 of file WaveTrack.cpp.

1198{
1199 assert(IsLeader());
1200 sampleCount result{ 0 };
1201
1202 for (const auto pChannel : TrackList::Channels(this))
1203 for (const auto& clip : pChannel->mClips)
1204 result += clip->GetSequenceSamplesCount();
1205
1206 return result;
1207}

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 2793 of file WaveTrack.cpp.

2794{
2795 return PlayableTrack::GetSolo();
2796}
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 3045 of file WaveTrack.cpp.

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

References ChannelGroup::GetStartTime().

Referenced by ApplyStretchRatio(), 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 951 of file WaveTrack.cpp.

952{
953 return typeInfo();
954}

References typeInfo().

Here is the call graph for this function:

◆ GetVisibleSampleCount()

sampleCount WaveTrack::GetVisibleSampleCount ( ) const

Definition at line 1187 of file WaveTrack.cpp.

1188{
1189 sampleCount result{ 0 };
1190
1191 for (const auto& clip : mClips)
1192 result += clip->GetVisibleSampleCount();
1193
1194 return result;
1195}

References mClips.

◆ GetWaveColorIndex()

int WaveTrack::GetWaveColorIndex ( ) const

Definition at line 1171 of file WaveTrack.cpp.

1172{
1173 return WaveTrackData::Get(*this).GetWaveColorIndex();
1174}

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 795 of file WaveTrack.cpp.

796{
797 return 1;
798}

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 1909 of file WaveTrack.cpp.

1911{
1912 // For debugging, use an ASSERT so that we stop
1913 // closer to the problem.
1914 wxASSERT( t1 >= t0 );
1915 if (t1 < t0)
1917
1918 t0 = SnapToSample(t0);
1919 t1 = SnapToSample(t1);
1920
1921 WaveClipPointers clipsToDelete;
1922 WaveClipHolders clipsToAdd;
1923
1924 // We only add cut lines when deleting in the middle of a single clip
1925 // The cut line code is not really prepared to handle other situations
1926 if (addCutLines)
1927 {
1928 for (const auto &clip : mClips)
1929 {
1930 if (clip->PartlyWithinPlayRegion(t0, t1))
1931 {
1932 addCutLines = false;
1933 break;
1934 }
1935 }
1936 }
1937
1938 for (const auto &clip : mClips)
1939 {
1940 if (clip->CoversEntirePlayRegion(t0, t1))
1941 {
1942 // Whole clip must be deleted - remember this
1943 clipsToDelete.push_back(clip.get());
1944 }
1945 else if (clip->IntersectsPlayRegion(t0, t1))
1946 {
1947 // Clip data is affected by command
1948 if (addCutLines)
1949 {
1950 // Don't modify this clip in place, because we want a strong
1951 // guarantee, and might modify another clip
1952 clipsToDelete.push_back( clip.get() );
1953 auto newClip =
1954 std::make_shared<WaveClip>(*clip, mpFactory, true);
1955 newClip->ClearAndAddCutLine( t0, t1 );
1956 clipsToAdd.push_back( std::move( newClip ) );
1957 }
1958 else
1959 {
1960 if (split || clearByTrimming) {
1961 // Three cases:
1962
1963 if (clip->BeforePlayRegion(t0)) {
1964 // Delete from the left edge
1965
1966 // Don't modify this clip in place, because we want a strong
1967 // guarantee, and might modify another clip
1968 clipsToDelete.push_back( clip.get() );
1969 auto newClip =
1970 std::make_shared<WaveClip>(*clip, mpFactory, true);
1971 newClip->TrimLeft(t1 - clip->GetPlayStartTime());
1972 if (!split)
1973 // If this is not a split-cut, where things are left in
1974 // place, we need to reposition the clip.
1975 newClip->ShiftBy(t0 - t1);
1976 clipsToAdd.push_back( std::move( newClip ) );
1977 }
1978 else if (clip->AfterPlayRegion(t1)) {
1979 // Delete to right edge
1980
1981 // Don't modify this clip in place, because we want a strong
1982 // guarantee, and might modify another clip
1983 clipsToDelete.push_back( clip.get() );
1984 auto newClip =
1985 std::make_shared<WaveClip>(*clip, mpFactory, true);
1986 newClip->TrimRight(clip->GetPlayEndTime() - t0);
1987
1988 clipsToAdd.push_back( std::move( newClip ) );
1989 }
1990 else {
1991 // Delete in the middle of the clip...we actually create two
1992 // NEW clips out of the left and right halves...
1993
1994 auto leftClip =
1995 std::make_shared<WaveClip>(*clip, mpFactory, true);
1996 leftClip->TrimRight(clip->GetPlayEndTime() - t0);
1997 clipsToAdd.push_back(std::move(leftClip));
1998
1999 auto rightClip =
2000 std::make_shared<WaveClip>(*clip, mpFactory, true);
2001 rightClip->TrimLeft(t1 - clip->GetPlayStartTime());
2002 if (!split)
2003 // If this is not a split-cut, where things are left in
2004 // place, we need to reposition the clip.
2005 rightClip->ShiftBy(t0 - t1);
2006 clipsToAdd.push_back(std::move(rightClip));
2007
2008 clipsToDelete.push_back(clip.get());
2009 }
2010 }
2011 else {
2012 // (We are not doing a split cut)
2013
2014 // Don't modify this clip in place, because we want a strong
2015 // guarantee, and might modify another clip
2016 clipsToDelete.push_back( clip.get() );
2017 auto newClip =
2018 std::make_shared<WaveClip>(*clip, mpFactory, true);
2019
2020 // clip->Clear keeps points < t0 and >= t1 via Envelope::CollapseRegion
2021 newClip->Clear(t0,t1);
2022
2023 clipsToAdd.push_back( std::move( newClip ) );
2024 }
2025 }
2026 }
2027 }
2028
2029 // Only now, change the contents of this track
2030 // use No-fail-guarantee for the rest
2031
2032 const auto moveClipsLeft = !split && GetEditClipsCanMove();
2033 if (moveClipsLeft)
2034 // Clip is "behind" the region -- offset it unless we're splitting
2035 // or we're using the "don't move other clips" mode
2036 for (const auto& clip : mClips)
2037 if (clip->AtOrBeforePlayRegion(t1))
2038 clip->ShiftBy(-(t1 - t0));
2039
2040 for (const auto &clip: clipsToDelete)
2041 {
2042 auto myIt = FindClip(mClips, clip);
2043 if (myIt != mClips.end())
2044 mClips.erase(myIt); // deletes the clip!
2045 else
2046 wxASSERT(false);
2047 }
2048
2049 for (auto &clip: clipsToAdd)
2050 InsertClip(std::move(clip)); // transfer ownership
2051}
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 2865 of file WaveTrack.cpp.

2866{
2867 if ( auto pChild = WaveTrackIORegistry::Get()
2868 .CallObjectAccessor(tag, *this) )
2869 return pChild;
2870
2871 //
2872 // This is legacy code (1.2 and previous) and is not called for NEW projects!
2873 //
2874 if (tag == "sequence" || tag == "envelope")
2875 {
2876 // This is a legacy project, so set the cached offset
2878
2879 // Legacy project file tracks are imported as one single wave clip
2880 if (tag == "sequence")
2881 return NewestOrNewClip()->GetSequence(0);
2882 else if (tag == "envelope")
2883 return NewestOrNewClip()->GetEnvelope();
2884 }
2885
2886 // JKC... for 1.1.0, one step better than what we had, but still badly broken.
2887 // If we see a waveblock at this level, we'd better generate a sequence.
2888 if (tag == "waveblock")
2889 {
2890 // This is a legacy project, so set the cached offset
2892 Sequence *pSeq = NewestOrNewClip()->GetSequence(0);
2893 return pSeq;
2894 }
2895
2896 //
2897 // This is for the NEW file format (post-1.2)
2898 //
2899 if (tag == "waveclip")
2900 {
2901 // Make clips (which don't serialize the rate) consistent with channel rate,
2902 // though the consistency check of channels with each other remains to do.
2903 // Not all `WaveTrackData` fields are properly initialized by now,
2904 // use deserialization helpers.
2905 auto clip = std::make_shared<WaveClip>(1,
2907 const auto xmlHandler = clip.get();
2908 mClips.push_back(std::move(clip));
2909 return xmlHandler;
2910 }
2911
2912 return nullptr;
2913}
int mLegacyRate
used only during deserialization
Definition: WaveTrack.h:1109
sampleFormat mLegacyFormat
used only during deserialization
Definition: WaveTrack.h:1110
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 2853 of file WaveTrack.cpp.

2854{
2855#if 0
2856 // In case we opened a pre-multiclip project, we need to
2857 // simulate closing the waveclip tag.
2858 NewestOrNewClip()->HandleXMLEndTag("waveclip");
2859#else
2860 // File compatibility breaks have intervened long since, and the line above
2861 // would now have undesirable side effects
2862#endif
2863}
void HandleXMLEndTag(const std::string_view &tag) override
Definition: WaveClip.cpp:599

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 2798 of file WaveTrack.cpp.

2799{
2800 if (tag == "wavetrack") {
2801 double dblValue;
2802 long nValue;
2803
2804 for (const auto& pair : attrs)
2805 {
2806 const auto& attr = pair.first;
2807 const auto& value = pair.second;
2808
2809 if (attr == "rate")
2810 {
2811 // mRate is an int, but "rate" in the project file is a float.
2812 if (!value.TryGet(dblValue) ||
2813 (dblValue < 1.0) || (dblValue > 1000000.0)) // allow a large range to be read
2814 return false;
2815
2816 // Defer the setting of rate until LinkConsistencyFix
2817 mLegacyRate = lrint(dblValue);
2818 }
2819 else if (attr == "offset" && value.TryGet(dblValue))
2820 {
2821 // Offset is only relevant for legacy project files. The value
2822 // is cached until the actual WaveClip containing the legacy
2823 // track is created.
2824 mLegacyProjectFileOffset = dblValue;
2825 }
2826 else if (this->WritableSampleTrack::HandleXMLAttribute(attr, value))
2827 {}
2828 else if (this->Track::HandleCommonXMLAttribute(attr, value))
2829 ;
2830 else if (attr == "gain" && value.TryGet(dblValue))
2831 DoSetGain(dblValue);
2832 else if (attr == "pan" && value.TryGet(dblValue) &&
2833 (dblValue >= -1.0) && (dblValue <= 1.0))
2834 DoSetPan(dblValue);
2835 else if (attr == "linked" && value.TryGet(nValue))
2836 SetLinkType(ToLinkType(nValue), false);
2837 else if (attr == "colorindex" && value.TryGet(nValue))
2838 // Don't use SetWaveColorIndex as it sets the clips too.
2839 WaveTrackData::Get(*this).SetWaveColorIndex(nValue);
2840 else if (attr == "sampleformat" && value.TryGet(nValue) &&
2842 {
2843 //Remember sample format until consistency check is performed.
2844 SetLegacyFormat(static_cast<sampleFormat>(nValue));
2845 }
2846 } // while
2847 return true;
2848 }
2849
2850 return false;
2851}
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:1135
void SetLegacyFormat(sampleFormat format)
Definition: WaveTrack.cpp:2741
void DoSetGain(float value)
Definition: WaveTrack.cpp:1117
#define lrint(dbl)
Definition: float_cast.h:169
Track::LinkType ToLinkType(int value)
Definition: WaveTrack.cpp:685

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 4382 of file WaveTrack.cpp.

4383{
4384 assert(IsLeader());
4385 for (const auto pChannel : TrackList::Channels(this))
4386 for (const auto& clip : pChannel->GetClips())
4387 if (clip->GetTrimLeft() != 0 || clip->GetTrimRight() != 0)
4388 return true;
4389 return false;
4390}

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 3569 of file WaveTrack.cpp.

3570{
3571 auto pTrack = this;
3572 if (GetOwner())
3573 // Substitute the leader track
3574 pTrack = *TrackList::Channels(this).begin();
3575 auto &clips = pTrack->GetClips();
3576 return std::all_of(clips.begin(), clips.end(),
3577 [](const auto &pClip){ return pClip->GetEnvelope()->IsTrivial(); });
3578}

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 823 of file WaveTrack.cpp.

824{
826 mpFactory = orig.mpFactory;
827}
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)
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

Definition at line 2338 of file WaveTrack.cpp.

2339{
2340 if(!clip->GetIsPlaceholder() && clip->IsEmpty())
2341 return false;
2342
2343 const auto& tempo = GetProjectTempo();
2344 if (tempo.has_value())
2345 clip->OnProjectTempoChange(std::nullopt, *tempo);
2346 mClips.push_back(std::move(clip));
2347
2348 return true;
2349}

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 4118 of file WaveTrack.cpp.

4119{
4120 assert(IsLeader());
4121 auto channel = 0;
4122 for (const auto pChannel : TrackList::Channels(this))
4123 {
4124 const auto clip = interval->GetClip(channel++);
4125 if (clip)
4126 pChannel->InsertClip(clip);
4127 }
4128}

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 2434 of file WaveTrack.cpp.

2435{
2436 assert(IsLeader());
2437 // Nothing to do, if length is zero.
2438 // Fixes Bug 1626
2439 if (len == 0)
2440 return;
2441 if (len <= 0)
2443
2444 for (const auto pChannel : TrackList::Channels(this)) {
2445 auto &clips = pChannel->mClips;
2446 if (clips.empty()) {
2447 // Special case if there is no clip yet
2448 // TODO wide wave tracks -- match clip width
2449 auto clip = std::make_shared<WaveClip>(1,
2451 clip->InsertSilence(0, len);
2452 // use No-fail-guarantee
2453 pChannel->InsertClip(move(clip));
2454 }
2455 else
2456 {
2457 // Assume at most one clip contains t
2458 const auto end = clips.end();
2459 const auto it = std::find_if(clips.begin(), end,
2460 [&](const WaveClipHolder &clip) { return clip->SplitsPlayRegion(t); } );
2461
2462 // use Strong-guarantee
2463 if (it != end)
2464 it->get()->InsertSilence(t, len);
2465
2466 // use No-fail-guarantee
2467 for (const auto &clip : clips)
2468 if (clip->BeforePlayRegion(t))
2469 clip->ShiftBy(len);
2470 }
2471 }
2472}

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 1026 of file WaveTrack.h.

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

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

Here is the caller graph for this function:

◆ Intervals() [2/2]

auto WaveTrack::Intervals ( ) const
inline

Definition at line 1027 of file WaveTrack.h.

1027{ 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 1238 of file WaveTrack.cpp.

1239{
1240 if (t0 > t1)
1241 return true;
1242
1243 //wxPrintf("Searching for overlap in %.6f...%.6f\n", t0, t1);
1244 for (const auto &clip : mClips)
1245 {
1246 if (clip->IntersectsPlayRegion(t0, t1)) {
1247 //wxPrintf("Overlapping clip: %.6f...%.6f\n",
1248 // clip->GetStartTime(),
1249 // clip->GetEndTime());
1250 // We found a clip that overlaps this region
1251 return false;
1252 }
1253 }
1254 //wxPrintf("No overlap found\n");
1255
1256 // Otherwise, no clips overlap this region
1257 return true;
1258}

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 2565 of file WaveTrack.cpp.

2567{
2568 assert(IsLeader());
2569 // Merge all WaveClips overlapping selection into one
2570 const auto intervals = Intervals();
2571 std::vector<IntervalHolder> intervalsToJoin;
2572 for (auto interval : intervals)
2573 if (interval->IntersectsPlayRegion(t0, t1))
2574 intervalsToJoin.push_back(interval);
2575 if (intervalsToJoin.size() < 2u)
2576 return;
2577 if (std::any_of(
2578 intervalsToJoin.begin() + 1, intervalsToJoin.end(),
2579 [first =
2580 intervalsToJoin[0]->GetStretchRatio()](const auto& interval) {
2581 return first != interval->GetStretchRatio();
2582 }))
2583 ApplyStretchRatioOnIntervals(intervalsToJoin, reportProgress);
2584
2585 for (const auto pChannel : TrackList::Channels(this))
2586 JoinOne(*pChannel, t0, t1);
2587}
static void JoinOne(WaveTrack &track, double t0, double t1)
Definition: WaveTrack.cpp:2589

References ApplyStretchRatioOnIntervals(), 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 2589 of file WaveTrack.cpp.

2591{
2592 WaveClipPointers clipsToDelete;
2593 WaveClip* newClip{};
2594
2595 const auto rate = track.GetRate();
2596 auto &clips = track.mClips;
2597 for (const auto &clip: clips) {
2598 if (clip->IntersectsPlayRegion(t0, t1)) {
2599 // Put in sorted order
2600 auto it = clipsToDelete.begin(), end = clipsToDelete.end();
2601 for (; it != end; ++it)
2602 if ((*it)->GetPlayStartTime() > clip->GetPlayStartTime())
2603 break;
2604 //wxPrintf("Insert clip %.6f at position %d\n", clip->GetStartTime(), i);
2605 clipsToDelete.insert(it, clip.get());
2606 }
2607 }
2608
2609 //if there are no clips to DELETE, nothing to do
2610 if (clipsToDelete.empty())
2611 return;
2612
2613 auto t = clipsToDelete[0]->GetPlayStartTime();
2614 //preserve left trim data if any
2615 newClip = track.CreateClip(clipsToDelete[0]->GetSequenceStartTime(),
2616 clipsToDelete[0]->GetName());
2617
2618 for (auto clip : clipsToDelete) {
2619 // wxPrintf("t=%.6f adding clip (offset %.6f, %.6f ... %.6f)\n",
2620 // t, clip->GetOffset(), clip->GetStartTime(),
2621 // clip->GetEndTime());
2622
2623 if (clip->GetPlayStartTime() - t > (1.0 / rate))
2624 {
2625 double addedSilence = (clip->GetPlayStartTime() - t);
2626 // wxPrintf("Adding %.6f seconds of silence\n");
2627 auto offset = clip->GetPlayStartTime();
2628 auto value = clip->GetEnvelope()->GetValue(offset);
2629 newClip->AppendSilence(addedSilence, value);
2630 t += addedSilence;
2631 }
2632
2633 // wxPrintf("Pasting at %.6f\n", t);
2634 bool success = newClip->Paste(t, *clip);
2635 assert(success); // promise of CreateClip
2636
2637 t = newClip->GetPlayEndTime();
2638
2639 auto it = FindClip(clips, clip);
2640 clips.erase(it); // deletes the clip
2641 }
2642}
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:3760

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 875 of file WaveTrack.cpp.

876{
877 assert(!doFix || IsLeader());
878
879
880 const auto removeZeroClips = [](WaveClipHolders& clips) {
881 // Check for zero-length clips and remove them
882 for (auto it = clips.begin(); it != clips.end();)
883 {
884 if ((*it)->IsEmpty())
885 it = clips.erase(it);
886 else
887 ++it;
888 }
889 };
890
892
893 const auto linkType = GetLinkType();
894 if (linkType != LinkType::None) {
895 auto next = *TrackList::Channels(this).first.advance(1);
896 if (next == nullptr) {
897 //next track is absent or not a wave track, fix and report error
898 if (doFix) {
899 wxLogWarning(L"Right track %s is expected to be a WaveTrack."
900 "\n Removing link from left wave track %s.",
901 next->GetName(), GetName());
903 }
904 err = true;
905 }
906 else if (doFix) {
907 // non-error upgrades happen here
908 if (!AreAligned(SortedClipArray(), next->SortedClipArray()) ||
910 {
912 }
913 else
914 {
916 // Be sure to lose any right channel group data that might
917 // have been made during during deserialization of the channel
918 // before joining it
919 next->DestroyGroupData();
920 //clean up zero clips only after alignment check has completed
921 //this can't break alignment as there should be a "twin"
922 //in the right channel which will also be removed, otherwise
923 //track will be unlinked
924 removeZeroClips(next->mClips);
925 }
926 }
927 }
928 if (doFix) {
929 // More non-error upgrading
930 // Set the common channel group rate from the leader's rate
931 if (mLegacyRate > 0)
932 {
934 mLegacyRate = 0;
936 WaveTrackData::Get(*this).SetSampleFormat(mLegacyFormat);
937 }
938 removeZeroClips(mClips);
939 }
940 return !err;
941}
@ 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:1090
bool FormatConsistencyCheck() const
Whether all tracks in group and all clips have a common sample format.
Definition: WaveTrack.cpp:2327
bool RateConsistencyCheck() const
Whether all clips of a leader track have a common rate.
Definition: WaveTrack.cpp:2306
bool AreAligned(const WaveClipPointers &a, const WaveClipPointers &b)
Definition: WaveTrack.cpp:666

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 1061 of file WaveTrack.cpp.

1062{
1063 auto name = originalName;
1064 for (auto i = 1;; ++i)
1065 {
1066 if (FindClipByName(name) == nullptr)
1067 return name;
1068 //i18n-hint Template for clip name generation on copy-paste
1069 name = XC("%s.%i", "clip name template").Format(originalName, i).Translation();
1070 }
1071}
#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:1004

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 1073 of file WaveTrack.cpp.

1074{
1075 auto name = GetName();
1076 for (auto i = 1;; ++i)
1077 {
1078 if (FindClipByName(name) == nullptr)
1079 return name;
1080 //i18n-hint Template for clip name generation on inserting new empty clip
1081 name = XC("%s %i", "clip name template").Format(GetName(), i).Translation();
1082 }
1083}

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 4065 of file WaveTrack.cpp.

4066{
4067 const auto channels = TrackList::Channels(this);
4068 return std::all_of(channels.begin(), channels.end(),
4069 [&](const auto pChannel){
4070 return pChannel->MergeOneClipPair(clipidx1, clipidx2); });
4071}

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 4074 of file WaveTrack.cpp.

4075{
4076 WaveClip* clip1 = GetClipByIndex(clipidx1);
4077 WaveClip* clip2 = GetClipByIndex(clipidx2);
4078
4079 if (!clip1 || !clip2) // Could happen if one track of a linked pair had a split and the other didn't.
4080 return false; // Don't throw, just do nothing.
4081
4082 const auto stretchRatiosEqual = clip1->HasEqualStretchRatio(*clip2);
4083 if (!stretchRatiosEqual)
4084 return false;
4085
4086 // Append data from second clip to first clip
4087 // use Strong-guarantee
4088 bool success = clip1->Paste(clip1->GetPlayEndTime(), *clip2);
4089 assert(success); // assuming clips of the same track must have same width
4090
4091 // use No-fail-guarantee for the rest
4092 // Delete second clip
4093 auto it = FindClip(mClips, clip2);
4094 mClips.erase(it);
4095
4096 return true;
4097}
bool HasEqualStretchRatio(const WaveClip &other) const
Definition: WaveClip.cpp:349

References anonymous_namespace{WaveTrack.cpp}::FindClip(), GetClipByIndex(), WaveClip::GetPlayEndTime(), WaveClip::HasEqualStretchRatio(), 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 1355 of file WaveTrack.cpp.

1356{
1357 assert(!GetOwner());
1358
1359 auto result = Duplicate();
1360 result->MakeMultiChannelTrack(**result->begin(), 2);
1361
1362 return result;
1363}

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 845 of file WaveTrack.cpp.

846{
847 double delta = origin - GetStartTime();
848 assert(IsLeader());
849 for (const auto pChannel : TrackList::Channels(this)) {
850 for (const auto &clip : pChannel->mClips)
851 // assume No-fail-guarantee
852 clip->ShiftBy(delta);
853 }
854 WaveTrackData::Get(*this).SetOrigin(origin);
855}

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 800 of file WaveTrack.cpp.

801{
802 if (IsLeader() && GetOwner()) {
803 auto result = TrackList::NChannels(*this);
804 assert(result > 0);
805 return result;
806 }
807 else
808 return 1;
809}

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::GetStretchRenderedCopy(), PasteWaveTrackAtSameTempo(), NyquistEffect::Process(), EffectReverse::Process(), Reinit(), WaveTrack::Interval::SetTrimLeft(), WaveTrack::Interval::SetTrimRight(), WaveTrack::Interval::StretchLeftTo(), WaveTrack::Interval::StretchRatioEquals(), 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 767 of file WaveTrack.cpp.

768{
769 auto &trackFactory = WaveTrackFactory::Get( project );
770 auto &tracks = TrackList::Get( project );
771 auto result = tracks.Add(trackFactory.Create());
772 result->AttachedTrackObjects::BuildAll();
773 return result;
774}
const auto tracks
const auto project
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:347
static WaveTrackFactory & Get(AudacityProject &project)
Definition: WaveTrack.cpp:4476

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 3780 of file WaveTrack.cpp.

3781{
3782 if (mClips.empty()) {
3783 return CreateClip(WaveTrackData::Get(*this).GetOrigin(), MakeNewClipName());
3784 }
3785 else
3786 return mClips.back().get();
3787}
wxString MakeNewClipName() const
Definition: WaveTrack.cpp:1073

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 982 of file WaveTrack.cpp.

983{
984 return mClips.size();
985}

References mClips.

Referenced by 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 364 of file Track.cpp.

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

◆ Paste() [3/3]

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

Implements Track.

Definition at line 2393 of file WaveTrack.cpp.

2394{
2395 assert(IsLeader()); // pre of Track::Paste
2396 if (const auto other = dynamic_cast<const WaveTrack*>(&src))
2397 {
2398 // Currently `Paste` isn't used by code that wants the newer "don't merge
2399 // when copy/pasting" behaviour ...
2400 constexpr auto merge = true;
2401 PasteWaveTrack(t0, *other, merge);
2402 }
2403 else
2404 // THROW_INCONSISTENCY_EXCEPTION; // ?
2405 (void)0;// Empty if intentional.
2406}

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 961 of file WaveTrack.cpp.

963{
964 assert(IsLeader());
965 auto &trackFactory = WaveTrackFactory::Get(project);
966 auto &pSampleBlockFactory = trackFactory.GetSampleBlockFactory();
967 Track::Holder pFirstTrack;
968 const WaveTrack *pFirstChannel{};
969 for (const auto pChannel : TrackList::Channels(this)) {
970 auto pNewTrack = pChannel->EmptyCopy(pSampleBlockFactory);
971 list.Add(pNewTrack);
972 assert(pNewTrack->IsLeader() == pChannel->IsLeader());
973 if (!pFirstTrack) {
974 pFirstTrack = pNewTrack;
975 pFirstChannel = pChannel;
976 }
977 }
978 pFirstTrack->Paste(0.0, *pFirstChannel);
979 return pFirstTrack;
980}
std::shared_ptr< Track > Holder
Definition: Track.h:225
TrackKind * Add(const std::shared_ptr< TrackKind > &t)
Definition: Track.h:1183

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 2131 of file WaveTrack.cpp.

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

2101{
2102 // Get a modifiable copy of `src` because it may come from another project
2103 // with different tempo, making boundary queries incorrect.
2104 const auto& tempo = GetProjectTempo();
2105 if (!tempo.has_value())
2107 WaveTrack* copy;
2108 const auto copyHolder = other.DuplicateWithOtherTempo(*tempo, copy);
2109 PasteWaveTrackAtSameTempo(t0, *copy, merge);
2110}
void PasteWaveTrackAtSameTempo(double t0, const WaveTrack &other, bool merge)
Definition: WaveTrack.cpp:2112

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 2112 of file WaveTrack.cpp.

2114{
2115 assert(IsLeader());
2116 const auto otherNChannels = other.NChannels();
2117 assert(otherNChannels == 1 || otherNChannels == NChannels());
2118 assert(
2119 GetProjectTempo().has_value() &&
2120 GetProjectTempo() == other.GetProjectTempo());
2121 const auto startTime = other.GetStartTime();
2122 const auto endTime = other.GetEndTime();
2123 auto iter = TrackList::Channels(&other).begin();
2124 for (const auto pChannel : TrackList::Channels(this)) {
2125 PasteOne(*pChannel, t0, **iter, startTime, endTime, merge);
2126 if (otherNChannels > 1)
2127 ++iter;
2128 }
2129}

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 696 of file WaveTrack.cpp.

697{
699 return std::max(ProjectRate::Get(project).GetRate(),
700 tracks.Any<const WaveTrack>().max(&WaveTrack::GetRate))
701 / 2.0;
702}
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 2306 of file WaveTrack.cpp.

2307{
2308 assert(IsLeader());
2309
2310 // The channels and all clips in them should have the same sample rate.
2311 std::optional<double> oRate;
2312 auto channels = TrackList::Channels(this);
2313 return std::all_of(channels.begin(), channels.end(),
2314 [&](const WaveTrack *pTrack){
2315 if (!pTrack)
2316 return false;
2317
2318 const auto rate = pTrack->mLegacyRate;
2319 if (!oRate)
2320 oRate = rate;
2321 else if (*oRate != rate)
2322 return false;
2323 return true;
2324 });
2325}

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 1034 of file WaveTrack.cpp.

1035{
1036 const Track *pTrack = this;
1037 if (const auto pOwner = GetHolder())
1038 pTrack = *pOwner->Find(this);
1039 const ChannelGroup &group = *pTrack;
1040 return const_cast<ChannelGroup&>(group);
1041}
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:1462

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 829 of file WaveTrack.cpp.

830{
831 assert(IsLeader());
832 assert(orig.IsLeader());
833 assert(NChannels() == orig.NChannels());
834 const auto channels = TrackList::Channels(this);
835 auto iter = TrackList::Channels(&orig).begin();
836 for (const auto pChannel : channels)
837 pChannel->Init(**iter++);
838}

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 1879 of file WaveTrack.cpp.

1880{
1881 // Be clear about who owns the clip!!
1882 auto it = FindClip(mClips, clip);
1883 if (it != mClips.end()) {
1884 auto result = std::move(*it); // Array stops owning the clip, before we shrink it
1885 mClips.erase(it);
1886 return result;
1887 }
1888 else
1889 return {};
1890}

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 4049 of file WaveTrack.cpp.

4050{
4051 assert(IsLeader());
4052
4053 bool removed = false;
4054 for (const auto pChannel : TrackList::Channels(this))
4055 for (const auto &clip : pChannel->mClips)
4056 if (clip->RemoveCutLine(cutLinePosition)) {
4057 removed = true;
4058 break;
4059 }
4060
4061 return removed;
4062}

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 4130 of file WaveTrack.cpp.

4131{
4132 assert(IsLeader());
4133 auto channel = 0;
4134 for (const auto pChannel : TrackList::Channels(this))
4135 {
4136 const auto clip = interval->GetClip(channel);
4137 if (clip)
4138 pChannel->RemoveAndReturnClip(clip.get());
4139 ++channel;
4140 }
4141}

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