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
 
void ShiftBy (double t0, double delta) 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 GetVolume () const
 
void SetVolume (float newVolume)
 
float GetPan () const
 
void SetPan (float newPan)
 
float GetChannelVolume (int channel) const override
 Takes volume 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 ShiftBy (double t0, double delta)=0
 Shift all intervals that starts after t0 by delta seconds. 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 GetChannelVolume (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, 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 DoSetVolume (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:830
WaveChannel mChannel
Definition: WaveTrack.h:768
void DoSetRate(double newRate)
Definition: WaveTrack.cpp:836
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 2248 of file WaveTrack.cpp.

2251{
2252 assert(iChannel < NChannels());
2253 auto pTrack = this;
2254 constSamplePtr buffers[]{ buffer };
2255 auto pClip = RightmostOrNewClip();
2256 return pClip->Append(iChannel, 1,
2257 buffers, format, len, stride, effectiveFormat);
2258}
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:3017
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 1945 of file WaveTrack.cpp.

1947{
1948 // Assert that the interval is reasonable, but this function will be no-op
1949 // anyway if not
1950 assert(!interval.has_value() ||
1951 interval->first <= interval->second);
1952 if (GetNumClips() == 0)
1953 return;
1954 const auto startTime =
1955 interval ? std::max(SnapToSample(interval->first), GetStartTime()) :
1956 GetStartTime();
1957 const auto endTime =
1958 interval ? std::min(SnapToSample(interval->second), GetEndTime()) :
1959 GetEndTime();
1960 if (startTime >= endTime)
1961 return;
1962
1963 // Here we assume that left- and right clips are aligned.
1964 if (auto clipAtT0 = GetClipAtTime(startTime);
1965 clipAtT0 && clipAtT0->SplitsPlayRegion(startTime) &&
1966 clipAtT0->HasPitchOrSpeed())
1967 Split(startTime, startTime);
1968 if (auto clipAtT1 = GetClipAtTime(endTime);
1969 clipAtT1 && clipAtT1->SplitsPlayRegion(endTime) &&
1970 clipAtT1->HasPitchOrSpeed())
1971 Split(endTime, endTime);
1972
1973 IntervalHolders srcIntervals;
1974 auto clip = GetIntervalAtTime(startTime);
1975 while (clip && clip->GetPlayStartTime() < endTime)
1976 {
1977 if (clip->HasPitchOrSpeed())
1978 srcIntervals.push_back(clip);
1980 }
1981
1982 ApplyPitchAndSpeedOnIntervals(srcIntervals, reportProgress);
1983}
int min(int a, int b)
double GetStartTime() const override
Implement WideSampleSequence.
Definition: WaveTrack.cpp:2603
void ApplyPitchAndSpeedOnIntervals(const std::vector< IntervalHolder > &intervals, const ProgressReporter &reportProgress)
Definition: WaveTrack.cpp:3207
IntervalConstHolder GetNextInterval(const Interval &interval, PlaybackDirection searchDirection) const
Definition: WaveTrack.cpp:173
IntervalConstHolder GetClipAtTime(double time) const
Definition: WaveTrack.cpp:2951
void Split(double t0, double t1)
Definition: WaveTrack.cpp:3157
std::vector< IntervalHolder > IntervalHolders
Definition: WaveTrack.h:210
double GetEndTime() const override
Implement WideSampleSequence.
Definition: WaveTrack.cpp:2613
int GetNumClips() const
Definition: WaveTrack.cpp:3049
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 3207 of file WaveTrack.cpp.

3210{
3211 IntervalHolders dstIntervals;
3212 dstIntervals.reserve(srcIntervals.size());
3213 std::transform(
3214 srcIntervals.begin(), srcIntervals.end(),
3215 std::back_inserter(dstIntervals), [&](const IntervalHolder& interval) {
3216 return GetRenderedCopy(interval,
3217 reportProgress, mpFactory, GetSampleFormat());
3218 });
3219
3220 // If we reach this point it means that no error was thrown - we can replace
3221 // the source with the destination intervals.
3222 for (auto i = 0; i < srcIntervals.size(); ++i)
3223 ReplaceInterval(srcIntervals[i], dstIntervals[i]);
3224}
std::shared_ptr< Interval > IntervalHolder
Definition: WaveTrack.h:209
void ReplaceInterval(const IntervalHolder &oldOne, const IntervalHolder &newOne)
Definition: WaveTrack.cpp:3254

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

3115{
3116 const auto &clips = Intervals();
3117 if (clips.empty())
3118 return true;
3119 // Find clip in this that overlaps most with `clip`:
3120 const auto candidateClipStartTime = candidateClip.GetPlayStartTime();
3121 const auto candidateClipEndTime = candidateClip.GetPlayEndTime();
3122 const auto t0 = SnapToSample(candidateClipStartTime + slideBy);
3123 const auto t1 = SnapToSample(candidateClipEndTime + slideBy);
3124 std::vector<double> overlaps;
3125 std::transform(
3126 clips.begin(), clips.end(), std::back_inserter(overlaps),
3127 [&](const auto& pClip) {
3128 return pClip->IntersectsPlayRegion(t0, t1) ?
3129 std::min(pClip->GetPlayEndTime(), t1) -
3130 std::max(pClip->GetPlayStartTime(), t0) :
3131 0.0;
3132 });
3133 const auto maxOverlap = std::max_element(overlaps.begin(), overlaps.end());
3134 if (*maxOverlap > tolerance)
3135 return false;
3136 auto iter = clips.begin();
3137 std::advance(iter, std::distance(overlaps.begin(), maxOverlap));
3138 const auto overlappedClip = *iter;
3139 const auto requiredOffset = slideBy +
3140 *maxOverlap * (overlappedClip->GetPlayStartTime() < t0 ? 1 : -1);
3141 // Brute-force check to see if there's another clip that'd be in the way.
3142 if (std::any_of(
3143 clips.begin(), clips.end(),
3144 [&](const auto& pClip)
3145 {
3146 const auto result = pClip->IntersectsPlayRegion(
3147 SnapToSample(candidateClipStartTime + requiredOffset),
3148 SnapToSample(candidateClipEndTime + requiredOffset));
3149 return result;
3150 }))
3151 return false;
3152 slideBy = requiredOffset;
3153 return true;
3154}
auto Intervals()
Definition: WaveTrack.h:671

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

3058{
3059 if (allowedAmount)
3060 *allowedAmount = amount;
3061
3062 const auto &moving = [&](Interval *clip){
3063 // linear search might be improved, but expecting few moving clips
3064 // compared with the fixed clips
3065 return movingClips.end() !=
3066 std::find(movingClips.begin(), movingClips.end(), clip);
3067 };
3068
3069 for (const auto &c: Intervals()) {
3070 if ( moving( c.get() ) )
3071 continue;
3072 for (const auto clip : movingClips) {
3073 if (c->GetPlayStartTime() < clip->GetPlayEndTime() + amount &&
3074 c->GetPlayEndTime() > clip->GetPlayStartTime() + amount)
3075 {
3076 if (!allowedAmount)
3077 return false; // clips overlap
3078
3079 if (amount > 0)
3080 {
3081 if (c->GetPlayStartTime() - clip->GetPlayEndTime() < *allowedAmount)
3082 *allowedAmount = c->GetPlayStartTime() - clip->GetPlayEndTime();
3083 if (*allowedAmount < 0)
3084 *allowedAmount = 0;
3085 } else
3086 {
3087 if (c->GetPlayEndTime() - clip->GetPlayStartTime() > *allowedAmount)
3088 *allowedAmount = c->GetPlayEndTime() - clip->GetPlayStartTime();
3089 if (*allowedAmount > 0)
3090 *allowedAmount = 0;
3091 }
3092 }
3093 }
3094 }
3095
3096 if (allowedAmount)
3097 {
3098 if (*allowedAmount == amount)
3099 return true;
3100
3101 // Check if the NEW calculated amount would not violate
3102 // any other constraint
3103 if (!CanOffsetClips(movingClips, *allowedAmount, nullptr)) {
3104 *allowedAmount = 0; // play safe and don't allow anything
3105 return false;
3106 }
3107 else
3108 return true;
3109 } else
3110 return true;
3111}
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:3054

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

690{
691 return typeInfo();
692}
static const Track::TypeInfo & typeInfo()
Definition: WaveTrack.cpp:676

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

1162{
1163 HandleClear(t0, t1, false, false);
1164}
void HandleClear(double t0, double t1, bool addCutLines, bool split, bool clearByTrimming=false)
Definition: WaveTrack.cpp:1550

References HandleClear().

Referenced by Cut(), TruncSilenceBase::DoRemoval(), anonymous_namespace{LabelMenus.cpp}::OnCutLabels(), TrackSpectrumTransformer::PostProcess(), StereoToMono::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 1167 of file WaveTrack.cpp.

1168{
1169 HandleClear(t0, t1, true, false);
1170}

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

1227{
1228 // Get a modifiable copy of `src` because it may come from another project
1229 // with different tempo, making boundary queries incorrect.
1230 const auto& tempo = GetProjectTempo(*this);
1231 if (!tempo.has_value())
1233 const auto copyHolder = src.DuplicateWithOtherTempo(*tempo);
1235 t0, t1, *copyHolder, preserve, merge, effectWarper, clearByTrimming);
1236}
#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:589
void ClearAndPasteAtSameTempo(double t0, double t1, const WaveTrack &src, bool preserve, bool merge, const TimeWarper *effectWarper, bool clearByTrimming)
Definition: WaveTrack.cpp:1238

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

Referenced by SBSMSBase::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 1238 of file WaveTrack.cpp.

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

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

779{
780 auto newTrack = EmptyCopy(NChannels());
781 if(backup)
782 {
783 //Init-time rate and format should be preserved as initialization
784 //phase is not yet completed for that track.
785 newTrack->mLegacyFormat = mLegacyFormat;
786 newTrack->mLegacyRate = mLegacyRate;
787 }
788 newTrack->CopyClips(newTrack->mClips,
789 newTrack->mpFactory, this->mClips, backup);
790 return newTrack;
791}
int mLegacyRate
used only during deserialization
Definition: WaveTrack.h:778
sampleFormat mLegacyFormat
used only during deserialization
Definition: WaveTrack.h:779
Holder EmptyCopy(size_t nChannels, const SampleBlockFactoryPtr &pFactory={}) const
Definition: WaveTrack.cpp:1012

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

926{
927 for (const auto &pClip : Intervals())
928 pClip->ConvertToSampleFormat(format, progressReport);
929 WaveTrackData::Get(*this).SetSampleFormat(format);
930}

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

1098{
1099 if (t1 < t0)
1101
1102 auto newTrack = EmptyCopy(NChannels());
1103 for (const auto pClip : Intervals()) {
1104 // PRL: Why shouldn't cutlines be copied and pasted too? I don't know,
1105 // but that was the old behavior. But this function is also used by the
1106 // Duplicate command and I changed its behavior in that case.
1107 if (pClip->IsEmpty())
1108 continue;
1109 else if (t0 <= pClip->GetPlayStartTime() && t1 >= pClip->GetPlayEndTime())
1110 {
1111 newTrack->CopyWholeClip(*pClip, t0, forClipboard);
1112 }
1113 else if (pClip->CountSamples(t0, t1) >= 1) {
1114 newTrack->CopyPartOfClip(*pClip, t0, t1, forClipboard);
1115 }
1116 }
1117 newTrack->FinishCopy(t0, t1, forClipboard);
1118 return newTrack;
1119}

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

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

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

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

1133{
1134 const auto &pFactory = GetSampleBlockFactory();
1135 auto newClip = std::make_shared<Interval>(
1136 clip, pFactory, !forClipboard, t0, t1);
1137 newClip->SetName(clip.GetName());
1138 newClip->ShiftBy(-t0);
1139 if (newClip->GetPlayStartTime() < 0)
1140 newClip->SetPlayStartTime(0);
1141 InsertInterval(std::move(newClip), false, false);
1142}
void InsertInterval(const IntervalHolder &interval, bool newClip, bool allowEmpty=false)
Definition: WaveTrack.cpp:3235
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 1121 of file WaveTrack.cpp.

1123{
1124 const auto &pFactory = GetSampleBlockFactory();
1125 const auto newClip =
1126 std::make_shared<Interval>(clip, pFactory, !forClipboard);
1127 InsertInterval(newClip, false, false);
1128 newClip->ShiftBy(-t0);
1129}

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

2963{
2964 if (pToCopy) {
2965 auto pNewClip =
2966 std::make_shared<WaveClip>(*pToCopy, mpFactory, copyCutlines);
2967 pNewClip->SetName(name);
2968 pNewClip->SetSequenceStartTime(offset);
2969 return pNewClip;
2970 }
2971 else
2972 return DoCreateClip(offset, name);
2973}
wxString name
Definition: TagsEditor.cpp:166
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:2987

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

2983{
2984 mRightChannel.emplace(*this);
2985}
std::optional< WaveChannel > mRightChannel
may be null
Definition: WaveTrack.h:770

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

956{
957 if (t1 < t0)
959
960 auto result = Copy(t0, t1);
961 Clear(t0, t1);
962 return result;
963}
void Clear(double t0, double t1) override
Definition: WaveTrack.cpp:1161
Track::Holder Copy(double t0, double t1, bool forClipboard=true) const override
Create new tracks and don't modify this track.
Definition: WaveTrack.cpp:1097

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

2062{
2064 const size_t maxAtOnce = 1048576;
2065 std::vector<float> buffer;
2066 std::vector<samplePtr> buffers;
2067 Regions regions;
2068
2069 const size_t width = NChannels();
2070
2071 for (const auto &interval : Intervals()) {
2072 double startTime = interval->Start();
2073 double endTime = interval->End();
2074
2075 if (endTime < t0 || startTime > t1)
2076 continue;
2077
2078 // Assume all clips will have the same width
2079 if (buffer.empty()) {
2080 buffer.resize(maxAtOnce * width);
2081 buffers.resize(width);
2082 auto pBuffer = buffer.data();
2083 for (size_t ii = 0; ii < width; ++ii, pBuffer += maxAtOnce)
2084 buffers[ii] = reinterpret_cast<samplePtr>(pBuffer);
2085 }
2086
2087 const auto allZeroesAt = [&](size_t i) {
2088 auto pData = buffer.data() + i;
2089 for (size_t ii = 0; ii < width; ++ii, pData += maxAtOnce) {
2090 if (*pData != 0.0)
2091 return false;
2092 }
2093 return true;
2094 };
2095
2096 // simply look for a sequence of zeroes (across all channels) and if the
2097 // sequence is longer than the minimum number, split-delete the region
2098
2099 sampleCount seqStart = -1;
2100 auto start = interval->TimeToSamples(std::max(.0, t0 - startTime));
2101 auto end = interval->TimeToSamples(std::min(endTime, t1) - startTime);
2102
2103 auto len = (end - start);
2104 for (decltype(len) done = 0; done < len; done += maxAtOnce) {
2105 auto numSamples = limitSampleBufferSize(maxAtOnce, len - done);
2106
2107 auto bufferIt = buffers.begin();
2108
2109 for (auto channel : interval->Channels())
2110 channel->GetSamples(
2111 *bufferIt++, floatSample, start + done, numSamples);
2112
2113 for (decltype(numSamples) i = 0; i < numSamples; ++i) {
2114 auto curSamplePos = start + done + i;
2115
2116 //start a NEW sequence
2117 if (seqStart == -1 && allZeroesAt(i))
2118 seqStart = curSamplePos;
2119 else if (curSamplePos == end - 1 || !allZeroesAt(i)) {
2120 if (seqStart != -1) {
2121 decltype(end) seqEnd;
2122
2123 //consider the end case, where selection ends in zeroes
2124 if (curSamplePos == end - 1 && allZeroesAt(i))
2125 seqEnd = end;
2126 else
2127 seqEnd = curSamplePos;
2128 if (seqEnd - seqStart + 1 > minSamples) {
2129 regions.push_back(
2130 Region(
2131 startTime + interval->SamplesToTime(seqStart),
2132 startTime + interval->SamplesToTime(seqEnd)
2133 )
2134 );
2135 }
2136 seqStart = -1;
2137 }
2138 }
2139 } // samples
2140 } // blocks
2141 } // finding regions
2142
2143 for (const auto &region : regions)
2144 SplitDelete(region.start, region.end);
2145}
WaveTrack::Region Region
Definition: LabelMenus.cpp:25
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
#define WAVETRACK_MERGE_POINT_TOLERANCE
Definition: WaveTrack.h:67
void SplitDelete(double t0, double t1)
Definition: WaveTrack.cpp:1526
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 2987 of file WaveTrack.cpp.

2989{
2990 auto clip = std::make_shared<WaveClip>(NChannels(),
2992 clip->SetName(name);
2993 clip->SetSequenceStartTime(offset);
2994
2995 const auto& tempo = GetProjectTempo(*this);
2996 if (tempo.has_value())
2997 clip->OnProjectTempoChange(std::nullopt, *tempo);
2998 assert(clip->NChannels() == NChannels());
2999 return clip;
3000}
sampleFormat GetSampleFormat() const override
Definition: WaveTrack.cpp:918
double GetRate() const override
Definition: WaveTrack.cpp:821

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

2640{
2641 const auto nChannels = NChannels();
2642 assert(iChannel + nBuffers <= nChannels); // precondition
2643 return std::all_of(buffers, buffers + nBuffers, [&](samplePtr buffer) {
2644 const auto result = GetOne(mClips, iChannel++,
2645 buffer, format, start, len, backwards, fill, mayThrow,
2646 pNumWithinClips);
2647 return result;
2648 });
2649}
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:2651
WaveClipHolders mClips
Definition: WaveTrack.h:776

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

736{
737 auto nChannels = NChannels();
738 if (iChannel >= nChannels)
739 return {};
740 // TODO: more-than-two-channels
741 ::Channel &aliased = (iChannel == 0)
742 ? mChannel
743 : *mRightChannel;
744 // Use aliasing constructor of std::shared_ptr
745 return { shared_from_this(), &aliased };
746}

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

722{
723 if (iInterval < NIntervals())
724 return mClips[iInterval];
725 return {};
726}
size_t NIntervals() const override
Report the number of intervals.
Definition: WaveTrack.cpp:705

References mClips, and NIntervals().

Here is the call graph for this function:

◆ DoSetPan()

void WaveTrack::DoSetPan ( float  value)
private

Definition at line 865 of file WaveTrack.cpp.

866{
867 WaveTrackData::Get(*this).SetPan(value);
868}

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

837{
838 auto &data = WaveTrackData::Get(*this);
839 data.SetRate(static_cast<int>(newRate));
840}

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:

◆ DoSetVolume()

void WaveTrack::DoSetVolume ( float  value)
private

Definition at line 847 of file WaveTrack.cpp.

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

References BasicUI::Get().

Referenced by HandleXMLTag(), and SetVolume().

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

590{
591 const auto srcCopy = Duplicate();
592 ::DoProjectTempoChange(*srcCopy, newTempo);
593 return std::static_pointer_cast<WaveTrack>(srcCopy);
594}
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 1033 of file WaveTrack.cpp.

1035{
1036 return EmptyCopy(NChannels(), pFactory);
1037}

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

1014{
1015 const auto rate = GetRate();
1016 auto result = std::make_shared<WaveTrack>(CreateToken{},
1017 pFactory, GetSampleFormat(), rate);
1018 if (nChannels > 1)
1019 result->CreateRight();
1020 result->Init(*this);
1021 // Copy state rather than BuildAll()
1022 Track::CopyAttachments(*result, *this, true /* deep copy */);
1023 // The previous line might have destroyed the rate information stored in
1024 // channel group data. The copy is not yet in a TrackList. Reassign rate
1025 // in case the track needs to make WaveClips before it is properly joined
1026 // with the opposite channel in a TrackList.
1027 result->DoSetRate(rate);
1028 result->mpFactory = pFactory ? pFactory : mpFactory;
1029 WaveTrackData::Get(*result).SetOrigin(0);
1030 return result;
1031}
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(), StereoToMono::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 2334 of file WaveTrack.cpp.

2335{
2336 return this;
2337}

◆ FindClip()

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

Definition at line 1533 of file WaveTrack.cpp.

1534{
1535 auto clips = Intervals();
1536 const auto begin = clips.begin();
1537 const auto pred = [&](auto pClip){ return pClip.get() == &clip; };
1538 auto iter = std::find_if(begin, clips.end(), pred);
1539 return std::distance(begin, iter);
1540}
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,
bool  forClipboard 
)
private

Definition at line 1144 of file WaveTrack.cpp.

1146{
1147 // AWD, Oct 2009: If the selection ends in whitespace, create a
1148 // placeholder clip representing that whitespace
1149 // PRL: Only if we want the track for pasting into other tracks. Not if
1150 // it goes directly into a project as in the Duplicate command.
1151 if (forClipboard && GetEndTime() + 1.0 / GetRate() < t1 - t0) {
1152 auto placeholder = CreateClip();
1153 placeholder->SetIsPlaceholder(true);
1154 placeholder->InsertSilence(0, (t1 - t0) - GetEndTime());
1155 placeholder->ShiftBy(GetEndTime());
1156 InsertInterval(move(placeholder), true, false);
1157 }
1158}

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

2316{
2317 if (NIntervals() == 0)
2318 return;
2319 // After appending, presumably. Do this to the clip that gets appended.
2320 GetRightmostClip()->Flush();
2321}
IntervalHolder GetRightmostClip()
Definition: WaveTrack.cpp:2576

References GetRightmostClip(), and NIntervals().

Referenced by ImportUtils::FinalizeImport(), WaveTrackSink::Flush(), TrackSpectrumTransformer::PostProcess(), and SBSMSBase::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 1920 of file WaveTrack.cpp.

1921{
1922 const auto channels = TrackList::Channels(this);
1923 return std::all_of(channels.begin(), channels.end(),
1924 [&](const WaveTrack *pTrack){
1925 return pTrack && pTrack->mLegacyFormat == mLegacyFormat;
1926 });
1927}
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 2260 of file WaveTrack.cpp.

2261{
2262 auto bestBlockSize = GetMaxBlockSize();
2263
2264 for (const auto &clip : Intervals()) {
2265 auto startSample = clip->GetPlayStartSample();
2266 auto endSample = clip->GetPlayEndSample();
2267 if (s >= startSample && s < endSample)
2268 {
2269 // ignore extra channels (this function will soon be removed)
2270 bestBlockSize =
2271 clip->GetBestBlockSize(s - clip->GetSequenceStartSample());
2272 break;
2273 }
2274 }
2275
2276 return bestBlockSize;
2277}
size_t GetMaxBlockSize() const
Definition: WaveTrack.cpp:2279

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.

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

◆ GetChannelVolume()

float WaveTrack::GetChannelVolume ( int  channel) const
overridevirtual

Takes volume and pan into account.

Implements WideSampleSequence.

Definition at line 888 of file WaveTrack.cpp.

889{
890 // channel is not necessarily less than the channel group width but
891 // a mono track might pan differently according to that
892 float left = 1.0;
893 float right = 1.0;
894
895 const auto pan = GetPan();
896 if (pan < 0)
897 right = (pan + 1.0);
898 else if (pan > 0)
899 left = 1.0 - pan;
900
901 const auto volume = GetVolume();
902 if ((channel % 2) == 0)
903 return left * volume;
904 else
905 return right * volume;
906}
float GetPan() const
Definition: WaveTrack.cpp:860
float GetVolume() const
Definition: WaveTrack.cpp:842

References GetPan(), and GetVolume().

Referenced by WaveChannel::GetChannelVolume(), and StereoToMono::ProcessOne().

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

◆ GetClip() [1/2]

auto WaveTrack::GetClip ( size_t  iInterval)

Definition at line 710 of file WaveTrack.cpp.

711{
712 return std::static_pointer_cast<Interval>(DoGetInterval(iInterval));
713}
std::shared_ptr< WideChannelGroupInterval > DoGetInterval(size_t iInterval) override
Retrieve an interval.
Definition: WaveTrack.cpp:721

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

716{
717 return const_cast<WaveTrack&>(*this).GetClip(iInterval);
718}
IntervalHolder GetClip(size_t iInterval)
Definition: WaveTrack.cpp:710

References GetClip().

Here is the call graph for this function:

◆ GetClipAtTime()

auto WaveTrack::GetClipAtTime ( double  time) const
private

Definition at line 2951 of file WaveTrack.cpp.

2952{
2953 const auto clips = SortedClipArray();
2954 auto p = std::find_if(
2955 clips.rbegin(), clips.rend(), [&](const auto &pClip) {
2956 return pClip->WithinPlayRegion(time);
2957 });
2958 return p != clips.rend() ? *p : nullptr;
2959}
IntervalConstHolders SortedClipArray() const
Return all WaveClips sorted by clip play start time.
Definition: WaveTrack.cpp:3287

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

3038{
3039 int result = 0;
3040 const auto &clips = Intervals();
3041 const auto test =
3042 [&](const auto &pOtherClip){ return &clip == pOtherClip.get(); };
3043 auto begin = clips.begin(),
3044 end = clips.end(),
3045 iter = std::find_if(begin, end, test);
3046 return std::distance(begin, iter);
3047}

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

2593{
2594 auto clips = Intervals();
2595 return { clips.begin(), clips.end() };
2596}

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:3398
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, 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 2613 of file WaveTrack.cpp.

2614{
2615 return ChannelGroup::GetEndTime();
2616}
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(), TruncSilenceBase::Analyze(), ApplyPitchAndSpeed(), ClearAndPasteAtSameTempo(), FinishCopy(), Effect::GetBounds(), WaveChannel::GetEndTime(), PasteWaveTrackAtSameTempo(), TrackSpectrumTransformer::PostProcess(), StereoToMono::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 2874 of file WaveTrack.cpp.

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

References limitSampleBufferSize(), min(), and anonymous_namespace{RegisterBuiltinEffects.cpp}::reverse.

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

2549{
2550 for (const auto &pClip : Intervals()) {
2551 const auto width = pClip->NChannels();
2552 for (size_t ii = 0; ii < width; ++ii)
2553 if (pClip->GetSequence(ii)->GetErrorOpening())
2554 return XO("A track has a corrupted sample sequence.");
2555 }
2556
2557 return {};
2558}
XO("Cut/Copy/Paste")

References Intervals(), and XO().

Here is the call graph for this function:

◆ GetIdealBlockSize()

size_t WaveTrack::GetIdealBlockSize ( )

Definition at line 2300 of file WaveTrack.cpp.

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

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

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

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

2572 {
2573 return const_cast<WaveTrack&>(*this).GetLeftmostClip();
2574}
IntervalHolder GetLeftmostClip()
Definition: WaveTrack.cpp:2560

References GetLeftmostClip().

Here is the call graph for this function:

◆ GetMaxBlockSize()

size_t WaveTrack::GetMaxBlockSize ( ) const

Definition at line 2279 of file WaveTrack.cpp.

2280{
2281 const auto clips = Intervals();
2282 auto maxblocksize = std::accumulate(clips.begin(), clips.end(), size_t{},
2283 [](size_t acc, auto pClip){
2284 return std::max(acc, pClip->GetMaxBlockSize()); });
2285
2286 if (maxblocksize == 0)
2287 {
2288 // We really need the maximum block size, so create a
2289 // temporary sequence to get it.
2290 maxblocksize =
2292 .GetMaxBlockSize();
2293 }
2294
2295 wxASSERT(maxblocksize > 0);
2296
2297 return maxblocksize;
2298}
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 TruncSilenceBase::Analyze(), CompareAudioCommand::Apply(), GetBestBlockSize(), WaveChannel::GetMaxBlockSize(), LegacyCompressorBase::InitPass1(), StereoToMono::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 2339 of file WaveTrack.cpp.

2340{
2341 return PlayableTrack::GetMute();
2342}
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 3049 of file WaveTrack.cpp.

3050{
3051 return NarrowClips().size();
3052}
WaveClipHolders & NarrowClips()
Definition: WaveTrack.cpp:768

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

2655{
2656 if (backwards)
2657 start -= len;
2658 // Simple optimization: When this buffer is completely contained within one clip,
2659 // don't clear anything (because we won't have to). Otherwise, just clear
2660 // everything to be on the safe side.
2661 bool doClear = true;
2662 bool result = true;
2663 sampleCount samplesCopied = 0;
2664 for (const auto &clip: clips)
2665 {
2666 if (start >= clip->GetPlayStartSample() && start+len <= clip->GetPlayEndSample())
2667 {
2668 doClear = false;
2669 break;
2670 }
2671 }
2672 if (doClear)
2673 {
2674 // Usually we fill in empty space with zero
2675 if (fill == FillFormat::fillZero)
2676 ClearSamples(buffer, format, 0, len);
2677 // but we don't have to.
2678 else if (fill == FillFormat::fillTwo)
2679 {
2680 wxASSERT( format==floatSample );
2681 float * pBuffer = (float*)buffer;
2682 for(size_t i=0;i<len;i++)
2683 pBuffer[i]=2.0f;
2684 }
2685 else
2686 {
2687 wxFAIL_MSG(wxT("Invalid fill format"));
2688 }
2689 }
2690
2691 // Iterate the clips. They are not necessarily sorted by time.
2692 for (const auto &clip: clips)
2693 {
2694 auto clipStart = clip->GetPlayStartSample();
2695 auto clipEnd = clip->GetPlayEndSample();
2696
2697 if (clipEnd > start && clipStart < start+len)
2698 {
2699 if (clip->HasPitchOrSpeed())
2700 return false;
2701
2702 // Clip sample region and Get/Put sample region overlap
2703 auto samplesToCopy =
2704 std::min( start+len - clipStart, clip->GetVisibleSampleCount() );
2705 auto startDelta = clipStart - start;
2706 decltype(startDelta) inclipDelta = 0;
2707 if (startDelta < 0)
2708 {
2709 inclipDelta = -startDelta; // make positive value
2710 samplesToCopy -= inclipDelta;
2711 // samplesToCopy is now either len or
2712 // (clipEnd - clipStart) - (start - clipStart)
2713 // == clipEnd - start > 0
2714 // samplesToCopy is not more than len
2715 //
2716 startDelta = 0;
2717 // startDelta is zero
2718 }
2719 else {
2720 // startDelta is nonnegative and less than len
2721 // samplesToCopy is positive and not more than len
2722 }
2723
2724 if (!clip->GetSamples(iChannel,
2725 (samplePtr)(((char*)buffer) +
2726 startDelta.as_size_t() *
2728 format, inclipDelta, samplesToCopy.as_size_t(), mayThrow ))
2729 result = false;
2730 else
2731 samplesCopied += samplesToCopy;
2732 }
2733 }
2734 if( pNumWithinClips )
2735 *pNumWithinClips = samplesCopied;
2736 if (result == true && backwards)
2737 ReverseSamples(buffer, format, 0, len);
2738 return result;
2739}
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 860 of file WaveTrack.cpp.

861{
862 return WaveTrackData::Get(*this).GetPan();
863}

References BasicUI::Get().

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

2576 {
2577 auto clips = Intervals();
2578 if (clips.empty())
2579 return nullptr;
2580 const auto begin = clips.begin(),
2581 iter = std::max_element(begin, clips.end(),
2582 [](const auto& a, const auto b) {
2583 return a->GetPlayEndTime() < b->GetPlayEndTime();
2584 });
2585 return GetClip(std::distance(begin, iter));
2586}

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

2588 {
2589 return const_cast<WaveTrack&>(*this).GetRightmostClip();
2590}

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

919{
920 return WaveTrackData::Get(*this).GetSampleFormat();
921}

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

2743{
2745 for (const auto& channel : Channels()) {
2746 result.push_back(channel->GetSampleView(t0, t1, mayThrow));
2747 }
2748 return result;
2749}
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 2344 of file WaveTrack.cpp.

2345{
2346 return PlayableTrack::GetSolo();
2347}
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 2603 of file WaveTrack.cpp.

2604{
2606}
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(), StereoToMono::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 684 of file WaveTrack.cpp.

685{
686 return typeInfo();
687}

References typeInfo().

Here is the call graph for this function:

◆ GetVisibleSampleCount()

sampleCount WaveTrack::GetVisibleSampleCount ( ) const

Definition at line 908 of file WaveTrack.cpp.

909{
910 sampleCount result{ 0 };
911
912 for (const auto& clip : Intervals())
913 result += clip->GetVisibleSampleCount();
914
915 return result;
916}

References Intervals().

Here is the call graph for this function:

◆ GetVolume()

float WaveTrack::GetVolume ( ) const

Definition at line 842 of file WaveTrack.cpp.

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

References BasicUI::Get().

Referenced by GetChannelVolume(), GetInfoCommand::SendTracks(), SetVolume(), and WaveTrackControls::VolumeSlider().

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

◆ HandleClear()

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

Definition at line 1550 of file WaveTrack.cpp.

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

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

2426{
2427 if (auto pChild = WaveTrackIORegistry::Get().CallObjectAccessor(tag, *this))
2428 // Deserialize any extra attached structures
2429 return pChild;
2430
2431 const auto getClip = [this]() -> WaveClip & {
2432 return (*NewestOrNewClip()->Channels().begin())->GetClip();
2433 };
2434
2435 //
2436 // This is legacy code (1.2 and previous) and is not called for new projects!
2437 if (tag == Sequence::Sequence_tag || tag == "envelope") {
2438 // This is a legacy project, so set the cached offset
2439 NewestOrNewClip()->SetSequenceStartTime(mLegacyProjectFileOffset);
2440
2441 // Legacy project file tracks are imported as one single wave clip
2442 if (tag == Sequence::Sequence_tag)
2443 return getClip().GetSequence(0);
2444 else if (tag == "envelope")
2445 return &getClip().GetEnvelope();
2446 }
2447
2448 // JKC... for 1.1.0, one step better than what we had, but still badly broken.
2449 // If we see a waveblock at this level, we'd better generate a sequence.
2450 if (tag == Sequence::WaveBlock_tag) {
2451 // This is a legacy project, so set the cached offset
2452 NewestOrNewClip()->SetSequenceStartTime(mLegacyProjectFileOffset);
2453 auto pSeq = getClip().GetSequence(0);
2454 return pSeq;
2455 }
2456
2457 // This is for the new file format (post-1.2)
2458 if (tag == WaveClip::WaveClip_tag) {
2459 // Make clips (which don't serialize the rate) consistent with channel rate,
2460 // though the consistency check of channels with each other remains to do.
2461 // Not all `WaveTrackData` fields are properly initialized by now,
2462 // use deserialization helpers.
2463 auto clip = std::make_shared<WaveClip>(1,
2465 const auto xmlHandler = clip.get();
2466 auto &clips = NarrowClips();
2467 clips.push_back(std::move(clip));
2468 Publish({ clips.back(), WaveTrackMessage::Deserialized });
2469 return xmlHandler;
2470 }
2471
2472 return nullptr;
2473}
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:834
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 2413 of file WaveTrack.cpp.

2414{
2415#if 0
2416 // In case we opened a pre-multiclip project, we need to
2417 // simulate closing the waveclip tag.
2418 NewestOrNewClip()->HandleXMLEndTag(WaveClip::WaveClip_tag);
2419#else
2420 // File compatibility breaks have intervened long since, and the line above
2421 // would now have undesirable side effects
2422#endif
2423}

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

2362{
2363 if (tag == WaveTrack_tag) {
2364 double dblValue;
2365 long nValue;
2366
2367 for (const auto& pair : attrs)
2368 {
2369 const auto& attr = pair.first;
2370 const auto& value = pair.second;
2371
2372 if (attr == Rate_attr)
2373 {
2374 // mRate is an int, but "rate" in the project file is a float.
2375 if (!value.TryGet(dblValue) ||
2376 (dblValue < 1.0) || (dblValue > 1000000.0)) // allow a large range to be read
2377 return false;
2378
2379 // Defer the setting of rate until LinkConsistencyFix
2380 mLegacyRate = lrint(dblValue);
2381 }
2382 else if (attr == Offset_attr && value.TryGet(dblValue))
2383 {
2384 // Offset is only relevant for legacy project files. The value
2385 // is cached until the actual WaveClip containing the legacy
2386 // track is created.
2387 mLegacyProjectFileOffset = dblValue;
2388 }
2389 else if (this->WritableSampleTrack::HandleXMLAttribute(attr, value))
2390 {}
2391 else if (this->Track::HandleCommonXMLAttribute(attr, value))
2392 ;
2393 else if (attr == Volume_attr && value.TryGet(dblValue))
2394 DoSetVolume(dblValue);
2395 else if (attr == Pan_attr && value.TryGet(dblValue) &&
2396 (dblValue >= -1.0) && (dblValue <= 1.0))
2397 DoSetPan(dblValue);
2398 else if (attr == Linked_attr && value.TryGet(nValue))
2399 SetLinkType(ToLinkType(nValue), false);
2400 else if (attr == SampleFormat_attr && value.TryGet(nValue) &&
2402 {
2403 //Remember sample format until consistency check is performed.
2404 SetLegacyFormat(static_cast<sampleFormat>(nValue));
2405 }
2406 } // while
2407 return true;
2408 }
2409
2410 return false;
2411}
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:2356
static constexpr auto Rate_attr
Definition: WaveTrack.cpp:2352
static constexpr auto Volume_attr
Definition: WaveTrack.cpp:2353
static constexpr auto SampleFormat_attr
Definition: WaveTrack.cpp:2358
static constexpr auto Offset_attr
Definition: WaveTrack.cpp:2351
static constexpr auto Linked_attr
Definition: WaveTrack.cpp:2357
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:1902
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:865
static const char * WaveTrack_tag
Definition: WaveTrack.h:206
void SetLegacyFormat(sampleFormat format)
Definition: WaveTrack.cpp:2329
void DoSetVolume(float value)
Definition: WaveTrack.cpp:847
#define lrint(dbl)
Definition: float_cast.h:169
Track::LinkType ToLinkType(int value)
Definition: WaveTrack.cpp:345

References DoSetPan(), DoSetVolume(), 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(), Volume_attr, and WaveTrack_tag.

Here is the call graph for this function:

◆ HasClipNamed()

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

Definition at line 728 of file WaveTrack.cpp.

729{
730 auto clips = Intervals();
731 return std::any_of(clips.begin(), clips.end(),
732 [&](const auto &pClip){ return pClip->GetName() == name; });
733}

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

2859{
2860 auto pTrack = this;
2861 if (!pTrack)
2862 return false;
2863 auto clips = pTrack->Intervals();
2864 return std::all_of(clips.begin(), clips.end(),
2865 [](const auto &pClip){ return pClip->GetEnvelope().IsTrivial(); });
2866}

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

1931{
1932 if (!backup && !clip->GetIsPlaceholder() && !allowEmpty && clip->IsEmpty())
1933 return false;
1934
1935 const auto& tempo = GetProjectTempo(*this);
1936 if (tempo.has_value())
1937 clip->OnProjectTempoChange(std::nullopt, *tempo);
1938 clips.push_back(std::move(clip));
1939 Publish({ clips.back(),
1941
1942 return true;
1943}
@ 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 3235 of file WaveTrack.cpp.

3237{
3238 if (clip) {
3239 constexpr bool backup = false;
3240 InsertClip(mClips, clip, newClip, backup, allowEmpty);
3241 // Detect errors resulting in duplicate shared pointers to clips
3242 assert(ClipsAreUnique(mClips));
3243 }
3244}
bool ClipsAreUnique(const WaveClipHolders &clips)
Definition: WaveTrack.cpp:3227

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

2024{
2025 // Nothing to do, if length is zero.
2026 // Fixes Bug 1626
2027 if (len == 0)
2028 return;
2029 if (len <= 0)
2031
2032 auto &&clips = Intervals();
2033 if (clips.empty()) {
2034 // Special case if there is no clip yet
2035 auto clip = CreateClip(0);
2036 clip->InsertSilence(0, len);
2037 // use No-fail-guarantee
2038 InsertInterval(move(clip), true);
2039 }
2040 else
2041 {
2042 // Assume at most one clip contains t
2043 const auto end = clips.end();
2044 const auto it = std::find_if(clips.begin(), end,
2045 [&](const IntervalHolder &clip) { return clip->SplitsPlayRegion(t); } );
2046
2047 // use Strong-guarantee
2048 if (it != end)
2049 (*it)->InsertSilence(t, len);
2050
2051 // use No-fail-guarantee
2052 for (const auto &&clip : clips)
2053 if (clip->BeforePlayRegion(t))
2054 clip->ShiftBy(len);
2055 }
2056}

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

Referenced by AUPImportFileHandle::AddSilence(), and SilenceBase::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 672 of file WaveTrack.h.

672{ 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 933 of file WaveTrack.cpp.

934{
935 if (t0 > t1)
936 return true;
937
938 //wxPrintf("Searching for overlap in %.6f...%.6f\n", t0, t1);
939 for (const auto &clip : Intervals())
940 {
941 if (clip->IntersectsPlayRegion(t0, t1)) {
942 //wxPrintf("Overlapping clip: %.6f...%.6f\n",
943 // clip->GetStartTime(),
944 // clip->GetEndTime());
945 // We found a clip that overlaps this region
946 return false;
947 }
948 }
949 //wxPrintf("No overlap found\n");
950
951 // Otherwise, no clips overlap this region
952 return true;
953}

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

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

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

597{
598 // This implies satisfaction of the precondition of SetRate()
599 assert(!doFix || IsLeader());
600
601 const auto removeZeroClips = [](WaveClipHolders& clips) {
602 // Check for zero-length clips and remove them
603 for (auto it = clips.begin(); it != clips.end();)
604 {
605 if ((*it)->IsEmpty())
606 it = clips.erase(it);
607 else
608 ++it;
609 }
610 };
611
613
614 auto linkType = GetLinkType();
615 if (linkType != LinkType::None) {
616 auto next = *TrackList::Channels(this).first.advance(1);
617 if (next == nullptr) {
618 //next track is absent or not a wave track, fix and report error
619 if (doFix) {
620 wxLogWarning(L"Right track %s is expected to be a WaveTrack."
621 "\n Removing link from left wave track %s.",
622 next->GetName(), GetName());
624 }
625 err = true;
626 }
627 else if (doFix) {
628 // non-error upgrades happen here
629 if (!AreAligned(SortedClipArray(), next->SortedClipArray()) ||
631 {
632 SetLinkType(linkType = LinkType::None);
633 }
634 else
635 {
636 SetLinkType(linkType = LinkType::Aligned);
637 //clean up zero clips only after alignment check has completed
638 //this can't break alignment as there should be a "twin"
639 //in the right channel which will also be removed, otherwise
640 //track will be unlinked because AreAligned returned false
641 removeZeroClips(NarrowClips());
642 removeZeroClips(next->NarrowClips());
643 }
644 }
645 }
646 if (doFix) {
647 // More non-error upgrading
648 // Set the common channel group rate from the unzipped leader's rate
649 if (mLegacyRate > 0)
650 {
651 WaveTrack *next{};
652 if (linkType != LinkType::None)
653 next = *TrackList::Channels(this).first.advance(1);
655 mLegacyRate = 0;
656 if (next && next->mLegacyRate > 0)
657 {
658 next->SetRate(next->mLegacyRate);
659 next->mLegacyRate = 0;
660 }
662 WaveTrackData::Get(*this).SetSampleFormat(mLegacyFormat);
663 if (next && next->mLegacyFormat != undefinedSample)
664 WaveTrackData::Get(*next).SetSampleFormat(mLegacyFormat);
665 }
666 if (linkType == LinkType::None)
667 // Did not visit the other call to removeZeroClips, do it now
668 removeZeroClips(NarrowClips());
669 else
670 // Make a real wide wave track from two deserialized narrow tracks
671 ZipClips();
672 }
673 return !err;
674}
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:826
void ZipClips(bool mustAlign=true)
Definition: WaveTrack.cpp:3317
bool FormatConsistencyCheck() const
Definition: WaveTrack.cpp:1920
bool RateConsistencyCheck() const
Whether all clips of an unzipped leader track have a common rate.
Definition: WaveTrack.cpp:1901
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 793 of file WaveTrack.cpp.

794{
795 auto name = originalName;
796 for (auto i = 1;; ++i)
797 {
798 if (!HasClipNamed(name))
799 return name;
800 //i18n-hint Template for clip name generation on copy-paste
801 name = XC("%s.%i", "clip name template").Format(originalName, i).Translation();
802 }
803}
#define XC(s, c)
Definition: Internat.h:37
bool HasClipNamed(const wxString &name) const
Definition: WaveTrack.cpp:728

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

1040{
1041 mRightChannel.reset();
1042 for (auto &pClip : mClips)
1043 pClip->DiscardRightChannel();
1045}
void EraseChannelAttachments(size_t index)
Erase all attachments for a given index.
Definition: WaveTrack.cpp:452

References EraseChannelAttachments(), mClips, and mRightChannel.

Referenced by StereoToMono::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 805 of file WaveTrack.cpp.

806{
807 for (auto i = 1;; ++i)
808 {
809 //i18n-hint Template for clip name generation on inserting new empty clip
810 auto name = XC("%s.%i", "clip name template").Format(GetName(), i).Translation();
811 if (!HasClipNamed(name))
812 return name;
813 }
814}

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

3186{
3187 const auto clip1 = GetClip(clipidx1);
3188 const auto clip2 = GetClip(clipidx2);
3189
3190 if (!clip1 || !clip2)
3191 return false; // Don't throw, just do nothing.
3192
3193 if (!clip1->HasEqualPitchAndSpeed(*clip2))
3194 return false;
3195
3196 // Append data from second clip to first clip
3197 // use Strong-guarantee
3198 bool success = clip1->Paste(clip1->GetPlayEndTime(), *clip2);
3199 assert(success); // assuming clips of the same track must have same width
3200
3201 // use No-fail-guarantee for the rest
3202 // Delete second clip
3203 RemoveInterval(clip2);
3204 return true;
3205}

References GetClip(), and RemoveInterval().

Here is the call graph for this function:

◆ MonoToStereo()

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

Definition at line 1047 of file WaveTrack.cpp.

1048{
1049 assert(!GetOwner());
1050 MakeMono();
1051
1052 // Make temporary new mono track
1053 auto newTrack = Duplicate();
1054
1055 // Make a list
1056 auto result = TrackList::Temporary(nullptr, shared_from_this());
1057 result->Add(newTrack);
1058 // Destroy the temporary track, widening this track to stereo
1059 ZipClips();
1060
1061 return std::static_pointer_cast<WaveTrack>(result->DetachFirst());
1062}
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:1039

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

769{
770 return mClips;
771}

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

774{
775 return mClips;
776}

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

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

3003{
3004 const auto &intervals = Intervals();
3005 if (intervals.empty()) {
3006 const auto origin = WaveTrackData::Get(*this).GetOrigin();
3007 const auto name = MakeNewClipName();
3008 auto pInterval = CreateClip(origin, name);
3009 InsertInterval(pInterval, true, true);
3010 return pInterval;
3011 }
3012 else
3013 return mClips.back();
3014}
wxString MakeNewClipName() const
Definition: WaveTrack.cpp:805

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

706{
707 return NarrowClips().size();
708}

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

1987{
1988 if (const auto other = dynamic_cast<const WaveTrack*>(&src))
1989 {
1990 // Currently `Paste` isn't used by code that wants the newer "don't merge
1991 // when copy/pasting" behaviour ...
1992 constexpr auto merge = true;
1993 PasteWaveTrack(t0, *other, merge);
1994 }
1995 else
1996 // THROW_INCONSISTENCY_EXCEPTION; // ?
1997 (void)0;// Empty if intentional.
1998}

References PasteWaveTrack().

Referenced by StereoToMono::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 694 of file WaveTrack.cpp.

696{
697 auto &trackFactory = WaveTrackFactory::Get(project);
698 auto &pSampleBlockFactory = trackFactory.GetSampleBlockFactory();
699 auto pFirstTrack = EmptyCopy(pSampleBlockFactory);
700 list.Add(pFirstTrack->SharedPointer());
701 pFirstTrack->Paste(0.0, *this);
702 return pFirstTrack->SharedPointer();
703}
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 1709 of file WaveTrack.cpp.

1710{
1711 // Get a modifiable copy of `src` because it may come from another project
1712 // with different tempo, making boundary queries incorrect.
1713 const auto& tempo = GetProjectTempo(*this);
1714 if (!tempo.has_value())
1716 const auto copyHolder = other.DuplicateWithOtherTempo(*tempo);
1717 PasteWaveTrackAtSameTempo(t0, *copyHolder, merge);
1718}
void PasteWaveTrackAtSameTempo(double t0, const WaveTrack &other, bool merge)
Definition: WaveTrack.cpp:1720

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

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

1902{
1903 // The channels and all clips in them should have the same sample rate.
1904 std::optional<double> oRate;
1905 auto channels = TrackList::Channels(this);
1906 return std::all_of(channels.begin(), channels.end(),
1907 [&](const WaveTrack *pTrack){
1908 if (!pTrack)
1909 return false;
1910
1911 const auto rate = pTrack->mLegacyRate;
1912 if (!oRate)
1913 oRate = rate;
1914 else if (*oRate != rate)
1915 return false;
1916 return true;
1917 });
1918}

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

1543{
1544 auto &clips = NarrowClips();
1545 if (distance < clips.size())
1546 clips.erase(clips.begin() + distance);
1547}

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

3247{
3248 const auto end = mClips.end(),
3249 iter = find(mClips.begin(), end, interval);
3250 if (iter != end)
3251 mClips.erase(iter);
3252}

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

2324{
2325 for (auto pInterval : Intervals())
2326 pInterval->RepairChannels();
2327}

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

3256{
3257 assert(newOne == oldOne || FindClip(*newOne) == Intervals().size());
3258 assert(oldOne->NChannels() == newOne->NChannels());
3259 RemoveInterval(oldOne);
3260 InsertInterval(newOne, false);
3261 newOne->SetName(oldOne->GetName());
3262}
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 3266 of file WaveTrack.cpp.

3267{
3268 for (const auto &pClip : Intervals())
3269 pClip->Resample(rate, progress);
3270 DoSetRate(rate);
3271}

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

3018{
3019 if (mClips.empty()) {
3020 auto pInterval = CreateClip(
3021 WaveTrackData::Get(*this).GetOrigin());
3022 InsertInterval(pInterval, true, true);
3023 return pInterval;
3024 }
3025 else {
3026 auto end = mClips.end(),
3027 it = max_element(mClips.begin(), end,
3028 [](const auto &pClip1, const auto &pClip2){
3029 return pClip1->GetPlayStartTime() < pClip2->GetPlayStartTime();
3030 });
3031 assert(it != end);
3032 return *it;
3033 }
3034}

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

3275{
3276 bool result = true;
3277 size_t ii = 0;
3278 for (const auto &pChannel : Channels()) {
3279 const auto buffer = buffers[ii++];
3280 assert(buffer); // precondition
3281 result = pChannel->SetFloats(buffer, start, len, effectiveFormat)
3282 && result;
3283 }
3284 return result;
3285}

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:

◆ SetLegacyFormat()

void WaveTrack::SetLegacyFormat ( sampleFormat  format)

Definition at line 2329 of file WaveTrack.cpp.

2330{
2332}

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

871{
872 if (newPan > 1.0)
873 newPan = 1.0;
874 else if (newPan < -1.0)
875 newPan = -1.0;
876
877 if ( GetPan() != newPan ) {
878 DoSetPan(newPan);
879 Notify(true);
880 }
881}
void Notify(bool allChannels, int code=-1)
Definition: Track.cpp:234

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

827{
828 assert(newRate > 0);
829 newRate = std::max( 1.0, newRate );
830 DoSetRate(newRate);
831
832 for (const auto &clip : Intervals())
833 clip->SetRate(newRate);
834}

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:

◆ SetVolume()

void WaveTrack::SetVolume ( float  newVolume)

Definition at line 852 of file WaveTrack.cpp.

853{
854 if (GetVolume() != newVolume) {
855 DoSetVolume(newVolume);
856 Notify(true);
857 }
858}

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

◆ ShiftBy()

void WaveTrack::ShiftBy ( double  t0,
double  delta 
)
overridevirtual
Exception safety guarantee:
No-fail

Implements ChannelGroup.

Definition at line 574 of file WaveTrack.cpp.

575{
576 for (const auto &pInterval : Intervals())
577 { // assume No-fail-guarantee
578 if(pInterval->Start() >= t0)
579 pInterval->ShiftBy(delta);
580 }
581 const auto origin = WaveTrackData::Get(*this).GetOrigin();
582 if(t0 <= origin)
583 {
584 const auto offset = t0 >= 0 ? delta : t0 + delta;
585 WaveTrackData::Get(*this).SetOrigin(origin + offset);
586 }
587}

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

Here is the call graph for this function:

◆ Silence()

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

Implements Track.

Definition at line 2000 of file WaveTrack.cpp.

2001{
2002 if (t1 < t0)
2004
2005 ApplyPitchAndSpeed({ { t0, t1 } }, std::move(reportProgress));
2006
2007 auto start = TimeToLongSamples(t0);
2008 auto end = TimeToLongSamples(t1);
2009
2010 for (const auto &pClip : Intervals()) {
2011 auto clipStart = pClip->GetPlayStartSample();
2012 auto clipEnd = pClip->GetPlayEndSample();
2013 if (clipEnd > start && clipStart < end) {
2014 auto offset = std::max(start - clipStart, sampleCount(0));
2015 // Clip sample region and Get/Put sample region overlap
2016 auto length = std::min(end, clipEnd) - (clipStart + offset);
2017 pClip->SetSilence(offset, length);
2018 }
2019 }
2020}
void ApplyPitchAndSpeed(std::optional< TimeInterval > interval, ProgressReporter reportProgress)
Definition: WaveTrack.cpp:1945

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

3288{
3289 const auto &intervals = Intervals();
3290 IntervalConstHolders clips{ intervals.begin(), intervals.end() };
3291 const auto comp = [](const auto &a, const auto &b) {
3292 return a->GetPlayStartTime() < b->GetPlayStartTime(); };
3293 std::sort(clips.begin(), clips.end(), comp);
3294 return clips;
3295}
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 3297 of file WaveTrack.cpp.

3298{
3299 const auto &intervals = Intervals();
3300 IntervalHolders result;
3301 copy(intervals.begin(), intervals.end(), back_inserter(result));
3302 sort(result.begin(), result.end(), [](const auto &pA, const auto &pB){
3303 return pA->GetPlayStartTime() < pB->GetPlayStartTime(); });
3304 return result;
3305}
void copy(const T *src, T *dst, int32_t n)
Definition: VectorOps.h:40

References staffpad::vo::copy().

Referenced by SetEnvelopeCommand::ApplyInner(), SBSMSBase::Finalize(), anonymous_namespace{ClipMenus.cpp}::FindNextClip(), anonymous_namespace{ClipMenus.cpp}::FindNextClipBoundary(), anonymous_namespace{ClipMenus.cpp}::FindPrevClip(), anonymous_namespace{ClipMenus.cpp}::FindPrevClipBoundary(), FindWaveTrackLocations(), anonymous_namespace{NyquistBase.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 3307 of file WaveTrack.cpp.

3308{
3309 const auto &intervals = Intervals();
3310 IntervalConstHolders result;
3311 copy(intervals.begin(), intervals.end(), back_inserter(result));
3312 sort(result.begin(), result.end(), [](const auto &pA, const auto &pB){
3313 return pA->GetPlayStartTime() < pB->GetPlayStartTime(); });
3314 return result;
3315}

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

3158{
3159 SplitAt(t0);
3160 if (t0 != t1)
3161 SplitAt(t1);
3162}
std::pair< IntervalHolder, IntervalHolder > SplitAt(double t)
Definition: WaveTrack.cpp:3165

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

3166{
3167 for (const auto &&c : Intervals()) {
3168 if (c->SplitsPlayRegion(t)) {
3169 t = SnapToSample(t);
3170 auto newClip = CopyClip(*c, true);
3171 c->TrimRightTo(t);// put t on a sample
3172 newClip->TrimLeftTo(t);
3173 auto result = std::pair{ c, newClip };
3174
3175 // This could invalidate the iterators for the loop! But we return
3176 // at once so it's okay
3177 InsertInterval(move(newClip), false); // transfer ownership
3178 return result;
3179 }
3180 }
3181 return {};
3182}

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

Here is the caller graph for this function:

◆ SplitChannels()

auto WaveTrack::SplitChannels ( )

Definition at line 1064 of file WaveTrack.cpp.

1065{
1066 std::vector<Holder> result{ SharedPointer<WaveTrack>() };
1067 if (NChannels() == 2) {
1068 auto pOwner = GetOwner();
1069 assert(pOwner); // pre
1070 auto pNewTrack = result.emplace_back(EmptyCopy(1));
1071 for (auto &pClip : mClips)
1072 pNewTrack->mClips.emplace_back(pClip->SplitChannels());
1073 this->mRightChannel.reset();
1074 TrackList::AssignUniqueId(pNewTrack);
1075 auto iter = pOwner->Find(this);
1076 pOwner->Insert(*++iter, pNewTrack);
1077 // Fix up the channel attachments to avoid waste of space
1078 result[0]->EraseChannelAttachments(1);
1079 result[1]->EraseChannelAttachments(0);
1080 }
1081 return result;
1082}
static void AssignUniqueId(const Track::Holder &track)
Assigns a new unique non-persistent id to a track.
Definition: Track.cpp:870

References TrackList::AssignUniqueId().

Referenced by WaveTrackMenuTable::SplitStereo().

Here is the call graph for this function:
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 966 of file WaveTrack.cpp.

967{
968 if (t1 < t0)
970
971 // SplitCut is the same as 'Copy', then 'SplitDelete'
972 auto result = Copy(t0, t1);
973 SplitDelete(t0, t1);
974 return std::static_pointer_cast<WaveTrack>(result);
975}

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

1527{
1528 constexpr bool addCutLines = false;
1529 constexpr bool split = true;
1530 HandleClear(t0, t1, addCutLines, split);
1531}

References HandleClear().

Referenced by Disjoin(), SBSMSBase::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 1084 of file WaveTrack.cpp.

1085{
1086 assert(NChannels() == 2);
1087 for (const auto &pClip: mClips)
1088 pClip->SwapChannels();
1089 this->AttachedTrackObjects::ForEach([this](TrackAttachment &attachment){
1090 if (const auto pAttachments =
1091 dynamic_cast<ChannelAttachmentsBase *>(&attachment)) {
1092 pAttachments->SwapChannels(shared_from_this());
1093 }
1094 });
1095}

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

1672{
1673 const auto endTime = GetEndTime();
1674 if (newT1 > oldT1 &&
1675 // JKC: This is a rare case where using >= rather than > on a float matters.
1676 // GetEndTime() looks through the clips and may give us EXACTLY the same
1677 // value as T1, when T1 was set to be at the end of one of those clips.
1678 oldT1 >= endTime)
1679 return;
1680 if (newT1 > oldT1) {
1681 // Insert space within the track
1682
1683 // If track is empty at oldT1 insert whitespace; otherwise, silence
1684 if (IsEmpty(oldT1, oldT1)) {
1685 // Check if clips can move
1686 if (EditClipsCanMove.Read()) {
1687 const auto offset = newT1 - oldT1;
1688 const auto rate = GetRate();
1689 for (const auto &clip : Intervals())
1690 if (clip->GetPlayStartTime() > oldT1 - (1.0 / rate))
1691 clip->ShiftBy(offset);
1692 }
1693 return;
1694 }
1695 else {
1696 // AWD: Could just use InsertSilence() on its own here, but it doesn't
1697 // follow EditClipCanMove rules (Paste() does it right)
1698 const auto duration = newT1 - oldT1;
1699 auto tmp = EmptyCopy(mpFactory);
1700 tmp->InsertSilence(0.0, duration);
1701 tmp->Flush();
1702 Paste(oldT1, *tmp);
1703 }
1704 }
1705 else if (newT1 < oldT1)
1706 Clear(newT1, oldT1);
1707}
BoolSetting EditClipsCanMove
Definition: WaveTrack.cpp:3417
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:933

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

981{
982 bool inside0 = false;
983 bool inside1 = false;
984
985 for (const auto &clip : Intervals()) {
986 if (t1 > clip->GetPlayStartTime() && t1 < clip->GetPlayEndTime()) {
987 clip->SetTrimRight(
988 clip->GetTrimRight() + clip->GetPlayEndTime() - t1);
989 inside1 = true;
990 }
991
992 if (t0 > clip->GetPlayStartTime() && t0 < clip->GetPlayEndTime()) {
993 clip->SetTrimLeft(
994 clip->GetTrimLeft() + t0 - clip->GetPlayStartTime());
995 inside0 = true;
996 }
997 }
998
999 //if inside0 is false, then the left selector was between
1000 //clips, so DELETE everything to its left.
1001 if (const auto endTime = GetEndTime()
1002 ; !inside1 && t1 < endTime
1003 )
1004 Clear(t1, endTime);
1005
1006 if (const auto startTime = GetStartTime()
1007 ; !inside0 && t0 > startTime
1008 )
1009 SplitDelete(startTime, t0);
1010}

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

2846{
2847 auto result = narrowestSampleFormat;
2848 for (const auto &pClip : Intervals())
2849 result = std::max(result, pClip->GetSampleFormats().Effective());
2850 return result;
2851}
@ 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 2485 of file WaveTrack.cpp.

2488{
2489 // Track data has always been written using channel-major iteration.
2490 // Do it still this way for compatibility.
2491
2492 // Some values don't vary independently in channels but have been written
2493 // redundantly for each channel. Keep doing this in 3.4 and later in case
2494 // a project is opened in an earlier version.
2495
2496 xmlFile.StartTag(WaveTrack_tag);
2497 auto &track = channel.GetTrack();
2498
2499 // Name, selectedness, etc. are channel group properties
2500 track.Track::WriteCommonXMLAttributes(xmlFile);
2501
2502 // Write the "channel" attribute so earlier versions can interpret stereo
2503 // tracks, but this version doesn't read it
2504 {
2505 enum ChannelType {
2506 LeftChannel = 0,
2507 RightChannel = 1,
2508 MonoChannel = 2
2509 };
2510 const auto channelType = (nChannels == 0)
2511 ? MonoChannel
2512 : (iChannel == 0)
2513 ? LeftChannel
2514 : RightChannel;
2515 xmlFile.WriteAttr(Channel_attr, channelType);
2516 }
2517
2518 // The "linked" flag is used to define the beginning of a channel group
2519 // that isn't mono
2520 const auto linkType = static_cast<int>(
2521 (iChannel == 0) && (nChannels == 2)
2523 : LinkType::None);
2524 xmlFile.WriteAttr(Linked_attr, linkType);
2525
2526 // VS: trying to save tracks that didn't pass all necessary
2527 // initializations on project read from the disk.
2528 const auto useLegacy = track.mLegacyRate != 0;
2529
2530 // More channel group properties written redundantly
2531 track.WritableSampleTrack::WriteXMLAttributes(xmlFile);
2532 xmlFile.WriteAttr(Rate_attr, useLegacy ? track.mLegacyRate : track.GetRate());
2533 xmlFile.WriteAttr(Volume_attr, static_cast<double>(track.GetVolume()));
2534 xmlFile.WriteAttr(Pan_attr, static_cast<double>(track.GetPan()));
2535 xmlFile.WriteAttr(SampleFormat_attr, static_cast<long>(useLegacy ? track.mLegacyFormat : track.GetSampleFormat()));
2536
2537 // Other persistent data specified elsewhere;
2538 // NOT written redundantly any more
2539 if (iChannel == 0)
2540 WaveTrackIORegistry::Get().CallWriters(track, xmlFile);
2541
2542 for (const auto &clip : channel.Intervals())
2543 clip->WriteXML(xmlFile);
2544
2545 xmlFile.EndTag(WaveTrack_tag);
2546}
static constexpr auto Channel_attr
Definition: WaveTrack.cpp:2359
WaveTrack & GetTrack()
Definition: WaveTrack.h:841
IteratorRange< IntervalIterator< WaveClipChannel > > Intervals()
Definition: WaveTrack.cpp:762
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(), 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(), Volume_attr, 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 2475 of file WaveTrack.cpp.

2477{
2478 const auto channels = Channels();
2479 size_t iChannel = 0,
2480 nChannels = channels.size();
2481 for (const auto pChannel : channels)
2482 WriteOneXML(*pChannel, xmlFile, iChannel++, nChannels);
2483}
static void WriteOneXML(const WaveChannel &channel, XMLWriter &xmlFile, size_t iChannel, size_t nChannels)
Definition: WaveTrack.cpp:2485

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

3318{
3319 const auto pOwner = GetOwner();
3320 assert(GetOwner()); // pre
3321 assert(NChannels() == 1); // pre
3322
3323 // If deserializing, first un-link the track, so iterator finds the partner.
3325
3326 auto iter = pOwner->Find(this);
3327 assert(this == *iter);
3328 ++iter;
3329 assert(iter != pOwner->end()); // pre
3330 auto pRight = dynamic_cast<WaveTrack*>(*iter);
3331 assert(pRight && pRight->NChannels() == 1); // pre
3332
3334 if (mustAlign &&
3335 !AreAligned(this->SortedClipArray(), pRight->SortedClipArray()))
3336 return;
3337
3338 CreateRight();
3339
3340 // Now steal right side sample data info. When not requiring alignment,
3341 // because this is a track that just keeps the sample counts of blocks
3342 // above 0 for later purposes -- then there is laxity about consistent
3343 // width of the clips.
3344 auto iterMe = mClips.begin(),
3345 endMe = mClips.end();
3346 auto iterRight = pRight->mClips.begin(),
3347 endRight = pRight->mClips.end();
3348 while (iterMe != endMe && iterRight != endRight) {
3349 (*iterMe)->MakeStereo(std::move(**iterRight), mustAlign);
3350 ++iterMe;
3351 ++iterRight;
3352 }
3353 assert(!mustAlign || (iterMe == endMe && iterRight == endRight));
3354
3355 while (iterRight != endRight) {
3356 // Leftover misaligned mono clips
3357 mClips.emplace_back(move(*iterRight));
3358 ++iterRight;
3359 }
3360
3361 this->MergeChannelAttachments(std::move(*pRight));
3362
3363 pOwner->Remove(*pRight);
3364}
void CreateRight()
Definition: WaveTrack.cpp:2982
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 833 of file WaveTrack.h.

◆ mChannel

WaveChannel WaveTrack::mChannel
private
Invariant
non-null

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

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

◆ mFlushCriticalSection

wxCriticalSection WaveTrack::mFlushCriticalSection
private

Definition at line 832 of file WaveTrack.h.

◆ mLegacyFormat

sampleFormat WaveTrack::mLegacyFormat { undefinedSample }
private

used only during deserialization

Definition at line 779 of file WaveTrack.h.

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

◆ mLegacyProjectFileOffset

double WaveTrack::mLegacyProjectFileOffset { 0 }
private

Definition at line 834 of file WaveTrack.h.

Referenced by HandleXMLChild(), and HandleXMLTag().

◆ mLegacyRate

int WaveTrack::mLegacyRate { 0 }
mutableprivate

used only during deserialization

Definition at line 778 of file WaveTrack.h.

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

◆ mpFactory

SampleBlockFactoryPtr WaveTrack::mpFactory
private

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

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

◆ WaveChannel

friend WaveTrack::WaveChannel
private

Definition at line 836 of file WaveTrack.h.

◆ WaveTrack_tag

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

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