Etterna 0.74.4
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 GetBeatInternal(GetBeatStarts& start,
552 GetBeatArgs& args,
553 unsigned int max_segment) const;
554 auto GetElapsedTimeInternal(GetBeatStarts& start,
555 float beat,
556 unsigned int max_segment) const -> float;
557 void GetBeatAndBPSFromElapsedTime(GetBeatArgs& args) const;
558
559 [[nodiscard]] auto GetBeatFromElapsedTime(float elapsed_time) const
560 -> float // shortcut for places that care only about the beat
561 {
562 GetBeatArgs args;
563 args.elapsed_time = elapsed_time;
564 GetBeatAndBPSFromElapsedTime(args);
565 return args.beat;
566 }
567
568 [[nodiscard]] auto GetElapsedTimeFromBeat(float fBeat) const -> float;
569
570 void GetBeatAndBPSFromElapsedTimeNoOffset(GetBeatArgs& args) const;
571
572 [[nodiscard]] auto GetBeatFromElapsedTimeNoOffset(float elapsed_time) const
573 -> float // shortcut for places that care only about the beat
574 {
575 GetBeatArgs args;
576 args.elapsed_time = elapsed_time;
577 GetBeatAndBPSFromElapsedTimeNoOffset(args);
578 return args.beat;
579 }
580
581 [[nodiscard]] auto GetElapsedTimeFromBeatNoOffset(float fBeat) const
582 -> float;
583 [[nodiscard]] auto GetDisplayedBeat(float fBeat) const -> float;
584
585 [[nodiscard]] auto HasBpmChanges() const -> bool
586 {
587 return GetTimingSegments(SEGMENT_BPM).size() > 1;
588 }
589
590 [[nodiscard]] auto HasStops() const -> bool
591 {
592 return !GetTimingSegments(SEGMENT_STOP).empty();
593 }
594 [[nodiscard]] auto HasDelays() const -> bool
595 {
596 return !GetTimingSegments(SEGMENT_DELAY).empty();
597 }
598 [[nodiscard]] auto HasWarps() const -> bool
599 {
600 return !GetTimingSegments(SEGMENT_WARP).empty();
601 }
602 [[nodiscard]] auto HasFakes() const -> bool
603 {
604 return !GetTimingSegments(SEGMENT_FAKE).empty();
605 }
606
607 [[nodiscard]] auto HasSpeedChanges() const -> bool;
608 [[nodiscard]] auto HasScrollChanges() const -> bool;
609
615 auto operator==(const TimingData& other) const -> bool
616 {
617 FOREACH_ENUM(TimingSegmentType, tst)
618 {
619 const auto& us = m_avpTimingSegments[tst];
620 const auto& them = other.m_avpTimingSegments[tst];
621
622 // optimization: check std::vector sizes before contents
623 if (us.size() != them.size()) {
624 return false;
625 }
626
627 for (unsigned i = 0; i < us.size(); ++i) {
628 /* UGLY: since TimingSegment's comparison compares base data,
629 * and the derived versions only compare derived data, we must
630 * manually call each. */
631 if (!(*us[i]).TimingSegment::operator==(*them[i])) {
632 return false;
633 }
634 if (!(*us[i]).operator==(*them[i])) {
635 return false;
636 }
637 }
638 }
639
641 return true;
642 }
643
649 auto operator!=(const TimingData& other) const -> bool
650 {
651 return !operator==(other);
652 }
653
654 void ScaleRegion(float fScale = 1,
655 int iStartRow = 0,
656 int iEndRow = MAX_NOTE_ROW,
657 bool bAdjustBPM = false);
658 void InsertRows(int iStartRow, int iRowsToAdd);
659 void DeleteRows(int iStartRow, int iRowsToDelete);
660
661 void SortSegments(TimingSegmentType tst);
662
663 [[nodiscard]] auto GetTimingSegments(TimingSegmentType tst) const
664 -> const std::vector<TimingSegment*>&
665 {
666 return const_cast<TimingData*>(this)->GetTimingSegments(tst);
667 }
668 auto GetTimingSegments(TimingSegmentType tst)
669 -> std::vector<TimingSegment*>&
670 {
671 return m_avpTimingSegments[tst];
672 }
673
680 void TidyUpData(bool allowEmpty);
681
682 // Lua
683 void PushSelf(lua_State* L);
684
690 std::string m_sFile;
691
694
695 // XXX: this breaks encapsulation. get rid of it ASAP
696 [[nodiscard]] auto ToVectorString(TimingSegmentType tst, int dec = 6) const
697 -> std::vector<std::string>;
698
699 /* Wow it's almost like this should have been done a decade ago.
700 Essentially what's happening here is the results of getelapsedtimeat(row)
701 are pre-calculated and stored in a std::vector that can be simply subset
702 rather than values being recalculated millions of times per file. This only
703 applies however to files for which there can be made an assumption of
704 sequential execution I don't actually know for sure if any of negative
705 bpms/stops/warps do this, or if mod maps have the power to fundamentally
706 change timing data. If they don't then I suppose all of these checks aren't
707 needed at all :/. Not my responsibility to investigate, though. - Mina.*/
708
709 std::vector<float> ElapsedTimesAtAllRows;
710 std::vector<float> ElapsedTimesAtNonEmptyRows;
711 auto BuildAndGetEtaner(const std::vector<int>& nerv)
712 -> const std::vector<float>&;
713 auto BuildAndGetEtar(int lastrow) -> const std::vector<float>&;
714 void SetElapsedTimesAtAllRows(std::vector<float>& etar)
715 {
716 ElapsedTimesAtAllRows = etar;
717 }
718
719 [[nodiscard]] auto GetElapsedTimesAtAllRows() const -> std::vector<float>
720 {
721 return ElapsedTimesAtAllRows;
722 }
723 void UnsetElapsedTimesAtAllRows()
724 {
725 ElapsedTimesAtAllRows.clear();
726 ElapsedTimesAtAllRows.shrink_to_fit();
727 };
728 void UnsetEtaner()
729 {
730 ElapsedTimesAtNonEmptyRows.clear();
731 ElapsedTimesAtNonEmptyRows.shrink_to_fit();
732 }
733
734 [[nodiscard]] auto WhereUAtBro(float beat) const -> float;
735 auto WhereUAtBro(float beat) -> float;
736 [[nodiscard]] auto WhereUAtBroNoOffset(float beat) const -> float;
737 auto WhereUAtBroNoOffset(float beat) -> float;
738 auto WhereUAtBro(int row) -> float;
739
740 auto ConvertReplayNoteRowsToTimestamps(const std::vector<int>& nrv,
741 float rate) -> std::vector<float>;
742
743 protected:
744 // don't call this directly; use the derived-type overloads.
745 void AddSegment(const TimingSegment* seg);
746
747 // All of the following vectors must be sorted before gameplay.
748 std::vector<TimingSegment*> m_avpTimingSegments[NUM_TimingSegmentType];
749};
750
751#undef COMPARE
752
753#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:690
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:693
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:615
auto operator!=(const TimingData &other) const -> bool
Compare two sets of timing data to see if they are not equal.
Definition TimingData.h:649
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