CSNG (File Format): Difference between revisions
Jump to navigation
Jump to search
Fix pitch/mod encoding scheme
imported>Jackoalan (Clarify nature of delta time encoding) |
imported>Jackoalan (Fix pitch/mod encoding scheme) |
||
Line 163: | Line 163: | ||
next = streamIn.PeekU16() | next = streamIn.PeekU16() | ||
if next == 0: | if next == 0: | ||
# Automatically consume no-op and continue accumulating time value | |||
total += 0xffff | total += 0xffff | ||
streamIn.seekAhead(2) | streamIn.seekAhead(2) | ||
Line 169: | Line 170: | ||
return total | return total | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=====No-Op Command===== | |||
When the two bytes following the delta-time are both zero, this is a no-op command. | |||
As mentioned before, no-ops are useful for accumulating delta times greater than 65535. | |||
=====Note Command===== | =====Note Command===== | ||
Line 253: | Line 260: | ||
====Continuous Pitch / Modulation Data==== | ====Continuous Pitch / Modulation Data==== | ||
If the pitch or mod offsets in a region are non-zero, they point to a buffer of | If the pitch or mod offsets in a region are non-zero, they point to a buffer of | ||
(delta-tick, delta-value) pairs | (delta-tick, delta-value) pairs. The delta times are encoded as unsigned 7/15 bit values | ||
the absolute time and value, summing each consecutive update for the current time/values. | and the delta values are signed 7/15-bit values. The values are promoted to 15-bit if they | ||
exceed their 7-bit range. In this case, the highest bit is set on the first byte in the pair | |||
(0x80). The decoder must track the absolute time and value, summing each consecutive update | |||
for the current time/values. | |||
Similar to the command stream, when the delta time exceeds 15 bit range (>32767), extra pairs | |||
with a value delta are inserted. | |||
<syntaxhighlight lang="python" line="1"> | <syntaxhighlight lang="python" line="1"> | ||
def | def SignExtend7(value): | ||
return (value & 0x3f) - (value & 0x40) | |||
def SignExtend15(value): | |||
return (value & 0x3fff) - (value & 0x4000) | |||
return | |||
def | def DecodeSignedValue(streamIn): | ||
byte0 = streamIn.ReadU8() | |||
if byte0 & 0x80: | |||
byte1 = streamIn.ReadU8() | |||
return SignExtend15(byte1 | ((byte0 & 0x7f) << 8)) | |||
else: | |||
return SignExtend7(byte0) | |||
def DecodeUnsignedValue(streamIn): | |||
byte0 = streamIn.ReadU8() | |||
if byte0 & 0x80: | |||
byte1 = streamIn.ReadU8() | |||
return byte1 | ((byte0 & 0x7f) << 8) | |||
else: | |||
return byte0 | |||
def DecodeDeltaPair(streamIn): | |||
return | ret = [0,0] | ||
while ret[1] == 0: | |||
ret[0] += DecodeUnsignedValue(streamIn) | |||
ret[1] = DecodeSignedValue(streamIn) | |||
return ret | |||
</syntaxhighlight> | </syntaxhighlight> | ||