Code:
public static final int MIDI_HEADER_MAGIC = 0x4d546864;
public static final int MIDI_TRACK_MAGIC = 0x4d54726b;
public static final int CONTINUOUS_0_MSB = 0;
public static final int CONTINUOUS_0_LSB = 32;
public static final int MODULATION_WHEEL_MSB = 1;
public static final int MODULATION_WHEEL_LSB = 0x21;
public static final int PORTAMENTO_TIME_MSB = 5;
public static final int PORTAMENTO_TIME_LSB = 37;
public static final int DATA_MSB = 6;
public static final int DATA_LSB = 38;
public static final int VOLUME_MSB = 7;
public static final int VOLUME_LSB = 39;
public static final int PAN_MSB = 10;
public static final int PAN_LSB = 42;
public static final int EXPRESSION_MSB = 11;
public static final int EXPRESSION_LSB = 43;
public static final int GP0_MSB = 16;
public static final int GP0_LSB = 48;
public static final int GP1_MSB = 17;
public static final int GP1_LSB = 49;
public static final int DAMPER_SUSTAIN_PEDAL = 64;
public static final int PORTAMENTO_SWITCH = 65;
public static final int NRPN_MSB = 99;
public static final int NRPN_LSB = 98;
public static final int RPN_MSB = 101;
public static final int RPN_LSB = 100;
public static final int ALL_SOUND_OFF = 120;
public static final int RESET_ALL_CONTROLLERS = 121;
public static final int ALL_NOTES_OFF = 123;
public static final int END_OF_TRACK = 0x2f;
public static final int TEMPO_SET = 0x51;
public static final int NOTE_OFF = 0x80;
public static final int NOTE_ON = 0x90;
public static final int POLYPHONIC_AFTERTOUCH = 0xa0;
public static final int CONTROL_MODE_CHANGE = 0xb0;
public static final int PROGRAM_CHANGE = 0xc0;
public static final int AFTERTOUCH = 0xd0;
public static final int PITCH_WHEEL = 0xe0;
public static final int SYSEX_START = 0xf0;
public static final int SYSEX_END = 0xf7;
public static final int GPSWITCH_0 = 81;
Code:
package com.jagex.game.runetek5.sound.midi;/* com.jagex.tb - Decompiled by JODE
* Visit http://jode.sourceforge.net/
*/
import com.jagex.core.collections.HashTable;
import com.jagex.core.collections.Node;
import com.jagex.core.io.Packet;
import com.jagex.js5.Js5;
public final class CompressedMidi extends Node {
public static final int OP_END_OF_TRACK = 0x7;
public static final int OP_TEMPO_SET = 0x17;
public static final int OP_NOTE_ON = 0;
public static final int OP_NOTE_OFF = 1;
public static final int OP_CONTROL = 2;
public static final int OP_PITCH = 3;
public static final int OP_AFTERTOUCH = 4;
public static final int OP_POLY_AFTERTOUCH = 5;
public static final int OP_PROGRAM_CHANGE = 6;
public byte[] midiBuffer;
public static CompressedMidi get(Js5 js5, int group, int file) {
byte[] is = js5.get_file(group, file);
if (is == null)
return null;
return new CompressedMidi(new Packet(is));
}
private CompressedMidi(Packet inputPacket) {
inputPacket.position = inputPacket.buffer.length - 3;
int trackCount = inputPacket.g1();
int division = inputPacket.g2();
int midiMaxSize = 14 + trackCount * 10;
inputPacket.position = 0;
int tempoCount = 0;
int controlCount = 0;
int noteOnCount = 0;
int noteOffCount = 0;
int pitchWheelCount = 0;
int aftertouchCount = 0;
int polyAftertouchCount = 0;
int cont0Count = 0;
while_62_:
for (int i_26_ = 0; i_26_ < trackCount; i_26_++) {
int runningOpcode = -1;
for (; ; ) {
int opcode = inputPacket.g1();
if (opcode != runningOpcode)
midiMaxSize++;
runningOpcode = opcode & 0xf;
if (opcode == OP_END_OF_TRACK)
continue while_62_;
if (opcode == OP_TEMPO_SET)
tempoCount++;
else if (runningOpcode == OP_NOTE_ON)
noteOnCount++;
else if (runningOpcode == OP_NOTE_OFF)
noteOffCount++;
else if (runningOpcode == OP_CONTROL)
controlCount++;
else if (runningOpcode == OP_PITCH)
pitchWheelCount++;
else if (runningOpcode == OP_AFTERTOUCH)
aftertouchCount++;
else if (runningOpcode == OP_POLY_AFTERTOUCH)
polyAftertouchCount++;
else {
if (runningOpcode != OP_PROGRAM_CHANGE)
break;
cont0Count++;
}
}
throw new RuntimeException("Invalid midi opcode");
}
midiMaxSize += 5 * tempoCount;
midiMaxSize += 2 * (noteOnCount + noteOffCount + controlCount + pitchWheelCount + polyAftertouchCount);
midiMaxSize += aftertouchCount + cont0Count;
int deltaTimePtr = inputPacket.position;
int eventCount = (trackCount + tempoCount + controlCount + noteOnCount + noteOffCount + pitchWheelCount + aftertouchCount + polyAftertouchCount + cont0Count);
for (int i_31_ = 0; i_31_ < eventCount; i_31_++)
inputPacket.smf_gvlength();
midiMaxSize += inputPacket.position - deltaTimePtr;
int controlPtr = inputPacket.position;
int modulationWheelMSBCount = 0;
int modulationWheelLSBCount = 0;
int volumeMSBCount = 0;
int volumeLSBCount = 0;
int panMSBCount = 0;
int panLSBCount = 0;
int nrpnMSBCount = 0;
int nrpnLSBCount = 0;
int rpnMSBCount = 0;
int rpnLSBCount = 0;
int switchControlCount = 0;
int miscControlCount = 0;
int control = 0;
for (int event = 0; event < controlCount; event++) {
control = control + inputPacket.g1() & 0x7f;
if (control == 0 || control == 32)
cont0Count++;
else if (control == 1)
modulationWheelMSBCount++;
else if (control == 33)
modulationWheelLSBCount++;
else if (control == 7)
volumeMSBCount++;
else if (control == 39)
volumeLSBCount++;
else if (control == 10)
panMSBCount++;
else if (control == 42)
panLSBCount++;
else if (control == 99)
nrpnMSBCount++;
else if (control == 98)
nrpnLSBCount++;
else if (control == 101)
rpnMSBCount++;
else if (control == 100)
rpnLSBCount++;
else if (control == 64 || control == 65 || control == 120 || control == 121
|| control == 123)
switchControlCount++;
else
miscControlCount++;
}
int opcodePtr = 0;
int switchControlPtr = inputPacket.position;
inputPacket.position += switchControlCount;
int polyAtPressurePtr = inputPacket.position;
inputPacket.position += polyAftertouchCount;
int atPressurePtr = inputPacket.position;
inputPacket.position += aftertouchCount;
int pitchWheelMSBPtr = inputPacket.position;
inputPacket.position += pitchWheelCount;
int modulationWheelMSBPtr = inputPacket.position;
inputPacket.position += modulationWheelMSBCount;
int volumeMSBPtr = inputPacket.position;
inputPacket.position += volumeMSBCount;
int panMSBPtr = inputPacket.position;
inputPacket.position += panMSBCount;
int notePtr = inputPacket.position;
inputPacket.position += noteOnCount + noteOffCount + polyAftertouchCount;
int velocityPtr = inputPacket.position;
inputPacket.position += noteOnCount;
int miscControlPtr = inputPacket.position;
inputPacket.position += miscControlCount;
int releaseVelocityPtr = inputPacket.position;
inputPacket.position += noteOffCount;
int modulationWheelLSBPtr = inputPacket.position;
inputPacket.position += modulationWheelLSBCount;
int volumeLSBPtr = inputPacket.position;
inputPacket.position += volumeLSBCount;
int panLSBPtr = inputPacket.position;
inputPacket.position += panLSBCount;
int continuous0Ptr = inputPacket.position;
inputPacket.position += cont0Count;
int pitchWheelLSBPtr = inputPacket.position;
inputPacket.position += pitchWheelCount;
int nrpnMSBPtr = inputPacket.position;
inputPacket.position += nrpnMSBCount;
int nrpnLSBPtr = inputPacket.position;
inputPacket.position += nrpnLSBCount;
int rpnMSBPtr = inputPacket.position;
inputPacket.position += rpnMSBCount;
int rpnLSBPtr = inputPacket.position;
inputPacket.position += rpnLSBCount;
int tempoPtr = inputPacket.position;
inputPacket.position += tempoCount * 3;
this.midiBuffer = new byte[midiMaxSize];
Packet midiFile = new Packet(this.midiBuffer);
midiFile.p4(MidiConstants.MIDI_HEADER_MAGIC);
midiFile.p4(6);
midiFile.p2(trackCount > 1 ? 1 : 0);
midiFile.p2(trackCount);
midiFile.p2(division);
inputPacket.position = deltaTimePtr;
int channel = 0;
int note = 0;
int velocity = 0;
int releaseVelocity = 0;
int pitchWheel = 0;
int atPressure = 0;
int polyAtPressure = 0;
int[] controlValues = new int[128];
control = 0;
for (int track = 0; track < trackCount; track++) {
midiFile.p4(MidiConstants.MIDI_TRACK_MAGIC);
midiFile.position += 4;
int trackStart = midiFile.position;
int lastBaseOpcode = -1;
track_loop:
do {
for (; ; ) {
int deltaTime = inputPacket.smf_gvlength();
midiFile.smf_pvlength(deltaTime);
int opcode = inputPacket.buffer[opcodePtr++] & 0xff;
boolean newOpcode = opcode != lastBaseOpcode;
lastBaseOpcode = opcode & 0xf;
if (opcode == OP_END_OF_TRACK) {
if (newOpcode)
midiFile.p1(255);
midiFile.p1(MidiConstants.END_OF_TRACK);
midiFile.p1(0);
break track_loop;
}
if (opcode == OP_TEMPO_SET) {
if (newOpcode)
midiFile.p1(255);
midiFile.p1(MidiConstants.TEMPO_SET);
midiFile.p1(3);
midiFile.p1((int) inputPacket.buffer[tempoPtr++]);
midiFile.p1((int) inputPacket.buffer[tempoPtr++]);
midiFile.p1((int) inputPacket.buffer[tempoPtr++]);
} else {
channel ^= opcode >> 4;
if (lastBaseOpcode == OP_NOTE_ON) {
if (newOpcode)
midiFile.p1(MidiConstants.NOTE_ON + channel);
note += inputPacket.buffer[notePtr++];
velocity += inputPacket.buffer[velocityPtr++];
midiFile.p1(note & 0x7f);
midiFile.p1(velocity & 0x7f);
} else if (lastBaseOpcode == OP_NOTE_OFF) {
if (newOpcode)
midiFile.p1(MidiConstants.NOTE_OFF + channel);
note += inputPacket.buffer[notePtr++];
releaseVelocity += inputPacket.buffer[releaseVelocityPtr++];
midiFile.p1(note & 0x7f);
midiFile.p1(releaseVelocity & 0x7f);
} else if (lastBaseOpcode == OP_CONTROL) {
if (newOpcode)
midiFile.p1(MidiConstants.CONTROL_MODE_CHANGE + channel);
control = (control + inputPacket.buffer[controlPtr++]
& 0x7f);
midiFile.p1(control);
int data;
if (control == MidiConstants.CONTINUOUS_0_MSB || control == MidiConstants.CONTINUOUS_0_LSB)
data = inputPacket.buffer[continuous0Ptr++];
else if (control == MidiConstants.MODULATION_WHEEL_MSB)
data = inputPacket.buffer[modulationWheelMSBPtr++];
else if (control == MidiConstants.MODULATION_WHEEL_LSB)
data = inputPacket.buffer[modulationWheelLSBPtr++];
else if (control == MidiConstants.VOLUME_MSB)
data = inputPacket.buffer[volumeMSBPtr++];
else if (control == MidiConstants.VOLUME_LSB)
data = inputPacket.buffer[volumeLSBPtr++];
else if (control == MidiConstants.PAN_MSB)
data = inputPacket.buffer[panMSBPtr++];
else if (control == MidiConstants.PAN_LSB)
data = inputPacket.buffer[panLSBPtr++];
else if (control == MidiConstants.NRPN_MSB)
data = inputPacket.buffer[nrpnMSBPtr++];
else if (control == MidiConstants.NRPN_LSB)
data = inputPacket.buffer[nrpnLSBPtr++];
else if (control == MidiConstants.RPN_MSB)
data = inputPacket.buffer[rpnMSBPtr++];
else if (control == MidiConstants.RPN_LSB)
data = inputPacket.buffer[rpnLSBPtr++];
else if (control == MidiConstants.DAMPER_SUSTAIN_PEDAL ||
control == MidiConstants.PORTAMENTO_SWITCH ||
control == MidiConstants.ALL_SOUND_OFF ||
control == MidiConstants.RESET_ALL_CONTROLLERS ||
control == MidiConstants.ALL_NOTES_OFF)
data = inputPacket.buffer[switchControlPtr++];
else
data = inputPacket.buffer[miscControlPtr++];
data += controlValues[control];
controlValues[control] = data;
midiFile.p1(data & 0x7f);
} else if (lastBaseOpcode == OP_PITCH) {
if (newOpcode)
midiFile.p1(MidiConstants.PITCH_WHEEL + channel);
pitchWheel += inputPacket.buffer[pitchWheelLSBPtr++];
pitchWheel += inputPacket.buffer[pitchWheelMSBPtr++] << 7;
midiFile.p1(pitchWheel & 0x7f);
midiFile.p1(pitchWheel >> 7 & 0x7f);
} else if (lastBaseOpcode == OP_AFTERTOUCH) {
if (newOpcode)
midiFile.p1(MidiConstants.AFTERTOUCH + channel);
atPressure += inputPacket.buffer[atPressurePtr++];
midiFile.p1(atPressure & 0x7f);
} else if (lastBaseOpcode == OP_POLY_AFTERTOUCH) {
if (newOpcode)
midiFile.p1(MidiConstants.POLYPHONIC_AFTERTOUCH + channel);
note += inputPacket.buffer[notePtr++];
polyAtPressure += inputPacket.buffer[polyAtPressurePtr++];
midiFile.p1(note & 0x7f);
midiFile.p1(polyAtPressure & 0x7f);
} else {
if (lastBaseOpcode != OP_PROGRAM_CHANGE)
break;
if (newOpcode)
midiFile.p1(MidiConstants.PROGRAM_CHANGE + channel);
midiFile.p1(((int) inputPacket.buffer[continuous0Ptr++]));
}
}
}
throw new RuntimeException("Invalid midi opcode");
} while (false);
midiFile.sp4(midiFile.position - trackStart);
}
}
}