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);
156 case dsp::notes::NoteLength::Bar:
157 ticks = ticks_per_bar;
159 case dsp::notes::NoteLength::Beat:
160 ticks = ticks_per_beat;
162 case dsp::notes::NoteLength::Note_2_1:
165 case dsp::notes::NoteLength::Note_1_1:
168 case dsp::notes::NoteLength::Note_1_2:
171 case dsp::notes::NoteLength::Note_1_4:
174 case dsp::notes::NoteLength::Note_1_8:
177 case dsp::notes::NoteLength::Note_1_16:
180 case dsp::notes::NoteLength::Note_1_32:
183 case dsp::notes::NoteLength::Note_1_64:
186 case dsp::notes::NoteLength::Note_1_128:
193 case dsp::notes::NoteType::Normal:
195 case dsp::notes::NoteType::Dotted:
197 assert (ticks % 2 == 0);
200 case dsp::notes::NoteType::Triplet:
202 assert (ticks % 3 == 0);
210 static QString stringize_length_and_type (
211 dsp::notes::NoteLength note_length,
212 dsp::notes::NoteType note_type);
215 void snapAdaptiveChanged ();
216 void snapToGridChanged ();
217 void snapToEventsChanged ();
218 void keepOffsetChanged ();
219 void sixteenthsVisibleChanged ();
220 void beatsVisibleChanged ();
221 void snapNoteLengthChanged ();
222 void snapNoteTypeChanged ();
223 void lengthTypeChanged ();
227 static constexpr auto kSnapNoteLengthKey =
"snapNoteLength"sv;
228 static constexpr auto kSnapNoteTypeKey =
"snapNoteType"sv;
229 static constexpr auto kSnapAdaptiveKey =
"snapAdaptive"sv;
230 static constexpr auto kLengthTypeKey =
"lengthType"sv;
231 static constexpr auto kSnapToGridKey =
"snapToGrid"sv;
232 static constexpr auto kKeepOffsetKey =
"keepOffset"sv;
233 static constexpr auto kSnapToEventsKey =
"snapToEvents"sv;
234 friend void to_json (nlohmann::json &j,
const SnapGrid &p);
235 friend void from_json (
const nlohmann::json &j, SnapGrid &p);
237 bool get_prev_or_next_snap_point (
240 bool get_prev_point)
const;
242 get_event_snap_points (
double start_ticks,
double end_ticks)
const;
250 constexpr dsp::notes::NoteLength get_effective_note_length ()
const
252 return snap_adaptive_
253 ? (sixteenths_visible_
254 ? dsp::notes::NoteLength::Note_1_16
255 : (beats_visible_ ? dsp::notes::NoteLength::Beat
256 : dsp::notes::NoteLength::Bar))
261 bool snap_adaptive_ =
false;
262 dsp::notes::NoteLength snap_note_length_{ dsp::notes::NoteLength::Note_1_4 };
263 dsp::notes::NoteType snap_note_type_{ dsp::notes::NoteType::Normal };
266 bool snap_to_grid_ =
true;
273 bool snap_to_grid_keep_offset_ =
false;
281 bool snap_to_events_ =
false;
284 bool sixteenths_visible_ =
false;
285 bool beats_visible_ =
false;
291 dsp::notes::NoteLength default_note_length_;
293 const TempoMap &tempo_map_;
294 std::optional<SnapEventCallback> event_callback_;
295 LastObjectLengthProvider last_object_length_provider_;