Next data dump.
I’ve reverse-engineered the broad format and some detail about the meta file. It’s not complete, but I’m documenting as I progress here in case other people are interested (or I get bored and stop). As a general comment to Singular: this is not an attractive data format, binary is a brittle format and really you only resort to it on embedded projects that are space-constrained, which Aeros isn’t. I also hope you can see by this progress that you don’t really get any secrecy benefit from binary formats. Want to help me yet?
[MAGIC_NUMBERx1 = 0x0a]
[TITLExN]
[HEADER x20]
= (HEADER[3] = [BPM*2])
= (HEADER[8] = [TIME_SIGNATURE_NUMERATOR])
= (HEADER[10] = [TIME_SIGNATURE_DENOMINATOR])
= (HEADER[19] = [SONG_LIST_INDEX])
[TAG x3] [tag_specific_payload xN]
...
[TAG x3] [tag_specific_payload xN]
...
[TAG x3] [tag_specific_payload xN]
...
[TAG x3] [tag_specific_payload xN]
Some fields are variable length (like [TITLE]
, they are prefixed with a single byte which represents their length.
There appear to be various [TAG]
values, all of the form
9X XX XX
Each tag type has a different payload; and some payloads themselves contain other [TAG]
s. Here’s the tag codes I know:
[TAG] Description
---------------- ------------------------------------------------------
90 01 01 section seems to be only present in stereo
98 01 02 section seems to be always present, contains version
90 06 06 parts list container
9a 06 30 stereo _part_ container of 1
9a 06 2f stereo _part_ container of 1, with no measure count byte
9a 06 38 mono _part_ container of 2
9a 06 37 mono _part_ container of 2, with no measure count byte
9a 06 60 stereo _part_ container of 2
9a 06 5f stereo _part_ container of 2, with no measure count byte
9a 06 19 mono _track_ container
9a 06 18 mono _track_ container, no measure count byte
9a 06 2d stereo _track_ container
9a 06 2c stereo _track_ container, no measure count byte
[90 01 01]
has no payload, and (so far) appears only in stereo songs. I can find no other bits in [HEADER]
that change for a stereo song, so I believe it’s a zero-payload boolean tag.
[98 01 02]
has a payload of this form:
[UNKNOWN x7] [FIRMWARE_VERSION xN]
In the Aeros I’m using the version string is 20 bytes, “4.14.108-aeros-4.0.2”. It seems unlikely (and would be dangerous) for an Aeros to rely on any particular string here, because we’d expect a
future version to be able to load past version’s files. But it’s a sensible choice to keep it here because in an emergency future firmwares could work around bugs using this string to tell them it’s needed.
[90 06 06]
announces the start of the parts tags. I think it’s best to think of it as a variable length container tag. It’s content will be a variable number of “part” [TAGS]
. Given the modes of the Aeros,
there will be 2 or 6.
[PART_TAG0]
...
[PART_TAGn]
[9a 06 30]
et al are the [PART_TAG]
s. I won’t list them all here, and there are likely additional ones I’ve not found yet (see above table). Their payload is:
[PART_HEADER x4] (not yet deciphered)
[TRACK_TAG0 xN]
[TRACK_TAG1 xN]
For some reason the [OPTIONAL_MEASURE_COUNT]
presence (see below) also affects the particular choice of [PART_TAG]
, with the same one less rule applying here as well. I think it can be safely ignored though, as it’s tracks that have lengths, not parts.
[9a 06 19]
et al are the [TRACK_TAG]
s. The various values seem to indicate the presence of a measure count field and whether the track is mono or stereo. Their payload is:
[TRACK_HEADER x4]
[OPTIONAL_MEASURE_COUNT] (see below)
[CHANNEL_A_PAYLOAD]
or, for stereo:
[TRACK_HEADER x3] (not yet deciphered, but always `08 71 18`)
[MEASURE_COUNT_PRESENT] (`c0` when measure count present, `60` otherwise)
[OPTIONAL_MEASURE_COUNT] (see below)
[CHANNEL_A_PAYLOAD]
[CHANNEL_B_PAYLOAD]
The [OPTIONAL_MEASURE_COUNT]
seems to be added when there is more than one measure; and it’s presence is determined by the particular [TRACK_TAG]
used (by observation one less than the numeric value used for the [TRACK_TAG]
with the measure count. If it’s not present, then we can assume one measure. When it is presence the [OPTIONAL_MEASURE_COUNT]
field seems to store one less than the actual measure count. There’s also some complexity with counting non-4/4
measures. I’ve got a feeling that the definition of a “beat” in beats per minute needs closer scrutiny.
The [CHANNEL_x_PAYLOAD]
is
[CHANNEL_INDICATOR] (52 = channel A, 5a = channel B)
[CHANNEL_OTHER x7] (not yet deciphered)
[CHANNEL_WAV_FILENAME xN]