Audacity 3.2.0
Classes | Public Types | Public Member Functions | Static Public Member Functions | Static Public Attributes | 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

struct  CreateToken
 
struct  Region
 Structure to hold region of a wavetrack and a comparison function for sortability. More...
 

Public Types

using Interval = WaveClip
 
using IntervalHolder = std::shared_ptr< Interval >
 
using IntervalHolders = std::vector< IntervalHolder >
 
using IntervalConstHolder = std::shared_ptr< const Interval >
 
using IntervalConstHolders = std::vector< IntervalConstHolder >
 
using Regions = std::vector< Region >
 
using Holder = std::shared_ptr< WaveTrack >
 
- 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 = ChannelGroupAttachments
 
using Interval = WideChannelGroupInterval
 
- Public Types inherited from Observer::Publisher< WaveTrackMessage >
using message_type = WaveTrackMessage
 
using CallbackReturn = std::conditional_t< true, void, bool >
 
using Callback = std::function< CallbackReturn(const WaveTrackMessage &) >
 Type of functions that can be connected to the Publisher. More...
 

Public Member Functions

 WaveTrack (CreateToken &&, const SampleBlockFactoryPtr &pFactory, sampleFormat format, double rate)
 Don't call directly, but use Create. More...
 
const SampleBlockFactoryPtrGetSampleBlockFactory () const
 
size_t NChannels () const override
 A constant property. 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 Init (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)
 !brief Sets the new rate for the track without resampling it More...
 
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...
 
sampleCount GetVisibleSampleCount () const
 
sampleFormat GetSampleFormat () const override
 
void ConvertToSampleFormat (sampleFormat format, const std::function< void(size_t)> &progressReport={})
 
Track::Holder Cut (double t0, double t1) override
 Create tracks and modify this track. More...
 
Holder EmptyCopy (size_t nChannels, const SampleBlockFactoryPtr &pFactory={}) const
 
Holder EmptyCopy (const SampleBlockFactoryPtr &pFactory={}) const
 
void MakeMono ()
 Simply discard any right channel. More...
 
Holder MonoToStereo ()
 
std::vector< HolderSplitChannels ()
 
void SwapChannels ()
 
Track::Holder 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 Silence (double t0, double t1, ProgressReporter reportProgress) override
 
void InsertSilence (double t, double len) override
 
void Split (double t0, double t1)
 
std::pair< IntervalHolder, IntervalHolderSplitAt (double t)
 
void ClearAndAddCutLine (double t0, double t1)
 
Holder SplitCut (double t0, double t1)
 
void SplitDelete (double t0, double t1)
 
void Join (double t0, double t1, const ProgressReporter &reportProgress)
 
void Disjoin (double t0, double t1)
 
void Trim (double t0, double t1)
 
void ApplyPitchAndSpeed (std::optional< TimeInterval > interval, ProgressReporter reportProgress)
 
void SyncLockAdjust (double oldT1, double newT1) override
 
bool IsEmpty (double t0, double t1) const
 Returns true if there are no WaveClips in the specified region. More...
 
bool Append (size_t iChannel, constSamplePtr buffer, sampleFormat format, size_t len, unsigned int stride=1, sampleFormat effectiveFormat=widestSampleFormat) override
 
void Flush () override
 
void RepairChannels () 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...
 
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
 
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
 
IntervalHolder GetLeftmostClip ()
 
IntervalConstHolder GetLeftmostClip () const
 
IntervalHolder GetRightmostClip ()
 
IntervalConstHolder GetRightmostClip () const
 
ClipConstHolders GetClipInterfaces () const
 Get access to the (visible) clips in the tracks, in unspecified order. More...
 
IntervalHolder CreateClip (double offset=.0, const wxString &name=wxEmptyString, const Interval *pToCopy=nullptr, bool copyCutlines=true)
 
IntervalHolder CopyClip (const Interval &toCopy, bool copyCutlines)
 Create new clip and add it to this track. More...
 
IntervalHolder NewestOrNewClip ()
 Get access to the most recently added clip, or create a clip, if there is not already one. THIS IS NOT NECESSARILY RIGHTMOST. More...
 
IntervalHolder RightmostOrNewClip ()
 Get access to the last (rightmost) clip, or create a clip, if there is not already one. More...
 
int GetNumClips () const
 
IntervalHolders SortedIntervalArray ()
 Return all WaveClips sorted by clip play start time. More...
 
IntervalConstHolders SortedIntervalArray () const
 Return all WaveClips sorted by clip play start time. More...
 
bool CanOffsetClips (const std::vector< Interval * > &movingClips, double amount, double *allowedAmount=nullptr)
 Decide whether the clips could be offset (and inserted) together without overlapping other clips. More...
 
bool CanInsertClip (const Interval &clip, double &slideBy, double tolerance) const
 
bool MergeClips (int clipidx1, int clipidx2)
 
void Resample (int rate, BasicUI::ProgressDialog *progress=NULL)
 
bool SetFloats (const float *const *buffers, sampleCount start, size_t len, sampleFormat effectiveFormat=widestSampleFormat)
 Random-access assignment of a range of samples. More...
 
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
 
void InsertInterval (const IntervalHolder &interval, bool newClip, bool allowEmpty=false)
 
void RemoveInterval (const IntervalHolder &interval)
 
Track::Holder PasteInto (AudacityProject &project, TrackList &list) const override
 
bool HasClipNamed (const wxString &name) const
 
size_t NIntervals () const override
 Report the number of intervals. More...
 
IntervalHolder GetClip (size_t iInterval)
 
IntervalConstHolder GetClip (size_t iInterval) const
 used only during deserialization More...
 
void SetLegacyFormat (sampleFormat format)
 
int GetClipIndex (const Interval &clip) const
 Get the linear index of a given clip (== number of clips if not found) More...
 
void ZipClips (bool mustAlign=true)
 
virtual void Paste (double t, const Track &src)=0
 Weak precondition allows overrides to replicate one channel into many. More...
 
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
 
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
 
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 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 > >
 
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
 
LinkType GetLinkType () const noexcept
 
 Track ()
 
 Track (const Track &orig, ProtectedCreationArg &&)
 
Trackoperator= (const Track &orig)=delete
 
virtual ~Track ()
 
void Init (const Track &orig)
 
virtual Holder Duplicate (DuplicateOptions={}) const
 public nonvirtual duplication function that invokes Clone() More...
 
void ReparentAllAttachments ()
 
const wxString & GetName () const
 Name is always the same for all channels of a group. More...
 
void SetName (const wxString &n)
 
bool GetSelected () const
 Selectedness is always the same for all channels of a group. More...
 
virtual void SetSelected (bool s)
 
virtual Holder Cut (double t0, double t1)=0
 Create tracks and modify this track. More...
 
virtual Holder 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...
 
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
 
void AdjustPositions ()
 
void WriteCommonXMLAttributes (XMLWriter &xmlFile, bool includeNameAndSelected=true) const
 
bool HandleCommonXMLAttribute (const std::string_view &attr, const XMLAttributeValueView &valueView)
 
- Public Member Functions inherited from XMLTagHandler
 XMLTagHandler ()
 
virtual ~XMLTagHandler ()
 
virtual bool HandleXMLTag (const std::string_view &tag, const AttributesList &attrs)=0
 
virtual void HandleXMLEndTag (const std::string_view &WXUNUSED(tag))
 
virtual void HandleXMLContent (const std::string_view &WXUNUSED(content))
 
virtual XMLTagHandlerHandleXMLChild (const std::string_view &tag)=0
 
void ReadXMLEndTag (const char *tag)
 
void ReadXMLContent (const char *s, int len)
 
XMLTagHandlerReadXMLChild (const char *tag)
 
- Public Member Functions inherited from ClientData::Site< Host, ClientData, ObjectCopyingPolicy, Pointer, ObjectLockingPolicy, RegistryLockingPolicy >
 ~Site ()
 
 Site ()
 
 Site (const Site &other)
 
Siteoperator= (const Site &other)
 
 Site (Site &&other)
 
Siteoperator= (Site &&other)
 
size_t size () const
 How many attachment pointers are in the Site. More...
 
template<typename Subclass = ClientData>
Subclass & Get (const RegisteredFactory &key)
 Get reference to an attachment, creating on demand if not present, down-cast it to Subclass. More...
 
template<typename Subclass = const ClientData>
auto Get (const RegisteredFactory &key) const -> std::enable_if_t< std::is_const< Subclass >::value, Subclass & >
 Get reference to an attachment, creating on demand if not present, down-cast it to Subclass. More...
 
template<typename Subclass = ClientData>
Subclass * Find (const RegisteredFactory &key)
 Get a (bare) pointer to an attachment, or null, down-cast it to Subclass *; will not create on demand. More...
 
template<typename Subclass = const ClientData>
auto Find (const RegisteredFactory &key) const -> std::enable_if_t< std::is_const< Subclass >::value, Subclass * >
 Get a (bare) pointer to an attachment, or null, down-cast it to Subclass *; will not create on demand. More...
 
template<typename ReplacementPointer >
void Assign (const RegisteredFactory &key, ReplacementPointer &&replacement)
 Reassign Site's pointer to ClientData. More...
 
- 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...
 
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...
 
std::shared_ptr< ChannelNthChannel (size_t nChannel)
 
std::shared_ptr< const ChannelNthChannel (size_t nChannel) const
 
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 (size_t iChannel, constSamplePtr buffer, sampleFormat format, size_t len, unsigned int stride, sampleFormat effectiveFormat)=0
 Append the sample data to the track. You must call Flush() after the last Append. More...
 
virtual void Flush ()=0
 Flush must be called after last Append. More...
 
virtual void RepairChannels ()=0
 
virtual void InsertSilence (double t, double len)=0
 
- Public Member Functions inherited from Observer::Publisher< WaveTrackMessage >
 Publisher (ExceptionPolicy *pPolicy=nullptr, Alloc a={})
 Constructor supporting type-erased custom allocation/deletion. More...
 
 Publisher (Publisher &&)=default
 
Publisheroperator= (Publisher &&)=default
 
Subscription Subscribe (Callback callback)
 Connect a callback to the Publisher; later-connected are called earlier. More...
 
Subscription Subscribe (Object &obj, Return(Object::*callback)(Args...))
 Overload of Subscribe takes an object and pointer-to-member-function. More...
 

Static Public Member Functions

static wxString GetDefaultAudioTrackNamePreference ()
 
static double ProjectNyquistFrequency (const AudacityProject &project)
 
static WaveTrackNew (AudacityProject &project)
 
static Holder Create (const SampleBlockFactoryPtr &pFactory, sampleFormat format, double rate)
 Factory builds all AttachedTrackObjects. More...
 
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 void CopyAttachments (Track &dst, const Track &src, bool deep)
 Copy (deep) or just share (!deep) AttachedTrackObjects. More...
 
- 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...
 

Static Public Attributes

static const char * WaveTrack_tag = "wavetrack"
 
- Static Public Attributes inherited from Observer::Publisher< WaveTrackMessage >
static constexpr bool notifies_all
 

Private Member Functions

std::ptrdiff_t FindClip (const Interval &clip)
 
void RemoveClip (std::ptrdiff_t distance)
 
Track::Holder Clone (bool backup) const override
 
wxString MakeClipCopyName (const wxString &originalName) const
 
wxString MakeNewClipName () const
 
void CopyWholeClip (const Interval &clip, double t0, bool forClipboard)
 
void CopyPartOfClip (const Interval &clip, double t0, double t1, bool forClipboard)
 
void FinishCopy (double t0, double t1, double endTime, bool forClipboard)
 
IntervalConstHolders SortedClipArray () const
 Return all WaveClips sorted by clip play start time. More...
 
IntervalConstHolder GetClipAtTime (double time) const
 
void CreateRight ()
 
WaveClipHolder DoCreateClip (double offset=.0, const wxString &name=wxEmptyString) const
 Create a new clip that can be inserted later into the track. More...
 
bool InsertClip (WaveClipHolders &clips, WaveClipHolder clip, bool newClip, bool backup, bool allowEmpty)
 
void CopyClips (WaveClipHolders &clips, SampleBlockFactoryPtr pFactory, const WaveClipHolders &orig, bool backup)
 
void MergeChannelAttachments (WaveTrack &&other)
 
void EraseChannelAttachments (size_t index)
 Erase all attachments for a given index. More...
 
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 ExpandOneCutLine (double cutLinePosition, double *cutlineStart, double *cutlineEnd)
 
void ApplyPitchAndSpeedOnIntervals (const std::vector< IntervalHolder > &intervals, const ProgressReporter &reportProgress)
 
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
 
WaveClipHoldersNarrowClips ()
 
const WaveClipHoldersNarrowClips () const
 
void DoSetRate (double newRate)
 
Holder DuplicateWithOtherTempo (double newTempo) const
 
bool GetOne (const WaveClipHolders &clips, size_t iChannel, samplePtr buffer, sampleFormat format, sampleCount start, size_t len, bool backwards, fillFormat fill, bool mayThrow, sampleCount *pNumWithinClips) const
 
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 an unzipped leader track have a common rate. More...
 
bool FormatConsistencyCheck () const
 
void ApplyPitchAndSpeedOne (double t0, double t1, const ProgressReporter &reportProgress)
 

Static Private Member Functions

static void JoinOne (WaveTrack &track, double t0, double t1)
 
static void WriteOneXML (const WaveChannel &channel, XMLWriter &xmlFile, size_t iChannel, size_t nChannels)
 

Private Attributes

WaveChannel mChannel
 
std::optional< WaveChannelmRightChannel
 may be null More...
 
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 { 0 }
 
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)
 
- 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 >
void ForCorresponding (Site &other, const Function &function, bool create=true)
 
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...
 
template<typename Function >
void EraseIf (const Function &function)
 Erase attached objects satisfying a predicate. 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
 
virtual std::shared_ptr< IntervalDoGetInterval (size_t iInterval)=0
 Retrieve an interval. More...
 
- Protected Member Functions inherited from Observer::Publisher< WaveTrackMessage >
CallbackReturn Publish (const WaveTrackMessage &message)
 Send a message to connected callbacks. 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...
 

Detailed Description

A Track that contains audio waveform data.

Definition at line 200 of file WaveTrack.h.

Member Typedef Documentation

◆ Holder

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

Definition at line 247 of file WaveTrack.h.

◆ Interval

Definition at line 208 of file WaveTrack.h.

◆ IntervalConstHolder

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

Definition at line 211 of file WaveTrack.h.

◆ IntervalConstHolders

Definition at line 212 of file WaveTrack.h.

◆ IntervalHolder

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

Definition at line 209 of file WaveTrack.h.

◆ IntervalHolders

Definition at line 210 of file WaveTrack.h.

◆ Regions

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

Definition at line 230 of file WaveTrack.h.

Constructor & Destructor Documentation

◆ WaveTrack()

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

Don't call directly, but use Create.

Definition at line 494 of file WaveTrack.cpp.

496 : mpFactory(pFactory)
497 , mChannel(*this)
498{
499 WaveTrackData::Get(*this).SetSampleFormat(format);
500 DoSetRate(static_cast<int>(rate));
501}
SampleBlockFactoryPtr mpFactory
Definition: WaveTrack.h:829
WaveChannel mChannel
Definition: WaveTrack.h:767
void DoSetRate(double newRate)
Definition: WaveTrack.cpp:818
Services * Get()
Fetch the global instance, or nullptr if none is yet installed.
Definition: BasicUI.cpp:202

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

Here is the call graph for this function:

◆ ~WaveTrack()

WaveTrack::~WaveTrack ( )
virtual

Definition at line 559 of file WaveTrack.cpp.

560{
561}

Member Function Documentation

◆ Append()

bool WaveTrack::Append ( size_t  iChannel,
constSamplePtr  buffer,
sampleFormat  format,
size_t  len,
unsigned int  stride = 1,
sampleFormat  effectiveFormat = widestSampleFormat 
)
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.

Precondition
iChannel < NChannels()
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 2232 of file WaveTrack.cpp.

2235{
2236 assert(iChannel < NChannels());
2237 auto pTrack = this;
2238 constSamplePtr buffers[]{ buffer };
2239 auto pClip = RightmostOrNewClip();
2240 return pClip->Append(iChannel, 1,
2241 buffers, format, len, stride, effectiveFormat);
2242}
const char * constSamplePtr
Definition: SampleFormat.h:58
IntervalHolder RightmostOrNewClip()
Get access to the last (rightmost) clip, or create a clip, if there is not already one.
Definition: WaveTrack.cpp:2999
size_t NChannels() const override
A constant property.
Definition: WaveTrack.cpp:530

References anonymous_namespace{ExportPCM.cpp}::format, anonymous_namespace{StretchingSequenceIntegrationTest.cpp}::iChannel, NChannels(), and RightmostOrNewClip().

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

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

◆ ApplyPitchAndSpeed()

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

Definition at line 1929 of file WaveTrack.cpp.

1931{
1932 // Assert that the interval is reasonable, but this function will be no-op
1933 // anyway if not
1934 assert(!interval.has_value() ||
1935 interval->first <= interval->second);
1936 if (GetNumClips() == 0)
1937 return;
1938 const auto startTime =
1939 interval ? std::max(SnapToSample(interval->first), GetStartTime()) :
1940 GetStartTime();
1941 const auto endTime =
1942 interval ? std::min(SnapToSample(interval->second), GetEndTime()) :
1943 GetEndTime();
1944 if (startTime >= endTime)
1945 return;
1946
1947 // Here we assume that left- and right clips are aligned.
1948 if (auto clipAtT0 = GetClipAtTime(startTime);
1949 clipAtT0 && clipAtT0->SplitsPlayRegion(startTime) &&
1950 clipAtT0->HasPitchOrSpeed())
1951 Split(startTime, startTime);
1952 if (auto clipAtT1 = GetClipAtTime(endTime);
1953 clipAtT1 && clipAtT1->SplitsPlayRegion(endTime) &&
1954 clipAtT1->HasPitchOrSpeed())
1955 Split(endTime, endTime);
1956
1957 IntervalHolders srcIntervals;
1958 auto clip = GetIntervalAtTime(startTime);
1959 while (clip && clip->GetPlayStartTime() < endTime)
1960 {
1961 if (clip->HasPitchOrSpeed())
1962 srcIntervals.push_back(clip);
1964 }
1965
1966 ApplyPitchAndSpeedOnIntervals(srcIntervals, reportProgress);
1967}
int min(int a, int b)
double GetStartTime() const override
Implement WideSampleSequence.
Definition: WaveTrack.cpp:2585
void ApplyPitchAndSpeedOnIntervals(const std::vector< IntervalHolder > &intervals, const ProgressReporter &reportProgress)
Definition: WaveTrack.cpp:3189
IntervalConstHolder GetNextInterval(const Interval &interval, PlaybackDirection searchDirection) const
Definition: WaveTrack.cpp:173
IntervalConstHolder GetClipAtTime(double time) const
Definition: WaveTrack.cpp:2933
void Split(double t0, double t1)
Definition: WaveTrack.cpp:3139
std::vector< IntervalHolder > IntervalHolders
Definition: WaveTrack.h:210
double GetEndTime() const override
Implement WideSampleSequence.
Definition: WaveTrack.cpp:2595
int GetNumClips() const
Definition: WaveTrack.cpp:3031
IntervalHolder GetIntervalAtTime(double t)
Definition: WaveTrack.cpp:201
double SnapToSample(double t) const

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

Referenced by Silence().

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

◆ ApplyPitchAndSpeedOne()

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

◆ ApplyPitchAndSpeedOnIntervals()

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

Definition at line 3189 of file WaveTrack.cpp.

3192{
3193 IntervalHolders dstIntervals;
3194 dstIntervals.reserve(srcIntervals.size());
3195 std::transform(
3196 srcIntervals.begin(), srcIntervals.end(),
3197 std::back_inserter(dstIntervals), [&](const IntervalHolder& interval) {
3198 return GetRenderedCopy(interval,
3199 reportProgress, mpFactory, GetSampleFormat());
3200 });
3201
3202 // If we reach this point it means that no error was thrown - we can replace
3203 // the source with the destination intervals.
3204 for (auto i = 0; i < srcIntervals.size(); ++i)
3205 ReplaceInterval(srcIntervals[i], dstIntervals[i]);
3206}
std::shared_ptr< Interval > IntervalHolder
Definition: WaveTrack.h:209
void ReplaceInterval(const IntervalHolder &oldOne, const IntervalHolder &newOne)
Definition: WaveTrack.cpp:3236

References ReplaceInterval().

Referenced by ApplyPitchAndSpeed(), and Join().

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

◆ CanInsertClip()

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

Definition at line 3095 of file WaveTrack.cpp.

3097{
3098 const auto &clips = Intervals();
3099 if (clips.empty())
3100 return true;
3101 // Find clip in this that overlaps most with `clip`:
3102 const auto candidateClipStartTime = candidateClip.GetPlayStartTime();
3103 const auto candidateClipEndTime = candidateClip.GetPlayEndTime();
3104 const auto t0 = SnapToSample(candidateClipStartTime + slideBy);
3105 const auto t1 = SnapToSample(candidateClipEndTime + slideBy);
3106 std::vector<double> overlaps;
3107 std::transform(
3108 clips.begin(), clips.end(), std::back_inserter(overlaps),
3109 [&](const auto& pClip) {
3110 return pClip->IntersectsPlayRegion(t0, t1) ?
3111 std::min(pClip->GetPlayEndTime(), t1) -
3112 std::max(pClip->GetPlayStartTime(), t0) :
3113 0.0;
3114 });
3115 const auto maxOverlap = std::max_element(overlaps.begin(), overlaps.end());
3116 if (*maxOverlap > tolerance)
3117 return false;
3118 auto iter = clips.begin();
3119 std::advance(iter, std::distance(overlaps.begin(), maxOverlap));
3120 const auto overlappedClip = *iter;
3121 const auto requiredOffset = slideBy +
3122 *maxOverlap * (overlappedClip->GetPlayStartTime() < t0 ? 1 : -1);
3123 // Brute-force check to see if there's another clip that'd be in the way.
3124 if (std::any_of(
3125 clips.begin(), clips.end(),
3126 [&](const auto& pClip)
3127 {
3128 const auto result = pClip->IntersectsPlayRegion(
3129 SnapToSample(candidateClipStartTime + requiredOffset),
3130 SnapToSample(candidateClipEndTime + requiredOffset));
3131 return result;
3132 }))
3133 return false;
3134 slideBy = requiredOffset;
3135 return true;
3136}
auto Intervals()
Definition: WaveTrack.h:670

References Intervals(), and WideSampleSequence::SnapToSample().

Here is the call graph for this function:

◆ CanOffsetClips()

bool WaveTrack::CanOffsetClips ( const std::vector< Interval * > &  movingClips,
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
movingClipsnot necessarily in this track
amountsigned
[out]allowedAmountif null, test exact amount only; else, largest (in magnitude) possible offset with same sign

Definition at line 3036 of file WaveTrack.cpp.

3040{
3041 if (allowedAmount)
3042 *allowedAmount = amount;
3043
3044 const auto &moving = [&](Interval *clip){
3045 // linear search might be improved, but expecting few moving clips
3046 // compared with the fixed clips
3047 return movingClips.end() !=
3048 std::find(movingClips.begin(), movingClips.end(), clip);
3049 };
3050
3051 for (const auto &c: Intervals()) {
3052 if ( moving( c.get() ) )
3053 continue;
3054 for (const auto clip : movingClips) {
3055 if (c->GetPlayStartTime() < clip->GetPlayEndTime() + amount &&
3056 c->GetPlayEndTime() > clip->GetPlayStartTime() + amount)
3057 {
3058 if (!allowedAmount)
3059 return false; // clips overlap
3060
3061 if (amount > 0)
3062 {
3063 if (c->GetPlayStartTime() - clip->GetPlayEndTime() < *allowedAmount)
3064 *allowedAmount = c->GetPlayStartTime() - clip->GetPlayEndTime();
3065 if (*allowedAmount < 0)
3066 *allowedAmount = 0;
3067 } else
3068 {
3069 if (c->GetPlayEndTime() - clip->GetPlayStartTime() > *allowedAmount)
3070 *allowedAmount = c->GetPlayEndTime() - clip->GetPlayStartTime();
3071 if (*allowedAmount > 0)
3072 *allowedAmount = 0;
3073 }
3074 }
3075 }
3076 }
3077
3078 if (allowedAmount)
3079 {
3080 if (*allowedAmount == amount)
3081 return true;
3082
3083 // Check if the NEW calculated amount would not violate
3084 // any other constraint
3085 if (!CanOffsetClips(movingClips, *allowedAmount, nullptr)) {
3086 *allowedAmount = 0; // play safe and don't allow anything
3087 return false;
3088 }
3089 else
3090 return true;
3091 } else
3092 return true;
3093}
WaveClip Interval
Definition: WaveTrack.h:208
bool CanOffsetClips(const std::vector< Interval * > &movingClips, double amount, double *allowedAmount=nullptr)
Decide whether the clips could be offset (and inserted) together without overlapping other clips.
Definition: WaveTrack.cpp:3036

References CanOffsetClips(), and Intervals().

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

◆ Channels() [2/2]

auto WaveTrack::Channels ( ) const
inline

Definition at line 265 of file WaveTrack.h.

265 {
266 return this->ChannelGroup::Channels<const WaveChannel>(); }

◆ ClassTypeInfo()

auto WaveTrack::ClassTypeInfo ( )
static

Definition at line 670 of file WaveTrack.cpp.

671{
672 return typeInfo();
673}
static const Track::TypeInfo & typeInfo()
Definition: WaveTrack.cpp:657

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

1144{
1145 HandleClear(t0, t1, false, false);
1146}
void HandleClear(double t0, double t1, bool addCutLines, bool split, bool clearByTrimming=false)
Definition: WaveTrack.cpp:1532

References HandleClear().

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

Exception safety guarantee:
Strong

Definition at line 1149 of file WaveTrack.cpp.

1150{
1151 HandleClear(t0, t1, true, false);
1152}

References HandleClear().

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

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

◆ ClearAndPaste()

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

1209{
1210 // Get a modifiable copy of `src` because it may come from another project
1211 // with different tempo, making boundary queries incorrect.
1212 const auto& tempo = GetProjectTempo(*this);
1213 if (!tempo.has_value())
1215 const auto copyHolder = src.DuplicateWithOtherTempo(*tempo);
1217 t0, t1, *copyHolder, preserve, merge, effectWarper, clearByTrimming);
1218}
#define THROW_INCONSISTENCY_EXCEPTION
Throw InconsistencyException, using C++ preprocessor to identify the source code location.
const std::optional< double > & GetProjectTempo(const ChannelGroup &group)
Definition: TempoChange.cpp:48
Holder DuplicateWithOtherTempo(double newTempo) const
Definition: WaveTrack.cpp:573
void ClearAndPasteAtSameTempo(double t0, double t1, const WaveTrack &src, bool preserve, bool merge, const TimeWarper *effectWarper, bool clearByTrimming)
Definition: WaveTrack.cpp:1220

References ClearAndPasteAtSameTempo(), DuplicateWithOtherTempo(), GetProjectTempo(), and THROW_INCONSISTENCY_EXCEPTION.

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

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

1223{
1224 const auto srcNChannels = src.NChannels();
1225 assert(srcNChannels == NChannels());
1226 assert(
1227 GetProjectTempo(*this).has_value() &&
1228 GetProjectTempo(*this) == GetProjectTempo(src));
1229
1230 t0 = SnapToSample(t0);
1231 t1 = SnapToSample(t1);
1232
1233 const auto endTime = src.GetEndTime();
1234 double dur = std::min(t1 - t0, endTime);
1235
1236 // If duration is 0, then it's just a plain paste
1237 if (dur == 0.0) {
1238 // use Weak-guarantee
1239 PasteWaveTrack(t0, src, merge);
1240 return;
1241 }
1242
1243 auto &track = *this;
1244
1245 std::vector<SplitInfo> splits;
1246 IntervalHolders cuts;
1247
1248 //helper routine, that finds SplitInfo by time value,
1249 //or creates a new one if no one exists yet
1250 auto get_split = [&](double time) {
1251 auto it = std::find_if(splits.begin(), splits.end(),
1252 [time](const SplitInfo& split) { return split.time == time; });
1253 if(it == splits.end())
1254 it = splits.insert(
1255 splits.end(),
1256 { time, nullptr, nullptr, std::nullopt, std::nullopt }
1257 );
1258 return it;
1259 };
1260
1261 // If provided time warper was NULL, use a default one that does nothing
1262 IdentityTimeWarper localWarper;
1263 const TimeWarper *warper = (effectWarper ? effectWarper : &localWarper);
1264
1265 const auto roundTime = [&track](double t){
1266 return track.SnapToSample(t);
1267 };
1268
1269 // Align to a sample
1270 t0 = roundTime(t0);
1271 t1 = roundTime(t1);
1272
1273 // Save the cut/split lines whether preserving or not since merging
1274 // needs to know if a clip boundary is being crossed since Paste()
1275 // will add split lines around the pasted clip if so.
1276 for (const auto &&clip : track.Intervals()) {
1277 double st;
1278
1279 // Remember clip boundaries as locations to split
1280 // we need to copy clips, trims and names, because the original ones
1281 // could be changed later during Clear/Paste routines
1282 st = roundTime(clip->GetPlayStartTime());
1283 if (st >= t0 && st <= t1) {
1284 auto it = get_split(st);
1285 if (clip->GetTrimLeft() != 0) {
1286 //keep only hidden left part
1287 it->right = track.CopyClip(*clip, false);
1288 it->right->SetTrimLeft(.0);
1289 it->right->ClearRight(clip->GetPlayStartTime());
1290 }
1291 it->rightClipName = clip->GetName();
1292 }
1293
1294 st = roundTime(clip->GetPlayEndTime());
1295 if (st >= t0 && st <= t1) {
1296 auto it = get_split(st);
1297 if (clip->GetTrimRight() != 0) {
1298 //keep only hidden right part
1299 it->left = track.CopyClip(*clip, false);
1300 it->left->SetTrimRight(.0);
1301 it->left->ClearLeft(clip->GetPlayEndTime());
1302 }
1303 it->leftClipName = clip->GetName();
1304 }
1305
1306 // Search for cut lines
1307 auto cutlines = clip->GetCutLines();
1308 for (auto &cut : cutlines) {
1309 const auto unrounded =
1310 clip->GetSequenceStartTime() + cut->GetSequenceStartTime();
1311 const double cs = roundTime(unrounded);
1312
1313 // Remember cut point
1314 if (cs >= t0 && cs <= t1) {
1315 // Remember the absolute offset and add to our cuts array.
1316 cut->SetSequenceStartTime(cs);
1317 bool removed = clip->RemoveCutLine(unrounded);
1318 assert(removed);
1319 cuts.push_back(move(cut));
1320 }
1321 }
1322 }
1323
1324 const auto tolerance = 2.0 / track.GetRate();
1325
1326 // This is not a split-cut operation.
1327 constexpr auto split = false;
1328
1329 // Now, clear the selection
1330 track.HandleClear(t0, t1, false, split, clearByTrimming);
1331
1332 // And paste in the new data
1333 track.PasteWaveTrackAtSameTempo(t0, src, merge);
1334
1335 // First, merge the new clip(s) in with the existing clips
1336 if (merge && splits.size() > 0) {
1337 {
1338 // Now t1 represents the absolute end of the pasted data.
1339 t1 = t0 + endTime;
1340
1341 // Get a sorted array of the clips
1342 auto clips = track.SortedIntervalArray();
1343
1344 // Scan the sorted clips for the first clip whose start time
1345 // exceeds the pasted regions end time.
1346 IntervalHolder prev;
1347 for (const auto clip : clips) {
1348 // Merge this clip and the previous clip if the end time
1349 // falls within it and this isn't the first clip in the track.
1350 if (fabs(t1 - clip->GetPlayStartTime()) < tolerance) {
1351 if (prev && clip->HasEqualPitchAndSpeed(*prev))
1352 track.MergeClips(
1353 track.GetClipIndex(*prev), track.GetClipIndex(*clip));
1354 break;
1355 }
1356 prev = clip;
1357 }
1358 }
1359
1360 {
1361 // Refill the array since clips have changed.
1362 auto clips = track.SortedIntervalArray();
1363
1364 // Scan the sorted clips to look for the start of the pasted
1365 // region.
1366 IntervalHolder prev;
1367 for (const auto clip : clips) {
1368 if (prev) {
1369 // It must be that clip is what was pasted and it begins where
1370 // prev ends.
1371 // use Weak-guarantee
1372 if (clip->HasEqualPitchAndSpeed(*prev))
1373 track.MergeClips(
1374 track.GetClipIndex(*prev), track.GetClipIndex(*clip));
1375 break;
1376 }
1377 if (fabs(t0 - clip->GetPlayEndTime()) < tolerance)
1378 // Merge this clip and the next clip if the start time
1379 // falls within it and this isn't the last clip in the track.
1380 prev = clip;
1381 else
1382 prev = nullptr;
1383 }
1384 }
1385 }
1386
1387 // Restore cut/split lines
1388 if (preserve) {
1389 auto attachLeft = [](Interval& target, Interval& src) {
1390 // What this lambda does is restoring the left hidden data of `target`
1391 // that was cleared by `HandleClear`. Hence, `target` has no left
1392 // hidden data at this stage.
1393 assert(target.GetTrimLeft() == 0);
1394 if (target.GetTrimLeft() != 0)
1395 return;
1396
1397 // `src` was created by copy from `target`, so they have equal width,
1398 // pitch and speed.
1399 assert(target.NChannels() == src.NChannels());
1400 assert(target.HasEqualPitchAndSpeed(src));
1401
1402 auto trim = src.GetPlayEndTime() - src.GetPlayStartTime();
1403 auto success = target.Paste(target.GetPlayStartTime(), src);
1404 assert(success); // because of precondition above
1405 target.SetTrimLeft(trim);
1406 //Play start time needs to be adjusted after
1407 //prepending data to the sequence
1408 target.ShiftBy(-trim);
1409 };
1410
1411 auto attachRight = [](Interval &target, Interval &src)
1412 {
1413 // See `attachLeft` for rationale behind these asserts.
1414 assert(target.GetTrimRight() == 0);
1415 if (target.GetTrimRight() != 0)
1416 return;
1417 assert(target.NChannels() == src.NChannels());
1418 assert(target.HasEqualPitchAndSpeed(src));
1419
1420 auto trim = src.GetPlayEndTime() - src.GetPlayStartTime();
1421 auto success = target.Paste(target.GetPlayEndTime(), src);
1422 assert(success); // because of precondition above
1423 target.SetTrimRight(trim);
1424 };
1425
1426 // Restore the split lines and trims, transforming the position appropriately
1427 for (const auto& split: splits) {
1428 auto at = roundTime(warper->Warp(split.time));
1429 for (const auto &&clip : track.Intervals()) {
1430 // Clips in split began as copies of a clip in the track,
1431 // therefore have the same width, satisfying preconditions to
1432 // attach
1433 if (clip->SplitsPlayRegion(at))//strictly inside
1434 {
1435 auto newClip = CopyClip(*clip, true);
1436 clip->ClearRight(at);
1437 newClip->ClearLeft(at);
1438 if (split.left)
1439 // clip was cleared right
1440 attachRight(*clip, *split.left);
1441 if (split.right)
1442 // new clip was cleared left
1443 attachLeft(*newClip, *split.right);
1444 track.InsertInterval(move(newClip), false);
1445 break;
1446 }
1447 else if (clip->GetPlayStartSample() ==
1448 track.TimeToLongSamples(at) && split.right) {
1449 // Satisfy the precondition of attachLeft first!
1450 const auto trim = clip->GetTrimLeft();
1451 const auto seqStartTime = clip->GetSequenceStartTime();
1452 clip->Clear(seqStartTime, seqStartTime + trim);
1453 // This clearing, although only removing the hidden part, moved
1454 // the clip leftwards. We don't want this in this case.
1455 clip->ShiftBy(trim);
1456 attachLeft(*clip, *split.right);
1457 break;
1458 }
1459 else if (clip->GetPlayEndSample() ==
1460 track.TimeToLongSamples(at) && split.left) {
1461 // Satisfy the precondition of attachRight first!
1462 clip->Clear(
1463 clip->GetPlayEndTime(), clip->GetSequenceEndTime());
1464 attachRight(*clip, *split.left);
1465 break;
1466 }
1467 }
1468 }
1469
1470 //Restore clip names
1471 for (const auto& split : splits)
1472 {
1473 auto s = track.TimeToLongSamples(warper->Warp(split.time));
1474 for (auto &&clip : track.Intervals()) {
1475 if (split.rightClipName.has_value() && clip->GetPlayStartSample() == s)
1476 clip->SetName(*split.rightClipName);
1477 else if (split.leftClipName.has_value() && clip->GetPlayEndSample() == s)
1478 clip->SetName(*split.leftClipName);
1479 }
1480 }
1481
1482 // Restore the saved cut lines, also transforming if time altered
1483 for (const auto &&clip : track.Intervals()) {
1484 const double st = clip->GetPlayStartTime();
1485 const double et = clip->GetPlayEndTime();
1486
1487 // Scan the cuts for any that live within this clip
1488 for (auto &cut : cuts) {
1489 if (!cut)
1490 continue;
1491
1492 //cutlines in this array were orphaned previously
1493 double cs = cut->GetSequenceStartTime();
1494
1495 // Offset the cut from the start of the clip and add it to
1496 // this clips cutlines.
1497 if (cs >= st && cs <= et) {
1498 cut->SetSequenceStartTime(warper->Warp(cs) - st);
1499 clip->AddCutLine(cut);
1500 cut = {};
1501 }
1502 }
1503 }
1504 }
1505}
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
void Paste(double t0, const Track &src) override
Definition: WaveTrack.cpp:1970
IntervalHolder CopyClip(const Interval &toCopy, bool copyCutlines)
Create new clip and add it to this track.
Definition: WaveTrack.cpp:2957
void PasteWaveTrack(double t0, const WaveTrack &other, bool merge)
Definition: WaveTrack.cpp:1691

References CopyClip(), GetEndTime(), GetProjectTempo(), min(), WideChannelGroupInterval::NChannels(), NChannels(), PasteWaveTrack(), WideSampleSequence::SnapToSample(), and TimeWarper::Warp().

Referenced by ClearAndPaste().

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

◆ Clone()

Track::Holder WaveTrack::Clone ( bool  backup) const
overrideprivatevirtual

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

Parameters
backupwhether the duplication is for backup purposes while opening a project, instead of other editing operations
Postcondition
result tracks have same TrackIds as the channels of this

Implements Track.

Definition at line 759 of file WaveTrack.cpp.

760{
761 auto newTrack = EmptyCopy(NChannels());
762 if(backup)
763 {
764 //Init-time rate and format should be preserved as initialization
765 //phase is not yet completed for that track.
766 newTrack->mLegacyFormat = mLegacyFormat;
767 newTrack->mLegacyRate = mLegacyRate;
768 }
769 newTrack->CopyClips(newTrack->mClips,
770 newTrack->mpFactory, this->mClips, backup);
771 return newTrack;
772}
int mLegacyRate
used only during deserialization
Definition: WaveTrack.h:777
sampleFormat mLegacyFormat
used only during deserialization
Definition: WaveTrack.h:778
Holder EmptyCopy(size_t nChannels, const SampleBlockFactoryPtr &pFactory={}) const
Definition: WaveTrack.cpp:994

References EmptyCopy(), mLegacyFormat, mLegacyRate, and NChannels().

Here is the call graph for this function:

◆ ConvertToSampleFormat()

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

Definition at line 906 of file WaveTrack.cpp.

908{
909 for (const auto &pClip : Intervals())
910 pClip->ConvertToSampleFormat(format, progressReport);
911 WaveTrackData::Get(*this).SetSampleFormat(format);
912}

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

Here is the call graph for this function:

◆ Copy()

Track::Holder 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

Implements Track.

Definition at line 1078 of file WaveTrack.cpp.

1079{
1080 if (t1 < t0)
1082
1083 auto newTrack = EmptyCopy(NChannels());
1084 const auto endTime = std::max(GetEndTime(), t1);
1085 for (const auto pClip : Intervals()) {
1086 // PRL: Why shouldn't cutlines be copied and pasted too? I don't know,
1087 // but that was the old behavior. But this function is also used by the
1088 // Duplicate command and I changed its behavior in that case.
1089 if (pClip->IsEmpty())
1090 continue;
1091 else if (t0 <= pClip->GetPlayStartTime() && t1 >= pClip->GetPlayEndTime())
1092 {
1093 newTrack->CopyWholeClip(*pClip, t0, forClipboard);
1094 }
1095 else if (pClip->CountSamples(t0, t1) >= 1) {
1096 newTrack->CopyPartOfClip(*pClip, t0, t1, forClipboard);
1097 }
1098 }
1099 newTrack->FinishCopy(t0, t1, endTime, forClipboard);
1100 return newTrack;
1101}

References EmptyCopy(), GetEndTime(), Intervals(), NChannels(), and THROW_INCONSISTENCY_EXCEPTION.

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

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

◆ CopyClip()

auto WaveTrack::CopyClip ( const Interval toCopy,
bool  copyCutlines 
)

Create new clip and add it to this track.

Returns a pointer to the newly created clip, using this track's block factory but copying all else from the given clip, except possibly the cutlines.

Definition at line 2957 of file WaveTrack.cpp.

2959{
2960 return CreateClip(toCopy.GetSequenceStartTime(),
2961 toCopy.GetName(), &toCopy, copyCutlines);
2962}
IntervalHolder CreateClip(double offset=.0, const wxString &name=wxEmptyString, const Interval *pToCopy=nullptr, bool copyCutlines=true)
Definition: WaveTrack.cpp:2943

Referenced by ClearAndPasteAtSameTempo(), and HandleClear().

Here is the caller graph for this function:

◆ CopyClips()

void WaveTrack::CopyClips ( WaveClipHolders clips,
SampleBlockFactoryPtr  pFactory,
const WaveClipHolders orig,
bool  backup 
)
private

Definition at line 516 of file WaveTrack.cpp.

518{
519 for (const auto &clip : orig)
520 InsertClip(clips,
521 std::make_shared<WaveClip>(*clip, pFactory, true),
522 false, backup, false);
523}
bool InsertClip(WaveClipHolders &clips, WaveClipHolder clip, bool newClip, bool backup, bool allowEmpty)
Definition: WaveTrack.cpp:1913

References InsertClip().

Here is the call graph for this function:

◆ CopyPartOfClip()

void WaveTrack::CopyPartOfClip ( const Interval clip,
double  t0,
double  t1,
bool  forClipboard 
)
private

Definition at line 1113 of file WaveTrack.cpp.

1115{
1116 const auto &pFactory = GetSampleBlockFactory();
1117 auto newClip = std::make_shared<Interval>(
1118 clip, pFactory, !forClipboard, t0, t1);
1119 newClip->SetName(clip.GetName());
1120 newClip->ShiftBy(-t0);
1121 if (newClip->GetPlayStartTime() < 0)
1122 newClip->SetPlayStartTime(0);
1123 InsertInterval(std::move(newClip), false, false);
1124}
void InsertInterval(const IntervalHolder &interval, bool newClip, bool allowEmpty=false)
Definition: WaveTrack.cpp:3217
const SampleBlockFactoryPtr & GetSampleBlockFactory() const
Definition: WaveTrack.h:253

References GetSampleBlockFactory(), and InsertInterval().

Here is the call graph for this function:

◆ CopyWholeClip()

void WaveTrack::CopyWholeClip ( const Interval clip,
double  t0,
bool  forClipboard 
)
private

Definition at line 1103 of file WaveTrack.cpp.

1105{
1106 const auto &pFactory = GetSampleBlockFactory();
1107 const auto newClip =
1108 std::make_shared<Interval>(clip, pFactory, !forClipboard);
1109 InsertInterval(newClip, false, false);
1110 newClip->ShiftBy(-t0);
1111}

References GetSampleBlockFactory(), and InsertInterval().

Here is the call graph for this function:

◆ Create()

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

Factory builds all AttachedTrackObjects.

Definition at line 503 of file WaveTrack.cpp.

506{
507 auto result =
508 std::make_shared<WaveTrack>(CreateToken{}, pFactory, format, rate);
509 // Only after make_shared returns, can weak_from_this be used, which
510 // attached object factories may need
511 // (but this is anyway just the factory for unit test purposes)
512 result->AttachedTrackObjects::BuildAll();
513 return result;
514}

References anonymous_namespace{ExportPCM.cpp}::format.

Referenced by TestWaveTrackMaker::Track().

Here is the caller graph for this function:

◆ CreateClip()

auto WaveTrack::CreateClip ( double  offset = .0,
const wxString &  name = wxEmptyString,
const Interval pToCopy = nullptr,
bool  copyCutlines = true 
)

Create new clip that uses this track's factory but do not add it to the track

Returns a pointer to the newly created clip. Optionally initial offset and clip name may be provided, and a clip from which to copy all sample data. The clip is not owned by the track. Use InsertInterval to make it so.

Parameters
offsetdesired sequence (not play) start time

Definition at line 2943 of file WaveTrack.cpp.

2945{
2946 if (pToCopy) {
2947 auto pNewClip =
2948 std::make_shared<WaveClip>(*pToCopy, mpFactory, copyCutlines);
2949 pNewClip->SetName(name);
2950 pNewClip->SetSequenceStartTime(offset);
2951 return pNewClip;
2952 }
2953 else
2954 return DoCreateClip(offset, name);
2955}
const TranslatableString name
Definition: Distortion.cpp:76
WaveClipHolder DoCreateClip(double offset=.0, const wxString &name=wxEmptyString) const
Create a new clip that can be inserted later into the track.
Definition: WaveTrack.cpp:2969

References name.

Referenced by ProjectAudioManager::DoRecord(), FinishCopy(), AUPImportFileHandle::HandleWaveClip(), InsertSilence(), Join(), and PasteWaveTrackAtSameTempo().

Here is the caller graph for this function:

◆ CreateRight()

void WaveTrack::CreateRight ( )
private

Definition at line 2964 of file WaveTrack.cpp.

2965{
2966 mRightChannel.emplace(*this);
2967}
std::optional< WaveChannel > mRightChannel
may be null
Definition: WaveTrack.h:769

References mRightChannel.

Referenced by ZipClips().

Here is the caller graph for this function:

◆ Cut()

Track::Holder WaveTrack::Cut ( double  t0,
double  t1 
)
overridevirtual

Create tracks and modify this track.

Returns
non-NULL or else throw May assume precondition: t0 <= t1

Implements Track.

Definition at line 937 of file WaveTrack.cpp.

938{
939 if (t1 < t0)
941
942 auto result = Copy(t0, t1);
943 Clear(t0, t1);
944 return result;
945}
void Clear(double t0, double t1) override
Definition: WaveTrack.cpp:1143
Track::Holder Copy(double t0, double t1, bool forClipboard=true) const override
Create new tracks and don't modify this track.
Definition: WaveTrack.cpp:1078

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

Here is the call graph for this function:

◆ Disjoin()

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

Definition at line 2045 of file WaveTrack.cpp.

2046{
2048 const size_t maxAtOnce = 1048576;
2049 std::vector<float> buffer;
2050 std::vector<samplePtr> buffers;
2051 Regions regions;
2052
2053 const size_t width = NChannels();
2054
2055 for (const auto &interval : Intervals()) {
2056 double startTime = interval->Start();
2057 double endTime = interval->End();
2058
2059 if (endTime < t0 || startTime > t1)
2060 continue;
2061
2062 // Assume all clips will have the same width
2063 if (buffer.empty()) {
2064 buffer.resize(maxAtOnce * width);
2065 buffers.resize(width);
2066 auto pBuffer = buffer.data();
2067 for (size_t ii = 0; ii < width; ++ii, pBuffer += maxAtOnce)
2068 buffers[ii] = reinterpret_cast<samplePtr>(pBuffer);
2069 }
2070
2071 const auto allZeroesAt = [&](size_t i) {
2072 auto pData = buffer.data() + i;
2073 for (size_t ii = 0; ii < width; ++ii, pData += maxAtOnce) {
2074 if (*pData != 0.0)
2075 return false;
2076 }
2077 return true;
2078 };
2079
2080 // simply look for a sequence of zeroes (across all channels) and if the
2081 // sequence is longer than the minimum number, split-delete the region
2082
2083 sampleCount seqStart = -1;
2084 auto start = interval->TimeToSamples(std::max(.0, t0 - startTime));
2085 auto end = interval->TimeToSamples(std::min(endTime, t1) - startTime);
2086
2087 auto len = (end - start);
2088 for (decltype(len) done = 0; done < len; done += maxAtOnce) {
2089 auto numSamples = limitSampleBufferSize(maxAtOnce, len - done);
2090
2091 auto bufferIt = buffers.begin();
2092
2093 for (auto channel : interval->Channels())
2094 channel->GetSamples(
2095 *bufferIt++, floatSample, start + done, numSamples);
2096
2097 for (decltype(numSamples) i = 0; i < numSamples; ++i) {
2098 auto curSamplePos = start + done + i;
2099
2100 //start a NEW sequence
2101 if (seqStart == -1 && allZeroesAt(i))
2102 seqStart = curSamplePos;
2103 else if (curSamplePos == end - 1 || !allZeroesAt(i)) {
2104 if (seqStart != -1) {
2105 decltype(end) seqEnd;
2106
2107 //consider the end case, where selection ends in zeroes
2108 if (curSamplePos == end - 1 && allZeroesAt(i))
2109 seqEnd = end;
2110 else
2111 seqEnd = curSamplePos;
2112 if (seqEnd - seqStart + 1 > minSamples) {
2113 regions.push_back(
2114 Region(
2115 startTime + interval->SamplesToTime(seqStart),
2116 startTime + interval->SamplesToTime(seqEnd)
2117 )
2118 );
2119 }
2120 seqStart = -1;
2121 }
2122 }
2123 } // samples
2124 } // blocks
2125 } // finding regions
2126
2127 for (const auto &region : regions)
2128 SplitDelete(region.start, region.end);
2129}
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:67
void SplitDelete(double t0, double t1)
Definition: WaveTrack.cpp:1508
sampleCount TimeToLongSamples(double t0) const
Positions or offsets within audio files need a wide type.
Definition: SampleCount.h:19
const char * end(const char *str) noexcept
Definition: StringUtils.h:106

References details::end(), floatSample, Intervals(), 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:

◆ DoCreateClip()

auto WaveTrack::DoCreateClip ( double  offset = .0,
const wxString &  name = wxEmptyString 
) const
private

Create a new clip that can be inserted later into the track.

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

Postcondition
result: result->NChannels() == track.NChannels()

Definition at line 2969 of file WaveTrack.cpp.

2971{
2972 auto clip = std::make_shared<WaveClip>(NChannels(),
2974 clip->SetName(name);
2975 clip->SetSequenceStartTime(offset);
2976
2977 const auto& tempo = GetProjectTempo(*this);
2978 if (tempo.has_value())
2979 clip->OnProjectTempoChange(std::nullopt, *tempo);
2980 assert(clip->NChannels() == NChannels());
2981 return clip;
2982}
sampleFormat GetSampleFormat() const override
Definition: WaveTrack.cpp:900
double GetRate() const override
Definition: WaveTrack.cpp:803

References GetProjectTempo(), anonymous_namespace{TimeTrack.cpp}::GetRate(), and name.

Here is the call 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.

Implements WideSampleSequence.

Definition at line 2618 of file WaveTrack.cpp.

2622{
2623 const auto nChannels = NChannels();
2624 assert(iChannel + nBuffers <= nChannels); // precondition
2625 return std::all_of(buffers, buffers + nBuffers, [&](samplePtr buffer) {
2626 const auto result = GetOne(mClips, iChannel++,
2627 buffer, format, start, len, backwards, fill, mayThrow,
2628 pNumWithinClips);
2629 return result;
2630 });
2631}
bool GetOne(const WaveClipHolders &clips, size_t iChannel, samplePtr buffer, sampleFormat format, sampleCount start, size_t len, bool backwards, fillFormat fill, bool mayThrow, sampleCount *pNumWithinClips) const
Definition: WaveTrack.cpp:2633
WaveClipHolders mClips
Definition: WaveTrack.h:775

References anonymous_namespace{ExportPCM.cpp}::format, GetOne(), anonymous_namespace{StretchingSequenceIntegrationTest.cpp}::iChannel, mClips, and NChannels().

Referenced by WaveChannel::DoGet().

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

◆ DoGetChannel()

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

Retrieve a channel For fixed iChannel, resulting address must be unchanging, if there has been no other mutation of this ChannelGroup

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

Implements ChannelGroup.

Definition at line 716 of file WaveTrack.cpp.

717{
718 auto nChannels = NChannels();
719 if (iChannel >= nChannels)
720 return {};
721 // TODO: more-than-two-channels
722 ::Channel &aliased = (iChannel == 0)
723 ? mChannel
724 : *mRightChannel;
725 // Use aliasing constructor of std::shared_ptr
726 return { shared_from_this(), &aliased };
727}

References anonymous_namespace{StretchingSequenceIntegrationTest.cpp}::iChannel, mChannel, mRightChannel, and NChannels().

Here is the call graph for this function:

◆ DoGetInterval()

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

Retrieve an interval.

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

Implements ChannelGroup.

Definition at line 702 of file WaveTrack.cpp.

703{
704 if (iInterval < NIntervals())
705 return mClips[iInterval];
706 return {};
707}
size_t NIntervals() const override
Report the number of intervals.
Definition: WaveTrack.cpp:686

References mClips, and NIntervals().

Here is the call graph for this function:

◆ DoSetGain()

void WaveTrack::DoSetGain ( float  value)
private

Definition at line 829 of file WaveTrack.cpp.

830{
831 WaveTrackData::Get(*this).SetGain(value);
832}

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

848{
849 WaveTrackData::Get(*this).SetPan(value);
850}

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

819{
820 auto &data = WaveTrackData::Get(*this);
821 data.SetRate(static_cast<int>(newRate));
822}

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

auto WaveTrack::DuplicateWithOtherTempo ( double  newTempo) const
private

Definition at line 573 of file WaveTrack.cpp.

574{
575 const auto srcCopy = Duplicate();
576 ::DoProjectTempoChange(*srcCopy, newTempo);
577 return std::static_pointer_cast<WaveTrack>(srcCopy);
578}
void DoProjectTempoChange(ChannelGroup &group, double newTempo)
Definition: TempoChange.cpp:41
virtual Holder Duplicate(DuplicateOptions={}) const
public nonvirtual duplication function that invokes Clone()
Definition: Track.cpp:109

References DoProjectTempoChange(), and anonymous_namespace{FloatVectorClip.cpp}::Duplicate().

Referenced by ClearAndPaste(), and PasteWaveTrack().

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

◆ EmptyCopy() [1/2]

auto WaveTrack::EmptyCopy ( const SampleBlockFactoryPtr pFactory = {}) const

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

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

Definition at line 1015 of file WaveTrack.cpp.

1017{
1018 return EmptyCopy(NChannels(), pFactory);
1019}

◆ EmptyCopy() [2/2]

WaveTrack::Holder WaveTrack::EmptyCopy ( size_t  nChannels,
const SampleBlockFactoryPtr pFactory = {} 
) const

Make another track copying format, rate, etc. but containing no clips; with the specified number of channels.

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.

Definition at line 994 of file WaveTrack.cpp.

996{
997 const auto rate = GetRate();
998 auto result = std::make_shared<WaveTrack>(CreateToken{},
999 pFactory, GetSampleFormat(), rate);
1000 if (nChannels > 1)
1001 result->CreateRight();
1002 result->Init(*this);
1003 // Copy state rather than BuildAll()
1004 Track::CopyAttachments(*result, *this, true /* deep copy */);
1005 // The previous line might have destroyed the rate information stored in
1006 // channel group data. The copy is not yet in a TrackList. Reassign rate
1007 // in case the track needs to make WaveClips before it is properly joined
1008 // with the opposite channel in a TrackList.
1009 result->DoSetRate(rate);
1010 result->mpFactory = pFactory ? pFactory : mpFactory;
1011 WaveTrackData::Get(*result).SetOrigin(0);
1012 return result;
1013}
static void CopyAttachments(Track &dst, const Track &src, bool deep)
Copy (deep) or just share (!deep) AttachedTrackObjects.
Definition: Track.cpp:94

References Track::CopyAttachments(), BasicUI::Get(), GetRate(), GetSampleFormat(), and mpFactory.

Referenced by Clone(), Copy(), WaveTrackFactory::Create(), PasteInto(), EffectStereoToMono::ProcessOne(), and SyncLockAdjust().

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

◆ EraseChannelAttachments()

void WaveTrack::EraseChannelAttachments ( size_t  index)
private

Erase all attachments for a given index.

Definition at line 452 of file WaveTrack.cpp.

453{
455 [this, ii](TrackAttachment &attachment){
456 if (const auto pAttachments =
457 dynamic_cast<ChannelAttachmentsBase *>(&attachment))
458 pAttachments->Erase(shared_from_this(), ii);
459 });
460}
Holds multiple objects as a single attachment to Track.
void ForEach(const Function &function)
Invoke function on each ClientData object that has been created in this.
Definition: ClientData.h:389

References ClientData::Site< Host, ClientData, ObjectCopyingPolicy, Pointer, ObjectLockingPolicy, RegistryLockingPolicy >::ForEach().

Referenced by MakeMono().

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

◆ ExpandOneCutLine()

void WaveTrack::ExpandOneCutLine ( double  cutLinePosition,
double *  cutlineStart,
double *  cutlineEnd 
)
private

◆ FindChannelGroup()

const ChannelGroup * WaveTrack::FindChannelGroup ( ) const
overridevirtual

Find associated ChannelGroup if any.

Implements PlayableSequence.

Definition at line 2318 of file WaveTrack.cpp.

2319{
2320 return this;
2321}

◆ FindClip()

std::ptrdiff_t WaveTrack::FindClip ( const Interval clip)
private

Definition at line 1515 of file WaveTrack.cpp.

1516{
1517 auto clips = Intervals();
1518 const auto begin = clips.begin();
1519 const auto pred = [&](auto pClip){ return pClip.get() == &clip; };
1520 auto iter = std::find_if(begin, clips.end(), pred);
1521 return std::distance(begin, iter);
1522}
const char * begin(const char *str) noexcept
Definition: StringUtils.h:101

References details::begin(), and Intervals().

Referenced by Join(), and ReplaceInterval().

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

◆ FinishCopy()

void WaveTrack::FinishCopy ( double  t0,
double  t1,
double  endTime,
bool  forClipboard 
)
private

Definition at line 1126 of file WaveTrack.cpp.

1128{
1129 // AWD, Oct 2009: If the selection ends in whitespace, create a
1130 // placeholder clip representing that whitespace
1131 // PRL: Only if we want the track for pasting into other tracks. Not if
1132 // it goes directly into a project as in the Duplicate command.
1133 if (forClipboard && endTime + 1.0 / GetRate() < t1 - t0) {
1134 auto placeholder = CreateClip();
1135 placeholder->SetIsPlaceholder(true);
1136 placeholder->InsertSilence(0, (t1 - t0) - GetEndTime());
1137 placeholder->ShiftBy(GetEndTime());
1138 InsertInterval(move(placeholder), true, false);
1139 }
1140}

References CreateClip(), GetEndTime(), GetRate(), and InsertInterval().

Here is the call 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 2299 of file WaveTrack.cpp.

2300{
2301 if (NIntervals() == 0)
2302 return;
2303 // After appending, presumably. Do this to the clip that gets appended.
2304 GetRightmostClip()->Flush();
2305}
IntervalHolder GetRightmostClip()
Definition: WaveTrack.cpp:2558

References GetRightmostClip(), and NIntervals().

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

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

◆ FormatConsistencyCheck()

bool WaveTrack::FormatConsistencyCheck ( ) const
private

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

Definition at line 1904 of file WaveTrack.cpp.

1905{
1906 const auto channels = TrackList::Channels(this);
1907 return std::all_of(channels.begin(), channels.end(),
1908 [&](const WaveTrack *pTrack){
1909 return pTrack && pTrack->mLegacyFormat == mLegacyFormat;
1910 });
1911}
static auto Channels(TrackType *pTrack) -> TrackIterRange< TrackType >
Definition: Track.h:1016
A Track that contains audio waveform data.
Definition: WaveTrack.h:203

References TrackList::Channels().

Referenced by LinkConsistencyFix().

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

◆ GetBestBlockSize()

size_t WaveTrack::GetBestBlockSize ( sampleCount  t) const

Definition at line 2244 of file WaveTrack.cpp.

2245{
2246 auto bestBlockSize = GetMaxBlockSize();
2247
2248 for (const auto &clip : Intervals()) {
2249 auto startSample = clip->GetPlayStartSample();
2250 auto endSample = clip->GetPlayEndSample();
2251 if (s >= startSample && s < endSample)
2252 {
2253 // ignore extra channels (this function will soon be removed)
2254 bestBlockSize =
2255 clip->GetBestBlockSize(s - clip->GetSequenceStartSample());
2256 break;
2257 }
2258 }
2259
2260 return bestBlockSize;
2261}
size_t GetMaxBlockSize() const
Definition: WaveTrack.cpp:2263

References GetMaxBlockSize(), and Intervals().

Referenced by WaveChannel::GetBestBlockSize(), and anonymous_namespace{WaveTrackUtilities.cpp}::ReverseOneClip().

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

258 {
259 return this->ChannelGroup::GetChannel<WaveChannel>(iChannel); }

References anonymous_namespace{StretchingSequenceIntegrationTest.cpp}::iChannel.

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

Here is the caller graph for this function:

◆ GetChannel() [2/2]

auto WaveTrack::GetChannel ( size_t  iChannel) const
inline

Definition at line 260 of file WaveTrack.h.

260 {
261 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 870 of file WaveTrack.cpp.

871{
872 // channel is not necessarily less than the channel group width but
873 // a mono track might pan differently according to that
874 float left = 1.0;
875 float right = 1.0;
876
877 const auto pan = GetPan();
878 if (pan < 0)
879 right = (pan + 1.0);
880 else if (pan > 0)
881 left = 1.0 - pan;
882
883 const auto gain = GetGain();
884 if ((channel % 2) == 0)
885 return left * gain;
886 else
887 return right * gain;
888}
float GetPan() const
Definition: WaveTrack.cpp:842
float GetGain() const
Definition: WaveTrack.cpp:824

References GetGain(), and GetPan().

Referenced by WaveChannel::GetChannelGain(), and 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 546 of file WaveTrack.cpp.

547{
548 // Not quite meaningful but preserving old behavior
549 return (*Channels().begin())->WaveChannel::GetChannelType();
550}
auto Channels()
Definition: WaveTrack.h:263

References details::begin(), and Channels().

Here is the call graph for this function:

◆ GetClip() [1/2]

auto WaveTrack::GetClip ( size_t  iInterval)

Definition at line 691 of file WaveTrack.cpp.

692{
693 return std::static_pointer_cast<Interval>(DoGetInterval(iInterval));
694}
std::shared_ptr< WideChannelGroupInterval > DoGetInterval(size_t iInterval) override
Retrieve an interval.
Definition: WaveTrack.cpp:702

Referenced by GetClip(), HandleXMLChild(), MergeClips(), and PasteWaveTrackAtSameTempo().

Here is the caller graph for this function:

◆ GetClip() [2/2]

auto WaveTrack::GetClip ( size_t  iInterval) const

used only during deserialization

Definition at line 696 of file WaveTrack.cpp.

697{
698 return const_cast<WaveTrack&>(*this).GetClip(iInterval);
699}
IntervalHolder GetClip(size_t iInterval)
Definition: WaveTrack.cpp:691

References GetClip().

Here is the call graph for this function:

◆ GetClipAtTime()

auto WaveTrack::GetClipAtTime ( double  time) const
private

Definition at line 2933 of file WaveTrack.cpp.

2934{
2935 const auto clips = SortedClipArray();
2936 auto p = std::find_if(
2937 clips.rbegin(), clips.rend(), [&](const auto &pClip) {
2938 return pClip->WithinPlayRegion(time);
2939 });
2940 return p != clips.rend() ? *p : nullptr;
2941}
IntervalConstHolders SortedClipArray() const
Return all WaveClips sorted by clip play start time.
Definition: WaveTrack.cpp:3269

References WaveChannelUtilities::SortedClipArray().

Referenced by ApplyPitchAndSpeed().

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

◆ GetClipIndex()

int WaveTrack::GetClipIndex ( const Interval clip) const

Get the linear index of a given clip (== number of clips if not found)

Definition at line 3019 of file WaveTrack.cpp.

3020{
3021 int result = 0;
3022 const auto &clips = Intervals();
3023 const auto test =
3024 [&](const auto &pOtherClip){ return &clip == pOtherClip.get(); };
3025 auto begin = clips.begin(),
3026 end = clips.end(),
3027 iter = std::find_if(begin, end, test);
3028 return std::distance(begin, iter);
3029}

References details::begin(), details::end(), and Intervals().

Here is the call graph for this function:

◆ GetClipInterfaces()

ClipConstHolders WaveTrack::GetClipInterfaces ( ) const

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

Definition at line 2574 of file WaveTrack.cpp.

2575{
2576 auto clips = Intervals();
2577 return { clips.begin(), clips.end() };
2578}

References Intervals().

Here is the call graph for this function:

◆ GetDefaultAudioTrackNamePreference()

wxString WaveTrack::GetDefaultAudioTrackNamePreference ( )
static

Definition at line 373 of file WaveTrack.cpp.

374{
376
377 if (name.empty() || ( name == DefaultName.MSGID() ))
378 // When nothing was specified,
379 // the default-default is whatever translation of...
380 /* i18n-hint: The default name for an audio track. */
381 return DefaultName.Translation();
382 else
383 return name;
384}
static auto DefaultName
Definition: WaveTrack.cpp:364
StringSetting AudioTrackNameSetting
Definition: WaveTrack.cpp:3380
bool ReadWithDefault(T *pVar, const T &defaultValue) const
overload of ReadWithDefault returning a boolean that is true if the value was previously defined *‍/
Definition: Prefs.h:213

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

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

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

◆ GetEndTime()

double WaveTrack::GetEndTime ( ) const
overridevirtual

Implement WideSampleSequence.

Implements WideSampleSequence.

Definition at line 2595 of file WaveTrack.cpp.

2596{
2597 return ChannelGroup::GetEndTime();
2598}
double GetEndTime() const
Get the maximum of End() values of intervals, or 0 when none.
Definition: Channel.cpp:61

References ChannelGroup::GetEndTime().

Referenced by AUPImportFileHandle::AddSilence(), EffectTruncSilence::Analyze(), ApplyPitchAndSpeed(), ClearAndPasteAtSameTempo(), Copy(), FinishCopy(), Effect::GetBounds(), WaveChannel::GetEndTime(), 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:

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

2858{
2859 auto pTrack = this;
2860 if (!pTrack)
2861 return;
2862
2863 if (backwards)
2864 t0 -= bufferLen / pTrack->GetRate();
2865 // The output buffer corresponds to an unbroken span of time which the callers expect
2866 // to be fully valid. As clips are processed below, the output buffer is updated with
2867 // envelope values from any portion of a clip, start, end, middle, or none at all.
2868 // Since this does not guarantee that the entire buffer is filled with values we need
2869 // to initialize the entire buffer to a default value.
2870 //
2871 // This does mean that, in the cases where a usable clip is located, the buffer value will
2872 // be set twice. Unfortunately, there is no easy way around this since the clips are not
2873 // stored in increasing time order. If they were, we could just track the time as the
2874 // buffer is filled.
2875 for (decltype(bufferLen) i = 0; i < bufferLen; i++)
2876 {
2877 buffer[i] = 1.0;
2878 }
2879
2880 double startTime = t0;
2881 const auto rate = pTrack->GetRate();
2882 auto tstep = 1.0 / rate;
2883 double endTime = t0 + tstep * bufferLen;
2884 for (const auto &clip: pTrack->Intervals())
2885 {
2886 // IF clip intersects startTime..endTime THEN...
2887 auto dClipStartTime = clip->GetPlayStartTime();
2888 auto dClipEndTime = clip->GetPlayEndTime();
2889 if ((dClipStartTime < endTime) && (dClipEndTime > startTime))
2890 {
2891 auto rbuf = buffer;
2892 auto rlen = bufferLen;
2893 auto rt0 = t0;
2894
2895 if (rt0 < dClipStartTime)
2896 {
2897 // This is not more than the number of samples in
2898 // (endTime - startTime) which is bufferLen:
2899 auto nDiff = (sampleCount)floor((dClipStartTime - rt0) * rate + 0.5);
2900 auto snDiff = nDiff.as_size_t();
2901 rbuf += snDiff;
2902 wxASSERT(snDiff <= rlen);
2903 rlen -= snDiff;
2904 rt0 = dClipStartTime;
2905 }
2906
2907 if (rt0 + rlen*tstep > dClipEndTime)
2908 {
2909 auto nClipLen = clip->GetPlayEndSample() - clip->GetPlayStartSample();
2910
2911 if (nClipLen <= 0) // Testing for bug 641, this problem is consistently '== 0', but doesn't hurt to check <.
2912 return;
2913
2914 // This check prevents problem cited in http://bugzilla.audacityteam.org/show_bug.cgi?id=528#c11,
2915 // Gale's cross_fade_out project, which was already corrupted by bug 528.
2916 // This conditional prevents the previous write past the buffer end, in clip->GetEnvelope() call.
2917 // Never increase rlen here.
2918 // PRL bug 827: rewrote it again
2919 rlen = limitSampleBufferSize( rlen, nClipLen );
2920 rlen = std::min(rlen, size_t(floor(0.5 + (dClipEndTime - rt0) / tstep)));
2921 }
2922 // Samples are obtained for the purpose of rendering a wave track,
2923 // so quantize time
2924 clip->GetEnvelope().GetValues(rbuf, rlen, rt0, tstep);
2925 }
2926 }
2927 if (backwards)
2928 std::reverse(buffer, buffer + bufferLen);
2929}

References limitSampleBufferSize(), and min().

Referenced by WaveChannel::GetEnvelopeValues().

Here is the call graph for this function:
Here is the caller 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

Reimplemented from Track.

Definition at line 2530 of file WaveTrack.cpp.

2531{
2532 for (const auto &pClip : Intervals()) {
2533 const auto width = pClip->NChannels();
2534 for (size_t ii = 0; ii < width; ++ii)
2535 if (pClip->GetSequence(ii)->GetErrorOpening())
2536 return XO("A track has a corrupted sample sequence.");
2537 }
2538
2539 return {};
2540}
XO("Cut/Copy/Paste")

References Intervals(), and XO().

Here is the call graph for this function:

◆ GetGain()

float WaveTrack::GetGain ( ) const

Definition at line 824 of file WaveTrack.cpp.

825{
826 return WaveTrackData::Get(*this).GetGain();
827}

References BasicUI::Get().

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

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

◆ GetIdealBlockSize()

size_t WaveTrack::GetIdealBlockSize ( )

Definition at line 2284 of file WaveTrack.cpp.

2285{
2286 // ignore extra channels (this function will soon be removed)
2287 return (*NewestOrNewClip()->Channels().begin())->GetClip()
2288 .GetSequence(0)->GetIdealBlockSize();
2289}
IntervalHolder NewestOrNewClip()
Get access to the most recently added clip, or create a clip, if there is not already one....
Definition: WaveTrack.cpp:2984

References details::begin(), Channels(), 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 201 of file WaveTrack.cpp.

202{
203 IntervalHolder result;
204 for (const auto &interval : Intervals())
205 if (interval->WithinPlayRegion(t))
206 return interval;
207 return nullptr;
208}

References Intervals().

Referenced by ApplyPitchAndSpeed().

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

◆ GetLeftmostClip() [1/2]

auto WaveTrack::GetLeftmostClip ( )

Definition at line 2542 of file WaveTrack.cpp.

2542 {
2543 auto clips = Intervals();
2544 if (clips.empty())
2545 return nullptr;
2546 const auto begin = clips.begin(),
2547 iter = std::min_element(begin, clips.end(),
2548 [](const auto& a, const auto b) {
2549 return a->GetPlayStartTime() < b->GetPlayStartTime();
2550 });
2551 return GetClip(std::distance(begin, iter));
2552}

References details::begin().

Referenced by GetLeftmostClip(), and PasteWaveTrackAtSameTempo().

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

◆ GetLeftmostClip() [2/2]

auto WaveTrack::GetLeftmostClip ( ) const

Definition at line 2554 of file WaveTrack.cpp.

2554 {
2555 return const_cast<WaveTrack&>(*this).GetLeftmostClip();
2556}
IntervalHolder GetLeftmostClip()
Definition: WaveTrack.cpp:2542

References GetLeftmostClip().

Here is the call graph for this function:

◆ GetMaxBlockSize()

size_t WaveTrack::GetMaxBlockSize ( ) const

Definition at line 2263 of file WaveTrack.cpp.

2264{
2265 const auto clips = Intervals();
2266 auto maxblocksize = std::accumulate(clips.begin(), clips.end(), size_t{},
2267 [](size_t acc, auto pClip){
2268 return std::max(acc, pClip->GetMaxBlockSize()); });
2269
2270 if (maxblocksize == 0)
2271 {
2272 // We really need the maximum block size, so create a
2273 // temporary sequence to get it.
2274 maxblocksize =
2276 .GetMaxBlockSize();
2277 }
2278
2279 wxASSERT(maxblocksize > 0);
2280
2281 return maxblocksize;
2282}
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 GetSampleFormat(), Intervals(), and mpFactory.

Referenced by EffectTruncSilence::Analyze(), CompareAudioCommand::Apply(), GetBestBlockSize(), WaveChannel::GetMaxBlockSize(), EffectStereoToMono::ProcessOne(), PerTrackEffect::ProcessPass(), and anonymous_namespace{WaveTrackUtilities.cpp}::ReverseOneClip().

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

2324{
2325 return PlayableTrack::GetMute();
2326}
bool GetMute() const
Definition: PlayableTrack.h:47

References PlayableTrack::GetMute().

Referenced by ExportAudioDialog::DoExportSplitByTracks(), ExportUtils::FindExportWaveTracks(), GetInfoCommand::SendTracks(), and ExportAudioDialog::UpdateTrackExportSettings().

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

196{
197 return std::const_pointer_cast<Interval>(
198 std::as_const(*this).GetNextInterval(interval, searchDirection));
199}

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

174{
175 std::shared_ptr<const Interval> result;
176 auto bestMatchTime = searchDirection == PlaybackDirection::forward
177 ? std::numeric_limits<double>::max()
178 : std::numeric_limits<double>::lowest();
179
180 for (const auto &other : Intervals()) {
181 if((searchDirection == PlaybackDirection::forward &&
182 (other->Start() > interval.Start() && other->Start() < bestMatchTime))
183 ||
184 (searchDirection == PlaybackDirection::backward &&
185 (other->Start() < interval.Start() && other->Start() > bestMatchTime)))
186 {
187 result = other;
188 bestMatchTime = other->Start();
189 }
190 }
191 return result;
192}
STL namespace.

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

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

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

◆ GetNumClips()

int WaveTrack::GetNumClips ( ) const

Definition at line 3031 of file WaveTrack.cpp.

3032{
3033 return NarrowClips().size();
3034}
WaveClipHolders & NarrowClips()
Definition: WaveTrack.cpp:749

References NarrowClips().

Referenced by ApplyPitchAndSpeed(), and PasteWaveTrackAtSameTempo().

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

◆ GetOne()

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

Definition at line 2633 of file WaveTrack.cpp.

2637{
2638 if (backwards)
2639 start -= len;
2640 // Simple optimization: When this buffer is completely contained within one clip,
2641 // don't clear anything (because we won't have to). Otherwise, just clear
2642 // everything to be on the safe side.
2643 bool doClear = true;
2644 bool result = true;
2645 sampleCount samplesCopied = 0;
2646 for (const auto &clip: clips)
2647 {
2648 if (start >= clip->GetPlayStartSample() && start+len <= clip->GetPlayEndSample())
2649 {
2650 doClear = false;
2651 break;
2652 }
2653 }
2654 if (doClear)
2655 {
2656 // Usually we fill in empty space with zero
2657 if (fill == FillFormat::fillZero)
2658 ClearSamples(buffer, format, 0, len);
2659 // but we don't have to.
2660 else if (fill == FillFormat::fillTwo)
2661 {
2662 wxASSERT( format==floatSample );
2663 float * pBuffer = (float*)buffer;
2664 for(size_t i=0;i<len;i++)
2665 pBuffer[i]=2.0f;
2666 }
2667 else
2668 {
2669 wxFAIL_MSG(wxT("Invalid fill format"));
2670 }
2671 }
2672
2673 // Iterate the clips. They are not necessarily sorted by time.
2674 for (const auto &clip: clips)
2675 {
2676 auto clipStart = clip->GetPlayStartSample();
2677 auto clipEnd = clip->GetPlayEndSample();
2678
2679 if (clipEnd > start && clipStart < start+len)
2680 {
2681 if (clip->HasPitchOrSpeed())
2682 return false;
2683
2684 // Clip sample region and Get/Put sample region overlap
2685 auto samplesToCopy =
2686 std::min( start+len - clipStart, clip->GetVisibleSampleCount() );
2687 auto startDelta = clipStart - start;
2688 decltype(startDelta) inclipDelta = 0;
2689 if (startDelta < 0)
2690 {
2691 inclipDelta = -startDelta; // make positive value
2692 samplesToCopy -= inclipDelta;
2693 // samplesToCopy is now either len or
2694 // (clipEnd - clipStart) - (start - clipStart)
2695 // == clipEnd - start > 0
2696 // samplesToCopy is not more than len
2697 //
2698 startDelta = 0;
2699 // startDelta is zero
2700 }
2701 else {
2702 // startDelta is nonnegative and less than len
2703 // samplesToCopy is positive and not more than len
2704 }
2705
2706 if (!clip->GetSamples(iChannel,
2707 (samplePtr)(((char*)buffer) +
2708 startDelta.as_size_t() *
2710 format, inclipDelta, samplesToCopy.as_size_t(), mayThrow ))
2711 result = false;
2712 else
2713 samplesCopied += samplesToCopy;
2714 }
2715 }
2716 if( pNumWithinClips )
2717 *pNumWithinClips = samplesCopied;
2718 if (result == true && backwards)
2719 ReverseSamples(buffer, format, 0, len);
2720 return result;
2721}
wxT("CloseDown"))
void ReverseSamples(samplePtr dst, sampleFormat format, int start, int len)
void ClearSamples(samplePtr dst, sampleFormat format, size_t start, size_t len)
#define SAMPLE_SIZE(SampleFormat)
Definition: SampleFormat.h:52

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

Referenced by DoGet().

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

◆ GetPan()

float WaveTrack::GetPan ( ) const

Definition at line 842 of file WaveTrack.cpp.

843{
844 return WaveTrackData::Get(*this).GetPan();
845}

References BasicUI::Get().

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

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

◆ GetRate()

double WaveTrack::GetRate ( ) const
overridevirtual

◆ GetRightmostClip() [1/2]

auto WaveTrack::GetRightmostClip ( )

Definition at line 2558 of file WaveTrack.cpp.

2558 {
2559 auto clips = Intervals();
2560 if (clips.empty())
2561 return nullptr;
2562 const auto begin = clips.begin(),
2563 iter = std::max_element(begin, clips.end(),
2564 [](const auto& a, const auto b) {
2565 return a->GetPlayEndTime() < b->GetPlayEndTime();
2566 });
2567 return GetClip(std::distance(begin, iter));
2568}

References details::begin().

Referenced by Flush(), GetRightmostClip(), and PasteWaveTrackAtSameTempo().

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

◆ GetRightmostClip() [2/2]

auto WaveTrack::GetRightmostClip ( ) const

Definition at line 2570 of file WaveTrack.cpp.

2570 {
2571 return const_cast<WaveTrack&>(*this).GetRightmostClip();
2572}

References GetRightmostClip().

Here is the call graph for this function:

◆ GetSampleBlockFactory()

const SampleBlockFactoryPtr & WaveTrack::GetSampleBlockFactory ( ) const
inline

Definition at line 253 of file WaveTrack.h.

254 { return mpFactory; }

Referenced by CopyPartOfClip(), and CopyWholeClip().

Here is the caller graph for this function:

◆ GetSampleFormat()

sampleFormat WaveTrack::GetSampleFormat ( ) const
overridevirtual

Implements RecordableSequence.

Definition at line 900 of file WaveTrack.cpp.

901{
902 return WaveTrackData::Get(*this).GetSampleFormat();
903}

References BasicUI::Get().

Referenced by EmptyCopy(), GetMaxBlockSize(), WaveChannel::GetSampleFormat(), and WaveTrackMenuTable::OnMergeStereo().

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.

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

Definition at line 2724 of file WaveTrack.cpp.

2725{
2727 for (const auto& channel : Channels()) {
2728 result.push_back(channel->GetSampleView(t0, t1, mayThrow));
2729 }
2730 return result;
2731}
std::vector< std::vector< AudioSegmentSampleView > > ChannelGroupSampleView
Definition: MixerBoard.h:35

References Channels().

Here is the call graph for this function:

◆ GetSolo()

bool WaveTrack::GetSolo ( ) const
overridevirtual

May vary asynchronously.

Implements PlayableSequence.

Definition at line 2328 of file WaveTrack.cpp.

2329{
2330 return PlayableTrack::GetSolo();
2331}
bool GetSolo() const
Definition: PlayableTrack.h:48

References PlayableTrack::GetSolo().

Referenced by ExportAudioDialog::DoExportSplitByTracks(), WaveformView::Draw(), ExportUtils::FindExportWaveTracks(), 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 2585 of file WaveTrack.cpp.

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

References ChannelGroup::GetStartTime().

Referenced by ApplyPitchAndSpeed(), Effect::GetBounds(), TranscriptionToolBar::GetSamples(), WaveChannel::GetStartTime(), 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 665 of file WaveTrack.cpp.

666{
667 return typeInfo();
668}

References typeInfo().

Here is the call graph for this function:

◆ GetVisibleSampleCount()

sampleCount WaveTrack::GetVisibleSampleCount ( ) const

Definition at line 890 of file WaveTrack.cpp.

891{
892 sampleCount result{ 0 };
893
894 for (const auto& clip : Intervals())
895 result += clip->GetVisibleSampleCount();
896
897 return result;
898}

References Intervals().

Here is the call 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 1532 of file WaveTrack.cpp.

1534{
1535 // For debugging, use an ASSERT so that we stop
1536 // closer to the problem.
1537 wxASSERT( t1 >= t0 );
1538 if (t1 < t0)
1540
1541 t0 = SnapToSample(t0);
1542 t1 = SnapToSample(t1);
1543
1544 IntervalHolders clipsToDelete;
1545 IntervalHolders clipsToAdd;
1546
1547 // We only add cut lines when deleting in the middle of a single clip
1548 // The cut line code is not really prepared to handle other situations
1549 if (addCutLines)
1550 for (const auto &clip : Intervals())
1551 if (clip->PartlyWithinPlayRegion(t0, t1)) {
1552 addCutLines = false;
1553 break;
1554 }
1555
1556 for (const auto &clip : Intervals()) {
1557 if (clip->CoversEntirePlayRegion(t0, t1))
1558 // Whole clip must be deleted - remember this
1559 clipsToDelete.push_back(clip);
1560 else if (clip->IntersectsPlayRegion(t0, t1)) {
1561 // Clip data is affected by command
1562 if (addCutLines) {
1563 // Don't modify this clip in place, because we want a strong
1564 // guarantee, and might modify another clip
1565 clipsToDelete.push_back(clip);
1566 auto newClip = CopyClip(*clip, true);
1567 newClip->ClearAndAddCutLine(t0, t1);
1568 clipsToAdd.push_back(move(newClip));
1569 }
1570 else {
1571 if (split || clearByTrimming) {
1572 // Three cases:
1573
1574 if (clip->BeforePlayRegion(t0)) {
1575 // Delete from the left edge
1576
1577 // Don't modify this clip in place, because we want a strong
1578 // guarantee, and might modify another clip
1579 clipsToDelete.push_back(clip);
1580 auto newClip = CopyClip(*clip, true);
1581 newClip->TrimLeft(t1 - clip->GetPlayStartTime());
1582 if (!split)
1583 // If this is not a split-cut, where things are left in
1584 // place, we need to reposition the clip.
1585 newClip->ShiftBy(t0 - t1);
1586 clipsToAdd.push_back(move(newClip));
1587 }
1588 else if (clip->AfterPlayRegion(t1)) {
1589 // Delete to right edge
1590
1591 // Don't modify this clip in place, because we want a strong
1592 // guarantee, and might modify another clip
1593 clipsToDelete.push_back(clip);
1594 auto newClip = CopyClip(*clip, true);
1595 newClip->TrimRight(clip->GetPlayEndTime() - t0);
1596
1597 clipsToAdd.push_back(move(newClip));
1598 }
1599 else {
1600 // Delete in the middle of the clip...we actually create two
1601 // NEW clips out of the left and right halves...
1602
1603 auto leftClip = CopyClip(*clip, true);
1604 leftClip->TrimRight(clip->GetPlayEndTime() - t0);
1605 clipsToAdd.push_back(move(leftClip));
1606
1607 auto rightClip = CopyClip(*clip, true);
1608 rightClip->TrimLeft(t1 - clip->GetPlayStartTime());
1609 if (!split)
1610 // If this is not a split-cut, where things are left in
1611 // place, we need to reposition the clip.
1612 rightClip->ShiftBy(t0 - t1);
1613 clipsToAdd.push_back(move(rightClip));
1614
1615 clipsToDelete.push_back(clip);
1616 }
1617 }
1618 else {
1619 // (We are not doing a split cut)
1620
1621 // Don't modify this clip in place, because we want a strong
1622 // guarantee, and might modify another clip
1623 clipsToDelete.push_back(clip);
1624 auto newClip = CopyClip(*clip, true);
1625
1626 // clip->Clear keeps points < t0 and >= t1 via Envelope::CollapseRegion
1627 newClip->Clear(t0,t1);
1628
1629 clipsToAdd.push_back(move(newClip));
1630 }
1631 }
1632 }
1633 }
1634
1635 // Only now, change the contents of this track
1636 // use No-fail-guarantee for the rest
1637
1638 for (const auto &clip: clipsToDelete)
1639 RemoveInterval(clip);
1640
1641 const auto moveClipsLeft = !split && GetEditClipsCanMove();
1642 if (moveClipsLeft)
1643 // Clip is "behind" the region -- offset it unless we're splitting
1644 // or we're using the "don't move other clips" mode
1645 for (const auto &clip : Intervals())
1646 if (clip->AtOrBeforePlayRegion(t1))
1647 clip->ShiftBy(-(t1 - t0));
1648
1649 for (auto &clip: clipsToAdd)
1650 InsertInterval(move(clip), false);
1651}
bool GetEditClipsCanMove()
Definition: WaveTrack.cpp:3390
void RemoveInterval(const IntervalHolder &interval)
Definition: WaveTrack.cpp:3228

References CopyClip(), GetEditClipsCanMove(), InsertInterval(), Intervals(), RemoveInterval(), WideSampleSequence::SnapToSample(), and THROW_INCONSISTENCY_EXCEPTION.

Referenced by Clear(), ClearAndAddCutLine(), and SplitDelete().

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

2408{
2409 if (auto pChild = WaveTrackIORegistry::Get().CallObjectAccessor(tag, *this))
2410 // Deserialize any extra attached structures
2411 return pChild;
2412
2413 const auto getClip = [this]() -> WaveClip & {
2414 return (*NewestOrNewClip()->Channels().begin())->GetClip();
2415 };
2416
2417 //
2418 // This is legacy code (1.2 and previous) and is not called for new projects!
2419 if (tag == Sequence::Sequence_tag || tag == "envelope") {
2420 // This is a legacy project, so set the cached offset
2421 NewestOrNewClip()->SetSequenceStartTime(mLegacyProjectFileOffset);
2422
2423 // Legacy project file tracks are imported as one single wave clip
2424 if (tag == Sequence::Sequence_tag)
2425 return getClip().GetSequence(0);
2426 else if (tag == "envelope")
2427 return &getClip().GetEnvelope();
2428 }
2429
2430 // JKC... for 1.1.0, one step better than what we had, but still badly broken.
2431 // If we see a waveblock at this level, we'd better generate a sequence.
2432 if (tag == Sequence::WaveBlock_tag) {
2433 // This is a legacy project, so set the cached offset
2434 NewestOrNewClip()->SetSequenceStartTime(mLegacyProjectFileOffset);
2435 auto pSeq = getClip().GetSequence(0);
2436 return pSeq;
2437 }
2438
2439 // This is for the new file format (post-1.2)
2440 if (tag == WaveClip::WaveClip_tag) {
2441 // Make clips (which don't serialize the rate) consistent with channel rate,
2442 // though the consistency check of channels with each other remains to do.
2443 // Not all `WaveTrackData` fields are properly initialized by now,
2444 // use deserialization helpers.
2445 auto clip = std::make_shared<WaveClip>(1,
2447 const auto xmlHandler = clip.get();
2448 auto &clips = NarrowClips();
2449 clips.push_back(std::move(clip));
2450 Publish({ clips.back(), WaveTrackMessage::Deserialized });
2451 return xmlHandler;
2452 }
2453
2454 return nullptr;
2455}
CallbackReturn Publish(const WaveTrackMessage &message)
Send a message to connected callbacks.
Definition: Observer.h:207
static const char * Sequence_tag
Definition: Sequence.h:56
static const char * WaveBlock_tag
Definition: Sequence.h:57
This allows multiple clips to be a part of one WaveTrack.
Definition: WaveClip.h:238
static const char * WaveClip_tag
Definition: WaveClip.h:249
double mLegacyProjectFileOffset
Definition: WaveTrack.h:833
static XMLMethodRegistry & Get()
Get the unique instance.
@ Deserialized
being read from project file
Definition: WaveTrack.h:76

References WaveTrackMessage::Deserialized, XMLMethodRegistry< Host >::Get(), GetClip(), mLegacyFormat, mLegacyProjectFileOffset, mLegacyRate, mpFactory, NarrowClips(), NewestOrNewClip(), Observer::Publisher< WaveTrackMessage >::Publish(), Sequence::Sequence_tag, Sequence::WaveBlock_tag, and WaveClip::WaveClip_tag.

Here is the call graph for this function:

◆ HandleXMLEndTag()

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

Definition at line 2395 of file WaveTrack.cpp.

2396{
2397#if 0
2398 // In case we opened a pre-multiclip project, we need to
2399 // simulate closing the waveclip tag.
2400 NewestOrNewClip()->HandleXMLEndTag(WaveClip::WaveClip_tag);
2401#else
2402 // File compatibility breaks have intervened long since, and the line above
2403 // would now have undesirable side effects
2404#endif
2405}

References NewestOrNewClip(), and WaveClip::WaveClip_tag.

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

2344{
2345 if (tag == WaveTrack_tag) {
2346 double dblValue;
2347 long nValue;
2348
2349 for (const auto& pair : attrs)
2350 {
2351 const auto& attr = pair.first;
2352 const auto& value = pair.second;
2353
2354 if (attr == Rate_attr)
2355 {
2356 // mRate is an int, but "rate" in the project file is a float.
2357 if (!value.TryGet(dblValue) ||
2358 (dblValue < 1.0) || (dblValue > 1000000.0)) // allow a large range to be read
2359 return false;
2360
2361 // Defer the setting of rate until LinkConsistencyFix
2362 mLegacyRate = lrint(dblValue);
2363 }
2364 else if (attr == Offset_attr && value.TryGet(dblValue))
2365 {
2366 // Offset is only relevant for legacy project files. The value
2367 // is cached until the actual WaveClip containing the legacy
2368 // track is created.
2369 mLegacyProjectFileOffset = dblValue;
2370 }
2371 else if (this->WritableSampleTrack::HandleXMLAttribute(attr, value))
2372 {}
2373 else if (this->Track::HandleCommonXMLAttribute(attr, value))
2374 ;
2375 else if (attr == Gain_attr && value.TryGet(dblValue))
2376 DoSetGain(dblValue);
2377 else if (attr == Pan_attr && value.TryGet(dblValue) &&
2378 (dblValue >= -1.0) && (dblValue <= 1.0))
2379 DoSetPan(dblValue);
2380 else if (attr == Linked_attr && value.TryGet(nValue))
2381 SetLinkType(ToLinkType(nValue), false);
2382 else if (attr == SampleFormat_attr && value.TryGet(nValue) &&
2384 {
2385 //Remember sample format until consistency check is performed.
2386 SetLegacyFormat(static_cast<sampleFormat>(nValue));
2387 }
2388 } // while
2389 return true;
2390 }
2391
2392 return false;
2393}
sampleFormat
The ordering of these values with operator < agrees with the order of increasing bit width.
Definition: SampleFormat.h:30
static constexpr auto Pan_attr
Definition: WaveTrack.cpp:2338
static constexpr auto Rate_attr
Definition: WaveTrack.cpp:2336
static constexpr auto SampleFormat_attr
Definition: WaveTrack.cpp:2340
static constexpr auto Offset_attr
Definition: WaveTrack.cpp:2335
static constexpr auto Linked_attr
Definition: WaveTrack.cpp:2339
static constexpr auto Gain_attr
Definition: WaveTrack.cpp:2337
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:1905
void SetLinkType(LinkType linkType, bool completeList=true)
Definition: Track.cpp:136
bool HandleCommonXMLAttribute(const std::string_view &attr, const XMLAttributeValueView &valueView)
Definition: Track.cpp:819
void DoSetPan(float value)
Definition: WaveTrack.cpp:847
static const char * WaveTrack_tag
Definition: WaveTrack.h:206
void SetLegacyFormat(sampleFormat format)
Definition: WaveTrack.cpp:2313
void DoSetGain(float value)
Definition: WaveTrack.cpp:829
#define lrint(dbl)
Definition: float_cast.h:169
Track::LinkType ToLinkType(int value)
Definition: WaveTrack.cpp:345

References DoSetGain(), DoSetPan(), Gain_attr, Track::HandleCommonXMLAttribute(), PlayableTrack::HandleXMLAttribute(), Sequence::IsValidSampleFormat(), Linked_attr, lrint, mLegacyProjectFileOffset, mLegacyRate, Offset_attr, Pan_attr, Rate_attr, SampleFormat_attr, SetLegacyFormat(), Track::SetLinkType(), anonymous_namespace{WaveTrack.cpp}::ToLinkType(), and WaveTrack_tag.

Here is the call graph for this function:

◆ HasClipNamed()

bool WaveTrack::HasClipNamed ( const wxString &  name) const

Definition at line 709 of file WaveTrack.cpp.

710{
711 auto clips = Intervals();
712 return std::any_of(clips.begin(), clips.end(),
713 [&](const auto &pClip){ return pClip->GetName() == name; });
714}

References Intervals().

Referenced by ProjectAudioManager::DoRecord(), MakeClipCopyName(), and MakeNewClipName().

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

◆ HasTrivialEnvelope()

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

Implements WideSampleSequence.

Definition at line 2840 of file WaveTrack.cpp.

2841{
2842 auto pTrack = this;
2843 if (!pTrack)
2844 return false;
2845 auto clips = pTrack->Intervals();
2846 return std::all_of(clips.begin(), clips.end(),
2847 [](const auto &pClip){ return pClip->GetEnvelope().IsTrivial(); });
2848}

Referenced by WaveChannel::HasTrivialEnvelope().

Here is the caller graph for this function:

◆ Init()

void WaveTrack::Init ( const WaveTrack orig)

Overwrite data excluding the sample sequence but including display settings

Definition at line 553 of file WaveTrack.cpp.

554{
556 mpFactory = orig.mpFactory;
557}
void Init(const Track &orig)
Definition: Track.cpp:47

References Track::Init(), and mpFactory.

Referenced by ProjectAudioManager::DoRecord().

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

◆ InsertClip()

bool WaveTrack::InsertClip ( WaveClipHolders clips,
WaveClipHolder  clip,
bool  newClip,
bool  backup,
bool  allowEmpty 
)
private

Sets project tempo on clip upon push. Use this instead of NarrowClips().push_back

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

Definition at line 1913 of file WaveTrack.cpp.

1915{
1916 if (!backup && !clip->GetIsPlaceholder() && !allowEmpty && clip->IsEmpty())
1917 return false;
1918
1919 const auto& tempo = GetProjectTempo(*this);
1920 if (tempo.has_value())
1921 clip->OnProjectTempoChange(std::nullopt, *tempo);
1922 clips.push_back(std::move(clip));
1923 Publish({ clips.back(),
1925
1926 return true;
1927}
@ New
newly created and empty
Definition: WaveTrack.h:75
@ Inserted
(partly) copied from another clip, or moved from a track
Definition: WaveTrack.h:77

References GetProjectTempo(), WaveTrackMessage::Inserted, WaveTrackMessage::New, and Observer::Publisher< WaveTrackMessage >::Publish().

Referenced by CopyClips(), and InsertInterval().

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

◆ InsertInterval()

void WaveTrack::InsertInterval ( const IntervalHolder interval,
bool  newClip,
bool  allowEmpty = false 
)

Definition at line 3217 of file WaveTrack.cpp.

3219{
3220 if (clip) {
3221 constexpr bool backup = false;
3222 InsertClip(mClips, clip, newClip, backup, allowEmpty);
3223 // Detect errors resulting in duplicate shared pointers to clips
3224 assert(ClipsAreUnique(mClips));
3225 }
3226}
bool ClipsAreUnique(const WaveClipHolders &clips)
Definition: WaveTrack.cpp:3209

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

Referenced by CopyPartOfClip(), CopyWholeClip(), ProjectAudioManager::DoRecord(), FinishCopy(), HandleClear(), AUPImportFileHandle::HandleWaveClip(), InsertSilence(), Join(), ReplaceInterval(), and WaveTrackUtilities::Reverse().

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

2008{
2009 // Nothing to do, if length is zero.
2010 // Fixes Bug 1626
2011 if (len == 0)
2012 return;
2013 if (len <= 0)
2015
2016 auto &&clips = Intervals();
2017 if (clips.empty()) {
2018 // Special case if there is no clip yet
2019 auto clip = CreateClip(0);
2020 clip->InsertSilence(0, len);
2021 // use No-fail-guarantee
2022 InsertInterval(move(clip), true);
2023 }
2024 else
2025 {
2026 // Assume at most one clip contains t
2027 const auto end = clips.end();
2028 const auto it = std::find_if(clips.begin(), end,
2029 [&](const IntervalHolder &clip) { return clip->SplitsPlayRegion(t); } );
2030
2031 // use Strong-guarantee
2032 if (it != end)
2033 (*it)->InsertSilence(t, len);
2034
2035 // use No-fail-guarantee
2036 for (const auto &&clip : clips)
2037 if (clip->BeforePlayRegion(t))
2038 clip->ShiftBy(len);
2039 }
2040}

References CreateClip(), details::end(), InsertInterval(), Intervals(), and THROW_INCONSISTENCY_EXCEPTION.

Referenced by AUPImportFileHandle::AddSilence(), and EffectSilence::GenerateTrack().

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

◆ Intervals() [1/2]

auto WaveTrack::Intervals ( )
inline

◆ Intervals() [2/2]

auto WaveTrack::Intervals ( ) const
inline

Definition at line 671 of file WaveTrack.h.

671{ 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 915 of file WaveTrack.cpp.

916{
917 if (t0 > t1)
918 return true;
919
920 //wxPrintf("Searching for overlap in %.6f...%.6f\n", t0, t1);
921 for (const auto &clip : Intervals())
922 {
923 if (clip->IntersectsPlayRegion(t0, t1)) {
924 //wxPrintf("Overlapping clip: %.6f...%.6f\n",
925 // clip->GetStartTime(),
926 // clip->GetEndTime());
927 // We found a clip that overlaps this region
928 return false;
929 }
930 }
931 //wxPrintf("No overlap found\n");
932
933 // Otherwise, no clips overlap this region
934 return true;
935}

References Intervals().

Referenced by SyncLockAdjust().

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

◆ Join()

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

Definition at line 2132 of file WaveTrack.cpp.

2134{
2135 // Merge all WaveClips overlapping selection into one
2136 const auto &intervals = Intervals();
2137
2138 {
2139 IntervalHolders intervalsToJoin;
2140 for (const auto &interval : intervals)
2141 if (interval->IntersectsPlayRegion(t0, t1))
2142 intervalsToJoin.push_back(interval);
2143 if (intervalsToJoin.size() < 2u)
2144 return;
2145 if (std::any_of(
2146 intervalsToJoin.begin() + 1, intervalsToJoin.end(),
2147 [first = intervalsToJoin[0]](const auto& interval) {
2148 return !first->HasEqualPitchAndSpeed(*interval);
2149 }))
2150 ApplyPitchAndSpeedOnIntervals(intervalsToJoin, reportProgress);
2151 }
2152
2153 IntervalHolders clipsToDelete;
2154 IntervalHolder newClip{};
2155
2156 const auto rate = GetRate();
2157 for (const auto &clip: intervals) {
2158 if (clip->IntersectsPlayRegion(t0, t1)) {
2159 // Put in sorted order
2160 auto it = clipsToDelete.begin(), end = clipsToDelete.end();
2161 for (; it != end; ++it)
2162 if ((*it)->GetPlayStartTime() > clip->GetPlayStartTime())
2163 break;
2164 //wxPrintf("Insert clip %.6f at position %d\n", clip->GetStartTime(), i);
2165 clipsToDelete.insert(it, clip);
2166 }
2167 }
2168
2169 //if there are no clips to delete, nothing to do
2170 if (clipsToDelete.empty())
2171 return;
2172
2173 const auto firstToDelete = clipsToDelete[0].get();
2174 auto t = firstToDelete->GetPlayStartTime();
2175 //preserve left trim data if any
2176 newClip = CreateClip(
2177 firstToDelete->GetSequenceStartTime(),
2178 firstToDelete->GetName());
2179
2180 for (const auto &clip : clipsToDelete) {
2181 // wxPrintf("t=%.6f adding clip (offset %.6f, %.6f ... %.6f)\n",
2182 // t, clip->GetOffset(), clip->GetStartTime(),
2183 // clip->GetEndTime());
2184
2185 if (clip->GetPlayStartTime() - t > (1.0 / rate))
2186 {
2187 double addedSilence = (clip->GetPlayStartTime() - t);
2188 // wxPrintf("Adding %.6f seconds of silence\n");
2189 auto offset = clip->GetPlayStartTime();
2190 auto value = clip->GetEnvelope().GetValue(offset);
2191 newClip->AppendSilence(addedSilence, value);
2192 t += addedSilence;
2193 }
2194
2195 // wxPrintf("Pasting at %.6f\n", t);
2196 bool success = newClip->Paste(t, *clip);
2197 assert(success); // promise of DoCreateClip
2198
2199 t = newClip->GetPlayEndTime();
2200
2201 RemoveClip(FindClip(*clip));
2202 }
2203
2204 InsertInterval(move(newClip), false);
2205}
void RemoveClip(std::ptrdiff_t distance)
Definition: WaveTrack.cpp:1524
std::ptrdiff_t FindClip(const Interval &clip)
Definition: WaveTrack.cpp:1515

References ApplyPitchAndSpeedOnIntervals(), CreateClip(), details::end(), FindClip(), GetRate(), InsertInterval(), Intervals(), and RemoveClip().

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

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

◆ JoinOne()

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

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

581{
582 // This implies satisfaction of the precondition of SetRate()
583 assert(!doFix || IsLeader());
584
585 const auto removeZeroClips = [](WaveClipHolders& clips) {
586 // Check for zero-length clips and remove them
587 for (auto it = clips.begin(); it != clips.end();)
588 {
589 if ((*it)->IsEmpty())
590 it = clips.erase(it);
591 else
592 ++it;
593 }
594 };
595
597
598 auto linkType = GetLinkType();
599 if (linkType != LinkType::None) {
600 auto next = *TrackList::Channels(this).first.advance(1);
601 if (next == nullptr) {
602 //next track is absent or not a wave track, fix and report error
603 if (doFix) {
604 wxLogWarning(L"Right track %s is expected to be a WaveTrack."
605 "\n Removing link from left wave track %s.",
606 next->GetName(), GetName());
608 }
609 err = true;
610 }
611 else if (doFix) {
612 // non-error upgrades happen here
613 if (!AreAligned(SortedClipArray(), next->SortedClipArray()) ||
615 {
616 SetLinkType(linkType = LinkType::None);
617 }
618 else
619 {
620 SetLinkType(linkType = LinkType::Aligned);
621 //clean up zero clips only after alignment check has completed
622 //this can't break alignment as there should be a "twin"
623 //in the right channel which will also be removed, otherwise
624 //track will be unlinked because AreAligned returned false
625 removeZeroClips(NarrowClips());
626 removeZeroClips(next->NarrowClips());
627 }
628 }
629 }
630 if (doFix) {
631 // More non-error upgrading
632 // Set the common channel group rate from the unzipped leader's rate
633 if (mLegacyRate > 0)
634 {
635 WaveTrack *next{};
636 if (linkType != LinkType::None)
637 next = *TrackList::Channels(this).first.advance(1);
639 mLegacyRate = 0;
640 if (next)
641 next->mLegacyRate = 0;
643 WaveTrackData::Get(*this).SetSampleFormat(mLegacyFormat);
644 if (next && next->mLegacyFormat != undefinedSample)
645 WaveTrackData::Get(*next).SetSampleFormat(mLegacyFormat);
646 }
647 if (linkType == LinkType::None)
648 // Did not visit the other call to removeZeroClips, do it now
649 removeZeroClips(NarrowClips());
650 else
651 // Make a real wide wave track from two deserialized narrow tracks
652 ZipClips();
653 }
654 return !err;
655}
std::vector< WaveClipHolder > WaveClipHolders
Definition: WaveClip.h:45
@ 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:266
const wxString & GetName() const
Name is always the same for all channels of a group.
Definition: Track.cpp:64
bool IsLeader() const
Definition: Track.cpp:261
LinkType GetLinkType() const noexcept
Definition: Track.cpp:853
void SetRate(double newRate)
!brief Sets the new rate for the track without resampling it
Definition: WaveTrack.cpp:808
void ZipClips(bool mustAlign=true)
Definition: WaveTrack.cpp:3299
bool FormatConsistencyCheck() const
Definition: WaveTrack.cpp:1904
bool RateConsistencyCheck() const
Whether all clips of an unzipped leader track have a common rate.
Definition: WaveTrack.cpp:1885
bool AreAligned(const WaveTrack::IntervalConstHolders &a, const WaveTrack::IntervalConstHolders &b)
Definition: WaveTrack.cpp:324

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

Here is the call graph for this function:

◆ MakeClipCopyName()

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

Definition at line 774 of file WaveTrack.cpp.

775{
776 auto name = originalName;
777 for (auto i = 1;; ++i)
778 {
779 if (!HasClipNamed(name))
780 return name;
781 //i18n-hint Template for clip name generation on copy-paste
782 name = XC("%s.%i", "clip name template").Format(originalName, i).Translation();
783 }
784}
#define XC(s, c)
Definition: Internat.h:37
bool HasClipNamed(const wxString &name) const
Definition: WaveTrack.cpp:709

References HasClipNamed(), name, and XC.

Here is the call graph for this function:

◆ MakeMono()

void WaveTrack::MakeMono ( )

Simply discard any right channel.

Definition at line 1021 of file WaveTrack.cpp.

1022{
1023 mRightChannel.reset();
1024 for (auto &pClip : mClips)
1025 pClip->DiscardRightChannel();
1027}
void EraseChannelAttachments(size_t index)
Erase all attachments for a given index.
Definition: WaveTrack.cpp:452

References EraseChannelAttachments(), mClips, and mRightChannel.

Referenced by EffectStereoToMono::ProcessOne().

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

787{
788 auto name = GetName();
789 for (auto i = 1;; ++i)
790 {
791 if (!HasClipNamed(name))
792 return name;
793 //i18n-hint Template for clip name generation on inserting new empty clip
794 name = XC("%s %i", "clip name template").Format(GetName(), i).Translation();
795 }
796}

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

Here is the call graph for this function:

◆ MergeChannelAttachments()

void WaveTrack::MergeChannelAttachments ( WaveTrack &&  other)
private

Steal channel attachments from other, then destroy the track attachment slot

Definition at line 429 of file WaveTrack.cpp.

430{
432 [this](TrackAttachment *pLeft, TrackAttachment *pRight){
433 // Precondition of callback from ClientData::Site
434 assert(pLeft && pRight);
435 const auto pLeftAttachments =
436 dynamic_cast<ChannelAttachmentsBase *>(pLeft);
437 const auto pRightAttachments =
438 dynamic_cast<ChannelAttachmentsBase *>(pRight);
439 // They should have come from the same factory of channel attachments
440 assert((pLeftAttachments == nullptr) == (pRightAttachments == nullptr));
441 if (pLeftAttachments) {
442 // First fixup the back-pointers from channel views to their track
443 pRightAttachments->Reparent(shared_from_this());
444 // Then "steal" them
445 pLeftAttachments->MakeStereo(shared_from_this(),
446 std::move(*pRightAttachments));
447 }
448 });
449}
void ForCorresponding(Site &other, const Function &function, bool create=true)
Definition: ClientData.h:428

References ClientData::Site< Host, ClientData, ObjectCopyingPolicy, Pointer, ObjectLockingPolicy, RegistryLockingPolicy >::ForCorresponding().

Referenced by ZipClips().

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

3168{
3169 const auto clip1 = GetClip(clipidx1);
3170 const auto clip2 = GetClip(clipidx2);
3171
3172 if (!clip1 || !clip2)
3173 return false; // Don't throw, just do nothing.
3174
3175 if (!clip1->HasEqualPitchAndSpeed(*clip2))
3176 return false;
3177
3178 // Append data from second clip to first clip
3179 // use Strong-guarantee
3180 bool success = clip1->Paste(clip1->GetPlayEndTime(), *clip2);
3181 assert(success); // assuming clips of the same track must have same width
3182
3183 // use No-fail-guarantee for the rest
3184 // Delete second clip
3185 RemoveInterval(clip2);
3186 return true;
3187}

References GetClip(), and RemoveInterval().

Here is the call graph for this function:

◆ MonoToStereo()

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

Definition at line 1029 of file WaveTrack.cpp.

1030{
1031 assert(!GetOwner());
1032 MakeMono();
1033
1034 // Make temporary new mono track
1035 auto newTrack = Duplicate();
1036
1037 // Make a list
1038 auto result = TrackList::Temporary(nullptr, shared_from_this());
1039 result->Add(newTrack);
1040 // Destroy the temporary track, widening this track to stereo
1041 ZipClips();
1042
1043 return std::static_pointer_cast<WaveTrack>(result->DetachFirst());
1044}
std::shared_ptr< TrackList > GetOwner() const
Definition: Track.h:230
static TrackListHolder Temporary(AudacityProject *pProject, const Track::Holder &pTrack={})
Definition: Track.cpp:858
void MakeMono()
Simply discard any right channel.
Definition: WaveTrack.cpp:1021

References anonymous_namespace{FloatVectorClip.cpp}::Duplicate(), and TrackList::Temporary().

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

565{
566 double delta = origin - GetStartTime();
567 for (const auto &pInterval : Intervals())
568 // assume No-fail-guarantee
569 pInterval->ShiftBy(delta);
570 WaveTrackData::Get(*this).SetOrigin(origin);
571}

References BasicUI::Get(), GetStartTime(), and Intervals().

Here is the call graph for this function:

◆ NarrowClips() [1/2]

WaveClipHolders & WaveTrack::NarrowClips ( )
private

Definition at line 749 of file WaveTrack.cpp.

750{
751 return mClips;
752}

References mClips.

Referenced by GetNumClips(), HandleXMLChild(), LinkConsistencyFix(), NIntervals(), and RemoveClip().

Here is the caller graph for this function:

◆ NarrowClips() [2/2]

const WaveClipHolders & WaveTrack::NarrowClips ( ) const
private

Definition at line 754 of file WaveTrack.cpp.

755{
756 return mClips;
757}

References mClips.

◆ NChannels()

size_t WaveTrack::NChannels ( ) const
overridevirtual

◆ New()

WaveTrack * WaveTrack::New ( AudacityProject project)
static

Definition at line 486 of file WaveTrack.cpp.

487{
488 auto &trackFactory = WaveTrackFactory::Get( project );
489 auto &tracks = TrackList::Get( project );
490 auto result = tracks.Add(trackFactory.Create());
491 return result;
492}
const auto tracks
const auto project
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:314
static WaveTrackFactory & Get(AudacityProject &project)
Definition: WaveTrack.cpp:3358

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

Here is the call graph for this function:

◆ NewestOrNewClip()

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

2985{
2986 const auto &intervals = Intervals();
2987 if (intervals.empty()) {
2988 const auto origin = WaveTrackData::Get(*this).GetOrigin();
2989 const auto name = MakeNewClipName();
2990 auto pInterval = CreateClip(origin, name);
2991 InsertInterval(pInterval, true, true);
2992 return pInterval;
2993 }
2994 else
2995 return mClips.back();
2996}
wxString MakeNewClipName() const
Definition: WaveTrack.cpp:786

References BasicUI::Get(), and name.

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

Report the number of intervals.

Implements ChannelGroup.

Definition at line 686 of file WaveTrack.cpp.

687{
688 return NarrowClips().size();
689}

References NarrowClips().

Referenced by DoGetInterval(), and Flush().

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

◆ Paste() [1/2]

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

Weak precondition allows overrides to replicate one channel into many.

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

Implements Track.

◆ Paste() [2/2]

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

Implements Track.

Definition at line 1970 of file WaveTrack.cpp.

1971{
1972 if (const auto other = dynamic_cast<const WaveTrack*>(&src))
1973 {
1974 // Currently `Paste` isn't used by code that wants the newer "don't merge
1975 // when copy/pasting" behaviour ...
1976 constexpr auto merge = true;
1977 PasteWaveTrack(t0, *other, merge);
1978 }
1979 else
1980 // THROW_INCONSISTENCY_EXCEPTION; // ?
1981 (void)0;// Empty if intentional.
1982}

References PasteWaveTrack().

Referenced by EffectStereoToMono::ProcessOne(), and SyncLockAdjust().

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

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 track

Implements Track.

Definition at line 675 of file WaveTrack.cpp.

677{
678 auto &trackFactory = WaveTrackFactory::Get(project);
679 auto &pSampleBlockFactory = trackFactory.GetSampleBlockFactory();
680 auto pFirstTrack = EmptyCopy(pSampleBlockFactory);
681 list.Add(pFirstTrack->SharedPointer());
682 pFirstTrack->Paste(0.0, *this);
683 return pFirstTrack->SharedPointer();
684}
TrackKind * Add(const std::shared_ptr< TrackKind > &t, bool assignIds=true)
Definition: Track.h:1048

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

Here is the call graph for this function:

◆ PasteWaveTrack()

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

Definition at line 1691 of file WaveTrack.cpp.

1692{
1693 // Get a modifiable copy of `src` because it may come from another project
1694 // with different tempo, making boundary queries incorrect.
1695 const auto& tempo = GetProjectTempo(*this);
1696 if (!tempo.has_value())
1698 const auto copyHolder = other.DuplicateWithOtherTempo(*tempo);
1699 PasteWaveTrackAtSameTempo(t0, *copyHolder, merge);
1700}
void PasteWaveTrackAtSameTempo(double t0, const WaveTrack &other, bool merge)
Definition: WaveTrack.cpp:1702

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

1704{
1705 const auto otherNChannels = other.NChannels();
1706 assert(otherNChannels == NChannels());
1707 assert(
1708 GetProjectTempo(*this).has_value() &&
1709 GetProjectTempo(*this) == GetProjectTempo(other));
1710 const auto startTime = other.GetStartTime();
1711 const auto endTime = other.GetEndTime();
1712
1713 const auto insertDuration = endTime;
1714 auto &track = *this;
1715 //
1716 // Pasting is a bit complicated, because with the existence of multiclip mode,
1717 // we must guess the behaviour the user wants.
1718 //
1719 // Currently, two modes are implemented:
1720 //
1721 // - If a single clip should be pasted, and it should be pasted inside another
1722 // clip, no NEW clips are generated. The audio is simply inserted.
1723 // This resembles the old (pre-multiclip support) behaviour. However, if
1724 // the clip is pasted outside of any clip, a NEW clip is generated. This is
1725 // the only behaviour which is different to what was done before, but it
1726 // shouldn't confuse users too much.
1727 //
1728 // - If multiple clips should be pasted, or a single clip that does not fill
1729 // the duration of the pasted track, these are always pasted as single
1730 // clips, and the current clip is split, when necessary. This may seem
1731 // strange at first, but it probably is better than trying to auto-merge
1732 // anything. The user can still merge the clips by hand (which should be a
1733 // simple command reachable by a hotkey or single mouse click).
1734 //
1735
1736 if (other.GetNumClips() == 0)
1737 return;
1738
1739 t0 = track.SnapToSample(t0);
1740
1741 //wxPrintf("paste: we have at least one clip\n");
1742
1743 const auto clipAtT0 = track.GetIntervalAtTime(t0);
1744 const auto otherFirstClip = other.GetLeftmostClip();
1745 const auto otherLastClip = other.GetRightmostClip();
1746 const auto pitchAndSpeedMatch =
1747 !clipAtT0 || (clipAtT0->HasEqualPitchAndSpeed(*otherFirstClip) &&
1748 clipAtT0->HasEqualPitchAndSpeed(*otherLastClip));
1749
1750 // `singleClipMode` will try to merge. Only allow this if clips on both ends
1751 // of the selection have equal stretch ratio.
1752 const bool singleClipMode =
1753 other.GetNumClips() == 1 &&
1754 std::abs(startTime) < track.LongSamplesToTime(1) * 0.5 &&
1755 pitchAndSpeedMatch && merge;
1756
1757 const auto rate = track.GetRate();
1758 if (insertDuration != 0 && insertDuration < 1.0 / rate)
1759 // PRL: I added this check to avoid violations of preconditions in other WaveClip and Sequence
1760 // methods, but allow the value 0 so I don't subvert the purpose of commit
1761 // 739422ba70ceb4be0bb1829b6feb0c5401de641e which causes append-recording always to make
1762 // a new clip.
1763 return;
1764
1765 //wxPrintf("Check if we need to make room for the pasted data\n");
1766
1767 auto pastingFromTempTrack = !other.GetOwner();
1768 bool editClipCanMove = GetEditClipsCanMove();
1769
1770 const SimpleMessageBoxException notEnoughSpaceException {
1772 XO("There is not enough room available to paste the selection"),
1773 XO("Warning"), "Error:_Insufficient_space_in_track"
1774 };
1775
1776 // Make room for the pasted data
1777 if (editClipCanMove) {
1778 if (!singleClipMode)
1779 // We need to insert multiple clips, so split the current clip and ...
1780 track.SplitAt(t0);
1781
1782 //else if there is a clip at t0 insert new clip inside it and ...
1783
1784 // ... move everything to the right
1785 for (const auto& clip : track.Intervals())
1786 if (clip->GetPlayStartTime() > t0 - (1.0 / rate))
1787 clip->ShiftBy(insertDuration);
1788 }
1789 else
1790 {
1791 if (!merge)
1792 track.SplitAt(t0);
1793 const auto clipAtT0 = track.GetClipAtTime(t0);
1794 const auto t = clipAtT0 ? clipAtT0->GetPlayEndTime() : t0;
1795 if (!track.IsEmpty(t, t + insertDuration))
1796 throw notEnoughSpaceException;
1797 }
1798
1799 // See if the clipboard data is one clip only and if it should be merged. If
1800 // edit-clip-can-move mode is checked, merging happens only if the pasting
1801 // point splits a clip. If it isn't, merging also happens when the pasting
1802 // point is at the exact beginning of a clip.
1803 if (singleClipMode && merge) {
1804 // Single clip mode
1805 // wxPrintf("paste: checking for single clip mode!\n");
1806
1807 IntervalHolder insideClip{};
1808 for (const auto& clip : track.Intervals()) {
1809 if (editClipCanMove) {
1810 if (clip->SplitsPlayRegion(t0)) {
1811 //wxPrintf("t0=%.6f: inside clip is %.6f ... %.6f\n",
1812 // t0, clip->GetStartTime(), clip->GetEndTime());
1813 insideClip = clip;
1814 break;
1815 }
1816 }
1817 else {
1818 // If clips are immovable we also allow prepending to clips
1819 if (clip->WithinPlayRegion(t0))
1820 {
1821 insideClip = clip;
1822 break;
1823 }
1824 }
1825 }
1826
1827 if (insideClip) {
1828 // Exhibit traditional behaviour
1829 //wxPrintf("paste: traditional behaviour\n");
1830 if (!editClipCanMove) {
1831 // We did not move other clips out of the way already, so
1832 // check if we can paste without having to move other clips
1833 for (const auto& clip : track.Intervals()) {
1834 if (clip->GetPlayStartTime() > insideClip->GetPlayStartTime() &&
1835 insideClip->GetPlayEndTime() + insertDuration >
1836 clip->GetPlayStartTime())
1837 // Strong-guarantee in case of this path
1838 // not that it matters.
1839 throw notEnoughSpaceException;
1840 }
1841 }
1842 if (auto pClip = other.GetClip(0)) {
1843 // This branch only gets executed in `singleClipMode` - we've
1844 // already made sure that stretch ratios are equal, satisfying
1845 // `WaveClip::Paste`'s precondition.
1846 assert(insideClip->GetStretchRatio() == pClip->GetStretchRatio());
1847 // This too should follow from the assertion of the same number
1848 // of channels in the tracks, near the top
1849 assert(insideClip->NChannels() == pClip->NChannels());
1850 bool success = insideClip->Paste(t0, *pClip);
1851 assert(success);
1852 }
1853 return;
1854 }
1855 // Just fall through and exhibit NEW behaviour
1856 }
1857
1858 // Insert NEW clips
1859 //wxPrintf("paste: multi clip mode!\n");
1860
1861 if (!editClipCanMove &&
1862 !track.IsEmpty(t0, t0 + insertDuration - 1.0 / rate))
1863 // Strong-guarantee in case of this path
1864 // not that it matters.
1865 throw notEnoughSpaceException;
1866
1867 for (const auto& clip : other.Intervals()) {
1868 // AWD Oct. 2009: Don't actually paste in placeholder clips
1869 if (!clip->GetIsPlaceholder()) {
1870 const auto name = (pastingFromTempTrack)
1871 //Clips from the tracks which aren't bound to any TrackList are
1872 //considered to be new entities, thus named using "new" name template
1873 ? track.MakeNewClipName()
1874 : track.MakeClipCopyName(clip->GetName());
1875 const auto oldPlayStart = clip->GetPlayStartTime();
1876 const auto newSequenceStart =
1877 (oldPlayStart + t0) - clip->GetTrimLeft();
1878 const auto newClip = CreateClip(newSequenceStart, name, clip.get());
1879 newClip->Resample(rate);
1880 track.InsertInterval(move(newClip), false);
1881 }
1882 }
1883}
@ BadUserAction
Indicates that the user performed an action that is not allowed.
A MessageBoxException that shows a given, unvarying string.

References BadUserAction, CreateClip(), GetClip(), GetEditClipsCanMove(), GetEndTime(), GetLeftmostClip(), GetNumClips(), Track::GetOwner(), GetProjectTempo(), GetRightmostClip(), GetStartTime(), Intervals(), name, NChannels(), and XO().

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

357{
359 return std::max(ProjectRate::Get(project).GetRate(),
360 tracks.Any<const WaveTrack>().max(&WaveTrack::GetRate))
361 / 2.0;
362}
static ProjectRate & Get(AudacityProject &project)
Definition: ProjectRate.cpp:28

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

Referenced by SelectFrequenciesCommand::Apply(), and SpectralSelectionBar::ModifySpectralSelection().

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 an unzipped leader track have a common rate.

Definition at line 1885 of file WaveTrack.cpp.

1886{
1887 // The channels and all clips in them should have the same sample rate.
1888 std::optional<double> oRate;
1889 auto channels = TrackList::Channels(this);
1890 return std::all_of(channels.begin(), channels.end(),
1891 [&](const WaveTrack *pTrack){
1892 if (!pTrack)
1893 return false;
1894
1895 const auto rate = pTrack->mLegacyRate;
1896 if (!oRate)
1897 oRate = rate;
1898 else if (*oRate != rate)
1899 return false;
1900 return true;
1901 });
1902}

References TrackList::Channels().

Referenced by LinkConsistencyFix().

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

◆ RemoveClip()

void WaveTrack::RemoveClip ( std::ptrdiff_t  distance)
private

Definition at line 1524 of file WaveTrack.cpp.

1525{
1526 auto &clips = NarrowClips();
1527 if (distance < clips.size())
1528 clips.erase(clips.begin() + distance);
1529}

References NarrowClips().

Referenced by Join().

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

◆ RemoveInterval()

void WaveTrack::RemoveInterval ( const IntervalHolder interval)

Definition at line 3228 of file WaveTrack.cpp.

3229{
3230 const auto end = mClips.end(),
3231 iter = find(mClips.begin(), end, interval);
3232 if (iter != end)
3233 mClips.erase(iter);
3234}

References details::end(), and mClips.

Referenced by HandleClear(), MergeClips(), ReplaceInterval(), and WaveTrackUtilities::Reverse().

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

◆ RepairChannels()

void WaveTrack::RepairChannels ( )
overridevirtual

Called in exception handling after possibly unbalanced calls to Append in different channels. Allows the sequence to repair consistency.

Implements RecordableSequence.

Definition at line 2307 of file WaveTrack.cpp.

2308{
2309 for (auto pInterval : Intervals())
2310 pInterval->RepairChannels();
2311}

References Intervals().

Here is the call graph for this function:

◆ ReplaceInterval()

void WaveTrack::ReplaceInterval ( const IntervalHolder oldOne,
const IntervalHolder newOne 
)
private
Precondition
oldOne->NChannels() == newOne->NChannels()
newOne and oldOne are the same, or else newOne is not already owned by this or any other track

Definition at line 3236 of file WaveTrack.cpp.

3238{
3239 assert(newOne == oldOne || FindClip(*newOne) == Intervals().size());
3240 assert(oldOne->NChannels() == newOne->NChannels());
3241 RemoveInterval(oldOne);
3242 InsertInterval(newOne, false);
3243 newOne->SetName(oldOne->GetName());
3244}
size_t size() const
How many attachment pointers are in the Site.
Definition: ClientData.h:260

References FindClip(), InsertInterval(), Intervals(), RemoveInterval(), and ClientData::Site< Host, ClientData, ObjectCopyingPolicy, Pointer, ObjectLockingPolicy, RegistryLockingPolicy >::size().

Referenced by ApplyPitchAndSpeedOnIntervals().

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

◆ Resample()

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

Definition at line 3248 of file WaveTrack.cpp.

3249{
3250 for (const auto &pClip : Intervals())
3251 pClip->Resample(rate, progress);
3252 DoSetRate(rate);
3253}

References DoSetRate(), and Intervals().

Here is the call graph for this function:

◆ RightmostOrNewClip()

auto WaveTrack::RightmostOrNewClip ( )

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

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

Definition at line 2999 of file WaveTrack.cpp.

3000{
3001 if (mClips.empty()) {
3002 auto pInterval = CreateClip(
3003 WaveTrackData::Get(*this).GetOrigin(), MakeNewClipName());
3004 InsertInterval(pInterval, true, true);
3005 return pInterval;
3006 }
3007 else {
3008 auto end = mClips.end(),
3009 it = max_element(mClips.begin(), end,
3010 [](const auto &pClip1, const auto &pClip2){
3011 return pClip1->GetPlayStartTime() < pClip2->GetPlayStartTime();
3012 });
3013 assert(it != end);
3014 return *it;
3015 }
3016}

References details::end(), and BasicUI::Get().

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

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

◆ SetFloats()

bool WaveTrack::SetFloats ( const float *const *  buffers,
sampleCount  start,
size_t  len,
sampleFormat  effectiveFormat = widestSampleFormat 
)

Random-access assignment of a range of samples.

Parameters
buffersa span of pointers of size NChannels()
Precondition
each of buffers is non-null
Parameters
effectiveFormatMake the effective format of the data at least the minumum of this value and `format`. (Maybe wider, if merging with preexistent data.) If the data are later narrowed from stored format, but not narrower than the effective, then no dithering will occur.

Definition at line 3255 of file WaveTrack.cpp.

3257{
3258 bool result = true;
3259 size_t ii = 0;
3260 for (const auto &pChannel : Channels()) {
3261 const auto buffer = buffers[ii++];
3262 assert(buffer); // precondition
3263 result = pChannel->SetFloats(buffer, start, len, effectiveFormat)
3264 && result;
3265 }
3266 return result;
3267}

References Channels().

Referenced by anonymous_namespace{WaveTrackUtilities.cpp}::ReverseOneClip().

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

◆ SetGain()

void WaveTrack::SetGain ( float  newGain)

Definition at line 834 of file WaveTrack.cpp.

835{
836 if (GetGain() != newGain) {
837 DoSetGain(newGain);
838 Notify(true);
839 }
840}
void Notify(bool allChannels, int code=-1)
Definition: Track.cpp:234

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

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

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

◆ SetLegacyFormat()

void WaveTrack::SetLegacyFormat ( sampleFormat  format)

Definition at line 2313 of file WaveTrack.cpp.

2314{
2316}

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

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

Here is the caller graph for this function:

◆ SetPan()

void WaveTrack::SetPan ( float  newPan)

Definition at line 852 of file WaveTrack.cpp.

853{
854 if (newPan > 1.0)
855 newPan = 1.0;
856 else if (newPan < -1.0)
857 newPan = -1.0;
858
859 if ( GetPan() != newPan ) {
860 DoSetPan(newPan);
861 Notify(true);
862 }
863}

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

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

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

◆ SetRate()

void WaveTrack::SetRate ( double  newRate)

!brief Sets the new rate for the track without resampling it

Precondition
newRate > 0

Definition at line 808 of file WaveTrack.cpp.

809{
810 assert(newRate > 0);
811 newRate = std::max( 1.0, newRate );
812 DoSetRate(newRate);
813
814 for (const auto &clip : Intervals())
815 clip->SetRate(newRate);
816}

References DoSetRate(), and Intervals().

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

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

◆ Silence()

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

Implements Track.

Definition at line 1984 of file WaveTrack.cpp.

1985{
1986 if (t1 < t0)
1988
1989 ApplyPitchAndSpeed({ { t0, t1 } }, std::move(reportProgress));
1990
1991 auto start = TimeToLongSamples(t0);
1992 auto end = TimeToLongSamples(t1);
1993
1994 for (const auto &pClip : Intervals()) {
1995 auto clipStart = pClip->GetPlayStartSample();
1996 auto clipEnd = pClip->GetPlayEndSample();
1997 if (clipEnd > start && clipStart < end) {
1998 auto offset = std::max(start - clipStart, sampleCount(0));
1999 // Clip sample region and Get/Put sample region overlap
2000 auto length = std::min(end, clipEnd) - (clipStart + offset);
2001 pClip->SetSilence(offset, length);
2002 }
2003 }
2004}
void ApplyPitchAndSpeed(std::optional< TimeInterval > interval, ProgressReporter reportProgress)
Definition: WaveTrack.cpp:1929

References ApplyPitchAndSpeed(), details::end(), Intervals(), min(), THROW_INCONSISTENCY_EXCEPTION, and WideSampleSequence::TimeToLongSamples().

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

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

◆ SortedClipArray()

auto WaveTrack::SortedClipArray ( ) const
private

Return all WaveClips sorted by clip play start time.

Definition at line 3269 of file WaveTrack.cpp.

3270{
3271 const auto &intervals = Intervals();
3272 IntervalConstHolders clips{ intervals.begin(), intervals.end() };
3273 const auto comp = [](const auto &a, const auto &b) {
3274 return a->GetPlayStartTime() < b->GetPlayStartTime(); };
3275 std::sort(clips.begin(), clips.end(), comp);
3276 return clips;
3277}
std::vector< IntervalConstHolder > IntervalConstHolders
Definition: WaveTrack.h:212

References Intervals().

Referenced by LinkConsistencyFix(), and ZipClips().

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

◆ SortedIntervalArray() [1/2]

auto WaveTrack::SortedIntervalArray ( )

Return all WaveClips sorted by clip play start time.

Definition at line 3279 of file WaveTrack.cpp.

3280{
3281 const auto &intervals = Intervals();
3282 IntervalHolders result;
3283 copy(intervals.begin(), intervals.end(), back_inserter(result));
3284 sort(result.begin(), result.end(), [](const auto &pA, const auto &pB){
3285 return pA->GetPlayStartTime() < pB->GetPlayStartTime(); });
3286 return result;
3287}
void copy(const T *src, T *dst, int32_t n)
Definition: VectorOps.h:40

References staffpad::vo::copy().

Referenced by SetEnvelopeCommand::ApplyInner(), EffectSBSMS::Finalize(), anonymous_namespace{ClipMenus.cpp}::FindNextClip(), anonymous_namespace{ClipMenus.cpp}::FindNextClipBoundary(), anonymous_namespace{ClipMenus.cpp}::FindPrevClip(), anonymous_namespace{ClipMenus.cpp}::FindPrevClipBoundary(), FindWaveTrackLocations(), anonymous_namespace{Nyquist.cpp}::GetClipBoundaries(), WaveTrackUtilities::Reverse(), and GetInfoCommand::SendEnvelopes().

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

◆ SortedIntervalArray() [2/2]

auto WaveTrack::SortedIntervalArray ( ) const

Return all WaveClips sorted by clip play start time.

Definition at line 3289 of file WaveTrack.cpp.

3290{
3291 const auto &intervals = Intervals();
3292 IntervalConstHolders result;
3293 copy(intervals.begin(), intervals.end(), back_inserter(result));
3294 sort(result.begin(), result.end(), [](const auto &pA, const auto &pB){
3295 return pA->GetPlayStartTime() < pB->GetPlayStartTime(); });
3296 return result;
3297}

References staffpad::vo::copy(), and Intervals().

Here is the call graph for this function:

◆ Split()

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

Definition at line 3139 of file WaveTrack.cpp.

3140{
3141 SplitAt(t0);
3142 if (t0 != t1)
3143 SplitAt(t1);
3144}
std::pair< IntervalHolder, IntervalHolder > SplitAt(double t)
Definition: WaveTrack.cpp:3147

References SplitAt().

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

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

◆ SplitAt()

auto WaveTrack::SplitAt ( double  t)
Exception safety guarantee:
Weak

Definition at line 3147 of file WaveTrack.cpp.

3148{
3149 for (const auto &&c : Intervals()) {
3150 if (c->SplitsPlayRegion(t)) {
3151 t = SnapToSample(t);
3152 auto newClip = CopyClip(*c, true);
3153 c->TrimRightTo(t);// put t on a sample
3154 newClip->TrimLeftTo(t);
3155 auto result = std::pair{ c, newClip };
3156
3157 // This could invalidate the iterators for the loop! But we return
3158 // at once so it's okay
3159 InsertInterval(move(newClip), false); // transfer ownership
3160 return result;
3161 }
3162 }
3163 return {};
3164}

Referenced by WaveTrackUtilities::Reverse(), and Split().

Here is the caller graph for this function:

◆ SplitChannels()

auto WaveTrack::SplitChannels ( )

Definition at line 1046 of file WaveTrack.cpp.

1047{
1048 std::vector<Holder> result{ SharedPointer<WaveTrack>() };
1049 if (NChannels() == 2) {
1050 auto pOwner = GetOwner();
1051 assert(pOwner); // pre
1052 auto pNewTrack = result.emplace_back(EmptyCopy(1));
1053 for (auto &pClip : mClips)
1054 pNewTrack->mClips.emplace_back(pClip->SplitChannels());
1055 this->mRightChannel.reset();
1056 auto iter = pOwner->Find(this);
1057 pOwner->Insert(*++iter, pNewTrack);
1058 // Fix up the channel attachments to avoid waste of space
1059 result[0]->EraseChannelAttachments(1);
1060 result[1]->EraseChannelAttachments(0);
1061 }
1062 return result;
1063}

Referenced by WaveTrackMenuTable::SplitStereo().

Here is the caller graph for this function:

◆ SplitCut()

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

Definition at line 948 of file WaveTrack.cpp.

949{
950 if (t1 < t0)
952
953 // SplitCut is the same as 'Copy', then 'SplitDelete'
954 auto result = Copy(t0, t1);
955 SplitDelete(t0, t1);
956 return std::static_pointer_cast<WaveTrack>(result);
957}

References THROW_INCONSISTENCY_EXCEPTION.

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

Here is the caller graph for this function:

◆ SplitDelete()

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

Definition at line 1508 of file WaveTrack.cpp.

1509{
1510 constexpr bool addCutLines = false;
1511 constexpr bool split = true;
1512 HandleClear(t0, t1, addCutLines, split);
1513}

References HandleClear().

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

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

◆ SwapChannels()

void WaveTrack::SwapChannels ( )
Precondition
NChannels() == 2

Definition at line 1065 of file WaveTrack.cpp.

1066{
1067 assert(NChannels() == 2);
1068 for (const auto &pClip: mClips)
1069 pClip->SwapChannels();
1070 this->AttachedTrackObjects::ForEach([this](TrackAttachment &attachment){
1071 if (const auto pAttachments =
1072 dynamic_cast<ChannelAttachmentsBase *>(&attachment)) {
1073 pAttachments->SwapChannels(shared_from_this());
1074 }
1075 });
1076}

References ClientData::Site< Host, ClientData, ObjectCopyingPolicy, Pointer, ObjectLockingPolicy, RegistryLockingPolicy >::ForEach(), mClips, and NChannels().

Referenced by WaveTrackMenuTable::OnSwapChannels().

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

◆ SyncLockAdjust()

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

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

Reimplemented from Track.

Definition at line 1653 of file WaveTrack.cpp.

1654{
1655 const auto endTime = GetEndTime();
1656 if (newT1 > oldT1 &&
1657 // JKC: This is a rare case where using >= rather than > on a float matters.
1658 // GetEndTime() looks through the clips and may give us EXACTLY the same
1659 // value as T1, when T1 was set to be at the end of one of those clips.
1660 oldT1 >= endTime)
1661 return;
1662 if (newT1 > oldT1) {
1663 // Insert space within the track
1664
1665 // If track is empty at oldT1 insert whitespace; otherwise, silence
1666 if (IsEmpty(oldT1, oldT1)) {
1667 // Check if clips can move
1668 if (EditClipsCanMove.Read()) {
1669 const auto offset = newT1 - oldT1;
1670 const auto rate = GetRate();
1671 for (const auto &clip : Intervals())
1672 if (clip->GetPlayStartTime() > oldT1 - (1.0 / rate))
1673 clip->ShiftBy(offset);
1674 }
1675 return;
1676 }
1677 else {
1678 // AWD: Could just use InsertSilence() on its own here, but it doesn't
1679 // follow EditClipCanMove rules (Paste() does it right)
1680 const auto duration = newT1 - oldT1;
1681 auto tmp = EmptyCopy(mpFactory);
1682 tmp->InsertSilence(0.0, duration);
1683 tmp->Flush();
1684 Paste(oldT1, *tmp);
1685 }
1686 }
1687 else if (newT1 < oldT1)
1688 Clear(newT1, oldT1);
1689}
BoolSetting EditClipsCanMove
Definition: WaveTrack.cpp:3399
bool Read(T *pVar) const
overload of Read returning a boolean that is true if the value was previously defined *‍/
Definition: Prefs.h:207
bool IsEmpty(double t0, double t1) const
Returns true if there are no WaveClips in the specified region.
Definition: WaveTrack.cpp:915

References Clear(), EditClipsCanMove, EmptyCopy(), GetEndTime(), GetRate(), Intervals(), IsEmpty(), mpFactory, Paste(), and Setting< T >::Read().

Here is the call graph for this function:

◆ Trim()

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

Definition at line 962 of file WaveTrack.cpp.

963{
964 bool inside0 = false;
965 bool inside1 = false;
966
967 for (const auto &clip : Intervals()) {
968 if (t1 > clip->GetPlayStartTime() && t1 < clip->GetPlayEndTime()) {
969 clip->SetTrimRight(
970 clip->GetTrimRight() + clip->GetPlayEndTime() - t1);
971 inside1 = true;
972 }
973
974 if (t0 > clip->GetPlayStartTime() && t0 < clip->GetPlayEndTime()) {
975 clip->SetTrimLeft(
976 clip->GetTrimLeft() + t0 - clip->GetPlayStartTime());
977 inside0 = true;
978 }
979 }
980
981 //if inside0 is false, then the left selector was between
982 //clips, so DELETE everything to its left.
983 if (const auto endTime = GetEndTime()
984 ; !inside1 && t1 < endTime
985 )
986 Clear(t1, endTime);
987
988 if (const auto startTime = GetStartTime()
989 ; !inside0 && t0 > startTime
990 )
991 SplitDelete(startTime, t0);
992}

References Clear(), GetEndTime(), GetStartTime(), Intervals(), and SplitDelete().

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

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

◆ WidestEffectiveFormat()

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

Implements WideSampleSequence.

Definition at line 2827 of file WaveTrack.cpp.

2828{
2829 auto result = narrowestSampleFormat;
2830 for (const auto &pClip : Intervals())
2831 result = std::max(result, pClip->GetSampleFormats().Effective());
2832 return result;
2833}
@ narrowestSampleFormat
Two synonyms for previous values that might change if more values were added.

References Intervals(), and narrowestSampleFormat.

Referenced by WaveChannel::WidestEffectiveFormat().

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

◆ WriteOneXML()

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

Definition at line 2467 of file WaveTrack.cpp.

2470{
2471 // Track data has always been written using channel-major iteration.
2472 // Do it still this way for compatibility.
2473
2474 // Some values don't vary independently in channels but have been written
2475 // redundantly for each channel. Keep doing this in 3.4 and later in case
2476 // a project is opened in an earlier version.
2477
2478 xmlFile.StartTag(WaveTrack_tag);
2479 auto &track = channel.GetTrack();
2480
2481 // Name, selectedness, etc. are channel group properties
2482 track.Track::WriteCommonXMLAttributes(xmlFile);
2483
2484 // Write the "channel" attribute so earlier versions can interpret stereo
2485 // tracks, but this version doesn't read it
2486 {
2487 enum ChannelType {
2488 LeftChannel = 0,
2489 RightChannel = 1,
2490 MonoChannel = 2
2491 };
2492 const auto channelType = (nChannels == 0)
2493 ? MonoChannel
2494 : (iChannel == 0)
2495 ? LeftChannel
2496 : RightChannel;
2497 xmlFile.WriteAttr(Channel_attr, channelType);
2498 }
2499
2500 // The "linked" flag is used to define the beginning of a channel group
2501 // that isn't mono
2502 const auto linkType = static_cast<int>(
2503 (iChannel == 0) && (nChannels == 2)
2505 : LinkType::None);
2506 xmlFile.WriteAttr(Linked_attr, linkType);
2507
2508 // VS: trying to save tracks that didn't pass all necessary
2509 // initializations on project read from the disk.
2510 const auto useLegacy = track.mLegacyRate != 0;
2511
2512 // More channel group properties written redundantly
2513 track.WritableSampleTrack::WriteXMLAttributes(xmlFile);
2514 xmlFile.WriteAttr(Rate_attr, useLegacy ? track.mLegacyRate : track.GetRate());
2515 xmlFile.WriteAttr(Gain_attr, static_cast<double>(track.GetGain()));
2516 xmlFile.WriteAttr(Pan_attr, static_cast<double>(track.GetPan()));
2517 xmlFile.WriteAttr(SampleFormat_attr, static_cast<long>(useLegacy ? track.mLegacyFormat : track.GetSampleFormat()));
2518
2519 // Other persistent data specified elsewhere;
2520 // NOT written redundantly any more
2521 if (iChannel == 0)
2522 WaveTrackIORegistry::Get().CallWriters(track, xmlFile);
2523
2524 for (const auto &clip : channel.Intervals())
2525 clip->WriteXML(xmlFile);
2526
2527 xmlFile.EndTag(WaveTrack_tag);
2528}
static constexpr auto Channel_attr
Definition: WaveTrack.cpp:2341
WaveTrack & GetTrack()
Definition: WaveTrack.h:840
IteratorRange< IntervalIterator< WaveClipChannel > > Intervals()
Definition: WaveTrack.cpp:743
void CallWriters(const Host &host, XMLWriter &writer)
virtual void StartTag(const wxString &name)
Definition: XMLWriter.cpp:79
void WriteAttr(const wxString &name, const Identifier &value)
Definition: XMLWriter.h:36
virtual void EndTag(const wxString &name)
Definition: XMLWriter.cpp:102
ChannelType
Mutually exclusive channel classifications.

References ChannelGroup::Aligned, XMLMethodRegistry< Host >::CallWriters(), Channel_attr, XMLWriter::EndTag(), Gain_attr, XMLMethodRegistry< Host >::Get(), WaveChannel::GetTrack(), anonymous_namespace{StretchingSequenceIntegrationTest.cpp}::iChannel, WaveChannel::Intervals(), AudioGraph::LeftChannel, Linked_attr, AudioGraph::MonoChannel, ChannelGroup::None, Pan_attr, Rate_attr, AudioGraph::RightChannel, SampleFormat_attr, XMLWriter::StartTag(), WaveTrack_tag, and XMLWriter::WriteAttr().

Here is the call graph for this function:

◆ WriteXML()

void WaveTrack::WriteXML ( XMLWriter xmlFile) const
overridevirtual

Implements Track.

Definition at line 2457 of file WaveTrack.cpp.

2459{
2460 const auto channels = Channels();
2461 size_t iChannel = 0,
2462 nChannels = channels.size();
2463 for (const auto pChannel : channels)
2464 WriteOneXML(*pChannel, xmlFile, iChannel++, nChannels);
2465}
static void WriteOneXML(const WaveChannel &channel, XMLWriter &xmlFile, size_t iChannel, size_t nChannels)
Definition: WaveTrack.cpp:2467

References anonymous_namespace{StretchingSequenceIntegrationTest.cpp}::iChannel.

◆ ZipClips()

void WaveTrack::ZipClips ( bool  mustAlign = true)

Convert channel-major storage to interval-major, replacing two tracks with one in the owning TrackList

Precondition
GetOwner()
next track in the list exists, is a WaveTrack, has one channel only
NChannels() == 1
if mustAlign, then clips are aligned across the tracks
Parameters
mustAlignif false, clips may be of different number or not aligned. Do not use the resulting track normally!

Refuse if clips are not well aligned.

Definition at line 3299 of file WaveTrack.cpp.

3300{
3301 const auto pOwner = GetOwner();
3302 assert(GetOwner()); // pre
3303 assert(NChannels() == 1); // pre
3304
3305 // If deserializing, first un-link the track, so iterator finds the partner.
3307
3308 auto iter = pOwner->Find(this);
3309 assert(this == *iter);
3310 ++iter;
3311 assert(iter != pOwner->end()); // pre
3312 auto pRight = dynamic_cast<WaveTrack*>(*iter);
3313 assert(pRight && pRight->NChannels() == 1); // pre
3314
3316 if (mustAlign &&
3317 !AreAligned(this->SortedClipArray(), pRight->SortedClipArray()))
3318 return;
3319
3320 CreateRight();
3321
3322 // Now steal right side sample data info. When not requiring alignment,
3323 // because this is a track that just keeps the sample counts of blocks
3324 // above 0 for later purposes -- then there is laxity about consistent
3325 // width of the clips.
3326 auto iterMe = mClips.begin(),
3327 endMe = mClips.end();
3328 auto iterRight = pRight->mClips.begin(),
3329 endRight = pRight->mClips.end();
3330 while (iterMe != endMe && iterRight != endRight) {
3331 (*iterMe)->MakeStereo(std::move(**iterRight), mustAlign);
3332 ++iterMe;
3333 ++iterRight;
3334 }
3335 assert(!mustAlign || (iterMe == endMe && iterRight == endRight));
3336
3337 while (iterRight != endRight) {
3338 // Leftover misaligned mono clips
3339 mClips.emplace_back(move(*iterRight));
3340 ++iterRight;
3341 }
3342
3343 this->MergeChannelAttachments(std::move(*pRight));
3344
3345 pOwner->Remove(*pRight);
3346}
void CreateRight()
Definition: WaveTrack.cpp:2964
void MergeChannelAttachments(WaveTrack &&other)
Definition: WaveTrack.cpp:429

References anonymous_namespace{WaveTrack.cpp}::anonymous_namespace{WaveTrack.cpp}::AreAligned(), CreateRight(), Track::GetOwner(), mClips, MergeChannelAttachments(), NChannels(), ChannelGroup::None, Track::SetLinkType(), and SortedClipArray().

Referenced by LinkConsistencyFix(), PerTrackEffect::ProcessPass(), and ProjectFileManager::ReadProjectFile().

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

Friends And Related Function Documentation

◆ WaveTrackFactory

friend class WaveTrackFactory
friend

Definition at line 280 of file WaveTrack.h.

Member Data Documentation

◆ mAppendCriticalSection

wxCriticalSection WaveTrack::mAppendCriticalSection
private

Definition at line 832 of file WaveTrack.h.

◆ mChannel

WaveChannel WaveTrack::mChannel
private
Invariant
non-null

Definition at line 767 of file WaveTrack.h.

Referenced by DoGetChannel().

◆ mClips

WaveClipHolders WaveTrack::mClips
private

Do not call mClips.push_back directly. Use InsertClip instead.

Invariant
all are non-null

Definition at line 775 of file WaveTrack.h.

Referenced by DoGet(), DoGetInterval(), InsertInterval(), MakeMono(), NarrowClips(), RemoveInterval(), SwapChannels(), and ZipClips().

◆ mFlushCriticalSection

wxCriticalSection WaveTrack::mFlushCriticalSection
private

Definition at line 831 of file WaveTrack.h.

◆ mLegacyFormat

sampleFormat WaveTrack::mLegacyFormat { undefinedSample }
private

used only during deserialization

Definition at line 778 of file WaveTrack.h.

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

◆ mLegacyProjectFileOffset

double WaveTrack::mLegacyProjectFileOffset { 0 }
private

Definition at line 833 of file WaveTrack.h.

Referenced by HandleXMLChild(), and HandleXMLTag().

◆ mLegacyRate

int WaveTrack::mLegacyRate { 0 }
mutableprivate

used only during deserialization

Definition at line 777 of file WaveTrack.h.

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

◆ mpFactory

SampleBlockFactoryPtr WaveTrack::mpFactory
private

Definition at line 829 of file WaveTrack.h.

Referenced by EmptyCopy(), GetMaxBlockSize(), HandleXMLChild(), Init(), and SyncLockAdjust().

◆ mRightChannel

std::optional<WaveChannel> WaveTrack::mRightChannel
private

may be null

Definition at line 769 of file WaveTrack.h.

Referenced by CreateRight(), DoGetChannel(), MakeMono(), and NChannels().

◆ WaveChannel

friend WaveTrack::WaveChannel
private

Definition at line 835 of file WaveTrack.h.

◆ WaveTrack_tag

const char * WaveTrack::WaveTrack_tag = "wavetrack"
static

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