File: NoteTrack.h

package info (click to toggle)
audacity 3.7.3%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 125,252 kB
  • sloc: cpp: 358,238; ansic: 75,458; lisp: 7,761; sh: 3,410; python: 1,503; xml: 1,385; perl: 854; makefile: 122
file content (251 lines) | stat: -rw-r--r-- 7,897 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
/**********************************************************************

  Audacity: A Digital Audio Editor

  NoteTrack.h

  Dominic Mazzoni

**********************************************************************/

#ifndef __AUDACITY_NOTETRACK__
#define __AUDACITY_NOTETRACK__

#include <utility>
#include "AudioIOSequences.h"
#include "CRTPBase.h"
#include "Prefs.h"
#include "PlayableTrack.h"

#if defined(USE_MIDI)

// define this switch to play MIDI during redisplay to sonify run times
// Note that if SONIFY is defined, the default MIDI device will be opened
// and may block normal MIDI playback.
//#define SONIFY 1

#ifdef SONIFY

#define SONFNS(name) \
   void Begin ## name(); \
   void End ## name();

SONFNS(NoteBackground)
SONFNS(NoteForeground)
SONFNS(Measures)
SONFNS(Serialize)
SONFNS(Unserialize)
SONFNS(ModifyState)
SONFNS(AutoSave)

#undef SONFNS

#endif

class wxDC;
class wxRect;

class Alg_seq;   // from "allegro.h"

using QuantizedTimeAndBeat = std::pair< double, double >;

class NoteTrack;
class StretchHandle;
class TimeWarper;

struct NOTE_TRACK_API NoteTrackAttachment;
CRTP_BASE(NoteTrackAttachmentBase, struct,
   ClientData::Cloneable<NoteTrackAttachment, ClientData::UniquePtr>);
struct NoteTrackAttachment : NoteTrackAttachmentBase
{
   ~NoteTrackAttachment() override;
   //! Default implementation does nothing
   virtual void WriteXML(XMLWriter &xmlFile) const;
   //! Return whether the attribute was used; default returns false
   virtual bool HandleAttribute(const Attribute &attribute);
};

using NoteTrackAttachments = ClientData::Site<
   NoteTrack,
   NoteTrackAttachment,
   ClientData::DeepCopying
>;

class NOTE_TRACK_API NoteTrack final
   : public UniqueChannelTrack<PlayableTrack>
   , public OtherPlayableSequence
   , public NoteTrackAttachments
{
public:
   using Attachments = NoteTrackAttachments;
   static EnumSetting<bool> AllegroStyleSetting;

   // Construct and also build all attachments
   static NoteTrack *New(AudacityProject &project);

   NoteTrack();
   //! Copy construction hasn't been necessary yet
   NoteTrack(const NoteTrack &orig) = delete;
   NoteTrack(const NoteTrack &orig, ProtectedCreationArg &&) = delete;
   virtual ~NoteTrack();

   using Holder = std::shared_ptr<NoteTrack>;

private:
   Track::Holder Clone(bool backup) const override;

public:
   void MoveTo(double origin) override { mOrigin = origin; }
   void ShiftBy(double t0, double delta) override;

   Alg_seq &GetSeq() const;

   void WarpAndTransposeNotes(double t0, double t1,
                              const TimeWarper &warper, double semitones);

   void SetSequence(std::unique_ptr<Alg_seq> &&seq);
   void PrintSequence();

   Alg_seq *MakeExportableSeq(std::unique_ptr<Alg_seq> &cleanup) const;
   bool ExportMIDI(const wxString &f) const;
   bool ExportAllegro(const wxString &f) const;

   // High-level editing
   Track::Holder Cut(double t0, double t1) override;
   Track::Holder Copy(double t0, double t1, bool forClipboard = true)
      const override;
   bool Trim (double t0, double t1) /* not override */;
   void Clear(double t0, double t1) override;
   void Paste(double t, const Track &src) override;
   void
   Silence(double t0, double t1, ProgressReporter reportProgress = {}) override;
   void InsertSilence(double t, double len) override;
   bool Shift(double t) /* not override */;

   float GetVelocity() const {
      return mVelocity.load(std::memory_order_relaxed); }
   void SetVelocity(float velocity);

   QuantizedTimeAndBeat NearestBeatTime( double time ) const;
   bool StretchRegion
      ( QuantizedTimeAndBeat t0, QuantizedTimeAndBeat t1, double newDur );

   bool HandleXMLTag(const std::string_view& tag, const AttributesList& attrs) override;
   XMLTagHandler *HandleXMLChild(const std::string_view& tag) override;
   void WriteXML(XMLWriter &xmlFile) const override;

   // channels are numbered as integers 0-15, visible channels
   // (mVisibleChannels) is a bit set. Channels are displayed as
   // integers 1-16.

   // Allegro's data structure does not restrict channels to 16.
   // Since there is not way to select more than 16 channels,
   // map all channel numbers mod 16. This will have no effect
   // on MIDI files, but it will allow users to at least select
   // all channels on non-MIDI event sequence data.
#define NUM_CHANNELS 16
   // Bitmask with all NUM_CHANNELS bits set
#define ALL_CHANNELS (1 << NUM_CHANNELS) - 1
#define CHANNEL_BIT(c) (1 << (c % NUM_CHANNELS))
   unsigned GetVisibleChannels() const {
      return mVisibleChannels.load(std::memory_order_relaxed);
   }
   void SetVisibleChannels(unsigned value) {
      mVisibleChannels.store(value, std::memory_order_relaxed);
   }
   bool IsVisibleChan(int c) const {
      return (GetVisibleChannels() & CHANNEL_BIT(c)) != 0;
   }
   void SetVisibleChan(int c) {
      mVisibleChannels.fetch_or(CHANNEL_BIT(c), std::memory_order_relaxed); }
   void ClearVisibleChan(int c) {
      mVisibleChannels.fetch_and(~CHANNEL_BIT(c), std::memory_order_relaxed); }
   void ToggleVisibleChan(int c) {
      mVisibleChannels.fetch_xor(CHANNEL_BIT(c), std::memory_order_relaxed); }
   // Solos the given channel.  If it's the only channel visible, all channels
   // are enabled; otherwise, it is set to the only visible channel.
   void SoloVisibleChan(int c) {
      auto visibleChannels = 0u;
      if (GetVisibleChannels() == CHANNEL_BIT(c))
         visibleChannels = ALL_CHANNELS;
      else
         visibleChannels = CHANNEL_BIT(c);
      mVisibleChannels.store(visibleChannels, std::memory_order_relaxed);
   }

   const TypeInfo &GetTypeInfo() const override;
   static const TypeInfo &ClassTypeInfo();

   Track::Holder PasteInto(AudacityProject &project, TrackList &list)
      const override;

   size_t NIntervals() const override;

   struct Interval final : WideChannelGroupInterval {
      explicit Interval(const NoteTrack &track);
      ~Interval() override;
      std::shared_ptr<ChannelInterval> DoGetChannel(size_t iChannel) override;
      double Start() const override;
      double End() const override;
      size_t NChannels() const override;
   private:
      //! @invariant not null
      const std::shared_ptr<const NoteTrack> mpTrack;
   };

private:
   std::shared_ptr<WideChannelGroupInterval> DoGetInterval(size_t iInterval)
      override;

   void DoSetVelocity(float velocity);

   void AddToDuration( double delta );

   // These are mutable to allow NoteTrack to switch details of representation
   // in logically const methods
   // At most one of the two pointers is not null at any time.
   // Both are null in a newly constructed NoteTrack.
   mutable std::unique_ptr<Alg_seq> mSeq;
   mutable std::unique_ptr<char[]> mSerializationBuffer;
   mutable long mSerializationLength;

   //! Atomic because it may be read by worker threads in playback
   std::atomic<float> mVelocity{ 0.0f }; // velocity offset

   //! A bit set; atomic because it may be read by worker threads in playback
   std::atomic<unsigned> mVisibleChannels{ ALL_CHANNELS };
   double mOrigin{ 0.0 };
};

extern NOTE_TRACK_API StringSetting MIDIPlaybackDevice;
extern NOTE_TRACK_API StringSetting MIDIRecordingDevice;
extern NOTE_TRACK_API IntSetting MIDISynthLatency_ms;

ENUMERATE_TRACK_TYPE(NoteTrack);

#endif // USE_MIDI

#ifndef SONIFY
// no-ops:
#define SonifyBeginSonification()
#define SonifyEndSonification()
#define SonifyBeginNoteBackground()
#define SonifyEndNoteBackground()
#define SonifyBeginNoteForeground()
#define SonifyEndNoteForeground()
#define SonifyBeginMeasures()
#define SonifyEndMeasures()
#define SonifyBeginSerialize()
#define SonifyEndSerialize()
#define SonifyBeginUnserialize()
#define SonifyEndUnserialize()
#define SonifyBeginAutoSave()
#define SonifyEndAutoSave()
#define SonifyBeginModifyState()
#define SonifyEndModifyState()
#endif


NOTE_TRACK_API wxString GetMIDIDeviceInfo();

#endif