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
35 MidiNote (
const dsp::TempoMap &tempo_map, QObject * parent =
nullptr);
36 Q_DISABLE_COPY_MOVE (MidiNote)
37 ~MidiNote ()
override;
41 enum class Notation : std::uint8_t
51 int pitch ()
const {
return static_cast<int> (pitch_); }
52 void setPitch (
int ipitch)
54 ipitch = std::clamp (ipitch, 0, 127);
55 const auto pitch =
static_cast<midi_byte_t> (ipitch);
59 Q_EMIT pitchChanged (ipitch);
67 setPitch (
static_cast<int> (pitch_) + delta);
69 Q_SIGNAL
void pitchChanged (
int ipitch);
70 Q_INVOKABLE QString pitchAsRichText ()
const
75 int velocity ()
const {
return static_cast<int> (velocity_); }
76 void setVelocity (
int ivelocity)
78 ivelocity = std::clamp (ivelocity, 0, 127);
79 const auto velocity =
static_cast<midi_byte_t> (ivelocity);
80 if (velocity_ != velocity)
83 Q_EMIT velocityChanged (ivelocity);
86 Q_SIGNAL
void velocityChanged (
int ivelocity);
88 int midiChannel ()
const {
return static_cast<int> (midi_channel_); }
89 void setMidiChannel (
int ichannel)
91 ichannel = std::clamp (ichannel, 0, 15);
92 const auto channel =
static_cast<uint8_t
> (ichannel);
93 if (midi_channel_ != channel)
95 midi_channel_ = channel;
96 Q_EMIT midiChannelChanged (ichannel);
99 Q_SIGNAL
void midiChannelChanged (
int ichannel);
115 template <RangeOfM
idiNotePo
inters Range>
118 auto it = std::ranges::min_element (range, [] (
const auto &a,
const auto &b) {
119 return a->position ()->ticks () < b->position ()->ticks ();
121 return (it != range.end ()) ? *it :
nullptr;
127 template <RangeOfM
idiNotePo
inters Range>
132 const auto range_to_test = range | std::views::reverse;
133 auto it = std::ranges::max_element (
134 range_to_test, [] (
const auto &a,
const auto &b) {
135 return a->bounds ()->get_end_position_samples (
false)
136 < b->bounds ()->get_end_position_samples (
false);
138 return (it != range_to_test.end ()) ? *it :
nullptr;
144 template <RangeOfM
idiNotePo
inters Range>
146 -> std::optional<std::pair<midi_byte_t, midi_byte_t>>
148 auto [min_it, max_it] =
149 std::ranges::minmax_element (range, [] (
const auto &a,
const auto &b) {
150 return a->pitch () < b->pitch ();
152 if (min_it == range.end () || max_it == range.end ())
154 return std::make_pair ((*min_it)->pitch (), (*max_it)->pitch ());
157 friend void init_from (
162 static constexpr auto kVelocityKey =
"velocity"sv;
163 static constexpr auto kPitchKey =
"pitch"sv;
164 static constexpr auto kChannelKey =
"midiChannel"sv;
165 friend void to_json (nlohmann::json &j,
const MidiNote ¬e);
166 friend void from_json (
const nlohmann::json &j,
MidiNote ¬e);
170 std::uint8_t velocity_{ DEFAULT_VELOCITY };
173 std::uint8_t pitch_{ 60 };
176 std::uint8_t midi_channel_{ 0 };
178 BOOST_DESCRIBE_CLASS (
183 (velocity_, pitch_, midi_channel_))