예제 #1
0
파일: s3m.py 프로젝트: valnar1/SickGear
 def createFields(self):
     yield Bits(self, "unused", 2)
     yield Bit(self, "is_tonable")
     yield Bit(self, "16bits")
     yield Bit(self, "loop_bidir")
     yield Bit(self, "loop")
     yield Enum(Bits(self, "origin", 2), self.TYPES)
예제 #2
0
파일: mpeg_ts.py 프로젝트: valnar1/SickGear
    def createFields(self):
        if self._m2ts:
            yield Bits(self, "c", 2)
            yield Bits(self, "ats", 32 - 2)
        yield textHandler(UInt8(self, "sync", 8), hexadecimal)
        if self["sync"].value != 0x47:
            raise ParserError("MPEG-2 TS: Invalid synchronization byte")
        yield Bit(self, "has_error")
        yield Bit(self, "payload_unit_start")
        yield Bit(self, "priority")
        yield Enum(
            textHandler(Bits(self, "pid", 13, "Program identifier"),
                        hexadecimal), self.PID)
        yield Bits(self, "scrambling_control", 2)
        yield Bit(self, "has_adaptation")
        yield Bit(self, "has_payload")
        yield Bits(self, "counter", 4)

        if self["has_adaptation"].value:
            yield AdaptationField(self, "adaptation_field")
        if self["has_payload"].value:
            size = 188
            if self._m2ts:
                size += 4
            size -= (self.current_size // 8)
            yield RawBytes(self, "payload", size)
        if self["has_error"].value:
            yield RawBytes(self, "error_correction", 16)
예제 #3
0
파일: tcpdump.py 프로젝트: valnar1/SickGear
    def createFields(self):
        yield Bits(self, "version", 4, "Version")
        yield Bits(self, "hdr_size", 4, "Header size divided by 5")

        # Type of service
        yield Enum(Bits(self, "precedence", 3, "Precedence"),
                   self.precedence_name)
        yield Bit(self, "low_delay", "If set, low delay, else normal delay")
        yield Bit(self, "high_throu",
                  "If set, high throughput, else normal throughput")
        yield Bit(self, "high_rel", "If set, high relibility, else normal")
        yield NullBits(self, "reserved[]", 2, "(reserved for future use)")

        yield UInt16(self, "length")
        yield UInt16(self, "id")

        yield NullBits(self, "reserved[]", 1)
        yield Bit(self, "df", "Don't fragment")
        yield Bit(self, "more_frag",
                  "There are more fragments? if not set, it's the last one")
        yield Bits(self, "frag_ofst_lo", 5)
        yield UInt8(self, "frag_ofst_hi")
        yield UInt8(self, "ttl", "Type to live")
        yield Enum(UInt8(self, "protocol"), self.PROTOCOL_NAME)
        yield textHandler(UInt16(self, "checksum"), hexadecimal)
        yield IPv4_Address(self, "src")
        yield IPv4_Address(self, "dst")

        size = (self.size - self.current_size) // 8
        if size:
            yield RawBytes(self, "options", size)
예제 #4
0
파일: mpeg_ts.py 프로젝트: valnar1/SickGear
    def createFields(self):
        yield UInt8(self, "length")

        yield Bit(self, "discontinuity_indicator")
        yield Bit(self, "random_access_indicator")
        yield Bit(self, "es_prio_indicator")
        yield Bit(self, "has_pcr")
        yield Bit(self, "has_opcr")
        yield Bit(self, "has_splice_point")
        yield Bit(self, "private_data")
        yield Bit(self, "has_extension")

        if self['has_pcr'].value:
            yield Bits(self, "pcr_base", 33)
            yield Bits(self, "pcr_ext", 9)

        if self['has_opcr'].value:
            yield Bits(self, "opcr_base", 33)
            yield Bits(self, "opcr_ext", 9)

        if self['has_splice_point'].value:
            yield Bits(self, "splice_countdown", 8)

        stuff_len = ((self['length'].value + 1) * 8) - self.current_size
        if self['length'].value and stuff_len:
            yield RawBits(self, 'stuffing', stuff_len)
예제 #5
0
 def createFields(self):
     yield Bits(self, "ts_32_30", 3)
     yield Bit(self, "sync[]")  # =True
     yield Bits(self, "ts_29_15", 15)
     yield Bit(self, "sync[]")  # =True
     yield Bits(self, "ts_14_0", 15)
     yield Bit(self, "sync[]")  # =True
예제 #6
0
    def createFields(self):
        yield Bit(self, "has_private")
        yield Bit(self, "has_pack_lgth")
        yield Bit(self, "has_pack_seq")
        yield Bit(self, "has_pstd_buffer")
        yield Bits(self, "sync[]", 3)  # =7
        yield Bit(self, "has_extension2")

        if self["has_private"].value:
            yield RawBytes(self, "private", 16)

        if self["has_pack_lgth"].value:
            yield UInt8(self, "pack_lgth")

        if self["has_pack_seq"].value:
            yield Bit(self, "sync[]")  # =True
            yield Bits(self, "pack_seq_counter", 7)
            yield Bit(self, "sync[]")  # =True
            yield Bit(self, "mpeg12_id")
            yield Bits(self, "orig_stuffing_length", 6)

        if self["has_pstd_buffer"].value:
            yield Bits(self, "sync[]", 2)  # =1
            yield Enum(Bit(self, "pstd_buffer_scale"),
                       {True: "128 bytes", False: "1024 bytes"})
            yield Bits(self, "pstd_size", 13)
예제 #7
0
 def createFields(self):
     yield Enum(Bits(self, "compression_method", 4), {
         8: "deflate",
         15: "reserved"
     })  # CM
     yield Bits(self, "compression_info", 4,
                "base-2 log of the window size")  # CINFO
     yield Bits(self, "flag_check_bits", 5)  # FCHECK
     yield Bit(self, "flag_dictionary_present")  # FDICT
     yield Enum(
         Bits(self, "flag_compression_level", 2),  # FLEVEL
         {
             0: "Fastest",
             1: "Fast",
             2: "Default",
             3: "Maximum, Slowest"
         })
     if self["flag_dictionary_present"].value:
         yield textHandler(
             UInt32(self, "dict_checksum",
                    "ADLER32 checksum of dictionary information"),
             hexadecimal)
     yield DeflateData(self,
                       "data",
                       self.stream,
                       description="Compressed Data")
     yield textHandler(
         UInt32(self, "data_checksum",
                "ADLER32 checksum of compressed data"), hexadecimal)
예제 #8
0
파일: flac.py 프로젝트: valnar1/SickGear
 def createFields(self):
     yield Bits(self, "sync", 14, "Sync code: 11111111111110")
     yield Bit(self, "reserved[]")
     yield Bit(self, "blocking_strategy")
     yield Bits(self, "block_size", 4)
     yield Enum(Bits(self, "sample_rate", 4), self.SAMPLE_RATES)
     yield Bits(self, "channel_assign", 4)
     yield Bits(self, "sample_size", 3)
     yield Bit(self, "reserved[]")
예제 #9
0
 def __init__(self,
              parent,
              name,
              nbits,
              description="Padding",
              pattern=None):
     Bits.__init__(self, parent, name, nbits, description)
     self.pattern = pattern
     self._display_pattern = self.checkPattern()
예제 #10
0
 def createFields(self):
     yield Bits(self, "scr_32_30", 3)
     yield Bit(self, "sync[]")  # =True
     yield Bits(self, "scr_29_15", 15)
     yield Bit(self, "sync[]")  # =True
     yield Bits(self, "scr_14_0", 15)
     yield Bit(self, "sync[]")  # =True
     yield Bits(self, "scr_ext", 9)
     yield Bit(self, "sync[]")  # =True
예제 #11
0
파일: lzx.py 프로젝트: valnar1/SickGear
 def createFields(self):
     for i in xrange(20):
         yield Bits(self, "pretree_lengths[]", 4)
     pre_tree = build_tree(
         [self['pretree_lengths[%d]' % x].value for x in xrange(20)])
     if not hasattr(self.root, "lzx_tree_lengths_" + self.name):
         self.lengths = [0] * self.num_elements
         setattr(self.root, "lzx_tree_lengths_" + self.name, self.lengths)
     else:
         self.lengths = getattr(self.root, "lzx_tree_lengths_" + self.name)
     i = 0
     while i < self.num_elements:
         field = HuffmanCode(self, "tree_code[]", pre_tree)
         if field.realvalue <= 16:
             self.lengths[i] = (self.lengths[i] - field.realvalue) % 17
             field._description = "Literal tree delta length %i (new length value %i for element %i)" % (
                 field.realvalue, self.lengths[i], i)
             i += 1
             yield field
         elif field.realvalue == 17:
             field._description = "Tree Code 17: Zeros for 4-19 elements"
             yield field
             extra = Bits(self, "extra[]", 4)
             zeros = 4 + extra.value
             extra._description = "Extra bits: zeros for %i elements (elements %i through %i)" % (
                 zeros, i, i + zeros - 1)
             yield extra
             self.lengths[i:i + zeros] = [0] * zeros
             i += zeros
         elif field.realvalue == 18:
             field._description = "Tree Code 18: Zeros for 20-51 elements"
             yield field
             extra = Bits(self, "extra[]", 5)
             zeros = 20 + extra.value
             extra._description = "Extra bits: zeros for %i elements (elements %i through %i)" % (
                 zeros, i, i + zeros - 1)
             yield extra
             self.lengths[i:i + zeros] = [0] * zeros
             i += zeros
         elif field.realvalue == 19:
             field._description = "Tree Code 19: Same code for 4-5 elements"
             yield field
             extra = Bits(self, "extra[]", 1)
             run = 4 + extra.value
             extra._description = "Extra bits: run for %i elements (elements %i through %i)" % (
                 run, i, i + run - 1)
             yield extra
             newfield = HuffmanCode(self, "tree_code[]", pre_tree)
             assert newfield.realvalue <= 16
             newfield._description = "Literal tree delta length %i (new length value %i for elements %i through %i)" % (
                 newfield.realvalue, self.lengths[i], i, i + run - 1)
             self.lengths[i:i + run] = [
                 (self.lengths[i] - newfield.realvalue) % 17
             ] * run
             i += run
             yield newfield
예제 #12
0
파일: cab.py 프로젝트: valnar1/SickGear
 def createFields(self):
     yield Bit(self, "readonly")
     yield Bit(self, "hidden")
     yield Bit(self, "system")
     yield Bits(self, "reserved[]", 2)
     yield Bit(self, "archive",
               "Has the file been modified since the last backup?")
     yield Bit(self, "exec", "Run file after extraction?")
     yield Bit(self, "name_is_utf", "Is the filename using UTF-8?")
     yield Bits(self, "reserved[]", 8)
예제 #13
0
 def createFields(self):
     yield Bit(self, "drop_frame")
     yield Bits(self, "time_hh", 5)
     yield Bits(self, "time_mm", 6)
     yield PaddingBits(self, "time_pad[]", 1)
     yield Bits(self, "time_ss", 6)
     yield Bits(self, "time_ff", 6)
     yield Bit(self, "closed_group")
     yield Bit(self, "broken_group")
     yield PaddingBits(self, "pad[]", 5)
예제 #14
0
파일: ogg.py 프로젝트: valnar1/SickGear
def parseVorbisHeader(parent):
    yield UInt32(parent, "vorbis_version")
    yield UInt8(parent, "audio_channels")
    yield UInt32(parent, "audio_sample_rate")
    yield UInt32(parent, "bitrate_maximum")
    yield UInt32(parent, "bitrate_nominal")
    yield UInt32(parent, "bitrate_minimum")
    yield Bits(parent, "blocksize_0", 4)
    yield Bits(parent, "blocksize_1", 4)
    yield UInt8(parent, "framing_flag")
예제 #15
0
 def createFields(self):
     yield displayHandler(
         Bits(self,
              "offset",
              27,
              description="Offset into file divided by 32"),
         lambda x: hex(x * 32).strip('L'))
     yield displayHandler(
         Bits(self, "size", 5, description="Power-of-2 size of the block"),
         lambda x: hex(1 << x).strip('L'))
예제 #16
0
파일: flac.py 프로젝트: valnar1/SickGear
 def createFields(self):
     yield UInt16(self, "min_block_size", "The minimum block size (in samples) used in the stream")
     yield UInt16(self, "max_block_size", "The maximum block size (in samples) used in the stream")
     yield UInt24(self, "min_frame_size", "The minimum frame size (in bytes) used in the stream")
     yield UInt24(self, "max_frame_size", "The maximum frame size (in bytes) used in the stream")
     yield Bits(self, "sample_hertz", 20, "Sample rate in Hertz")
     yield Bits(self, "nb_channel", 3, "Number of channels minus one")
     yield Bits(self, "bits_per_sample", 5, "Bits per sample minus one")
     yield Bits(self, "total_samples", 36, "Total samples in stream")
     yield RawBytes(self, "md5sum", 16, "MD5 signature of the unencoded audio data")
예제 #17
0
 def createFields(self):
     padding = 0
     position = 0
     streamlength = self["../length"].value
     while position < streamlength * 8:
         next = ord(self.parent.stream.readBytes(self.absolute_address + self.current_size + position, 1))
         if next == 0xff:
             padding += 1
             position += 8
         elif padding:
             yield PaddingBytes(self, "pad[]", padding)
             padding = None
             position = 0
         elif 0x40 <= next <= 0x7f:
             yield Bits(self, "scale_marker", 2)  # 1
             yield Bit(self, "scale")
             scale = self['scale'].value
             if scale:
                 scaleval = 1024
             else:
                 scaleval = 128
             yield textHandler(Bits(self, "size", 13), lambda field: str(field.value * scaleval))
         elif 0x00 <= next <= 0x3f:
             yield Bits(self, "ts_marker", 2)  # 0
             yield Bit(self, "has_pts")
             yield Bit(self, "has_dts")
             if self['has_pts'].value:
                 yield Timestamp(self, "pts")
             if self['has_dts'].value:
                 yield PaddingBits(self, "pad[]", 4)
                 yield Timestamp(self, "dts")
             if self.current_size % 8 == 4:
                 yield PaddingBits(self, "pad[]", 4)
             break
         elif 0x80 <= next <= 0xbf:
             # MPEG-2 extension
             yield PacketElement(self, "pkt")
             break
         else:
             # 0xc0 - 0xfe: unknown
             break
     length = self["../length"].value - self.current_size // 8
     if length:
         tag = self['../tag'].value
         group = self.root.streamgroups[tag]
         parname = self.parent._name
         if parname.startswith('audio'):
             frag = CustomFragment(self, "data", length * 8, MpegAudioFile, group=group)
         elif parname.startswith('video'):
             frag = CustomFragment(self, "data", length * 8, VideoStream, group=group)
         else:
             frag = CustomFragment(self, "data", length * 8, None, group=group)
         self.root.streamgroups[tag] = frag.group
         yield frag
예제 #18
0
파일: swf.py 프로젝트: valnar1/SickGear
 def createFields(self):
     yield Bits(self, "nbits", 5)
     nbits = self["nbits"].value
     if not nbits:
         raise ParserError("SWF parser: Invalid RECT field size (0)")
     yield Bits(self, "xmin", nbits, "X minimum in twips")
     yield Bits(self, "xmax", nbits, "X maximum in twips")
     yield Bits(self, "ymin", nbits, "Y minimum in twips")
     yield Bits(self, "ymax", nbits, "Y maximum in twips")
     size = paddingSize(self.current_size, 8)
     if size:
         yield NullBits(self, "padding", size)
예제 #19
0
def parseAudio(parent, size):
    yield Enum(Bits(parent, "codec", 4, "Audio codec"), AUDIO_CODEC_NAME)
    yield Enum(Bits(parent, "sampling_rate", 2, "Sampling rate"),
               SAMPLING_RATE_TEXT)
    yield Bit(parent, "is_16bit", "16-bit or 8-bit per sample")
    yield Bit(parent, "is_stereo", "Stereo or mono channel")

    size -= 1
    if 0 < size:
        if parent["codec"].value == AUDIO_CODEC_MP3:
            yield Frame(parent, "music_data", size=size * 8)
        else:
            yield RawBytes(parent, "music_data", size)
예제 #20
0
def parseSMPTEOffset(parser, size):
    yield RawBits(parser, "padding", 1)
    yield Enum(Bits(parser, "frame_rate", 2), {
        0: "24 fps",
        1: "25 fps",
        2: "30 fps (drop frame)",
        3: "30 fps"
    })
    yield Bits(parser, "hour", 5)
    yield UInt8(parser, "minute")
    yield UInt8(parser, "second")
    yield UInt8(parser, "frame")
    yield UInt8(parser, "subframe", "100 subframes per frame")
예제 #21
0
파일: gif.py 프로젝트: swipswaps/SickGear
 def createFields(self):
     dictionary = {}
     self.nbits = self.startbits
     CLEAR_CODE = 2**self.nbits
     END_CODE = CLEAR_CODE + 1
     compress_code = CLEAR_CODE + 2
     obuf = []
     output = []
     while True:
         if compress_code >= 2**self.nbits:
             self.nbits += 1
         code = Bits(self, "code[]", self.nbits)
         if code.value == CLEAR_CODE:
             if compress_code == 2**(self.nbits - 1):
                 # this fixes a bizarre edge case where the reset code could
                 # appear just after the bits incremented. Apparently, the
                 # correct behaviour is to express the reset code with the
                 # old number of bits, not the new...
                 code = Bits(self, "code[]", self.nbits - 1)
             self.nbits = self.startbits + 1
             dictionary = {}
             compress_code = CLEAR_CODE + 2
             obuf = []
             code._description = "Reset Code (LZW code %i)" % code.value
             yield code
             continue
         elif code.value == END_CODE:
             code._description = "End of Information Code (LZW code %i)" % code.value
             yield code
             break
         if code.value < CLEAR_CODE:  # literal
             if obuf:
                 chain = obuf + [code.value]
                 dictionary[compress_code] = chain
                 compress_code += 1
             obuf = [code.value]
             output.append(code.value)
             code._description = "Literal Code %i" % code.value
         elif code.value >= CLEAR_CODE + 2:
             if code.value in dictionary:
                 chain = dictionary[code.value]
                 code._description = "Compression Code %i (found in dictionary as %s)" % (
                     code.value, rle_repr(chain))
             else:
                 chain = obuf + [obuf[0]]
                 code._description = "Compression Code %i (not found in dictionary; guessed to be %s)" % (
                     code.value, rle_repr(chain))
             dictionary[compress_code] = obuf + [chain[0]]
             compress_code += 1
             obuf = chain
             output += chain
         code._description += "; Current Decoded Length %i" % len(output)
         yield code
     padding = paddingSize(self.current_size, 8)
     if padding:
         yield NullBits(self, "padding[]", padding)
예제 #22
0
파일: swf.py 프로젝트: valnar1/SickGear
def parseSoundHeader(parent, size):
    yield Bit(parent, "playback_is_stereo")
    yield Bit(parent, "playback_is_16bit")
    yield textHandler(Bits(parent, "playback_rate", 2), bit2hertz)
    yield NullBits(parent, "reserved", 4)

    yield Bit(parent, "sound_is_stereo")
    yield Bit(parent, "sound_is_16bit")
    yield textHandler(Bits(parent, "sound_rate", 2), bit2hertz)
    yield Enum(Bits(parent, "codec", 4), SOUND_CODEC)

    yield UInt16(parent, "sample_count")

    if parent["codec"].value == 2:
        yield UInt16(parent, "latency_seek")
예제 #23
0
파일: asn1.py 프로젝트: valnar1/SickGear
 def createFields(self):
     yield Enum(Bits(self, "class", 2), self.CLASS_DESC)
     yield Enum(Bit(self, "form"), self.FORM_DESC)
     if self['class'].value == 0:
         yield Enum(Bits(self, "type", 5), self.TYPE_DESC)
     else:
         yield Bits(self, "type", 5)
     yield ASNInteger(self, "size", "Size in bytes")
     size = self["size"].value
     if size:
         if self._handler:
             for field in self._handler(self, size):
                 yield field
         else:
             yield RawBytes(self, "raw", size)
예제 #24
0
 def __init__(self, parent, name, description=None):
     Bits.__init__(self, parent, name, 8, description)
     stream = parent.stream
     addr = self.absolute_address
     value = 0
     while True:
         bits = stream.readBits(addr, 8, parent.endian)
         value = (value << 7) + (bits & 127)
         if not (bits & 128):
             break
         addr += 8
         self._size += 8
         if 32 < self._size:
             raise ParserError("Integer size is bigger than 32-bit")
     self.createValue = lambda: value
예제 #25
0
파일: swf.py 프로젝트: valnar1/SickGear
 def createFields(self):
     if self.stream.readBits(self.absolute_address, 6, self.endian) == 63:
         yield Bits(self, "length_ext", 6)
         yield Bits(self, "code", 10)
         yield filesizeHandler(UInt32(self, "length"))
     else:
         yield filesizeHandler(Bits(self, "length", 6))
         yield Bits(self, "code", 10)
     size = self["length"].value
     if 0 < size:
         if self.parser:
             for field in self.parser(self, size):
                 yield field
         else:
             yield RawBytes(self, "data", size)
예제 #26
0
    def createFields(self):
        yield UInt8(self, "id_length", "Length of the image ID field")
        yield UInt8(self, "palette_type", "Colormap present?")
        yield Enum(UInt8(self, "codec", "Pixels encoding"), self.CODEC_NAME)
        yield UInt16(self, "palette_ofs", "Palette absolute file offset")
        yield UInt16(self, "nb_color", "Number of colors in the palette")
        yield UInt8(self, "color_map_size", "Size of each palette entry")
        yield UInt16(self, "x_min")
        yield UInt16(self, "y_min")
        yield UInt16(self, "width")
        yield UInt16(self, "height")
        yield UInt8(self, "bpp", "Bits per pixel")
        yield Bits(self, "alpha_depth", 4, "Alpha channel depth")
        yield Bit(
            self, "x_flip",
            "Flip across the X-axis? (If set, columns run right-to-left)")
        yield Bit(self, "y_flip",
                  "Flip across the Y-axis? (If set, rows run top-to-bottom)")
        yield RawBits(self, "reserved_flags", 2)

        if self["id_length"].value:
            yield RawBytes(self, "image_id", self["id_length"].value)

        if self["palette_type"].value == 1:
            yield PaletteRGB(self, "palette", 1 << self["bpp"].value)

        if self["codec"] in (1, 2, 3):
            yield Pixels(self, "pixels")
        else:
            size = (self.size - self.current_size) // 8
            if size:
                yield RawBytes(self, "raw_pixels", size)
예제 #27
0
 def createFields(self):
     for name in ['arctime', 'atime', 'ctime', 'mtime']:
         yield Bits(self, "%s_count" % name, 2, "Number of %s bytes" % name)
         yield Bit(self, "%s_onesec" % name,
                   "Add one second to the timestamp?")
         yield Bit(self, "%s_present" % name,
                   "Is %s extra time present?" % name)
예제 #28
0
파일: tcpdump.py 프로젝트: valnar1/SickGear
    def createFields(self):
        yield Enum(UInt16(self, "src"), self.port_name)
        yield Enum(UInt16(self, "dst"), self.port_name)
        yield UInt32(self, "seq_num")
        yield UInt32(self, "ack_num")

        yield Bits(self, "hdrlen", 6, "Header lenght")
        yield NullBits(self, "reserved", 2, "Reserved")

        yield Bit(self, "cgst", "Congestion Window Reduced")
        yield Bit(self, "ecn-echo", "ECN-echo")
        yield Bit(self, "urg", "Urgent")
        yield Bit(self, "ack", "Acknowledge")
        yield Bit(self, "psh", "Push mmode")
        yield Bit(self, "rst", "Reset connection")
        yield Bit(self, "syn", "Synchronize")
        yield Bit(self, "fin", "Stop the connection")

        yield UInt16(self, "winsize", "Windows size")
        yield textHandler(UInt16(self, "checksum"), hexadecimal)
        yield UInt16(self, "urgent")

        size = self["hdrlen"].value * 8 - self.current_size
        while 0 < size:
            option = TCP_Option(self, "option[]")
            yield option
            size -= option.size
예제 #29
0
 def createFields(self):
     yield Bits(self, "start_length", 5)
     length = self["start_length"].value
     lengths = []
     for i in xrange(self.symbols):
         while True:
             bit = Bit(self, "change_length[%i][]" % i,
                       "Should the length be changed for symbol %i?" % i)
             yield bit
             if not bit.value:
                 break
             else:
                 bit = Enum(
                     Bit(self, "length_decrement[%i][]" % i,
                         "Decrement the value?"), {
                             True: "Decrement",
                             False: "Increment"
                         })
                 yield bit
                 if bit.value:
                     length -= 1
                 else:
                     length += 1
         lengths.append(length)
     self.final_length = length
     self.tree = build_tree(lengths)
예제 #30
0
파일: swf.py 프로젝트: valnar1/SickGear
def parseDefineSound(parent, size):
    yield UInt16(parent, "sound_id")

    yield Bit(parent, "is_stereo")
    yield Bit(parent, "is_16bit")
    yield textHandler(Bits(parent, "rate", 2), bit2hertz)
    yield Enum(Bits(parent, "codec", 4), SOUND_CODEC)

    yield UInt32(parent, "sample_count")

    if parent["codec"].value == SOUND_CODEC_MP3:
        yield UInt16(parent, "len")

    size = (parent.size - parent.current_size) // 8
    if size:
        yield RawBytes(parent, "music_data", size)