Skip to content

Commit 1471f05

Browse files
committed
Handle changing the quantization while stepping. Refactored saving, and added failsafe mechanisms to prevent data loss.
1 parent 353ef17 commit 1471f05

File tree

4 files changed

+82
-57
lines changed

4 files changed

+82
-57
lines changed

src/Core/Utils.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,25 @@ inline color32 ToColor32(float r, float g, float b, float a)
326326
return u32;
327327
}
328328

329+
static int gcd(int a, int b)
330+
{
331+
if (a == 0)
332+
{
333+
return b;
334+
}
335+
if (b == 0)
336+
{
337+
return a;
338+
}
339+
if (a > b)
340+
{
341+
return gcd(a - b, b);
342+
}
343+
else
344+
{
345+
return gcd(a, b - a);
346+
}
347+
}
329348
}; // namespace Vortex
330349

331350
#undef TT

src/Editor/Editing.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,26 @@ void onChanges(int changes)
327327
// ================================================================================================
328328
// EditingImpl :: member functions.
329329

330+
static int gcd(int a, int b)
331+
{
332+
if (a == 0)
333+
{
334+
return b;
335+
}
336+
if (b == 0)
337+
{
338+
return a;
339+
}
340+
if (a > b)
341+
{
342+
return gcd(a - b, b);
343+
}
344+
else
345+
{
346+
return gcd(a, b - a);
347+
}
348+
}
349+
330350
void finishNotePlacement(int col)
331351
{
332352
auto& pnote = myPlacingNotes[col];
@@ -348,6 +368,14 @@ void finishNotePlacement(int col)
348368
}
349369
}
350370

371+
if (note.quant > 0 && note.quant <= 192)
372+
{
373+
note.quant = min(192u, note.quant * gView->getSnapQuant() / gcd(note.quant, gView->getSnapQuant()));
374+
}
375+
else
376+
{
377+
note.quant = 192;
378+
}
351379
NoteEdit edit;
352380
edit.add.append(note);
353381
gNotes->modify(edit, false);

src/Simfile/LoadSm.cpp

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <numeric>
66

77
#include <Core/StringUtils.h>
8+
#include <Core/Utils.h>
89

910
#include <System/Debug.h>
1011
#include <System/File.h>
@@ -376,26 +377,6 @@ struct ReadNoteData
376377
Vector<int> quants;
377378
};
378379

379-
static int gcd(int a, int b)
380-
{
381-
if (a == 0)
382-
{
383-
return b;
384-
}
385-
if (b == 0)
386-
{
387-
return a;
388-
}
389-
if (a > b)
390-
{
391-
return gcd(a - b, b);
392-
}
393-
else
394-
{
395-
return gcd(a, b - a);
396-
}
397-
}
398-
399380
static void ReadNoteRow(ReadNoteData& data, int row, char* p, int quantization)
400381
{
401382
for(int col = 0; col < data.numCols; ++col, ++p)
@@ -426,7 +407,7 @@ static void ReadNoteRow(ReadNoteData& data, int row, char* p, int quantization)
426407
// Make sure we set the note to its largest quantization to avoid data loss
427408
if (data.quants[col] > 0 && hold->quant > 0)
428409
{
429-
hold->quant = quantization * hold->quant / gcd(quantization, hold->quant);
410+
hold->quant = min(192u, quantization * hold->quant / gcd(quantization, hold->quant));
430411
}
431412
else // There was some error, so always play safe and use 192
432413
{

src/Simfile/SaveSm.cpp

Lines changed: 33 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include <Core/StringUtils.h>
2+
#include <Core/Utils.h>
23

34
#include <System/File.h>
45

@@ -450,24 +451,21 @@ static const char* GetDifficultyString(Difficulty difficulty)
450451
return "Edit";
451452
}
452453

453-
static int gcd(int a, int b)
454+
static inline bool TestSectionCompression(const char* section, int width, int quant)
454455
{
455-
if (a == 0)
456-
{
457-
return b;
458-
}
459-
if (b == 0)
460-
{
461-
return a;
462-
}
463-
if (a > b)
464-
{
465-
return gcd(a - b, b);
466-
}
467-
else
456+
String zeroline(width, '0');
457+
float mod = (float)ROWS_PER_NOTE_SECTION / quant;
458+
for (int j = 0; j < ROWS_PER_NOTE_SECTION; ++j)
468459
{
469-
return gcd(a, b - a);
460+
float rem = round(fmod(j, mod));
461+
// Check all the compressed rows and make sure they are empty
462+
if (rem > 0 && rem < static_cast<int>(mod)
463+
&& memcmp(section + j * width, zeroline.str(), width))
464+
{
465+
return false;
466+
}
470467
}
468+
return quant >= MIN_SECTIONS_PER_MEASURE;
471469
}
472470

473471
static bool GetSectionCompression(const char* section, int width, std::list<uint> quantVec, int& count, int& pitch)
@@ -505,35 +503,34 @@ static bool GetSectionCompression(const char* section, int width, std::list<uint
505503
// Determines the best compression for the given section.
506504
// Maybe lcm is the best factor, so just keep that.
507505
count = lcm;
508-
String zeroline(width, '0');
509-
510-
//The factor list is small, just check them all by hand
511-
for (int i = lcm / 2; i >= 2; i--)
506+
bool valid = false;
507+
//The factor list is small, just check them all by hand, but only up to 96 at most since there won't be factors otherwise
508+
for (int i = 4; i <= lcm / 2; i++)
512509
{
513510
// Skip anything that isn't a lcm factor
514511
if (lcm % i > 0) continue;
515512

516-
bool valid = true;
517-
float mod = (float) ROWS_PER_NOTE_SECTION / i;
518-
for (int j = 0; valid && j < ROWS_PER_NOTE_SECTION; ++j)
519-
{
520-
float rem = round(fmod(j, mod));
521-
// Check all the compressed rows and make sure they are empty
522-
if (rem > 0 && rem < static_cast<int>(mod)
523-
&& memcmp(section + j * width, zeroline.str(), width))
524-
{
525-
valid = false;
526-
break;
527-
}
528-
}
529-
530-
// The first (largest) match is always the best
531-
if (valid && i >= MIN_SECTIONS_PER_MEASURE)
513+
// The first (smallest) match is always the best
514+
if (TestSectionCompression(section, width, i))
532515
{
516+
valid = true;
533517
count = i;
534518
break;
535519
}
536520
}
521+
522+
// If no factor was found, double-check we won't have any data loss from our lcm guess
523+
// Why not check all factors? Saving files would be several times slower otherwise
524+
if (!valid)
525+
{
526+
valid = TestSectionCompression(section, width, lcm);
527+
}
528+
if (!valid)
529+
{
530+
// Okay, we WOULD have had data loss, so set the rows to 192 and error
531+
error = true;
532+
count = ROWS_PER_NOTE_SECTION;
533+
}
537534
}
538535
// Is our factor a standard snap? If so, use it.
539536
// If not, save the measure as 192nds for SM5 Editor compatibility.
@@ -641,7 +638,7 @@ static void WriteSections(ExportData& data)
641638
quantVec.unique();
642639
if (GetSectionCompression(m, numCols, quantVec, count, pitch))
643640
{
644-
HudError("Bug: zero or negative quantization recorded in chart in measure starting at row %d, quantization %d", startRow, it->quant);
641+
HudError("Bug: invalid quantization recorded in chart in measure starting at row %d", startRow);
645642
}
646643
quantVec.clear();
647644
if (ROWS_PER_NOTE_SECTION % count != 0)

0 commit comments

Comments
 (0)