/* * 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); }
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); }
/* * 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); }
/* 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); }
/* * 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); }