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 RLE-compressed
If the pitch or mod offsets in a region are non-zero, they point to a buffer of
(delta-tick, delta-value) pairs, decoding to signed 16-bit precision. The decoder must track
(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.


The algorithm for this RLE is different than the delta-time one for commands. It may
Similar to the command stream, when the delta time exceeds 15 bit range (>32767), extra pairs
scale down to a single byte if able.
with a value delta are inserted.


<syntaxhighlight lang="python" line="1">
<syntaxhighlight lang="python" line="1">
def DecodeRLE(streamIn):
def SignExtend7(value):
     # high-bit shift-trigger RLE, limited to 2 bytes
     return (value & 0x3f) - (value & 0x40)
    term = streamIn.ReadU8()
 
    total = term & 0x7f
def SignExtend15(value):
    if term & 0x80:
     return (value & 0x3fff) - (value & 0x4000)
        total = total * 256 + streamIn.ReadU8()
     return total


def DecodeContinuousRLE(streamIn, isValue):
def DecodeSignedValue(streamIn):
     total = 0
     byte0 = streamIn.ReadU8()
     while True:
     if byte0 & 0x80:
         # 1-2 byte RLE accumulated within continuable RLE
         byte1 = streamIn.ReadU8()
        term = DecodeRLE(streamIn)
         return SignExtend15(byte1 | ((byte0 & 0x7f) << 8))
         if term == 0x8000:
    else:
            total += 0xffff
         return SignExtend7(byte0)
            dummy = streamIn.ReadU8()
            continue
         total += term


        # values are signed deltas;
def DecodeUnsignedValue(streamIn):
        # extending into the high-half of 15-bit precision
    byte0 = streamIn.ReadU8()
        if isValue:
    if byte0 & 0x80:
            if total >= 0x4000:
        byte1 = streamIn.ReadU8()
                return total - 0xffff
        return byte1 | ((byte0 & 0x7f) << 8)
            else:
    else:
                return total
        return byte0


         # times are always forward-deltas
def DecodeDeltaPair(streamIn):
         return total
    ret = [0,0]
    while ret[1] == 0:
         ret[0] += DecodeUnsignedValue(streamIn)
         ret[1] = DecodeSignedValue(streamIn)
    return ret
</syntaxhighlight>
</syntaxhighlight>


Anonymous user

Navigation menu