Beispiel #1
0
        public XACTClip(BinaryReader reader, double clipVolume)
        {
            // Number of XACT Events
            INTERNAL_events = new XACTEvent[reader.ReadByte()];

            for (int i = 0; i < INTERNAL_events.Length; i += 1)
            {
                // Full Event information
                uint eventInfo = reader.ReadUInt32();

                // XACT Event Type, Timestamp
                uint eventType      = eventInfo & 0x0000001F;
                uint eventTimestamp = (eventInfo >> 5) & 0x0000FFFF;
                // uint eventUnknown = eventInfo >> 21;

                // Random offset, unused
                reader.ReadUInt16();

                // Load the Event
                if (eventType == 0)
                {
                    // TODO: Codename OhGodNo
                    // Stop Event
                }
                else if (eventType == 1)
                {
                    // Unknown value
                    reader.ReadByte();

                    /* Event Flags
                     * 0x01 = Break Loop
                     * 0x02 = Use Speaker Position
                     * 0x04 = Use Center Speaker
                     * 0x08 = New Speaker Position On Loop
                     */
                    reader.ReadByte();

                    // WaveBank Track Index
                    ushort track = reader.ReadUInt16();

                    // WaveBank Index
                    byte waveBank = reader.ReadByte();

                    // Number of times to loop wave (255 is infinite)
                    byte loopCount = reader.ReadByte();

                    // Speaker position angle/arc, unused
                    reader.ReadUInt16();
                    reader.ReadUInt16();

                    // Finally.
                    INTERNAL_events[i] = new PlayWaveEvent(
                        eventTimestamp,
                        new ushort[] { track },
                        new byte[] { waveBank },
                        0,
                        0,
                        clipVolume,
                        clipVolume,
                        -1,
                        loopCount,
                        0,
                        new byte[] { 0xFF }
                        );
                }
                else if (eventType == 3)
                {
                    // Unknown value
                    reader.ReadByte();

                    /* Event Flags
                     * 0x01 = Break Loop
                     * 0x02 = Use Speaker Position
                     * 0x04 = Use Center Speaker
                     * 0x08 = New Speaker Position On Loop
                     */
                    reader.ReadByte();

                    // Number of times to loop wave (255 is infinite)
                    byte loopCount = reader.ReadByte();

                    // Speaker position angle/arc, unused
                    reader.ReadUInt16();
                    reader.ReadUInt16();

                    // Number of WaveBank tracks
                    ushort numTracks = reader.ReadUInt16();

                    /* Variation Playlist Type.
                     * First 4 bytes indicates Variation Type.
                     * Next 4 bytes appear to indicate New Variation On Loop.
                     * The rest is currently unknown.
                     * -flibit
                     */
                    ushort variationType = (ushort)(reader.ReadUInt16() & 0x000F);

                    // Unknown values
                    reader.ReadBytes(4);

                    // Obtain WaveBank track information
                    ushort[] tracks    = new ushort[numTracks];
                    byte[]   waveBanks = new byte[numTracks];
                    byte[]   weights   = new byte[numTracks];
                    for (ushort j = 0; j < numTracks; j += 1)
                    {
                        tracks[j]    = reader.ReadUInt16();
                        waveBanks[j] = reader.ReadByte();
                        byte minWeight = reader.ReadByte();
                        byte maxWeight = reader.ReadByte();
                        weights[j] = (byte)(maxWeight - minWeight);
                    }

                    // Finally.
                    INTERNAL_events[i] = new PlayWaveEvent(
                        eventTimestamp,
                        tracks,
                        waveBanks,
                        0,
                        0,
                        clipVolume,
                        clipVolume,
                        -1,
                        loopCount,
                        variationType,
                        weights
                        );
                }
                else if (eventType == 4)
                {
                    // Unknown value
                    reader.ReadByte();

                    /* Event Flags
                     * 0x01 = Break Loop
                     * 0x02 = Use Speaker Position
                     * 0x04 = Use Center Speaker
                     * 0x08 = New Speaker Position On Loop
                     */
                    reader.ReadByte();

                    // WaveBank track
                    ushort track = reader.ReadUInt16();

                    // WaveBank index, unconfirmed
                    byte waveBank = reader.ReadByte();

                    // Loop Count, unconfirmed
                    byte loopCount = reader.ReadByte();

                    // Speaker position angle/arc, unused
                    reader.ReadUInt16();
                    reader.ReadUInt16();

                    // Pitch Variation
                    short minPitch = reader.ReadInt16();
                    short maxPitch = reader.ReadInt16();

                    // Volume Variation
                    double minVolume = XACTCalculator.ParseDecibel(reader.ReadByte());
                    double maxVolume = XACTCalculator.ParseDecibel(reader.ReadByte());

                    // Frequency Variation, unusued
                    reader.ReadSingle();
                    reader.ReadSingle();

                    // Q Factor Variation, unused
                    reader.ReadSingle();
                    reader.ReadSingle();

                    // Filter Type
                    byte filterType = reader.ReadByte();

                    // Finally.
                    INTERNAL_events[i] = new PlayWaveEvent(
                        eventTimestamp,
                        new ushort[] { track },
                        new byte[] { waveBank },
                        minPitch,
                        maxPitch,
                        minVolume,
                        maxVolume,
                        (int)filterType,
                        loopCount,
                        0,
                        new byte[] { 0xFF }
                        );
                }
                else if (eventType == 6)
                {
                    // Unknown value
                    reader.ReadByte();

                    /* Event Flags
                     * 0x01 = Break Loop
                     * 0x02 = Use Speaker Position
                     * 0x04 = Use Center Speaker
                     * 0x08 = New Speaker Position On Loop
                     */
                    reader.ReadByte();

                    // Number of times to loop wave (255 is infinite)
                    byte loopCount = reader.ReadByte();

                    // Speaker position angle/arc, unused
                    reader.ReadUInt16();
                    reader.ReadUInt16();

                    // Pitch variation
                    short minPitch = reader.ReadInt16();
                    short maxPitch = reader.ReadInt16();

                    // Volume variation
                    double minVolume = XACTCalculator.ParseDecibel(reader.ReadByte());
                    double maxVolume = XACTCalculator.ParseDecibel(reader.ReadByte());

                    // Frequency Variation, unusued
                    reader.ReadSingle();
                    reader.ReadSingle();

                    // Q Factor Variation, unused
                    reader.ReadSingle();
                    reader.ReadSingle();

                    // Filter Type
                    byte filterType = reader.ReadByte();

                    // Variation flags
                    // FIXME: There's probably more to these flags...
                    byte varFlags = reader.ReadByte();
                    if ((varFlags & 0x20) != 0x20)
                    {
                        // Throw out the volume variation.
                        minVolume = clipVolume;
                        maxVolume = clipVolume;
                    }
                    if ((varFlags & 0x10) != 0x10)
                    {
                        // Throw out the pitch variation
                        minPitch = 0;
                        maxPitch = 0;
                    }

                    // Number of WaveBank tracks
                    ushort numTracks = reader.ReadUInt16();

                    /* Variation Playlist Type.
                     * First 4 bytes indicates Variation Type.
                     * Next 4 bytes appear to indicate New Variation On Loop.
                     * The rest is currently unknown.
                     * -flibit
                     */
                    ushort variationType = (ushort)(reader.ReadUInt16() & 0x000F);

                    // Unknown values
                    reader.ReadBytes(4);

                    // Obtain WaveBank track information
                    ushort[] tracks    = new ushort[numTracks];
                    byte[]   waveBanks = new byte[numTracks];
                    byte[]   weights   = new byte[numTracks];
                    for (ushort j = 0; j < numTracks; j += 1)
                    {
                        tracks[j]    = reader.ReadUInt16();
                        waveBanks[j] = reader.ReadByte();
                        byte minWeight = reader.ReadByte();
                        byte maxWeight = reader.ReadByte();
                        weights[j] = (byte)(maxWeight - minWeight);
                    }

                    // Finally.
                    INTERNAL_events[i] = new PlayWaveEvent(
                        eventTimestamp,
                        tracks,
                        waveBanks,
                        minPitch,
                        maxPitch,
                        minVolume,
                        maxVolume,
                        (int)filterType,
                        loopCount,
                        variationType,
                        weights
                        );
                }
                else if (eventType == 7)
                {
                    // TODO: Codename OhGodNo -flibit
                    // Pitch Event
                }
                else if (eventType == 8)
                {
                    // Unknown values
                    reader.ReadBytes(2);

                    /* Event Flags
                     * 0x01 = Add, rather than replace
                     * Rest is unknown
                     */
                    bool addVolume = (reader.ReadByte() & 0x01) == 0x01;

                    // Operand Constant
                    float constant = reader.ReadSingle() / 100.0f;
                    if (addVolume)
                    {
                        constant += (float)clipVolume;
                    }

                    // Unknown values
                    reader.ReadBytes(8);

                    INTERNAL_events[i] = new SetVolumeEvent(
                        eventTimestamp,
                        XACTCalculator.CalculateAmplitudeRatio(constant)
                        );
                }
                else if (eventType == 15)
                {
                    // TODO: Codename OhGodNo -flibit
                    // Unknown Event!
                }
                else if (eventType == 17)
                {
                    // TODO: Codename OhGodNo -flibit
                    // Volume Repeat Event
                }
                else
                {
                    /* TODO: All XACT Events.
                     * The following type information is based on
                     * third-party contributions:
                     * Type 9 - Marker Event
                     * -flibit
                     */
                    throw new Exception(
                              "EVENT TYPE " + eventType.ToString() + " NOT IMPLEMENTED!"
                              );
                }
            }
        }
Beispiel #2
0
        public XACTClip(BinaryReader reader, double clipVolume)
        {
            INTERNAL_clipVolume = clipVolume;

            // Number of XACT Events
            INTERNAL_events = new XACTEvent[reader.ReadByte()];

            for (int i = 0; i < INTERNAL_events.Length; i += 1)
            {
                // Full Event information
                uint eventInfo = reader.ReadUInt32();

                // XACT Event Type, Timestamp
                uint eventType = eventInfo & 0x0000001F;
                // uint eventTimestamp = (eventInfo >> 5) & 0x0000FFFF;
                // uint eventUnknown = eventInfo >> 21;

                // Random offset, unused
                reader.ReadUInt16();

                // Load the Event
                if (eventType == 1)
                {
                    // Unknown value
                    reader.ReadByte();

                    /* Event Flags
                     * 0x01 = Break Loop
                     * 0x02 = Use Speaker Position
                     * 0x04 = Use Center Speaker
                     * 0x08 = New Speaker Position On Loop
                     */
                    reader.ReadByte();

                    // WaveBank Track Index
                    ushort track = reader.ReadUInt16();

                    // WaveBank Index
                    byte waveBank = reader.ReadByte();

                    // Number of times to loop wave (255 is infinite)
                    byte loopCount = reader.ReadByte();

                    // Unknown value
                    reader.ReadUInt32();

                    // Finally.
                    INTERNAL_events[i] = new PlayWaveEvent(
                        new ushort[] { track },
                        new byte[] { waveBank },
                        0,
                        0,
                        0.0,
                        0.0,
                        loopCount,
                        0,
                        new byte[] { 0xFF }
                        );
                }
                else if (eventType == 3)
                {
                    // Unknown value
                    reader.ReadByte();

                    /* Event Flags
                     * 0x01 = Break Loop
                     * 0x02 = Use Speaker Position
                     * 0x04 = Use Center Speaker
                     * 0x08 = New Speaker Position On Loop
                     */
                    reader.ReadByte();

                    // Unknown values
                    reader.ReadBytes(5);

                    // Number of WaveBank tracks
                    ushort numTracks = reader.ReadUInt16();

                    // Variation Playlist Type
                    ushort variationType = reader.ReadUInt16();

                    // Unknown values
                    reader.ReadBytes(4);

                    // Obtain WaveBank track information
                    ushort[] tracks    = new ushort[numTracks];
                    byte[]   waveBanks = new byte[numTracks];
                    byte[]   weights   = new byte[numTracks];
                    for (ushort j = 0; j < numTracks; j += 1)
                    {
                        tracks[j]    = reader.ReadUInt16();
                        waveBanks[j] = reader.ReadByte();
                        byte minWeight = reader.ReadByte();
                        byte maxWeight = reader.ReadByte();
                        weights[j] = (byte)(maxWeight - minWeight);
                    }

                    // Finally.
                    INTERNAL_events[i] = new PlayWaveEvent(
                        tracks,
                        waveBanks,
                        0,
                        0,
                        0.0,
                        0.0,
                        0,
                        variationType,
                        weights
                        );
                }
                else if (eventType == 4)
                {
                    // Unknown value
                    reader.ReadByte();

                    /* Event Flags
                     * 0x01 = Break Loop
                     * 0x02 = Use Speaker Position
                     * 0x04 = Use Center Speaker
                     * 0x08 = New Speaker Position On Loop
                     */
                    reader.ReadByte();

                    // WaveBank track
                    ushort track = reader.ReadUInt16();

                    // WaveBank index, unconfirmed
                    byte waveBank = reader.ReadByte();

                    // Loop Count, unconfirmed
                    byte loopCount = reader.ReadByte();

                    // Unknown values
                    reader.ReadBytes(4);

                    // Pitch Variation
                    short minPitch = reader.ReadInt16();
                    short maxPitch = reader.ReadInt16();

                    // Volume Variation
                    double minVolume = XACTCalculator.ParseDecibel(reader.ReadByte());
                    double maxVolume = XACTCalculator.ParseDecibel(reader.ReadByte());

                    // Unknown values
                    reader.ReadSingle();
                    reader.ReadSingle();
                    reader.ReadSingle();
                    reader.ReadSingle();
                    reader.ReadByte();

                    // Finally.
                    INTERNAL_events[i] = new PlayWaveEvent(
                        new ushort[] { track },
                        new byte[] { waveBank },
                        minPitch,
                        maxPitch,
                        minVolume,
                        maxVolume,
                        loopCount,
                        0,
                        new byte[] { 0xFF }
                        );
                }
                else if (eventType == 6)
                {
                    // Unknown value
                    reader.ReadByte();

                    /* Event Flags
                     * 0x01 = Break Loop
                     * 0x02 = Use Speaker Position
                     * 0x04 = Use Center Speaker
                     * 0x08 = New Speaker Position On Loop
                     */
                    reader.ReadByte();

                    // Unknown values
                    reader.ReadBytes(5);

                    // Pitch variation
                    short minPitch = reader.ReadInt16();
                    short maxPitch = reader.ReadInt16();

                    // Volume variation
                    double minVolume = XACTCalculator.ParseDecibel(reader.ReadByte());
                    double maxVolume = XACTCalculator.ParseDecibel(reader.ReadByte());

                    // Unknown values
                    reader.ReadSingle();
                    reader.ReadSingle();
                    reader.ReadSingle();
                    reader.ReadSingle();
                    reader.ReadByte();

                    // Variation flags
                    // FIXME: There's probably more to these flags...
                    byte varFlags = reader.ReadByte();
                    if ((varFlags & 0x20) != 0x20)
                    {
                        // Throw out the volume variation.
                        minVolume = 0.0;
                        maxVolume = 0.0;
                    }
                    if ((varFlags & 0x10) != 0x10)
                    {
                        // Throw out the pitch variation
                        minPitch = 0;
                        maxPitch = 0;
                    }

                    // Number of WaveBank tracks
                    ushort numTracks = reader.ReadUInt16();

                    // Variation Playlist Type
                    ushort variationType = reader.ReadUInt16();

                    // Unknown values
                    reader.ReadBytes(4);

                    // Obtain WaveBank track information
                    ushort[] tracks    = new ushort[numTracks];
                    byte[]   waveBanks = new byte[numTracks];
                    byte[]   weights   = new byte[numTracks];
                    for (ushort j = 0; j < numTracks; j += 1)
                    {
                        tracks[j]    = reader.ReadUInt16();
                        waveBanks[j] = reader.ReadByte();
                        byte minWeight = reader.ReadByte();
                        byte maxWeight = reader.ReadByte();
                        weights[j] = (byte)(maxWeight - minWeight);
                    }

                    // Finally.
                    INTERNAL_events[i] = new PlayWaveEvent(
                        tracks,
                        waveBanks,
                        minPitch,
                        maxPitch,
                        minVolume,
                        maxVolume,
                        0,
                        variationType,
                        weights
                        );
                }
                else if (eventType == 8)
                {
                    // Unknown values
                    reader.ReadBytes(3);

                    // Operand Constant
                    float constant = reader.ReadSingle();

                    // Unknown values
                    reader.ReadBytes(8);

                    INTERNAL_events[i] = new SetVolumeEvent(
                        constant
                        );
                }
                else
                {
                    /* TODO: All XACT Events.
                     * The following type information is based on
                     * third-party contributions:
                     * Type 0 - Stop Event
                     * Type 7 - Pitch Event
                     * Type 9 - Marker Event
                     * -flibit
                     */
                    throw new Exception(
                              "EVENT TYPE " + eventType.ToString() + " NOT IMPLEMENTED!"
                              );
                }
            }
        }
Beispiel #3
0
        public XACTClip(BinaryReader reader, double clipVolume)
        {
            // Number of XACT Events
            INTERNAL_events = new XACTEvent[reader.ReadByte()];

            for (int i = 0; i < INTERNAL_events.Length; i += 1)
            {
                // Full Event information
                uint eventInfo = reader.ReadUInt32();

                // XACT Event Type, Timestamp
                uint eventType = eventInfo & 0x0000001F;
                uint eventTimestamp = (eventInfo >> 5) & 0x0000FFFF;
                // uint eventUnknown = eventInfo >> 21;

                // Random offset, unused
                reader.ReadUInt16();

                // Load the Event
                if (eventType == 1)
                {
                    // Unknown value
                    reader.ReadByte();

                    /* Event Flags
                     * 0x01 = Break Loop
                     * 0x02 = Use Speaker Position
                     * 0x04 = Use Center Speaker
                     * 0x08 = New Speaker Position On Loop
                     */
                    reader.ReadByte();

                    // WaveBank Track Index
                    ushort track = reader.ReadUInt16();

                    // WaveBank Index
                    byte waveBank = reader.ReadByte();

                    // Number of times to loop wave (255 is infinite)
                    byte loopCount = reader.ReadByte();

                    // Speaker position angle/arc, unused
                    reader.ReadUInt16();
                    reader.ReadUInt16();

                    // Finally.
                    INTERNAL_events[i] = new PlayWaveEvent(
                        eventTimestamp,
                        new ushort[] { track },
                        new byte[] { waveBank },
                        0,
                        0,
                        clipVolume,
                        clipVolume,
                        loopCount,
                        0,
                        new byte[] { 0xFF }
                    );
                }
                else if (eventType == 3)
                {
                    // Unknown value
                    reader.ReadByte();

                    /* Event Flags
                     * 0x01 = Break Loop
                     * 0x02 = Use Speaker Position
                     * 0x04 = Use Center Speaker
                     * 0x08 = New Speaker Position On Loop
                     */
                    reader.ReadByte();

                    // Number of times to loop wave (255 is infinite)
                    byte loopCount = reader.ReadByte();

                    // Speaker position angle/arc, unused
                    reader.ReadUInt16();
                    reader.ReadUInt16();

                    // Number of WaveBank tracks
                    ushort numTracks = reader.ReadUInt16();

                    /* Variation Playlist Type.
                     * First 4 bytes indicates Variation Type.
                     * Next 4 bytes appear to indicate New Variation On Loop.
                     * The rest is currently unknown.
                     * -flibit
                     */
                    ushort variationType = (ushort) (reader.ReadUInt16() & 0x000F);

                    // Unknown values
                    reader.ReadBytes(4);

                    // Obtain WaveBank track information
                    ushort[] tracks = new ushort[numTracks];
                    byte[] waveBanks = new byte[numTracks];
                    byte[] weights = new byte[numTracks];
                    for (ushort j = 0; j < numTracks; j += 1)
                    {
                        tracks[j] = reader.ReadUInt16();
                        waveBanks[j] = reader.ReadByte();
                        byte minWeight = reader.ReadByte();
                        byte maxWeight = reader.ReadByte();
                        weights[j] = (byte) (maxWeight - minWeight);
                    }

                    // Finally.
                    INTERNAL_events[i] = new PlayWaveEvent(
                        eventTimestamp,
                        tracks,
                        waveBanks,
                        0,
                        0,
                        clipVolume,
                        clipVolume,
                        loopCount,
                        variationType,
                        weights
                    );
                }
                else if (eventType == 4)
                {
                    // Unknown value
                    reader.ReadByte();

                    /* Event Flags
                     * 0x01 = Break Loop
                     * 0x02 = Use Speaker Position
                     * 0x04 = Use Center Speaker
                     * 0x08 = New Speaker Position On Loop
                     */
                    reader.ReadByte();

                    // WaveBank track
                    ushort track = reader.ReadUInt16();

                    // WaveBank index, unconfirmed
                    byte waveBank = reader.ReadByte();

                    // Loop Count, unconfirmed
                    byte loopCount = reader.ReadByte();

                    // Speaker position angle/arc, unused
                    reader.ReadUInt16();
                    reader.ReadUInt16();

                    // Pitch Variation
                    short minPitch = reader.ReadInt16();
                    short maxPitch = reader.ReadInt16();

                    // Volume Variation
                    double minVolume = XACTCalculator.ParseDecibel(reader.ReadByte());
                    double maxVolume = XACTCalculator.ParseDecibel(reader.ReadByte());

                    // Frequency Variation, unusued
                    reader.ReadSingle();
                    reader.ReadSingle();

                    // Q Factor Variation, unused
                    reader.ReadSingle();
                    reader.ReadSingle();

                    // Unknown value
                    reader.ReadByte();

                    // Finally.
                    INTERNAL_events[i] = new PlayWaveEvent(
                        eventTimestamp,
                        new ushort[] { track },
                        new byte[] { waveBank },
                        minPitch,
                        maxPitch,
                        minVolume,
                        maxVolume,
                        loopCount,
                        0,
                        new byte[] { 0xFF }
                    );
                }
                else if (eventType == 6)
                {
                    // Unknown value
                    reader.ReadByte();

                    /* Event Flags
                     * 0x01 = Break Loop
                     * 0x02 = Use Speaker Position
                     * 0x04 = Use Center Speaker
                     * 0x08 = New Speaker Position On Loop
                     */
                    reader.ReadByte();

                    // Number of times to loop wave (255 is infinite)
                    byte loopCount = reader.ReadByte();

                    // Speaker position angle/arc, unused
                    reader.ReadUInt16();
                    reader.ReadUInt16();

                    // Pitch variation
                    short minPitch = reader.ReadInt16();
                    short maxPitch = reader.ReadInt16();

                    // Volume variation
                    double minVolume = XACTCalculator.ParseDecibel(reader.ReadByte());
                    double maxVolume = XACTCalculator.ParseDecibel(reader.ReadByte());

                    // Frequency Variation, unusued
                    reader.ReadSingle();
                    reader.ReadSingle();

                    // Q Factor Variation, unused
                    reader.ReadSingle();
                    reader.ReadSingle();

                    // Unknown value
                    reader.ReadByte();

                    // Variation flags
                    // FIXME: There's probably more to these flags...
                    byte varFlags = reader.ReadByte();
                    if ((varFlags & 0x20) != 0x20)
                    {
                        // Throw out the volume variation.
                        minVolume = clipVolume;
                        maxVolume = clipVolume;
                    }
                    if ((varFlags & 0x10) != 0x10)
                    {
                        // Throw out the pitch variation
                        minPitch = 0;
                        maxPitch = 0;
                    }

                    // Number of WaveBank tracks
                    ushort numTracks = reader.ReadUInt16();

                    /* Variation Playlist Type.
                     * First 4 bytes indicates Variation Type.
                     * Next 4 bytes appear to indicate New Variation On Loop.
                     * The rest is currently unknown.
                     * -flibit
                     */
                    ushort variationType = (ushort) (reader.ReadUInt16() & 0x000F);

                    // Unknown values
                    reader.ReadBytes(4);

                    // Obtain WaveBank track information
                    ushort[] tracks = new ushort[numTracks];
                    byte[] waveBanks = new byte[numTracks];
                    byte[] weights = new byte[numTracks];
                    for (ushort j = 0; j < numTracks; j += 1)
                    {
                        tracks[j] = reader.ReadUInt16();
                        waveBanks[j] = reader.ReadByte();
                        byte minWeight = reader.ReadByte();
                        byte maxWeight = reader.ReadByte();
                        weights[j] = (byte) (maxWeight - minWeight);
                    }

                    // Finally.
                    INTERNAL_events[i] = new PlayWaveEvent(
                        eventTimestamp,
                        tracks,
                        waveBanks,
                        minPitch,
                        maxPitch,
                        minVolume,
                        maxVolume,
                        loopCount,
                        variationType,
                        weights
                    );
                }
                else if (eventType == 8)
                {
                    // Unknown values
                    reader.ReadBytes(2);

                    /* Event Flags
                     * 0x01 = Add, rather than replace
                     * Rest is unknown
                     */
                    bool addVolume = (reader.ReadByte() & 0x01) == 0x01;

                    // Operand Constant
                    float constant = reader.ReadSingle() / 100.0f;
                    if (addVolume)
                    {
                        constant += (float) clipVolume;
                    }

                    // Unknown values
                    reader.ReadBytes(8);

                    INTERNAL_events[i] = new SetVolumeEvent(
                        eventTimestamp,
                        XACTCalculator.CalculateAmplitudeRatio(constant)
                    );
                }
                else
                {
                    /* TODO: All XACT Events.
                     * The following type information is based on
                     * third-party contributions:
                     * Type 0 - Stop Event
                     * Type 7 - Pitch Event
                     * Type 9 - Marker Event
                     * Type 17 - Volume Repeat Event
                     * -flibit
                     */
                    throw new Exception(
                        "EVENT TYPE " + eventType.ToString() + " NOT IMPLEMENTED!"
                    );
                }
            }
        }
Beispiel #4
0
        public XACTClip(BinaryReader reader, double clipVolume, byte filterType)
        {
            // Number of XACT Events
            Events = new XACTEvent[reader.ReadByte()];

            for (int i = 0; i < Events.Length; i += 1)
            {
                // Full Event information
                uint eventInfo = reader.ReadUInt32();

                // XACT Event Type, Timestamp
                uint eventType      = eventInfo & 0x0000001F;
                uint eventTimestamp = (eventInfo >> 5) & 0x0000FFFF;
                // uint eventUnknown = eventInfo >> 21;

                // Random offset, unused
                reader.ReadUInt16();

                // Load the Event
                if (eventType == 0)                 // StopEvent
                {
                    // TODO: Codename OhGodNo
                }
                else if (eventType == 1)                 // Basic PlayWaveEvent
                {
                    // Unknown value
                    reader.ReadByte();

                    /* Event Flags
                     * 0x01 = Break Loop
                     * 0x02 = Use Speaker Position
                     * 0x04 = Use Center Speaker
                     * 0x08 = New Speaker Position On Loop
                     */
                    reader.ReadByte();

                    // WaveBank Track Index
                    ushort track = reader.ReadUInt16();

                    // WaveBank Index
                    byte waveBank = reader.ReadByte();

                    // Number of times to loop wave (255 is infinite)
                    byte loopCount = reader.ReadByte();

                    // Speaker position angle/arc, unused
                    reader.ReadUInt16();
                    reader.ReadUInt16();

                    // Finally.
                    Events[i] = new PlayWaveEvent(
                        eventTimestamp,
                        new ushort[] { track },
                        new byte[] { waveBank },
                        0,
                        0,
                        clipVolume,
                        clipVolume,
                        filterType,
                        loopCount,
                        false,
                        false,
                        false,
                        false,
                        0,
                        false,
                        new byte[] { 0xFF }
                        );
                }
                else if (eventType == 3)                 // PlayWaveEvent with track variation
                {
                    // Unknown value
                    reader.ReadByte();

                    /* Event Flags
                     * 0x01 = Break Loop
                     * 0x02 = Use Speaker Position
                     * 0x04 = Use Center Speaker
                     * 0x08 = New Speaker Position On Loop
                     */
                    reader.ReadByte();

                    // Number of times to loop wave (255 is infinite)
                    byte loopCount = reader.ReadByte();

                    // Speaker position angle/arc, unused
                    reader.ReadUInt16();
                    reader.ReadUInt16();

                    // Number of WaveBank tracks
                    ushort numTracks = reader.ReadUInt16();

                    /* Variation Playlist Type.
                     * First 4 bytes indicates Variation Type.
                     * Next 4 bytes appear to indicate New Variation On Loop.
                     * The rest is currently unknown.
                     * -flibit
                     */
                    ushort variationValues = reader.ReadUInt16();
                    ushort variationType   = (ushort)(variationValues & 0x000F);
                    bool   variationOnLoop = (variationValues & 0x00F0) > 0;

                    // Unknown values
                    reader.ReadBytes(4);

                    // Obtain WaveBank track information
                    ushort[] tracks    = new ushort[numTracks];
                    byte[]   waveBanks = new byte[numTracks];
                    byte[]   weights   = new byte[numTracks];
                    for (ushort j = 0; j < numTracks; j += 1)
                    {
                        tracks[j]    = reader.ReadUInt16();
                        waveBanks[j] = reader.ReadByte();
                        byte minWeight = reader.ReadByte();
                        byte maxWeight = reader.ReadByte();
                        weights[j] = (byte)(maxWeight - minWeight);
                    }

                    // Finally.
                    Events[i] = new PlayWaveEvent(
                        eventTimestamp,
                        tracks,
                        waveBanks,
                        0,
                        0,
                        clipVolume,
                        clipVolume,
                        filterType,
                        loopCount,
                        false,
                        false,
                        false,
                        false,
                        variationType,
                        variationOnLoop,
                        weights
                        );
                }
                else if (eventType == 4)                 // PlayWaveEvent with effect variation
                {
                    // Unknown value
                    reader.ReadByte();

                    /* Event Flags
                     * 0x01 = Break Loop
                     * 0x02 = Use Speaker Position
                     * 0x04 = Use Center Speaker
                     * 0x08 = New Speaker Position On Loop
                     */
                    reader.ReadByte();

                    // WaveBank track
                    ushort track = reader.ReadUInt16();

                    // WaveBank index, unconfirmed
                    byte waveBank = reader.ReadByte();

                    // Loop Count, unconfirmed
                    byte loopCount = reader.ReadByte();

                    // Speaker position angle/arc, unused
                    reader.ReadUInt16();
                    reader.ReadUInt16();

                    // Pitch Variation
                    short minPitch = reader.ReadInt16();
                    short maxPitch = reader.ReadInt16();

                    // Volume Variation
                    double minVolume = XACTCalculator.ParseDecibel(reader.ReadByte());
                    double maxVolume = XACTCalculator.ParseDecibel(reader.ReadByte());

                    // Frequency Variation, unusued
                    reader.ReadSingle();
                    reader.ReadSingle();

                    // Q Factor Variation, unused
                    reader.ReadSingle();
                    reader.ReadSingle();

                    // Variation On Loop flags
                    ushort varFlags = reader.ReadUInt16();
                    if ((varFlags & 0x1000) == 0)
                    {
                        minPitch = 0;
                        maxPitch = 0;
                    }
                    if ((varFlags & 0x2000) == 0)
                    {
                        minVolume = clipVolume;
                        maxVolume = clipVolume;
                    }
                    // varFlags & 0xC000 is freq/qfactor, always together
                    bool pitchVarLoop  = (varFlags & 0x0100) > 0;
                    bool volumeVarLoop = (varFlags & 0x0200) > 0;
                    // varFlags & 0x0C00 is freq/qfactor loop, always together
                    bool pitchVarAdd  = (varFlags & 0x0004) > 0;
                    bool volumeVarAdd = (varFlags & 0x0001) > 0;
                    // varFlags & 0x0050 is freq/qfactor add, can be separate

                    // Finally.
                    Events[i] = new PlayWaveEvent(
                        eventTimestamp,
                        new ushort[] { track },
                        new byte[] { waveBank },
                        minPitch,
                        maxPitch,
                        minVolume,
                        maxVolume,
                        filterType,
                        loopCount,
                        pitchVarLoop,
                        pitchVarAdd,
                        volumeVarLoop,
                        volumeVarAdd,
                        0,
                        false,
                        new byte[] { 0xFF }
                        );
                }
                else if (eventType == 6)                 // PlayWaveEvent with track/effect variation
                {
                    // Unknown value
                    reader.ReadByte();

                    /* Event Flags
                     * 0x01 = Break Loop
                     * 0x02 = Use Speaker Position
                     * 0x04 = Use Center Speaker
                     * 0x08 = New Speaker Position On Loop
                     */
                    reader.ReadByte();

                    // Number of times to loop wave (255 is infinite)
                    byte loopCount = reader.ReadByte();

                    // Speaker position angle/arc, unused
                    reader.ReadUInt16();
                    reader.ReadUInt16();

                    // Pitch variation
                    short minPitch = reader.ReadInt16();
                    short maxPitch = reader.ReadInt16();

                    // Volume variation
                    double minVolume = XACTCalculator.ParseDecibel(reader.ReadByte());
                    double maxVolume = XACTCalculator.ParseDecibel(reader.ReadByte());

                    // Frequency Variation, unusued
                    reader.ReadSingle();
                    reader.ReadSingle();

                    // Q Factor Variation, unused
                    reader.ReadSingle();
                    reader.ReadSingle();

                    // Variation On Loop flags
                    ushort varFlags = reader.ReadUInt16();
                    if ((varFlags & 0x1000) == 0)
                    {
                        minPitch = 0;
                        maxPitch = 0;
                    }
                    if ((varFlags & 0x2000) == 0)
                    {
                        minVolume = clipVolume;
                        maxVolume = clipVolume;
                    }
                    // varFlags & 0xC000 is freq/qfactor, always together
                    bool pitchVarLoop  = (varFlags & 0x0100) > 0;
                    bool volumeVarLoop = (varFlags & 0x0200) > 0;
                    // varFlags & 0x0C00 is freq/qfactor loop, always together
                    bool pitchVarAdd  = (varFlags & 0x0004) > 0;
                    bool volumeVarAdd = (varFlags & 0x0001) > 0;
                    // varFlags & 0x0050 is freq/qfactor add, can be separate

                    // Number of WaveBank tracks
                    ushort numTracks = reader.ReadUInt16();

                    /* Variation Playlist Type.
                     * First 4 bytes indicates Variation Type.
                     * Next 4 bytes appear to indicate New Variation On Loop.
                     * The rest is currently unknown.
                     * -flibit
                     */
                    ushort variationValues = reader.ReadUInt16();
                    ushort variationType   = (ushort)(variationValues & 0x000F);
                    bool   variationOnLoop = (variationValues & 0x00F0) > 0;

                    // Unknown values
                    reader.ReadBytes(4);

                    // Obtain WaveBank track information
                    ushort[] tracks    = new ushort[numTracks];
                    byte[]   waveBanks = new byte[numTracks];
                    byte[]   weights   = new byte[numTracks];
                    for (ushort j = 0; j < numTracks; j += 1)
                    {
                        tracks[j]    = reader.ReadUInt16();
                        waveBanks[j] = reader.ReadByte();
                        byte minWeight = reader.ReadByte();
                        byte maxWeight = reader.ReadByte();
                        weights[j] = (byte)(maxWeight - minWeight);
                    }

                    // Finally.
                    Events[i] = new PlayWaveEvent(
                        eventTimestamp,
                        tracks,
                        waveBanks,
                        minPitch,
                        maxPitch,
                        minVolume,
                        maxVolume,
                        filterType,
                        loopCount,
                        pitchVarLoop,
                        pitchVarAdd,
                        volumeVarLoop,
                        volumeVarAdd,
                        variationType,
                        variationOnLoop,
                        weights
                        );
                }
                else if (eventType == 7)                 // SetPitchEvent
                {
                    // Unknown values
                    reader.ReadBytes(2);

                    /* Event Flags
                     * 0x08 = Min/Max Values
                     * Rest is unknown
                     */
                    bool minMax = (reader.ReadByte() & 0x08) == 0x08;

                    // Min/Max Random
                    float min = reader.ReadSingle() / 1000.0f;
                    float max;
                    if (minMax)
                    {
                        max = reader.ReadSingle() / 1000.0f;
                    }
                    else
                    {
                        max = min;
                    }

                    // FIXME: Any more...? -flibit

                    Events[i] = new SetPitchEvent(
                        eventTimestamp,
                        min,
                        max
                        );
                }
                else if (eventType == 8)                 // SetVolumeEvent
                {
                    // Unknown values
                    reader.ReadBytes(2);

                    /* Event Flags
                     * 0x08 = Min/Max Values
                     * 0x01 = Add, rather than replace
                     * Rest is unknown
                     */
                    byte flags     = reader.ReadByte();
                    bool addVolume = (flags & 0x01) == 0x01;
                    bool minMax    = (flags & 0x08) == 0x08;

                    // Operand Constant
                    float min = reader.ReadSingle() / 100.0f;
                    float max;
                    if (minMax)
                    {
                        max = reader.ReadSingle() / 100.0f;

                        // Unknown bytes
                        reader.ReadBytes(5);
                    }
                    else
                    {
                        max = min;

                        // Unknown values
                        reader.ReadBytes(8);
                    }
                    if (addVolume)
                    {
                        min += (float)clipVolume;
                        max += (float)clipVolume;
                    }

                    Events[i] = new SetVolumeEvent(
                        eventTimestamp,
                        XACTCalculator.CalculateAmplitudeRatio(min),
                        XACTCalculator.CalculateAmplitudeRatio(max)
                        );
                }
                else if (eventType == 15)                 // ???
                {
                    // TODO: Codename OhGodNo -flibit
                }
                else if (eventType == 17)                 // Volume Repeat Event
                {
                    // TODO: Codename OhGodNo -flibit
                }
                else
                {
                    /* TODO: All XACT Events.
                     * The following type information is based on
                     * third-party contributions:
                     * Type 9 - Marker Event
                     * -flibit
                     */
                    throw new NotImplementedException(
                              "EVENT TYPE " + eventType.ToString() + " NOT IMPLEMENTED!"
                              );
                }
            }
        }