Skip to main content
song.ini is a text file of key = value lines in one [song] section:
Metadata and Settings list the keys. A .sng file holds the same keys in its own metadata, with stricter rules.

Encoding

A scanner decodes song.ini as it decodes a .chart file: see Encoding. Recommended: UTF-8.

The [song] section

  • Required: one [song] section, on the file’s first line. Every key is inside it.
  • Required: [song] alone on its line, with no spaces inside the brackets.
  • A scanner matches the section’s name in any letter case, as written between the brackets. Recommended: [song], in lowercase.

Lines

Required: each line after [song] a key line, a comment, or a blank line.
  • A line ends at a line feed, or at a carriage return followed by a line feed. A carriage return alone doesn’t end a line. Recommended: a carriage return and a line feed.
  • A scanner ignores blank lines, and white space at the start and the end of each line.
  • White space is a space, a tab, or another character that .NET counts as white space, such as a no-break space (U+00A0). A byte order mark (U+FEFF) isn’t white space.

Comments

A comment is a line whose first character, after any spaces, is ;. It takes the whole line. A scanner ignores it. Required: a comment on a line of its own.

Key lines

  • The key is the text before the first =. A scanner matches keys in any letter case. Recommended: in lowercase, as these pages write them. Required: a key without spaces, and a value that doesn’t start with =.
  • The value is the text after the =, without the white space at its start and end.
  • Required: no quotation marks around a value.
  • Required: no white space other than spaces and tabs at either end of a value.
  • Recommended: one space on each side of the =.
  • Required: each key once in a file.
  • Required: keys and section names of at most 1,024 characters.

Key order

Recommended: the keys a song needs, in this order: name, artist, album, genre, year, charter, song_length, diff_band, diff_guitar, diff_guitar_coop, diff_rhythm, diff_bass, diff_drums, diff_drums_real, diff_keys, diff_keys_ghl, diff_guitarghl, diff_guitar_coop_ghl, diff_rhythm_ghl, diff_bassghl, diff_vocals, preview_start_time, preview_end_time, icon, loading_phrase, album_track, playlist_track, playlist, sub_playlist, modchart, explicit_lyrics, sustain_cutoff_threshold, chord_snap_threshold, video_start_time, five_lane_drums, pro_drums
  • The keys only YARG reads go after explicit_lyrics, in the order of Read by YARG only.
  • A deprecated key that an older chart still holds goes after them, before sustain_cutoff_threshold, in the order delay, hopo_frequency, eighthnote_hopo, multiplier_note.
  • Other keys, such as ignored_issues, come last.
  • The order doesn’t change how a scanner reads the file. It keeps files alike, so that each key is in the same place in every file.
  • scan-chart writes keys in this order. It reports keys out of order as iniTagOrder, with its styleNotes option, and fixIssues puts them in order.

Values

Each key takes one type of value:
  • No key takes a decimal number.
  • Times are in milliseconds.
  • A scanner also reads true and false in any other letter case, and 1 and 0, as booleans. They mean the same as True and False.
  • Required: each value in the form of its key’s type.

Values that mean not set

A key that isn’t in the file isn’t set, and a scanner uses its default. Metadata and Settings give each key’s default. Required: a value in every key line, and no -1 in a number key. To leave a value unset, leave its key out. In a text key, 0 and -1 are text: charter = 0 shows the charter as “0”.

Ignored

  • Sections other than [song]. An exporter may keep them. scan-chart reports one as iniLayout, and fixIssues keeps its lines as ; comments.
  • Keys a scanner doesn’t read. An exporter should keep them as written. Metadata lists the keys of older games.

Invalid forms

Clone Hero, YARG and scan-chart ignore them, and read the [song] section after them. scan-chart reports any line that isn’t blank before [song] as iniLayout, comments included, and fixIssues writes [song] on the first line, with the earlier lines kept as comments after it.
A scanner reads the folder as if it had no song.ini: see Files in a song folder. A [song] section with no key lines counts as none. scan-chart reports it as invalidMetadata.
Clone Hero and scan-chart read them as one section, and the last line of each key counts. YARG reads only the last section. A scanner reads them as Clone Hero does. scan-chart reports the second section as iniLayout, and when its fixIssues lays out or orders the file, it merges them into one section.
No scanner reads [ song ] or [song] ; comment as [song], so the key lines after it aren’t in a [song] section.
Clone Hero and scan-chart skip it as a comment. YARG reads it as a key that starts with #, which it doesn’t know, so it has no effect. A scanner ignores the line. scan-chart’s fixIssues rewrites it as a ; comment.
No scanner reads it as a comment. A scanner ignores it: Clone Hero skips it when it has no =, and reads it as a key that no scanner knows when it has one. scan-chart reports a // line without = as badIniLine, and fixIssues rewrites any // line as a ; comment.
No scanner reads it as a comment: it’s part of the value. A text value shows it, and a number followed by a comment is a number in another form, below.
Clone Hero ignores it. YARG reads the first word as the key, so name Song is name = Song. A scanner ignores the line. scan-chart reports it as badIniLine.
Clone Hero reads diff guitar = 3 as a key named diff guitar, which no scanner knows, and name = = Song as the value = Song. YARG reads them as the key diff with the value guitar = 3, and as the value Song. A scanner reads them as Clone Hero does.
Clone Hero can’t read the file, so it reads the folder as if it had no song.ini: see Files in a song folder. YARG and scan-chart read the line as a key or section they don’t know. A scanner reads it as YARG and scan-chart do.
A scanner removes every kind of white space from both ends of a value, as Clone Hero, YARG and scan-chart do. scan-chart doesn’t write a value that starts or ends with white space.
Unlike in a .chart file, a scanner keeps them as part of the value, so a text value shows them. A scanner reads a number or boolean in quotation marks as not set, as Clone Hero and scan-chart do, and YARG reads 0. scan-chart reports quotation marks as quotedIniValue, and a quoted difficulty, such as diff_guitar = "4", also as missingValue. fixIssues removes the quotation marks around text, and leaves a quoted number or boolean for the charter to write as meant.
A scanner uses the last line. scan-chart reports it as duplicateIniKey, and saving an edited song removes the earlier lines.
Clone Hero reads a number as .NET does: an optional sign, then digits, within the 32-bit range, with spaces allowed around them. It uses the key’s default for anything else. YARG reads a number’s leading digits, so 12abc is 12 and 1.5 is 1, and reads 0 when there are none. A scanner reads it as Clone Hero does. Clone Hero reads a delay with a decimal point as seconds instead: see Settings.scan-chart reads the leading number of most keys, so 12abc is 12, and rounds 1.5 to 2 and reports it as invalidValue. It reads hopo_frequency, multiplier_note, sustain_cutoff_threshold and chord_snap_threshold as Clone Hero does, and reports anything else as invalidValue.
Clone Hero and scan-chart read any whole number other than 0 as true, and anything else that isn’t true or false as not set. YARG reads a value that starts with 1 or true as true, and anything else as false: 2 is false, and 10 is true. A scanner reads it as Clone Hero does.
Clone Hero reads a blank number or boolean as not set, and blank text as empty. scan-chart reads every blank value as not set. Clone Hero doesn’t list a song whose name is blank.YARG reads a blank number as 0 and a blank boolean as false, and counts the key as set: a blank preview_start_time starts the preview at 0:00, a blank album_track sorts the song first, a blank difficulty shows 0 instead of no rating, and a blank sustain_cutoff_threshold turns off the cutoff of a .mid file.A scanner reads a blank value as not set, as if the key weren’t in the file. A blank charter or album_track still counts as written, so a scanner doesn’t read frets or track instead: see Metadata. scan-chart reports a blank number as blankIniNumber, and blank text as blankIniValue with its styleNotes option. fixIssues removes the line.
Clone Hero, YARG and scan-chart read -1 in a difficulty, preview_start_time or preview_end_time as not set. In other number keys, Clone Hero and YARG read it as the number -1: album_track = -1 sorts the song first, and delay = -1 moves every note 1 millisecond earlier. scan-chart reads -1 as not set in every number key.A scanner reads -1 in a number key as not set, as if the key weren’t in the file. An album_track of -1 still counts as written, so a scanner doesn’t read track instead.When Clone Hero creates a song.ini for a folder without one, it writes -1 for each difficulty without a rating. Tens of thousands of song folders hold these values. scan-chart reports -1 as blankIniValue with its styleNotes option, and fixIssues removes the line.