Audacity 3.2.0
Channel.h
Go to the documentation of this file.
1/*!********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 @file Channel.h
6 @brief Abstract class ChannelGroup with two discrete iterable dimensions,
7 channels and intervals; subclasses associate information with those and
8 their intersections
9
10 Dominic Mazzoni
11
12 Paul Licameli split from Track.h
13
14**********************************************************************/
15#ifndef __AUDACITY_CHANNEL__
16#define __AUDACITY_CHANNEL__
17
18#include <cassert>
19#include <optional>
20#include <vector>
21
22#include "ClientData.h"
23#include "MemoryX.h"
24
26
30class CHANNEL_API ChannelGroupInterval {
31public:
33 ChannelGroupInterval(double start, double end)
34 : mStart{ start }, mEnd{ end }
35 {
36 assert(start <= end);
37 }
38
40
41 double Start() const { return mStart; }
42 double End() const { return mEnd; }
43
44private:
45 const double mStart, mEnd;
46};
47
49class CHANNEL_API ChannelInterval {
50public:
52};
53
54class ChannelGroup;
55
58
64public:
67
73 const ChannelGroup &group, double start, double end);
75
77
80 size_t NChannels() const { return mNChannels; }
81
83
89 template<typename IntervalType = ChannelInterval>
90 std::shared_ptr<IntervalType> GetChannel(size_t iChannel)
91 {
92 return
93 std::dynamic_pointer_cast<IntervalType>(DoGetChannel(iChannel));
94 }
95
99 template<typename IntervalType = const ChannelInterval>
100 auto GetChannel(size_t iChannel) const
101 -> std::enable_if_t<std::is_const_v<IntervalType>,
102 std::shared_ptr<IntervalType>>
103 {
104 return std::dynamic_pointer_cast<IntervalType>(
105 const_cast<WideChannelGroupInterval*>(this)->DoGetChannel(iChannel));
106 }
107
110 template<typename IntervalType>
112 : public ValueIterator<
113 std::shared_ptr<IntervalType>, std::bidirectional_iterator_tag
114 >
115 {
116 using GroupType = std::conditional_t<std::is_const_v<IntervalType>,
118 public:
119 ChannelIterator() = default;
120 ChannelIterator(GroupType *pGroup, size_t index)
121 : mpGroup{ pGroup }, mIndex{ index }
122 {}
123
124 std::shared_ptr<IntervalType> operator *() const
125 {
126 if (!mpGroup || mIndex >= mpGroup->NChannels())
127 return {};
128 return mpGroup->template GetChannel<IntervalType>(mIndex);
129 }
130
131 ChannelIterator &operator ++() { ++mIndex; return *this; }
132 ChannelIterator operator ++(int)
133 { auto copy{ *this }; operator ++(); return copy; }
134
135 ChannelIterator &operator --() { --mIndex; return *this; }
136 ChannelIterator operator --(int)
137 { auto copy{ *this }; operator --(); return copy; }
138
140 { return a.mpGroup == b.mpGroup && a.mIndex == b.mIndex; }
142 { return !(a == b); }
143
144 private:
145 GroupType *mpGroup{};
146 size_t mIndex{};
147 };
148
150 template<typename IntervalType = ChannelInterval>
152 {
153 return { { this, 0 }, { this, NChannels() } };
154 }
155
157 template<typename IntervalType = const ChannelInterval>
158 auto Channels() const
159 -> std::enable_if_t<std::is_const_v<IntervalType>,
160 IteratorRange<ChannelIterator<IntervalType>>
161 >
162 {
163 return { { this, 0 }, { this, NChannels() } };
164 }
165
166protected:
168
171 virtual std::shared_ptr<ChannelInterval> DoGetChannel(size_t iChannel) = 0;
172
173private:
174 const size_t mNChannels;
175};
176
177class CHANNEL_API Channel
178{
179public:
180 virtual ~Channel();
181
183 ChannelGroup &GetChannelGroup();
187 const ChannelGroup &GetChannelGroup() const;
188
192 size_t GetChannelIndex() const;
193
194 size_t ReallyGetChannelIndex() const;
195
202
204 size_t NIntervals() const;
205
207
211 template<typename IntervalType = Interval>
212 std::shared_ptr<IntervalType> GetInterval(size_t iInterval);
213
217 template<typename IntervalType = const Interval>
218 auto GetInterval(size_t iInterval) const
219 -> std::enable_if_t<std::is_const_v<IntervalType>,
220 std::shared_ptr<IntervalType>>;
221
224
228 template<typename IntervalType>
230 : public ValueIterator<
231 std::shared_ptr<IntervalType>, std::bidirectional_iterator_tag
232 >
233 {
234 using ChannelType = std::conditional_t<std::is_const_v<IntervalType>,
235 const Channel, Channel>;
236 public:
237 IntervalIterator() = default;
238 IntervalIterator(ChannelType *pChannel, size_t index)
239 : mpChannel{ pChannel }, mIndex{ index }
240 {}
241
242 std::shared_ptr<IntervalType> operator *() const
243 {
244 if (!mpChannel || mIndex >= mpChannel->NIntervals())
245 return {};
246 return mpChannel->template GetInterval<IntervalType>(mIndex);
247 }
248
249 IntervalIterator &operator ++() { ++mIndex; return *this; }
250 IntervalIterator operator ++(int)
251 { auto copy{ *this }; operator ++(); return copy; }
252
253 IntervalIterator &operator --() { --mIndex; return *this; }
254 IntervalIterator operator --(int)
255 { auto copy{ *this }; operator --(); return copy; }
256
258 { return a.mpChannel == b.mpChannel && a.mIndex == b.mIndex; }
260 { return !(a == b); }
261
262 private:
263 ChannelType *mpChannel{};
264 size_t mIndex{};
265 };
266
268 template<typename IntervalType = Interval>
270 {
271 return { { this, 0 }, { this, NIntervals() } };
272 }
273
275 template<typename IntervalType = const Interval>
276 auto Intervals() const
277 -> std::enable_if_t<std::is_const_v<IntervalType>,
278 IteratorRange<IntervalIterator<IntervalType>>
279 >
280 {
281 return { { this, 0 }, { this, NIntervals() } };
282 }
283
288protected:
290
294 virtual ChannelGroup &DoGetChannelGroup() const = 0;
295
297 virtual ChannelGroup &ReallyDoGetChannelGroup() const;
298
299private:
300 int FindChannelIndex() const;
301};
302
303class CHANNEL_API ChannelGroup
304{
305public:
306 virtual ~ChannelGroup();
307
309 double GetStartTime() const;
311 double GetEndTime() const;
312
314 /*
315 @pre `IsLeader()`
316 */
317 void ShiftBy(double t) { MoveTo(GetStartTime() + t); }
318
320 /*
321 @pre `IsLeader()`
322 */
323 virtual void MoveTo(double o) = 0;
324
331
334 virtual size_t NChannels() const = 0;
335
337
343 template<typename ChannelType = Channel>
344 std::shared_ptr<ChannelType> GetChannel(size_t iChannel)
345 {
346 return
347 std::dynamic_pointer_cast<ChannelType>(DoGetChannel(iChannel));
348 }
349
353 template<typename ChannelType = const Channel>
354 auto GetChannel(size_t iChannel) const
355 -> std::enable_if_t<std::is_const_v<ChannelType>,
356 std::shared_ptr<ChannelType>>
357 {
358 return std::dynamic_pointer_cast<ChannelType>(
359 const_cast<ChannelGroup*>(this)->DoGetChannel(iChannel));
360 }
361
364 template<typename ChannelType>
366 : public ValueIterator<
367 std::shared_ptr<ChannelType>, std::bidirectional_iterator_tag
368 >
369 {
370 using GroupType = std::conditional_t<std::is_const_v<ChannelType>,
372 public:
373 ChannelIterator() = default;
374 ChannelIterator(GroupType *pGroup, size_t index)
375 : mpGroup{ pGroup }, mIndex{ index }
376 {}
377
378 std::shared_ptr<ChannelType> operator *() const
379 {
380 if (!mpGroup || mIndex >= mpGroup->NChannels())
381 return {};
382 return mpGroup->template GetChannel<ChannelType>(mIndex);
383 }
384
385 ChannelIterator &operator ++() { ++mIndex; return *this; }
386 ChannelIterator operator ++(int)
387 { auto copy{ *this }; operator ++(); return copy; }
388
389 ChannelIterator &operator --() { --mIndex; return *this; }
390 ChannelIterator operator --(int)
391 { auto copy{ *this }; operator --(); return copy; }
392
394 { return a.mpGroup == b.mpGroup && a.mIndex == b.mIndex; }
396 { return !(a == b); }
397
398 private:
399 GroupType *mpGroup{};
400 size_t mIndex{};
401 };
402
404
407 template<typename ChannelType = Channel>
409 {
410 assert(IsLeader());
411 return { { this, 0 }, { this, NChannels() } };
412 }
413
415
418 template<typename ChannelType = const Channel>
419 auto Channels() const
420 -> std::enable_if_t<std::is_const_v<ChannelType>,
422 >
423 {
424 assert(IsLeader());
425 return { { this, 0 }, { this, NChannels() } };
426 }
427
435
437 virtual size_t NIntervals() const = 0;
438
440
444 template<typename IntervalType = Interval>
445 std::shared_ptr<IntervalType> GetInterval(size_t iInterval)
446 {
447 return
448 std::dynamic_pointer_cast<IntervalType>(DoGetInterval(iInterval));
449 }
450
454 template<typename IntervalType = const Interval>
455 auto GetInterval(size_t iInterval) const
456 -> std::enable_if_t<std::is_const_v<IntervalType>,
457 std::shared_ptr<IntervalType>>
458 {
459 return std::dynamic_pointer_cast<IntervalType>(
460 const_cast<ChannelGroup*>(this)->DoGetInterval(iInterval));
461 }
462
465
469 template<typename IntervalType>
471 : public ValueIterator<
472 std::shared_ptr<IntervalType>, std::bidirectional_iterator_tag
473 >
474 {
475 using GroupType = std::conditional_t<std::is_const_v<IntervalType>,
477 public:
478 IntervalIterator() = default;
479 IntervalIterator(GroupType *pGroup, size_t index)
480 : mpGroup{ pGroup }, mIndex{ index }
481 {}
482
483 std::shared_ptr<IntervalType> operator *() const
484 {
485 if (!mpGroup || mIndex >= mpGroup->NIntervals())
486 return {};
487 return mpGroup->template GetInterval<IntervalType>(mIndex);
488 }
489
490 IntervalIterator &operator ++() { ++mIndex; return *this; }
491 IntervalIterator operator ++(int)
492 { auto copy{ *this }; operator ++(); return copy; }
493
494 IntervalIterator &operator --() { --mIndex; return *this; }
495 IntervalIterator operator --(int)
496 { auto copy{ *this }; operator --(); return copy; }
497
499 { return a.mpGroup == b.mpGroup && a.mIndex == b.mIndex; }
501 { return !(a == b); }
502
503 private:
504 GroupType *mpGroup{};
505 size_t mIndex{};
506 };
507
509 /*
510 @pre `IsLeader()`
511 */
512 template<typename IntervalType = Interval>
514 {
515 assert(IsLeader());
516 return { { this, 0 }, { this, NIntervals() } };
517 }
518
520 /*
521 @pre `IsLeader()`
522 */
523 template<typename IntervalType = const Interval>
524 auto Intervals() const
525 -> std::enable_if_t<std::is_const_v<IntervalType>,
526 IteratorRange<IntervalIterator<IntervalType>>
527 >
528 {
529 assert(IsLeader());
530 return { { this, 0 }, { this, NIntervals() } };
531 }
532
537 // TODO remove this which is only used in assertions
538 virtual bool IsLeader() const = 0;
539
541 struct ChannelGroupData;
544 >;
545
547 ChannelGroupData &GetGroupData();
550 const ChannelGroupData &GetGroupData() const;
551
553 ChannelGroupData *FindGroupData() { return mpGroupData.get(); }
555 const ChannelGroupData *FindGroupData() const { return mpGroupData.get(); }
556
558 void Init(const ChannelGroup &other);
559
561 void DestroyGroupData();
562
564 std::unique_ptr<ChannelGroupData> DetachGroupData();
565
567 void AssignGroupData(std::unique_ptr<ChannelGroupData> pGroupData);
568
569 // TODO wide wave tracks -- remove this
571 enum class LinkType : int {
572 None = 0,
573 // 1 - reserved for backward compatibility with projects generated by
574 // older versions of Audacity
575 Group = 2,
577 Aligned,
578 };
579
580 // Structure describing data common to channels of a group of tracks
581 // Should be deep-copyable (think twice before adding shared pointers!)
582 struct CHANNEL_API ChannelGroupData : Attachments {
584 wxString mName;
585 LinkType mLinkType{ LinkType::None };
586 std::optional<double> mProjectTempo;
587 bool mSelected{ false };
588 };
589
590protected:
592
595 virtual std::shared_ptr<Channel> DoGetChannel(size_t iChannel) = 0;
596
598
601 virtual std::shared_ptr<Interval> DoGetInterval(size_t iInterval) = 0;
602
603private:
604 // TODO wide wave tracks -- Make ChannelGroup itself the Site
605 std::unique_ptr<ChannelGroupData> mpGroupData;
606};
607
608inline size_t Channel::NIntervals() const
609{
610 return GetChannelGroup().NIntervals();
611}
612
613template<typename IntervalType>
614std::shared_ptr<IntervalType> Channel::GetInterval(size_t iInterval)
615{
616 return ReallyDoGetChannelGroup().GetInterval(iInterval)
617 ->template GetChannel<IntervalType>(ReallyGetChannelIndex());
618}
619
620template<typename IntervalType>
621auto Channel::GetInterval(size_t iInterval) const
622 -> std::enable_if_t<std::is_const_v<IntervalType>,
623 std::shared_ptr<IntervalType>>
624{
625 return ReallyDoGetChannelGroup().GetInterval(iInterval)
626 ->template GetChannel<IntervalType>(ReallyGetChannelIndex());
627}
628#endif
Utility ClientData::Site to register hooks into a host class that attach client data.
Vector operator*(const Vector &left, const Vector &right)
Definition: Matrix.cpp:153
bool operator==(const EffectReverbSettings &a, const EffectReverbSettings &b)
Definition: Reverb.cpp:632
bool operator!=(const WaveTrackLocation &a, const WaveTrackLocation &b)
IntervalIterator(ChannelType *pChannel, size_t index)
Definition: Channel.h:238
ChannelType * mpChannel
Definition: Channel.h:263
std::conditional_t< std::is_const_v< IntervalType >, const Channel, Channel > ChannelType
Definition: Channel.h:235
std::conditional_t< std::is_const_v< ChannelType >, const ChannelGroup, ChannelGroup > GroupType
Definition: Channel.h:371
ChannelIterator(GroupType *pGroup, size_t index)
Definition: Channel.h:374
std::conditional_t< std::is_const_v< IntervalType >, const ChannelGroup, ChannelGroup > GroupType
Definition: Channel.h:476
IntervalIterator(GroupType *pGroup, size_t index)
Definition: Channel.h:479
auto Channels() const -> std::enable_if_t< std::is_const_v< ChannelType >, IteratorRange< ChannelIterator< ChannelType > > >
Get range of channels with read-only access.
Definition: Channel.h:419
auto Intervals() const -> std::enable_if_t< std::is_const_v< IntervalType >, IteratorRange< IntervalIterator< IntervalType > > >
Get range of intervals with read-only access.
Definition: Channel.h:524
ClientData::Site< ChannelGroupData, ClientData::Cloneable<>, ClientData::DeepCopying > Attachments
Definition: Channel.h:544
virtual void MoveTo(double o)=0
Change start time to given time point.
ChannelGroupData * FindGroupData()
Do not make attachment site on demand if absent.
Definition: Channel.h:553
virtual bool IsLeader() const =0
LinkType
For two tracks describes the type of the linkage.
Definition: Channel.h:571
virtual size_t NIntervals() const =0
Report the number of intervals.
IteratorRange< ChannelIterator< ChannelType > > Channels()
Get range of channels with mutative access.
Definition: Channel.h:408
auto GetChannel(size_t iChannel) const -> std::enable_if_t< std::is_const_v< ChannelType >, std::shared_ptr< ChannelType > >
Definition: Channel.h:354
void ShiftBy(double t)
Change start time by given duration.
Definition: Channel.h:317
virtual std::shared_ptr< Interval > DoGetInterval(size_t iInterval)=0
Retrieve an interval.
auto GetInterval(size_t iInterval) const -> std::enable_if_t< std::is_const_v< IntervalType >, std::shared_ptr< IntervalType > >
Definition: Channel.h:455
IteratorRange< IntervalIterator< IntervalType > > Intervals()
Get range of intervals with mutative access.
Definition: Channel.h:513
std::unique_ptr< ChannelGroupData > mpGroupData
Definition: Channel.h:605
std::shared_ptr< IntervalType > GetInterval(size_t iInterval)
Retrieve an interval, cast to the given type.
Definition: Channel.h:445
const ChannelGroupData * FindGroupData() const
Do not make attachment site on demand if absent.
Definition: Channel.h:555
virtual size_t NChannels() const =0
Report the number of channels.
std::shared_ptr< ChannelType > GetChannel(size_t iChannel)
Retrieve a channel, cast to the given type.
Definition: Channel.h:344
virtual std::shared_ptr< Channel > DoGetChannel(size_t iChannel)=0
Retrieve a channel.
virtual ~ChannelGroup()
A start and an end time, and whatever else subclasses associate with them.
Definition: Channel.h:30
virtual ~ChannelGroupInterval()
double End() const
Definition: Channel.h:42
const double mEnd
Definition: Channel.h:45
double Start() const
Definition: Channel.h:41
ChannelGroupInterval(double start, double end)
Definition: Channel.h:33
auto Intervals() const -> std::enable_if_t< std::is_const_v< IntervalType >, IteratorRange< IntervalIterator< IntervalType > > >
Get range of intervals with read-only access.
Definition: Channel.h:276
size_t NIntervals() const
Report the number of intervals.
Definition: Channel.h:608
std::shared_ptr< IntervalType > GetInterval(size_t iInterval)
Retrieve an interval, cast to the given type.
Definition: Channel.h:614
virtual ~Channel()
IteratorRange< IntervalIterator< IntervalType > > Intervals()
Get range of intervals with mutative access.
Definition: Channel.h:269
virtual ChannelGroup & ReallyDoGetChannelGroup() const
This is temporary! It defaults to call the above.
Definition: Channel.cpp:82
ChannelGroup & GetChannelGroup()
Channel object's lifetime is assumed to be nested in its Track's.
Definition: Channel.cpp:71
virtual ChannelGroup & DoGetChannelGroup() const =0
Subclass must override.
size_t ReallyGetChannelIndex() const
Definition: Channel.cpp:52
The intersection of a Channel and a WideChannelGroupInterval.
Definition: Channel.h:49
virtual ~ChannelInterval()
Utility to register hooks into a host class that attach client data.
Definition: ClientData.h:228
std::conditional_t< std::is_const_v< IntervalType >, const WideChannelGroupInterval, WideChannelGroupInterval > GroupType
Definition: Channel.h:117
ChannelIterator(GroupType *pGroup, size_t index)
Definition: Channel.h:120
IteratorRange< ChannelIterator< IntervalType > > Channels()
Get range of ChannelInterval objects with mutative access.
Definition: Channel.h:151
auto GetChannel(size_t iChannel) const -> std::enable_if_t< std::is_const_v< IntervalType >, std::shared_ptr< IntervalType > >
Definition: Channel.h:100
const size_t mNChannels
Definition: Channel.h:174
~WideChannelGroupInterval() override
auto Channels() const -> std::enable_if_t< std::is_const_v< IntervalType >, IteratorRange< ChannelIterator< IntervalType > > >
Get range of channels with read-only access.
Definition: Channel.h:158
std::shared_ptr< IntervalType > GetChannel(size_t iChannel)
Retrieve a channel, cast to the given type.
Definition: Channel.h:90
virtual std::shared_ptr< ChannelInterval > DoGetChannel(size_t iChannel)=0
Retrieve a channel.
size_t NChannels() const
Report the number of channels.
Definition: Channel.h:80
ChannelType
Mutually exclusive channel classifications.
@ DeepCopying
point to new sub-objects; these must define a Clone() member; won't compile for std::weak_ptr
MenuRegistry::GroupItem< MenuRegistry::Traits > Group
Definition: MenuHelper.h:11
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Definition: PackedArray.h:159
void copy(const T *src, T *dst, int32_t n)
Definition: VectorOps.h:40
STL namespace.
std::optional< double > mProjectTempo
Definition: Channel.h:586
A convenient base class defining abstract virtual Clone() for a given kind of pointer.
Definition: ClientData.h:49
A convenience for use with range-for.
Definition: MemoryX.h:277
A convenience for defining iterators that return rvalue types, so that they cooperate correctly with ...
Definition: MemoryX.h:263