示例#1
0
        /*
         * JAIV1 Oscillator Format
         * 0x00 - byte mode
         * 0x01 - byte[3] unknown
         * 0x04 - float rate
         * 0x08 - int32 attackVectorOffset
         * 0x0C - int32 releaseVectorOffset
         * 0x10 - float width
         * 0x14 - float vertex
         */
        public JOscillator loadOscillator(BeBinaryReader binStream, int Base)
        {
            var Osc    = new JOscillator();                                      // Create new oscillator
            var target = binStream.ReadByte();                                   // load target -- what is it affecting?

            binStream.BaseStream.Seek(3, SeekOrigin.Current);                    // read 3 bytes?
            Osc.rate = binStream.ReadSingle();                                   // Read the rate at which the oscillator progresses -- this will be relative to the number of ticks per beat.
            var attackSustainTableOffset = binStream.ReadInt32();                // Offset of AD table
            var releaseDecayTableOffset  = binStream.ReadInt32();                // Offset of SR table

            Osc.Width  = binStream.ReadSingle();                                 // We should load these next, this is the width, ergo the value of the oscillator at 32768.
            Osc.Vertex = binStream.ReadSingle();                                 // This is the vertex, the oscillator will always cross this point.
            // To determine the value of an oscillator, it's Vertex + Width*(value/32768) -- each vector should progress the value, depending on the mode.
            if (attackSustainTableOffset > 0)                                    // first is AS table
            {
                binStream.BaseStream.Position = attackSustainTableOffset + Base; // Seek to the vector table
                Osc.envelopes[0] = readEnvelope(binStream, Base);                // Load the table
            }
            if (releaseDecayTableOffset > 0)                                     // Next is RD table
            {
                binStream.BaseStream.Position = releaseDecayTableOffset + Base;  // Seek to the vector and load it
                Osc.envelopes[1] = readEnvelope(binStream, Base);                // loadddd
            }
            Osc.target = (JOscillatorTarget)target;
            return(Osc);
        }
示例#2
0
        /*
         * JAIV2 Oscillator Structure
         * 0x00 - int32 0x4F736369 'Osci'
         * 0x04 - byte mode
         * 0x05 - byte[3] unknown
         * 0x08 - float rate
         * 0x0c - int32 attackVectorOffset (RELATIVE TO ENVT + 0x08)
         * 0x10 - int32 releaseVectorOffset (RELATIVE TO ENVT + 0x08)
         * 0x14 - float width
         * 0x18 - float vertex
         */

        /* NOTE THAT THESE OSCILLATORS HAVE THE SAME FORMAT AS JAIV1, HOWEVER THE VECTORS ARE IN THE ENVT */
        public JOscillator loadOscillator(BeBinaryReader binStream, int EnvTableBase)
        {
            var Osc = new JOscillator();       // Create new oscillator

            if (binStream.ReadInt32() != Osci) // Read first 4 bytes
            {
                throw new InvalidDataException("Oscillator format is invalid. " + binStream.BaseStream.Position);
            }

            var target = binStream.ReadByte();                    // load target -- what is it affecting?

            binStream.BaseStream.Seek(3, SeekOrigin.Current);     // read 3 bytes?
            Osc.rate = binStream.ReadSingle();                    // Read the rate at which the oscillator progresses -- this will be relative to the number of ticks per beat.
            var attackSustainTableOffset = binStream.ReadInt32(); // Offset of AD table
            var releaseDecayTableOffset  = binStream.ReadInt32(); // Offset of SR table

            Osc.Width  = binStream.ReadSingle();                  // We should load these next, this is the width, ergo the value of the oscillator at 32768.
            Osc.Vertex = binStream.ReadSingle();                  // This is the vertex, the oscillator will always cross this point.
            // To determine the value of an oscillator, it's Vertex + Width*(value/32768) -- each vector should progress the value, depending on the mode.
            // We need to add + 8 to the offsets, because the pointers are the offset based on where the data starts, not the section
            if (attackSustainTableOffset > 0)                                                // first is AS table
            {
                binStream.BaseStream.Position = attackSustainTableOffset + EnvTableBase + 8; // Seek to the vector table
                Osc.envelopes[0] = readEnvelope(binStream, EnvTableBase + 8);                // Load the table
            }
            if (releaseDecayTableOffset > 0)                                                 // Next is RD table
            {
                binStream.BaseStream.Position = releaseDecayTableOffset + EnvTableBase + 8;  // Seek to the vector and load it
                Osc.envelopes[1] = readEnvelope(binStream, EnvTableBase + 8);                // loadddd
            }
            Osc.target = OscillatorTargetConversionLUT[target];
            return(Osc);
        }
示例#3
0
        /*
         *  JAIV1 Velocity Region Structure
         * 0x00 byte baseVelocity;
         * 0x04 byte[0x03] unused;
         * 0x07 short wsysID;
         * 0x09 short waveID;
         * 0x0D float Volume;
         * 0x11 float Pitch;
         */

        public JInstrumentKeyVelocity readKeyVelRegion(BeBinaryReader binStream, int Base)
        {
            JInstrumentKeyVelocity newReg = new JInstrumentKeyVelocity();

            newReg.baseVel = binStream.ReadByte();
            binStream.BaseStream.Seek(3, SeekOrigin.Current);;  // Skip 3 bytes.
            newReg.velocity = newReg.baseVel;
            newReg.wsysid   = binStream.ReadInt16();
            newReg.wave     = binStream.ReadInt16();
            newReg.Volume   = binStream.ReadSingle();
            newReg.Pitch    = binStream.ReadSingle();
            return(newReg);
        }
示例#4
0
        /*
         * JAIV1 PER2 Structure
         * 0x00 int32 0x50455232 'PER2'
         * 0x04 byte[0x84] unused; // the actual f**k? Waste of 0x84 perfectly delicious bytes.
         * 0x8C *PercussionKey[100]
         *
         * PER2 PercussionKey Structure
         *   float pitch;
         *   float volume;
         *   byte[0x8] unused?
         *   int32 velocityRegionCount
         * VelocityRegion[velocityRegionCount]  velocities
         *
         */

        public JInstrument loadPercussionInstrument(BeBinaryReader binStream, int Base)
        {
            var Inst = new JInstrument();

            if (binStream.ReadUInt32() != PER2) // Check if first 4 bytes are PER2
            {
                throw new InvalidDataException("Data is not an PER2");
            }
            Inst.Pitch        = 1.0f;
            Inst.Volume       = 1.0f;
            Inst.IsPercussion = true;
            binStream.BaseStream.Seek(0x84, SeekOrigin.Current);
            JInstrumentKey[] keys        = new JInstrumentKey[100];
            int[]            keyPointers = new int[100];
            keyPointers = Helpers.readInt32Array(binStream, 100); // read the pointers.

            for (int i = 0; i < 100; i++)                         // Loop through all pointers.
            {
                if (keyPointers[i] == 0)
                {
                    continue;
                }
                binStream.BaseStream.Position = keyPointers[i] + Base; // Set position to key pointer pos (relative to base)
                var newKey = new JInstrumentKey();
                newKey.Pitch  = binStream.ReadSingle();                // read the pitch
                newKey.Volume = binStream.ReadSingle();                // read the volume
                binStream.BaseStream.Seek(8, SeekOrigin.Current);      // runtime values, skip
                var velRegCount = binStream.ReadInt32();               // read count of regions we have
                newKey.Velocities = new JInstrumentKeyVelocity[0xff];  // 0xFF just in case.
                int[] velRegPointers = Helpers.readInt32Array(binStream, velRegCount);

                var velLow = 0;  // Again, these are regions -- see LoadInstrument for this exact code ( a few lines above )
                for (int b = 0; b < velRegCount; b++)
                {
                    binStream.BaseStream.Position = velRegPointers[b] + Base;
                    var breg = readKeyVelRegion(binStream, Base);  // Read the vel region.
                    for (int c = 0; c < breg.baseVel - velLow; c++)
                    {
                        //  They're velocity regions, so we're going to have a toothy / gappy piano. So we need to span the missing gaps with the previous region config.
                        // This means that if the last key was 4, and the next key was 8 -- whatever parameters 4 had will span keys 4 5 6 and 7.
                        newKey.Velocities[c]   = breg; // store the  region
                        newKey.Velocities[127] = breg;
                    }
                    velLow = breg.baseVel; // store the velocity for spanning
                }
                keys[i] = newKey;
            }
            Inst.Keys = keys;
            return(Inst);
        }
示例#5
0
        /* JAIV2 Instrument Structure
         *    0x00 int32 = 0x496E7374 'Inst'
         *    0x04 int32 oscillatorCount
         *    0x08 int32[oscillatorCount] oscillatorIndicies
         *    ???? int32 0
         *    ???? int32 keyRegionCount
         *    ???? keyRegion[keyRegionCount]
         *    ???? float gain
         *    ???? float freqmultiplier
         *
         */
        public JInstrument loadInstrument(BeBinaryReader binStream, int Base)
        {
            var newInst = new JInstrument();

            newInst.IsPercussion = false; // Instrument isn't percussion
            // This is wrong, they come at the end of the instrument
            //newInst.Pitch = 1; // So these kinds of instruments don't initialize with a pitch value, which is strange.
            //newInst.Volume = 1; // I guess they figured that it was redundant since they're already doing it in 3 other places.
            if (binStream.ReadInt32() != Inst)
            {
                throw new InvalidDataException("Inst section started with unexpected data");
            }
            var osciCount = binStream.ReadInt32();                   // Read the count of the oscillators.

            newInst.oscillatorCount = (byte)osciCount;               // Hope no instrument never ever ever has > 255 oscillators lol.
            newInst.oscillators     = new JOscillator[osciCount];    // Initialize the instrument with the proper amount of oscillaotrs
            for (int i = 0; i < osciCount; i++)                      // Loop through and read each oscillator.
            {
                var osciIndex = binStream.ReadInt32();               // Each oscillator is stored as a 32 bit index.
                newInst.oscillators[i] = bankOscillators[osciIndex]; // We loaded the oscillators already, I hope.  So this will grab them by their index.
            }
            var notpadding = binStream.ReadInt32();                  // NOT PADDING. F**K. Probably effects.

            Helpers.readInt32Array(binStream, notpadding);
            var keyRegCount = binStream.ReadInt32();
            var keyLow      = 0;                              // For region spanning.

            JInstrumentKey[] keys = new JInstrumentKey[0x81]; // Always go for one more.
            for (int i = 0; i < keyRegCount; i++)             // Loop through all pointers.
            {
                var bkey = readKeyRegion(binStream, Base);    // Read the key region
                //Console.WriteLine("KREG BASE KEY {0}", bkey.baseKey);
                for (int b = 0; b < bkey.baseKey - keyLow; b++)
                {
                    //  They're key regions, so we're going to have a toothy / gappy piano. So we need to span the missing gaps with the previous region config.
                    // This means that if the last key was 4, and the next key was 8 -- whatever parameters 4 had will span keys 4 5 6 and 7.
                    keys[b + keyLow] = bkey; // span the keys
                    keys[127]        = bkey;
                }
                keyLow = bkey.baseKey; // Store our last key
            }
            newInst.Keys = keys;

            newInst.Volume = binStream.ReadSingle(); // ^^
            newInst.Pitch  = binStream.ReadSingle(); // Pitch and volume come last???
            // WE HAVE READ EVERY BYTE IN THE INST, WOOO
            return(newInst);
        }
示例#6
0
        /// <summary>
        /// Gets the ticks from the binary data.
        /// </summary>
        /// <param name="data">The data.</param>
        /// <returns></returns>
        public List <Tick> LoadTicks(byte[] data)
        {
            var result = new List <Tick>();

            byte[] decompressed = SevenZip.Compression.LZMA.SevenZipHelper.Decompress(data);

            using (var reader = new BeBinaryReader(new MemoryStream(decompressed)))
            {
                while (reader.BaseStream.Position != reader.BaseStream.Length)
                {
                    var tick = new Tick();

                    tick.Milliseconds = reader.ReadInt32();
                    tick.Ask          = reader.ReadInt32();
                    tick.Bid          = reader.ReadInt32();
                    tick.AskVolume    = reader.ReadSingle();
                    tick.BidVolume    = reader.ReadSingle();

                    result.Add(tick);
                }
            }

            return(result);
        }
示例#7
0
        private JWave loadWave(BeBinaryReader binStream, int Base)
        {
            var newWave = new JWave();

            binStream.ReadByte();                                                           // First byte unknown?
            newWave.format = binStream.ReadByte();                                          // Read wave format, usually 5
            newWave.key    = binStream.ReadByte();                                          // Read the base tuning key
            //Console.WriteLine(newWave.key);
            binStream.ReadByte();                                                           // fourth byte unknown?
            newWave.sampleRate  = binStream.ReadSingle();                                   // Read the samplerate
            newWave.wsys_start  = binStream.ReadInt32();                                    // Read the offset in the AW
            newWave.wsys_size   = binStream.ReadInt32();                                    // Read the length in the AW
            newWave.loop        = binStream.ReadUInt32() == UInt32.MaxValue ? true : false; // Check if it loops?
            newWave.loop_start  = binStream.ReadInt32();                                    // Even if looping is disabled, it should still read loops
            newWave.loop_end    = binStream.ReadInt32();                                    // Sample index of loop end
            newWave.sampleCount = binStream.ReadInt32();                                    // Sample count
            return(newWave);
        }
示例#8
0
        /*
         *  JAIV1 INST Structure
         *  0x00 int32 0x494E5354 'INST'
         *  0x04 int32 0 - unused?
         *  0x08 float frequencyMultiplier
         *  0x0C float gainMultiplier
         *  0x10 int32 oscillator table offset
         *  0x14 int32 oscillator table count
         *  0x18 int32 effect table offset
         *  0x1C int32 effect table size
         *  0x20 int32 sensor object table
         *  0x24 int32 sensor object table count
         *  0x28 int32 key_region_count
         *  0x2C *KeyRegion[key_region_count]
         *
         */

        public JInstrument loadInstrument(BeBinaryReader binStream, int Base)
        {
            var Inst = new JInstrument();

            if (binStream.ReadUInt32() != INST) // Check if first 4 bytes are INST
            {
                throw new InvalidDataException("Data is not an INST");
            }
            binStream.ReadUInt32(); // oh god oh god oh god its null
            Inst.Pitch  = binStream.ReadSingle();
            Inst.Volume = binStream.ReadSingle();
            var osc1Offset = binStream.ReadUInt32();
            var osc2Offset = binStream.ReadUInt32();

            binStream.ReadUInt32();                           // *NOT IMPLEMENTED* //
            binStream.ReadUInt32();                           // *NOT IMPLEMENTED* //
            binStream.ReadUInt32();                           // *NOT IMPLEMENTED* //
            binStream.ReadUInt32();                           // *NOT IMPLEMENTED* //
            // * trashy furry screaming * //
            int keyregCount = binStream.ReadInt32();          // Read number of key regions

            JInstrumentKey[] keys = new JInstrumentKey[0x81]; // Always go for one more.
            int[]            keyRegionPointers = new int[keyregCount];
            keyRegionPointers = Helpers.readInt32Array(binStream, keyregCount);
            var keyLow = 0;                                                  // For region spanning.

            for (int i = 0; i < keyregCount; i++)                            // Loop through all pointers.
            {
                binStream.BaseStream.Position = keyRegionPointers[i] + Base; // Set position to key pointer pos (relative to base)
                var bkey = readKeyRegion(binStream, Base);                   // Read the key region
                for (int b = 0; b < bkey.baseKey - keyLow; b++)
                {
                    //  They're key regions, so we're going to have a toothy / gappy piano. So we need to span the missing gaps with the previous region config.
                    // This means that if the last key was 4, and the next key was 8 -- whatever parameters 4 had will span keys 4 5 6 and 7.
                    keys[b + keyLow] = bkey; // span the keys
                    keys[127]        = bkey;
                }
                keyLow = bkey.baseKey; // Store our last key
            }
            Inst.Keys = keys;
            byte oscCount = 0;

            if (osc1Offset > 0)
            {
                oscCount++;
            }
            if (osc2Offset > 0)
            {
                oscCount++;
            }
            Inst.oscillatorCount = oscCount;                                     // Redundant?
            Inst.oscillators     = new JOscillator[oscCount];                    // new oscillator array
            if (osc1Offset != 0)                                                 // if the oscillator isnt null
            {
                binStream.BaseStream.Position = osc1Offset + Base;               // seek to it's position
                Inst.oscillators[0]           = loadOscillator(binStream, Base); // then load it.
            }
            if (osc2Offset != 0)                                                 // if the second oscillator isn't null
            {
                binStream.BaseStream.Position = osc2Offset + Base;               // seek to its position
                Inst.oscillators[1]           = loadOscillator(binStream, Base); // and load it.
            }
            return(Inst);
        }
示例#9
0
        private void loadIBNKJaiV2(BeBinaryReader instReader)
        {
            long anchor         = 0;
            var  BaseAddress    = instReader.BaseStream.Position;
            var  current_header = instReader.ReadUInt32();

            if (current_header != 0x49424e4b) // Check to see if it equals IBNK
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine("0x{0:X}", BaseAddress);
                throw new InvalidDataException("Scanned header is not an IBNK.");
            }

            var IBNKSize = instReader.ReadUInt32();

            id = instReader.ReadInt32();
            var flags = instReader.ReadUInt32();                  // usually 1, determines if the bank is melodic or used for sound effects. Usually the bank is melodic.

            instReader.BaseStream.Seek(0x10, SeekOrigin.Current); // Skip 16 bytes, always 0x00, please document if wrong.
            var i = 0;

            while (true)
            {
                anchor = instReader.BaseStream.Position; // Store current section base.
                i++;
                // Console.WriteLine("Iteration {0} 0x{1:X}", i,anchor);
                current_header = instReader.ReadUInt32();
                //  Console.WriteLine("GOT HD {0:X}", current_header);
                if (current_header == 0x00)
                {
                    break;                        // End of section.
                }
                else if (current_header < 0xFFFF) // Read below for explanation
                {
                    // I've noticed VERY RARELY, that the section pointer is wrong by two bytes. This sucks. So we check if it's less than two full bytes.
                    // If it is, we seek back 2 bytes then read again, and our alignment is fixed :).
                    // of course, this comes after our check to see if it's 0, which indicates end of section
                    instReader.BaseStream.Seek(-2, SeekOrigin.Current);
                    Console.WriteLine("[!] Misalignment detected in IBNK, new position 0x{0:X}", instReader.BaseStream.Position);
                    anchor         = instReader.BaseStream.Position; // 3/14/2019, i forgot this. It's S M R T to update your read base.
                    current_header = instReader.ReadUInt32();
                    Console.WriteLine("New header {0:X}", current_header);
                }
                var next_section = ReadJARCSizePointer(instReader); // if that works, go ahead and grab the 'pointer' to the next section.
                if (current_header < 0xFFFF)
                {
                    Console.WriteLine("Corrupt IBNK 0x{0:X}", BaseAddress);
                    break;
                }
                switch (current_header)
                {
                case 0x4F534354:                                            // OSCT
                case 0x52414E44:                                            // RAND
                case 0x454E5654:                                            // EVNT
                case 0x53454E53:                                            // SENS
                    instReader.BaseStream.Position = anchor + next_section; // Skip section.
                    break;

                case INST:
                {
                    var NewINST   = new Instrument();
                    var InstCount = instReader.ReadInt32();
                    NewINST.Keys = new InstrumentKey[0xF0];
                    for (int instid = 0; instid < InstCount; instid++)
                    {
                        current_header = instReader.ReadUInt32();
                        var iebase = instReader.BaseStream.Position;
                        if (current_header != Inst)
                        {
                            break;         // F**K.
                        }
                        NewINST.oscillator = instReader.ReadInt32();
                        NewINST.id         = instReader.ReadInt32();

                        instReader.ReadInt32();                 // cant figure out what these are.
                        var keyCounts = instReader.ReadInt32(); // How many key regions are in here.
                        int KeyHigh   = 0;
                        int KeyLow    = 0;
                        for (int k = 0; k < keyCounts; k++)
                        {
                            var NewKey = new InstrumentKey();
                            NewKey.keys = new InstrumentKeyVelocity[0x81];

                            byte key = instReader.ReadByte();                  // Read the key identifierr
                            KeyHigh = key;                                     // Set the highest key to what we just read.
                            instReader.BaseStream.Seek(3, SeekOrigin.Current); // 3 bytes, unused.
                            var VelocityRegionCount = instReader.ReadInt32();  // read the number of entries in the velocity region array\
                            if (VelocityRegionCount > 0x7F)
                            {
                                Console.WriteLine("Alignment is f****d, IBNK load aborted.");
                                Console.WriteLine("E: VelocityRegionCount is too thicc. {0} > 128", VelocityRegionCount);
                                Console.WriteLine("IBASE: 0x{0:X} + 0x{1:X} ({2:X})", anchor, iebase - anchor, (instReader.BaseStream.Position - anchor) - (iebase - anchor));

                                return;
                            }
                            for (int b = 0; b < VelocityRegionCount; b++)
                            {
                                var NewVelR = new InstrumentKeyVelocity();
                                int VelLow  = 0;
                                int VelHigh = 0;
                                {
                                    var velocity = instReader.ReadByte();              // The velocity of this key.
                                    VelHigh = velocity;
                                    instReader.BaseStream.Seek(3, SeekOrigin.Current); // Unused.
                                    NewVelR.velocity = velocity;
                                    NewVelR.wave     = instReader.ReadUInt16();        // This will be the ID of the wave inside of that wavesystem
                                    NewVelR.wsysid   = instReader.ReadUInt16();        // This will be the ID of the WAVESYSTEM that its in

                                    NewVelR.Volume = instReader.ReadSingle();          // Finetune, volume, float
                                    NewVelR.Pitch  = instReader.ReadSingle();          // finetune pitch, float.
                                    for (int idx = 0; idx < (VelHigh - VelLow); idx++) // See below for what this is doing
                                    {
                                        NewKey.keys[(VelLow + idx)] = NewVelR;
                                        NewKey.keys[127]            = NewVelR;
                                    }
                                    VelLow = VelHigh;
                                }
                            }
                            for (int idx = 0; idx < (KeyHigh - KeyLow); idx++) // The keys are gappy.
                            {
                                NewINST.Keys[(KeyLow + idx)] = NewKey;         // So we want to interpolate the previous keys across the empty ones, so that way it's a region
                                NewINST.Keys[127]            = NewKey;
                            }
                            KeyLow = KeyHigh;         // Set our new lowest key to the previous highest
                        }
                    }
                    instReader.BaseStream.Position = anchor + next_section;         // SAFETY.
                    break;
                }

                case PERC:

                    instReader.BaseStream.Position = anchor + next_section;
                    break;

                case 0x4C495354:                                            // LIST
                    instReader.BaseStream.Position = anchor + next_section; // Skip section
                    // Explanation: This is just a set of pointers relative to BaseAddress for the instruments, nothing special because we're
                    // already parsing them above.
                    break;

                default:
                    instReader.BaseStream.Position = anchor + next_section;     // Skip section.
                    break;
                }
            }
        }
示例#10
0
        private void loadIBNKJaiV1(BeBinaryReader instReader)
        {
            long anchor         = 0;
            var  BaseAddress    = instReader.BaseStream.Position;
            var  current_header = 0u;

            current_header = instReader.ReadUInt32(); // read the first 4 byteas
            if (current_header != 0x49424e4b)         // Check to see if it equals IBNK
            {
                throw new InvalidDataException("Scanned header is not an IBNK.");
            }
            var size = instReader.ReadUInt32();

            id = instReader.ReadInt32();                          // Global virtual ID
            instReader.BaseStream.Seek(0x14, SeekOrigin.Current); // 0x14 bytes always blank
            current_header = instReader.ReadUInt32();             // We should be reading "BANK"
            for (int inst_id = 0; inst_id < 0xF0; inst_id++)
            {
                var inst_offset = instReader.ReadInt32();                       // Read the relative pointer to the instrument
                anchor = instReader.BaseStream.Position;                        // store the position to jump back into.
                if (inst_offset > 0)                                            // If we have a 0 offset, then the instrument is unassigned.
                {
                    instReader.BaseStream.Position = BaseAddress + inst_offset; // Seek to the offset of the instrument.
                    current_header = instReader.ReadUInt32();                   // Read the 4 byte identity of the instrument.
                    var NewINST = new Instrument();
                    NewINST.Keys = new InstrumentKey[0xF0];
                    switch (current_header)
                    {
                    case INST:
                    {
                        instReader.ReadUInt32();                  // The first 4 bytes following an instrument is always 0, for some reason.  Maybe reserved.
                        NewINST.Pitch  = instReader.ReadSingle(); // 4 byte float pitch
                        NewINST.Volume = instReader.ReadSingle(); // 4 byte float volume
                        /* Lots of skipping, i havent added these yet, but i'll comment what they are. */
                        var poscioffs = instReader.ReadUInt32();  // offset to first oscillator table
                        var poscicnt  = instReader.ReadUInt32();  // Offset to second oscillator count
                        // Console.WriteLine("Oscillator at 0x{0:X}, length {1}", poscioffs, poscicnt);
                        //Console.ReadLine();
                        instReader.ReadUInt32();                // Offset to first effect object
                        instReader.ReadUInt32();                // offset to second effect object
                        instReader.ReadUInt32();                // offset of first sensor object
                        instReader.ReadUInt32();                // offset of second sensor object
                        /*////////////////////////////////////////////////////////////////////////////*/
                        var keyCounts = instReader.ReadInt32(); // How many key regions are in here.
                        int KeyHigh   = 0;
                        int KeyLow    = 0;
                        for (int k = 0; k < keyCounts; k++)
                        {
                            var NewKey = new InstrumentKey();
                            NewKey.keys = new InstrumentKeyVelocity[0x81];
                            var keyreg_offset = instReader.ReadInt32();                   // This will be where the data for our key region is.
                            var keyptr_return = instReader.BaseStream.Position;           // This is our position after reading the pointer, we'll need to return to it
                            instReader.BaseStream.Position = BaseAddress + keyreg_offset; // Seek to the key region
                            byte key = instReader.ReadByte();                             // Read the key identifierr
                            KeyHigh = key;                                                // Set the highest key to what we just read.
                            instReader.BaseStream.Seek(3, SeekOrigin.Current);            // 3 bytes, unused.
                            var VelocityRegionCount = instReader.ReadInt32();             // read the number of entries in the velocity region array
                            for (int b = 0; b < VelocityRegionCount; b++)
                            {
                                var NewVelR     = new InstrumentKeyVelocity();
                                var velreg_offs = instReader.ReadInt32();         // read the offset of the velocity region
                                var velreg_retn = instReader.BaseStream.Position; // another one of these.  Return pointer
                                instReader.BaseStream.Position = velreg_offs + BaseAddress;
                                int VelLow  = 0;
                                int VelHigh = 0;
                                {
                                    var velocity = instReader.ReadByte();                    // The velocity of this key.
                                    VelHigh = velocity;
                                    instReader.BaseStream.Seek(3, SeekOrigin.Current);       // Unused.
                                    NewVelR.velocity = velocity;
                                    NewVelR.wsysid   = instReader.ReadUInt16();              // This will be the ID of the WAVESYSTEM that its in
                                    NewVelR.wave     = instReader.ReadUInt16();              // This will be the ID of the wave inside of that wavesystem
                                    NewVelR.Volume   = instReader.ReadSingle();              // Finetune, volume, float
                                    NewVelR.Pitch    = instReader.ReadSingle();              // finetune pitch, float.
                                    for (int idx = 0; idx < ((1 + VelHigh) - VelLow); idx++) // See below for what this is doing
                                    {
                                        NewKey.keys[(VelLow + idx)] = NewVelR;
                                        NewKey.keys[127]            = NewVelR;
                                    }
                                    VelLow = VelHigh;
                                }
                                instReader.BaseStream.Position = velreg_retn;  // return to our pointer position  [THIS IS BELOW]
                            }
                            for (int idx = 0; idx < (KeyHigh - KeyLow); idx++) // The keys are gappy.
                            {
                                NewINST.Keys[(KeyLow + idx)] = NewKey;         // So we want to interpolate the previous keys across the empty ones, so that way it's a region
                                NewINST.Keys[127]            = NewKey;
                            }
                            KeyLow = KeyHigh;                               // Set our new lowest key to the previous highest
                            instReader.BaseStream.Position = keyptr_return; // return to our last pointer position
                        }


                        break;
                    }

                    case PER2:
                    {
                        NewINST.IsPercussion = true;
                        instReader.BaseStream.Seek(0x84, SeekOrigin.Current);         // 0x88 - 4 (PERC)
                        for (int per = 0; per < 100; per++)
                        {
                            var NewKey = new InstrumentKey();
                            NewKey.keys = new InstrumentKeyVelocity[0x81];

                            var keyreg_offset = instReader.ReadInt32();         // This will be where the data for our key region is.
                            var keyptr_return = instReader.BaseStream.Position; // This is our position after reading the pointer, we'll need to return to it
                            if (keyreg_offset == 0)
                            {
                                continue;                                                 // Skip, its empty.
                            }
                            instReader.BaseStream.Position = BaseAddress + keyreg_offset; // seek to position.
                            NewINST.Pitch  = instReader.ReadSingle();
                            NewINST.Volume = instReader.ReadSingle();
                            instReader.BaseStream.Seek(8, SeekOrigin.Current);
                            var VelocityRegionCount = instReader.ReadInt32();         // read the number of entries in the velocity region array
                            for (int b = 0; b < VelocityRegionCount; b++)
                            {
                                var NewVelR     = new InstrumentKeyVelocity();
                                var velreg_offs = instReader.ReadInt32();         // read the offset of the velocity region
                                var velreg_retn = instReader.BaseStream.Position; // another one of these.  Return pointer
                                instReader.BaseStream.Position = velreg_offs + BaseAddress;
                                int VelLow  = 0;
                                int VelHigh = 0;
                                {
                                    var velocity = instReader.ReadByte();                // The velocity of this key.
                                    VelHigh = velocity;
                                    instReader.BaseStream.Seek(3, SeekOrigin.Current);   // Unused.
                                    NewVelR.velocity = velocity;
                                    NewVelR.wsysid   = instReader.ReadUInt16();          // This will be the ID of the WAVESYSTEM that its in

                                    NewVelR.wave   = instReader.ReadUInt16();            // This will be the ID of the wave inside of that wavesystem
                                    NewVelR.Volume = instReader.ReadSingle();            // Finetune, volume, float
                                    NewVelR.Pitch  = instReader.ReadSingle();            // finetune pitch, float.
                                    for (int idx = 0; idx < (VelHigh - (VelLow)); idx++) // See below for what this is doing
                                    {
                                        NewKey.keys[(VelLow + (idx))] = NewVelR;
                                        NewKey.keys[127] = NewVelR;
                                    }
                                    VelLow = VelHigh;
                                }
                                instReader.BaseStream.Position = velreg_retn;         // return to our pointer position  [THIS IS BELOW]
                            }
                            instReader.BaseStream.Position = keyptr_return;
                            NewINST.Keys[per] = NewKey;         // oops, add to instrument data or else it doesnt load x.x
                            NewINST.Keys[127] = NewKey;
                        }

                        break;
                    }

                    case PERC:

                        break;
                    }
                    Instruments[inst_id] = NewINST;      // Store it in the instruments bank
                }
                instReader.BaseStream.Position = anchor; // return back to our original pos to read the next pointer
            }
        }
示例#11
0
        private int back           = 0; // utility

        public void LoadWSYS(BeBinaryReader WSYSReader)
        {
            BaseAddress    = WSYSReader.BaseStream.Position;
            waves          = new WSYSWave[32768]; // TEMPORARY. Fix WSYS Loading!
            current_header = WSYSReader.ReadInt32();
            if (current_header != WSYS)
            {
                Console.WriteLine("Error: Section base at {0} is not WSYS, is instead {1:X}", BaseAddress, current_header);
                return;
            }

            size = WSYSReader.ReadInt32();

            id = WSYSReader.ReadInt32();

            WSYSReader.ReadUInt32(); // 4 bytes, not used. .. I think

            //  A little messy, but both of these need to be loaded before we can continue.
            var winfo_offset = WSYSReader.ReadInt32(); // relative offset to wave info offset pointer table.
            var wbct_offset  = WSYSReader.ReadInt32(); // relative offset to wave info offset pointer table.

            int[] winfOffsets;
            int[] wbctOffsets;
            {
                // Load WINF offsets.
                WSYSReader.BaseStream.Position = BaseAddress + winfo_offset;
                current_header = WSYSReader.ReadInt32();          // Should be WINF
                winfOffsets    = new int[WSYSReader.ReadInt32()]; // 4 bytes count

                for (int i = 0; i < winfOffsets.Length; i++)
                {
                    winfOffsets[i] = WSYSReader.ReadInt32();  // Int32's following the length.
                }

                // Load WBCT data

                WSYSReader.BaseStream.Position = BaseAddress + wbct_offset;
                current_header = WSYSReader.ReadInt32();       // Should be WBCT
                WSYSReader.ReadUInt32();                       // 4 bytes unused?
                wbctOffsets = new int[WSYSReader.ReadInt32()]; // 4 bytes count

                for (int i = 0; i < wbctOffsets.Length; i++)
                {
                    wbctOffsets[i] = WSYSReader.ReadInt32();  // Int32's following the length.
                }
            }

            groups = new WSYSGroup[winfOffsets.Length];
            for (int i = 0; i < winfOffsets.Length; i++)
            {
                /* This is loading the data for a WINF */
                WSYSReader.BaseStream.Position = BaseAddress + winfOffsets[i];

                var Group = new WSYSGroup();
                Group.path = Helpers.readArchiveName(WSYSReader);


                var fobj        = File.OpenRead("./Banks/" + Group.path); // Open the .AW file  (AW contains only ADPCM data, nothing else.)
                var fobj_reader = new BeBinaryReader(fobj);               // Create a reader for it.


                int   waveInfoCounts = WSYSReader.ReadInt32(); // 4 byte count
                int[] info_offsets   = new int[waveInfoCounts];
                for (int q = 0; q < waveInfoCounts; q++)
                {
                    info_offsets[q] = WSYSReader.ReadInt32();
                }
                Group.IDMap = new int[UInt16.MaxValue]; // We have to initialize the containers for the wave information
                Group.Waves = new WSYSWave[waveInfoCounts];


                /* Since the count should be equal, we're loading the info for the WBCT in he re as well */
                WSYSReader.BaseStream.Position = BaseAddress + wbctOffsets[i];
                // The first several bytes of the WBCT are uselss, a WBCT points directly to a SCNE.
                current_header = WSYSReader.ReadInt32(); // This should be SCNE.
                WSYSReader.ReadUInt64();                 // The next 8 bytes are useless.
                var cdf_offset = WSYSReader.ReadInt32(); // However, the next 4 contain the pointer to c_DF  relative to our base.
                WSYSReader.BaseStream.Position = BaseAddress + cdf_offset;

                current_header = WSYSReader.ReadInt32();       // Should be C_DF.
                int   waveid_count   = WSYSReader.ReadInt32(); // Count of our WAVE ID
                int[] waveid_offsets = new int[waveid_count];  // Be ready to store them
                for (int q = 0; q < waveid_count; q++)
                {
                    waveid_offsets[q] = WSYSReader.ReadInt32(); // Read each waveid
                }



                // Finally, we're going to get our wave data.

                for (int wav = 0; wav < waveInfoCounts; wav++)
                {
                    var o_Wave = new WSYSWave();
                    WSYSReader.BaseStream.Position = BaseAddress + waveid_offsets[wav];
                    var aw_id = WSYSReader.ReadInt16(); // Strangely enough, it has an AW_ID here. This tells which file it sits in?  I guess they're normally loaded separately.
                    o_Wave.id = WSYSReader.ReadInt16(); // This is the waveid for this wave, it's normally globally unique, but some games hot-load banks.


                    WSYSReader.BaseStream.Position = BaseAddress + info_offsets[wav]; // Seek to the offset of the actual wave parameters.

                    WSYSReader.ReadByte();                                            // I have no clue what the first byte does.
                    o_Wave.format = WSYSReader.ReadByte();                            // Tells what format it's in, usually type 5 AFC (ADPCM)
                    o_Wave.key    = WSYSReader.ReadByte();                            // Tells the base key for this wave (0-127 usually)
                    WSYSReader.ReadByte();                                            // I have no clue what this byte does.
                    //var srate = WSYSReader.ReadBytes(4);

                    o_Wave.sampleRate = WSYSReader.ReadSingle();

                    /*
                     * oh. its a float.
                     * oops
                     * if (o_Wave.format == 5)
                     * {
                     *  o_Wave.sampleRate = 32000; /// ????
                     * }
                     *
                     * if (o_Wave.sampleRate == 5666) // What the actual f**k. Broken  value, can't figure out why.
                     * {
                     *  o_Wave.sampleRate = 44100; // I guess set the srate to 44100?
                     * }
                     */

                    o_Wave.w_start = WSYSReader.ReadUInt32();                // 4 byte start in AW
                    o_Wave.w_size  = WSYSReader.ReadUInt32();                // 4 byte size in AW
                    var b = WSYSReader.ReadUInt32();
                    o_Wave.loop       = b == UInt32.MaxValue ? true : false; // Weird looping flag?
                    o_Wave.loop_start = (int)Math.Floor(((WSYSReader.ReadInt32() / 8f)) * 16f);
                    o_Wave.loop_end   = (int)Math.Floor(((WSYSReader.ReadInt32() / 8f)) * 16f);

                    o_Wave.sampleCount = WSYSReader.ReadInt32(); // 4 byte sample cont

                    // Console.WriteLine("L {0:X} (0x{1:X}), LS {2:X} , LE {3:X}, SC {4:X} SZ {5:X}", o_Wave.loop, b, o_Wave.loop_start, o_Wave.loop_end,o_Wave.sampleCount,o_Wave.w_size);
                    //Console.ReadLine();
                    var name  = string.Format("0x{0:X}.wav", o_Wave.id);
                    var name2 = string.Format("0x{0:X}.par", o_Wave.id);
                    if (!Directory.Exists("./WSYS_CACHE"))
                    {
                        Directory.CreateDirectory("./WSYS_CACHE");
                    }
                    if (!Directory.Exists("./WSYS_CACHE/AW_" + Group.path))
                    {
                        Directory.CreateDirectory("./WSYS_CACHE/AW_" + Group.path);
                    }

                    o_Wave.pcmpath = "./WSYS_CACHE/AW_" + Group.path + "/" + name;

                    Group.Waves[wav]       = o_Wave; // We're done with just about everything except the PCM data now (ADPCM / AFC conversion)
                    Group.IDMap[o_Wave.id] = wav;
                    waves[o_Wave.id]       = o_Wave; // TEMPORARY, FIX WSYS LOADING!

                    fobj_reader.BaseStream.Position = o_Wave.w_start;
                    var adpcm = fobj_reader.ReadBytes((int)o_Wave.w_size);

                    if (!File.Exists(o_Wave.pcmpath))
                    {
                        Helpers.AFCtoPCM16(adpcm, o_Wave.sampleRate, (int)o_Wave.w_size, o_Wave.format, o_Wave.pcmpath);
                    }
                }
            }
        }