Extensions
Port assign
Octavia supports the following ways of specifying port assignment: standard port assign, XGworks port assign.
Standard port assign
This is a single-byte meta event of type 33
(0x21
).
pp
pp
:00
..ff
→ Port 1..256
XGworks port assign
This is an implementation-specific meta event with schema provided below.
43 00 01 pp
pp
:00
..ff
→ Port 1..256
Lyrics
Octavia supports the following ways of specifying lyrics: standard lyrics, text event substitution, XF lyrics.
Standard lyrics
This is a variable-length meta event of type 05
(0x05
).
To make any SMF parser function normally, the character encoding used must be backwards-compatible with ASCII. While suitable for use in any way desired, for karaoke capabilities, data programmers must follow the standard authored by AMEI (United States) and TUNE1000 Corporation (Canada). Below is an extension compatible to both of the mentioned standards.
Despite the original version devised by the TUNE1000 Corporation requires the file to be in format 0 (single track), Octavia has no problem handling format 1 (multiple single-channel tracks) and format 2 (multiple mixed-channel tracks) files just fine without a constraining hardware.
Escape sequences
This has not yet been supported by Octavia.
These escape sequences will affect how the lyrics events are parsed.
\v
: Vertical tab.\r
: Carriage return.\n
: Line feed.\\
: Backslash itself.
These escape sequences won't affect the lyrics event parsing.
\%
: The percent sign itself. Unescaped percent signs are used to notate chords.\[
,\]
: The square brackets themselves. Unescaped square brackets are used to notate rubies.\{
,\}
: The curly braces themselves. Unescaped curly braces are used to specify tags.
Controls
Word break
When the space character
is received as the last character in the event payload, the continuous word stream will be broken. In Octavia's case, it will try to exclude the space characters at the beginning and at the end of the event payload from duration calculation. This, however, also means that space characters sandwiched between other characters will not break the word stream.
Karaoke implementations should not consider word breaks in their duration calculation.
End of line
When either \v
(extension) or \r
(AMEI) is received, a new line is signaled.
End of paragraph
When \n
(AMEI) is received, a new paragraph/section is signaled.
Tags
This has not yet been supported by Octavia.
Can be used to provide additional data. Tag specifiers can be in all caps, captilized at initials, or all in small caps.
For compatibility reasons, tags must be specified at the beginning of each lyrics event, and there should only be a single tag in each.
Text encoding
Specifies the indicated text encoding of the lyrics, valid until the next override with events of the same type. Schema below.
{@${Encoding}}
A list of known possible encodings with their specifiers available below.
Specifier | Encoding | Octavia |
---|---|---|
Unicode | UTF-8 | UTF-8 (utf-8 ) |
Latin | ISO 8859-1 | ISO 8859-15 (l9 ) |
JP | Shift-JIS | Shift-JIS (sjis ) |
There are exceptions for handling text encoding. If the raw binary payload begins with the following values, the text encoding will be overridden to the ones listed below.
Bytes | Encoding |
---|---|
EF BB BF | UTF-8 |
FF FE | UTF-16LE |
FE FF | UTF-16BE |
Examples below.
{@Latin} # ISO 8859-15
{@Unicode} # UTF-8
{@JP} # Shift-JIS
Song metadata
Provides metadata. While overwriting elsewhere mostly, Octavia allows stacking of certain metadata tags.
{#${key}=${value}}
Recommended keys below.
Key | Use | Stackable | Standard |
---|---|---|---|
Artist | Artist Performer | ✓ | ✓ |
Composer | Composer | ✓ | ✓ |
Lyrics | Lyricist | ✓ | ✓ |
Title | Song title | ✕ | ✓ |
Album | Album | ✓ | ✕ |
By | SMF programmer | ✕ | ✕ |
Date | Release date | ✕ | ✕ |
Genre | Genre | ✕ | ✕ |
Track | Track number/total | ✕ | ✕ |
Examples below.
{#Artist=James Lord Pierpont}
{#Title=Jingle Bells}
Tag end
{#}
Explicitly indicates completion of tags.
Rubies
This has not yet been supported by Octavia.
Used to annotate the pronunciation of each unit. The left square bracket ([
) starts the ruby annotation for the text in the exact event before the markup, while the right square bracket (]
) ends the active ruby annotation. It is recommended to separate each syllable inside the rubies in dedicated events.
Example below.
あ
の
地[ち]
平[へ
い]
線[せ
ん]
\r
輝[か
が
や]
く
の
は
\r
Which should be displayed as the example below.
あの地平線
輝くのは
Some examples below. Green marks recommended practices, yellow marks practices supported but not recommended, and red marks unsupported mistakes. Practices marked in yellow will often result in errors in time parsing.
Case | Example | Result |
Ruby begins with preceding text |
|
馬だ |
Separate first syllable(s) |
|
馬だ |
Separate syllables not split |
|
馬だ |
Separate ruby end markup |
|
馬だ |
Separate ruby end markup with the next syllable |
|
馬だ |
Next syllable directly with a proper end ruby |
|
馬だ |
Ruby begins without preceding text |
|
馬だ |
[ in a ruby |
|
馬だ |
] out of a ruby |
|
馬だ] |
Control characters in a ruby |
|
馬だ |
|
馬だ | |
|
馬だ | |
|
馬だ | |
|
馬だ |
Chords
It is possible to include chord info. See the TUNE chords section for further information.
Lyrics feed
While it is possible to provide lyrics via unorthodox means, it is generally recommended to conform to the following to ensure maximum compatibility.
- Every syllable should have its dedicated lyrics event, with space appended to the last syllable or the punctuation mark of the last syllable of a word.
- New lines (
\v
,\r
) and new sections (\n
) should have dedicated lyrics events.
There are some additional tips as well.
- If there are no lyrics immediately at the beginning, placing a blank lyrics event or specifying tags in the first measure is recommended to turn on lyrics for certain devices.
- Due to display area limitations, it's recommended that lines should be within 40 characters. Parsers, however, should not stop unintentionally if that limit is exceeded.
- The dedicated new line/section events should be emitted after the last syllable of the line has ended, not immediately.
A recommended example below.
00 FF 05 01 "A"
08 FF 05 02 "ma"
08 FF 05 05 "zing "
08 FF 05 05 "grace"
04 FF 05 01 "\r" // New line
04 FF 05 04 "How "
08 FF 05 06 "sweet "
08 FF 05 04 "the "
08 FF 05 05 "sound"
04 FF 05 01 "\r" // New line
04 FF 05 05 "That "
08 FF 05 06 "saved "
08 FF 05 02 "a "
08 FF 05 07 "wretch "
08 FF 05 05 "like "
08 FF 05 02 "me"
04 FF 05 01 "\n" // New section
04 FF 05 02 "I "
08 FF 05 05 "once "
08 FF 05 04 "was "
08 FF 05 04 "lost"
04 FF 05 01 "\r" // New line
04 FF 05 04 "But "
08 FF 05 04 "now "
08 FF 05 02 "I "
08 FF 05 05 "found"
04 FF 05 01 "\r" // New line
04 FF 05 04 "Was "
08 FF 05 06 "blind "
08 FF 05 04 "but "
08 FF 05 04 "now "
08 FF 05 02 "I "
08 FF 05 03 "see"
04 FF 05 01 "\n" // New section
Text event substitution
Developed by TUNE1000 Corporation under the supposed name "Soft Karaoke".
As the name used by Octavia suggests, these events hijack the standard text meta events. When toggled on, the text event substitution parser will take over the text event emitter.
Despite the original version devised by the TUNE1000 Corporation requires the file to be in format 1 (multiple single-chanel tracks), Octavia has no problem handling format 0 (single track) and format 2 (multiple mixed-channel tracks) files just fine without a constraining hardware.
Trigger
Upon receiving the karaoke trigger among the text events, the text event substitution lyrics parser shall take over for the majority of the text events, leaving only tags intact. See "karaoke trigger" below for information.
Tags
Tag parsing shall be exempt from lyrics handling. Tags all precede with @
, with the exact type specified for only a single byte. Each text event can only contain a single tag.
Karaoke trigger
Specified with @K
. Contains either file type or copyright information.
More often than not, you will receive @KMIDI KARAOKE FILE
than any other text event. If the event is received exactly as-is, no copyright information will be displayed from it.
Language
Specified with @L
. Contains a four-letter code of the language of the lyrics, which might be used to indicate the used text encoding. The only known codes are listed below, as such please contribute if possible!
Code | Language | Encoding |
---|---|---|
ENGL | English | ISO 8859-15 (l9 ) |
Title
Specified with @T
. The fields listed below could be contained, which most doesn't have any way to distinguish.
- Song title (must be the first
@T
event) - Song artist (must be the second
@T
event) - Sequencer
Information
Specified with @I
. Contains "other information", which has no surviving documentation anywhere.
Controls
Control character can only appear as the first character of each text event.
New line
When /
is received, a new line is signalled.
New section
When \\
is received, a new section is signalled.
Lyrics feed
Similar to the standard lyrics, while it is possible to provide lyrics via unorthodox means, to ensure maximum compatibility, it is generally recommended to dedicate every syllable to their own events, with spaces either at the beginning or the end of a word.
XF lyrics
Developed by Yamaha Corporation.
XF lyrics events replace the standard lyrics meta events. When toggled on, the XF lyrics parser will take over the standard lyrics parser.
Trigger
Documentation is not finished for this section.
Upon receiving the following cue point meta event (type 7
, 0x07
), the XF lyrics parser shall begin to take over the standard lyrics parser. Said event also provides text encoding information of lyrics to the parser, while .
Part cues
Upon receiving a 2-byte cue point meta event that begins with an ampersand (&
), the XF cue parser shall attempt interpreting XF part cues. Valid values are listed below.
&m
: Male&f
: Female&c
: Chorus&s
: Solo&p
: Plural or mixed&w
: Words or spoken line&x
: Non-vocal
If non-vocal part cues are active, lyrics shall not be interpreted as karaoke, thus no duration calculations shall be performed. They are used to show functional information other than lyrics, such as INTRO
(イントロ
in Japanese), INTERLUDE
(間奏
in Japanese) and ENDING
(エンディング
in Japanese) markings.
Scenes
Upon receiving a cue point meta event that begins with a hash (#
), the XF cue parser shall attempt interpreting XF scene numbers.
Usually specified as a three-digit number, like #001
. Only one-indexed integers are considered valid scene numbers.
Controls
Escape
Prefix any of the following control characters with a backslash (\
) to display themselves as-is. Use double backslashes (\\
) to show the backslash itself.
Space
Instead of a normal ASCII space (
), XF uses carets (^
) for spaces.
Usually appears at the end of each XF lyrics event. Octavia handles all occurances, but will only exclude ones at either end of a string from duration calculation.
New line
Instead of a normal ASCII carriage return (\r
), XF uses slashes (/
) to signal new lines. Percent signs (%
) are also used to signal new lines, however even if Octavia handles them as if they are slashes, the original specification intended them to be semantic breaks with or without actual line breaks, and to be applicable on constrained displays.
Usually appears at the end of each XF lyrics event. If the preceding syllable takes a little bit too long, it's recommended to have a dedicated new line event.
New section
Instead of a normal ASCII line feed (\n
), XF uses left angle brackets (<
) to signal new sections.
Usually appears at the beginning of each XF lyrics event. Dedicating events to signal new sections is not recommended.
Tab
Instead of a normal ASCII horizontal tab (\t
), XF uses right angle brackets (>
) to provide horizontal tabs.
Usually appears at the beginning of each XF lyrics event. Tabs should generally only be used at the beginning of a line.
Rubies
This has not yet been supported by Octavia.
Used to annotate the pronunciation of each unit.
There are two types of rubies in XF, primary and secondary. Primary rubies are annotated via square brackets ([]
), while secondary rubies are annotated via round brackets (()
). If display permits, primary rubies shall always be displayed. Secondary rubies are used to assist in utility functions like searching, thus should be hidden from view.
Rubies specified with curly braces ({}
) called "auxillery text" are considered invalid, thus ignored entirely in Octavia, however XF do recommend showing them as lyrics as-is.
Lyrics feed
See the XF controls section to acknowledge recommendations on producing XF lyrics.
Solton
This has not yet been supported by Octavia.
Developed by Keytron Laboratories.
Solton lyrics events augment the standard lyrics meta events.
Trigger
Solton lyrics do not have a toggle. However, because the first characters specified by Solton will always be either <
or %
, these two characters can serve as suggestions that the specific lyric event could be in the Solton format.
Chords
It is possible to include chord info. See the Solton chords section for further information.
Lyrics feed
When a line of lyrics get emitted with the <
prefix, none of the characters will be immediately highlighted. The position of the highlighted character is instead controlled by cc31 on channel 1, with the value 0
highlighting nothing. This implies that cc31 will be initialized to 0
, and implicitly restricts each line of lyrics to 127 characters, prefix not included.
00 FF 05 ll <Nom Olenian # Hightlights nothing
08 B0 1F 03 # Nom
08 B0 1F 05 # Nom O
08 B0 1F 07 # Nom Ole
08 B0 1F 0B # Nom Olenian
08 B0 1F 00 # Highlights nothing again
00 FF 05 ll <Very tasty # Still highlights nothing
08 B0 1F 02 # Ve
08 B0 1F 04 # Very
08 B0 1F 07 # Very ta
08 B0 1F 0A # Very tasty
As demonstrated by the example, the lyrics events must be delivered before the highlighting cc31 events. Before a new line of lyrics is delivered, it's recommended to have cc31 reset to 0
for compatibility reasons, even though Octavia will automatically reset it to 0
on reception.
Chords
Octavia supports the following ways of specifying chord information: XF chord type, YMCS chord control.
TUNE chords
This has not yet been supported by Octavia.
This is a text meta event with schema provided below. Each specific chord must be separated with a forward slash (/
).
${root}${accidental}${chordType}
root
: Any ofC
,D
,E
,F
,G
,A
andB
. Must be a single character.accidental
: Any ofb
(flat),#
(sharp). Must be a single character, thus cannot be omitted.chordType
: The standard chord notation. See the "specifier" field in the chord list.
Examples include "E
" (space is preserved!), E m7(11)
, G#sus4
and AbM7/Bb
.
Solton chords
This has not yet been supported by Octavia.
This is a lyrics meta event with schema provided below.
${root}${accidental}${chordType}
root
: Any ofC
,D
,E
,F
,G
,A
andB
. Must be a single character.accidental
: Any ofbbb
,bb
,b
(flat), omitted (natural),#
(sharp),##
or###
.chordType
: The standard chord notation. See the "specifier" field in the chord list.
The whole chord event must be prefixed with a percent sign (%
). While the original specification may only allow a single chord to be specified, Octavia supports specifying multiple delimited with either a forward slash (/
) or a space (
).
XF chord type
This is an implementation-specific meta event with schema provided below.
43 7B 91 as cc as cc
a
:0
..6
→ ♭𝄫, 𝄫, ♭, ♮, ♯, 𝄪, 𝄪♯s
:1
..7
→ C, D, E, F, G, A, Bcc
: See the "XF ID" field in the chord list.
Notes:
- When
as
is set to7F
, the note is considered disabled. Anyas
byte set to7F
will immediately halt chord parsing on the event.
YMCS chord control
This is a SysEx message with schema provided below.
43 7E 02 as cc as cc
The details are exactly the same as above.
Chord list
Type | ID | XF ID | Specifier | Full name | Voicing | Semitones | On QY? | On PSR? |
---|---|---|---|---|---|---|---|---|
Other | ff |
22 (has root)7f (no root) |
--- |
No chords | 1 | 0 | ||
Major | 00 |
00 |
M |
Major | 1+3+5 | 0, 4, 7 | ||
02 |
✕ | b5 |
Flatted fifth | 1+3+♭5 | 0, 4, 6 | |||
03 |
07 |
aug |
Augmented | 1+3+♯5 | 0, 4, 8 | |||
01 |
20 |
sus4 |
Suspended fourth | 1+4+5 | 0, 5, 7 | |||
05 |
01 |
6 |
Sixth | 1+5+6 | 0, 7, 9 | |||
1+3+5+6 | 0, 4, 7, 9 | |||||||
06 |
04 |
(9) add9 |
Add ninth | 1+2+3+5 | 0, 2, 4, 7 | |||
07 |
06 |
6(9) 6add9 |
Sixth ninth | 1+2+3+6 | 0, 2, 4, 9 | |||
1+2+3+5+6 | 0, 2, 4, 7, 9 | |||||||
3+6+2 | 4, 9, 14 | |||||||
20 |
02 |
M7 |
Major seventh | 1+3+7 | 0, 4, 11 | |||
1+3+5+7 | 0, 4, 7, 11 | |||||||
22 |
✕ | M7(b5) |
Major seventh flatted fifth | 1+3+♭5+7 | 0, 4, 6, 11 | |||
23 |
1c |
M7aug |
Major seventh augmented | 1+♯5+7 | 0, 8, 11 | |||
1+3+♯5+7 | 0, 4, 8, 11 | |||||||
26 |
05 |
M7(9) M7add9 |
Major seventh add ninth | 1+2+3+7 | 0, 2, 4, 11 | |||
1+2+3+5+7 | 0, 2, 4, 7, 11 | |||||||
24 |
03 |
M7(#11) |
Major seventh sharp eleventh | 1+2+3+♯4+7 | 0, 2, 4, 6, 11 | |||
1+3+♯4+5+7 | 0, 4, 6, 7, 11 | |||||||
1+2+3+♯4+5+7 | 0, 2, 4, 6, 7, 11 | |||||||
Minor | 10 |
08 |
m |
Minor | 1+♭3+5 | 0, 3, 7 | ||
70 |
21 |
sus2 1+2+5 |
Suspended second | 1+2+5 | 0, 2, 7 | |||
15 |
09 |
m6 |
Minor sixth | 1+♭3+5+6 | 0, 3, 7, 9 | |||
16 |
0c |
m(9) madd9 |
Minor add ninth | 1+2+♭3+5 | 0, 2, 3, 7 | |||
17 |
✕ | m6(9) m6add9 |
Minor sixth add ninth | 1+♭3+6+2 | 0, 4, 9, 14 | |||
1+♭3+5+6+2 | 0, 3, 7, 9, 14 | |||||||
♭3+6+2 | 3, 9, 14 | |||||||
50 |
0a |
m7 |
Minor seventh | 1+♭3+♭7 | 0, 3, 10 | |||
1+♭3+5+♭7 | 0, 3, 7, 10 | |||||||
52 |
0b |
m7b5 |
Minor seventh flatted fifth Half-diminished chord |
1+♭3+♭5+♭7 | 0, 3, 6, 10 | |||
53 |
✕ | m7aug |
Minor seventh augmented | 1+♭3+♯5+♭7 | 0, 3, 8, 10 | |||
56 |
0d |
m7(9) m7add9 |
Minor seventh add ninth | 1+2+♭3+♭7 | 0, 2, 3, 7 | |||
1+2+♭3+5+♭7 | 0, 2, 3, 7, 10 | |||||||
♭3+♭7+2 | 3, 10, 14 | |||||||
|
0e |
m7(11) |
Minor seventh eleventh | 1+♭3+4+5 | 0, 3, 5, 7 | |||
1+2+♭3+4+5 | 0, 2, 3, 5, 7 | |||||||
1+♭3+4+5+♭7 | 0, 3, 5, 7, 10 | |||||||
1+2+♭3+4+5+♭7 | 0, 2, 3, 5, 7, 10 | |||||||
30 |
0f |
mM7 |
Minor major seventh | 1+♭3+7 | 0, 3, 11 | |||
1+♭3+5+7 | 0, 3, 7, 11 | |||||||
32 |
✕ | mM7b5 |
Minor major seventh flatted fifth | 1+♭3+♭5+7 | 0, 3, 6, 11 | |||
36 |
10 |
mM7(9) mM7add9 |
Minor major seventh add ninth | 1+2+♭3+7 | 0, 2, 3, 7, 11 | |||
1+2+♭3+5+7 | 0, 2, 3, 7, 11 | |||||||
Dominant | 40 |
13 |
7 |
Seventh | 1+3+♭7 | 0, 4, 10 | ||
1+5+♭7 | 0, 7, 10 | |||||||
1+3+5+♭7 | 0, 4, 7, 10 | |||||||
41 |
14 |
7sus4 |
||||||
42 |
15 |
7b5 |
||||||
43 |
1d |
7aug |
||||||
|
19 |
7(b9) |
||||||
46 |
16 |
7(9) 7add9 |
||||||
|
1b |
7(#9) |
||||||
44 |
17 |
7(#11) |
||||||
|
1a |
7(b13) |
||||||
|
18 |
7(13) |
||||||
Diminished | 75 |
11 |
dim |
Diminished | 1+♭3+♭5 | 0, 3, 6 | ||
76 |
12 |
dim7 |
Diminished seventh | 1+♭3+♭5+6 | 0, 3, 6, 9 | |||
Other | 73 |
1e |
1+8 |
Perfect octave | 1+8 | 0, 12 | ||
72 |
1f |
5 1+5 |
Power | 1+5 | 0, 7 | |||
71 |
✕ | sus2sus4 |
Suspended second, suspended fourth | 1+2+4+5 | 0, 2, 5, 7 | |||
74 |
✕ | cc |
Cancel | 1+♭2+2 | 0, 1, 2 |
Native chord mapping
Type | Sub-category | M ( 000 ) | M7 ( 010 ) | m ( 001 ) | mM7 ( 011 ) | 7 ( 100 ) | m7 ( 101 ) | Misc. ( 111 ) |
---|---|---|---|---|---|---|---|---|
Normal | - ( 0000 ) | M | M7 | m | mM7 | 7 | m7 | sus2 |
sus4 ( 0001 ) | sus4 | 7sus4 | sus2sus4 |
|||||
b5 ( 0010 ) | b5 | M7(b5) | mM7b5 | 7b5 | m7b5 | 5 |
||
aug ( 0011 ) | aug | M7aug | 7aug | m7aug | 1+8 |
|||
#11 ( 0100 ) | M7(#11) | 7(#11) | cc |
|||||
6 ( 0101 ) | 6 | m6 | dim |
|||||
add9 ( 0110 ) | add9 | M7(9) | madd9 | mM7(9) | 7(9) | m7(9) | dim7 |
|
6(9) ( 0111 ) | 6(9) | m6add9 | ||||||
Alt. 1 | 9 | 9 | M9 | m9 | mM9 | 7(b13) | ||
11 | 11 | M11 | m11 | M9(#11) | m7(11) | |||
13 | 13 | M13 | m13 | M13(#11) | 7(13) | |||
Alt. 2 | b9 | 7b5(b9) | 7aug(b9) | 11b9 | 13b9 | 7(b9) | 9b5 | |
#9 | 7b5(#9) | 7aug(#9) | 7(#9) | 9aug |