Annotate a bunch of MidiPlayer

This commit is contained in:
Alex Iadicicco 2022-12-11 00:37:25 -08:00 committed by Alexis King
parent 158e745975
commit 7c0c4046a6
18 changed files with 775 additions and 751 deletions

View File

@ -10,13 +10,13 @@ public abstract class AudioSource extends NodeList.Node implements Iterable<Audi
protected AudioSource() {}
public abstract void processAndWrite(int[] dataS16P8, int offset, int len);
public abstract void processAndWrite(int[] data_s16p8, int offset, int len);
public abstract void processAndDiscard(int len);
protected final void processAndWriteIfEnabled(final int[] dataS16P8, final int offset, final int len) {
protected final void processAndWriteIfEnabled(final int[] data_s16p8, final int offset, final int len) {
if (this.enabled) {
this.processAndWrite(dataS16P8, offset, len);
this.processAndWrite(data_s16p8, offset, len);
} else {
this.processAndDiscard(len);
}

View File

@ -1,13 +0,0 @@
package funorb.audio;
public final class KeyParams_idk {
public int _j;
public int _c;
public int _a;
public int _h;
public byte[] _e;
public int _k;
public byte[] _n;
public int _f;
public int vibratoPhaseSpeed_idk;
}

View File

@ -4,12 +4,12 @@ import funorb.io.Buffer;
public final class MidiInstrument {
public final RawSampleS8[] noteSample = new RawSampleS8[128];
public final KeyParams_idk[] keyParams_idk = new KeyParams_idk[128];
public final byte[] notePan_idk = new byte[128];
public final int mainVolume_idk;
public final short[] noteTuning_idk = new short[128];
public final MidiKeyParams[] keyParams = new MidiKeyParams[128];
public final byte[] notePan_p7 = new byte[128];
public final int mainAmp;
public final short[] baseNote_p8 = new short[128]; // <0 for looped
public final byte[] noteOffNote_idk = new byte[128];
public final byte[] noteVolume_idk = new byte[128];
public final byte[] noteAmp = new byte[128];
private int[] noteSampleIds_idk = new int[128];
public MidiInstrument(final byte[] instrumentData) {
@ -88,20 +88,20 @@ public final class MidiInstrument {
}
}
final KeyParams_idk[] var37 = new KeyParams_idk[var12];
final MidiKeyParams[] var37 = new MidiKeyParams[var12];
KeyParams_idk var38;
MidiKeyParams var38;
for (var14 = 0; var14 < var37.length; ++var14) {
var38 = var37[var14] = new KeyParams_idk();
var38 = var37[var14] = new MidiKeyParams();
final int var16 = buf.readUByte();
if (var16 > 0) {
var38._n = new byte[var16 * 2];
var38.volEnv = new byte[var16 * 2];
}
final int j137 = buf.readUByte();
if (j137 > 0) {
var38._e = new byte[2 * j137 + 2];
var38._e[1] = 64;
var38.relEnv = new byte[2 * j137 + 2];
var38.relEnv[1] = 64;
}
}
@ -129,14 +129,14 @@ public final class MidiInstrument {
int var20;
for (var20 = 0; var20 < 128; ++var20) {
var19 += buf.readUByte();
this.noteTuning_idk[var20] = (short) var19;
this.baseNote_p8[var20] = (short) var19;
}
var19 = 0;
for (var20 = 0; var20 < 128; ++var20) {
var19 += buf.readUByte();
this.noteTuning_idk[var20] = (short) (this.noteTuning_idk[var20] + (var19 << 8));
this.baseNote_p8[var20] = (short) (this.baseNote_p8[var20] + (var19 << 8));
}
var20 = 0;
@ -155,7 +155,7 @@ public final class MidiInstrument {
var22 = buf.readVariableInt();
}
this.noteTuning_idk[var23] = (short) (this.noteTuning_idk[var23] + ((var22 - 1 & 2) << 14));
this.baseNote_p8[var23] = (short) (this.baseNote_p8[var23] + ((var22 - 1 & 2) << 14));
--var20;
this.noteSampleIds_idk[var23] = var22;
}
@ -199,13 +199,13 @@ public final class MidiInstrument {
}
--var20;
this.notePan_idk[var25] = (byte) var24;
this.notePan_p7[var25] = (byte) var24;
}
}
int i2 = 0;
var20 = 0;
KeyParams_idk var42 = null;
MidiKeyParams var42 = null;
int var26;
for (var26 = 0; var26 < 128; ++var26) {
@ -220,7 +220,7 @@ public final class MidiInstrument {
}
--var20;
this.keyParams_idk[var26] = var42;
this.keyParams[var26] = var42;
}
}
@ -243,24 +243,24 @@ public final class MidiInstrument {
}
--var20;
this.noteVolume_idk[var27] = (byte) var26;
this.noteAmp[var27] = (byte) var26;
}
this.mainVolume_idk = buf.readUByte() + 1;
this.mainAmp = buf.readUByte() + 1;
KeyParams_idk var28;
MidiKeyParams var28;
int var29;
for (var27 = 0; var27 < var12; ++var27) {
var28 = var37[var27];
if (var28._n != null) {
for (var29 = 1; var29 < var28._n.length; var29 += 2) {
var28._n[var29] = buf.readByte();
if (var28.volEnv != null) {
for (var29 = 1; var29 < var28.volEnv.length; var29 += 2) {
var28.volEnv[var29] = buf.readByte();
}
}
if (var28._e != null) {
for (var29 = 3; var28._e.length - 2 > var29; var29 += 2) {
var28._e[var29] = buf.readByte();
if (var28.relEnv != null) {
for (var29 = 3; var28.relEnv.length - 2 > var29; var29 += 2) {
var28.relEnv[var29] = buf.readByte();
}
}
}
@ -279,24 +279,24 @@ public final class MidiInstrument {
for (var27 = 0; var27 < var12; ++var27) {
var28 = var37[var27];
if (var28._e != null) {
if (var28.relEnv != null) {
var19 = 0;
for (var29 = 2; var29 < var28._e.length; var29 += 2) {
for (var29 = 2; var29 < var28.relEnv.length; var29 += 2) {
var19 = buf.readUByte() + var19 + 1;
var28._e[var29] = (byte) var19;
var28.relEnv[var29] = (byte) var19;
}
}
}
for (var27 = 0; var12 > var27; ++var27) {
var28 = var37[var27];
if (var28._n != null) {
if (var28.volEnv != null) {
var19 = 0;
for (var29 = 2; var29 < var28._n.length; var29 += 2) {
for (var29 = 2; var29 < var28.volEnv.length; var29 += 2) {
var19 = buf.readUByte() + var19 + 1;
var28._n[var29] = (byte) var19;
var28.volEnv[var29] = (byte) var19;
}
}
}
@ -320,7 +320,7 @@ public final class MidiInstrument {
byte var43 = var39[1];
for (var29 = 0; var29 < var47; ++var29) {
this.noteVolume_idk[var29] = (byte) (32 + this.noteVolume_idk[var29] * var43 >> 6);
this.noteAmp[var29] = (byte) (32 + this.noteAmp[var29] * var43 >> 6);
}
for (var29 = 2; var29 < var39.length; var47 = var30) {
@ -330,7 +330,7 @@ public final class MidiInstrument {
for (var33 = var47; var30 > var33; ++var33) {
var34 = a666ql(var32, var30 - var47);
this.noteVolume_idk[var33] = (byte) (32 + this.noteVolume_idk[var33] * var34 >> 6);
this.noteAmp[var33] = (byte) (32 + this.noteAmp[var33] * var34 >> 6);
var32 += -var43 + var31;
}
@ -339,7 +339,7 @@ public final class MidiInstrument {
}
for (var45 = var47; var45 < 128; ++var45) {
this.noteVolume_idk[var45] = (byte) (32 + this.noteVolume_idk[var45] * var43 >> 6);
this.noteAmp[var45] = (byte) (32 + this.noteAmp[var45] * var43 >> 6);
}
}
@ -356,7 +356,7 @@ public final class MidiInstrument {
int var44 = var40[1] << 1;
for (var29 = 0; var29 < var47; ++var29) {
var45 = (this.notePan_idk[var29] & 255) + var44;
var45 = (this.notePan_p7[var29] & 255) + var44;
if (var45 < 0) {
var45 = 0;
}
@ -365,7 +365,7 @@ public final class MidiInstrument {
var45 = 128;
}
this.notePan_idk[var29] = (byte) var45;
this.notePan_p7[var29] = (byte) var45;
}
int var46;
@ -376,7 +376,7 @@ public final class MidiInstrument {
for (var33 = var47; var33 < var30; ++var33) {
var34 = a666ql(var32, -var47 + var30);
int var35 = var34 + (255 & this.notePan_idk[var33]);
int var35 = var34 + (255 & this.notePan_p7[var33]);
if (var35 < 0) {
var35 = 0;
}
@ -385,7 +385,7 @@ public final class MidiInstrument {
var35 = 128;
}
this.notePan_idk[var33] = (byte) var35;
this.notePan_p7[var33] = (byte) var35;
var32 += -var44 + var46;
}
@ -394,7 +394,7 @@ public final class MidiInstrument {
}
for (var45 = var47; var45 < 128; ++var45) {
var46 = var44 + (this.notePan_idk[var45] & 255);
var46 = var44 + (this.notePan_p7[var45] & 255);
if (var46 < 0) {
var46 = 0;
}
@ -403,44 +403,44 @@ public final class MidiInstrument {
var46 = 128;
}
this.notePan_idk[var45] = (byte) var46;
this.notePan_p7[var45] = (byte) var46;
}
}
for (var27 = 0; var12 > var27; ++var27) {
var37[var27]._h = buf.readUByte();
var37[var27].expEnv = buf.readUByte();
}
for (var27 = 0; var12 > var27; ++var27) {
var28 = var37[var27];
if (var28._n != null) {
var28._k = buf.readUByte();
if (var28.volEnv != null) {
var28.volEnvKeytrack = buf.readUByte();
}
if (var28._e != null) {
var28._c = buf.readUByte();
if (var28.relEnv != null) {
var28.relEnvKeytrack = buf.readUByte();
}
if (var28._h > 0) {
var28._a = buf.readUByte();
if (var28.expEnv > 0) {
var28.expEnvKeytrack = buf.readUByte();
}
}
for (var27 = 0; var27 < var12; ++var27) {
var37[var27].vibratoPhaseSpeed_idk = buf.readUByte();
var37[var27].vibratoPhaseSpeed_p9 = buf.readUByte();
}
for (var27 = 0; var12 > var27; ++var27) {
var28 = var37[var27];
if (var28.vibratoPhaseSpeed_idk > 0) {
var28._f = buf.readUByte();
if (var28.vibratoPhaseSpeed_p9 > 0) {
var28.vibrato_p6 = buf.readUByte();
}
}
for (var27 = 0; var12 > var27; ++var27) {
var28 = var37[var27];
if (var28._f > 0) {
var28._j = buf.readUByte();
if (var28.vibrato_p6 > 0) {
var28.vibratoAttack = buf.readUByte();
}
}
@ -463,9 +463,9 @@ public final class MidiInstrument {
if (sampleId != var6) {
var6 = sampleId--;
if ((1 & sampleId) == 0) {
sampleData = loader.loadSingleton1(sampleId >> 2);
sampleData = loader.loadSingletonSynth(sampleId >> 2);
} else {
sampleData = loader.loadSingleton2(sampleId >> 2);
sampleData = loader.loadSingletonVorbis(sampleId >> 2);
}
if (sampleData == null) {

View File

@ -0,0 +1,13 @@
package funorb.audio;
public final class MidiKeyParams {
public int vibratoAttack;
public int expEnvKeytrack;
public int expEnv;
public int volEnvKeytrack;
public byte[] volEnv;
public int relEnvKeytrack;
public byte[] relEnv;
public int vibrato_p6;
public int vibratoPhaseSpeed_p9;
}

View File

@ -11,35 +11,36 @@ import java.util.Map;
// "play time" has units of tick-microseconds per quarter note, i.e. it has an extra factor of ticks per
// quarter note in it, which is constant for any given song. "play time" is abbreviated to "pt" in many places
public final class MidiPlayer extends AudioSource {
private static final double PHASE_512_TO_RADIANS = 0.01227184630308513D;
private static final double P9_TURNS_TO_RADIANS = 0.01227184630308513D;
private static final double P8_NOTE_TO_OCTAVE = 3.255208333333333E-4D;
public static final int FLAG_SUSTAIN = 0x0001;
public static final int FLAG_PORTAMENTO = 0x0002;
public static final int FLAG_GENERAL_6 = 0x0004;
public final int[] chGeneral1 = new int[16];
public final int[] chStartOffset_p6 = new int[16]; // GP controller 1
private final int[] chGeneral2 = new int[16]; // GP controller 2
public final int[] chGeneral2Exp = new int[16];
public final int[] chFlags = new int[16];
private final int[] chModWheel = new int[16];
private final int[] chVolume = new int[16];
private final int[] chVol_p14 = new int[16];
private final int[] chRpn = new int[16];
private final MidiPlayerNoteState_idk[][] noteStates = new MidiPlayerNoteState_idk[16][128];
private final MidiPlayingNote[][] noteStates = new MidiPlayingNote[16][128];
private final int[] chPitchBendRange = new int[16];
private final int[] chDefaultBank_idk = new int[16];
private final Map<Integer, MidiInstrument> instruments;
private final int[] chPan = new int[16];
private final int[] chPan_p14 = new int[16];
private final MidiReader midiReader = new MidiReader();
private final int[] chCurrentProgram = new int[16];
private final int[] chBank = new int[16];
private final int[] chGeneral2 = new int[16];
private final int[] chPortaTime = new int[16];
private final int[] chVolumeAgainForSomeReason_idk = new int[16];
private final int[] chGlobalAmp_p8 = new int[16];
private final int[] chPitchWheel = new int[16];
private final MidiPlayerNoteSet_idk noteSet = new MidiPlayerNoteSet_idk(this);
public final int[] _u = new int[16];
private int volume = 256;
private final MidiPlayerNoteState_idk[][] noteOffStates_idk = new MidiPlayerNoteState_idk[16][128];
private int microsecondsPerSecond = 1000000;
private final int[] chExpression = new int[16];
private final MidiPlayingNoteSet noteSet = new MidiPlayingNoteSet(this);
private int amp_p8 = 256;
private final MidiPlayingNote[][] noteOffStates_idk = new MidiPlayingNote[16][128];
private int usPerSec = 1000000;
private final int[] chExpression_p14 = new int[16];
private int trackWithSoonestEvent;
private long outputPt;
private int nextEventTicks;
@ -49,14 +50,14 @@ public final class MidiPlayer extends AudioSource {
public MidiPlayer() {
this.instruments = new HashMap<>();
this.a679();
this.initChGlobalAmp();
this.handleReset(true);
}
@SuppressWarnings("CopyConstructorMissesField")
public MidiPlayer(final MidiPlayer copyInstruments) {
this.instruments = copyInstruments.instruments;
this.a679();
this.initChGlobalAmp();
this.handleReset(true);
}
@ -80,28 +81,31 @@ public final class MidiPlayer extends AudioSource {
private void handleGeneral2(final int value, final int channel) {
this.chGeneral2[channel] = value;
this._u[channel] = (int) (0.5D + 2097152.0D * Math.pow(2.0D, 5.4931640625E-4D * (double) value));
this.chGeneral2Exp[channel] = (int) (0.5D + 2097152.0D * Math.pow(2.0D, 5.4931640625E-4D * (double) value));
}
private int calcPitchX_idk(final MidiPlayerNoteState_idk note) {
int var3 = (note._pitch_fac_1 * note._pitch_fac_2 >> 12) + note.pitch_idk;
var3 += this.chPitchBendRange[note.channel] * (this.chPitchWheel[note.channel] - 8192) >> 12;
final KeyParams_idk var4 = note.keyParams_idk;
int pitch;
if (var4.vibratoPhaseSpeed_idk > 0 && (var4._f > 0 || this.chModWheel[note.channel] > 0)) {
pitch = var4._f << 2;
final int var7 = var4._j << 1;
if (var7 > note._C) {
pitch = note._C * pitch / var7;
private int calcSpeed_p8(final MidiPlayingNote note) {
int relNote_p8 = (note.portaRange_p8 * note.portaMag_p12 >> 12) + note.relNote_p8;
relNote_p8 += this.chPitchBendRange[note.channel] * (this.chPitchWheel[note.channel] - 8192) >> 12;
final MidiKeyParams params = note.params;
int vibrato_p8;
if (params.vibratoPhaseSpeed_p9 > 0 && (params.vibrato_p6 > 0 || this.chModWheel[note.channel] > 0)) {
vibrato_p8 = params.vibrato_p6 << 2;
final int vibratoAttack = params.vibratoAttack << 1;
if (note.vibratoTime < vibratoAttack) {
vibrato_p8 = note.vibratoTime * vibrato_p8 / vibratoAttack;
}
pitch += this.chModWheel[note.channel] >> 7;
final double vibrato = Math.sin((double) (note.vibratoPhase_idk & 0x1ff) * PHASE_512_TO_RADIANS);
var3 += (int) ((double) pitch * vibrato);
vibrato_p8 += this.chModWheel[note.channel] >> 7;
relNote_p8 += (int) (vibrato_p8 * Math.sin((note.vibratoPhase_p9 & 0x1ff) * P9_TURNS_TO_RADIANS));
}
pitch = (int) ((double) (256 * note.sampleData.sampleRate) * Math.pow(2.0D, 3.255208333333333E-4D * (double) var3) / (double) SampledAudioChannelS16.SAMPLE_RATE + 0.5D);
return Math.max(pitch, 1);
int speed_p8 = (int)(
(double)(256 * note.sampleData.sampleRate)
* Math.pow(2.0D, P8_NOTE_TO_OCTAVE * relNote_p8) / (double) SampledAudioChannelS16.SAMPLE_RATE
+ 0.5D);
return Math.max(speed_p8, 1);
}
public synchronized void f150() {
@ -111,37 +115,37 @@ public final class MidiPlayer extends AudioSource {
}
private void handleAllNotesOff(final int channel) {
for (final MidiPlayerNoteState_idk state : this.noteSet.notes) {
if ((channel < 0 || state.channel == channel) && state.notePlaying_idfk < 0) {
for (final MidiPlayingNote state : this.noteSet.notes) {
if ((channel < 0 || state.channel == channel) && state.relEnvTime < 0) {
this.noteStates[state.channel][state.note] = null;
state.notePlaying_idfk = 0;
state.relEnvTime = 0;
}
}
}
private void handleNoteOff(final int channel, final int note) {
final MidiPlayerNoteState_idk state = this.noteStates[channel][note];
final MidiPlayingNote state = this.noteStates[channel][note];
if (state != null) {
this.noteStates[channel][note] = null;
if ((FLAG_PORTAMENTO & this.chFlags[channel]) == 0) {
state.notePlaying_idfk = 0;
} else if (this.noteSet.notes.stream().anyMatch(var6 -> state.channel == var6.channel && var6.notePlaying_idfk < 0 && var6 != state)) {
state.notePlaying_idfk = 0;
state.relEnvTime = 0;
} else if (this.noteSet.notes.stream().anyMatch(n -> state.channel == n.channel && n.relEnvTime < 0 && n != state)) {
state.relEnvTime = 0;
}
}
}
public synchronized void c430() {
this.microsecondsPerSecond = 1000000;
public synchronized void initMicrosecondsPerSecond() {
this.usPerSec = 1000000;
}
public synchronized void a679() {
public synchronized void initChGlobalAmp() {
for (int channel = 0; channel < 16; ++channel) {
this.chVolumeAgainForSomeReason_idk[channel] = 256;
this.chGlobalAmp_p8[channel] = 256;
}
}
public synchronized void a350(final SoundLoader soundLoader, final ResourceLoader loader, final SongData track) {
public synchronized void loadNoteSamplesForSong(final SoundLoader soundLoader, final ResourceLoader loader, final SongData track) {
track.analyzeNotesUsedPerProgram();
boolean success = true;
@ -170,9 +174,9 @@ public final class MidiPlayer extends AudioSource {
}
@Override
public synchronized void processAndWrite(final int[] dataS16P8, int offset, int len) {
public synchronized void processAndWrite(final int[] data_s16p8, int offset, int len) {
if (this.midiReader.isLoaded()) {
final long ptPerSample = this.midiReader.ticksPerQuarterNote * this.microsecondsPerSecond / SampledAudioChannelS16.SAMPLE_RATE;
final long ptPerSample = (long) this.midiReader.ticksPerQn * this.usPerSec / SampledAudioChannelS16.SAMPLE_RATE;
do {
final long bufferPt = this.outputPt + len * ptPerSample;
@ -183,20 +187,20 @@ public final class MidiPlayer extends AudioSource {
final long samples = (this.playerPt - this.outputPt + ptPerSample - 1L) / ptPerSample;
this.outputPt += samples * ptPerSample;
this.noteSet.processAndWrite(dataS16P8, offset, (int) samples);
this.noteSet.processAndWrite(data_s16p8, offset, (int) samples);
offset += samples;
len -= samples;
this.pumpEvents();
} while (this.midiReader.isLoaded());
}
this.noteSet.processAndWrite(dataS16P8, offset, len);
this.noteSet.processAndWrite(data_s16p8, offset, len);
}
@Override
public synchronized void processAndDiscard(int len) {
if (this.midiReader.isLoaded()) {
final long ptPerSample = this.midiReader.ticksPerQuarterNote * this.microsecondsPerSecond / SampledAudioChannelS16.SAMPLE_RATE;
final long ptPerSample = (long) this.midiReader.ticksPerQn * this.usPerSec / SampledAudioChannelS16.SAMPLE_RATE;
do {
final long bufferPt = len * ptPerSample + this.outputPt;
@ -217,8 +221,8 @@ public final class MidiPlayer extends AudioSource {
}
@SuppressWarnings("SameParameterValue")
public synchronized void setVolume(final int volume) {
this.volume = volume;
public synchronized void setAmp_p8(final int amp_p8) {
this.amp_p8 = amp_p8;
}
private synchronized void reset(final boolean doSoundOff) {
@ -228,7 +232,7 @@ public final class MidiPlayer extends AudioSource {
}
private void handleAllSoundOff(final int channel) {
for (final MidiPlayerNoteState_idk note : this.noteSet.notes) {
for (final MidiPlayingNote note : this.noteSet.notes) {
if (channel < 0 || channel == note.channel) {
if (note.playback != null) {
note.playback.setVolZeroRamped(SampledAudioChannelS16.SAMPLE_RATE / 100);
@ -236,10 +240,10 @@ public final class MidiPlayer extends AudioSource {
this.noteSet.sum.addFirst(note.playback);
}
note.reset_idk();
note.reset();
}
if (note.notePlaying_idfk < 0) {
if (note.relEnvTime < 0) {
this.noteStates[note.channel][note.note] = null;
}
@ -250,24 +254,24 @@ public final class MidiPlayer extends AudioSource {
private void handlePortamentoOff(final int channel) {
if ((FLAG_PORTAMENTO & this.chFlags[channel]) != 0) {
for (final MidiPlayerNoteState_idk var3 : this.noteSet.notes) {
if (var3.channel == channel && this.noteStates[channel][var3.note] == null && var3.notePlaying_idfk < 0) {
var3.notePlaying_idfk = 0;
for (final MidiPlayingNote var3 : this.noteSet.notes) {
if (var3.channel == channel && this.noteStates[channel][var3.note] == null && var3.relEnvTime < 0) {
var3.relEnvTime = 0;
}
}
}
}
public synchronized void a077(final SongData songData, final boolean looped) {
public synchronized void changeSong(final SongData songData, final boolean looped) {
this.changeSong(looped, songData, true);
}
private void handleResetAllControllers(int channel) {
if (channel >= 0) {
this.chVolume[channel] = 12800;
this.chPan[channel] = 8192;
this.chVol_p14[channel] = 12800; // not a typo, many midi impls default to vol=100
this.chPan_p14[channel] = 8192;
this.chExpression[channel] = 16383;
this.chExpression_p14[channel] = 16383;
this.chPitchWheel[channel] = 8192;
this.chModWheel[channel] = 0;
this.chPortaTime[channel] = 8192;
@ -276,7 +280,7 @@ public final class MidiPlayer extends AudioSource {
this.chFlags[channel] = 0;
this.chRpn[channel] = 32767;
this.chPitchBendRange[channel] = 256;
this.chGeneral1[channel] = 0;
this.chStartOffset_p6[channel] = 0;
this.handleGeneral2(8192, channel);
} else {
for (channel = 0; channel < 16; ++channel) {
@ -306,9 +310,9 @@ public final class MidiPlayer extends AudioSource {
}
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
public boolean a258(final MidiPlayerNoteState_idk note) {
public boolean noteIgnored(final MidiPlayingNote note) {
if (note.playback == null) {
if (note.notePlaying_idfk >= 0) {
if (note.relEnvTime >= 0) {
note.unlink();
if (note.noteOffNote_idk > 0 && note == this.noteOffStates_idk[note.channel][note.noteOffNote_idk]) {
this.noteOffStates_idk[note.channel][note.noteOffNote_idk] = null;
@ -368,25 +372,25 @@ public final class MidiPlayer extends AudioSource {
}
if (controller == 7) { // volume msb
this.chVolume[channel] = (value << 7) + (0xffffc07f & this.chVolume[channel]);
this.chVol_p14[channel] = (value << 7) + (0xffffc07f & this.chVol_p14[channel]);
}
if (controller == 39) { // volume lsb
this.chVolume[channel] = (0xffffff80 & this.chVolume[channel]) + value;
this.chVol_p14[channel] = (0xffffff80 & this.chVol_p14[channel]) + value;
}
if (controller == 10) { // pan msb
this.chPan[channel] = (value << 7) + (this.chPan[channel] & 0xffffc07f);
this.chPan_p14[channel] = (value << 7) + (this.chPan_p14[channel] & 0xffffc07f);
}
if (controller == 42) { // pan lsb
this.chPan[channel] = (this.chPan[channel] & 0xffffff80) + value;
this.chPan_p14[channel] = (this.chPan_p14[channel] & 0xffffff80) + value;
}
if (controller == 11) { // expression msb
this.chExpression[channel] = (value << 7) + (0xffffc07f & this.chExpression[channel]);
this.chExpression_p14[channel] = (value << 7) + (0xffffc07f & this.chExpression_p14[channel]);
}
if (controller == 43) { // expression lsb
this.chExpression[channel] = value + (this.chExpression[channel] & 0xffffff80);
this.chExpression_p14[channel] = value + (this.chExpression_p14[channel] & 0xffffff80);
}
if (controller == 64) { // sustain on/off
@ -444,10 +448,10 @@ public final class MidiPlayer extends AudioSource {
}
if (controller == 16) { // gp controller #1 msb
this.chGeneral1[channel] = (value << 7) + (this.chGeneral1[channel] & 0xffffc07f);
this.chStartOffset_p6[channel] = (value << 7) + (this.chStartOffset_p6[channel] & 0xffffc07f);
}
if (controller == 48) { // gp controller #1 lsb
this.chGeneral1[channel] = (this.chGeneral1[channel] & 0xffffff80) + value;
this.chStartOffset_p6[channel] = (this.chStartOffset_p6[channel] & 0xffffff80) + value;
}
if (controller == 81) { // gp controller #6 lsb
@ -514,7 +518,7 @@ public final class MidiPlayer extends AudioSource {
private void handleGeneral6Off(final int var2) {
if ((FLAG_GENERAL_6 & this.chFlags[var2]) != 0) {
for (final MidiPlayerNoteState_idk var3 : this.noteSet.notes) {
for (final MidiPlayingNote var3 : this.noteSet.notes) {
if (var3.channel == var2) {
var3._j = 0;
}
@ -526,15 +530,15 @@ public final class MidiPlayer extends AudioSource {
private void handleNoteOn(final int noteNumber, final int channel, final int velocity) {
this.handleNoteOff(channel, noteNumber);
if ((this.chFlags[channel] & FLAG_PORTAMENTO) != 0) {
for (final Iterator<MidiPlayerNoteState_idk> it = this.noteSet.notes.descendingIterator(); it.hasNext(); ) {
final MidiPlayerNoteState_idk note = it.next();
if (note.channel == channel && note.notePlaying_idfk < 0) {
for (final Iterator<MidiPlayingNote> it = this.noteSet.notes.descendingIterator(); it.hasNext(); ) {
final MidiPlayingNote note = it.next();
if (note.channel == channel && note.relEnvTime < 0) {
this.noteStates[channel][note.note] = null;
this.noteStates[channel][noteNumber] = note;
final int var6 = (note._pitch_fac_2 * note._pitch_fac_1 >> 12) + note.pitch_idk;
note.pitch_idk += -note.note + noteNumber << 8;
note._pitch_fac_2 = 4096;
note._pitch_fac_1 = -note.pitch_idk + var6;
final int curNote_p8 = (note.portaMag_p12 * note.portaRange_p8 >> 12) + note.relNote_p8;
note.relNote_p8 += -note.note + noteNumber << 8;
note.portaMag_p12 = 4096;
note.portaRange_p8 = curNote_p8 - note.relNote_p8;
note.note = noteNumber;
return;
}
@ -542,151 +546,162 @@ public final class MidiPlayer extends AudioSource {
}
final MidiInstrument instrument = this.instruments.get(this.chCurrentProgram[channel]);
if (instrument != null) {
final RawSampleS8 sample = instrument.noteSample[noteNumber];
if (sample != null) {
final MidiPlayerNoteState_idk note = new MidiPlayerNoteState_idk();
note.channel = channel;
note.instrument = instrument;
note.sampleData = sample;
note.keyParams_idk = instrument.keyParams_idk[noteNumber];
note.noteOffNote_idk = instrument.noteOffNote_idk[noteNumber];
note.note = noteNumber;
note.volume_idk = instrument.noteVolume_idk[noteNumber] * velocity * velocity * instrument.mainVolume_idk + 1024 >> 11;
note.pan_idk = instrument.notePan_idk[noteNumber] & 255;
note.pitch_idk = (noteNumber << 8) - (instrument.noteTuning_idk[noteNumber] & 32767);
note._B = 0;
note.notePlaying_idfk = -1;
note._F = 0;
note._h = 0;
note._v = 0;
if (this.chGeneral1[channel] == 0) {
note.playback = RawSamplePlayer.start(sample, this.calcPitchX_idk(note), this.calcVolumeX_idk(note), this.calcPanX_idk(note));
} else {
note.playback = RawSamplePlayer.start(sample, this.calcPitchX_idk(note), 0, this.calcPanX_idk(note));
this.a559(note, instrument.noteTuning_idk[noteNumber] < 0);
}
if (instrument == null) return;
if (instrument.noteTuning_idk[noteNumber] < 0) {
assert note.playback != null;
note.playback.f150();
}
final RawSampleS8 sample = instrument.noteSample[noteNumber];
if (sample == null) return;
if (note.noteOffNote_idk >= 0) {
final MidiPlayerNoteState_idk noteOff = this.noteOffStates_idk[channel][note.noteOffNote_idk];
if (noteOff != null && noteOff.notePlaying_idfk < 0) {
this.noteStates[channel][noteOff.note] = null;
noteOff.notePlaying_idfk = 0;
}
final MidiPlayingNote note = new MidiPlayingNote();
note.channel = channel;
note.instrument = instrument;
note.sampleData = sample;
note.params = instrument.keyParams[noteNumber];
note.noteOffNote_idk = instrument.noteOffNote_idk[noteNumber];
note.note = noteNumber;
note.amp_p15 = instrument.noteAmp[noteNumber] * velocity * velocity * instrument.mainAmp + 1024 >> 11;
note.pan_p7 = instrument.notePan_p7[noteNumber] & 255;
note.relNote_p8 = (noteNumber << 8) - (instrument.baseNote_p8[noteNumber] & 32767);
note.relEnvTime = -1;
note.volEnvTime = 0;
note.expEnvTime = 0;
note.volEnvIdx = 0;
note.relEnvIdx = 0;
this.noteOffStates_idk[channel][note.noteOffNote_idk] = note;
}
this.noteSet.notes.addLast(note);
this.noteStates[channel][noteNumber] = note;
}
if (this.chStartOffset_p6[channel] == 0) {
note.playback = RawSamplePlayer.of(
sample,
this.calcSpeed_p8(note),
this.calcVol_p14(note),
this.calcPan_p14(note)
);
} else {
note.playback = RawSamplePlayer.of(sample, this.calcSpeed_p8(note), 0, this.calcPan_p14(note));
this.initPlayhead(note, instrument.baseNote_p8[noteNumber] < 0);
}
if (instrument.baseNote_p8[noteNumber] < 0) {
assert note.playback != null;
note.playback.setLooped();
}
if (note.noteOffNote_idk >= 0) {
final MidiPlayingNote noteOff = this.noteOffStates_idk[channel][note.noteOffNote_idk];
if (noteOff != null && noteOff.relEnvTime < 0) {
this.noteStates[channel][noteOff.note] = null;
noteOff.relEnvTime = 0;
}
this.noteOffStates_idk[channel][note.noteOffNote_idk] = note;
}
this.noteSet.notes.addLast(note);
this.noteStates[channel][noteNumber] = note;
}
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
public boolean a543(final int var1, final int[] var2, final MidiPlayerNoteState_idk var4, final int var5) {
var4.lenRemaining_idk = SampledAudioChannelS16.SAMPLE_RATE / 100;
if (var4.notePlaying_idfk < 0 || var4.playback != null && !var4.playback.isPlayheadOutOfBounds()) {
int var6 = var4._pitch_fac_2;
if (var6 > 0) {
var6 -= (int) (Math.pow(2.0D, (double) this.chPortaTime[var4.channel] * 4.921259842519685E-4D) * 16.0D + 0.5D);
if (var6 < 0) {
var6 = 0;
}
public boolean processNote(final int offset, final int[] dest_s16p8, final MidiPlayingNote note, final int len) {
note.timeLeft = SampledAudioChannelS16.SAMPLE_RATE / 100;
var4._pitch_fac_2 = var6;
}
var4.playback.setAbsSpeed_p8(this.calcPitchX_idk(var4));
final KeyParams_idk var7 = var4.keyParams_idk;
var4.vibratoPhase_idk += var7.vibratoPhaseSpeed_idk;
++var4._C;
boolean var8 = false;
final double var9 = 5.086263020833333E-6D * (double) ((var4.note - 60 << 8) + (var4._pitch_fac_2 * var4._pitch_fac_1 >> 12));
if (var7._h > 0) {
if (var7._a > 0) {
var4._h += (int) (Math.pow(2.0D, var9 * (double) var7._a) * 128.0D + 0.5D);
} else {
var4._h += 128;
}
if (var7._h * var4._h >= 819200) {
var8 = true;
}
}
if (var7._n != null) {
if (var7._k <= 0) {
var4._F += 128;
} else {
var4._F += (int) (0.5D + Math.pow(2.0D, var9 * (double) var7._k) * 128.0D);
}
while (var4._B < var7._n.length - 2 && ('\uff00' & var7._n[2 + var4._B] << 8) < var4._F) {
var4._B += 2;
}
if (var7._n.length - 2 == var4._B && var7._n[1 + var4._B] == 0) {
var8 = true;
}
}
if (var4.notePlaying_idfk >= 0 && var7._e != null && (FLAG_SUSTAIN & this.chFlags[var4.channel]) == 0 && (var4.noteOffNote_idk < 0 || this.noteOffStates_idk[var4.channel][var4.noteOffNote_idk] != var4)) {
if (var7._c <= 0) {
var4.notePlaying_idfk += 128;
} else {
var4.notePlaying_idfk += (int) (0.5D + 128.0D * Math.pow(2.0D, (double) var7._c * var9));
}
while (var4._v < var7._e.length - 2 && var4.notePlaying_idfk > (255 & var7._e[2 + var4._v]) << 8) {
var4._v += 2;
}
if (var7._e.length - 2 == var4._v) {
var8 = true;
}
}
if (var8) {
var4.playback.setVolZeroRamped(var4.lenRemaining_idk);
if (var2 == null) {
var4.playback.processAndDiscard(var5);
} else {
var4.playback.processAndWrite(var2, var1, var5);
}
if (var4.playback.isRampTimeNonzero()) {
this.noteSet.sum.addFirst(var4.playback);
}
var4.reset_idk();
if (var4.notePlaying_idfk >= 0) {
var4.unlink();
if (var4.noteOffNote_idk > 0 && this.noteOffStates_idk[var4.channel][var4.noteOffNote_idk] == var4) {
this.noteOffStates_idk[var4.channel][var4.noteOffNote_idk] = null;
}
}
return true;
} else {
var4.playback.setVolAndPanRamped_p14(var4.lenRemaining_idk, this.calcVolumeX_idk(var4), this.calcPanX_idk(var4));
return false;
}
} else {
var4.reset_idk();
var4.unlink();
if (var4.noteOffNote_idk > 0 && this.noteOffStates_idk[var4.channel][var4.noteOffNote_idk] == var4) {
this.noteOffStates_idk[var4.channel][var4.noteOffNote_idk] = null;
if (note.relEnvTime >= 0 && (note.playback == null || note.playback.isPlayheadOutOfBounds())) {
note.reset();
note.unlink();
if (note.noteOffNote_idk > 0 && this.noteOffStates_idk[note.channel][note.noteOffNote_idk] == note) {
this.noteOffStates_idk[note.channel][note.noteOffNote_idk] = null;
}
return true;
}
int porta = note.portaMag_p12;
if (porta > 0) {
porta -= (int) (Math.pow(2.0D, (double) this.chPortaTime[note.channel] * 4.921259842519685E-4D) * 16.0D + 0.5D);
if (porta < 0) {
porta = 0;
}
note.portaMag_p12 = porta;
}
note.playback.setAbsSpeed_p8(this.calcSpeed_p8(note));
final MidiKeyParams params = note.params;
note.vibratoPhase_p9 += params.vibratoPhaseSpeed_p9;
++note.vibratoTime;
boolean envEnded = false;
// relative to middle C (note=60), used for keytracking
final double relOctave = 5.086263020833333E-6D * (double) ((note.note - 60 << 8) + (note.portaMag_p12 * note.portaRange_p8 >> 12));
if (params.expEnv > 0) {
if (params.expEnvKeytrack > 0) {
note.expEnvTime += (int) (Math.pow(2.0D, relOctave * (double) params.expEnvKeytrack) * 128.0D + 0.5D);
} else {
note.expEnvTime += 128;
}
if (params.expEnv * note.expEnvTime >= 819200) {
envEnded = true;
}
}
if (params.volEnv != null) {
if (params.volEnvKeytrack <= 0) {
note.volEnvTime += 128;
} else {
note.volEnvTime += (int) (0.5D + Math.pow(2.0D, relOctave * (double) params.volEnvKeytrack) * 128.0D);
}
while (note.volEnvIdx < params.volEnv.length - 2 && ('\uff00' & params.volEnv[2 + note.volEnvIdx] << 8) < note.volEnvTime) {
note.volEnvIdx += 2;
}
if (params.volEnv.length - 2 == note.volEnvIdx && params.volEnv[1 + note.volEnvIdx] == 0) {
envEnded = true;
}
}
if (note.relEnvTime >= 0 && params.relEnv != null && (FLAG_SUSTAIN & this.chFlags[note.channel]) == 0 && (note.noteOffNote_idk < 0 || this.noteOffStates_idk[note.channel][note.noteOffNote_idk] != note)) {
if (params.relEnvKeytrack <= 0) {
note.relEnvTime += 128;
} else {
note.relEnvTime += (int) (0.5D + 128.0D * Math.pow(2.0D, (double) params.relEnvKeytrack * relOctave));
}
while (note.relEnvIdx < params.relEnv.length - 2 && note.relEnvTime > (255 & params.relEnv[2 + note.relEnvIdx]) << 8) {
note.relEnvIdx += 2;
}
if (params.relEnv.length - 2 == note.relEnvIdx) {
envEnded = true;
}
}
if (envEnded) {
note.playback.setVolZeroRamped(note.timeLeft);
if (dest_s16p8 == null) {
note.playback.processAndDiscard(len);
} else {
note.playback.processAndWrite(dest_s16p8, offset, len);
}
if (note.playback.isRampTimeNonzero()) {
this.noteSet.sum.addFirst(note.playback);
}
note.reset();
if (note.relEnvTime >= 0) {
note.unlink();
if (note.noteOffNote_idk > 0 && this.noteOffStates_idk[note.channel][note.noteOffNote_idk] == note) {
this.noteOffStates_idk[note.channel][note.noteOffNote_idk] = null;
}
}
return true;
} else {
note.playback.setVolAndPanRamped_p14(note.timeLeft, this.calcVol_p14(note), this.calcPan_p14(note));
return false;
}
}
private void handleProgramChange(final int channel, final int program) {
@ -698,11 +713,11 @@ public final class MidiPlayer extends AudioSource {
}
}
private int calcPanX_idk(final MidiPlayerNoteState_idk note) {
final int midiPan = this.chPan[note.channel];
return midiPan >= 8192
? -(32 + (128 - note.pan_idk) * (-midiPan + 16384) >> 6) + 16384
: 32 + note.pan_idk * midiPan >> 6;
private int calcPan_p14(final MidiPlayingNote note) {
final int chPan_p14 = this.chPan_p14[note.channel];
return chPan_p14 >= 8192
? 16384 - (32 + (128 - note.pan_p7) * (16384 - chPan_p14) >> 6)
: 32 + note.pan_p7 * chPan_p14 >> 6;
}
private void pumpEvents() {
@ -724,7 +739,7 @@ public final class MidiPlayer extends AudioSource {
this.midiReader.setTrackPlaybackPosToCursor(track);
if (this.midiReader.allTracksStopped()) {
if (this.songData != null) {
this.a077(this.songData, this.looped);
this.changeSong(this.songData, this.looped);
this.pumpEvents();
return;
}
@ -765,66 +780,68 @@ public final class MidiPlayer extends AudioSource {
}
}
public void a559(final MidiPlayerNoteState_idk note, final boolean var3) {
public void initPlayhead(final MidiPlayingNote note, final boolean isLooped) {
int sampleLength = note.sampleData.data_s8.length;
int playhead;
if (var3 && note.sampleData.isLooped_idk) {
final int var6 = -note.sampleData.loopStart_idfk + sampleLength + sampleLength;
playhead = (int) ((long) this.chGeneral1[note.channel] * (long) var6 >> 6);
if (isLooped && note.sampleData.isPingPongLoop) {
final int var6 = -note.sampleData.loopStart + sampleLength + sampleLength;
playhead = (int) ((long) this.chStartOffset_p6[note.channel] * (long) var6 >> 6);
sampleLength <<= 8;
if (playhead >= sampleLength) {
note.playback.setBackwards();
playhead = -playhead + sampleLength + sampleLength - 1;
}
} else {
playhead = (int) ((long) this.chGeneral1[note.channel] * (long) sampleLength >> 6);
playhead = (int) ((long) this.chStartOffset_p6[note.channel] * (long) sampleLength >> 6);
}
note.playback.setPlayhead_p8(playhead);
}
private int calcVolumeX_idk(final MidiPlayerNoteState_idk note) {
if (this.chVolumeAgainForSomeReason_idk[note.channel] == 0) {
private int calcVol_p14(final MidiPlayingNote note) {
if (this.chGlobalAmp_p8[note.channel] == 0) {
return 0;
}
final KeyParams_idk keyParams = note.keyParams_idk;
int x = this.chVolume[note.channel] * this.chExpression[note.channel] + 4096 >> 13;
x = x * x + 16384 >> 15;
x = note.volume_idk * x + 16384 >> 15;
x = 128 + this.volume * x >> 8;
x = this.chVolumeAgainForSomeReason_idk[note.channel] * x + 128 >> 8;
if (keyParams._h > 0) {
x = (int) (0.5D + (double) x * Math.pow(0.5D, (double) note._h * 1.953125E-5D * (double) keyParams._h));
final MidiKeyParams keyParams = note.params;
int x;
x = 4096 + this.chVol_p14[note.channel] * this.chExpression_p14[note.channel] >> 13;
x = 16384 + x * x >> 15;
x = 16384 + note.amp_p15 * x >> 15;
x = 128 + this.amp_p8 * x >> 8;
x = 128 + this.chGlobalAmp_p8[note.channel] * x >> 8;
if (keyParams.expEnv > 0) {
x = (int) (0.5D + (double) x * Math.pow(0.5D, (double) note.expEnvTime * 1.953125E-5D * (double) keyParams.expEnv));
}
int var5;
int var6;
int var7;
int var8;
if (keyParams._n != null) {
var5 = note._F;
var6 = keyParams._n[1 + note._B];
if (note._B < keyParams._n.length - 2) {
var7 = keyParams._n[note._B] << 8 & '\uff00';
var8 = (255 & keyParams._n[2 + note._B]) << 8;
var6 += (-var6 + keyParams._n[note._B + 3]) * (-var7 + var5) / (-var7 + var8);
int t_p8;
int env;
int t0_p8;
int t1_p8;
if (keyParams.volEnv != null) {
t_p8 = note.volEnvTime;
env = keyParams.volEnv[note.volEnvIdx + 1];
if (note.volEnvIdx < keyParams.volEnv.length - 2) {
t0_p8 = (255 & keyParams.volEnv[note.volEnvIdx]) << 8;
t1_p8 = (255 & keyParams.volEnv[note.volEnvIdx + 2]) << 8;
env += (keyParams.volEnv[note.volEnvIdx + 3] - env) * (t_p8 - t0_p8) / (t1_p8 - t0_p8);
}
x = var6 * x + 32 >> 6;
x = 32 + env * x >> 6;
}
if (note.notePlaying_idfk > 0 && keyParams._e != null) {
var5 = note.notePlaying_idfk;
var6 = keyParams._e[1 + note._v];
if (keyParams._e.length - 2 > note._v) {
var7 = (255 & keyParams._e[note._v]) << 8;
var8 = keyParams._e[2 + note._v] << 8 & '\uff00';
var6 += (keyParams._e[note._v + 3] - var6) * (-var7 + var5) / (-var7 + var8);
if (note.relEnvTime > 0 && keyParams.relEnv != null) {
t_p8 = note.relEnvTime;
env = keyParams.relEnv[note.relEnvIdx + 1];
if (note.relEnvIdx < keyParams.relEnv.length - 2) {
t0_p8 = (255 & keyParams.relEnv[note.relEnvIdx]) << 8;
t1_p8 = (255 & keyParams.relEnv[note.relEnvIdx + 2]) << 8;
env += (keyParams.relEnv[note.relEnvIdx + 3] - env) * (t_p8 - t0_p8) / (-t0_p8 + t1_p8);
}
x = 32 + x * var6 >> 6;
x = 32 + env * x >> 6;
}
return x;

View File

@ -1,149 +0,0 @@
package funorb.audio;
import funorb.data.NodeList;
import org.jetbrains.annotations.NotNull;
import java.util.Iterator;
import java.util.Objects;
public final class MidiPlayerNoteSet_idk extends AudioSource {
public final NodeList<MidiPlayerNoteState_idk> notes = new NodeList<>();
public final SoundManager sum = new SoundManager();
private final MidiPlayer midiPlayer;
public MidiPlayerNoteSet_idk(final MidiPlayer midiPlayer) {
this.midiPlayer = midiPlayer;
}
@Override
public @NotNull Iterator<AudioSource> iterator() {
return this.notes.stream().<AudioSource>map(var1 -> var1.playback).filter(Objects::nonNull).iterator();
}
@Override
public int returns_0_1_or_2() {
return 0;
}
@Override
public void processAndDiscard(final int len) {
this.sum.processAndDiscard(len);
for (final MidiPlayerNoteState_idk note : this.notes) {
if (!this.midiPlayer.a258(note)) {
int var2 = len;
do {
if (note.lenRemaining_idk >= var2) {
this.a222(note, var2);
note.lenRemaining_idk -= var2;
break;
}
this.a222(note, note.lenRemaining_idk);
var2 -= note.lenRemaining_idk;
} while (!this.midiPlayer.a543(0, null, note, var2));
}
}
}
@Override
public void processAndWrite(final int[] dataS16P8, final int totalOffset, final int totalLen) {
this.sum.processAndWrite(dataS16P8, totalOffset, totalLen);
for (final MidiPlayerNoteState_idk note : this.notes) {
if (this.midiPlayer.a258(note)) {
continue;
}
int offset = totalOffset;
int len = totalLen;
do {
if (note.lenRemaining_idk >= len) {
this.a829(dataS16P8, offset, note, len, offset + len);
note.lenRemaining_idk -= len;
break;
}
this.a829(dataS16P8, offset, note, note.lenRemaining_idk, offset + len);
len -= note.lenRemaining_idk;
offset += note.lenRemaining_idk;
} while (!this.midiPlayer.a543(offset, dataS16P8, note, len));
}
}
private void a222(final MidiPlayerNoteState_idk note, int totalLen) {
if ((MidiPlayer.FLAG_GENERAL_6 & this.midiPlayer.chFlags[note.channel]) != 0 && note.notePlaying_idfk < 0) {
final int var4 = this.midiPlayer._u[note.channel] / SampledAudioChannelS16.SAMPLE_RATE;
final int var5 = (1048575 + var4 - note._j) / var4;
note._j = 1048575 & note._j + totalLen * var4;
if (var5 <= totalLen) {
if (this.midiPlayer.chGeneral1[note.channel] == 0) {
note.playback = RawSamplePlayer.start(note.sampleData, note.playback.getSpeed_p8(), note.playback.getVol_p14(), note.playback.getPan_p14());
} else {
note.playback = RawSamplePlayer.start(note.sampleData, note.playback.getSpeed_p8(), 0, note.playback.getPan_p14());
this.midiPlayer.a559(note, note.instrument.noteTuning_idk[note.note] < 0);
}
if (note.instrument.noteTuning_idk[note.note] < 0) {
assert note.playback != null;
note.playback.f150();
}
totalLen = note._j / var4;
}
}
assert note.playback != null;
note.playback.processAndDiscard(totalLen);
}
private void a829(final int[] dest, int offset, final MidiPlayerNoteState_idk note, int lenToWrite, final int totalLen) {
if ((MidiPlayer.FLAG_GENERAL_6 & this.midiPlayer.chFlags[note.channel]) != 0 && note.notePlaying_idfk < 0) {
final int var7 = this.midiPlayer._u[note.channel] / SampledAudioChannelS16.SAMPLE_RATE;
while (true) {
final int len = (-note._j + 0xfffff + var7) / var7;
if (len > lenToWrite) {
note._j += var7 * lenToWrite;
break;
}
note.playback.processAndWrite(dest, offset, len);
note._j += len * var7 - 0x100000;
offset += len;
lenToWrite -= len;
int var9 = SampledAudioChannelS16.SAMPLE_RATE / 100;
final int var10 = 0x40000 / var7;
if (var10 < var9) {
var9 = var10;
}
final RawSamplePlayer playback = note.playback;
if (this.midiPlayer.chGeneral1[note.channel] == 0) {
note.playback = RawSamplePlayer.start(note.sampleData, playback.getSpeed_p8(), playback.getVol_p14(), playback.getPan_p14());
} else {
note.playback = RawSamplePlayer.start(note.sampleData, playback.getSpeed_p8(), 0, playback.getPan_p14());
this.midiPlayer.a559(note, note.instrument.noteTuning_idk[note.note] < 0);
note.playback.setVolRamped_p14(var9, playback.getVol_p14());
}
if (note.instrument.noteTuning_idk[note.note] < 0) {
assert note.playback != null;
note.playback.f150();
}
playback.setVolZeroRamped(var9);
playback.processAndWrite(dest, offset, totalLen - offset);
if (playback.isRampTimeNonzero()) {
this.sum.addFirst(playback);
}
}
}
note.playback.processAndWrite(dest, offset, lenToWrite);
}
}

View File

@ -1,35 +0,0 @@
package funorb.audio;
import funorb.data.NodeList;
public final class MidiPlayerNoteState_idk extends NodeList.Node {
/** seems to be -1 for active and 0 for inactive... ??? */
public int notePlaying_idfk;
public int _pitch_fac_2;
public int _v;
public int _F;
public int note;
public RawSampleS8 sampleData;
public KeyParams_idk keyParams_idk;
public RawSamplePlayer playback;
public MidiInstrument instrument;
public int _j;
public int _pitch_fac_1;
public int _C;
public int pan_idk;
public int channel;
public int pitch_idk;
public int _h;
public int noteOffNote_idk;
public int volume_idk;
public int lenRemaining_idk;
public int _B;
public int vibratoPhase_idk;
public void reset_idk() {
this.instrument = null;
this.playback = null;
this.sampleData = null;
this.keyParams_idk = null;
}
}

View File

@ -0,0 +1,34 @@
package funorb.audio;
import funorb.data.NodeList;
public final class MidiPlayingNote extends NodeList.Node {
public int relEnvTime;
public int portaMag_p12;
public int relEnvIdx;
public int volEnvTime;
public int note;
public RawSampleS8 sampleData;
public MidiKeyParams params;
public RawSamplePlayer playback;
public MidiInstrument instrument;
public int _j;
public int portaRange_p8;
public int vibratoTime;
public int pan_p7; // 0=left, 0.5=center, 1=right (128)
public int channel;
public int relNote_p8;
public int expEnvTime;
public int noteOffNote_idk;
public int amp_p15;
public int timeLeft;
public int volEnvIdx;
public int vibratoPhase_p9;
public void reset() {
this.instrument = null;
this.playback = null;
this.sampleData = null;
this.params = null;
}
}

View File

@ -0,0 +1,151 @@
package funorb.audio;
import funorb.data.NodeList;
import org.jetbrains.annotations.NotNull;
import java.util.Iterator;
import java.util.Objects;
public final class MidiPlayingNoteSet extends AudioSource {
public final NodeList<MidiPlayingNote> notes = new NodeList<>();
public final SoundManager sum = new SoundManager();
private final MidiPlayer midiPlayer;
public MidiPlayingNoteSet(final MidiPlayer midiPlayer) {
this.midiPlayer = midiPlayer;
}
@Override
public @NotNull Iterator<AudioSource> iterator() {
return this.notes.stream().<AudioSource>map(var1 -> var1.playback).filter(Objects::nonNull).iterator();
}
@Override
public int returns_0_1_or_2() {
return 0;
}
@Override
public void processAndDiscard(final int totalLen) {
this.sum.processAndDiscard(totalLen);
for (final MidiPlayingNote note : this.notes) {
if (this.midiPlayer.noteIgnored(note)) {
continue;
}
int len = totalLen;
do {
if (note.timeLeft >= len) {
this.processAndDiscardNote(note, len);
note.timeLeft -= len;
break;
}
this.processAndDiscardNote(note, note.timeLeft);
len -= note.timeLeft;
} while (!this.midiPlayer.processNote(0, null, note, len));
}
}
@Override
public void processAndWrite(final int[] data_s16p8, final int totalOffset, final int totalLen) {
this.sum.processAndWrite(data_s16p8, totalOffset, totalLen);
for (final MidiPlayingNote note : this.notes) {
if (this.midiPlayer.noteIgnored(note)) {
continue;
}
int offset = totalOffset;
int len = totalLen;
do {
if (note.timeLeft >= len) {
this.processAndWriteNote(data_s16p8, offset, note, len, offset + len);
note.timeLeft -= len;
break;
}
this.processAndWriteNote(data_s16p8, offset, note, note.timeLeft, offset + len);
len -= note.timeLeft;
offset += note.timeLeft;
} while (!this.midiPlayer.processNote(offset, data_s16p8, note, len));
}
}
private void processAndDiscardNote(final MidiPlayingNote note, int totalLen) {
if ((MidiPlayer.FLAG_GENERAL_6 & this.midiPlayer.chFlags[note.channel]) != 0 && note.relEnvTime < 0) {
final int var4 = this.midiPlayer.chGeneral2Exp[note.channel] / SampledAudioChannelS16.SAMPLE_RATE;
final int var5 = (0xfffff + var4 - note._j) / var4;
note._j = 0xfffff & note._j + totalLen * var4;
if (var5 <= totalLen) {
if (this.midiPlayer.chStartOffset_p6[note.channel] == 0) {
note.playback = RawSamplePlayer.of(note.sampleData, note.playback.getAbsSpeed_p8(), note.playback.getVol_p14(), note.playback.getPan_p14());
} else {
note.playback = RawSamplePlayer.of(note.sampleData, note.playback.getAbsSpeed_p8(), 0, note.playback.getPan_p14());
this.midiPlayer.initPlayhead(note, note.instrument.baseNote_p8[note.note] < 0);
}
if (note.instrument.baseNote_p8[note.note] < 0) {
assert note.playback != null;
note.playback.setLooped();
}
totalLen = note._j / var4;
}
}
assert note.playback != null;
note.playback.processAndDiscard(totalLen);
}
private void processAndWriteNote(final int[] dest_s16p8, int offset, final MidiPlayingNote note, int lenToWrite, final int totalLen) {
if ((MidiPlayer.FLAG_GENERAL_6 & this.midiPlayer.chFlags[note.channel]) != 0 && note.relEnvTime < 0) {
final int var7 = this.midiPlayer.chGeneral2Exp[note.channel] / SampledAudioChannelS16.SAMPLE_RATE;
while (true) {
final int len = (-note._j + 0xfffff + var7) / var7;
if (len > lenToWrite) {
note._j += var7 * lenToWrite;
break;
}
note.playback.processAndWrite(dest_s16p8, offset, len);
note._j += len * var7 - 0x100000;
offset += len;
lenToWrite -= len;
int timeLeft = SampledAudioChannelS16.SAMPLE_RATE / 100;
final int var10 = 0x40000 / var7;
if (var10 < timeLeft) {
timeLeft = var10;
}
final RawSamplePlayer playback = note.playback;
if (this.midiPlayer.chStartOffset_p6[note.channel] == 0) {
note.playback = RawSamplePlayer.of(note.sampleData, playback.getAbsSpeed_p8(), playback.getVol_p14(), playback.getPan_p14());
} else {
note.playback = RawSamplePlayer.of(note.sampleData, playback.getAbsSpeed_p8(), 0, playback.getPan_p14());
this.midiPlayer.initPlayhead(note, note.instrument.baseNote_p8[note.note] < 0);
note.playback.setVolRamped_p14(timeLeft, playback.getVol_p14());
}
if (note.instrument.baseNote_p8[note.note] < 0) {
assert note.playback != null;
note.playback.setLooped();
}
playback.setVolZeroRamped(timeLeft);
playback.processAndWrite(dest_s16p8, offset, totalLen - offset);
if (playback.isRampTimeNonzero()) {
this.sum.addFirst(playback);
}
}
}
note.playback.processAndWrite(dest_s16p8, offset, lenToWrite);
}
}

View File

@ -42,7 +42,7 @@ public final class MidiReader {
};
private final Buffer midi = new Buffer(null);
public int ticksPerQuarterNote;
public int ticksPerQn;
public int[] trackNextTick;
private int[] trackPlaybackPos;
private int[] trackStartPos;
@ -206,7 +206,7 @@ public final class MidiReader {
this.midi.data = midiData;
this.midi.pos = 10; // skip to count of MTrk chunks in MThd
final int numTracks = this.midi.readUShort();
this.ticksPerQuarterNote = this.midi.readUShort();
this.ticksPerQn = this.midi.readUShort();
this.tempo = 500000; // 120 bpm
this.trackStartPos = new int[numTracks];

View File

@ -7,15 +7,18 @@ import java.util.Collections;
import java.util.Iterator;
public final class MusicManager extends AudioSource {
private static final int P20_ONE = 0x100000;
private static final int P20_ONE_HALF = 0x80000;
public final MidiPlayer midiPlayer1;
public final MidiPlayer midiPlayer2;
private int[] midiBuffer2;
private SongData song1;
private int _l;
private int crossfade = 0x100000;
private int crossfade_p20 = P20_ONE;
private SongData song2;
private int[] midiBuffer1;
private int volume = 256;
private int volume_p8 = 256;
private boolean _C;
public MusicManager() {
@ -29,84 +32,86 @@ public final class MusicManager extends AudioSource {
}
@Override
public void processAndWrite(final int[] dataS16P8, final int offset, final int len) {
if (this.volume <= 0) {
public void processAndWrite(final int[] data_s16p8, final int offset, final int len) {
if (this.volume_p8 <= 0) {
this.processAndDiscard(len);
} else {
if (this._C) {
if (this._l > 0 && !this.midiPlayer2.h154()) {
this._C = false;
this._l = -this._l;
this.song2 = null;
} else if (this._l < 0 && !this.midiPlayer1.h154()) {
this.song1 = null;
this._C = false;
this._l = -this._l;
}
}
final int midiAmp2 = (this.crossfade >> 12) * this.volume / 256;
final int midiAmp1 = this.volume - midiAmp2;
if (this._l != 0) {
this.crossfade += this._l * len;
if (this.crossfade >= 0x100000) {
this.crossfade = 0x100000;
if (!this._C) {
this._l = 0;
if (this.song1 != null) {
this.midiPlayer1.e150();
}
this.song1 = null;
}
} else if (this.crossfade <= 0) {
this.crossfade = 0;
if (!this._C) {
this._l = 0;
if (this.song2 != null) {
this.midiPlayer2.e150();
}
this.song2 = null;
}
}
}
final int lenSamples = len << 1;
if (this.song2 != null || this.song1 != null) {
if (midiAmp2 == 256) {
this.midiPlayer2.processAndWrite(dataS16P8, offset, len);
} else if (midiAmp1 == 256) {
this.midiPlayer1.processAndWrite(dataS16P8, offset, len);
} else {
if (this.midiBuffer2 != null && this.midiBuffer2.length >= lenSamples) {
Arrays.fill(this.midiBuffer2, 0, lenSamples, 0);
Arrays.fill(this.midiBuffer1, 0, lenSamples, 0);
} else {
this.midiBuffer1 = new int[lenSamples];
this.midiBuffer2 = new int[lenSamples];
}
this.midiPlayer2.processAndWrite(this.midiBuffer2, 0, len);
this.midiPlayer1.processAndWrite(this.midiBuffer1, 0, len);
final int offsetSamples = offset << 1;
for (int i = 0; i < lenSamples; ++i) {
dataS16P8[offsetSamples + i] += this.midiBuffer1[i] * midiAmp1 + this.midiBuffer2[i] * midiAmp2 >> 8;
}
}
}
return;
}
if (this._C) {
if (this._l > 0 && !this.midiPlayer2.h154()) {
this._C = false;
this._l = -this._l;
this.song2 = null;
} else if (this._l < 0 && !this.midiPlayer1.h154()) {
this.song1 = null;
this._C = false;
this._l = -this._l;
}
}
final int midiAmp2_p8 = (this.crossfade_p20 >> 12) * this.volume_p8 / 256;
final int midiAmp1_p8 = this.volume_p8 - midiAmp2_p8;
if (this._l != 0) {
this.crossfade_p20 += this._l * len;
if (this.crossfade_p20 >= P20_ONE) {
this.crossfade_p20 = P20_ONE;
if (!this._C) {
this._l = 0;
if (this.song1 != null) {
this.midiPlayer1.e150();
}
this.song1 = null;
}
} else if (this.crossfade_p20 <= 0) {
this.crossfade_p20 = 0;
if (!this._C) {
this._l = 0;
if (this.song2 != null) {
this.midiPlayer2.e150();
}
this.song2 = null;
}
}
}
final int lenSamples = len << 1;
if (this.song2 != null || this.song1 != null) {
if (midiAmp2_p8 == 256) {
this.midiPlayer2.processAndWrite(data_s16p8, offset, len);
} else if (midiAmp1_p8 == 256) {
this.midiPlayer1.processAndWrite(data_s16p8, offset, len);
} else {
if (this.midiBuffer2 != null && this.midiBuffer2.length >= lenSamples) {
Arrays.fill(this.midiBuffer2, 0, lenSamples, 0);
Arrays.fill(this.midiBuffer1, 0, lenSamples, 0);
} else {
this.midiBuffer1 = new int[lenSamples];
this.midiBuffer2 = new int[lenSamples];
}
this.midiPlayer2.processAndWrite(this.midiBuffer2, 0, len);
this.midiPlayer1.processAndWrite(this.midiBuffer1, 0, len);
final int offsetSamples = offset << 1;
for (int i = 0; i < lenSamples; ++i) {
data_s16p8[offsetSamples + i] += this.midiBuffer1[i] * midiAmp1_p8 + this.midiBuffer2[i] * midiAmp2_p8 >> 8;
}
}
}
}
@Override
public synchronized void processAndDiscard(final int len) {
if (this.crossfade > 0 && this.song2 != null) {
if (this.crossfade_p20 > 0 && this.song2 != null) {
this.midiPlayer2.processAndDiscard(len);
}
if (this.crossfade < 0x100000 && this.song1 != null) {
if (this.crossfade_p20 < P20_ONE && this.song1 != null) {
this.midiPlayer1.processAndDiscard(len);
}
@ -123,9 +128,9 @@ public final class MusicManager extends AudioSource {
}
if (this._l != 0) {
this.crossfade += this._l * len;
if (this.crossfade >= 0x100000) {
this.crossfade = 0x100000;
this.crossfade_p20 += this._l * len;
if (this.crossfade_p20 >= P20_ONE) {
this.crossfade_p20 = P20_ONE;
if (!this._C) {
this._l = 0;
if (this.song1 != null) {
@ -134,8 +139,8 @@ public final class MusicManager extends AudioSource {
this.song1 = null;
}
} else if (this.crossfade <= 0) {
this.crossfade = 0;
} else if (this.crossfade_p20 <= 0) {
this.crossfade_p20 = 0;
if (!this._C) {
this._l = 0;
if (this.song2 != null) {
@ -150,12 +155,12 @@ public final class MusicManager extends AudioSource {
}
private void a633(final MidiPlayer midiPlayer) {
midiPlayer.a679();
midiPlayer.c430();
midiPlayer.initChGlobalAmp();
midiPlayer.initMicrosecondsPerSecond();
}
public synchronized void setVolume(final int volume) {
this.volume = volume;
public synchronized void setVolume_p8(final int volume_p8) {
this.volume_p8 = volume_p8;
}
@Override
@ -177,7 +182,7 @@ public final class MusicManager extends AudioSource {
this.song2 = track;
if (track != null) {
this.midiPlayer2.a077(track, false);
this.midiPlayer2.changeSong(track, false);
this.a633(this.midiPlayer2);
}
} else {
@ -187,7 +192,7 @@ public final class MusicManager extends AudioSource {
this.song1 = track;
if (track != null) {
this.midiPlayer1.a077(track, false);
this.midiPlayer1.changeSong(track, false);
this.a633(this.midiPlayer1);
}
}
@ -207,7 +212,7 @@ public final class MusicManager extends AudioSource {
} else if (this.song1 == null) {
var7 = false;
} else {
var7 = this.crossfade < 0x80000;
var7 = this.crossfade_p20 < P20_ONE_HALF;
}
if (var7) {
@ -217,7 +222,7 @@ public final class MusicManager extends AudioSource {
this.song2 = track;
if (track != null) {
this.midiPlayer2.a077(track, !var4);
this.midiPlayer2.changeSong(track, !var4);
this.a633(this.midiPlayer2);
}
@ -229,7 +234,7 @@ public final class MusicManager extends AudioSource {
this.song1 = track;
if (track != null) {
this.midiPlayer1.a077(track, !var4);
this.midiPlayer1.changeSong(track, !var4);
this.a633(this.midiPlayer1);
}

View File

@ -6,12 +6,12 @@ import java.util.Collections;
import java.util.Iterator;
public final class RawSamplePlayer extends AudioSource {
private static final double INV_0x2000 = 1.220703125E-4D;
private static final double P14_TO_DOUBLE = 1. / 0x4000;
private final boolean isLooped_idk;
private final int loopStart_idfk;
private final int loopEnd_idfk;
private int loopDirection_idk;
private final boolean isPingPongLoop;
private final int loopStart;
private final int loopEnd;
private int loopCount; // zero = no loop, negative = infinite loops, positive = loop count
private int vol_p14;
private int pan_p14; // left=0.0/0, center=0.5/0x2000, right=1.0/0x4000. negative values are "surround"
@ -29,9 +29,9 @@ public final class RawSamplePlayer extends AudioSource {
private RawSamplePlayer(final RawSampleS8 raw, final int speed_p8, final int vol_p14, final int pan_p14) {
this.rawSample = raw;
this.loopStart_idfk = raw.loopStart_idfk;
this.loopEnd_idfk = raw.loopEnd_idfk;
this.isLooped_idk = raw.isLooped_idk;
this.loopStart = raw.loopStart;
this.loopEnd = raw.loopEnd;
this.isPingPongLoop = raw.isPingPongLoop;
this.speed_p8 = speed_p8;
this.vol_p14 = vol_p14;
this.pan_p14 = pan_p14;
@ -39,7 +39,22 @@ public final class RawSamplePlayer extends AudioSource {
this.resetAmp();
}
public synchronized int getSpeed_p8() {
public static RawSamplePlayer of(final RawSampleS8 sample, final int speed_p8, final int vol_p14, final int pan_p14) {
if (sample.data_s8 == null || sample.data_s8.length == 0) {
return null;
}
return new RawSamplePlayer(sample, speed_p8, vol_p14, pan_p14);
}
public static RawSamplePlayer of(final RawSampleS8 sample, final int vol_p8) {
if (sample.data_s8 == null || sample.data_s8.length == 0) {
return null;
}
int speed_p8 = (int) ((long) sample.sampleRate * 256L * (long) 100 / (100L * SampledAudioChannelS16.SAMPLE_RATE));
return new RawSamplePlayer(sample, speed_p8, vol_p8 << 6, 0x2000);
}
public synchronized int getAbsSpeed_p8() {
return this.speed_p8 < 0 ? -this.speed_p8 : this.speed_p8;
}
@ -64,8 +79,8 @@ public final class RawSamplePlayer extends AudioSource {
this.speed_p8 = -this.speed_p8;
}
public synchronized void f150() {
this.loopDirection_idk = -1;
public synchronized void setLooped() {
this.loopCount = -1;
}
public synchronized boolean isRampTimeNonzero() {
@ -98,35 +113,6 @@ public final class RawSamplePlayer extends AudioSource {
this.resetAmp();
}
private void resetAmp() {
this.amp_p14 = this.vol_p14;
this.ampL_p14 = calcAmpL(this.vol_p14, this.pan_p14);
this.ampR_p14 = calcAmpR(this.vol_p14, this.pan_p14);
}
private static int calcAmpL(final int vol_p14, final int pan_p14) {
return pan_p14 < 0 ? vol_p14 : (int) ((double) vol_p14 * Math.sqrt((double) (0x4000 - pan_p14) * INV_0x2000)+ 0.5D);
}
private static int calcAmpR(final int vol_p14, final int pan_p14) {
return pan_p14 < 0 ? -vol_p14 : (int) ((double) vol_p14 * Math.sqrt((double) pan_p14 * INV_0x2000) + 0.5D);
}
public static RawSamplePlayer start(final RawSampleS8 sampleData, final int pitchX, final int volX, final int panX) {
return (sampleData.data_s8 == null || sampleData.data_s8.length == 0)
? null
: new RawSamplePlayer(sampleData, pitchX, volX, panX);
}
public static RawSamplePlayer a638(final RawSampleS8 sample, final int vol_p8) {
if (sample.data_s8 == null || sample.data_s8.length == 0) {
return null;
} else {
int speed_p8 = (int) ((long) sample.sampleRate * 256L * (long) 100 / (100L * SampledAudioChannelS16.SAMPLE_RATE));
return new RawSamplePlayer(sample, speed_p8, vol_p8 << 6, 0x2000);
}
}
public synchronized void setVolRamped_p14(final int time, final int vol_p14) {
this.setVolAndPanRamped_p14(time, vol_p14, this.getPan_p14());
}
@ -197,6 +183,20 @@ public final class RawSamplePlayer extends AudioSource {
this.rampR_p14 = (ampR - this.ampR_p14) / time;
}
private void resetAmp() {
this.amp_p14 = this.vol_p14;
this.ampL_p14 = calcAmpL(this.vol_p14, this.pan_p14);
this.ampR_p14 = calcAmpR(this.vol_p14, this.pan_p14);
}
private static int calcAmpL(final int vol_p14, final int pan_p14) {
return pan_p14 < 0 ? vol_p14 : (int) (vol_p14 * Math.sqrt(2. * (1. - pan_p14 * P14_TO_DOUBLE)) + 0.5D);
}
private static int calcAmpR(final int vol_p14, final int pan_p14) {
return pan_p14 < 0 ? -vol_p14 : (int) (vol_p14 * Math.sqrt(2. * pan_p14 * P14_TO_DOUBLE) + 0.5D);
}
@Override
public synchronized void processAndDiscard(int len) {
if (this.rampTime > 0) {
@ -221,17 +221,17 @@ public final class RawSamplePlayer extends AudioSource {
}
final RawSampleS8 sampleData = this.rawSample;
final int loopStart_idfk = this.loopStart_idfk << 8;
final int loopEnd_idfk = this.loopEnd_idfk << 8;
final int loopStart_idfk = this.loopStart << 8;
final int loopEnd_idfk = this.loopEnd << 8;
final int sampleLength = sampleData.data_s8.length << 8;
final int loopLength_idk = loopEnd_idfk - loopStart_idfk;
if (loopLength_idk <= 0) {
this.loopDirection_idk = 0;
this.loopCount = 0;
}
if (this.playhead_p8 < 0) {
if (this.speed_p8 <= 0) {
this.j797();
this.clearRamp();
this.unlink();
return;
}
@ -241,7 +241,7 @@ public final class RawSamplePlayer extends AudioSource {
if (this.playhead_p8 >= sampleLength) {
if (this.speed_p8 >= 0) {
this.j797();
this.clearRamp();
this.unlink();
return;
}
@ -250,8 +250,8 @@ public final class RawSamplePlayer extends AudioSource {
}
this.playhead_p8 += this.speed_p8 * len;
if (this.loopDirection_idk < 0) {
if (this.isLooped_idk) {
if (this.loopCount < 0) {
if (this.isPingPongLoop) {
if (this.speed_p8 < 0) {
if (this.playhead_p8 >= loopStart_idfk) {
return;
@ -286,7 +286,7 @@ public final class RawSamplePlayer extends AudioSource {
this.playhead_p8 = loopStart_idfk + (this.playhead_p8 - loopStart_idfk) % loopLength_idk;
}
} else {
if (this.loopDirection_idk > 0) {
if (this.loopCount > 0) {
label121:
{
if (this.speed_p8 < 0) {
@ -296,7 +296,7 @@ public final class RawSamplePlayer extends AudioSource {
this.playhead_p8 = loopStart_idfk + loopStart_idfk - 1 - this.playhead_p8;
this.speed_p8 = -this.speed_p8;
if (--this.loopDirection_idk == 0) {
if (--this.loopCount == 0) {
break label121;
}
}
@ -308,7 +308,7 @@ public final class RawSamplePlayer extends AudioSource {
this.playhead_p8 = loopEnd_idfk + loopEnd_idfk - 1 - this.playhead_p8;
this.speed_p8 = -this.speed_p8;
if (--this.loopDirection_idk == 0) {
if (--this.loopCount == 0) {
break;
}
@ -318,44 +318,44 @@ public final class RawSamplePlayer extends AudioSource {
this.playhead_p8 = loopStart_idfk + loopStart_idfk - 1 - this.playhead_p8;
this.speed_p8 = -this.speed_p8;
} while (--this.loopDirection_idk != 0);
} while (--this.loopCount != 0);
}
}
if (this.speed_p8 < 0) {
if (this.playhead_p8 < 0) {
this.playhead_p8 = -1;
this.j797();
this.clearRamp();
this.unlink();
}
} else if (this.playhead_p8 >= sampleLength) {
this.playhead_p8 = sampleLength;
this.j797();
this.clearRamp();
this.unlink();
}
}
}
@Override
public synchronized void processAndWrite(final int[] dataS16P8, final int offset, final int len) {
public synchronized void processAndWrite(final int[] data_s16p8, final int offset, final int len) {
if (this.vol_p14 == 0 && this.rampTime == 0) {
this.processAndDiscard(len);
return;
}
final int loopStart = this.loopStart_idfk << 8;
final int loopEnd = this.loopEnd_idfk << 8;
final int loopStart = this.loopStart << 8;
final int loopEnd = this.loopEnd << 8;
final int sampleLength = this.rawSample.data_s8.length << 8;
final int loopLength = loopEnd - loopStart;
if (loopLength <= 0) {
this.loopDirection_idk = 0;
this.loopCount = 0;
}
int pos = offset;
final int end = len + offset;
if (this.playhead_p8 < 0) {
if (this.speed_p8 <= 0) {
this.j797();
this.clearRamp();
this.unlink();
return;
}
@ -365,7 +365,7 @@ public final class RawSamplePlayer extends AudioSource {
if (this.playhead_p8 >= sampleLength) {
if (this.speed_p8 >= 0) {
this.j797();
this.clearRamp();
this.unlink();
return;
}
@ -373,10 +373,10 @@ public final class RawSamplePlayer extends AudioSource {
this.playhead_p8 = sampleLength - 1;
}
if (this.loopDirection_idk < 0) {
if (this.isLooped_idk) {
if (this.loopCount < 0) {
if (this.isPingPongLoop) {
if (this.speed_p8 < 0) {
pos = this.writeBackwards(dataS16P8, offset, loopStart, end, this.rawSample.data_s8[this.loopStart_idfk]);
pos = this.writeBackwards(data_s16p8, offset, loopStart, end, this.rawSample.data_s8[this.loopStart]);
if (this.playhead_p8 >= loopStart) {
return;
}
@ -386,14 +386,14 @@ public final class RawSamplePlayer extends AudioSource {
}
while (true) {
pos = this.writeForwards(dataS16P8, pos, loopEnd, end, this.rawSample.data_s8[this.loopEnd_idfk - 1]);
pos = this.writeForwards(data_s16p8, pos, loopEnd, end, this.rawSample.data_s8[this.loopEnd - 1]);
if (this.playhead_p8 < loopEnd) {
return;
}
this.playhead_p8 = loopEnd + loopEnd - 1 - this.playhead_p8;
this.speed_p8 = -this.speed_p8;
pos = this.writeBackwards(dataS16P8, pos, loopStart, end, this.rawSample.data_s8[this.loopStart_idfk]);
pos = this.writeBackwards(data_s16p8, pos, loopStart, end, this.rawSample.data_s8[this.loopStart]);
if (this.playhead_p8 >= loopStart) {
return;
}
@ -403,7 +403,7 @@ public final class RawSamplePlayer extends AudioSource {
}
} else if (this.speed_p8 < 0) {
while (true) {
pos = this.writeBackwards(dataS16P8, pos, loopStart, end, this.rawSample.data_s8[this.loopEnd_idfk - 1]);
pos = this.writeBackwards(data_s16p8, pos, loopStart, end, this.rawSample.data_s8[this.loopEnd - 1]);
if (this.playhead_p8 >= loopStart) {
return;
}
@ -412,7 +412,7 @@ public final class RawSamplePlayer extends AudioSource {
}
} else {
while (true) {
pos = this.writeForwards(dataS16P8, pos, loopEnd, end, this.rawSample.data_s8[this.loopStart_idfk]);
pos = this.writeForwards(data_s16p8, pos, loopEnd, end, this.rawSample.data_s8[this.loopStart]);
if (this.playhead_p8 < loopEnd) {
return;
}
@ -421,103 +421,104 @@ public final class RawSamplePlayer extends AudioSource {
}
}
} else {
if (this.loopDirection_idk > 0) {
if (this.isLooped_idk) {
if (this.loopCount > 0) {
if (this.isPingPongLoop) {
label131:
{
pos = offset;
if (this.speed_p8 < 0) {
pos = this.writeBackwards(dataS16P8, offset, loopStart, end, this.rawSample.data_s8[this.loopStart_idfk]);
pos = this.writeBackwards(data_s16p8, pos, loopStart, end, this.rawSample.data_s8[this.loopStart]);
if (this.playhead_p8 >= loopStart) {
return;
}
this.playhead_p8 = loopStart + loopStart - 1 - this.playhead_p8;
this.speed_p8 = -this.speed_p8;
if (--this.loopDirection_idk == 0) {
if (--this.loopCount == 0) {
break label131;
}
}
do {
pos = this.writeForwards(dataS16P8, pos, loopEnd, end, this.rawSample.data_s8[this.loopEnd_idfk - 1]);
pos = this.writeForwards(data_s16p8, pos, loopEnd, end, this.rawSample.data_s8[this.loopEnd - 1]);
if (this.playhead_p8 < loopEnd) {
return;
}
this.playhead_p8 = loopEnd + loopEnd - 1 - this.playhead_p8;
this.speed_p8 = -this.speed_p8;
if (--this.loopDirection_idk == 0) {
if (--this.loopCount == 0) {
break;
}
pos = this.writeBackwards(dataS16P8, pos, loopStart, end, this.rawSample.data_s8[this.loopStart_idfk]);
pos = this.writeBackwards(data_s16p8, pos, loopStart, end, this.rawSample.data_s8[this.loopStart]);
if (this.playhead_p8 >= loopStart) {
return;
}
this.playhead_p8 = loopStart + loopStart - 1 - this.playhead_p8;
this.speed_p8 = -this.speed_p8;
} while (--this.loopDirection_idk != 0);
} while (--this.loopCount != 0);
}
} else {
int var10;
if (this.speed_p8 < 0) {
while (true) {
pos = this.writeBackwards(dataS16P8, pos, loopStart, end, this.rawSample.data_s8[this.loopEnd_idfk - 1]);
pos = this.writeBackwards(data_s16p8, pos, loopStart, end, this.rawSample.data_s8[this.loopEnd - 1]);
if (this.playhead_p8 >= loopStart) {
return;
}
var10 = (loopEnd - 1 - this.playhead_p8) / loopLength;
if (var10 >= this.loopDirection_idk) {
this.playhead_p8 += loopLength * this.loopDirection_idk;
this.loopDirection_idk = 0;
if (var10 >= this.loopCount) {
this.playhead_p8 += loopLength * this.loopCount;
this.loopCount = 0;
break;
}
this.playhead_p8 += loopLength * var10;
this.loopDirection_idk -= var10;
this.loopCount -= var10;
}
} else {
while (true) {
pos = this.writeForwards(dataS16P8, pos, loopEnd, end, this.rawSample.data_s8[this.loopStart_idfk]);
pos = this.writeForwards(data_s16p8, pos, loopEnd, end, this.rawSample.data_s8[this.loopStart]);
if (this.playhead_p8 < loopEnd) {
return;
}
var10 = (this.playhead_p8 - loopStart) / loopLength;
if (var10 >= this.loopDirection_idk) {
this.playhead_p8 -= loopLength * this.loopDirection_idk;
this.loopDirection_idk = 0;
if (var10 >= this.loopCount) {
this.playhead_p8 -= loopLength * this.loopCount;
this.loopCount = 0;
break;
}
this.playhead_p8 -= loopLength * var10;
this.loopDirection_idk -= var10;
this.loopCount -= var10;
}
}
}
}
if (this.speed_p8 < 0) {
this.writeBackwards(dataS16P8, pos, 0, end, 0);
this.writeBackwards(data_s16p8, pos, 0, end, 0);
if (this.playhead_p8 < 0) {
this.playhead_p8 = -1;
this.j797();
this.clearRamp();
this.unlink();
}
} else {
this.writeForwards(dataS16P8, pos, sampleLength, end, 0);
this.writeForwards(data_s16p8, pos, sampleLength, end, 0);
if (this.playhead_p8 >= sampleLength) {
this.playhead_p8 = sampleLength;
this.j797();
this.clearRamp();
this.unlink();
}
}
}
}
private void j797() {
private void clearRamp() {
if (this.rampTime != 0) {
if (this.vol_p14 == Integer.MIN_VALUE) {
this.vol_p14 = 0;
@ -536,10 +537,10 @@ public final class RawSamplePlayer extends AudioSource {
public int someP8_idk() {
final int var1 = (this.amp_p14 * 3) >> 6;
int var2 = (var1 ^ (var1 >> 31)) + (var1 >>> 31);
if (this.loopDirection_idk == 0) {
if (this.loopCount == 0) {
var2 -= var2 * this.playhead_p8 / (this.rawSample.data_s8.length << 8);
} else if (this.loopDirection_idk >= 0) {
var2 -= var2 * this.loopStart_idfk / this.rawSample.data_s8.length;
} else if (this.loopCount >= 0) {
var2 -= var2 * this.loopStart / this.rawSample.data_s8.length;
}
return Math.min(var2, 255);
}

View File

@ -1,11 +1,11 @@
package funorb.audio;
public final class RawSampleS8 {
public final int loopEnd_idfk;
public final int loopStart_idfk;
public final int loopEnd;
public final int loopStart;
public final int sampleRate;
public final byte[] data_s8;
public final boolean isLooped_idk;
public final boolean isPingPongLoop;
public int someCounter_idk;
public RawSampleS8(final byte[] data, final int loopStart, final int loopEnd) {
@ -17,12 +17,12 @@ public final class RawSampleS8 {
final byte[] data,
final int loopStart,
final int loopEnd,
final boolean isLooped
final boolean isPingPongLoop
) {
this.sampleRate = sampleRate;
this.data_s8 = data;
this.loopStart_idfk = loopStart;
this.loopEnd_idfk = loopEnd;
this.isLooped_idk = isLooped;
this.loopStart = loopStart;
this.loopEnd = loopEnd;
this.isPingPongLoop = isPingPongLoop;
}
}

View File

@ -10,12 +10,12 @@ public final class SoundEffect {
}
@SuppressWarnings("SameParameterValue")
public static SoundEffect load1(final String item, final int volume) {
return new SoundEffect(SoundLoader.globalLoader.load1(item), volume);
public static SoundEffect loadSynth(final String item, final int volume) {
return new SoundEffect(SoundLoader.globalLoader.loadSynth(item), volume);
}
@SuppressWarnings("SameParameterValue")
public static SoundEffect load2(final String item, final int volume) {
return new SoundEffect(SoundLoader.globalLoader.load2(item), volume);
public static SoundEffect loadVorbis(final String item, final int volume) {
return new SoundEffect(SoundLoader.globalLoader.loadVorbis(item), volume);
}
}

View File

@ -7,26 +7,26 @@ import java.util.Map;
public final class SoundLoader {
public static SoundLoader globalLoader;
private final Map<Long, VorbisFormat> cache2 = new HashMap<>();
private final Map<Long, RawSampleS8> cache1 = new HashMap<>();
private final ResourceLoader loader1;
private final ResourceLoader loader2;
private final Map<Long, VorbisFormat> vorbisCache = new HashMap<>();
private final Map<Long, RawSampleS8> synthCache = new HashMap<>();
private final ResourceLoader synthLoader;
private final ResourceLoader vorbisLoader;
public SoundLoader(final ResourceLoader loader1, final ResourceLoader loader2) {
this.loader1 = loader1;
this.loader2 = loader2;
public SoundLoader(final ResourceLoader synthLoader, final ResourceLoader vorbisLoader) {
this.synthLoader = synthLoader;
this.vorbisLoader = vorbisLoader;
}
private RawSampleS8 load1(final int groupId, final int itemId) {
private RawSampleS8 loadSynth(final int groupId, final int itemId) {
final int cacheKey = (itemId ^ (((groupId << 4) & 0xfff3) | (groupId >>> 12))) | (groupId << 16);
final RawSampleS8 cachedRaw = this.cache1.get((long) cacheKey);
final RawSampleS8 cachedRaw = this.synthCache.get((long) cacheKey);
if (cachedRaw == null) {
final SynthFormat file = SynthFormat.load(this.loader1, groupId, itemId);
final SynthFormat file = SynthFormat.load(this.synthLoader, groupId, itemId);
if (file == null) {
return null;
} else {
final RawSampleS8 raw = file.toRawSample();
this.cache1.put((long) cacheKey, raw);
this.synthCache.put((long) cacheKey, raw);
return raw;
}
} else {
@ -34,64 +34,64 @@ public final class SoundLoader {
}
}
public RawSampleS8 loadSingleton2(final int id) {
if (this.loader2.groupCount() == 1) {
return this.load2(0, id);
} else if (this.loader2.itemCount(id) == 1) {
return this.load2(id, 0);
public RawSampleS8 loadSingletonVorbis(final int id) {
if (this.vorbisLoader.groupCount() == 1) {
return this.loadVorbis(0, id);
} else if (this.vorbisLoader.itemCount(id) == 1) {
return this.loadVorbis(id, 0);
} else {
throw new RuntimeException();
}
}
public RawSampleS8 loadSingleton1(final int id) {
if (this.loader1.groupCount() == 1) {
return this.load1(0, id);
} else if (this.loader1.itemCount(id) == 1) {
return this.load1(id, 0);
public RawSampleS8 loadSingletonSynth(final int id) {
if (this.synthLoader.groupCount() == 1) {
return this.loadSynth(0, id);
} else if (this.synthLoader.itemCount(id) == 1) {
return this.loadSynth(id, 0);
} else {
throw new RuntimeException();
}
}
private RawSampleS8 load2(final int groupId, final int itemId) {
private RawSampleS8 loadVorbis(final int groupId, final int itemId) {
final int var5 = (((groupId >>> 12) | (0xfff0 & (groupId << 4))) ^ itemId) | (groupId << 16);
final long cacheKey = 0x100000000L ^ (long) var5;
RawSampleS8 raw = this.cache1.get(cacheKey);
RawSampleS8 raw = this.synthCache.get(cacheKey);
if (raw == null) {
VorbisFormat file = this.cache2.get(cacheKey);
VorbisFormat file = this.vorbisCache.get(cacheKey);
if (file == null) {
file = VorbisFormat.load(this.loader2, groupId, itemId);
file = VorbisFormat.load(this.vorbisLoader, groupId, itemId);
if (file == null) {
return null;
}
this.cache2.put(cacheKey, file);
this.vorbisCache.put(cacheKey, file);
}
raw = file.toRawSample();
this.cache2.remove(cacheKey);
this.cache1.put(cacheKey, raw);
this.vorbisCache.remove(cacheKey);
this.synthCache.put(cacheKey, raw);
}
return raw;
}
@SuppressWarnings("SameParameterValue")
public RawSampleS8 load2(final String item) {
final int groupId = this.loader2.lookupGroup("");
public RawSampleS8 loadVorbis(final String item) {
final int groupId = this.vorbisLoader.lookupGroup("");
if (groupId < 0) {
return null;
} else {
final int itemId = this.loader2.lookupItem(groupId, item);
return itemId < 0 ? null : this.load2(groupId, itemId);
final int itemId = this.vorbisLoader.lookupItem(groupId, item);
return itemId < 0 ? null : this.loadVorbis(groupId, itemId);
}
}
public RawSampleS8 load1(final String item) {
final int groupId = this.loader1.lookupGroup("");
public RawSampleS8 loadSynth(final String item) {
final int groupId = this.synthLoader.lookupGroup("");
if (groupId >= 0) {
final int itemId = this.loader1.lookupItem(groupId, item);
return itemId < 0 ? null : this.load1(groupId, itemId);
final int itemId = this.synthLoader.lookupItem(groupId, item);
return itemId < 0 ? null : this.loadSynth(groupId, itemId);
} else {
return null;
}

View File

@ -30,9 +30,9 @@ public final class SoundManager extends AudioSource {
}
@Override
public synchronized void processAndWrite(final int[] dataS16P8, final int offset, final int len) {
public synchronized void processAndWrite(final int[] data_s16p8, final int offset, final int len) {
for (final AudioSource gen : this.inner) {
gen.processAndWriteIfEnabled(dataS16P8, offset, len);
gen.processAndWriteIfEnabled(data_s16p8, offset, len);
}
}
}

View File

@ -4265,8 +4265,8 @@ public final class ShatteredPlansClient extends JagexApplet {
final MusicManager musicTn = new MusicManager();
musicTn.midiPlayer2.initialize();
musicTn.midiPlayer1.initialize();
musicTn.midiPlayer2.setVolume(Sounds.MAX_VOLUME);
musicTn.midiPlayer1.setVolume(Sounds.MAX_VOLUME);
musicTn.midiPlayer2.setAmp_p8(Sounds.MAX_VOLUME);
musicTn.midiPlayer1.setAmp_p8(Sounds.MAX_VOLUME);
Sounds.musicChannel = createAudioChannel(0, SampledAudioChannelS16.SAMPLE_RATE);
Sounds.soundsChannel = createAudioChannel(1, 1102);
@ -4274,7 +4274,7 @@ public final class ShatteredPlansClient extends JagexApplet {
Sounds.soundsTn = new SoundManager();
Sounds.soundsChannel.setSource(Sounds.soundsTn);
Sounds.musicTn = musicTn;
Sounds.musicTn.setVolume(Sounds.musicVolume);
Sounds.musicTn.setVolume_p8(Sounds.musicVolume);
Sounds.musicChannel.setSource(Sounds.musicTn);
renderQuality = RenderQuality.high();

View File

@ -42,13 +42,13 @@ public final class Sounds {
public static void loadSoundEffects(final ResourceLoader loader1, final ResourceLoader loader2) {
SoundLoader.globalLoader = new SoundLoader(loader1, loader2);
SFX_SHIP_SELECTION = SoundEffect.load1("shatteredplans_ship_selection", 256);
SFX_SHIP_MOVE_ORDER = SoundEffect.load1("shatteredplans_ship_move_order", 256);
SFX_SHIP_ATTACK_ORDER = SoundEffect.load1("shatteredplans_ship_attack_order", 256);
SFX_FACTORY_NOISE = SoundEffect.load1("shatteredplans_factory_noise", 256);
SFX_EXPLOSION = SoundEffect.load2("shatteredplans_explosion", 120);
SFX_NEXT_OPEN = SoundEffect.load1("shatteredplans_next_open", 256);
SFX_NEXT_CLOSE = SoundEffect.load1("shatteredplans_next_close", 256);
SFX_SHIP_SELECTION = SoundEffect.loadSynth("shatteredplans_ship_selection", 256);
SFX_SHIP_MOVE_ORDER = SoundEffect.loadSynth("shatteredplans_ship_move_order", 256);
SFX_SHIP_ATTACK_ORDER = SoundEffect.loadSynth("shatteredplans_ship_attack_order", 256);
SFX_FACTORY_NOISE = SoundEffect.loadSynth("shatteredplans_factory_noise", 256);
SFX_EXPLOSION = SoundEffect.loadVorbis("shatteredplans_explosion", 120);
SFX_NEXT_OPEN = SoundEffect.loadSynth("shatteredplans_next_open", 256);
SFX_NEXT_CLOSE = SoundEffect.loadSynth("shatteredplans_next_close", 256);
}
public static void loadMusic(final ResourceLoader loader1, final ResourceLoader loader2) {
@ -59,9 +59,9 @@ public final class Sounds {
MUSIC_LOSE = SongData.load(loader1, "shattered_plans_lose");
ShatteredPlansClient.currentTrack = MUSIC_IN_GAME_2;
musicTn.midiPlayer2.a350(SoundLoader.globalLoader, loader2, MUSIC_INTRO);
musicTn.midiPlayer2.a350(SoundLoader.globalLoader, loader2, MUSIC_IN_GAME_1);
musicTn.midiPlayer2.a350(SoundLoader.globalLoader, loader2, MUSIC_IN_GAME_2);
musicTn.midiPlayer2.loadNoteSamplesForSong(SoundLoader.globalLoader, loader2, MUSIC_INTRO);
musicTn.midiPlayer2.loadNoteSamplesForSong(SoundLoader.globalLoader, loader2, MUSIC_IN_GAME_1);
musicTn.midiPlayer2.loadNoteSamplesForSong(SoundLoader.globalLoader, loader2, MUSIC_IN_GAME_2);
musicTn.midiPlayer2.f150();
SoundLoader.globalLoader = null;
@ -76,7 +76,7 @@ public final class Sounds {
}
private static PlayingSound play(final RawSampleS8 var1, final int volume) {
final RawSamplePlayer var01 = RawSamplePlayer.a638(var1, volume);
final RawSamplePlayer var01 = RawSamplePlayer.of(var1, volume);
assert var01 != null;
final PlayingSound sound = new PlayingSound(var01);
playingSounds.add(sound);
@ -93,7 +93,7 @@ public final class Sounds {
public static void setMusicVolume(final int volume) {
musicVolume = volume;
if (musicTn != null) {
musicTn.setVolume(volume);
musicTn.setVolume_p8(volume);
}
}
}