Skip to content

Commit

Permalink
BREAKING CHANGE: *.umpx now stores track size in bytes, not # of UMPs.
Browse files Browse the repository at this point in the history
This addresses #23
  • Loading branch information
atsushieno committed Oct 11, 2022
1 parent 8cab7ae commit 079e433
Show file tree
Hide file tree
Showing 7 changed files with 22 additions and 15 deletions.
18 changes: 9 additions & 9 deletions docs/MIDI2_FORMATS.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,18 @@ We provide two options for UMP-based music files:

```
// Data Format:
// identifier: 0xAAAAAAAAAAAAAAAA (16 bytes)
// i32 deltaTimeSpec
// i32 numTracks
// tracks - each track contains:
// identifier: 0xEEEEEEEEEEEEEEEE (16 bytes)
// i32 numUMPs
// umps (i32, i64 or i128) in BIG endian
// - identifier 0xAAAAAAAAAAAAAAAA (16 bytes)
// - i32 deltaTimeSpec
// - i32 numTracks
// - tracks - each track contains these items in order:
// - identifier 0xEEEEEEEEEEEEEEEE (16 bytes)
// - i32 sizeInBytes
// - UMPs (i32, i64 or i128) in BIG endian
```

If `deltaTimeSpec` is a positive integer, it works like the value in SMF header chunk. There is no "format" specifier in this format - if "numTracks" is 1 then it is obviously compatible with FORMAT 0.
If `deltaTimeSpec` is a positive integer, it works like the `division` field value in SMF header chunk. There is no "format" specifier in this format - if "numTracks" is 1 then it is obviously compatible with FORMAT 0.

All the UMPs are serialized in BIG endian for persistant stability across platforms.
All the UMPs are serialized in BIG endian per 32-bit integer for persistant stability across platforms and better binary readability.

## META events

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,16 @@ internal class Midi2MusicWriter(val stream: MutableList<Byte>) {
ret.add(music.tracks.size)
for (track in music.tracks) {
(0..3).forEach { _ -> ret.add(0xEEEEEEEE.toInt()) }
ret.add(track.messages.size)
for (message in track.messages)
ret.add(0) // stub for `size` field, to be replaced later
val trackStartOffset = ret.size
for (message in track.messages) {
when (message.messageType) {
5 -> ret.addAll(sequenceOf(message.int1, message.int2, message.int3, message.int4))
3, 4 -> ret.addAll(sequenceOf(message.int1, message.int2))
else -> ret.add(message.int1)
}
}
ret[trackStartOffset - 1] = (ret.size - trackStartOffset) * 4 // sizeof(Int)
}
return ret
}
Expand Down Expand Up @@ -89,9 +92,13 @@ internal class Midi2MusicReader(val music: Midi2Music, stream: List<Byte>) {
private fun readTrack(): Midi2Track {
val ret = Midi2Track()
expectIdentifier16(0xEE.toByte())
val numUMPs = reader.readInt32()
for (t in 0 until numUMPs)
ret.messages.add(reader.readUmp())
val numBytes = reader.readInt32()
var readSize = 0
while (readSize < numBytes) {
val ump = reader.readUmp()
readSize += ump.sizeInBytes
ret.messages.add(ump)
}
return ret
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,6 @@ class Midi2MusicTest {
// Note that "stream id" also counts in the packet size in sysex8 (hence 12, not 11).
// Note that umpx is always serialized in BIG endian.
assertContentEquals(musicFileIdentifier + listOf(0, 0, 0, 0) + listOf(0, 0, 0, 1) +musicTrackIdentifier +
listOf(0, 0, 0, 1) + listOf(0x50, 12, 0, 0, 0, 0, 0, ff, ff, ff, 3, 7, 0xA1.toByte(), 0x20, 0, 0), bytes, "umpx")
listOf(0, 0, 0, 16) + listOf(0x50, 12, 0, 0, 0, 0, 0, ff, ff, ff, 3, 7, 0xA1.toByte(), 0x20, 0, 0), bytes, "umpx")
}
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

0 comments on commit 079e433

Please sign in to comment.