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
|