Example #1
0
        /*
         * JAIV2 KeyRegion Structure
         * 0x00 byte baseKey
         * 0x01 byte[0x3] unused;
         * 0x04 int32 velocityRegionCount
         * VelocityRegion[velocityRegionCount] velocities; // NOTE THESE ARENT POINTERS, THESE ARE ACTUAL OBJECTS.
         */

        public JInstrumentKey readKeyRegion(BeBinaryReader binStream, int Base)
        {
            JInstrumentKey newKey = new JInstrumentKey();

            newKey.Velocities = new JInstrumentKeyVelocity[0x81]; // Create region array
            //-------
            //Console.WriteLine(binStream.BaseStream.Position);
            newKey.baseKey = binStream.ReadByte();             // Store base key
            binStream.BaseStream.Seek(3, SeekOrigin.Current);; // Skip 3 bytes
            var velRegCount = binStream.ReadInt32();           // Grab vel region count
            var velLow      = 0;                               // Again, these are regions -- see LoadInstrument for this exact code ( a few lines above )

            for (int i = 0; i < velRegCount; i++)
            {
                var breg = readKeyVelRegion(binStream, Base);  // Read the vel region.

                for (int b = 0; b < breg.baseVel - velLow; b++)
                {
                    //  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[b]   = breg;
                    newKey.Velocities[127] = breg;
                }
                velLow = breg.baseVel;
            }
            return(newKey);
        }
Example #2
0
        public JInstrument loadPercussionInstrument(BeBinaryReader binStream, int Base)
        {
            if (binStream.ReadInt32() != Perc)
            {
                throw new InvalidDataException("Perc section started with unexpected data");
            }
            var newPERC = new JInstrument();

            newPERC.IsPercussion = true;
            newPERC.Pitch        = 1f;
            newPERC.Volume       = 1f;

            var count = binStream.ReadInt32();
            var ptrs  = Helpers.readInt32Array(binStream, count);
            var iKeys = new JInstrumentKey[count];

            for (int i = 0; i < count; i++)
            {
                var PmapOffset = ptrs[i];
                if (PmapOffset > 0)
                {
                    var newKey = new JInstrumentKey();
                    newKey.Velocities = new JInstrumentKeyVelocity[0x81];
                    var pmapDataOffs = PmapOffset + Base;  // OH LOOK ANOTHER RELATIVE TO BANK BASE.
                    binStream.BaseStream.Position = pmapDataOffs;
                    if (binStream.ReadInt32() != Pmap)
                    {
                        Console.WriteLine("ERROR: Invalid PMAP data {0:X} -- Potential misalignment!", binStream.BaseStream.Position);
                        continue;
                    }

                    newKey.Volume = binStream.ReadInt32();
                    newKey.Pitch  = binStream.ReadInt32();
                    //binStream.ReadInt32(); // byte panning
                    binStream.BaseStream.Seek(8, SeekOrigin.Current); // runtime.
                    var velRegCount = binStream.ReadInt32();
                    var velLow      = 0;
                    for (int b = 0; b < velRegCount; b++)
                    {
                        var breg = readKeyVelRegion(binStream, Base);
                        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
                    }
                    iKeys[i] = newKey;
                }
            }
            newPERC.Keys            = iKeys;
            newPERC.oscillatorCount = 0;
            return(newPERC);
        }
Example #3
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);
        }
Example #4
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);
        }
Example #5
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);
        }