22class SnapGrid :
public QObject
26 bool snapAdaptive READ snapAdaptive WRITE setSnapAdaptive NOTIFY
29 bool snapToGrid READ snapToGrid WRITE setSnapToGrid NOTIFY snapToGridChanged)
31 bool snapToEvents READ snapToEvents WRITE setSnapToEvents NOTIFY
34 bool keepOffset READ keepOffset WRITE setKeepOffset NOTIFY keepOffsetChanged)
36 bool sixteenthsVisible READ sixteenthsVisible WRITE setSixteenthsVisible
37 NOTIFY sixteenthsVisibleChanged)
39 bool beatsVisible READ beatsVisible WRITE setBeatsVisible NOTIFY
42 zrythm::dsp::notes::NoteLength snapNoteLength READ snapNoteLength WRITE
43 setSnapNoteLength NOTIFY snapNoteLengthChanged)
45 zrythm::dsp::notes::NoteType snapNoteType READ snapNoteType WRITE
46 setSnapNoteType NOTIFY snapNoteTypeChanged)
48 NoteLengthType lengthType READ lengthType WRITE setLengthType NOTIFY
50 Q_PROPERTY (QString snapString READ snapString NOTIFY snapChanged)
52 QML_EXTENDED_NAMESPACE (zrythm::dsp::notes)
69 using SnapEventCallback =
70 std::function<std::vector<double> (
double start_ticks,
double end_ticks)>;
71 using LastObjectLengthProvider = std::function<double ()>;
74 const TempoMap &tempo_map,
75 dsp::notes::NoteLength default_note_length,
76 LastObjectLengthProvider last_object_length_provider,
77 QObject * parent =
nullptr);
80 bool snapAdaptive ()
const {
return snap_adaptive_; }
81 void setSnapAdaptive (
bool adaptive);
83 bool snapToGrid ()
const {
return snap_to_grid_; }
84 void setSnapToGrid (
bool snap);
86 bool snapToEvents ()
const {
return snap_to_events_; }
87 void setSnapToEvents (
bool snap);
89 bool keepOffset ()
const {
return snap_to_grid_keep_offset_; }
90 void setKeepOffset (
bool keep);
92 bool sixteenthsVisible ()
const {
return sixteenths_visible_; }
93 void setSixteenthsVisible (
bool visible);
95 bool beatsVisible ()
const {
return beats_visible_; }
96 void setBeatsVisible (
bool visible);
98 dsp::notes::NoteLength snapNoteLength ()
const {
return snap_note_length_; }
99 void setSnapNoteLength (dsp::notes::NoteLength length);
101 dsp::notes::NoteType snapNoteType ()
const {
return snap_note_type_; }
102 void setSnapNoteType (dsp::notes::NoteType type);
107 QString snapString ()
const;
110 Q_INVOKABLE
double snapWithoutStartTicks (
double ticks)
112 return snap (units::ticks (ticks)).in (units::ticks);
114 Q_INVOKABLE
double snapWithStartTicks (
double ticks,
double startTicks)
116 return snap (units::ticks (ticks), units::ticks (startTicks))
119 Q_INVOKABLE
double nextSnapPoint (
double ticks)
const;
120 Q_INVOKABLE
double prevSnapPoint (
double ticks)
const;
121 Q_INVOKABLE
double closestSnapPoint (
double ticks)
const;
122 Q_INVOKABLE
double snapTicks (int64_t ticks)
const;
123 Q_INVOKABLE
double defaultTicks (int64_t ticks)
const;
131 units::precise_tick_t
snap (
132 units::precise_tick_t ticks,
133 std::optional<units::precise_tick_t> start_ticks = std::nullopt)
const;
136 void set_event_callback (SnapEventCallback callback);
137 void set_last_object_length_callback (LastObjectLengthProvider callback)
139 last_object_length_provider_ = callback;
141 void clear_callbacks ();
143 static constexpr int get_ticks_from_length_and_type (
144 dsp::notes::NoteLength length,
145 dsp::notes::NoteType type,
149 assert (ticks_per_beat > 0);
150 assert (ticks_per_bar > 0);
155 case dsp::notes::NoteLength::Bar:
156 ticks = ticks_per_bar;
158 case dsp::notes::NoteLength::Beat:
159 ticks = ticks_per_beat;
161 case dsp::notes::NoteLength::Note_2_1:
164 case dsp::notes::NoteLength::Note_1_1:
167 case dsp::notes::NoteLength::Note_1_2:
170 case dsp::notes::NoteLength::Note_1_4:
173 case dsp::notes::NoteLength::Note_1_8:
176 case dsp::notes::NoteLength::Note_1_16:
179 case dsp::notes::NoteLength::Note_1_32:
182 case dsp::notes::NoteLength::Note_1_64:
185 case dsp::notes::NoteLength::Note_1_128:
192 case dsp::notes::NoteType::Normal:
194 case dsp::notes::NoteType::Dotted:
196 assert (ticks % 2 == 0);
199 case dsp::notes::NoteType::Triplet:
201 assert (ticks % 3 == 0);
209 static QString stringize_length_and_type (
210 dsp::notes::NoteLength note_length,
211 dsp::notes::NoteType note_type);
214 void snapAdaptiveChanged ();
215 void snapToGridChanged ();
216 void snapToEventsChanged ();
217 void keepOffsetChanged ();
218 void sixteenthsVisibleChanged ();
219 void beatsVisibleChanged ();
220 void snapNoteLengthChanged ();
221 void snapNoteTypeChanged ();
222 void lengthTypeChanged ();
226 static constexpr auto kSnapNoteLengthKey =
"snapNoteLength"sv;
227 static constexpr auto kSnapNoteTypeKey =
"snapNoteType"sv;
228 static constexpr auto kSnapAdaptiveKey =
"snapAdaptive"sv;
229 static constexpr auto kLengthTypeKey =
"lengthType"sv;
230 static constexpr auto kSnapToGridKey =
"snapToGrid"sv;
231 static constexpr auto kKeepOffsetKey =
"keepOffset"sv;
232 static constexpr auto kSnapToEventsKey =
"snapToEvents"sv;
233 friend void to_json (nlohmann::json &j,
const SnapGrid &p);
234 friend void from_json (
const nlohmann::json &j, SnapGrid &p);
236 bool get_prev_or_next_snap_point (
239 bool get_prev_point)
const;
241 get_event_snap_points (
double start_ticks,
double end_ticks)
const;
249 constexpr dsp::notes::NoteLength get_effective_note_length ()
const
251 return snap_adaptive_
252 ? (sixteenths_visible_
253 ? dsp::notes::NoteLength::Note_1_16
254 : (beats_visible_ ? dsp::notes::NoteLength::Beat
255 : dsp::notes::NoteLength::Bar))
260 bool snap_adaptive_ =
false;
261 dsp::notes::NoteLength snap_note_length_{ dsp::notes::NoteLength::Note_1_4 };
262 dsp::notes::NoteType snap_note_type_{ dsp::notes::NoteType::Normal };
265 bool snap_to_grid_ =
true;
272 bool snap_to_grid_keep_offset_ =
false;
280 bool snap_to_events_ =
false;
283 bool sixteenths_visible_ =
false;
284 bool beats_visible_ =
false;
290 dsp::notes::NoteLength default_note_length_;
292 const TempoMap &tempo_map_;
293 std::optional<SnapEventCallback> event_callback_;
294 LastObjectLengthProvider last_object_length_provider_;