Etterna 0.75.1
Loading...
Searching...
No Matches
TimingData.h
1#ifndef TIMING_DATA_H
2#define TIMING_DATA_H
3
4#include "NoteTypes.h"
5#include "TimingSegments.h"
6#include "Core/Services/Locator.hpp"
7#include <cfloat> // max float
8
9struct lua_State;
10
12#define COMPARE(x) \
13 if (this->x != other.x) \
14 return false;
15
16/* convenience functions to handle static casting */
17template<class T>
18auto
19ToDerived(const TimingSegment* t, TimingSegmentType /*tst*/) -> T
20{
21 return static_cast<T>(t);
22}
23
24#define TimingSegmentToXWithName(Seg, SegName, SegType) \
25 inline const Seg* To##SegName(const TimingSegment* t) \
26 { \
27 return static_cast<const Seg*>(t); \
28 } \
29 inline Seg* To##SegName(TimingSegment* t) { return static_cast<Seg*>(t); }
30
31#define TimingSegmentToX(Seg, SegType) \
32 TimingSegmentToXWithName(Seg##Segment, Seg, SEGMENT_##SegType)
33
34/* ToBPM(TimingSegment*), ToTimeSignature(TimingSegment*), etc. */
35TimingSegmentToX(BPM, BPM);
36TimingSegmentToX(Stop, STOP);
37TimingSegmentToX(Delay, DELAY);
38TimingSegmentToX(TimeSignature, TIME_SIG);
39TimingSegmentToX(Warp, WARP);
40TimingSegmentToX(Label, LABEL);
41TimingSegmentToX(Tickcount, TICKCOUNT);
42TimingSegmentToX(Combo, COMBO);
43TimingSegmentToX(Speed, SPEED);
44TimingSegmentToX(Scroll, SCROLL);
45TimingSegmentToX(Fake, FAKE);
46
47#undef TimingSegmentToXWithName
48#undef TimingSegmentToX
49
54{
55 public:
59 explicit TimingData(float fOffset = 0.F);
61
62 void Copy(const TimingData& other);
63 void Clear();
64
65 TimingData(const TimingData& cpy) { Copy(cpy); }
66 auto operator=(const TimingData& cpy) -> TimingData&
67 {
68 Copy(cpy);
69 return *this;
70 }
71 auto operator=(TimingData&& other) noexcept -> TimingData&
72 {
73 std::swap(m_beat_start_lookup, other.m_beat_start_lookup);
74 std::swap(m_time_start_lookup, other.m_time_start_lookup);
75 std::swap(m_avpTimingSegments, other.m_avpTimingSegments);
76 std::swap(m_sFile, other.m_sFile);
78 std::swap(ElapsedTimesAtAllRows, other.ElapsedTimesAtAllRows);
79 std::swap(ElapsedTimesAtNonEmptyRows, other.ElapsedTimesAtNonEmptyRows);
80
81 return *this;
82 }
83
84 // GetBeatArgs, GetBeatStarts, m_beat_start_lookup, m_time_start_lookup,
85 // PrepareLookup, and ReleaseLookup form a system for speeding up finding
86 // the current beat and bps from the time, or finding the time from the
87 // current beat.
88 // The lookup tables contain indices for the beat and time finding
89 // functions to start at so they don't have to walk through all the timing
90 // segments.
91 // PrepareLookup should be called before gameplay starts, so that the lookup
92 // tables are populated. ReleaseLookup should be called after gameplay
93 // finishes so that memory isn't wasted.
94 // -Kyz
96 {
97 float elapsed_time{ 0 };
98 float beat{ 0 };
99 float bps_out{ 0 };
100 float warp_dest_out{ 0 };
101 int warp_begin_out{ -1 };
102 bool freeze_out{ false };
103 bool delay_out{ false };
104 GetBeatArgs() = default;
105 };
107 {
108 unsigned int bpm{ 0 };
109 unsigned int warp{ 0 };
110 unsigned int stop{ 0 };
111 unsigned int delay{ 0 };
112 int last_row{ 0 };
113 float last_time{ 0 };
114 float warp_destination{ 0 };
115 bool is_warping{ false };
116 GetBeatStarts() = default;
117 };
118 // map can't be used for the lookup table because its find or *_bound
119 // functions would return the wrong entry.
120 // In a map<int, int> with three entries, [-1]= 3, [6]= 1, [8]= 2,
121 // lower_bound(0) and upper_bound(0) both returned the entry at [6]= 1.
122 // So the lookup table is a std::vector of entries and FindEntryInLookup
123 // does a binary search. -Kyz
125 {
126 float first;
127 GetBeatStarts second;
128 lookup_item_t(float f, GetBeatStarts& s)
129 : first(f)
130 , second(s)
131 {
132 }
133 };
134 using beat_start_lookup_t = std::vector<lookup_item_t>;
135 beat_start_lookup_t m_beat_start_lookup;
136 beat_start_lookup_t m_time_start_lookup;
137
138 void PrepareLookup();
139 void ReleaseLookup();
140
141 [[nodiscard]] auto GetSegmentIndexAtRow(TimingSegmentType tst,
142 int row) const -> int;
143
144 [[nodiscard]] auto GetSegmentIndexAtBeat(TimingSegmentType tst,
145 float beat) const -> int
146 {
147 return GetSegmentIndexAtRow(tst, BeatToNoteRow(beat));
148 }
149
150 [[nodiscard]] auto GetNextSegmentBeatAtRow(TimingSegmentType tst,
151 int row) const -> float;
152
153 [[nodiscard]] auto GetNextSegmentBeatAtBeat(TimingSegmentType tst,
154 float beat) const -> float
155 {
156 return GetNextSegmentBeatAtRow(tst, BeatToNoteRow(beat));
157 }
158
159 [[nodiscard]] auto GetPreviousSegmentBeatAtRow(TimingSegmentType tst,
160 int row) const -> float;
161
162 [[nodiscard]] auto GetPreviousSegmentBeatAtBeat(TimingSegmentType tst,
163 float beat) const -> float
164 {
165 return GetPreviousSegmentBeatAtRow(tst, BeatToNoteRow(beat));
166 }
167
168 [[nodiscard]] auto empty() const -> bool;
169
170 void CopyRange(int start_row,
171 int end_row,
172 TimingSegmentType copy_type,
173 int dest_row,
174 TimingData& dest) const;
175 void ShiftRange(int start_row,
176 int end_row,
177 TimingSegmentType shift_type,
178 int shift_amount);
179 void ClearRange(int start_row, int end_row, TimingSegmentType clear_type);
189 void GetActualBPM(float& fMinBPMOut,
190 float& fMaxBPMOut,
191 float highest = FLT_MAX) const;
192
199 [[nodiscard]] auto GetSegmentAtRow(int iNoteRow,
200 TimingSegmentType tst) const
201 -> const TimingSegment*;
202 auto GetSegmentAtRow(int iNoteRow, TimingSegmentType tst) -> TimingSegment*;
203
210 [[nodiscard]] auto GetSegmentAtBeat(float fBeat,
211 TimingSegmentType tst) const
212 -> const TimingSegment*
213 {
214 return GetSegmentAtRow(BeatToNoteRow(fBeat), tst);
215 }
216
217#define DefineSegmentWithName(Seg, SegName, SegType) \
218 const Seg* Get##Seg##AtRow(int iNoteRow) const \
219 { \
220 const TimingSegment* t = GetSegmentAtRow(iNoteRow, SegType); \
221 return To##SegName(t); \
222 } \
223 Seg* Get##Seg##AtRow(int iNoteRow) \
224 { \
225 return const_cast<Seg*>( \
226 ((const TimingData*)this)->Get##Seg##AtRow(iNoteRow)); \
227 } \
228 const Seg* Get##Seg##AtBeat(float fBeat) const \
229 { \
230 return Get##Seg##AtRow(BeatToNoteRow(fBeat)); \
231 } \
232 Seg* Get##Seg##AtBeat(float fBeat) \
233 { \
234 return const_cast<Seg*>( \
235 ((const TimingData*)this)->Get##Seg##AtBeat(fBeat)); \
236 } \
237 void AddSegment(const Seg& seg) { AddSegment(&seg); }
238
239// "XXX: this comment (and quote mark) exists so nano won't
240// display the rest of this file as one giant string
241
242// (TimeSignature,TIME_SIG) -> (TimeSignatureSegment,SEGMENT_TIME_SIG)
243#define DefineSegment(Seg, SegType) \
244 DefineSegmentWithName(Seg##Segment, Seg, SEGMENT_##SegType)
245
246 DefineSegment(BPM, BPM);
247 DefineSegment(Stop, STOP);
248 DefineSegment(Delay, DELAY);
249 DefineSegment(Warp, WARP);
250 DefineSegment(Label, LABEL);
251 DefineSegment(Tickcount, TICKCOUNT);
252 DefineSegment(Combo, COMBO);
253 DefineSegment(Speed, SPEED);
254 DefineSegment(Scroll, SCROLL);
255 DefineSegment(Fake, FAKE);
256 DefineSegment(TimeSignature, TIME_SIG);
257
258#undef DefineSegmentWithName
259#undef DefineSegment
260
261 /* convenience aliases (Set functions are deprecated) */
262 [[nodiscard]] auto GetBPMAtRow(int iNoteRow) const -> float
263 {
264 return GetBPMSegmentAtRow(iNoteRow)->GetBPM();
265 }
266
267 [[nodiscard]] auto GetBPMAtBeat(float fBeat) const -> float
268 {
269 return GetBPMAtRow(BeatToNoteRow(fBeat));
270 }
271 void SetBPMAtRow(int iNoteRow, float fBPM)
272 {
273 AddSegment(BPMSegment(iNoteRow, fBPM));
274 }
275 void SetBPMAtBeat(float fBeat, float fBPM)
276 {
277 SetBPMAtRow(BeatToNoteRow(fBeat), fBPM);
278 }
279
280 [[nodiscard]] auto GetStopAtRow(int iNoteRow) const -> float
281 {
282 return GetStopSegmentAtRow(iNoteRow)->GetPause();
283 }
284
285 [[nodiscard]] auto GetStopAtBeat(float fBeat) const -> float
286 {
287 return GetStopAtRow(BeatToNoteRow(fBeat));
288 }
289 void SetStopAtRow(int iNoteRow, float fSeconds)
290 {
291 AddSegment(StopSegment(iNoteRow, fSeconds));
292 }
293 void SetStopAtBeat(float fBeat, float fSeconds)
294 {
295 SetStopAtRow(BeatToNoteRow(fBeat), fSeconds);
296 }
297
298 [[nodiscard]] auto GetDelayAtRow(int iNoteRow) const -> float
299 {
300 return GetDelaySegmentAtRow(iNoteRow)->GetPause();
301 }
302
303 [[nodiscard]] auto GetDelayAtBeat(float fBeat) const -> float
304 {
305 return GetDelayAtRow(BeatToNoteRow(fBeat));
306 }
307 void SetDelayAtRow(int iNoteRow, float fSeconds)
308 {
309 AddSegment(DelaySegment(iNoteRow, fSeconds));
310 }
311 void SetDelayAtBeat(float fBeat, float fSeconds)
312 {
313 SetDelayAtRow(BeatToNoteRow(fBeat), fSeconds);
314 }
315
316 void SetTimeSignatureAtRow(int iNoteRow, int iNum, int iDen)
317 {
318 AddSegment(TimeSignatureSegment(iNoteRow, iNum, iDen));
319 }
320
321 void SetTimeSignatureAtBeat(float fBeat, int iNum, int iDen)
322 {
323 SetTimeSignatureAtRow(BeatToNoteRow(fBeat), iNum, iDen);
324 }
325
326 [[nodiscard]] auto GetWarpAtRow(int iNoteRow) const -> float
327 {
328 return GetWarpSegmentAtRow(iNoteRow)->GetLength();
329 }
330
331 [[nodiscard]] auto GetWarpAtBeat(float fBeat) const -> float
332 {
333 return GetWarpAtRow(BeatToNoteRow(fBeat));
334 }
335 /* Note: fLength is in beats, not rows */
336 void SetWarpAtRow(int iRow, float fLength)
337 {
338 AddSegment(WarpSegment(iRow, fLength));
339 }
340 void SetWarpAtBeat(float fBeat, float fLength)
341 {
342 AddSegment(WarpSegment(BeatToNoteRow(fBeat), fLength));
343 }
344
345 [[nodiscard]] auto GetTickcountAtRow(int iNoteRow) const -> int
346 {
347 return GetTickcountSegmentAtRow(iNoteRow)->GetTicks();
348 }
349
350 [[nodiscard]] auto GetTickcountAtBeat(float fBeat) const -> int
351 {
352 return GetTickcountAtRow(BeatToNoteRow(fBeat));
353 }
354 void SetTickcountAtRow(int iNoteRow, int iTicks)
355 {
356 AddSegment(TickcountSegment(iNoteRow, iTicks));
357 }
358 void SetTickcountAtBeat(float fBeat, int iTicks)
359 {
360 SetTickcountAtRow(BeatToNoteRow(fBeat), iTicks);
361 }
362
363 [[nodiscard]] auto GetComboAtRow(int iNoteRow) const -> int
364 {
365 return GetComboSegmentAtRow(iNoteRow)->GetCombo();
366 }
367
368 [[nodiscard]] auto GetComboAtBeat(float fBeat) const -> int
369 {
370 return GetComboAtRow(BeatToNoteRow(fBeat));
371 }
372
373 [[nodiscard]] auto GetMissComboAtRow(int iNoteRow) const -> int
374 {
375 return GetComboSegmentAtRow(iNoteRow)->GetMissCombo();
376 }
377
378 [[nodiscard]] auto GetMissComboAtBeat(float fBeat) const -> int
379 {
380 return GetMissComboAtRow(BeatToNoteRow(fBeat));
381 }
382
383 [[nodiscard]] auto GetLabelAtRow(int iNoteRow) const -> const std::string&
384 {
385 return GetLabelSegmentAtRow(iNoteRow)->GetLabel();
386 }
387
388 [[nodiscard]] auto GetLabelAtBeat(float fBeat) const -> const std::string&
389 {
390 return GetLabelAtRow(BeatToNoteRow(fBeat));
391 }
392 void SetLabelAtRow(int iNoteRow, const std::string& sLabel)
393 {
394 AddSegment(LabelSegment(iNoteRow, sLabel));
395 }
396 void SetLabelAtBeat(float fBeat, const std::string& sLabel)
397 {
398 SetLabelAtRow(BeatToNoteRow(fBeat), sLabel);
399 }
400
401 [[nodiscard]] auto DoesLabelExist(const std::string& sLabel) const -> bool;
402
403 [[nodiscard]] auto GetSpeedPercentAtRow(int iNoteRow) const -> float
404 {
405 return GetSpeedSegmentAtRow(iNoteRow)->GetRatio();
406 }
407
408 [[nodiscard]] auto GetSpeedPercentAtBeat(float fBeat) const -> float
409 {
410 return GetSpeedPercentAtRow(BeatToNoteRow(fBeat));
411 }
412
413 [[nodiscard]] auto GetSpeedWaitAtRow(int iNoteRow) const -> float
414 {
415 return GetSpeedSegmentAtRow(iNoteRow)->GetDelay();
416 }
417
418 [[nodiscard]] auto GetSpeedWaitAtBeat(float fBeat) const -> float
419 {
420 return GetSpeedWaitAtRow(BeatToNoteRow(fBeat));
421 }
422
423 // XXX: is there any point to having specific unit types?
424 [[nodiscard]] auto GetSpeedModeAtRow(int iNoteRow) const
426 {
427 return GetSpeedSegmentAtRow(iNoteRow)->GetUnit();
428 }
429
430 [[nodiscard]] auto GetSpeedModeAtBeat(float fBeat) const
432 {
433 return GetSpeedModeAtRow(BeatToNoteRow(fBeat));
434 }
435
436 void SetSpeedAtRow(int iNoteRow,
437 float fPercent,
438 float fWait,
440 {
441 AddSegment(SpeedSegment(iNoteRow, fPercent, fWait, unit));
442 }
443
444 void SetSpeedAtBeat(float fBeat,
445 float fPercent,
446 float fWait,
448 {
449 SetSpeedAtRow(BeatToNoteRow(fBeat), fPercent, fWait, unit);
450 }
451
452 void SetSpeedPercentAtRow(int iNoteRow, float fPercent)
453 {
454 const SpeedSegment* seg = GetSpeedSegmentAtRow(iNoteRow);
455 SetSpeedAtRow(iNoteRow, fPercent, seg->GetDelay(), seg->GetUnit());
456 }
457
458 void SetSpeedWaitAtRow(int iNoteRow, float fWait)
459 {
460 const SpeedSegment* seg = GetSpeedSegmentAtRow(iNoteRow);
461 SetSpeedAtRow(iNoteRow, seg->GetRatio(), fWait, seg->GetUnit());
462 }
463
464 void SetSpeedModeAtRow(int iNoteRow, SpeedSegment::BaseUnit unit)
465 {
466 const SpeedSegment* seg = GetSpeedSegmentAtRow(iNoteRow);
467 SetSpeedAtRow(iNoteRow, seg->GetRatio(), seg->GetDelay(), unit);
468 }
469
470 void SetSpeedPercentAtBeat(float fBeat, float fPercent)
471 {
472 SetSpeedPercentAtRow(BeatToNoteRow(fBeat), fPercent);
473 }
474 void SetSpeedWaitAtBeat(float fBeat, float fWait)
475 {
476 SetSpeedWaitAtRow(BeatToNoteRow(fBeat), fWait);
477 }
478 void SetSpeedModeAtBeat(float fBeat, SpeedSegment::BaseUnit unit)
479 {
480 SetSpeedModeAtRow(BeatToNoteRow(fBeat), unit);
481 }
482
483 [[nodiscard]] auto GetDisplayedSpeedPercent(float fBeat,
484 float fMusicSeconds) const
485 -> float;
486
487 [[nodiscard]] auto GetScrollAtRow(int iNoteRow) const -> float
488 {
489 return GetScrollSegmentAtRow(iNoteRow)->GetRatio();
490 }
491
492 [[nodiscard]] auto GetScrollAtBeat(float fBeat) const -> float
493 {
494 return GetScrollAtRow(BeatToNoteRow(fBeat));
495 }
496
497 void SetScrollAtRow(int iNoteRow, float fPercent)
498 {
499 AddSegment(ScrollSegment(iNoteRow, fPercent));
500 }
501 void SetScrollAtBeat(float fBeat, float fPercent)
502 {
503 SetScrollAtRow(BeatToNoteRow(fBeat), fPercent);
504 }
505
506 [[nodiscard]] auto GetFakeAtRow(int iRow) const -> float
507 {
508 return GetFakeSegmentAtRow(iRow)->GetLength();
509 }
510
511 [[nodiscard]] auto GetFakeAtBeat(float fBeat) const -> float
512 {
513 return GetFakeAtRow(BeatToNoteRow(fBeat));
514 }
515
516 [[nodiscard]] auto IsWarpAtRow(int iRow) const -> bool;
517
518 [[nodiscard]] auto IsWarpAtBeat(float fBeat) const -> bool
519 {
520 return IsWarpAtRow(BeatToNoteRow(fBeat));
521 }
522
523 [[nodiscard]] auto IsFakeAtRow(int iRow) const -> bool;
524
525 [[nodiscard]] auto IsFakeAtBeat(float fBeat) const -> bool
526 {
527 return IsFakeAtRow(BeatToNoteRow(fBeat));
528 }
529
534 [[nodiscard]] auto IsJudgableAtRow(int row) const -> bool
535 {
536 return !IsWarpAtRow(row) && !IsFakeAtRow(row);
537 }
538
539 [[nodiscard]] auto IsJudgableAtBeat(float beat) const -> bool
540 {
541 return IsJudgableAtRow(BeatToNoteRow(beat));
542 }
543
544 void MultiplyBPMInBeatRange(int iStartIndex, int iEndIndex, float fFactor);
545
546 void NoteRowToMeasureAndBeat(int iNoteRow,
547 int& iMeasureIndexOut,
548 int& iBeatIndexOut,
549 int& iRowsRemainder) const;
550
551 void GetBeatAndBPSFromElapsedTime(GetBeatArgs& args) const;
552
553 [[nodiscard]] auto GetBeatFromElapsedTime(float elapsed_time) const
554 -> float // shortcut for places that care only about the beat
555 {
556 GetBeatArgs args;
557 args.elapsed_time = elapsed_time;
558 GetBeatAndBPSFromElapsedTime(args);
559 return args.beat;
560 }
561
562 void GetBeatAndBPSFromElapsedTimeNoOffset(GetBeatArgs& args) const;
563
564 [[nodiscard]] auto GetBeatFromElapsedTimeNoOffset(float elapsed_time) const
565 -> float // shortcut for places that care only about the beat
566 {
567 GetBeatArgs args;
568 args.elapsed_time = elapsed_time;
569 GetBeatAndBPSFromElapsedTimeNoOffset(args);
570 return args.beat;
571 }
572
573 [[nodiscard]] auto GetDisplayedBeat(float fBeat) const -> float;
574
575 [[nodiscard]] auto HasBpmChanges() const -> bool
576 {
577 return GetTimingSegments(SEGMENT_BPM).size() > 1;
578 }
579
580 [[nodiscard]] auto HasStops() const -> bool
581 {
582 return !GetTimingSegments(SEGMENT_STOP).empty();
583 }
584 [[nodiscard]] auto HasDelays() const -> bool
585 {
586 return !GetTimingSegments(SEGMENT_DELAY).empty();
587 }
588 [[nodiscard]] auto HasWarps() const -> bool
589 {
590 return !GetTimingSegments(SEGMENT_WARP).empty();
591 }
592 [[nodiscard]] auto HasFakes() const -> bool
593 {
594 return !GetTimingSegments(SEGMENT_FAKE).empty();
595 }
596
597 [[nodiscard]] auto HasSpeedChanges() const -> bool;
598 [[nodiscard]] auto HasScrollChanges() const -> bool;
599
605 auto operator==(const TimingData& other) const -> bool
606 {
607 FOREACH_ENUM(TimingSegmentType, tst)
608 {
609 const auto& us = m_avpTimingSegments[tst];
610 const auto& them = other.m_avpTimingSegments[tst];
611
612 // optimization: check std::vector sizes before contents
613 if (us.size() != them.size()) {
614 return false;
615 }
616
617 for (unsigned i = 0; i < us.size(); ++i) {
618 /* UGLY: since TimingSegment's comparison compares base data,
619 * and the derived versions only compare derived data, we must
620 * manually call each. */
621 if (!(*us[i]).TimingSegment::operator==(*them[i])) {
622 return false;
623 }
624 if (!(*us[i]).operator==(*them[i])) {
625 return false;
626 }
627 }
628 }
629
631 return true;
632 }
633
639 auto operator!=(const TimingData& other) const -> bool
640 {
641 return !operator==(other);
642 }
643
644 void ScaleRegion(float fScale = 1,
645 int iStartRow = 0,
646 int iEndRow = MAX_NOTE_ROW,
647 bool bAdjustBPM = false);
648 void InsertRows(int iStartRow, int iRowsToAdd);
649 void DeleteRows(int iStartRow, int iRowsToDelete);
650
651 void SortSegments(TimingSegmentType tst);
652
653 [[nodiscard]] auto GetTimingSegments(TimingSegmentType tst) const
654 -> const std::vector<TimingSegment*>&
655 {
656 return const_cast<TimingData*>(this)->GetTimingSegments(tst);
657 }
658 auto GetTimingSegments(TimingSegmentType tst)
659 -> std::vector<TimingSegment*>&
660 {
661 return m_avpTimingSegments[tst];
662 }
663
670 void TidyUpData(bool allowEmpty);
671
672 // Lua
673 void PushSelf(lua_State* L);
674
680 std::string m_sFile;
681
684
685 // XXX: this breaks encapsulation. get rid of it ASAP
686 [[nodiscard]] auto ToVectorString(TimingSegmentType tst, int dec = 6) const
687 -> std::vector<std::string>;
688
689 /* Wow it's almost like this should have been done a decade ago.
690 Essentially what's happening here is the results of getelapsedtimeat(row)
691 are pre-calculated and stored in a std::vector that can be simply subset
692 rather than values being recalculated millions of times per file. This only
693 applies however to files for which there can be made an assumption of
694 sequential execution I don't actually know for sure if any of negative
695 bpms/stops/warps do this, or if mod maps have the power to fundamentally
696 change timing data. If they don't then I suppose all of these checks aren't
697 needed at all :/. Not my responsibility to investigate, though. - Mina.*/
698
699 std::vector<float> ElapsedTimesAtAllRows;
700 std::vector<float> ElapsedTimesAtNonEmptyRows;
701 auto BuildAndGetEtaner(const std::vector<int>& nerv)
702 -> const std::vector<float>&;
703 auto BuildAndGetEtar(int lastrow) -> const std::vector<float>&;
704 void SetElapsedTimesAtAllRows(std::vector<float>& etar)
705 {
706 ElapsedTimesAtAllRows = etar;
707 }
708
709 [[nodiscard]] auto GetElapsedTimesAtAllRows() const -> std::vector<float>
710 {
711 return ElapsedTimesAtAllRows;
712 }
713 void UnsetElapsedTimesAtAllRows()
714 {
715 ElapsedTimesAtAllRows.clear();
716 ElapsedTimesAtAllRows.shrink_to_fit();
717 };
718 void UnsetEtaner()
719 {
720 ElapsedTimesAtNonEmptyRows.clear();
721 ElapsedTimesAtNonEmptyRows.shrink_to_fit();
722 }
723
724 [[nodiscard]] auto GetTimeFromBeatFast(float beat) const -> float;
725 [[nodiscard]] auto GetTimeFromBeatFastNoOffset(float beat) const -> float;
726 [[nodiscard]] auto GetTimeFromRowFast(int row) const -> float;
727 [[nodiscard]] auto GetTimeFromRowFastNoOffset(int row) const -> float;
728
729 auto ConvertReplayNoteRowsToTimestamps(const std::vector<int>& nrv,
730 float rate) const
731 -> std::vector<float>;
732
733 protected:
734 // don't call this directly; use the derived-type overloads.
735 void AddSegment(const TimingSegment* seg);
736
737 [[nodiscard]] auto GetElapsedTimeFromBeat(float fBeat) const -> float;
738 [[nodiscard]] auto GetElapsedTimeFromBeatNoOffset(float fBeat) const
739 -> float;
740
741 // All of the following vectors must be sorted before gameplay.
742 std::vector<TimingSegment*> m_avpTimingSegments[NUM_TimingSegmentType];
743
744 private:
745 void GetBeatInternal(GetBeatStarts& start,
746 GetBeatArgs& args,
747 unsigned int max_segment) const;
748 auto GetElapsedTimeInternal(GetBeatStarts& start,
749 float beat,
750 unsigned int max_segment) const -> float;
751};
752
753#undef COMPARE
754
755#endif
Holds data for translating beats<->seconds.
Definition TimingData.h:54
std::string m_sFile
The file of the song/steps that use this TimingData.
Definition TimingData.h:680
auto GetSegmentAtBeat(float fBeat, TimingSegmentType tst) const -> const TimingSegment *
Retrieve the TimingSegment at the given beat.
Definition TimingData.h:210
void GetActualBPM(float &fMinBPMOut, float &fMaxBPMOut, float highest=FLT_MAX) const
Gets the actual BPM of the song, while respecting a limit.
Definition TimingData.cpp:298
float m_fBeat0OffsetInSeconds
The initial offset of a song.
Definition TimingData.h:683
auto GetSegmentAtRow(int iNoteRow, TimingSegmentType tst) const -> const TimingSegment *
Retrieve the TimingSegment at the specified row.
Definition TimingData.cpp:484
auto IsJudgableAtRow(int row) const -> bool
Determine if this notes on this row can be judged.
Definition TimingData.h:534
auto operator==(const TimingData &other) const -> bool
Compare two sets of timing data to see if they are equal.
Definition TimingData.h:605
auto operator!=(const TimingData &other) const -> bool
Compare two sets of timing data to see if they are not equal.
Definition TimingData.h:639
void TidyUpData(bool allowEmpty)
Tidy up the timing data, e.g. provide default BPMs, labels, tickcounts.
Definition TimingData.cpp:1122
Identifies when a song changes its BPM.
Definition TimingSegments.h:556
Identifies when a song has a delay, or pump style stop.
Definition TimingSegments.h:970
Identifies when a chart is entering a different section.
Definition TimingSegments.h:487
Identifies when the chart scroll changes.
Definition TimingSegments.h:834
Identifies when the arrow scroll changes.
Definition TimingSegments.h:733
BaseUnit
The type of unit used for segment scaling.
Definition TimingSegments.h:757
Identifies when a song has a stop, DDR/ITG style.
Definition TimingSegments.h:902
Identifies when a chart is to have a different tickcount value for hold notes.
Definition TimingSegments.h:335
Identifies when a song changes its time signature.
Definition TimingSegments.h:632
Definition TimingData.h:96
Definition TimingData.h:107
Definition TimingData.h:125
The base timing segment for make glorious benefit wolfman XXX: this should be an abstract class.
Definition TimingSegments.h:55
Identifies when a song needs to warp to a new beat.
Definition TimingSegments.h:243