Eliminating the 9ms bias

March ‘23 update

Hey, ITG folks! There’s been some exciting recent development in this area, namely Telperion’s nine-or-null unbiasing utility and some positive discussion of practicality in the ITC server. I’ve trimmed & edited this document to reflect recent developments like ITGMania and the unbiasing tool.


The Club Fantastic wiki describes the 4-panel dance game community’s longest-running technical issue well. To summarize:

  • A huge swath of simfile content is distributed with an intentional offset bias of 9 milliseconds (“ITG sync”) due to hardware reasons that are no longer relevant.
  • Players who have set their machine offset (AKA global offset) using StepMania’s “Calibrate Audio Offset” screen will find ITG-synced content to be offsync on their setup.
  • Players who have set their machine offset by auto-syncing to an ITG-synced simfile will find content without this sync bias (“null sync”) to be offsync on their setup.
  • There is no straightforward way to tell whether a simfile is ITG-synced or not.

As a StepMania creator, these are your options to deal with the sync bias disparity:

  • Supply all of your content both with and without the 9ms sync bias to appease 100% of the player base, either by manually editing a copy of your content or by writing a script to do so.
  • Only supply your content in the sync that’s convenient for you — the same sync your target audience uses, most likely — and slightly inconvenience the players who use the opposite sync standard.

And as a StepMania player, these are your options to solve the disparity for yourself:

  • Manually edit your entire “Songs” folder to have the same sync bias.
  • Maintain two separate StepMania installs with different machine offsets.
  • Recalibrate your machine offset whenever you want to switch which sync bias you want to play.

All of the above options require identifying the correct sync bias of:

  • Everything you’ve already created & downloaded, spanning possibly decades into the past.
  • Everything you will create & download in the future, spanning however long you play the game.

As you might imagine, most players don’t follow through with any of these options. Instead, they opt for the simplest choice:

  • Do nothing, and put up with some of your content being 9 milliseconds offsync.

For a long time, 9 milliseconds was just low enough that most players were able to tolerate the discrepancy. However, with the advent of FA+ and other advanced timing/judgement features, top ITG players are more accurate than ever, and a sync discrepancy of 9ms is no longer acceptable. We’re frogs boiling in our own pot, and it’s finally time to acknowledge that we need a solution that players will actually use.

Where do we want to be?

Let’s think for a second about our ideal state, in contrast to the status quo:

  • StepMania players can enjoy all of their simfiles with the correct sync, including:
    • Everything that’s already on their hard drives.
    • Any packs that they download, regardless of era.
  • Creators only need to release one, bias-free copy of their simfiles & packs.
  • Creators don’t need to update all their old packs.

This is a lot to ask, and I don’t think there’s any silver bullet that can cover everything on this list. This will undoubtedly be a multi-step endeavor, requiring work from people with a broad variety of technical expertise.

My proposal

  1. Establish a new file convention, pack.ini, for storing metadata about a simfile pack (particularly the sync bias).
  2. Update many StepMania forks to read pack.ini and compensate for the sync bias.
  3. Update some StepMania forks (at least ITGMania) to automatically create pack.ini files with the correct sync bias when missing.
  4. Create a standalone tool with the same functionality as (3).

This should cover everything in our ideal state:

  • Players running some StepMania forks (such as ITGMania) automatically get the correct sync.
  • Players running many other StepMania forks get the correct sync when pack.ini is present, and can use the standalone tool to populate it for all their packs.
  • Creators can release a single copy of a pack including pack.ini, which will automatically work for all up-to-date users.
  • Creators who trust players to use either ITGMania or the standalone tool don’t have to re-release their old packs.

pack.ini

pack.ini is a standard INI configuration file containing key=value pairs, intended to be placed in the root of a simfile pack directory (alongside the pack banner). It provides a standard way to specify additional information about a pack in a non-destructive fashion (no need to modify its title or its simfiles).

This proposal is only concerned with one field:

  • SyncBias — set to ITG for ITG-synced content or NULL for null-synced content

Similarly, simfile.ini can be placed in a simfile directory to specify the same information. This is important for the sake of distributing individual simfiles (simfiles not part of any pack), and it takes precedence over any pack.ini file in its enclosing pack’s directory.

You might be aware that StepMania calls packs groups internally - so why pack.ini? In practice, I think the best solution for packs/groups is to take any .ini file, with a preference for one that contains the substring “pack” or “group”, similar to how banners & other simfile assets are chosen. This logic would extend to simfile.ini, with “simfile” being the one preferred substring.

If no pack.ini or simfile.ini is found, or if they don’t specify SyncBias, the sync bias is considered unknown. A new StepMania.ini property, DefaultSyncBias, can be added to handle packs with an unknown sync bias. This value would default to NULL, but players could manually set it to ITG to regard all of their content as having the ITG sync bias by default.

  • 👍 The INI files are easy to identify, observe & change if needed.
  • 👍 The absence of a pack.ini file serves as a passive call to double-check the pack’s sync.
  • 👍 The functionality should be straightforward to implement in any version / fork of StepMania.
  • 👍 Old content can be annotated by adding a single file per pack, without needing to alter the simfiles.
  • 👍 There’s no risk of old versions of StepMania clobbering the metadata (more on this below).

That being said, storing sync information in this manner does have a few drawbacks:

  • 😕 simfile.ini appears superficially redundant with the SM and/or SSC files, being a separate key-value store.
  • 👎 Moving a simfile without a simfile.ini from one pack to another can cause its sync to change.

Let’s consider some alternative options:

#SYNCBIAS property

We could store the sync bias information as a new simfile property, eliminating the 😕 redundancy noted above. However, this comes with a new set of drawbacks:

  • 😕 Sync bias would be encoded in two different formats at the pack/simfile levels, INI (SyncBias=ITG) and MSD (#SYNCBIAS:ITG;).
    • We could change pack.ini to pack.ssc, but this would lead to some ambiguity as to whether a directory is intended to be a pack or a simfile. (Also, I don’t like the MSD format aesthetically and don’t want to create more use cases for it.)
  • 👎 While the SSC format is an active standard that could receive a new version to support a new property, the SM format is essentially frozen in time (not to mention unversioned) — and many simfiles only include an SM file.
  • 👎👎 Saving the simfile from any version of the StepMania editor that exists today would delete this property. New versions of StepMania could retain it, but old versions won’t.

Just change the offsets

This might seem like the obvious solution, but remember that one of the root causes of this dilemma is that players have no way to know whether a pack is ITG-synced or not. A solution that starts and ends with mass-adjusting offsets has some huge gaps in coverage of real-world scenarios.

  • 👍 Requires no extra StepMania / theme-side support.
  • 👎 No way to tell whether content has been adjusted or not (due to lack of annotations). This is especially bad because…
  • 👎👎 Patching content is no longer idempotent: if you accidentally adjust the offsets twice, they will be off-sync in an exciting new signedness of 9ms.
  • 👎👎 If you send your copy of a pack to a friend, they will have no way of knowing whether they themselves need to adjust (or un-adjust) the offsets for themselves.

StepMania updates

We’re interested in patching many StepMania forks with the following functionality:

  • StepMania.ini: new ExpectedSyncBias key which defines the expected sync bias for most content in the installation. Defaults to NULL if not specified
  • Song loader: check for & read into memory INI files
  • Gameplay engine: adjust the audio playback offset according to the install’s ExpectedSyncBias and the content’s SyncBias
  • (optional) Lua API: provide a way to read pack.ini fields for a given pack

My hope is that the source code won’t have changed much across modern versions & forks for the files that need to be updated, but if this isn’t the case, it’s not insurmountable.

Additionally, for the mainline StepMania branch, it would be nice to backport this functionality to legacy branches like StepMania 3.95 and OpenITG. We could provide drop-in replacement binaries for interested players using these legacy versions.

Theme updates

On the theme side, we want to reduce the amount of manual configuration editing required to use the new annotations effectively. This could go as far as incorporating the “sync library” mentioned earlier in the document to automatically annotate known content, but for now let’s focus on the top priorities:

DefaultSyncBias configuration

Somewhere in the Options menu, we need a new item for configuring StepMania.ini’s new DefaultSyncBias property:

Default sync bias   [ Null ] ITG

If the player changes this value, they should be presented with a modal dialog asking whether to change their global offset to compensate for their selection. Figuring out the exact phrasing for this modal is going to be a bit of a UX challenge, but here’s my first draft of the copytext:

You changed your default sync bias from Null to ITG. Do you also want to change your machine offset from 0.100 to 0.091?

If ITG-synced content is already on-sync for you, choose Yes. If you’re not sure, choose Calibrate.

[ Yes ] No Calibrate

(Note: I’m not sure if the example offsets are correct for this situation - it might be the case that the new machine offset should actually be 0.109 here. Need to confirm before implementing!)

“Calibrate” would take the player to the “Calibrate Audio Sync” screen in StepMania, which calibrates the machine offset according to a null-synced metronome file.

Automatic syncing

Proposal components (3) and (4) describe the ability to automatically create pack.ini files with the correct sync bias. This will require some creativity to solve; Telperion’s nine-or-null utility provides an excellent starting point for automation in this area.

Disclaimer, this isn’t my area of expertise, so these thoughts should be taken with a pinch of salt:

  • If automatic sync bias detection proves to be accurate enough at the pack level, integrating it into ITGMania & fleshing out a standalone tool around it would be enough to cover our desired use cases.
  • Including a hashmap of known false matches to their true sync bias seems like a reasonable solution for any gaps in the automated tooling. Of course, someone needs to report a false match for a given pack first.

Miscellaneous thoughts

  • pack.ini could also be used to define a sorting or grouping method for its simfiles.
  • It would be nice to have standalone pack.ini tooling ~ASAP to give creators a head start.