25 Q_PROPERTY (
int pitch READ pitch WRITE setPitch NOTIFY pitchChanged)
27 int velocity READ velocity WRITE setVelocity NOTIFY velocityChanged)
29 int midiChannel READ midiChannel WRITE setMidiChannel NOTIFY
37 QObject * parent =
nullptr);
38 Q_DISABLE_COPY_MOVE (MidiNote)
39 ~MidiNote ()
override;
43 return qobject_cast<dsp::ContentPosition *> (ArrangerObject::position ());
48 enum class Notation : std::uint8_t
58 int pitch ()
const {
return static_cast<int> (pitch_); }
59 void setPitch (
int ipitch)
61 ipitch = std::clamp (ipitch, 0, 127);
62 const auto pitch =
static_cast<midi_byte_t> (ipitch);
66 Q_EMIT pitchChanged (ipitch);
74 setPitch (
static_cast<int> (pitch_) + delta);
76 Q_SIGNAL
void pitchChanged (
int ipitch);
77 Q_INVOKABLE QString pitchAsRichText ()
const
82 int velocity ()
const {
return static_cast<int> (velocity_); }
83 void setVelocity (
int ivelocity)
85 ivelocity = std::clamp (ivelocity, 0, 127);
86 const auto velocity =
static_cast<midi_byte_t> (ivelocity);
87 if (velocity_ != velocity)
90 Q_EMIT velocityChanged (ivelocity);
93 Q_SIGNAL
void velocityChanged (
int ivelocity);
95 int midiChannel ()
const {
return static_cast<int> (midi_channel_); }
96 void setMidiChannel (
int ichannel)
98 ichannel = std::clamp (ichannel, 0, 15);
99 const auto channel =
static_cast<uint8_t
> (ichannel);
100 if (midi_channel_ != channel)
102 midi_channel_ = channel;
103 Q_EMIT midiChannelChanged (ichannel);
106 Q_SIGNAL
void midiChannelChanged (
int ichannel);
122 template <RangeOfM
idiNotePo
inters Range>
125 auto it = std::ranges::min_element (range, [] (
const auto &a,
const auto &b) {
126 return a->position ()->ticks () < b->position ()->ticks ();
128 return (it != range.end ()) ? *it :
nullptr;
134 template <RangeOfM
idiNotePo
inters Range>
139 const auto range_to_test = range | std::views::reverse;
140 auto it = std::ranges::max_element (
141 range_to_test, [] (
const auto &a,
const auto &b) {
142 return (a->position ()->ticks () + a->length ()->ticks ())
143 < (b->position ()->ticks () + b->length ()->ticks ());
145 return (it != range_to_test.end ()) ? *it :
nullptr;
151 template <RangeOfM
idiNotePo
inters Range>
153 -> std::optional<std::pair<midi_byte_t, midi_byte_t>>
155 auto [min_it, max_it] =
156 std::ranges::minmax_element (range, [] (
const auto &a,
const auto &b) {
157 return a->pitch () < b->pitch ();
159 if (min_it == range.end () || max_it == range.end ())
161 return std::make_pair ((*min_it)->pitch (), (*max_it)->pitch ());
164 friend void init_from (
169 static constexpr auto kVelocityKey =
"velocity"sv;
170 static constexpr auto kPitchKey =
"pitch"sv;
171 static constexpr auto kChannelKey =
"midiChannel"sv;
172 friend void to_json (nlohmann::json &j,
const MidiNote ¬e);
173 friend void from_json (
const nlohmann::json &j,
MidiNote ¬e);
177 std::uint8_t velocity_{ DEFAULT_VELOCITY };
180 std::uint8_t pitch_{ 60 };
183 std::uint8_t midi_channel_{ 0 };
185 BOOST_DESCRIBE_CLASS (
190 (velocity_, pitch_, midi_channel_))
A Position whose ticks are content-space (clip-local) ticks.
ArrangerObject(Type type, const dsp::TempoMapWrapper &tempo_map_wrapper, ArrangerObjectFeatures features, QObject *parent=nullptr) noexcept
Construct a new ArrangerObject.