From 4e563f3eb2bc9f55d752a1d51d4eb39ab770ca58 Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Mon, 29 Jan 2024 17:24:33 +0100 Subject: [PATCH 01/48] Add partial formal specification --- spec.md | 463 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 463 insertions(+) create mode 100644 spec.md diff --git a/spec.md b/spec.md new file mode 100644 index 0000000..2b17cd7 --- /dev/null +++ b/spec.md @@ -0,0 +1,463 @@ +# The UltraStar File Format + +The UltraStar file format is a timed text format for describing karaoke songs where singing performance is scored by the karaoke software. + +## Status of this document + +This document aims to describe the UltraStar File Format in its most recent version 2.0.0. + +> [!IMPORTANT] +> +> This document is currently a work-in-progress. Parts of the final specification may change significantly from the current state of this document. + +GitHub Issues are preferred for discussion of this specification. Alternatively, you can discuss comments on our Discord server. + +[toc] + +## 1. Introduction + +The UltraStar file format provides a standardized representation of karaoke songs. The format has been used for a long time by numerous karaoke games such as UltraStar Deluxe, Performous, or Vocaluxe. There exists an ecosystem of supporting applications for hosting, editing, and managing songs. However due to the lack of an official file format specification implementations differ and new features cannot be added in a consistent manner. This document aims to fix this problem by providing a formal specification for the syntax and semantics of the UltraStar file format. + +The UltraStar file format is designed to be edited by machines and humans alike and is intended to be easily understood and edited by technical and non-technical users. This guiding principle is influential for many decisions made during the design process. + +### 1.1. Conventions in this Document + +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC2119](https://datatracker.ietf.org/doc/html/rfc2119). + +The grammatical rules in this document are to be interpreted as described in [RFC5234](https://datatracker.ietf.org/doc/html/rfc5234). We are using the following core rules: + +```abnf +CR = %x0D ; carriage return +LF = %x0A ; line feed +CRLF = CR LF +DIGIT = %x30-39 ; 0-9 +HTAB = %x09 ; horizontal tab +SP = %x20 ; space +``` + + + +## 2. General Structure + +UltraStar files are plain text files. The UTF-8 encoding MUST be used. Implementations MUST NOT add a byte order mark to the beginning of a file. In the interests of interoperability, implementations MAY ignore the presence of a byte order mark rather than treating it as an error. + +> [!CAUTION] +> +> Whether files with a BOM may be accepted is an open discussion (#46). + +The canonical file extension for the UltraStar file format is `.txt`. + +UltraStar files consist of a header and a body. The header contains metadata about the song and the file. The body contains the musical data. A file SHOULD end with an `E` on a single line. Everything After a trailing `E` MUST be ignored. + +> [!CAUTION] +> +> Whether the trailing `E` is optional or not is open for discussion (#44). + +```abnf +UltraStar-file = file-header + file-body + [ %x45 *char ] ; E +char = %x00-10FFFF +``` + +### 2.1. Line Endings and White Space + +Both the header and the body of a file are defined in terms of lines. A line is a string of text that is terminated with an end-of-line sequence. + +```abnf +end-of-line = ( CR / LF / CRLF ) +empty-line = end-of-line +``` + +Implementations SHOULD use a single Line Feed (`%x0A`) as line terminator. Implementations MUST accept the end of input (`EOF`) as a valid line terminator. Empty lines are ignored throughout the entire file. + +> [!CAUTION] +> +> The allowed end-of-line sequences as well as potential recommendations for implementations are currently open for discussion (#43). + +> [!CAUTION] +> +> Whether empty lines are allowed or not is currently open for discussion (#43). Whether a line that consists only of whitespace is recognized as an empty line is not yet decided. + +Whitespace is used as a separator in many places of the format. Only space (`%x20`) and horizontal tab (`%x09`) are recognized as whitespace characters. In particular other unicode characters with the property `White_Space=yes` MUST NOT be treated as whitespace characters in the context of this specification. + +```abnf +WSP = ( SP / HTAB ) +``` + +> [!CAUTION] +> +> Definition and handling of whitespace characters is currently open for discussion (#46). + +## 2. The File Header + +The header of an UltraStar file consists of a sequence of key-value pairs. Each line in the header section starts with a hash. The key and value of a header are separated by a colon. Whitespace around key and value is ignored. + +> [!CAUTION] +> +> The terminology “header” is not decided yet. Other terms used for the same concept are “tag”, “attribute” or “field”. + +```abnf +file-header = *( header / empty-line ) +header = hash *WSP header-key *WSP colon *WSP header-value *WSP line-break +header-key = header-key-char + [ *( HTAB / SP / header-key-char ) + header-key-char ] +header-value = single-value / multi-value +multi-value = single-value [ comma single-value ] [ comma ] + +single-value = *( %x20-10FFFF ) +header-key-char = %x21-3A / %x3B-10FFFF ; does not include space, tab, or colon + +hash = %x23 ; # +colon = %x3A ; : +comma = %x2C ; , +``` + +> [!CAUTION] +> +> The use of trailing commas in comma-separated header lists has not been decided yet. + +Comparisons of header keys is case-insensitive. For the sake of consistency header keys SHOULD be capitalized. Header values are generally case-sensitive unless otherwise specified. An empty value is equivalent to the header being absent. + +Implementations MAY define application-specific headers but SHOULD prefix those headers with the application name to avoid conflicts with future standardized headers. Implementations MUST ignore headers they do not recognize. The order of headers is irrelevant (note the exception in section 3.1.) although standardized headers should precede any application-specific headers. + +> [!CAUTION] +> +> Handling of application-specific headers has not been decided yet. + +The following sections describe the standardized headers that have been defined. Some headers are marked as deprecated or removed from a certain version onward. Implementations MUST continue to apply the defined semantics to a headers if it has been deprecated in the file format version indicated by the file. Implementations MUST NOT apply semantics to a header if a file indicates a version where the header has been removed. + +### 3.1. Single-Valued and Multi-Valued Headers + +Headers can be single-valued or multi-valued. Single-valued headers can only be specified once and can only contain a single value. For the sake of robustness implementations SHOULD ignore multiple occurrences of single-valued headers (the selected header value is implementation specific in this case). + +Multi-valued headers can contain multiple values separated by a comma (`%x2C`). Additionally multiple occurrences of a multi-valued header are semantically equivalent to a single occurrence where all values are concatenated by a comma. In this way the order of multi-valued headers is significant. + +> [!WARNING] +> +> **Backwards-Compatible Change** in version 1.1.0 +> +> Multi-Valued Headers were introduced in version 1.1.0 of the format. Headers indicated as multi-valued were single-valued in previous versions. + +> [!WARNING] +> +> **Backwards-Compatible Change** in version ??? +> +> Concatenating multiple occurrences of multi-valued headers was introduced in version ??? of the format. Previously handling of repeated headers was not covered by this specification. + +> [!CAUTION] +> +> The use of multi-valued headers has not been decided yet (#22). + +### 3.2. The `VERSION` Header + +``` +Required: Yes +Multi-Valued: No +Since: 1.0.0 +``` + +The `VERSION` header indicates the version of this specification that a file complies to. The value of the tag is a [semantic version](https://semver.org), meaning that an implementation supporting version 1.0.0 of this spec should be able to process files using a version of 1.1.0 without any changes (although new features might not be supported). Implementations SHOULD NOT attempt to process files with a higher major version than they were designed to work with. + +In absence of the `VERSION` header the version 0.3.0 should be assumed. Implementations SHOULD reject a file based on the value of the `VERSION` header, in particular if the value is syntactically invalid. Applications MAY reject prerelease-versions altogether. + +The `VERSION` header SHOULD be the first header in a file. + +### 3.3. The `BPM` Header + +``` +Required: Yes +Multi-Valued: No +Since: 0.1.0 +``` + +The `BPM` header indicates the number of beats per minute. The notes in a song are quantized in beats. A single beat is the smallest unit of time that can be present in a song. The value is a 32 bit floating point number. The value of this tag is arbitrary in the sense that it is usually 4 to 8 times higher than the actual BPM of a song. + +> [!WARNING] +> +> **Breaking Change** in version 2.0.0 +> +> In versions 0.x and 1.x the value of the `BPM` header was implicitly quadrupled. This is **not** the case for version 2.0.0 and above. + +> [!CAUTION] +> +> The removal of the implicit quadrupling has not been decided yet. + +> [!WARNING] +> +> **Breaking Change** in version 2.0.0 +> +> In versions 0.x and 1.x the comma was allowed as decimal separator in addition to the period. This feature has been removed in version 2.0.0 and above. + +> [!CAUTION] +> +> The removal of the comma as a valid decimal separator has not been decided yet. + +### 3.4. The `AUDIO` Header + +``` +Required: Yes +Multi-Valued: No +Since: 1.1.0 +``` + +The `AUDIO` header indicates the location of an audio file relative to the UltraStar file. This file contains the full version of a song (including instrumentals and vocals). + +### 3.5. The `MP3` Header + +``` +Required: No (Version 2.x), Yes (Versions 0.x and 1.x) +Multi-Valued: No +Since: 0.1.0 +Deprecated: 1.1.0 +Removed: 2.0.0 +``` + +The `MP3` header indicates the location of an audio file relative to the UltraStar file. This header has been replaced by the `AUDIO` header. Implementations MUST disregard the `MP3` header if an `AUDIO` header is present (even if the specified file cannot be found or processed). + +### 3.6. The `GAP` Header + +``` +Required: No +Multi-Valued: No +Since: 0.2.0 +``` + +The `GAP` header indicates an amount of time in milliseconds from the beginning of the audio track until beat 0. This effectively offsets all notes in a song by this amount of time relative to the audio track. The `GAP` value must be an integer. + +> [!WARNING] +> +> **Breaking Change** in version 2.0.0 +> +> In versions 0.x and 1.x the value of `GAP` could also be a floating point number. Since version 2.0.0 this is not allowed anymore. + +### 3.7. The `NOTESGAP` Header + +``` +Required: No +Multi-Valued: No +Since: 0.2.0 +Deprecated: 0.3.0 +Removed: 1.0.0 +``` + +The `NOTESGAP` header is deprecated and MUST NOT be used. Implementations MUST ignore the field if present. + +> [!NOTE] +> +> The `NOTESGAP` header was defined in version 0.1.0 But its semantics were never fully specified. + +### 3.8. The `TITLE` Header + +``` +Required: Yes +Multi-Valued: No +Since: 0.1.0 +``` + +The `TITLE` header contains the title of the song. + +### 3.9. The `Artist` Header + +``` +Required: No +Multi-Valued: No +Since: 0.1.0 +``` + +The `ARTIST` header contains the artist of the song. + +### 3.10. The `GENRE` Header + +``` +Required: No +Multi-Valued: Yes +Since: 0.2.0 +``` + +The `GENRE` defines the genre(s) of the song. Individual genre values MUST be compared case-insensitively. For consistency it is usually best to capitalize genres. + +> [!CAUTION] +> +> Whether genres should be compared case-insensitively or not has not yet been decided. + +### 3.11. The `P1` and `P2` Headers + +``` +Required: No +Multi-Valued: No +Since: 0.2.0 +``` + +The headers `P1` and `P2` indicate the names of the artists that originally sang the song. `P1` is the name of the singer of first voice and `P2` is the name of the singer of the second voice. Usually `P2` is only included for duets. + +### 3.12. The `DUETSINGER1` and `DUETSINGER2` Headers + +``` +Required: No +Multi-Valued: No +Since: 0.2.0 +Deprecated: 0.3.0 +Removed: 1.0.0 +``` + +The headers `DUETSINGER1` and `DUETSINGER2` are aliases for `P1` and `P2`. If both are specified `P1` and `P2` take precedence. + +## 3. The File Body + +The body of a file consists of a sequence of notes, end-of-phrase markers, and player changes. + +```abnf +body = *( note / + end-of-phrase / + player-change / + empty-line ) +``` +The sequence of notes and end-of-phrase markers SHOULD appear in ascending order by their start beats. + +> [!CAUTION] +> +> Whether the body of a file must or may be sorted is not yet decided. + +### 3.1. Notes + +A note is a musical element in a song. Each note is defined by its type, start beat, duration, pitch, and text. + +```abnf +note = note-type + WSP start-beat + WSP duration + WSP pitch + WSP note-text + line-break + +note-type = %x21-22 / %x24-7E ; ASCII-characters except space and # +start-beat = *DIGIT +duration = *DIGIT +pitch = [ minus ] *DIGIT +note-text = 1*( %x20-10FFFF ) + +minus = %x2D ; - +``` + +> [!CAUTION] +> +> Whether only a single or multiple whitespaces in a row are allowed is currently up for discussion (#46). + +The note type indicates how singing the correct or wrong note should affect scoring. The following sections define standard note types. Implementations MAY substitute unknown note types with freestyle notes (`F`). Implementations MUST NOT attach semantics to note types not covered by this specification. + +The start beat and duration define the time when a note appears in a song. Both are indicated in beats (see section 3.3.) relative to offset indicated by the `GAP` header. The end beat of a note is calculated as its start beat plus its duration. Notes SHOULD NOT overlap, i.e. the start beat of a note being between the start beat (inclusive) and end beat (exclusive) of another note. + +> [!CAUTION] +> +> Whether and how applications may define custom note types is not yet decided. + +> [!CAUTION] +> +> Whether negative note starts and/or durations are valid is not yet decided. + +The pitch of a note is encoded as the number of half-steps relative to middle C or C4. So a pitch of `5` represent an F4 and a pitch of `-2` represents an A#3. + +#### 3.1.1. Regular Notes `:` + +A regular note is indicated by the note type `:` (colon, `%x3A`). A regular note indicates that a certail pitch is to be held for a certain duration. Game implementations MAY decide to compare pitches independently of the octave (i.e. compare pitches module 12). + +#### 3.1.2. Golden Notes `*` + +A golden note is indicated by the note type `*` (asterist, `%x2A`). Golden note have the same semantics as regular notes. However, during scoring game implementations SHOULD award more points for golden notes. The exact scoring behavior is an implementation detail. + +#### 3.1.3. Rap Notes `R` + +> [!WARNING] +> +> Rap notes are standardized in version 0.2.0 of this specification. + +A rap note is indicated by the note type `R` (the letter R, `%x52`). Rap notes have the same timing semantics as regular notes but are intended or spoken phrases that do not have a defined pitch. Implementations MUST ignore pitch information on rap notes. + +#### 3.1.4. Golden Rap Notes `G` + +> [!WARNING] +> +> Golden rap notes are standardized in version 0.2.0 of this specification. + +A golden rap note is indicated by the note type `G` (the letter G, `%x47`). Golden rap notes have the same semantics as rap notes. However, during scoring game implementations SHOULD award more points for golden rap notes. The exact scoring behavior is an implementation detail. + +#### 3.1.5. Freestyle Notes + +> [!WARNING] +> +> Freestyle notes are standardized in version 0.2.0 of this specification. + +A freestyle note is indicated by the note type `F` (the letter F, `%x46`). Similar to rap notes, freestyle notes do not carry pitch information. Additionally game implementations MUST NOT award points for freestyle notes. + +### 3.2. End-of-Phrase Markers + +End-of-Phrase markers are indicated by a `-` character (hyphen/minus, `%x2D`). + +```abnf +end-of-phrase = dash + WSP start-beat + *WSP line-break +``` + +An end-of-phrase marker carries no musical information but indicates the end of a phrase in the song. This is usually interpreted as a line break in the lyrics. + +An end-of-phrase SHOULD NOT appear between the start beat (inclusive) of a note and its end beat (exclusive). An end-of-phrase marker SHOULD NOT appear before the start time of the first note or after the start time of the last note. + +> [!CAUTION] +> +> Whether leading or trailing end-of-phrase markers are allowed is currently up for discussion (#44). + +> [!CAUTION] +> +> Whether there can be non-whitespace text following an end-of-phrase indicator is not yet decided. + +### 3.3. Player Changes + +A player change is indicated by a `P` (the letter P, `%x50`), immediately followed by a number. + +```abnf +player-change = p player-numer + *WSP line-break +p = %x50 ; P +player-number = "1" / "2" +``` + +A player change indicates that all notes and end-of-phrase markers following this line belong to the player, indicated by the `player-number`. This allows inclusion of up to 2 voices. If the body of a song does not start with a player change, `P1` is assumed implicitly. Implementations SHOULD NOT include the same player change more than once (i.e. notes for different players should not be interlaced). + +> [!NOTE] +> +> A player change does NOT implicitly add an end-of-phrase indicator. + +> [!TIP] +> +> An UltraStar file that makes use of player changes is referred to as a “duet”. + +> [!WARNING] +> +> **Breaking Change** in version 0.2.0 +> +> In version 0.1.0 only single-player songs were defined. Player changes are specified since version 0.2.0. + +> [!WARNING] +> +> There exists a legacy behavior where an indicated `P3` would start a sequence of notes that apply to both players. This behavior is explicitly NOT compliant with this specification. + +> [!CAUTION] +> +> Whether songs that make use of player changes need to start their body with a player change is not yet decided. + +> [!CAUTION] +> +> Whether single-voice songs can have player changes (only `P1`) is not yet decided. + +> [!CAUTION] +> +> Whether there may be a whitespace between the “P” and the indicated player is not yet decided. + +## Appendix + +### A. Relative mode + +How does player change work in relative mode? From 89b3d8fde6e518efb0163e7cfd40a7631b4ed446 Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Mon, 29 Jan 2024 17:59:40 +0100 Subject: [PATCH 02/48] Remove toc GitHub does not render the table of contents --- spec.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/spec.md b/spec.md index 2b17cd7..91e826d 100644 --- a/spec.md +++ b/spec.md @@ -12,8 +12,6 @@ This document aims to describe the UltraStar File Format in its most recent vers GitHub Issues are preferred for discussion of this specification. Alternatively, you can discuss comments on our Discord server. -[toc] - ## 1. Introduction The UltraStar file format provides a standardized representation of karaoke songs. The format has been used for a long time by numerous karaoke games such as UltraStar Deluxe, Performous, or Vocaluxe. There exists an ecosystem of supporting applications for hosting, editing, and managing songs. However due to the lack of an official file format specification implementations differ and new features cannot be added in a consistent manner. This document aims to fix this problem by providing a formal specification for the syntax and semantics of the UltraStar file format. From d9a1d674a028cffe316fb7daf8e719c31541d833 Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Mon, 29 Jan 2024 23:10:27 +0100 Subject: [PATCH 03/48] Add GitHub links to third parties --- spec.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec.md b/spec.md index 91e826d..7e55a2f 100644 --- a/spec.md +++ b/spec.md @@ -14,7 +14,7 @@ GitHub Issues are preferred for discussion of this specification. Alternatively, ## 1. Introduction -The UltraStar file format provides a standardized representation of karaoke songs. The format has been used for a long time by numerous karaoke games such as UltraStar Deluxe, Performous, or Vocaluxe. There exists an ecosystem of supporting applications for hosting, editing, and managing songs. However due to the lack of an official file format specification implementations differ and new features cannot be added in a consistent manner. This document aims to fix this problem by providing a formal specification for the syntax and semantics of the UltraStar file format. +The UltraStar file format provides a standardized representation of karaoke songs. The format has been used for a long time by numerous karaoke games such as [UltraStar Deluxe](https://github.com/UltraStar-Deluxe/USDX), [Performous](https://github.com/performous/performous), or [Vocaluxe](https://github.com/Vocaluxe/Vocaluxe). There exists an ecosystem of supporting applications for hosting, editing, and managing songs. However due to the lack of an official file format specification implementations differ and new features cannot be added in a consistent manner. This document aims to fix this problem by providing a formal specification for the syntax and semantics of the UltraStar file format. The UltraStar file format is designed to be edited by machines and humans alike and is intended to be easily understood and edited by technical and non-technical users. This guiding principle is influential for many decisions made during the design process. From 84cc316d0759dfd24153dfc38b5951e9c4ead00d Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Mon, 29 Jan 2024 23:11:04 +0100 Subject: [PATCH 04/48] Fix typo --- spec.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec.md b/spec.md index 7e55a2f..4bbb5fd 100644 --- a/spec.md +++ b/spec.md @@ -45,7 +45,7 @@ UltraStar files are plain text files. The UTF-8 encoding MUST be used. Implement The canonical file extension for the UltraStar file format is `.txt`. -UltraStar files consist of a header and a body. The header contains metadata about the song and the file. The body contains the musical data. A file SHOULD end with an `E` on a single line. Everything After a trailing `E` MUST be ignored. +UltraStar files consist of a header and a body. The header contains metadata about the song and the file. The body contains the musical data. A file SHOULD end with an `E` on a single line. Everything after a trailing `E` MUST be ignored. > [!CAUTION] > From 581477a62df0a0a745c361f0743152550cd041d9 Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Mon, 29 Jan 2024 23:14:46 +0100 Subject: [PATCH 05/48] Add issue links --- spec.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/spec.md b/spec.md index 4bbb5fd..c2f3432 100644 --- a/spec.md +++ b/spec.md @@ -41,7 +41,7 @@ UltraStar files are plain text files. The UTF-8 encoding MUST be used. Implement > [!CAUTION] > -> Whether files with a BOM may be accepted is an open discussion (#46). +> Whether files with a BOM may be accepted is an open discussion ([#46](https://github.com/UltraStar-Deluxe/format/issues/46)). The canonical file extension for the UltraStar file format is `.txt`. @@ -49,7 +49,7 @@ UltraStar files consist of a header and a body. The header contains metadata abo > [!CAUTION] > -> Whether the trailing `E` is optional or not is open for discussion (#44). +> Whether the trailing `E` is optional or not is open for discussion ([#44](https://github.com/UltraStar-Deluxe/format/issues/44)). ```abnf UltraStar-file = file-header @@ -71,11 +71,11 @@ Implementations SHOULD use a single Line Feed (`%x0A`) as line terminator. Imple > [!CAUTION] > -> The allowed end-of-line sequences as well as potential recommendations for implementations are currently open for discussion (#43). +> The allowed end-of-line sequences as well as potential recommendations for implementations are currently open for discussion ([#43](https://github.com/UltraStar-Deluxe/format/issues/43)). > [!CAUTION] > -> Whether empty lines are allowed or not is currently open for discussion (#43). Whether a line that consists only of whitespace is recognized as an empty line is not yet decided. +> Whether empty lines are allowed or not is currently open for discussion ([#43](https://github.com/UltraStar-Deluxe/format/issues/43)). Whether a line that consists only of whitespace is recognized as an empty line is not yet decided. Whitespace is used as a separator in many places of the format. Only space (`%x20`) and horizontal tab (`%x09`) are recognized as whitespace characters. In particular other unicode characters with the property `White_Space=yes` MUST NOT be treated as whitespace characters in the context of this specification. @@ -85,7 +85,7 @@ WSP = ( SP / HTAB ) > [!CAUTION] > -> Definition and handling of whitespace characters is currently open for discussion (#46). +> Definition and handling of whitespace characters is currently open for discussion ([#46](https://github.com/UltraStar-Deluxe/format/issues/46)). ## 2. The File Header @@ -146,7 +146,7 @@ Multi-valued headers can contain multiple values separated by a comma (`%x2C`). > [!CAUTION] > -> The use of multi-valued headers has not been decided yet (#22). +> The use of multi-valued headers has not been decided yet ([#22](https://github.com/UltraStar-Deluxe/format/issues/22)). ### 3.2. The `VERSION` Header @@ -341,7 +341,7 @@ minus = %x2D ; - > [!CAUTION] > -> Whether only a single or multiple whitespaces in a row are allowed is currently up for discussion (#46). +> Whether only a single or multiple whitespaces in a row are allowed is currently up for discussion ([#46](https://github.com/UltraStar-Deluxe/format/issues/46)). The note type indicates how singing the correct or wrong note should affect scoring. The following sections define standard note types. Implementations MAY substitute unknown note types with freestyle notes (`F`). Implementations MUST NOT attach semantics to note types not covered by this specification. @@ -405,7 +405,7 @@ An end-of-phrase SHOULD NOT appear between the start beat (inclusive) of a note > [!CAUTION] > -> Whether leading or trailing end-of-phrase markers are allowed is currently up for discussion (#44). +> Whether leading or trailing end-of-phrase markers are allowed is currently up for discussion ([#44](https://github.com/UltraStar-Deluxe/format/issues/44)). > [!CAUTION] > From 4fa8f1b4660dcd4ea4d7517615a1b1e54ee4b510 Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Mon, 29 Jan 2024 23:17:24 +0100 Subject: [PATCH 06/48] Fix imperative --- spec.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec.md b/spec.md index c2f3432..61d434d 100644 --- a/spec.md +++ b/spec.md @@ -158,7 +158,7 @@ Since: 1.0.0 The `VERSION` header indicates the version of this specification that a file complies to. The value of the tag is a [semantic version](https://semver.org), meaning that an implementation supporting version 1.0.0 of this spec should be able to process files using a version of 1.1.0 without any changes (although new features might not be supported). Implementations SHOULD NOT attempt to process files with a higher major version than they were designed to work with. -In absence of the `VERSION` header the version 0.3.0 should be assumed. Implementations SHOULD reject a file based on the value of the `VERSION` header, in particular if the value is syntactically invalid. Applications MAY reject prerelease-versions altogether. +In absence of the `VERSION` header implementations SHOULD assume the version 0.3.0. Implementations SHOULD reject a file based on the value of the `VERSION` header, in particular if the value is syntactically invalid. Applications MAY reject prerelease-versions altogether. The `VERSION` header SHOULD be the first header in a file. From 16a32d95c58c02ec6a669380b38febd43fa1cbb6 Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Mon, 29 Jan 2024 23:34:05 +0100 Subject: [PATCH 07/48] Fix vocab mistake --- spec.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec.md b/spec.md index 61d434d..9af22dc 100644 --- a/spec.md +++ b/spec.md @@ -116,7 +116,7 @@ comma = %x2C ; , > > The use of trailing commas in comma-separated header lists has not been decided yet. -Comparisons of header keys is case-insensitive. For the sake of consistency header keys SHOULD be capitalized. Header values are generally case-sensitive unless otherwise specified. An empty value is equivalent to the header being absent. +Comparisons of header keys is case-insensitive. For the sake of consistency header keys SHOULD use only capital letters. Header values are generally case-sensitive unless otherwise specified. An empty value is equivalent to the header being absent. Implementations MAY define application-specific headers but SHOULD prefix those headers with the application name to avoid conflicts with future standardized headers. Implementations MUST ignore headers they do not recognize. The order of headers is irrelevant (note the exception in section 3.1.) although standardized headers should precede any application-specific headers. @@ -452,7 +452,7 @@ A player change indicates that all notes and end-of-phrase markers following thi > [!CAUTION] > -> Whether there may be a whitespace between the “P” and the indicated player is not yet decided. +> Whether there may be a whitespace between the `P` and the indicated player is currently open for discussion ([#46](https://github.com/UltraStar-Deluxe/format/issues/46)). ## Appendix From 5b83ed54cd7327f851a696d6ab7cc9f181d6cf74 Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Tue, 30 Jan 2024 00:15:32 +0100 Subject: [PATCH 08/48] Add more headers --- spec.md | 86 +++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 72 insertions(+), 14 deletions(-) diff --git a/spec.md b/spec.md index 9af22dc..f4f758d 100644 --- a/spec.md +++ b/spec.md @@ -148,7 +148,19 @@ Multi-valued headers can contain multiple values separated by a comma (`%x2C`). > > The use of multi-valued headers has not been decided yet ([#22](https://github.com/UltraStar-Deluxe/format/issues/22)). -### 3.2. The `VERSION` Header +### 3.2. File References + +Some headers reference other files, most notably `AUDIO`, `VIDEO`, `COVER`, and `BACKGROUND`. These file references are always relative to the UltraStar file from which they are referenced. As a security measure file references MUST NOT use absolute paths. Implementations SHOULD refuse to load absolutely referenced files. + +> [!CAUTION] +> +> Whether absolute paths are allowed or not has not been decided yet. + +> [!IMPORTANT] +> +> In Windows file names are case-insensitive (i.e. there cannot be two files in a folder that differ only by their case). Linux and macOS however, use fully case-sensitive file systems. Implementations might need to pay special attention to this fact to ensure that files are compatible across all systems. + +### 3.3. The `VERSION` Header ``` Required: Yes @@ -162,7 +174,7 @@ In absence of the `VERSION` header implementations SHOULD assume the version 0.3 The `VERSION` header SHOULD be the first header in a file. -### 3.3. The `BPM` Header +### 3.4. The `BPM` Header ``` Required: Yes @@ -192,7 +204,7 @@ The `BPM` header indicates the number of beats per minute. The notes in a song a > > The removal of the comma as a valid decimal separator has not been decided yet. -### 3.4. The `AUDIO` Header +### 3.5. The `AUDIO` Header ``` Required: Yes @@ -200,9 +212,9 @@ Multi-Valued: No Since: 1.1.0 ``` -The `AUDIO` header indicates the location of an audio file relative to the UltraStar file. This file contains the full version of a song (including instrumentals and vocals). +The `AUDIO` header contains a file reference (as defined in section 3.2.) to an audio file. This file contains the full version of a song (including instrumentals and vocals). Supported audio formats are an implementation detail. -### 3.5. The `MP3` Header +### 3.6. The `MP3` Header ``` Required: No (Version 2.x), Yes (Versions 0.x and 1.x) @@ -212,9 +224,9 @@ Deprecated: 1.1.0 Removed: 2.0.0 ``` -The `MP3` header indicates the location of an audio file relative to the UltraStar file. This header has been replaced by the `AUDIO` header. Implementations MUST disregard the `MP3` header if an `AUDIO` header is present (even if the specified file cannot be found or processed). +The `MP3` header contains a file reference (as defined in section 3.2.) to an audio file. This header has been replaced by the `AUDIO` header. Implementations MUST disregard the `MP3` header if an `AUDIO` header is present (even if the specified file cannot be found or processed). -### 3.6. The `GAP` Header +### 3.7. The `COVER`, `BACKGROUND`, and `VIDEO` Headers ``` Required: No @@ -222,7 +234,17 @@ Multi-Valued: No Since: 0.2.0 ``` -The `GAP` header indicates an amount of time in milliseconds from the beginning of the audio track until beat 0. This effectively offsets all notes in a song by this amount of time relative to the audio track. The `GAP` value must be an integer. +The headers `COVER`, `BACKGROUND`, and `VIDEO` contain file references to image files or in case of `VIDEO` video files. Implementations MAY use these files to display cover artwork and background graphics during gameplay. Supported image and video formats are an implementation detail. + +### 3.8. The `GAP` Header + +``` +Required: No +Multi-Valued: No +Since: 0.2.0 +``` + +The `GAP` header indicates an amount of time in milliseconds from the beginning of the audio track until beat 0. This effectively offsets all notes in a song by this amount of time relative to the audio track. The `GAP` value is an integer. > [!WARNING] > @@ -230,7 +252,23 @@ The `GAP` header indicates an amount of time in milliseconds from the beginning > > In versions 0.x and 1.x the value of `GAP` could also be a floating point number. Since version 2.0.0 this is not allowed anymore. -### 3.7. The `NOTESGAP` Header +### 3.9. The `VIDEOGAP` Header + +``` +Required: No +Multi-Valued: No +Since: 0.2.0 +``` + +The `VIDEOGAP` header indicates an amount of time in milliseconds that the background video will be delayed relative to the audio of a song. The `VIDEOGAP` value is an integer. + +> [!WARNING] +> +> **Breaking Change** in version 2.0.0 +> +> In versions 0.x and 1.x the value of `VIDEOGAP` was specified in seconds as a floating point number. Version 2.0.0 changes this to an integer and milliseconds. + +### 3.10. The `NOTESGAP` Header ``` Required: No @@ -246,7 +284,27 @@ The `NOTESGAP` header is deprecated and MUST NOT be used. Implementations MUST i > > The `NOTESGAP` header was defined in version 0.1.0 But its semantics were never fully specified. -### 3.8. The `TITLE` Header +### 3.11. The `START` and `END` Headers + +``` +Required: No +Multi-Valued: No +Since: 0.2.0 +``` + +The `START` and `END` header specify two time points in milliseconds relative to the start of the audio data that indicate a start and end point for the song. Game implementations SHOULD start and end the song at the specified points and scale scoring accordingly. Both `START` and `END` values are integers. + +> [!NOTE] +> +> The `START` and `END` values do not affect the placement of notes relative to the audio. They simply skip a certain amount of time from the beginning or towards the end of a song. + +> [!WARNING] +> +> **Breaking Change** in version 2.0.0 +> +> In versions 0.x and 1.x `START` was specified in seconds as a floating point number. Version 2.0.0 changes this to an integer and milliseconds. + +### 3.12. The `TITLE` Header ``` Required: Yes @@ -256,7 +314,7 @@ Since: 0.1.0 The `TITLE` header contains the title of the song. -### 3.9. The `Artist` Header +### 3.13. The `ARTIST` Header ``` Required: No @@ -266,7 +324,7 @@ Since: 0.1.0 The `ARTIST` header contains the artist of the song. -### 3.10. The `GENRE` Header +### 3.14. The `GENRE` Header ``` Required: No @@ -280,7 +338,7 @@ The `GENRE` defines the genre(s) of the song. Individual genre values MUST be co > > Whether genres should be compared case-insensitively or not has not yet been decided. -### 3.11. The `P1` and `P2` Headers +### 3.15. The `P1` and `P2` Headers ``` Required: No @@ -290,7 +348,7 @@ Since: 0.2.0 The headers `P1` and `P2` indicate the names of the artists that originally sang the song. `P1` is the name of the singer of first voice and `P2` is the name of the singer of the second voice. Usually `P2` is only included for duets. -### 3.12. The `DUETSINGER1` and `DUETSINGER2` Headers +### 3.16. The `DUETSINGER1` and `DUETSINGER2` Headers ``` Required: No From 77d798f208f4772e11a8f19a6140043553d0acdd Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Tue, 30 Jan 2024 00:20:21 +0100 Subject: [PATCH 09/48] Allow arbitrarily many players --- spec.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/spec.md b/spec.md index f4f758d..c8adcc3 100644 --- a/spec.md +++ b/spec.md @@ -474,13 +474,14 @@ An end-of-phrase SHOULD NOT appear between the start beat (inclusive) of a note A player change is indicated by a `P` (the letter P, `%x50`), immediately followed by a number. ```abnf -player-change = p player-numer +player-change = p player-numer *WSP line-break -p = %x50 ; P -player-number = "1" / "2" +p = %x50 ; P +player-number = positive-digit *DIGIT +positive-digit = %x31-39 ; 1-9 ``` -A player change indicates that all notes and end-of-phrase markers following this line belong to the player, indicated by the `player-number`. This allows inclusion of up to 2 voices. If the body of a song does not start with a player change, `P1` is assumed implicitly. Implementations SHOULD NOT include the same player change more than once (i.e. notes for different players should not be interlaced). +A player change indicates that all notes and end-of-phrase markers following this line belong to the player indicated by the `player-number`. Implementations MAY choose to limit the number of voices. If the body of a song does not start with a player change, `P1` is assumed implicitly. To improve readablility notes for different players should not be interlaced. > [!NOTE] > From f1fb8e2c8dc4fab640f0bf495cc8f42a41412b8e Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Tue, 30 Jan 2024 00:21:25 +0100 Subject: [PATCH 10/48] Fix missing note type --- spec.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec.md b/spec.md index c8adcc3..a7459c7 100644 --- a/spec.md +++ b/spec.md @@ -439,7 +439,7 @@ A rap note is indicated by the note type `R` (the letter R, `%x52`). Rap notes h A golden rap note is indicated by the note type `G` (the letter G, `%x47`). Golden rap notes have the same semantics as rap notes. However, during scoring game implementations SHOULD award more points for golden rap notes. The exact scoring behavior is an implementation detail. -#### 3.1.5. Freestyle Notes +#### 3.1.5. Freestyle Notes `F` > [!WARNING] > From f4dd24e1d5836d3eda57f14d38ab98947df3def4 Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Tue, 30 Jan 2024 00:34:44 +0100 Subject: [PATCH 11/48] Fix small stuff --- spec.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/spec.md b/spec.md index a7459c7..c668e28 100644 --- a/spec.md +++ b/spec.md @@ -388,13 +388,13 @@ note = note-type WSP note-text line-break -note-type = %x21-22 / %x24-7E ; ASCII-characters except space and # +note-type = %x21-22 / %x24-7E ; Visible ASCII-characters except space and # start-beat = *DIGIT duration = *DIGIT pitch = [ minus ] *DIGIT note-text = 1*( %x20-10FFFF ) -minus = %x2D ; - +minus = %x2D ; - ``` > [!CAUTION] @@ -476,7 +476,7 @@ A player change is indicated by a `P` (the letter P, `%x50`), immediately follow ```abnf player-change = p player-numer *WSP line-break -p = %x50 ; P +p = %x50 ; P player-number = positive-digit *DIGIT positive-digit = %x31-39 ; 1-9 ``` @@ -497,7 +497,7 @@ A player change indicates that all notes and end-of-phrase markers following thi > > In version 0.1.0 only single-player songs were defined. Player changes are specified since version 0.2.0. -> [!WARNING] +> [!Note] > > There exists a legacy behavior where an indicated `P3` would start a sequence of notes that apply to both players. This behavior is explicitly NOT compliant with this specification. From edfd2e0237ef18266e30699c94c93cc6ea1e245a Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Tue, 30 Jan 2024 19:30:55 +0100 Subject: [PATCH 12/48] Add header length limit --- spec.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec.md b/spec.md index c668e28..7f368c6 100644 --- a/spec.md +++ b/spec.md @@ -20,9 +20,9 @@ The UltraStar file format is designed to be edited by machines and humans alike ### 1.1. Conventions in this Document -The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC2119](https://datatracker.ietf.org/doc/html/rfc2119). +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119](https://datatracker.ietf.org/doc/html/rfc2119). -The grammatical rules in this document are to be interpreted as described in [RFC5234](https://datatracker.ietf.org/doc/html/rfc5234). We are using the following core rules: +The grammatical rules in this document are to be interpreted as described in [RFC 5234](https://datatracker.ietf.org/doc/html/rfc5234). We are using the following core rules: ```abnf CR = %x0D ; carriage return @@ -116,7 +116,7 @@ comma = %x2C ; , > > The use of trailing commas in comma-separated header lists has not been decided yet. -Comparisons of header keys is case-insensitive. For the sake of consistency header keys SHOULD use only capital letters. Header values are generally case-sensitive unless otherwise specified. An empty value is equivalent to the header being absent. +Comparisons of header keys is case-insensitive. For the sake of consistency header keys SHOULD use only capital letters. Header values are generally case-sensitive unless otherwise specified. An empty value is equivalent to the header being absent. Header values may not exceed 255 characters. Implementations MAY define application-specific headers but SHOULD prefix those headers with the application name to avoid conflicts with future standardized headers. Implementations MUST ignore headers they do not recognize. The order of headers is irrelevant (note the exception in section 3.1.) although standardized headers should precede any application-specific headers. From 79295d0fd354dfa9a3ed23b9dfc109e4c38d22a2 Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Tue, 30 Jan 2024 19:31:02 +0100 Subject: [PATCH 13/48] Add missing headers --- spec.md | 241 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 229 insertions(+), 12 deletions(-) diff --git a/spec.md b/spec.md index 7f368c6..326e7ad 100644 --- a/spec.md +++ b/spec.md @@ -124,7 +124,7 @@ Implementations MAY define application-specific headers but SHOULD prefix those > > Handling of application-specific headers has not been decided yet. -The following sections describe the standardized headers that have been defined. Some headers are marked as deprecated or removed from a certain version onward. Implementations MUST continue to apply the defined semantics to a headers if it has been deprecated in the file format version indicated by the file. Implementations MUST NOT apply semantics to a header if a file indicates a version where the header has been removed. +The following sections describe the standardized headers that have been defined. If a syntax for a header is specified it applies to the `single-value`. If no syntax is specified any valid `single-value` is valid. Some headers are marked as deprecated or removed from a certain version onward. Implementations MUST continue to apply the defined semantics to a headers if it has been deprecated in the file format version indicated by the file. Implementations MUST NOT apply semantics to a header if a file indicates a version where the header has been removed. ### 3.1. Single-Valued and Multi-Valued Headers @@ -165,6 +165,7 @@ Some headers reference other files, most notably `AUDIO`, `VIDEO`, `COVER`, and ``` Required: Yes Multi-Valued: No +Syntax: Since: 1.0.0 ``` @@ -179,6 +180,7 @@ The `VERSION` header SHOULD be the first header in a file. ``` Required: Yes Multi-Valued: No +Syntax: 1*DIGIT Since: 0.1.0 ``` @@ -214,6 +216,10 @@ Since: 1.1.0 The `AUDIO` header contains a file reference (as defined in section 3.2.) to an audio file. This file contains the full version of a song (including instrumentals and vocals). Supported audio formats are an implementation detail. +> [!CAUTION] +> +> If media files should follow a specific naming scheme has not been decided yet. + ### 3.6. The `MP3` Header ``` @@ -236,43 +242,78 @@ Since: 0.2.0 The headers `COVER`, `BACKGROUND`, and `VIDEO` contain file references to image files or in case of `VIDEO` video files. Implementations MAY use these files to display cover artwork and background graphics during gameplay. Supported image and video formats are an implementation detail. -### 3.8. The `GAP` Header +For the best compatibility `COVER` images should be square and be no larger than 1920 pixels in width and height. + +> [!CAUTION] +> +> If a minimum requirement concerning media types should be part of the spec has not been decided yet. + +> [!CAUTION] +> +> If media files should follow a specific naming scheme has not been decided yet. + +### 3.8. The `VOCALS` and `INSTRUMENTAL` Headers + +``` +Required: No +Multi-Valued: No +Since: 1.1.0 +``` + +The `VOCALS` and `INSTRUMENTAL` header contain file references to audio files. These files contain the acapella and instrumental versions of the song respectively. Implementations MAY use these instead of `AUDIO` to give users the option of changing the volume of vocal and instrumental tracks separately. + +> [!CAUTION] +> +> Whether the inclusion of `VOCALS` requires the inclusion of `INSTRUMENTAL` is currently not decided. + +### 3.9. The `GAP` Header ``` Required: No Multi-Valued: No +Syntax: 1*DIGIT Since: 0.2.0 ``` The `GAP` header indicates an amount of time in milliseconds from the beginning of the audio track until beat 0. This effectively offsets all notes in a song by this amount of time relative to the audio track. The `GAP` value is an integer. +> [!CAUTION] +> +> Whether negative `GAP` values are allowed or disallowed is not decided yet. + > [!WARNING] > > **Breaking Change** in version 2.0.0 > > In versions 0.x and 1.x the value of `GAP` could also be a floating point number. Since version 2.0.0 this is not allowed anymore. -### 3.9. The `VIDEOGAP` Header +### 3.10. The `VIDEOGAP` Header ``` Required: No Multi-Valued: No +Syntax: [ minus ] 1*DIGIT Since: 0.2.0 ``` The `VIDEOGAP` header indicates an amount of time in milliseconds that the background video will be delayed relative to the audio of a song. The `VIDEOGAP` value is an integer. +> [!NOTE] +> +> + > [!WARNING] > > **Breaking Change** in version 2.0.0 > > In versions 0.x and 1.x the value of `VIDEOGAP` was specified in seconds as a floating point number. Version 2.0.0 changes this to an integer and milliseconds. -### 3.10. The `NOTESGAP` Header +### 3.11. The `NOTESGAP` Header ``` Required: No Multi-Valued: No +Syntax: [ minus ] 1*DIGIT Since: 0.2.0 Deprecated: 0.3.0 Removed: 1.0.0 @@ -284,11 +325,30 @@ The `NOTESGAP` header is deprecated and MUST NOT be used. Implementations MUST i > > The `NOTESGAP` header was defined in version 0.1.0 But its semantics were never fully specified. -### 3.11. The `START` and `END` Headers +### 3.12. The `RESOLUTION` Header + +``` +Required: No +Multi-Valued: No +Since: 0.2.0 +Deprecated: 0.3.0 +Removed: 1.0.0 +``` + +The `RESOLUTION` header is used by [UltraStar Deluxe](https://github.com/UltraStar-Deluxe/USDX) exclusively to change the resolution of the built-in song editor. + +> [!WARNING] +> +> **Breaking Change** in version 1.0.0 +> +> The `RESOLUTION` header was removed in version 1.0.0 of this specification. + +### 3.13. The `START` and `END` Headers ``` Required: No Multi-Valued: No +Syntax: 1*DIGIT Since: 0.2.0 ``` @@ -296,7 +356,7 @@ The `START` and `END` header specify two time points in milliseconds relative to > [!NOTE] > -> The `START` and `END` values do not affect the placement of notes relative to the audio. They simply skip a certain amount of time from the beginning or towards the end of a song. +> The `START` and `END` values do not affect the placement of notes nor any other time codes relative to the audio. They simply indicate that a song should be started or stopped a certain amount of time into the audio file. > [!WARNING] > @@ -304,7 +364,68 @@ The `START` and `END` header specify two time points in milliseconds relative to > > In versions 0.x and 1.x `START` was specified in seconds as a floating point number. Version 2.0.0 changes this to an integer and milliseconds. -### 3.12. The `TITLE` Header +### 3.14. The `PREVIEWSTART` Header + +``` +Required: No +Multi-Valued: No +Syntax: 1*DIGIT +Since: 0.2.0 +``` + +The `PREVIEWSTART` header indicates a time offset in milliseconds relative to the start of the audio where the preview starts. Implementations MAY use this value when playing a song in a preview setting (e.g. during song selection). In its absence implementations SHOULD default to the start of the medley section (if available). + +> [!WARNING] +> +> **Breaking Change** in version 2.0.0 +> +> In versions 0.x and 1.x `PREVIEWSTART` was specified in seconds as a floating point number. Version 2.0.0 of this specification changes this to an integer and milliseconds. + +### 3.15. The `MEDLEYSTART` and `MEDLEYEND` Headers + +``` +Required: No +Multi-Valued: No +Syntax: 1*DIGIT +Since: 2.0.0 +``` + +The `MEDLEYSTART` and `MEDLEYEND` headers indicate in milliseconds the start and end of the medley section of a song relative to the start of the audio. These tags replace `MEDLEYSTARTBEAT` and `MEDLEYENDBEAT` in version 2.0.0 of this specification. + +### 3.16. The `MEDLEYSTARTBEAT` and `MEDLEYENDBEAT` Headers + +``` +Required: No +Multi-Valued: No +Syntax: 1*DIGIT +Since: 0.2.0 +Removed: 2.0.0 +``` + +The `MEDLEYSTARTBEAT` and `MEDLEYENDBEAT` headers indicate in beats the start and end of the medley section of a song. Implementations MUST respect the `GAP` value when calculating the medley start and end times. + +> [!WARNING] +> +> **Breaking Change** in version 2.0.0 +> +> The headers `MEDLEYSTARTBEAT` and `MEDLEYENDBEAT` have been replaced by `MEDLEYSTART` and `MEDLEYEND` in version 2.0.0 of this specification. + +### 3.17. The `CALCMEDLEY` Header + +``` +Required: No +Multi-Valued: No +Syntax: %x6F %x6E / %x6F %x66 %x66 ; on / off +Since: 0.2.0 +``` + +If `MEDLEYSTART` or `MEDLEYEND` (`MEDLEYSTARTBEAT` or `MEDLEYENDBEAT` for versions before 2.0.0) are not specified, the `CALCMEDLEY` header indicates whether an implementation is supposed to determine the start and end of the medley section automatically. + +> [!CAUTION] +> +> The exact semantics of the `CALCMEDLEY` header have not been defined yet. + +### 3.18. The `TITLE` Header ``` Required: Yes @@ -314,17 +435,28 @@ Since: 0.1.0 The `TITLE` header contains the title of the song. -### 3.13. The `ARTIST` Header +### 3.19. The `ARTIST` Header ``` -Required: No +Required: Yes Multi-Valued: No Since: 0.1.0 ``` The `ARTIST` header contains the artist of the song. -### 3.14. The `GENRE` Header +### 3.20. The `YEAR` Header + +``` +Required: No +Multi-Valued: No +Syntax: 4DIGIT +Since: 0.2.0 +``` + +The `YEAR` indicates the year in which the song was released. The value must be a positive integer. + +### 3.21. The `GENRE` Header ``` Required: No @@ -338,7 +470,41 @@ The `GENRE` defines the genre(s) of the song. Individual genre values MUST be co > > Whether genres should be compared case-insensitively or not has not yet been decided. -### 3.15. The `P1` and `P2` Headers +### 3.22. The `LANGUAGE` Header + +``` +Required: No +Multi-Valued: Yes +Since: 0.2.0 +``` + +The `LANGUAGE` header indicates the spoken or sung language(s) of a song. + +### 3.23. The `EDITION` Header + +``` +Required: No +Multi-Valued: Yes +Since: 0.2.0 +``` + +The `EDITION` indicates what edition of games a song belongs to. While this header is intended to hold commercially available editions (e.g. SingStar Pop Hits, GuitarHero Live) implementations MUST NOT reject a file based on the value of this header. A list of SingStar editions is avaliable [here](https://github.com/bohning/usdb_syncer/wiki/SingStar-Editions). For arbitrary keywords see the `TAGS` header. + +### 3.24. The `TAGS` Header + +``` +Required: No +Multi-Valued: Yes +Since: 1.1.0 +``` + +The `TAGS` allow association of any reasonable keyword with a song. Implementations SHOULD compare tags in a case-insensitive manner. + +> [!CAUTION] +> +> Whether tags should be compared case-insensitively or not has not yet been decided. + +### 3.25. The `P1` and `P2` Headers ``` Required: No @@ -348,7 +514,7 @@ Since: 0.2.0 The headers `P1` and `P2` indicate the names of the artists that originally sang the song. `P1` is the name of the singer of first voice and `P2` is the name of the singer of the second voice. Usually `P2` is only included for duets. -### 3.16. The `DUETSINGER1` and `DUETSINGER2` Headers +### 3.26. The `DUETSINGER1` and `DUETSINGER2` Headers ``` Required: No @@ -360,6 +526,57 @@ Removed: 1.0.0 The headers `DUETSINGER1` and `DUETSINGER2` are aliases for `P1` and `P2`. If both are specified `P1` and `P2` take precedence. +### 3.27. The `CREATOR` Header + +``` +Required: No +Multi-Valued: Yes +Since: 0.2.0 +``` + +The `CREATOR` indicates who created the UltraStar version of a song. Values are usually usernames or gamer tags. + +### 3.28. The `PROVIDEDBY` Header + +``` +Required: No +Multi-Valued: No +Since: 1.1.0 +``` + +The `PROVIDEDBY` header indicates the source of a particular UltraStar file. Implementations concerned with providing UltraStar files to many users (sometimes referred to as “hosters”) SHOULD set this value automatically. Values SHOULD be valid URLs according to [RFC 1738](https://datatracker.ietf.org/doc/html/rfc1738) using the HTTP or HTTPS scheme. + +### 3.29. The `COMMENT` Header + +``` +Required: No +Multi-Valued: No +Since: 0.2.0 +``` + +The `COMMENT` header can include arbitrary text. + +### 3.30. The `ENCODING` Header + +``` +Required: No +Multi-Valued: No +Syntax: "UTF-8" / "CP1252" / "CP1250" +Since: 0.2.0 +Deprecated: 0.3.0 +Removed: 1.0.0 +``` + +The `ENCODING` header specifies the encoding used for text values in an UltraStar file. If present implementations MUST apply this encoding to all header values and all note texts. Implementations MAY support additional encodings. Names of encodings are compared in a case-insensitive manner. + +> [!IMPORTANT] +> +> Many implementations only apply the specified encoding to **subsequent** headers and note texts. Although this is technically not spec-compliant it is usually best to put the `ENCODING` header first. + +> [!WARNING] +> +> The use of the `ENCODING` tag is highly discouraged. UltraStar files must always use the UTF-8 encoding. + ## 3. The File Body The body of a file consists of a sequence of notes, end-of-phrase markers, and player changes. From 29c869cda2c504cf792e98a84a5766ad7c0820a2 Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Tue, 30 Jan 2024 19:37:55 +0100 Subject: [PATCH 14/48] Add notes about aliased headers --- spec.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/spec.md b/spec.md index 326e7ad..d29234f 100644 --- a/spec.md +++ b/spec.md @@ -536,6 +536,10 @@ Since: 0.2.0 The `CREATOR` indicates who created the UltraStar version of a song. Values are usually usernames or gamer tags. +> [!NOTE] +> +> Some implementations are known to use an application-specific header `AUTHOR` in place of `CREATOR`. The semantics of the `AUTHOR` header are not part of this specification. + ### 3.28. The `PROVIDEDBY` Header ``` @@ -546,6 +550,10 @@ Since: 1.1.0 The `PROVIDEDBY` header indicates the source of a particular UltraStar file. Implementations concerned with providing UltraStar files to many users (sometimes referred to as “hosters”) SHOULD set this value automatically. Values SHOULD be valid URLs according to [RFC 1738](https://datatracker.ietf.org/doc/html/rfc1738) using the HTTP or HTTPS scheme. +> [!NOTE] +> +> Some implementations are known to use an application-specific header `SOURCE` in place of `PROVIDEDBY`. The semantics of the `SOURCE` header are not part of this specification. + ### 3.29. The `COMMENT` Header ``` From 34add1738d28bd9dad4986423c38d49954d29ab3 Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Tue, 30 Jan 2024 19:49:48 +0100 Subject: [PATCH 15/48] Fix case-sensitivity --- spec.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec.md b/spec.md index d29234f..8a9394e 100644 --- a/spec.md +++ b/spec.md @@ -415,11 +415,11 @@ The `MEDLEYSTARTBEAT` and `MEDLEYENDBEAT` headers indicate in beats the start an ``` Required: No Multi-Valued: No -Syntax: %x6F %x6E / %x6F %x66 %x66 ; on / off +Syntax: "on" / "off" Since: 0.2.0 ``` -If `MEDLEYSTART` or `MEDLEYEND` (`MEDLEYSTARTBEAT` or `MEDLEYENDBEAT` for versions before 2.0.0) are not specified, the `CALCMEDLEY` header indicates whether an implementation is supposed to determine the start and end of the medley section automatically. +If `MEDLEYSTART` or `MEDLEYEND` (`MEDLEYSTARTBEAT` or `MEDLEYENDBEAT` for versions before 2.0.0) are not specified, the `CALCMEDLEY` header indicates whether an implementation is supposed to determine the start and end of the medley section automatically. The value of this header is compared case-insensitively. > [!CAUTION] > From cbc862b1b4d6e9c4aa23ed87649a9cc6d598d638 Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Tue, 30 Jan 2024 21:58:14 +0100 Subject: [PATCH 16/48] Clarify songs with more than 2 voices --- spec.md | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/spec.md b/spec.md index 8a9394e..453d97e 100644 --- a/spec.md +++ b/spec.md @@ -504,7 +504,7 @@ The `TAGS` allow association of any reasonable keyword with a song. Implementati > > Whether tags should be compared case-insensitively or not has not yet been decided. -### 3.25. The `P1` and `P2` Headers +### 3.25. The `P1`, `P2`, … Headers ``` Required: No @@ -512,9 +512,15 @@ Multi-Valued: No Since: 0.2.0 ``` -The headers `P1` and `P2` indicate the names of the artists that originally sang the song. `P1` is the name of the singer of first voice and `P2` is the name of the singer of the second voice. Usually `P2` is only included for duets. +The headers `P1`, `P2`, … indicate the names of the voices of a song. These names correspond to the voices indicated by the `P1`, `P2`, … player changes (see [section 3.3](#33-player-changes)). If the voices correspond to different singers in the original song, the header values often indicate the names of the original singers. -### 3.26. The `DUETSINGER1` and `DUETSINGER2` Headers +The association of header values to voices is defined by the numerical value after each `P` respectively, i.e. the header `P2` indicates the name of the voice whose notes are introduced by the `P2` player change. Leading zeroes are insignificant, i.e. the headers `P1` and `P001` both refer to the same voice. + +> [!CAUTION] +> +> The exact semantics of the `P` headers have not yet been decided. + +### 3.26. The `DUETSINGER1`, `DUETSINGER2`, … Headers ``` Required: No @@ -524,7 +530,7 @@ Deprecated: 0.3.0 Removed: 1.0.0 ``` -The headers `DUETSINGER1` and `DUETSINGER2` are aliases for `P1` and `P2`. If both are specified `P1` and `P2` take precedence. +The headers `DUETSINGER1`, `DUETSINGER2`, etc. are aliases for `P1`, `P2`, etc. If both are specified `P1`, `P2`, etc. take precedence. ### 3.27. The `CREATOR` Header @@ -696,6 +702,12 @@ An end-of-phrase SHOULD NOT appear between the start beat (inclusive) of a note ### 3.3. Player Changes +> [!WARNING] +> +> **Breaking Change** in version 0.2.0 +> +> In version 0.1.0 only single-player songs were defined. Player changes are specified since version 0.2.0. + A player change is indicated by a `P` (the letter P, `%x50`), immediately followed by a number. ```abnf @@ -712,16 +724,12 @@ A player change indicates that all notes and end-of-phrase markers following thi > > A player change does NOT implicitly add an end-of-phrase indicator. +Player changes SHOULD appear in ascending order of `player-number` and there SHOULD be no gaps (i.e. a song having notes for `P1` and `P3`, but not `P2`). The exact `player-number` carries no semantics other than its relative order with other `player-number` and its association with the corresponding header (see [section 3.25](#325-the-p1-and-p2-headers)). In particular a file that uses `P3` and `P5` can be rewritten using `P1` and `P2` with no change in semantics. + > [!TIP] > > An UltraStar file that makes use of player changes is referred to as a “duet”. -> [!WARNING] -> -> **Breaking Change** in version 0.2.0 -> -> In version 0.1.0 only single-player songs were defined. Player changes are specified since version 0.2.0. - > [!Note] > > There exists a legacy behavior where an indicated `P3` would start a sequence of notes that apply to both players. This behavior is explicitly NOT compliant with this specification. @@ -734,6 +742,10 @@ A player change indicates that all notes and end-of-phrase markers following thi > > Whether single-voice songs can have player changes (only `P1`) is not yet decided. +> [!CAUTION] +> +> Whether gaps in `player-number`s are allowed is not yet decided. + > [!CAUTION] > > Whether there may be a whitespace between the `P` and the indicated player is currently open for discussion ([#46](https://github.com/UltraStar-Deluxe/format/issues/46)). From 567a92705ca7bff608c94ee6ae55c343d3997862 Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Tue, 30 Jan 2024 22:09:38 +0100 Subject: [PATCH 17/48] Add relative mode --- spec.md | 49 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/spec.md b/spec.md index 453d97e..070f7e3 100644 --- a/spec.md +++ b/spec.md @@ -591,6 +591,19 @@ The `ENCODING` header specifies the encoding used for text values in an UltraSta > > The use of the `ENCODING` tag is highly discouraged. UltraStar files must always use the UTF-8 encoding. +### 3.31. The `RELATIVE` Header + +``` +Required: No +Multi-Valued: No +Syntax: "yes" / "no" +Since: 0.2.0 +Deprecated: 0.3.0 +Removed: 1.0.0 +``` + +The `RELATIVE` header enables [Relative Mode](#a-relative-mode) (see Appendix A). + ## 3. The File Body The body of a file consists of a sequence of notes, end-of-phrase markers, and player changes. @@ -752,6 +765,38 @@ Player changes SHOULD appear in ascending order of `player-number` and there SHO ## Appendix -### A. Relative mode +### A. Relative Mode + +> [!WARNING] +> +> Relative mode is deprecated and has been removed in version 1.0.0 of this specification. + +Relative mode is a special input mode that affects parsing and interpreting UltraStar files significantly. Relative mode is enabled by the `RELATIVE` header being set to `yes` (case-insensitive). + +### Syntax + +When relative mode is enabled, the syntax of end-of-phrase markers changes: + +```abnf +end-of-phrase = dash + WSP start-beat + WSP rel-offset + *WSP line-break +rel-offset = *DIGIT +``` + +Note that the syntax in relative mode is incompatible with the normal syntax. Implementations MUST NOT try to rectify a missing `RELATIVE` header based on the end-of-phrase markers encountered. + +### Semantics + +In relative mode the semantics of start times changes for notes and end-of-phrase markers. + +- At the start of the body a relative offset `rel` is initialized to the value of the `GAP` header (or `0` if no `GAP` header exists). +- The start times of notes and end-of-phrase markers are relative to the current `rel` value. The absolute start time is calculated as `rel + start-beat`. +- End-of-phrase markers in relative mode include a `rel-offset`. After the start time of the end-of-phrase marker has been interpreted, the `rel-offset` value is added to `rel`. + +> [!IMPORTANT] +> +> In relative mode the order of notes and end-of-phrase markers within a file is significant. -How does player change work in relative mode? +In files with multiple voices each voice has its own `rel` value which is independent of other voices. The `rel` value for a voice does not reset when a player change is encountered. From 03a406ff17724bc8beebf7bc8c0bb1b5390c4f38 Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Tue, 30 Jan 2024 22:12:27 +0100 Subject: [PATCH 18/48] Rename Player change to Voice Change --- spec.md | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/spec.md b/spec.md index 070f7e3..02f1857 100644 --- a/spec.md +++ b/spec.md @@ -512,9 +512,9 @@ Multi-Valued: No Since: 0.2.0 ``` -The headers `P1`, `P2`, … indicate the names of the voices of a song. These names correspond to the voices indicated by the `P1`, `P2`, … player changes (see [section 3.3](#33-player-changes)). If the voices correspond to different singers in the original song, the header values often indicate the names of the original singers. +The headers `P1`, `P2`, … indicate the names of the voices of a song. These names correspond to the voices indicated by the `P1`, `P2`, … voice changes (see [section 3.3](#33-voice-changes)). If the voices correspond to different singers in the original song, the header values often indicate the names of the original singers. -The association of header values to voices is defined by the numerical value after each `P` respectively, i.e. the header `P2` indicates the name of the voice whose notes are introduced by the `P2` player change. Leading zeroes are insignificant, i.e. the headers `P1` and `P001` both refer to the same voice. +The association of header values to voices is defined by the numerical value after each `P` respectively, i.e. the header `P2` indicates the name of the voice whose notes are introduced by the `P2` voice change. Leading zeroes are insignificant, i.e. the headers `P1` and `P001` both refer to the same voice. > [!CAUTION] > @@ -606,12 +606,12 @@ The `RELATIVE` header enables [Relative Mode](#a-relative-mode) (see Appendix A) ## 3. The File Body -The body of a file consists of a sequence of notes, end-of-phrase markers, and player changes. +The body of a file consists of a sequence of notes, end-of-phrase markers, and voice changes. ```abnf body = *( note / end-of-phrase / - player-change / + voice-change / empty-line ) ``` The sequence of notes and end-of-phrase markers SHOULD appear in ascending order by their start beats. @@ -713,55 +713,55 @@ An end-of-phrase SHOULD NOT appear between the start beat (inclusive) of a note > > Whether there can be non-whitespace text following an end-of-phrase indicator is not yet decided. -### 3.3. Player Changes +### 3.3. Voice Changes > [!WARNING] > > **Breaking Change** in version 0.2.0 > -> In version 0.1.0 only single-player songs were defined. Player changes are specified since version 0.2.0. +> In version 0.1.0 only single-voice songs were defined. Voice changes are specified since version 0.2.0. -A player change is indicated by a `P` (the letter P, `%x50`), immediately followed by a number. +A voice change (also referred to as a “player change”) is indicated by a `P` (the letter P, `%x50`), immediately followed by a number. ```abnf -player-change = p player-numer +voice-change = p voice-numer *WSP line-break p = %x50 ; P -player-number = positive-digit *DIGIT +voice-number = positive-digit *DIGIT positive-digit = %x31-39 ; 1-9 ``` -A player change indicates that all notes and end-of-phrase markers following this line belong to the player indicated by the `player-number`. Implementations MAY choose to limit the number of voices. If the body of a song does not start with a player change, `P1` is assumed implicitly. To improve readablility notes for different players should not be interlaced. +A voice change indicates that all notes and end-of-phrase markers following this line belong to the voice indicated by the `voice-number`. Implementations MAY choose to limit the number of voices. If the body of a song does not start with a voice change, `P1` is assumed implicitly. To improve readablility notes for different voices should not be interlaced. > [!NOTE] > -> A player change does NOT implicitly add an end-of-phrase indicator. +> A voice change does NOT implicitly add an end-of-phrase indicator. -Player changes SHOULD appear in ascending order of `player-number` and there SHOULD be no gaps (i.e. a song having notes for `P1` and `P3`, but not `P2`). The exact `player-number` carries no semantics other than its relative order with other `player-number` and its association with the corresponding header (see [section 3.25](#325-the-p1-and-p2-headers)). In particular a file that uses `P3` and `P5` can be rewritten using `P1` and `P2` with no change in semantics. +Voice changes SHOULD appear in ascending order of `voice-number` and there SHOULD be no gaps (i.e. a song having notes for `P1` and `P3`, but not `P2`). The exact `voice-number` carries no semantics other than its relative order with other `voice-number` and its association with the corresponding header (see [section 3.25](#325-the-p1-and-p2-headers)). In particular a file that uses `P3` and `P5` can be rewritten using `P1` and `P2` with no change in semantics. > [!TIP] > -> An UltraStar file that makes use of player changes is referred to as a “duet”. +> An UltraStar file that makes use of voice changes is referred to as a “duet”. > [!Note] > -> There exists a legacy behavior where an indicated `P3` would start a sequence of notes that apply to both players. This behavior is explicitly NOT compliant with this specification. +> There exists a legacy behavior where an indicated `P3` would start a sequence of notes that apply to both voices. This behavior is explicitly NOT compliant with this specification. > [!CAUTION] > -> Whether songs that make use of player changes need to start their body with a player change is not yet decided. +> Whether songs that make use of voice changes need to start their body with a voice change is not yet decided. > [!CAUTION] > -> Whether single-voice songs can have player changes (only `P1`) is not yet decided. +> Whether single-voice songs can have voice changes (only `P1`) is not yet decided. > [!CAUTION] > -> Whether gaps in `player-number`s are allowed is not yet decided. +> Whether gaps in `voice-number`s are allowed is not yet decided. > [!CAUTION] > -> Whether there may be a whitespace between the `P` and the indicated player is currently open for discussion ([#46](https://github.com/UltraStar-Deluxe/format/issues/46)). +> Whether there may be a whitespace between the `P` and the indicated voice is currently open for discussion ([#46](https://github.com/UltraStar-Deluxe/format/issues/46)). ## Appendix @@ -799,4 +799,4 @@ In relative mode the semantics of start times changes for notes and end-of-phras > > In relative mode the order of notes and end-of-phrase markers within a file is significant. -In files with multiple voices each voice has its own `rel` value which is independent of other voices. The `rel` value for a voice does not reset when a player change is encountered. +In files with multiple voices each voice has its own `rel` value which is independent of other voices. The `rel` value for a voice does not reset when a voice change is encountered. From 07a8d47717116f9b3a053171b846eca7cdb10726 Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Tue, 30 Jan 2024 22:22:12 +0100 Subject: [PATCH 19/48] Improve wording for multi-value headers --- spec.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/spec.md b/spec.md index 02f1857..993c680 100644 --- a/spec.md +++ b/spec.md @@ -128,9 +128,11 @@ The following sections describe the standardized headers that have been defined. ### 3.1. Single-Valued and Multi-Valued Headers -Headers can be single-valued or multi-valued. Single-valued headers can only be specified once and can only contain a single value. For the sake of robustness implementations SHOULD ignore multiple occurrences of single-valued headers (the selected header value is implementation specific in this case). +Headers can be single-valued or multi-valued. Single-valued headers can only be specified once and can only contain a single value. For the sake of robustness implementations SHOULD ignore multiple occurrences of single-valued headers (which value is chosen in such a case is an implementation detail). -Multi-valued headers can contain multiple values separated by a comma (`%x2C`). Additionally multiple occurrences of a multi-valued header are semantically equivalent to a single occurrence where all values are concatenated by a comma. In this way the order of multi-valued headers is significant. +Multi-valued headers can contain multiple values separated by a comma (`%x2C`). Additionally multiple occurrences of a multi-valued header are semantically equivalent to a single occurrence where all values are concatenated by commas in order of occurrence. In this way the order of multi-valued headers is significant. + +Empty values within a multi-valued header can be removed without changing sematics. > [!WARNING] > From f2151c414554967c8f1f1872d7d10bf360c70cd8 Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Tue, 30 Jan 2024 22:48:00 +0100 Subject: [PATCH 20/48] Fix grammar, typos, and punctuation --- spec.md | 62 +++++++++++++++++++++++++++------------------------------ 1 file changed, 29 insertions(+), 33 deletions(-) diff --git a/spec.md b/spec.md index 993c680..5a4ccb4 100644 --- a/spec.md +++ b/spec.md @@ -14,13 +14,13 @@ GitHub Issues are preferred for discussion of this specification. Alternatively, ## 1. Introduction -The UltraStar file format provides a standardized representation of karaoke songs. The format has been used for a long time by numerous karaoke games such as [UltraStar Deluxe](https://github.com/UltraStar-Deluxe/USDX), [Performous](https://github.com/performous/performous), or [Vocaluxe](https://github.com/Vocaluxe/Vocaluxe). There exists an ecosystem of supporting applications for hosting, editing, and managing songs. However due to the lack of an official file format specification implementations differ and new features cannot be added in a consistent manner. This document aims to fix this problem by providing a formal specification for the syntax and semantics of the UltraStar file format. +The UltraStar file format provides a standardized representation of karaoke songs. The format has been used for a long time by numerous karaoke games such as [UltraStar Deluxe](https://github.com/UltraStar-Deluxe/USDX), [Performous](https://github.com/performous/performous), or [Vocaluxe](https://github.com/Vocaluxe/Vocaluxe). There exists an ecosystem of supporting applications for hosting, editing, and managing songs. However, due to the lack of an official file format specification implementations differ and new features cannot be added consistently. This document aims to fix this problem by providing a formal specification for the syntax and semantics of the UltraStar file format. The UltraStar file format is designed to be edited by machines and humans alike and is intended to be easily understood and edited by technical and non-technical users. This guiding principle is influential for many decisions made during the design process. ### 1.1. Conventions in this Document -The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119](https://datatracker.ietf.org/doc/html/rfc2119). +The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119](https://datatracker.ietf.org/doc/html/rfc2119). The grammatical rules in this document are to be interpreted as described in [RFC 5234](https://datatracker.ietf.org/doc/html/rfc5234). We are using the following core rules: @@ -75,7 +75,7 @@ Implementations SHOULD use a single Line Feed (`%x0A`) as line terminator. Imple > [!CAUTION] > -> Whether empty lines are allowed or not is currently open for discussion ([#43](https://github.com/UltraStar-Deluxe/format/issues/43)). Whether a line that consists only of whitespace is recognized as an empty line is not yet decided. +> Whether empty lines are allowed or not is currently open for discussion ([#43](https://github.com/UltraStar-Deluxe/format/issues/43)). Whether a line that consists only of whitespace is recognized as an empty line has not been decided yet. Whitespace is used as a separator in many places of the format. Only space (`%x20`) and horizontal tab (`%x09`) are recognized as whitespace characters. In particular other unicode characters with the property `White_Space=yes` MUST NOT be treated as whitespace characters in the context of this specification. @@ -124,15 +124,15 @@ Implementations MAY define application-specific headers but SHOULD prefix those > > Handling of application-specific headers has not been decided yet. -The following sections describe the standardized headers that have been defined. If a syntax for a header is specified it applies to the `single-value`. If no syntax is specified any valid `single-value` is valid. Some headers are marked as deprecated or removed from a certain version onward. Implementations MUST continue to apply the defined semantics to a headers if it has been deprecated in the file format version indicated by the file. Implementations MUST NOT apply semantics to a header if a file indicates a version where the header has been removed. +The following sections describe the standardized headers that have been defined. If a syntax for a header is specified it applies to the `single-value`. If no syntax is specified any valid `single-value` is valid. Some headers are marked as deprecated or removed from a certain version onward. Implementations MUST continue to apply the defined semantics to a header if it has been deprecated in the file format version indicated by the file. Implementations MUST NOT apply semantics to a header if a file indicates a version where the header has been removed. ### 3.1. Single-Valued and Multi-Valued Headers Headers can be single-valued or multi-valued. Single-valued headers can only be specified once and can only contain a single value. For the sake of robustness implementations SHOULD ignore multiple occurrences of single-valued headers (which value is chosen in such a case is an implementation detail). -Multi-valued headers can contain multiple values separated by a comma (`%x2C`). Additionally multiple occurrences of a multi-valued header are semantically equivalent to a single occurrence where all values are concatenated by commas in order of occurrence. In this way the order of multi-valued headers is significant. +Multi-valued headers can contain multiple values separated by a comma (`%x2C`). Additionally, multiple occurrences of a multi-valued header are semantically equivalent to a single occurrence where all values are concatenated by commas in order of occurrence. In this way the order of multi-valued headers is significant. -Empty values within a multi-valued header can be removed without changing sematics. +Empty values within a multi-valued header can be removed without changing semantics. > [!WARNING] > @@ -156,7 +156,7 @@ Some headers reference other files, most notably `AUDIO`, `VIDEO`, `COVER`, and > [!CAUTION] > -> Whether absolute paths are allowed or not has not been decided yet. +> Whether absolute paths are allowed or not hasn't been decided yet. > [!IMPORTANT] > @@ -262,7 +262,7 @@ Multi-Valued: No Since: 1.1.0 ``` -The `VOCALS` and `INSTRUMENTAL` header contain file references to audio files. These files contain the acapella and instrumental versions of the song respectively. Implementations MAY use these instead of `AUDIO` to give users the option of changing the volume of vocal and instrumental tracks separately. +The `VOCALS` and `INSTRUMENTAL` header contain file references to audio files. These files contain the a cappella and instrumental versions of the song respectively. Implementations MAY use these instead of `AUDIO` to give users the option of changing the volume of vocal and instrumental tracks separately. > [!CAUTION] > @@ -300,10 +300,6 @@ Since: 0.2.0 The `VIDEOGAP` header indicates an amount of time in milliseconds that the background video will be delayed relative to the audio of a song. The `VIDEOGAP` value is an integer. -> [!NOTE] -> -> - > [!WARNING] > > **Breaking Change** in version 2.0.0 @@ -466,11 +462,11 @@ Multi-Valued: Yes Since: 0.2.0 ``` -The `GENRE` defines the genre(s) of the song. Individual genre values MUST be compared case-insensitively. For consistency it is usually best to capitalize genres. +The `GENRE` defines the genre(s) of the song. Individual genre values MUST be compared case-insensitively. For consistency, it is usually best to capitalize genres. > [!CAUTION] > -> Whether genres should be compared case-insensitively or not has not yet been decided. +> Whether genres should be compared case-insensitively or not hasn't been decided yet. ### 3.22. The `LANGUAGE` Header @@ -490,7 +486,7 @@ Multi-Valued: Yes Since: 0.2.0 ``` -The `EDITION` indicates what edition of games a song belongs to. While this header is intended to hold commercially available editions (e.g. SingStar Pop Hits, GuitarHero Live) implementations MUST NOT reject a file based on the value of this header. A list of SingStar editions is avaliable [here](https://github.com/bohning/usdb_syncer/wiki/SingStar-Editions). For arbitrary keywords see the `TAGS` header. +The `EDITION` indicates what edition of games a song belongs to. While this header is intended to hold commercially available editions (e.g. SingStar Pop Hits, GuitarHero Live) implementations MUST NOT reject a file based on the value of this header. A list of SingStar editions is available [here](https://github.com/bohning/usdb_syncer/wiki/SingStar-Editions). For arbitrary keywords see the `TAGS` header. ### 3.24. The `TAGS` Header @@ -504,7 +500,7 @@ The `TAGS` allow association of any reasonable keyword with a song. Implementati > [!CAUTION] > -> Whether tags should be compared case-insensitively or not has not yet been decided. +> Whether tags should be compared case-insensitively or not hasn't been decided yet. ### 3.25. The `P1`, `P2`, … Headers @@ -520,7 +516,7 @@ The association of header values to voices is defined by the numerical value aft > [!CAUTION] > -> The exact semantics of the `P` headers have not yet been decided. +> The exact semantics of the `P` headers have not been decided yet. ### 3.26. The `DUETSINGER1`, `DUETSINGER2`, … Headers @@ -532,7 +528,7 @@ Deprecated: 0.3.0 Removed: 1.0.0 ``` -The headers `DUETSINGER1`, `DUETSINGER2`, etc. are aliases for `P1`, `P2`, etc. If both are specified `P1`, `P2`, etc. take precedence. +The headers `DUETSINGER1`, `DUETSINGER2`, etc. are aliases for `P1`, `P2`, etc. If both are specified `P1`, `P2`, etc. take precedence. ### 3.27. The `CREATOR` Header @@ -556,7 +552,7 @@ Multi-Valued: No Since: 1.1.0 ``` -The `PROVIDEDBY` header indicates the source of a particular UltraStar file. Implementations concerned with providing UltraStar files to many users (sometimes referred to as “hosters”) SHOULD set this value automatically. Values SHOULD be valid URLs according to [RFC 1738](https://datatracker.ietf.org/doc/html/rfc1738) using the HTTP or HTTPS scheme. +The `PROVIDEDBY` header indicates the source of a particular UltraStar file. Implementations concerned with providing UltraStar files to many users (sometimes referred to as "hosters") SHOULD set this value automatically. Values SHOULD be valid URLs according to [RFC 1738](https://datatracker.ietf.org/doc/html/rfc1738) using the HTTP or HTTPS scheme. > [!NOTE] > @@ -620,7 +616,7 @@ The sequence of notes and end-of-phrase markers SHOULD appear in ascending order > [!CAUTION] > -> Whether the body of a file must or may be sorted is not yet decided. +> Whether the body of a file must or may be sorted is not decided yet. ### 3.1. Notes @@ -645,7 +641,7 @@ minus = %x2D ; - > [!CAUTION] > -> Whether only a single or multiple whitespaces in a row are allowed is currently up for discussion ([#46](https://github.com/UltraStar-Deluxe/format/issues/46)). +> Whether only a single or multiple whitespace character in a row are allowed is currently up for discussion ([#46](https://github.com/UltraStar-Deluxe/format/issues/46)). The note type indicates how singing the correct or wrong note should affect scoring. The following sections define standard note types. Implementations MAY substitute unknown note types with freestyle notes (`F`). Implementations MUST NOT attach semantics to note types not covered by this specification. @@ -653,21 +649,21 @@ The start beat and duration define the time when a note appears in a song. Both > [!CAUTION] > -> Whether and how applications may define custom note types is not yet decided. +> Whether and how applications may define custom note types hasn't been decided yet. > [!CAUTION] > -> Whether negative note starts and/or durations are valid is not yet decided. +> Whether negative note starts and/or durations are valid is, hasn't been decided yet. The pitch of a note is encoded as the number of half-steps relative to middle C or C4. So a pitch of `5` represent an F4 and a pitch of `-2` represents an A#3. #### 3.1.1. Regular Notes `:` -A regular note is indicated by the note type `:` (colon, `%x3A`). A regular note indicates that a certail pitch is to be held for a certain duration. Game implementations MAY decide to compare pitches independently of the octave (i.e. compare pitches module 12). +A regular note is indicated by the note type `:` (colon, `%x3A`). A regular note indicates that a certain pitch is to be held for a certain duration. Game implementations MAY decide to compare pitches independently of the octave (i.e. compare pitches module 12). #### 3.1.2. Golden Notes `*` -A golden note is indicated by the note type `*` (asterist, `%x2A`). Golden note have the same semantics as regular notes. However, during scoring game implementations SHOULD award more points for golden notes. The exact scoring behavior is an implementation detail. +A golden note is indicated by the note type `*` (asterisk, `%x2A`). Golden note have the same semantics as regular notes. However, during scoring game implementations SHOULD award more points for golden notes. The exact scoring behavior is an implementation detail. #### 3.1.3. Rap Notes `R` @@ -691,7 +687,7 @@ A golden rap note is indicated by the note type `G` (the letter G, `%x47`). Gold > > Freestyle notes are standardized in version 0.2.0 of this specification. -A freestyle note is indicated by the note type `F` (the letter F, `%x46`). Similar to rap notes, freestyle notes do not carry pitch information. Additionally game implementations MUST NOT award points for freestyle notes. +A freestyle note is indicated by the note type `F` (the letter F, `%x46`). Similar to rap notes, freestyle notes do not carry pitch information. Additionally, game implementations MUST NOT award points for freestyle notes. ### 3.2. End-of-Phrase Markers @@ -713,7 +709,7 @@ An end-of-phrase SHOULD NOT appear between the start beat (inclusive) of a note > [!CAUTION] > -> Whether there can be non-whitespace text following an end-of-phrase indicator is not yet decided. +> Whether there can be non-whitespace text following an end-of-phrase indicator has not been decided yet. ### 3.3. Voice Changes @@ -733,7 +729,7 @@ voice-number = positive-digit *DIGIT positive-digit = %x31-39 ; 1-9 ``` -A voice change indicates that all notes and end-of-phrase markers following this line belong to the voice indicated by the `voice-number`. Implementations MAY choose to limit the number of voices. If the body of a song does not start with a voice change, `P1` is assumed implicitly. To improve readablility notes for different voices should not be interlaced. +A voice change indicates that all notes and end-of-phrase markers following this line belong to the voice indicated by the `voice-number`. Implementations MAY choose to limit the number of voices. If the body of a song does not start with a voice change, `P1` is assumed implicitly. To improve readability notes for different voices should not be interlaced. > [!NOTE] > @@ -745,21 +741,21 @@ Voice changes SHOULD appear in ascending order of `voice-number` and there SHOUL > > An UltraStar file that makes use of voice changes is referred to as a “duet”. -> [!Note] +> [!NOTE] > > There exists a legacy behavior where an indicated `P3` would start a sequence of notes that apply to both voices. This behavior is explicitly NOT compliant with this specification. > [!CAUTION] > -> Whether songs that make use of voice changes need to start their body with a voice change is not yet decided. +> Whether songs that make use of voice changes need to start their body with a voice change has not been decided yet. > [!CAUTION] > -> Whether single-voice songs can have voice changes (only `P1`) is not yet decided. +> Whether single-voice songs can have voice changes (only `P1`) has not been decided yet. > [!CAUTION] > -> Whether gaps in `voice-number`s are allowed is not yet decided. +> Whether gaps in `voice-number`s are allowed has not been decided yet. > [!CAUTION] > @@ -791,7 +787,7 @@ Note that the syntax in relative mode is incompatible with the normal syntax. Im ### Semantics -In relative mode the semantics of start times changes for notes and end-of-phrase markers. +In relative mode the semantics of start times changes for notes and end-of-phrase markers. - At the start of the body a relative offset `rel` is initialized to the value of the `GAP` header (or `0` if no `GAP` header exists). - The start times of notes and end-of-phrase markers are relative to the current `rel` value. The absolute start time is calculated as `rel + start-beat`. From 14f037f8e19cff9808c4836d5afb980f93c89614 Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Wed, 31 Jan 2024 10:11:21 +0100 Subject: [PATCH 21/48] Clarify whitespace handling in headers --- spec.md | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/spec.md b/spec.md index 5a4ccb4..bcd572b 100644 --- a/spec.md +++ b/spec.md @@ -98,25 +98,27 @@ The header of an UltraStar file consists of a sequence of key-value pairs. Each ```abnf file-header = *( header / empty-line ) header = hash *WSP header-key *WSP colon *WSP header-value *WSP line-break -header-key = header-key-char - [ *( HTAB / SP / header-key-char ) - header-key-char ] +header-key = header-char + [ *( WSP / header-char ) + header-char ] header-value = single-value / multi-value multi-value = single-value [ comma single-value ] [ comma ] +single-value = *( header-char / colon ) -single-value = *( %x20-10FFFF ) -header-key-char = %x21-3A / %x3B-10FFFF ; does not include space, tab, or colon - -hash = %x23 ; # -colon = %x3A ; : -comma = %x2C ; , +header-char = %x00-09 / ; exclude line feed + %x0B-0C / ; exclude carriage return + %x0E-39 / ; exclude colon + %x3B-10FFFF +hash = %x23 ; # +colon = %x3A ; : +comma = %x2C ; , ``` > [!CAUTION] > > The use of trailing commas in comma-separated header lists has not been decided yet. -Comparisons of header keys is case-insensitive. For the sake of consistency header keys SHOULD use only capital letters. Header values are generally case-sensitive unless otherwise specified. An empty value is equivalent to the header being absent. Header values may not exceed 255 characters. +Comparisons of header keys is case-insensitive. For the sake of consistency header keys SHOULD use only capital letters. Header values are generally case-sensitive unless otherwise specified. An empty value is equivalent to the header being absent. Implementations MAY remove leading and trailing whitespace in header keys and values without changing semantics. Header values may not exceed 255 characters. Implementations MAY define application-specific headers but SHOULD prefix those headers with the application name to avoid conflicts with future standardized headers. Implementations MUST ignore headers they do not recognize. The order of headers is irrelevant (note the exception in section 3.1.) although standardized headers should precede any application-specific headers. @@ -776,10 +778,10 @@ Relative mode is a special input mode that affects parsing and interpreting Ultr When relative mode is enabled, the syntax of end-of-phrase markers changes: ```abnf -end-of-phrase = dash - WSP start-beat - WSP rel-offset - *WSP line-break +end-of-phrase =/ dash + WSP start-beat + WSP rel-offset + *WSP line-break rel-offset = *DIGIT ``` From e9bf617c0905295aee8a47ee2d3e99611bcdc39a Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Wed, 31 Jan 2024 15:44:16 +0100 Subject: [PATCH 22/48] Add Terminology, small fixes --- spec.md | 45 ++++++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/spec.md b/spec.md index bcd572b..2747aa3 100644 --- a/spec.md +++ b/spec.md @@ -33,32 +33,42 @@ HTAB = %x09 ; horizontal tab SP = %x20 ; space ``` +### 1.2. Terminology +The following terminology is used throughout this document: + +**Song**: A song refers to a file in the UltraStar file format. In some contexts **song** can refer to linked media files as well. In those cases **textfile** is used to disambiguate individual files. + +**Medley**: A medley is a short, recognizable excerpt from a song. Many games include a designated medley mode. + +> [!CAUTION] +> +> The exact terminology has not been decided yet. ## 2. General Structure -UltraStar files are plain text files. The UTF-8 encoding MUST be used. Implementations MUST NOT add a byte order mark to the beginning of a file. In the interests of interoperability, implementations MAY ignore the presence of a byte order mark rather than treating it as an error. +Songs are plain text files. The UTF-8 encoding MUST be used. Implementations MUST NOT add a byte order mark to the beginning of a file. In the interests of interoperability, implementations MAY ignore the presence of a byte order mark rather than treating it as an error. > [!CAUTION] > > Whether files with a BOM may be accepted is an open discussion ([#46](https://github.com/UltraStar-Deluxe/format/issues/46)). -The canonical file extension for the UltraStar file format is `.txt`. +The canonical file extension for textfiles is `.txt`. -UltraStar files consist of a header and a body. The header contains metadata about the song and the file. The body contains the musical data. A file SHOULD end with an `E` on a single line. Everything after a trailing `E` MUST be ignored. +Songs consist of a header and a body. The header contains metadata about the song. The body contains the musical data. A file SHOULD end with an `E` on a single line. Everything after a trailing `E` MUST be ignored. > [!CAUTION] > > Whether the trailing `E` is optional or not is open for discussion ([#44](https://github.com/UltraStar-Deluxe/format/issues/44)). ```abnf -UltraStar-file = file-header - file-body - [ %x45 *char ] ; E -char = %x00-10FFFF +song = file-header + file-body + [ %x45 *char ] ; E +char = %x00-10FFFF ``` -### 2.1. Line Endings and White Space +### 2.1. Line Endings and Whitespace Both the header and the body of a file are defined in terms of lines. A line is a string of text that is terminated with an end-of-line sequence. @@ -89,7 +99,7 @@ WSP = ( SP / HTAB ) ## 2. The File Header -The header of an UltraStar file consists of a sequence of key-value pairs. Each line in the header section starts with a hash. The key and value of a header are separated by a colon. Whitespace around key and value is ignored. +The header of a song consists of a sequence of key-value pairs. Each line in the header section starts with a hash. The key and value of a header are separated by a colon. Whitespace around key and value is ignored. > [!CAUTION] > @@ -112,6 +122,7 @@ header-char = %x00-09 / ; exclude line feed hash = %x23 ; # colon = %x3A ; : comma = %x2C ; , +period = %x2E ; . ``` > [!CAUTION] @@ -154,7 +165,7 @@ Empty values within a multi-valued header can be removed without changing semant ### 3.2. File References -Some headers reference other files, most notably `AUDIO`, `VIDEO`, `COVER`, and `BACKGROUND`. These file references are always relative to the UltraStar file from which they are referenced. As a security measure file references MUST NOT use absolute paths. Implementations SHOULD refuse to load absolutely referenced files. +Some headers reference other files, most notably `AUDIO`, `VIDEO`, `COVER`, and `BACKGROUND`. These file references are always relative to the textfile from which they are referenced. As a security measure file references MUST NOT use absolute paths. Implementations SHOULD refuse to load absolutely referenced files. > [!CAUTION] > @@ -184,7 +195,7 @@ The `VERSION` header SHOULD be the first header in a file. ``` Required: Yes Multi-Valued: No -Syntax: 1*DIGIT +Syntax: 1*DIGIT [ period 1*DIGIT ] Since: 0.1.0 ``` @@ -540,7 +551,7 @@ Multi-Valued: Yes Since: 0.2.0 ``` -The `CREATOR` indicates who created the UltraStar version of a song. Values are usually usernames or gamer tags. +The `CREATOR` indicates who created the textfile. Values are usually usernames or gamer tags. > [!NOTE] > @@ -554,7 +565,7 @@ Multi-Valued: No Since: 1.1.0 ``` -The `PROVIDEDBY` header indicates the source of a particular UltraStar file. Implementations concerned with providing UltraStar files to many users (sometimes referred to as "hosters") SHOULD set this value automatically. Values SHOULD be valid URLs according to [RFC 1738](https://datatracker.ietf.org/doc/html/rfc1738) using the HTTP or HTTPS scheme. +The `PROVIDEDBY` header indicates the source of a particular textfile. Implementations concerned with providing textfiles to many users (sometimes referred to as "hosters") SHOULD set this value automatically. Values SHOULD be valid URLs according to [RFC 1738](https://datatracker.ietf.org/doc/html/rfc1738) using the HTTP or HTTPS scheme. > [!NOTE] > @@ -581,7 +592,7 @@ Deprecated: 0.3.0 Removed: 1.0.0 ``` -The `ENCODING` header specifies the encoding used for text values in an UltraStar file. If present implementations MUST apply this encoding to all header values and all note texts. Implementations MAY support additional encodings. Names of encodings are compared in a case-insensitive manner. +The `ENCODING` header specifies the encoding used for text values in a textfile. If present implementations MUST apply this encoding to all header values and all note texts. Implementations MAY support additional encodings. Names of encodings are compared in a case-insensitive manner. > [!IMPORTANT] > @@ -589,7 +600,7 @@ The `ENCODING` header specifies the encoding used for text values in an UltraSta > [!WARNING] > -> The use of the `ENCODING` tag is highly discouraged. UltraStar files must always use the UTF-8 encoding. +> The use of the `ENCODING` tag is highly discouraged. Songs must always use the UTF-8 encoding. ### 3.31. The `RELATIVE` Header @@ -741,7 +752,7 @@ Voice changes SHOULD appear in ascending order of `voice-number` and there SHOUL > [!TIP] > -> An UltraStar file that makes use of voice changes is referred to as a “duet”. +> A song that makes use of voice changes is referred to as a “duet”. > [!NOTE] > @@ -771,7 +782,7 @@ Voice changes SHOULD appear in ascending order of `voice-number` and there SHOUL > > Relative mode is deprecated and has been removed in version 1.0.0 of this specification. -Relative mode is a special input mode that affects parsing and interpreting UltraStar files significantly. Relative mode is enabled by the `RELATIVE` header being set to `yes` (case-insensitive). +Relative mode is a special input mode that affects parsing and interpreting songs significantly. Relative mode is enabled by the `RELATIVE` header being set to `yes` (case-insensitive). ### Syntax From bf964ef9c28c615af8c942ad770f8652c91fe476 Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Wed, 31 Jan 2024 15:45:47 +0100 Subject: [PATCH 23/48] Remove #RESOLUTION header --- spec.md | 56 +++++++++++++++++++------------------------------------- 1 file changed, 19 insertions(+), 37 deletions(-) diff --git a/spec.md b/spec.md index 2747aa3..6af33a5 100644 --- a/spec.md +++ b/spec.md @@ -336,25 +336,7 @@ The `NOTESGAP` header is deprecated and MUST NOT be used. Implementations MUST i > > The `NOTESGAP` header was defined in version 0.1.0 But its semantics were never fully specified. -### 3.12. The `RESOLUTION` Header - -``` -Required: No -Multi-Valued: No -Since: 0.2.0 -Deprecated: 0.3.0 -Removed: 1.0.0 -``` - -The `RESOLUTION` header is used by [UltraStar Deluxe](https://github.com/UltraStar-Deluxe/USDX) exclusively to change the resolution of the built-in song editor. - -> [!WARNING] -> -> **Breaking Change** in version 1.0.0 -> -> The `RESOLUTION` header was removed in version 1.0.0 of this specification. - -### 3.13. The `START` and `END` Headers +### 3.12. The `START` and `END` Headers ``` Required: No @@ -375,7 +357,7 @@ The `START` and `END` header specify two time points in milliseconds relative to > > In versions 0.x and 1.x `START` was specified in seconds as a floating point number. Version 2.0.0 changes this to an integer and milliseconds. -### 3.14. The `PREVIEWSTART` Header +### 3.13. The `PREVIEWSTART` Header ``` Required: No @@ -392,7 +374,7 @@ The `PREVIEWSTART` header indicates a time offset in milliseconds relative to th > > In versions 0.x and 1.x `PREVIEWSTART` was specified in seconds as a floating point number. Version 2.0.0 of this specification changes this to an integer and milliseconds. -### 3.15. The `MEDLEYSTART` and `MEDLEYEND` Headers +### 3.14. The `MEDLEYSTART` and `MEDLEYEND` Headers ``` Required: No @@ -403,7 +385,7 @@ Since: 2.0.0 The `MEDLEYSTART` and `MEDLEYEND` headers indicate in milliseconds the start and end of the medley section of a song relative to the start of the audio. These tags replace `MEDLEYSTARTBEAT` and `MEDLEYENDBEAT` in version 2.0.0 of this specification. -### 3.16. The `MEDLEYSTARTBEAT` and `MEDLEYENDBEAT` Headers +### 3.15. The `MEDLEYSTARTBEAT` and `MEDLEYENDBEAT` Headers ``` Required: No @@ -421,7 +403,7 @@ The `MEDLEYSTARTBEAT` and `MEDLEYENDBEAT` headers indicate in beats the start an > > The headers `MEDLEYSTARTBEAT` and `MEDLEYENDBEAT` have been replaced by `MEDLEYSTART` and `MEDLEYEND` in version 2.0.0 of this specification. -### 3.17. The `CALCMEDLEY` Header +### 3.16. The `CALCMEDLEY` Header ``` Required: No @@ -436,7 +418,7 @@ If `MEDLEYSTART` or `MEDLEYEND` (`MEDLEYSTARTBEAT` or `MEDLEYENDBEAT` for versio > > The exact semantics of the `CALCMEDLEY` header have not been defined yet. -### 3.18. The `TITLE` Header +### 3.17. The `TITLE` Header ``` Required: Yes @@ -446,7 +428,7 @@ Since: 0.1.0 The `TITLE` header contains the title of the song. -### 3.19. The `ARTIST` Header +### 3.18. The `ARTIST` Header ``` Required: Yes @@ -456,7 +438,7 @@ Since: 0.1.0 The `ARTIST` header contains the artist of the song. -### 3.20. The `YEAR` Header +### 3.19. The `YEAR` Header ``` Required: No @@ -467,7 +449,7 @@ Since: 0.2.0 The `YEAR` indicates the year in which the song was released. The value must be a positive integer. -### 3.21. The `GENRE` Header +### 3.20. The `GENRE` Header ``` Required: No @@ -481,7 +463,7 @@ The `GENRE` defines the genre(s) of the song. Individual genre values MUST be co > > Whether genres should be compared case-insensitively or not hasn't been decided yet. -### 3.22. The `LANGUAGE` Header +### 3.21. The `LANGUAGE` Header ``` Required: No @@ -491,7 +473,7 @@ Since: 0.2.0 The `LANGUAGE` header indicates the spoken or sung language(s) of a song. -### 3.23. The `EDITION` Header +### 3.22. The `EDITION` Header ``` Required: No @@ -501,7 +483,7 @@ Since: 0.2.0 The `EDITION` indicates what edition of games a song belongs to. While this header is intended to hold commercially available editions (e.g. SingStar Pop Hits, GuitarHero Live) implementations MUST NOT reject a file based on the value of this header. A list of SingStar editions is available [here](https://github.com/bohning/usdb_syncer/wiki/SingStar-Editions). For arbitrary keywords see the `TAGS` header. -### 3.24. The `TAGS` Header +### 3.23. The `TAGS` Header ``` Required: No @@ -515,7 +497,7 @@ The `TAGS` allow association of any reasonable keyword with a song. Implementati > > Whether tags should be compared case-insensitively or not hasn't been decided yet. -### 3.25. The `P1`, `P2`, … Headers +### 3.24. The `P1`, `P2`, … Headers ``` Required: No @@ -531,7 +513,7 @@ The association of header values to voices is defined by the numerical value aft > > The exact semantics of the `P` headers have not been decided yet. -### 3.26. The `DUETSINGER1`, `DUETSINGER2`, … Headers +### 3.25. The `DUETSINGER1`, `DUETSINGER2`, … Headers ``` Required: No @@ -543,7 +525,7 @@ Removed: 1.0.0 The headers `DUETSINGER1`, `DUETSINGER2`, etc. are aliases for `P1`, `P2`, etc. If both are specified `P1`, `P2`, etc. take precedence. -### 3.27. The `CREATOR` Header +### 3.26. The `CREATOR` Header ``` Required: No @@ -557,7 +539,7 @@ The `CREATOR` indicates who created the textfile. Values are usually usernames o > > Some implementations are known to use an application-specific header `AUTHOR` in place of `CREATOR`. The semantics of the `AUTHOR` header are not part of this specification. -### 3.28. The `PROVIDEDBY` Header +### 3.27. The `PROVIDEDBY` Header ``` Required: No @@ -571,7 +553,7 @@ The `PROVIDEDBY` header indicates the source of a particular textfile. Implement > > Some implementations are known to use an application-specific header `SOURCE` in place of `PROVIDEDBY`. The semantics of the `SOURCE` header are not part of this specification. -### 3.29. The `COMMENT` Header +### 3.28. The `COMMENT` Header ``` Required: No @@ -581,7 +563,7 @@ Since: 0.2.0 The `COMMENT` header can include arbitrary text. -### 3.30. The `ENCODING` Header +### 3.29. The `ENCODING` Header ``` Required: No @@ -602,7 +584,7 @@ The `ENCODING` header specifies the encoding used for text values in a textfile. > > The use of the `ENCODING` tag is highly discouraged. Songs must always use the UTF-8 encoding. -### 3.31. The `RELATIVE` Header +### 3.30. The `RELATIVE` Header ``` Required: No From 678fc27b4f5939daef9d7e32a413d2dde079334d Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Wed, 31 Jan 2024 16:04:12 +0100 Subject: [PATCH 24/48] Add semantic line breaks --- spec.md | 306 +++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 227 insertions(+), 79 deletions(-) diff --git a/spec.md b/spec.md index 6af33a5..060033f 100644 --- a/spec.md +++ b/spec.md @@ -8,21 +8,30 @@ This document aims to describe the UltraStar File Format in its most recent vers > [!IMPORTANT] > -> This document is currently a work-in-progress. Parts of the final specification may change significantly from the current state of this document. +> This document is currently a work-in-progress. +> Parts of the final specification may change significantly from the current state of this document. -GitHub Issues are preferred for discussion of this specification. Alternatively, you can discuss comments on our Discord server. +GitHub Issues are preferred for discussion of this specification. +Alternatively, you can discuss comments on our Discord server. ## 1. Introduction -The UltraStar file format provides a standardized representation of karaoke songs. The format has been used for a long time by numerous karaoke games such as [UltraStar Deluxe](https://github.com/UltraStar-Deluxe/USDX), [Performous](https://github.com/performous/performous), or [Vocaluxe](https://github.com/Vocaluxe/Vocaluxe). There exists an ecosystem of supporting applications for hosting, editing, and managing songs. However, due to the lack of an official file format specification implementations differ and new features cannot be added consistently. This document aims to fix this problem by providing a formal specification for the syntax and semantics of the UltraStar file format. +The UltraStar file format provides a standardized representation of karaoke songs. +The format has been used for a long time by numerous karaoke games such as [UltraStar Deluxe](https://github.com/UltraStar-Deluxe/USDX), [Performous](https://github.com/performous/performous), or [Vocaluxe](https://github.com/Vocaluxe/Vocaluxe). +There exists an ecosystem of supporting applications for hosting, editing, and managing songs. +However, due to the lack of an official file format specification implementations differ and new features cannot be added consistently. +This document aims to fix this problem by providing a formal specification for the syntax and semantics of the UltraStar file format. -The UltraStar file format is designed to be edited by machines and humans alike and is intended to be easily understood and edited by technical and non-technical users. This guiding principle is influential for many decisions made during the design process. +The UltraStar file format is designed to be edited by machines and humans alike +and is intended to be easily understood and edited by technical and non-technical users. +This guiding principle is influential for many decisions made during the design process. ### 1.1. Conventions in this Document The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119](https://datatracker.ietf.org/doc/html/rfc2119). -The grammatical rules in this document are to be interpreted as described in [RFC 5234](https://datatracker.ietf.org/doc/html/rfc5234). We are using the following core rules: +The grammatical rules in this document are to be interpreted as described in [RFC 5234](https://datatracker.ietf.org/doc/html/rfc5234). +We are using the following core rules: ```abnf CR = %x0D ; carriage return @@ -37,9 +46,11 @@ SP = %x20 ; space The following terminology is used throughout this document: -**Song**: A song refers to a file in the UltraStar file format. In some contexts **song** can refer to linked media files as well. In those cases **textfile** is used to disambiguate individual files. +**Song**: A song refers to a file in the UltraStar file format. +In some contexts **song** can refer to linked media files as well. In those cases **textfile** is used to disambiguate individual files. -**Medley**: A medley is a short, recognizable excerpt from a song. Many games include a designated medley mode. +**Medley**: A medley is a short, recognizable excerpt from a song. +Many games include a designated medley mode. > [!CAUTION] > @@ -47,7 +58,10 @@ The following terminology is used throughout this document: ## 2. General Structure -Songs are plain text files. The UTF-8 encoding MUST be used. Implementations MUST NOT add a byte order mark to the beginning of a file. In the interests of interoperability, implementations MAY ignore the presence of a byte order mark rather than treating it as an error. +Songs are plain text files +The UTF-8 encoding MUST be used. +Implementations MUST NOT add a byte order mark to the beginning of a file. +In the interests of interoperability, implementations MAY ignore the presence of a byte order mark rather than treating it as an error. > [!CAUTION] > @@ -55,7 +69,11 @@ Songs are plain text files. The UTF-8 encoding MUST be used. Implementations MUS The canonical file extension for textfiles is `.txt`. -Songs consist of a header and a body. The header contains metadata about the song. The body contains the musical data. A file SHOULD end with an `E` on a single line. Everything after a trailing `E` MUST be ignored. +Songs consist of a header and a body. +The header contains metadata about the song. +The body contains the musical data. +A file SHOULD end with an `E` on a single line. +Everything after a trailing `E` MUST be ignored. > [!CAUTION] > @@ -70,14 +88,17 @@ char = %x00-10FFFF ### 2.1. Line Endings and Whitespace -Both the header and the body of a file are defined in terms of lines. A line is a string of text that is terminated with an end-of-line sequence. +Both the header and the body of a file are defined in terms of lines. +A line is a string of text that is terminated with an end-of-line sequence. ```abnf end-of-line = ( CR / LF / CRLF ) empty-line = end-of-line ``` -Implementations SHOULD use a single Line Feed (`%x0A`) as line terminator. Implementations MUST accept the end of input (`EOF`) as a valid line terminator. Empty lines are ignored throughout the entire file. +Implementations SHOULD use a single Line Feed (`%x0A`) as line terminator. +Implementations MUST accept the end of input (`EOF`) as a valid line terminator. +Empty lines are ignored throughout the entire file. > [!CAUTION] > @@ -85,9 +106,12 @@ Implementations SHOULD use a single Line Feed (`%x0A`) as line terminator. Imple > [!CAUTION] > -> Whether empty lines are allowed or not is currently open for discussion ([#43](https://github.com/UltraStar-Deluxe/format/issues/43)). Whether a line that consists only of whitespace is recognized as an empty line has not been decided yet. +> Whether empty lines are allowed or not is currently open for discussion ([#43](https://github.com/UltraStar-Deluxe/format/issues/43)). +> Whether a line that consists only of whitespace is recognized as an empty line has not been decided yet. -Whitespace is used as a separator in many places of the format. Only space (`%x20`) and horizontal tab (`%x09`) are recognized as whitespace characters. In particular other unicode characters with the property `White_Space=yes` MUST NOT be treated as whitespace characters in the context of this specification. +Whitespace is used as a separator in many places of the format. +Only space (`%x20`) and horizontal tab (`%x09`) are recognized as whitespace characters. +In particular other unicode characters with the property `White_Space=yes` MUST NOT be treated as whitespace characters in the context of this specification. ```abnf WSP = ( SP / HTAB ) @@ -99,11 +123,15 @@ WSP = ( SP / HTAB ) ## 2. The File Header -The header of a song consists of a sequence of key-value pairs. Each line in the header section starts with a hash. The key and value of a header are separated by a colon. Whitespace around key and value is ignored. +The header of a song consists of a sequence of key-value pairs. +Each line in the header section starts with a hash. +The key and value of a header are separated by a colon. +Whitespace around key and value is ignored. > [!CAUTION] > -> The terminology “header” is not decided yet. Other terms used for the same concept are “tag”, “attribute” or “field”. +> The terminology “header” is not decided yet. +> Other terms used for the same concept are “tag”, “attribute” or “field”. ```abnf file-header = *( header / empty-line ) @@ -129,21 +157,40 @@ period = %x2E ; . > > The use of trailing commas in comma-separated header lists has not been decided yet. -Comparisons of header keys is case-insensitive. For the sake of consistency header keys SHOULD use only capital letters. Header values are generally case-sensitive unless otherwise specified. An empty value is equivalent to the header being absent. Implementations MAY remove leading and trailing whitespace in header keys and values without changing semantics. Header values may not exceed 255 characters. +Comparisons of header keys is case-insensitive. +For the sake of consistency header keys SHOULD use only capital letters. +Header values are generally case-sensitive unless otherwise specified. +An empty value is equivalent to the header being absent. +Implementations MAY remove leading and trailing whitespace in header keys and values without changing semantics. +Header values may not exceed 255 characters. -Implementations MAY define application-specific headers but SHOULD prefix those headers with the application name to avoid conflicts with future standardized headers. Implementations MUST ignore headers they do not recognize. The order of headers is irrelevant (note the exception in section 3.1.) although standardized headers should precede any application-specific headers. +Implementations MAY define application-specific headers +but SHOULD prefix those headers with the application name to avoid conflicts with future standardized headers. +Implementations MUST ignore headers they do not recognize. +The order of headers is irrelevant (note the exception in section 3.1.) +although standardized headers should precede any application-specific headers. > [!CAUTION] > > Handling of application-specific headers has not been decided yet. -The following sections describe the standardized headers that have been defined. If a syntax for a header is specified it applies to the `single-value`. If no syntax is specified any valid `single-value` is valid. Some headers are marked as deprecated or removed from a certain version onward. Implementations MUST continue to apply the defined semantics to a header if it has been deprecated in the file format version indicated by the file. Implementations MUST NOT apply semantics to a header if a file indicates a version where the header has been removed. +The following sections describe the standardized headers that have been defined. +If a syntax for a header is specified it applies to the `single-value`. +If no syntax is specified any valid `single-value` is valid. +Some headers are marked as deprecated or removed from a certain version onward. +Implementations MUST continue to apply the defined semantics to a header if it is deprecated in the file format version indicated by the file. +Implementations MUST NOT apply semantics to a header if a file indicates a version where the header has been removed. ### 3.1. Single-Valued and Multi-Valued Headers -Headers can be single-valued or multi-valued. Single-valued headers can only be specified once and can only contain a single value. For the sake of robustness implementations SHOULD ignore multiple occurrences of single-valued headers (which value is chosen in such a case is an implementation detail). +Headers can be single-valued or multi-valued. +Single-valued headers can only be specified once and can only contain a single value. +For the sake of robustness implementations SHOULD ignore multiple occurrences of single-valued headers (which value is chosen in such a case is an implementation detail). -Multi-valued headers can contain multiple values separated by a comma (`%x2C`). Additionally, multiple occurrences of a multi-valued header are semantically equivalent to a single occurrence where all values are concatenated by commas in order of occurrence. In this way the order of multi-valued headers is significant. +Multi-valued headers can contain multiple values separated by a comma (`%x2C`). +Additionally, multiple occurrences of a multi-valued header are semantically equivalent to a single occurrence +where all values are concatenated by commas in order of occurrence. +In this way the order of multi-valued headers is significant. Empty values within a multi-valued header can be removed without changing semantics. @@ -151,13 +198,15 @@ Empty values within a multi-valued header can be removed without changing semant > > **Backwards-Compatible Change** in version 1.1.0 > -> Multi-Valued Headers were introduced in version 1.1.0 of the format. Headers indicated as multi-valued were single-valued in previous versions. +> Multi-Valued Headers were introduced in version 1.1.0 of the format. +> Headers indicated as multi-valued were single-valued in previous versions. > [!WARNING] > > **Backwards-Compatible Change** in version ??? > -> Concatenating multiple occurrences of multi-valued headers was introduced in version ??? of the format. Previously handling of repeated headers was not covered by this specification. +> Concatenating multiple occurrences of multi-valued headers was introduced in version ??? of the format. +> Previously handling of repeated headers was not covered by this specification. > [!CAUTION] > @@ -165,7 +214,10 @@ Empty values within a multi-valued header can be removed without changing semant ### 3.2. File References -Some headers reference other files, most notably `AUDIO`, `VIDEO`, `COVER`, and `BACKGROUND`. These file references are always relative to the textfile from which they are referenced. As a security measure file references MUST NOT use absolute paths. Implementations SHOULD refuse to load absolutely referenced files. +Some headers reference other files, most notably `AUDIO`, `VIDEO`, `COVER`, and `BACKGROUND`. +These file references are always relative to the textfile from which they are referenced. +As a security measure file references MUST NOT use absolute paths. +Implementations SHOULD refuse to load absolutely referenced files. > [!CAUTION] > @@ -173,7 +225,9 @@ Some headers reference other files, most notably `AUDIO`, `VIDEO`, `COVER`, and > [!IMPORTANT] > -> In Windows file names are case-insensitive (i.e. there cannot be two files in a folder that differ only by their case). Linux and macOS however, use fully case-sensitive file systems. Implementations might need to pay special attention to this fact to ensure that files are compatible across all systems. +> In Windows file names are case-insensitive (i.e. there cannot be two files in a folder that differ only by their case). +> Linux and macOS however, use fully case-sensitive file systems. +> Implementations might need to pay special attention to this fact to ensure that files are compatible across all systems. ### 3.3. The `VERSION` Header @@ -184,9 +238,15 @@ Syntax: Since: 1.0.0 ``` -The `VERSION` header indicates the version of this specification that a file complies to. The value of the tag is a [semantic version](https://semver.org), meaning that an implementation supporting version 1.0.0 of this spec should be able to process files using a version of 1.1.0 without any changes (although new features might not be supported). Implementations SHOULD NOT attempt to process files with a higher major version than they were designed to work with. +The `VERSION` header indicates the version of this specification that a file complies to. +The value of the tag is a [semantic version](https://semver.org), +meaning that an implementation supporting version 1.0.0 of this spec should be able to process files using a version of 1.1.0 without any changes (although new features might not be supported). +Implementations SHOULD NOT attempt to process files with a higher major version than they were designed to work with. -In absence of the `VERSION` header implementations SHOULD assume the version 0.3.0. Implementations SHOULD reject a file based on the value of the `VERSION` header, in particular if the value is syntactically invalid. Applications MAY reject prerelease-versions altogether. +In absence of the `VERSION` header implementations SHOULD assume the version 0.3.0. +Implementations SHOULD reject a file based on the value of the `VERSION` header, +in particular if the value is syntactically invalid. +Applications MAY reject prerelease-versions altogether. The `VERSION` header SHOULD be the first header in a file. @@ -199,13 +259,18 @@ Syntax: 1*DIGIT [ period 1*DIGIT ] Since: 0.1.0 ``` -The `BPM` header indicates the number of beats per minute. The notes in a song are quantized in beats. A single beat is the smallest unit of time that can be present in a song. The value is a 32 bit floating point number. The value of this tag is arbitrary in the sense that it is usually 4 to 8 times higher than the actual BPM of a song. +The `BPM` header indicates the number of beats per minute. +The notes in a song are quantized in beats. +A single beat is the smallest unit of time that can be present in a song. +The value is a 32 bit floating point number. +The value of this tag is arbitrary in the sense that it is usually 4 to 8 times higher than the actual BPM of a song. > [!WARNING] > > **Breaking Change** in version 2.0.0 > -> In versions 0.x and 1.x the value of the `BPM` header was implicitly quadrupled. This is **not** the case for version 2.0.0 and above. +> In versions 0.x and 1.x the value of the `BPM` header was implicitly quadrupled. +> This is **not** the case for version 2.0.0 and above. > [!CAUTION] > @@ -215,7 +280,8 @@ The `BPM` header indicates the number of beats per minute. The notes in a song a > > **Breaking Change** in version 2.0.0 > -> In versions 0.x and 1.x the comma was allowed as decimal separator in addition to the period. This feature has been removed in version 2.0.0 and above. +> In versions 0.x and 1.x the comma was allowed as decimal separator in addition to the period. +> This feature has been removed in version 2.0.0 and above. > [!CAUTION] > @@ -229,7 +295,9 @@ Multi-Valued: No Since: 1.1.0 ``` -The `AUDIO` header contains a file reference (as defined in section 3.2.) to an audio file. This file contains the full version of a song (including instrumentals and vocals). Supported audio formats are an implementation detail. +The `AUDIO` header contains a file reference (as defined in section 3.2.) to an audio file. +This file contains the full version of a song (including instrumentals and vocals). +Supported audio formats are an implementation detail. > [!CAUTION] > @@ -245,7 +313,9 @@ Deprecated: 1.1.0 Removed: 2.0.0 ``` -The `MP3` header contains a file reference (as defined in section 3.2.) to an audio file. This header has been replaced by the `AUDIO` header. Implementations MUST disregard the `MP3` header if an `AUDIO` header is present (even if the specified file cannot be found or processed). +The `MP3` header contains a file reference (as defined in section 3.2.) to an audio file. +This header has been replaced by the `AUDIO` header. +Implementations MUST disregard the `MP3` header if an `AUDIO` header is present (even if the specified file cannot be found or processed). ### 3.7. The `COVER`, `BACKGROUND`, and `VIDEO` Headers @@ -255,7 +325,9 @@ Multi-Valued: No Since: 0.2.0 ``` -The headers `COVER`, `BACKGROUND`, and `VIDEO` contain file references to image files or in case of `VIDEO` video files. Implementations MAY use these files to display cover artwork and background graphics during gameplay. Supported image and video formats are an implementation detail. +The headers `COVER`, `BACKGROUND`, and `VIDEO` contain file references to image files or in case of `VIDEO` video files. +Implementations MAY use these files to display cover artwork and background graphics during gameplay. +Supported image and video formats are an implementation detail. For the best compatibility `COVER` images should be square and be no larger than 1920 pixels in width and height. @@ -275,7 +347,10 @@ Multi-Valued: No Since: 1.1.0 ``` -The `VOCALS` and `INSTRUMENTAL` header contain file references to audio files. These files contain the a cappella and instrumental versions of the song respectively. Implementations MAY use these instead of `AUDIO` to give users the option of changing the volume of vocal and instrumental tracks separately. +The `VOCALS` and `INSTRUMENTAL` header contain file references to audio files. +These files contain the a cappella and instrumental versions of the song respectively. +Implementations MAY use these instead of `AUDIO` +to give users the option of changing the volume of vocal and instrumental tracks separately. > [!CAUTION] > @@ -290,7 +365,9 @@ Syntax: 1*DIGIT Since: 0.2.0 ``` -The `GAP` header indicates an amount of time in milliseconds from the beginning of the audio track until beat 0. This effectively offsets all notes in a song by this amount of time relative to the audio track. The `GAP` value is an integer. +The `GAP` header indicates an amount of time in milliseconds from the beginning of the audio track until beat 0. +This effectively offsets all notes in a song by this amount of time relative to the audio track. +The `GAP` value is an integer. > [!CAUTION] > @@ -300,7 +377,8 @@ The `GAP` header indicates an amount of time in milliseconds from the beginning > > **Breaking Change** in version 2.0.0 > -> In versions 0.x and 1.x the value of `GAP` could also be a floating point number. Since version 2.0.0 this is not allowed anymore. +> In versions 0.x and 1.x the value of `GAP` could also be a floating point number. +> Since version 2.0.0 this is not allowed anymore. ### 3.10. The `VIDEOGAP` Header @@ -311,13 +389,15 @@ Syntax: [ minus ] 1*DIGIT Since: 0.2.0 ``` -The `VIDEOGAP` header indicates an amount of time in milliseconds that the background video will be delayed relative to the audio of a song. The `VIDEOGAP` value is an integer. +The `VIDEOGAP` header indicates an amount of time in milliseconds that the background video will be delayed relative to the audio of a song. +The `VIDEOGAP` value is an integer. > [!WARNING] > > **Breaking Change** in version 2.0.0 > -> In versions 0.x and 1.x the value of `VIDEOGAP` was specified in seconds as a floating point number. Version 2.0.0 changes this to an integer and milliseconds. +> In versions 0.x and 1.x the value of `VIDEOGAP` was specified in seconds as a floating point number. +> Version 2.0.0 changes this to an integer and milliseconds. ### 3.11. The `NOTESGAP` Header @@ -330,7 +410,8 @@ Deprecated: 0.3.0 Removed: 1.0.0 ``` -The `NOTESGAP` header is deprecated and MUST NOT be used. Implementations MUST ignore the field if present. +The `NOTESGAP` header is deprecated and MUST NOT be used. +Implementations MUST ignore the field if present. > [!NOTE] > @@ -345,17 +426,21 @@ Syntax: 1*DIGIT Since: 0.2.0 ``` -The `START` and `END` header specify two time points in milliseconds relative to the start of the audio data that indicate a start and end point for the song. Game implementations SHOULD start and end the song at the specified points and scale scoring accordingly. Both `START` and `END` values are integers. +The `START` and `END` header specify two time points in milliseconds relative to the start of the audio data that indicate a start and end point for the song. +Game implementations SHOULD start and end the song at the specified points and scale scoring accordingly. +Both `START` and `END` values are integers. > [!NOTE] > -> The `START` and `END` values do not affect the placement of notes nor any other time codes relative to the audio. They simply indicate that a song should be started or stopped a certain amount of time into the audio file. +> The `START` and `END` values do not affect the placement of notes nor any other time codes relative to the audio. +> They simply indicate that a song should be started or stopped a certain amount of time into the audio file. > [!WARNING] > > **Breaking Change** in version 2.0.0 > -> In versions 0.x and 1.x `START` was specified in seconds as a floating point number. Version 2.0.0 changes this to an integer and milliseconds. +> In versions 0.x and 1.x `START` was specified in seconds as a floating point number. +> Version 2.0.0 changes this to an integer and milliseconds. ### 3.13. The `PREVIEWSTART` Header @@ -366,13 +451,16 @@ Syntax: 1*DIGIT Since: 0.2.0 ``` -The `PREVIEWSTART` header indicates a time offset in milliseconds relative to the start of the audio where the preview starts. Implementations MAY use this value when playing a song in a preview setting (e.g. during song selection). In its absence implementations SHOULD default to the start of the medley section (if available). +The `PREVIEWSTART` header indicates a time offset in milliseconds relative to the start of the audio where the preview starts. +Implementations MAY use this value when playing a song in a preview setting (e.g. during song selection). +In its absence implementations SHOULD default to the start of the medley section (if available). > [!WARNING] > > **Breaking Change** in version 2.0.0 > -> In versions 0.x and 1.x `PREVIEWSTART` was specified in seconds as a floating point number. Version 2.0.0 of this specification changes this to an integer and milliseconds. +> In versions 0.x and 1.x `PREVIEWSTART` was specified in seconds as a floating point number. +> Version 2.0.0 of this specification changes this to an integer and milliseconds. ### 3.14. The `MEDLEYSTART` and `MEDLEYEND` Headers @@ -383,7 +471,8 @@ Syntax: 1*DIGIT Since: 2.0.0 ``` -The `MEDLEYSTART` and `MEDLEYEND` headers indicate in milliseconds the start and end of the medley section of a song relative to the start of the audio. These tags replace `MEDLEYSTARTBEAT` and `MEDLEYENDBEAT` in version 2.0.0 of this specification. +The `MEDLEYSTART` and `MEDLEYEND` headers indicate in milliseconds the start and end of the medley section of a song relative to the start of the audio. +These tags replace `MEDLEYSTARTBEAT` and `MEDLEYENDBEAT` in version 2.0.0 of this specification. ### 3.15. The `MEDLEYSTARTBEAT` and `MEDLEYENDBEAT` Headers @@ -395,7 +484,8 @@ Since: 0.2.0 Removed: 2.0.0 ``` -The `MEDLEYSTARTBEAT` and `MEDLEYENDBEAT` headers indicate in beats the start and end of the medley section of a song. Implementations MUST respect the `GAP` value when calculating the medley start and end times. +The `MEDLEYSTARTBEAT` and `MEDLEYENDBEAT` headers indicate in beats the start and end of the medley section of a song. +Implementations MUST respect the `GAP` value when calculating the medley start and end times. > [!WARNING] > @@ -412,7 +502,9 @@ Syntax: "on" / "off" Since: 0.2.0 ``` -If `MEDLEYSTART` or `MEDLEYEND` (`MEDLEYSTARTBEAT` or `MEDLEYENDBEAT` for versions before 2.0.0) are not specified, the `CALCMEDLEY` header indicates whether an implementation is supposed to determine the start and end of the medley section automatically. The value of this header is compared case-insensitively. +If `MEDLEYSTART` or `MEDLEYEND` (`MEDLEYSTARTBEAT` or `MEDLEYENDBEAT` for versions before 2.0.0) are not specified, +the `CALCMEDLEY` header indicates whether an implementation is supposed to determine the start and end of the medley section automatically. +The value of this header is compared case-insensitively. > [!CAUTION] > @@ -447,7 +539,8 @@ Syntax: 4DIGIT Since: 0.2.0 ``` -The `YEAR` indicates the year in which the song was released. The value must be a positive integer. +The `YEAR` indicates the year in which the song was released. +The value must be a positive integer. ### 3.20. The `GENRE` Header @@ -457,7 +550,9 @@ Multi-Valued: Yes Since: 0.2.0 ``` -The `GENRE` defines the genre(s) of the song. Individual genre values MUST be compared case-insensitively. For consistency, it is usually best to capitalize genres. +The `GENRE` defines the genre(s) of the song. +Individual genre values MUST be compared case-insensitively. +For consistency, it is usually best to capitalize genres. > [!CAUTION] > @@ -481,7 +576,10 @@ Multi-Valued: Yes Since: 0.2.0 ``` -The `EDITION` indicates what edition of games a song belongs to. While this header is intended to hold commercially available editions (e.g. SingStar Pop Hits, GuitarHero Live) implementations MUST NOT reject a file based on the value of this header. A list of SingStar editions is available [here](https://github.com/bohning/usdb_syncer/wiki/SingStar-Editions). For arbitrary keywords see the `TAGS` header. +The `EDITION` indicates what edition of games a song belongs to. +While this header is intended to hold commercially available editions (e.g. SingStar Pop Hits, GuitarHero Live) implementations MUST NOT reject a file based on the value of this header. +A list of SingStar editions is available [here](https://github.com/bohning/usdb_syncer/wiki/SingStar-Editions). +For arbitrary keywords see the `TAGS` header. ### 3.23. The `TAGS` Header @@ -491,7 +589,8 @@ Multi-Valued: Yes Since: 1.1.0 ``` -The `TAGS` allow association of any reasonable keyword with a song. Implementations SHOULD compare tags in a case-insensitive manner. +The `TAGS` allow association of any reasonable keyword with a song. +Implementations SHOULD compare tags in a case-insensitive manner. > [!CAUTION] > @@ -505,9 +604,13 @@ Multi-Valued: No Since: 0.2.0 ``` -The headers `P1`, `P2`, … indicate the names of the voices of a song. These names correspond to the voices indicated by the `P1`, `P2`, … voice changes (see [section 3.3](#33-voice-changes)). If the voices correspond to different singers in the original song, the header values often indicate the names of the original singers. +The headers `P1`, `P2`, … indicate the names of the voices of a song. +These names correspond to the voices indicated by the `P1`, `P2`, … voice changes (see [section 3.3](#33-voice-changes)). +If the voices correspond to different singers in the original song, the header values often indicate the names of the original singers. -The association of header values to voices is defined by the numerical value after each `P` respectively, i.e. the header `P2` indicates the name of the voice whose notes are introduced by the `P2` voice change. Leading zeroes are insignificant, i.e. the headers `P1` and `P001` both refer to the same voice. +The association of header values to voices is defined by the numerical value after each `P` respectively, +i.e. the header `P2` indicates the name of the voice whose notes are introduced by the `P2` voice change. +Leading zeroes are insignificant, i.e. the headers `P1` and `P001` both refer to the same voice. > [!CAUTION] > @@ -523,7 +626,8 @@ Deprecated: 0.3.0 Removed: 1.0.0 ``` -The headers `DUETSINGER1`, `DUETSINGER2`, etc. are aliases for `P1`, `P2`, etc. If both are specified `P1`, `P2`, etc. take precedence. +The headers `DUETSINGER1`, `DUETSINGER2`, etc. are aliases for `P1`, `P2`, etc. +If both are specified `P1`, `P2`, etc. take precedence. ### 3.26. The `CREATOR` Header @@ -533,11 +637,13 @@ Multi-Valued: Yes Since: 0.2.0 ``` -The `CREATOR` indicates who created the textfile. Values are usually usernames or gamer tags. +The `CREATOR` indicates who created the textfile. +Values are usually usernames or gamer tags. > [!NOTE] > -> Some implementations are known to use an application-specific header `AUTHOR` in place of `CREATOR`. The semantics of the `AUTHOR` header are not part of this specification. +> Some implementations are known to use an application-specific header `AUTHOR` in place of `CREATOR`. +> The semantics of the `AUTHOR` header are not part of this specification. ### 3.27. The `PROVIDEDBY` Header @@ -547,11 +653,14 @@ Multi-Valued: No Since: 1.1.0 ``` -The `PROVIDEDBY` header indicates the source of a particular textfile. Implementations concerned with providing textfiles to many users (sometimes referred to as "hosters") SHOULD set this value automatically. Values SHOULD be valid URLs according to [RFC 1738](https://datatracker.ietf.org/doc/html/rfc1738) using the HTTP or HTTPS scheme. +The `PROVIDEDBY` header indicates the source of a particular textfile. +Implementations concerned with providing textfiles to many users (sometimes referred to as "hosters") SHOULD set this value automatically. +Values SHOULD be valid URLs according to [RFC 1738](https://datatracker.ietf.org/doc/html/rfc1738) using the HTTP or HTTPS scheme. > [!NOTE] > -> Some implementations are known to use an application-specific header `SOURCE` in place of `PROVIDEDBY`. The semantics of the `SOURCE` header are not part of this specification. +> Some implementations are known to use an application-specific header `SOURCE` in place of `PROVIDEDBY`. +> The semantics of the `SOURCE` header are not part of this specification. ### 3.28. The `COMMENT` Header @@ -562,6 +671,7 @@ Since: 0.2.0 ``` The `COMMENT` header can include arbitrary text. +Implementations MUST NOT assign semantics to the value of this header. ### 3.29. The `ENCODING` Header @@ -574,15 +684,20 @@ Deprecated: 0.3.0 Removed: 1.0.0 ``` -The `ENCODING` header specifies the encoding used for text values in a textfile. If present implementations MUST apply this encoding to all header values and all note texts. Implementations MAY support additional encodings. Names of encodings are compared in a case-insensitive manner. +The `ENCODING` header specifies the encoding used for text values in a textfile. +If present implementations MUST apply this encoding to all header values and all note texts. +Implementations MAY support additional encodings. +Names of encodings are compared in a case-insensitive manner. > [!IMPORTANT] > -> Many implementations only apply the specified encoding to **subsequent** headers and note texts. Although this is technically not spec-compliant it is usually best to put the `ENCODING` header first. +> Many implementations only apply the specified encoding to **subsequent** headers and note texts. +> Although this is technically not spec-compliant it is usually best to put the `ENCODING` header first. > [!WARNING] > -> The use of the `ENCODING` tag is highly discouraged. Songs must always use the UTF-8 encoding. +> The use of the `ENCODING` tag is highly discouraged. +> Songs must always use the UTF-8 encoding. ### 3.30. The `RELATIVE` Header @@ -615,7 +730,8 @@ The sequence of notes and end-of-phrase markers SHOULD appear in ascending order ### 3.1. Notes -A note is a musical element in a song. Each note is defined by its type, start beat, duration, pitch, and text. +A note is a musical element in a song. +Each note is defined by its type, start beat, duration, pitch, and text. ```abnf note = note-type @@ -638,9 +754,15 @@ minus = %x2D ; - > > Whether only a single or multiple whitespace character in a row are allowed is currently up for discussion ([#46](https://github.com/UltraStar-Deluxe/format/issues/46)). -The note type indicates how singing the correct or wrong note should affect scoring. The following sections define standard note types. Implementations MAY substitute unknown note types with freestyle notes (`F`). Implementations MUST NOT attach semantics to note types not covered by this specification. +The note type indicates how singing the correct or wrong note should affect scoring. +The following sections define standard note types. +Implementations MAY substitute unknown note types with freestyle notes (`F`). +Implementations MUST NOT attach semantics to note types not covered by this specification. -The start beat and duration define the time when a note appears in a song. Both are indicated in beats (see section 3.3.) relative to offset indicated by the `GAP` header. The end beat of a note is calculated as its start beat plus its duration. Notes SHOULD NOT overlap, i.e. the start beat of a note being between the start beat (inclusive) and end beat (exclusive) of another note. +The start beat and duration define the time when a note appears in a song. +Both are indicated in beats (see section 3.3.) relative to offset indicated by the `GAP` header. +The end beat of a note is calculated as its start beat plus its duration. +Notes SHOULD NOT overlap, i.e. the start beat of a note being between the start beat (inclusive) and end beat (exclusive) of another note. > [!CAUTION] > @@ -650,15 +772,21 @@ The start beat and duration define the time when a note appears in a song. Both > > Whether negative note starts and/or durations are valid is, hasn't been decided yet. -The pitch of a note is encoded as the number of half-steps relative to middle C or C4. So a pitch of `5` represent an F4 and a pitch of `-2` represents an A#3. +The pitch of a note is encoded as the number of half-steps relative to C4 (also referred to as middle C). +So a pitch of `5` represent an F4 and a pitch of `-2` represents an A#3. #### 3.1.1. Regular Notes `:` -A regular note is indicated by the note type `:` (colon, `%x3A`). A regular note indicates that a certain pitch is to be held for a certain duration. Game implementations MAY decide to compare pitches independently of the octave (i.e. compare pitches module 12). +A regular note is indicated by the note type `:` (colon, `%x3A`). +A regular note indicates that a certain pitch is to be held for a certain duration. +Game implementations MAY decide to compare pitches independently of the octave (i.e. compare pitches module 12). #### 3.1.2. Golden Notes `*` -A golden note is indicated by the note type `*` (asterisk, `%x2A`). Golden note have the same semantics as regular notes. However, during scoring game implementations SHOULD award more points for golden notes. The exact scoring behavior is an implementation detail. +A golden note is indicated by the note type `*` (asterisk, `%x2A`). +Golden note have the same semantics as regular notes. +However, during scoring game implementations SHOULD award more points for golden notes. +The exact scoring behavior is an implementation detail. #### 3.1.3. Rap Notes `R` @@ -666,7 +794,9 @@ A golden note is indicated by the note type `*` (asterisk, `%x2A`). Golden note > > Rap notes are standardized in version 0.2.0 of this specification. -A rap note is indicated by the note type `R` (the letter R, `%x52`). Rap notes have the same timing semantics as regular notes but are intended or spoken phrases that do not have a defined pitch. Implementations MUST ignore pitch information on rap notes. +A rap note is indicated by the note type `R` (the letter R, `%x52`). +Rap notes have the same timing semantics as regular notes but are intended or spoken phrases that do not have a defined pitch. +Implementations MUST ignore pitch information on rap notes. #### 3.1.4. Golden Rap Notes `G` @@ -674,7 +804,10 @@ A rap note is indicated by the note type `R` (the letter R, `%x52`). Rap notes h > > Golden rap notes are standardized in version 0.2.0 of this specification. -A golden rap note is indicated by the note type `G` (the letter G, `%x47`). Golden rap notes have the same semantics as rap notes. However, during scoring game implementations SHOULD award more points for golden rap notes. The exact scoring behavior is an implementation detail. +A golden rap note is indicated by the note type `G` (the letter G, `%x47`). +Golden rap notes have the same semantics as rap notes. +However, during scoring game implementations SHOULD award more points for golden rap notes. +The exact scoring behavior is an implementation detail. #### 3.1.5. Freestyle Notes `F` @@ -682,7 +815,9 @@ A golden rap note is indicated by the note type `G` (the letter G, `%x47`). Gold > > Freestyle notes are standardized in version 0.2.0 of this specification. -A freestyle note is indicated by the note type `F` (the letter F, `%x46`). Similar to rap notes, freestyle notes do not carry pitch information. Additionally, game implementations MUST NOT award points for freestyle notes. +A freestyle note is indicated by the note type `F` (the letter F, `%x46`). +Similar to rap notes, freestyle notes do not carry pitch information. +Additionally, game implementations MUST NOT award points for freestyle notes. ### 3.2. End-of-Phrase Markers @@ -694,9 +829,11 @@ end-of-phrase = dash *WSP line-break ``` -An end-of-phrase marker carries no musical information but indicates the end of a phrase in the song. This is usually interpreted as a line break in the lyrics. +An end-of-phrase marker carries no musical information but indicates the end of a phrase in the song. +This is usually interpreted as a line break in the lyrics. -An end-of-phrase SHOULD NOT appear between the start beat (inclusive) of a note and its end beat (exclusive). An end-of-phrase marker SHOULD NOT appear before the start time of the first note or after the start time of the last note. +An end-of-phrase SHOULD NOT appear between the start beat (inclusive) of a note and its end beat (exclusive). +An end-of-phrase marker SHOULD NOT appear before the start time of the first note or after the start time of the last note. > [!CAUTION] > @@ -712,7 +849,8 @@ An end-of-phrase SHOULD NOT appear between the start beat (inclusive) of a note > > **Breaking Change** in version 0.2.0 > -> In version 0.1.0 only single-voice songs were defined. Voice changes are specified since version 0.2.0. +> In version 0.1.0 only single-voice songs were defined. +> Voice changes are specified since version 0.2.0. A voice change (also referred to as a “player change”) is indicated by a `P` (the letter P, `%x50`), immediately followed by a number. @@ -724,13 +862,18 @@ voice-number = positive-digit *DIGIT positive-digit = %x31-39 ; 1-9 ``` -A voice change indicates that all notes and end-of-phrase markers following this line belong to the voice indicated by the `voice-number`. Implementations MAY choose to limit the number of voices. If the body of a song does not start with a voice change, `P1` is assumed implicitly. To improve readability notes for different voices should not be interlaced. +A voice change indicates that all notes and end-of-phrase markers following this line belong to the voice indicated by the `voice-number`. +Implementations MAY choose to limit the number of voices. +If the body of a song does not start with a voice change, `P1` is assumed implicitly. +To improve readability notes for different voices should not be interlaced. > [!NOTE] > > A voice change does NOT implicitly add an end-of-phrase indicator. -Voice changes SHOULD appear in ascending order of `voice-number` and there SHOULD be no gaps (i.e. a song having notes for `P1` and `P3`, but not `P2`). The exact `voice-number` carries no semantics other than its relative order with other `voice-number` and its association with the corresponding header (see [section 3.25](#325-the-p1-and-p2-headers)). In particular a file that uses `P3` and `P5` can be rewritten using `P1` and `P2` with no change in semantics. +Voice changes SHOULD appear in ascending order of `voice-number` and there SHOULD be no gaps (i.e. a song having notes for `P1` and `P3`, but not `P2`). +The exact `voice-number` carries no semantics other than its relative order with other `voice-number` and its association with the corresponding header (see [section 3.25](#325-the-p1-and-p2-headers)). +In particular a file that uses `P3` and `P5` can be rewritten using `P1` and `P2` with no change in semantics. > [!TIP] > @@ -738,7 +881,8 @@ Voice changes SHOULD appear in ascending order of `voice-number` and there SHOUL > [!NOTE] > -> There exists a legacy behavior where an indicated `P3` would start a sequence of notes that apply to both voices. This behavior is explicitly NOT compliant with this specification. +> There exists a legacy behavior where an indicated `P3` would start a sequence of notes that apply to both voices. +> This behavior is explicitly NOT compliant with this specification. > [!CAUTION] > @@ -764,7 +908,8 @@ Voice changes SHOULD appear in ascending order of `voice-number` and there SHOUL > > Relative mode is deprecated and has been removed in version 1.0.0 of this specification. -Relative mode is a special input mode that affects parsing and interpreting songs significantly. Relative mode is enabled by the `RELATIVE` header being set to `yes` (case-insensitive). +Relative mode is a special input mode that affects parsing and interpreting songs significantly. +Relative mode is enabled by the `RELATIVE` header being set to `yes` (case-insensitive). ### Syntax @@ -778,7 +923,8 @@ end-of-phrase =/ dash rel-offset = *DIGIT ``` -Note that the syntax in relative mode is incompatible with the normal syntax. Implementations MUST NOT try to rectify a missing `RELATIVE` header based on the end-of-phrase markers encountered. +Note that the syntax in relative mode is incompatible with the normal syntax. +Implementations MUST NOT try to rectify a missing `RELATIVE` header based on the end-of-phrase markers encountered. ### Semantics @@ -786,10 +932,12 @@ In relative mode the semantics of start times changes for notes and end-of-phras - At the start of the body a relative offset `rel` is initialized to the value of the `GAP` header (or `0` if no `GAP` header exists). - The start times of notes and end-of-phrase markers are relative to the current `rel` value. The absolute start time is calculated as `rel + start-beat`. -- End-of-phrase markers in relative mode include a `rel-offset`. After the start time of the end-of-phrase marker has been interpreted, the `rel-offset` value is added to `rel`. +- End-of-phrase markers in relative mode include a `rel-offset`. + After the start time of the end-of-phrase marker has been interpreted, the `rel-offset` value is added to `rel` for subsequent lines. > [!IMPORTANT] > > In relative mode the order of notes and end-of-phrase markers within a file is significant. -In files with multiple voices each voice has its own `rel` value which is independent of other voices. The `rel` value for a voice does not reset when a voice change is encountered. +In files with multiple voices each voice has its own `rel` value which is independent of other voices. +The `rel` value for a voice does not reset when a voice change is encountered. From f91e7ffbdf5896cd71a6c2e84210e31dc98166b7 Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Wed, 31 Jan 2024 16:22:07 +0100 Subject: [PATCH 25/48] Add terminology for implementations --- spec.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/spec.md b/spec.md index 060033f..a20beab 100644 --- a/spec.md +++ b/spec.md @@ -52,6 +52,11 @@ In some contexts **song** can refer to linked media files as well. In those case **Medley**: A medley is a short, recognizable excerpt from a song. Many games include a designated medley mode. +**Implementation**: An implementation is any program or software that interacts with the file format. + +**Game Implementation**: A game implementation is an implementation that allows users to sing karaoke songs +and potentially scores singing performance. + > [!CAUTION] > > The exact terminology has not been decided yet. From 067bbafb896367f3c213881ae971b55474549d15 Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Thu, 1 Feb 2024 11:26:51 +0100 Subject: [PATCH 26/48] Fix appendix headers --- spec.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec.md b/spec.md index a20beab..1a78361 100644 --- a/spec.md +++ b/spec.md @@ -916,7 +916,7 @@ In particular a file that uses `P3` and `P5` can be rewritten using `P1` and `P2 Relative mode is a special input mode that affects parsing and interpreting songs significantly. Relative mode is enabled by the `RELATIVE` header being set to `yes` (case-insensitive). -### Syntax +#### Syntax When relative mode is enabled, the syntax of end-of-phrase markers changes: @@ -931,7 +931,7 @@ rel-offset = *DIGIT Note that the syntax in relative mode is incompatible with the normal syntax. Implementations MUST NOT try to rectify a missing `RELATIVE` header based on the end-of-phrase markers encountered. -### Semantics +#### Semantics In relative mode the semantics of start times changes for notes and end-of-phrase markers. From 60b83942400debc25775b9e1e1bc784e3432438d Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Sat, 3 Feb 2024 11:26:57 +0100 Subject: [PATCH 27/48] Move MP3 vs AUDIO section --- spec.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec.md b/spec.md index 1a78361..e5f984a 100644 --- a/spec.md +++ b/spec.md @@ -303,6 +303,7 @@ Since: 1.1.0 The `AUDIO` header contains a file reference (as defined in section 3.2.) to an audio file. This file contains the full version of a song (including instrumentals and vocals). Supported audio formats are an implementation detail. +Implementations MUST disregard the `MP3` header if an `AUDIO` header is present (even if the specified file cannot be found or processed). > [!CAUTION] > @@ -311,7 +312,7 @@ Supported audio formats are an implementation detail. ### 3.6. The `MP3` Header ``` -Required: No (Version 2.x), Yes (Versions 0.x and 1.x) +Required: Yes (Versions 0.x and 1.x) Multi-Valued: No Since: 0.1.0 Deprecated: 1.1.0 @@ -320,7 +321,6 @@ Removed: 2.0.0 The `MP3` header contains a file reference (as defined in section 3.2.) to an audio file. This header has been replaced by the `AUDIO` header. -Implementations MUST disregard the `MP3` header if an `AUDIO` header is present (even if the specified file cannot be found or processed). ### 3.7. The `COVER`, `BACKGROUND`, and `VIDEO` Headers From fd2c41d2bb6ec11bca46198ab47eabe09643756e Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Sat, 3 Feb 2024 11:37:56 +0100 Subject: [PATCH 28/48] Remove max. cover size --- spec.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/spec.md b/spec.md index e5f984a..9f48ae7 100644 --- a/spec.md +++ b/spec.md @@ -334,8 +334,6 @@ The headers `COVER`, `BACKGROUND`, and `VIDEO` contain file references to image Implementations MAY use these files to display cover artwork and background graphics during gameplay. Supported image and video formats are an implementation detail. -For the best compatibility `COVER` images should be square and be no larger than 1920 pixels in width and height. - > [!CAUTION] > > If a minimum requirement concerning media types should be part of the spec has not been decided yet. From bd7dcf232dd843e69433b37d16a534e7692b3016 Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Sat, 3 Feb 2024 11:51:45 +0100 Subject: [PATCH 29/48] Move required headers to the top --- spec.md | 56 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/spec.md b/spec.md index 9f48ae7..e2a64d8 100644 --- a/spec.md +++ b/spec.md @@ -322,7 +322,25 @@ Removed: 2.0.0 The `MP3` header contains a file reference (as defined in section 3.2.) to an audio file. This header has been replaced by the `AUDIO` header. -### 3.7. The `COVER`, `BACKGROUND`, and `VIDEO` Headers +### 3.7. The `TITLE` Header + +``` +Required: Yes +Multi-Valued: No +Since: 0.1.0 +``` + +The `TITLE` header contains the title of the song. + +### 3.8. The `ARTIST` Header + +``` +Required: Yes +Multi-Valued: No +Since: 0.1.0 +``` + +### 3.9. The `COVER`, `BACKGROUND`, and `VIDEO` Headers ``` Required: No @@ -342,7 +360,7 @@ Supported image and video formats are an implementation detail. > > If media files should follow a specific naming scheme has not been decided yet. -### 3.8. The `VOCALS` and `INSTRUMENTAL` Headers +### 3.10. The `VOCALS` and `INSTRUMENTAL` Headers ``` Required: No @@ -359,7 +377,7 @@ to give users the option of changing the volume of vocal and instrumental tracks > > Whether the inclusion of `VOCALS` requires the inclusion of `INSTRUMENTAL` is currently not decided. -### 3.9. The `GAP` Header +### 3.11. The `GAP` Header ``` Required: No @@ -383,7 +401,7 @@ The `GAP` value is an integer. > In versions 0.x and 1.x the value of `GAP` could also be a floating point number. > Since version 2.0.0 this is not allowed anymore. -### 3.10. The `VIDEOGAP` Header +### 3.12. The `VIDEOGAP` Header ``` Required: No @@ -402,7 +420,7 @@ The `VIDEOGAP` value is an integer. > In versions 0.x and 1.x the value of `VIDEOGAP` was specified in seconds as a floating point number. > Version 2.0.0 changes this to an integer and milliseconds. -### 3.11. The `NOTESGAP` Header +### 3.13. The `NOTESGAP` Header ``` Required: No @@ -420,7 +438,7 @@ Implementations MUST ignore the field if present. > > The `NOTESGAP` header was defined in version 0.1.0 But its semantics were never fully specified. -### 3.12. The `START` and `END` Headers +### 3.14. The `START` and `END` Headers ``` Required: No @@ -445,7 +463,7 @@ Both `START` and `END` values are integers. > In versions 0.x and 1.x `START` was specified in seconds as a floating point number. > Version 2.0.0 changes this to an integer and milliseconds. -### 3.13. The `PREVIEWSTART` Header +### 3.15. The `PREVIEWSTART` Header ``` Required: No @@ -465,7 +483,7 @@ In its absence implementations SHOULD default to the start of the medley section > In versions 0.x and 1.x `PREVIEWSTART` was specified in seconds as a floating point number. > Version 2.0.0 of this specification changes this to an integer and milliseconds. -### 3.14. The `MEDLEYSTART` and `MEDLEYEND` Headers +### 3.16. The `MEDLEYSTART` and `MEDLEYEND` Headers ``` Required: No @@ -477,7 +495,7 @@ Since: 2.0.0 The `MEDLEYSTART` and `MEDLEYEND` headers indicate in milliseconds the start and end of the medley section of a song relative to the start of the audio. These tags replace `MEDLEYSTARTBEAT` and `MEDLEYENDBEAT` in version 2.0.0 of this specification. -### 3.15. The `MEDLEYSTARTBEAT` and `MEDLEYENDBEAT` Headers +### 3.17. The `MEDLEYSTARTBEAT` and `MEDLEYENDBEAT` Headers ``` Required: No @@ -496,7 +514,7 @@ Implementations MUST respect the `GAP` value when calculating the medley start a > > The headers `MEDLEYSTARTBEAT` and `MEDLEYENDBEAT` have been replaced by `MEDLEYSTART` and `MEDLEYEND` in version 2.0.0 of this specification. -### 3.16. The `CALCMEDLEY` Header +### 3.18. The `CALCMEDLEY` Header ``` Required: No @@ -513,24 +531,6 @@ The value of this header is compared case-insensitively. > > The exact semantics of the `CALCMEDLEY` header have not been defined yet. -### 3.17. The `TITLE` Header - -``` -Required: Yes -Multi-Valued: No -Since: 0.1.0 -``` - -The `TITLE` header contains the title of the song. - -### 3.18. The `ARTIST` Header - -``` -Required: Yes -Multi-Valued: No -Since: 0.1.0 -``` - The `ARTIST` header contains the artist of the song. ### 3.19. The `YEAR` Header From 353815acbd6002a62e6b68e328799564b7290fe8 Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Sat, 3 Feb 2024 12:44:33 +0100 Subject: [PATCH 30/48] Add header links --- spec.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/spec.md b/spec.md index e2a64d8..55a06b4 100644 --- a/spec.md +++ b/spec.md @@ -303,7 +303,7 @@ Since: 1.1.0 The `AUDIO` header contains a file reference (as defined in section 3.2.) to an audio file. This file contains the full version of a song (including instrumentals and vocals). Supported audio formats are an implementation detail. -Implementations MUST disregard the `MP3` header if an `AUDIO` header is present (even if the specified file cannot be found or processed). +Implementations MUST disregard the [`MP3`](#36-the-mp3-header) header if an `AUDIO` header is present (even if the specified file cannot be found or processed). > [!CAUTION] > @@ -340,6 +340,8 @@ Multi-Valued: No Since: 0.1.0 ``` +The `ARTIST` header contains the artist of the song. + ### 3.9. The `COVER`, `BACKGROUND`, and `VIDEO` Headers ``` @@ -370,7 +372,7 @@ Since: 1.1.0 The `VOCALS` and `INSTRUMENTAL` header contain file references to audio files. These files contain the a cappella and instrumental versions of the song respectively. -Implementations MAY use these instead of `AUDIO` +Implementations MAY use these instead of [`AUDIO`](#35-the-audio-header) to give users the option of changing the volume of vocal and instrumental tracks separately. > [!CAUTION] @@ -523,7 +525,7 @@ Syntax: "on" / "off" Since: 0.2.0 ``` -If `MEDLEYSTART` or `MEDLEYEND` (`MEDLEYSTARTBEAT` or `MEDLEYENDBEAT` for versions before 2.0.0) are not specified, +If [`MEDLEYSTART`](#316-the-medleystart-and-medleyend-headers) or [`MEDLEYEND`](#316-the-medleystart-and-medleyend-headers) ([`MEDLEYSTARTBEAT`](#317-the-medleystartbeat-and-medleyendbeat-headers) or [`MEDLEYENDBEAT`](#317-the-medleystartbeat-and-medleyendbeat-headers) for versions before 2.0.0) are not specified, the `CALCMEDLEY` header indicates whether an implementation is supposed to determine the start and end of the medley section automatically. The value of this header is compared case-insensitively. @@ -531,8 +533,6 @@ The value of this header is compared case-insensitively. > > The exact semantics of the `CALCMEDLEY` header have not been defined yet. -The `ARTIST` header contains the artist of the song. - ### 3.19. The `YEAR` Header ``` @@ -582,7 +582,7 @@ Since: 0.2.0 The `EDITION` indicates what edition of games a song belongs to. While this header is intended to hold commercially available editions (e.g. SingStar Pop Hits, GuitarHero Live) implementations MUST NOT reject a file based on the value of this header. A list of SingStar editions is available [here](https://github.com/bohning/usdb_syncer/wiki/SingStar-Editions). -For arbitrary keywords see the `TAGS` header. +For arbitrary keywords see the [`TAGS`](#323-the-tags-header) header. ### 3.23. The `TAGS` Header @@ -629,8 +629,8 @@ Deprecated: 0.3.0 Removed: 1.0.0 ``` -The headers `DUETSINGER1`, `DUETSINGER2`, etc. are aliases for `P1`, `P2`, etc. -If both are specified `P1`, `P2`, etc. take precedence. +The headers `DUETSINGER1`, `DUETSINGER2`, etc. are aliases for [`P1`](#324-the-p1-p2--headers), [`P2`](#324-the-p1-p2--headers), etc. +If both are specified [`P1`](#324-the-p1-p2--headers), [`P2`](#324-the-p1-p2--headers), etc. take precedence. ### 3.26. The `CREATOR` Header @@ -912,7 +912,7 @@ In particular a file that uses `P3` and `P5` can be rewritten using `P1` and `P2 > Relative mode is deprecated and has been removed in version 1.0.0 of this specification. Relative mode is a special input mode that affects parsing and interpreting songs significantly. -Relative mode is enabled by the `RELATIVE` header being set to `yes` (case-insensitive). +Relative mode is enabled by the [`RELATIVE`](#330-the-relative-header) header being set to `yes` (case-insensitive). #### Syntax From 5a48c192d0c934cad18adff6414a73dc607996c0 Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Sat, 3 Feb 2024 13:18:56 +0100 Subject: [PATCH 31/48] Restrict voice count to 1 thru 9 --- spec.md | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/spec.md b/spec.md index 55a06b4..6da3cbe 100644 --- a/spec.md +++ b/spec.md @@ -599,27 +599,30 @@ Implementations SHOULD compare tags in a case-insensitive manner. > > Whether tags should be compared case-insensitively or not hasn't been decided yet. -### 3.24. The `P1`, `P2`, … Headers +### 3.24. The `P1` thru `P9` Headers ``` -Required: No +Required: Header Pn is required if the Pn voice change is used Multi-Valued: No Since: 0.2.0 ``` -The headers `P1`, `P2`, … indicate the names of the voices of a song. -These names correspond to the voices indicated by the `P1`, `P2`, … voice changes (see [section 3.3](#33-voice-changes)). +The headers `P1`, `P2`, …, `P9` indicate the names of the voices of a song. +These names correspond to the voices indicated by the `P1`, `P2`, …, `P9` voice changes (see [section 3.3](#33-voice-changes)). If the voices correspond to different singers in the original song, the header values often indicate the names of the original singers. The association of header values to voices is defined by the numerical value after each `P` respectively, i.e. the header `P2` indicates the name of the voice whose notes are introduced by the `P2` voice change. -Leading zeroes are insignificant, i.e. the headers `P1` and `P001` both refer to the same voice. + +> [!NOTE] +> +> As `P0` is not a valid voice change, the header `P0` is not specified. > [!CAUTION] > > The exact semantics of the `P` headers have not been decided yet. -### 3.25. The `DUETSINGER1`, `DUETSINGER2`, … Headers +### 3.25. The `DUETSINGER1` thru `DUETSINGER9` Headers ``` Required: No @@ -629,8 +632,8 @@ Deprecated: 0.3.0 Removed: 1.0.0 ``` -The headers `DUETSINGER1`, `DUETSINGER2`, etc. are aliases for [`P1`](#324-the-p1-p2--headers), [`P2`](#324-the-p1-p2--headers), etc. -If both are specified [`P1`](#324-the-p1-p2--headers), [`P2`](#324-the-p1-p2--headers), etc. take precedence. +The headers `DUETSINGER1`, `DUETSINGER2`, …, `DUETSINGER9` are aliases for [`P1`](#324-the-p1-thru-p9-headers) thru [`P9`](#324-the-p1-thru-p9-headers), etc. +If both are specified [`P1`](#324-the-p1-thru-p9-headers) thru [`P9`](#324-the-p1-thru-p9-headers), headers take precedence. ### 3.26. The `CREATOR` Header From d1256db9d765247dfed72a0f0a981020e8f1aaa7 Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Sat, 3 Feb 2024 13:39:37 +0100 Subject: [PATCH 32/48] Allow large years --- spec.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec.md b/spec.md index 6da3cbe..ea4472b 100644 --- a/spec.md +++ b/spec.md @@ -538,7 +538,7 @@ The value of this header is compared case-insensitively. ``` Required: No Multi-Valued: No -Syntax: 4DIGIT +Syntax: 4*DIGIT Since: 0.2.0 ``` From 1ed0f6832e1ea672a59c7ebbacfa20925a387c2c Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Sat, 3 Feb 2024 13:47:56 +0100 Subject: [PATCH 33/48] Add suggestion for valid language values --- spec.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/spec.md b/spec.md index ea4472b..991c17f 100644 --- a/spec.md +++ b/spec.md @@ -570,6 +570,11 @@ Since: 0.2.0 ``` The `LANGUAGE` header indicates the spoken or sung language(s) of a song. +Valid values for this header are the english language names according to [ISO 639-2](https://www.loc.gov/standards/iso639-2/php/code_list.php). `LANGUAGE` values are compared case-insensitively. + +> [!CAUTION] +> +> The set of valid values for the `LANGUAGE` header has not been decided yet. ### 3.22. The `EDITION` Header From 5e1812356400c1c9ee226d476705bc6ee50cd48c Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Sat, 3 Feb 2024 13:51:45 +0100 Subject: [PATCH 34/48] Clarify voice changes --- spec.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/spec.md b/spec.md index 991c17f..a7036fd 100644 --- a/spec.md +++ b/spec.md @@ -607,7 +607,7 @@ Implementations SHOULD compare tags in a case-insensitive manner. ### 3.24. The `P1` thru `P9` Headers ``` -Required: Header Pn is required if the Pn voice change is used +Required: Yes for multi-voice songs Multi-Valued: No Since: 0.2.0 ``` @@ -618,6 +618,7 @@ If the voices correspond to different singers in the original song, the header v The association of header values to voices is defined by the numerical value after each `P` respectively, i.e. the header `P2` indicates the name of the voice whose notes are introduced by the `P2` voice change. +If a song uses the voice change `Pn` the corresponding `Pn` header is required. > [!NOTE] > @@ -863,14 +864,13 @@ An end-of-phrase marker SHOULD NOT appear before the start time of the first not > In version 0.1.0 only single-voice songs were defined. > Voice changes are specified since version 0.2.0. -A voice change (also referred to as a “player change”) is indicated by a `P` (the letter P, `%x50`), immediately followed by a number. +A voice change (also referred to as a “player change”) is indicated by a `P` (the letter P, `%x50`), immediately followed by a single digit. ```abnf -voice-change = p voice-numer +voice-change = p voice-numer *WSP line-break p = %x50 ; P -voice-number = positive-digit *DIGIT -positive-digit = %x31-39 ; 1-9 +voice-number = DIGIT ``` A voice change indicates that all notes and end-of-phrase markers following this line belong to the voice indicated by the `voice-number`. @@ -895,6 +895,8 @@ In particular a file that uses `P3` and `P5` can be rewritten using `P1` and `P2 > There exists a legacy behavior where an indicated `P3` would start a sequence of notes that apply to both voices. > This behavior is explicitly NOT compliant with this specification. +A song that uses voice changes MUST also include the appropriate [`P1`](#324-the-p1-thru-p9-headers) thru [`P9`](#324-the-p1-thru-p9-headers) headers indicating the names of the voices. + > [!CAUTION] > > Whether songs that make use of voice changes need to start their body with a voice change has not been decided yet. From b7ff7d50e6d82c1cd61fdee54b0e15d362433409 Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Sat, 3 Feb 2024 13:53:42 +0100 Subject: [PATCH 35/48] Remove mention of `SOURCE` header --- spec.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/spec.md b/spec.md index a7036fd..2cbd414 100644 --- a/spec.md +++ b/spec.md @@ -669,11 +669,6 @@ The `PROVIDEDBY` header indicates the source of a particular textfile. Implementations concerned with providing textfiles to many users (sometimes referred to as "hosters") SHOULD set this value automatically. Values SHOULD be valid URLs according to [RFC 1738](https://datatracker.ietf.org/doc/html/rfc1738) using the HTTP or HTTPS scheme. -> [!NOTE] -> -> Some implementations are known to use an application-specific header `SOURCE` in place of `PROVIDEDBY`. -> The semantics of the `SOURCE` header are not part of this specification. - ### 3.28. The `COMMENT` Header ``` From d5e8a8470ed7e4c5449a280f05ddb8af25b2e0e7 Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Sat, 3 Feb 2024 13:59:59 +0100 Subject: [PATCH 36/48] Add note about pitch notation. --- spec.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/spec.md b/spec.md index 2cbd414..6f7d07a 100644 --- a/spec.md +++ b/spec.md @@ -779,8 +779,12 @@ Notes SHOULD NOT overlap, i.e. the start beat of a note being between the start > > Whether negative note starts and/or durations are valid is, hasn't been decided yet. -The pitch of a note is encoded as the number of half-steps relative to C4 (also referred to as middle C). -So a pitch of `5` represent an F4 and a pitch of `-2` represents an A#3. +The pitch of a note is encoded as the number of half-steps relative to `C4` (also referred to as middle C). +So a pitch of `5` represent an `F4` and a pitch of `-2` represents an `A#3`. + +> [!NOTE] +> +> The pitches in this paragraph use [scientific pitch notation](https://en.wikipedia.org/wiki/Scientific_pitch_notation). #### 3.1.1. Regular Notes `:` From 2134bc359fbb5afd384e3dce87f1d557bb959647 Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Sat, 3 Feb 2024 14:09:05 +0100 Subject: [PATCH 37/48] Clarify whitespace in multi-valued headers --- spec.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec.md b/spec.md index 6f7d07a..b489c56 100644 --- a/spec.md +++ b/spec.md @@ -197,7 +197,7 @@ Additionally, multiple occurrences of a multi-valued header are semantically equ where all values are concatenated by commas in order of occurrence. In this way the order of multi-valued headers is significant. -Empty values within a multi-valued header can be removed without changing semantics. +Implementations MAY remove whitespace around individual values of a multi-valued header without changing sematics. Implementations MAY also remove empty values in a multi-valued header without changing semantics. > [!WARNING] > From 67c7b23c5b4d212439cc491066a68fd4ddeea883 Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Sat, 3 Feb 2024 14:09:51 +0100 Subject: [PATCH 38/48] Change some words --- spec.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec.md b/spec.md index b489c56..c262c78 100644 --- a/spec.md +++ b/spec.md @@ -197,7 +197,7 @@ Additionally, multiple occurrences of a multi-valued header are semantically equ where all values are concatenated by commas in order of occurrence. In this way the order of multi-valued headers is significant. -Implementations MAY remove whitespace around individual values of a multi-valued header without changing sematics. Implementations MAY also remove empty values in a multi-valued header without changing semantics. +Implementations MAY remove leading and trailing whitespace of individual values of a multi-valued header without changing sematics. Implementations MAY also remove empty values in a multi-valued header without changing semantics. > [!WARNING] > From c483d2b37f27731a534e20a4ec05ab829718e966 Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Sun, 4 Feb 2024 17:22:33 +0100 Subject: [PATCH 39/48] Fix capitalization --- spec.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec.md b/spec.md index c262c78..efdf72f 100644 --- a/spec.md +++ b/spec.md @@ -2,7 +2,7 @@ The UltraStar file format is a timed text format for describing karaoke songs where singing performance is scored by the karaoke software. -## Status of this document +## Status of this Document This document aims to describe the UltraStar File Format in its most recent version 2.0.0. From f1d62781d3973950e07c7a001f315f83b3d0f307 Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Sun, 4 Feb 2024 17:23:23 +0100 Subject: [PATCH 40/48] Fix header grammar --- spec.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec.md b/spec.md index efdf72f..5ca2d7f 100644 --- a/spec.md +++ b/spec.md @@ -139,13 +139,13 @@ Whitespace around key and value is ignored. > Other terms used for the same concept are “tag”, “attribute” or “field”. ```abnf -file-header = *( header / empty-line ) -header = hash *WSP header-key *WSP colon *WSP header-value *WSP line-break +file-header = *( header-line / empty-line ) +header-line = hash *WSP header-key *WSP colon *WSP header-value *WSP line-break header-key = header-char [ *( WSP / header-char ) header-char ] header-value = single-value / multi-value -multi-value = single-value [ comma single-value ] [ comma ] +multi-value = single-value [ comma multi-value ] [ comma ] single-value = *( header-char / colon ) header-char = %x00-09 / ; exclude line feed From 07847c913be0fd03ee987065bab10722dbe4549f Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Sun, 4 Feb 2024 17:24:45 +0100 Subject: [PATCH 41/48] Remove size of float --- spec.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec.md b/spec.md index 5ca2d7f..bb61775 100644 --- a/spec.md +++ b/spec.md @@ -267,7 +267,7 @@ Since: 0.1.0 The `BPM` header indicates the number of beats per minute. The notes in a song are quantized in beats. A single beat is the smallest unit of time that can be present in a song. -The value is a 32 bit floating point number. +The value is floating point number. The value of this tag is arbitrary in the sense that it is usually 4 to 8 times higher than the actual BPM of a song. > [!WARNING] From c32e59f4386710a90ae663e1937a72d8f4e158ee Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Sun, 4 Feb 2024 17:26:45 +0100 Subject: [PATCH 42/48] Update header grammar --- spec.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec.md b/spec.md index bb61775..f7d8ee6 100644 --- a/spec.md +++ b/spec.md @@ -145,7 +145,7 @@ header-key = header-char [ *( WSP / header-char ) header-char ] header-value = single-value / multi-value -multi-value = single-value [ comma multi-value ] [ comma ] +multi-value = single-value *[ comma single-value ] [ comma ] single-value = *( header-char / colon ) header-char = %x00-09 / ; exclude line feed From cf174ea0d01e559426322d15d6f3f9cbb8b91b6a Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Sun, 4 Feb 2024 17:27:37 +0100 Subject: [PATCH 43/48] Update header grammar --- spec.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec.md b/spec.md index f7d8ee6..9687f85 100644 --- a/spec.md +++ b/spec.md @@ -145,7 +145,7 @@ header-key = header-char [ *( WSP / header-char ) header-char ] header-value = single-value / multi-value -multi-value = single-value *[ comma single-value ] [ comma ] +multi-value = single-value *( comma single-value ) [ comma ] single-value = *( header-char / colon ) header-char = %x00-09 / ; exclude line feed From 4b3bd78ecdffd5e1314d16ca5bf27b999be79523 Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Sun, 4 Feb 2024 17:30:20 +0100 Subject: [PATCH 44/48] Add caution for header-char --- spec.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/spec.md b/spec.md index 9687f85..ce440e7 100644 --- a/spec.md +++ b/spec.md @@ -162,6 +162,10 @@ period = %x2E ; . > > The use of trailing commas in comma-separated header lists has not been decided yet. +> [!CAUTION] +> +> The allowed character sets for header keys and values have not been decided yet. + Comparisons of header keys is case-insensitive. For the sake of consistency header keys SHOULD use only capital letters. Header values are generally case-sensitive unless otherwise specified. From 23b7d87a4928d1e1db2aae5458969e9e3cc05869 Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Sun, 4 Feb 2024 18:54:49 +0100 Subject: [PATCH 45/48] Remove ambiguous grammar spec --- spec.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/spec.md b/spec.md index ce440e7..efedab5 100644 --- a/spec.md +++ b/spec.md @@ -141,9 +141,7 @@ Whitespace around key and value is ignored. ```abnf file-header = *( header-line / empty-line ) header-line = hash *WSP header-key *WSP colon *WSP header-value *WSP line-break -header-key = header-char - [ *( WSP / header-char ) - header-char ] +header-key = 1*header-char header-value = single-value / multi-value multi-value = single-value *( comma single-value ) [ comma ] single-value = *( header-char / colon ) From 079b728495261d3a7715409db678713d64a0a40a Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Sun, 4 Feb 2024 19:01:10 +0100 Subject: [PATCH 46/48] =?UTF-8?q?Floating=20Point=20=E2=86=92=20Decimal?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spec.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/spec.md b/spec.md index efedab5..046d098 100644 --- a/spec.md +++ b/spec.md @@ -266,10 +266,9 @@ Syntax: 1*DIGIT [ period 1*DIGIT ] Since: 0.1.0 ``` -The `BPM` header indicates the number of beats per minute. +The `BPM` header indicates the number of beats per minute as a decimal value. The notes in a song are quantized in beats. A single beat is the smallest unit of time that can be present in a song. -The value is floating point number. The value of this tag is arbitrary in the sense that it is usually 4 to 8 times higher than the actual BPM of a song. > [!WARNING] @@ -402,7 +401,7 @@ The `GAP` value is an integer. > > **Breaking Change** in version 2.0.0 > -> In versions 0.x and 1.x the value of `GAP` could also be a floating point number. +> In versions 0.x and 1.x the value of `GAP` could also be a decimal value. > Since version 2.0.0 this is not allowed anymore. ### 3.12. The `VIDEOGAP` Header @@ -421,7 +420,7 @@ The `VIDEOGAP` value is an integer. > > **Breaking Change** in version 2.0.0 > -> In versions 0.x and 1.x the value of `VIDEOGAP` was specified in seconds as a floating point number. +> In versions 0.x and 1.x the value of `VIDEOGAP` was specified in seconds as a decimal value. > Version 2.0.0 changes this to an integer and milliseconds. ### 3.13. The `NOTESGAP` Header @@ -464,7 +463,7 @@ Both `START` and `END` values are integers. > > **Breaking Change** in version 2.0.0 > -> In versions 0.x and 1.x `START` was specified in seconds as a floating point number. +> In versions 0.x and 1.x `START` was specified in seconds as a decimal value. > Version 2.0.0 changes this to an integer and milliseconds. ### 3.15. The `PREVIEWSTART` Header @@ -484,7 +483,7 @@ In its absence implementations SHOULD default to the start of the medley section > > **Breaking Change** in version 2.0.0 > -> In versions 0.x and 1.x `PREVIEWSTART` was specified in seconds as a floating point number. +> In versions 0.x and 1.x `PREVIEWSTART` was specified in seconds as a decimal value. > Version 2.0.0 of this specification changes this to an integer and milliseconds. ### 3.16. The `MEDLEYSTART` and `MEDLEYEND` Headers From 199818333875c6201f6ca474caf455d2b2df7337 Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Sun, 11 Feb 2024 13:10:08 +0100 Subject: [PATCH 47/48] Add caution for year header --- spec.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/spec.md b/spec.md index 046d098..79066c7 100644 --- a/spec.md +++ b/spec.md @@ -539,13 +539,17 @@ The value of this header is compared case-insensitively. ``` Required: No Multi-Valued: No -Syntax: 4*DIGIT +Syntax: 4DIGIT Since: 0.2.0 ``` The `YEAR` indicates the year in which the song was released. The value must be a positive integer. +> [!CAUTION] +> +> The exact syntax of the `YEAR` header has not been decided yet. + ### 3.20. The `GENRE` Header ``` From 9b1f53a3ed82082ab41a7ea5a68476c8a26ce424 Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Sun, 11 Feb 2024 13:11:07 +0100 Subject: [PATCH 48/48] Fix number syntax --- spec.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/spec.md b/spec.md index 79066c7..e58f3ea 100644 --- a/spec.md +++ b/spec.md @@ -754,9 +754,9 @@ note = note-type line-break note-type = %x21-22 / %x24-7E ; Visible ASCII-characters except space and # -start-beat = *DIGIT -duration = *DIGIT -pitch = [ minus ] *DIGIT +start-beat = 1*DIGIT +duration = 1*DIGIT +pitch = [ minus ] 1*DIGIT note-text = 1*( %x20-10FFFF ) minus = %x2D ; - @@ -937,7 +937,7 @@ end-of-phrase =/ dash WSP start-beat WSP rel-offset *WSP line-break -rel-offset = *DIGIT +rel-offset = 1*DIGIT ``` Note that the syntax in relative mode is incompatible with the normal syntax.