def VersionLength(name):
    """A struct for 32 or 64 bit fields, depending on version field."""

    return Con.IfThenElse(name, lambda ctx: ctx["version"] == 0,
                          Con.UBInt32(None), Con.UBInt64(None))
class WavPackAudio(ApeTaggedAudio, AudioFile):
    """A WavPack audio file."""

    SUFFIX = "wv"
    NAME = SUFFIX
    DEFAULT_COMPRESSION = "standard"
    COMPRESSION_MODES = ("veryfast", "fast", "standard", "high", "veryhigh")

    APE_TAG_CLASS = WavPackAPEv2

    HEADER = Con.Struct(
        "wavpackheader", Con.Const(Con.String("id", 4), 'wvpk'),
        Con.ULInt32("block_size"), Con.ULInt16("version"),
        Con.ULInt8("track_number"), Con.ULInt8("index_number"),
        Con.ULInt32("total_samples"), Con.ULInt32("block_index"),
        Con.ULInt32("block_samples"),
        Con.Embed(
            Con.BitStruct("flags", Con.Flag("floating_point_data"),
                          Con.Flag("hybrid_noise_shaping"),
                          Con.Flag("cross_channel_decorrelation"),
                          Con.Flag("joint_stereo"), Con.Flag("hybrid_mode"),
                          Con.Flag("mono_output"),
                          Con.Bits("bits_per_sample", 2),
                          Con.Bits("left_shift_data_low", 3),
                          Con.Flag("final_block_in_sequence"),
                          Con.Flag("initial_block_in_sequence"),
                          Con.Flag("hybrid_noise_balanced"),
                          Con.Flag("hybrid_mode_control_bitrate"),
                          Con.Flag("extended_size_integers"),
                          Con.Bit("sampling_rate_low"),
                          Con.Bits("maximum_magnitude", 5),
                          Con.Bits("left_shift_data_high", 2),
                          Con.Flag("reserved2"), Con.Flag("false_stereo"),
                          Con.Flag("use_IIR"), Con.Bits("reserved1", 2),
                          Con.Bits("sampling_rate_high", 3))),
        Con.ULInt32("crc"))

    SUB_HEADER = Con.Struct(
        "wavpacksubheader",
        Con.Embed(
            Con.BitStruct("flags", Con.Flag("large_block"),
                          Con.Flag("actual_size_1_less"),
                          Con.Flag("nondecoder_data"),
                          Con.Bits("metadata_function", 5))),
        Con.IfThenElse('size', lambda ctx: ctx['large_block'], ULInt24('s'),
                       Con.Byte('s')))

    BITS_PER_SAMPLE = (8, 16, 24, 32)
    SAMPLING_RATE = (6000, 8000, 9600, 11025, 12000, 16000, 22050, 24000,
                     32000, 44100, 48000, 64000, 88200, 96000, 192000, 0)

    __options__ = {
        "veryfast": {
            "block_size": 44100,
            "joint_stereo": True,
            "false_stereo": True,
            "wasted_bits": True,
            "decorrelation_passes": 1
        },
        "fast": {
            "block_size": 44100,
            "joint_stereo": True,
            "false_stereo": True,
            "wasted_bit": True,
            "decorrelation_passes": 2
        },
        "standard": {
            "block_size": 44100,
            "joint_stereo": True,
            "false_stereo": True,
            "wasted_bits": True,
            "decorrelation_passes": 5
        },
        "high": {
            "block_size": 44100,
            "joint_stereo": True,
            "false_stereo": True,
            "wasted_bits": True,
            "decorrelation_passes": 10
        },
        "veryhigh": {
            "block_size": 44100,
            "joint_stereo": True,
            "false_stereo": True,
            "wasted_bits": True,
            "decorrelation_passes": 16
        }
    }

    def __init__(self, filename):
        """filename is a plain string."""

        self.filename = filename
        self.__samplerate__ = 0
        self.__channels__ = 0
        self.__bitspersample__ = 0
        self.__total_frames__ = 0

        try:
            self.__read_info__()
        except IOError, msg:
            raise InvalidWavPack(str(msg))