Skip to content

Commit

Permalink
feat: midi fading
Browse files Browse the repository at this point in the history
  • Loading branch information
ultraviolet-jordan committed Jul 27, 2024
1 parent 9287838 commit 92e74f1
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 28 deletions.
6 changes: 3 additions & 3 deletions src/js/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -500,7 +500,7 @@ export abstract class Client extends GameShell {
/* empty */
}
this.stream = null;
stopMidi();
stopMidi(false);
// this.midiThreadActive = false;
// @ts-expect-error Force unload. This happens when the browser reloads entirely.
this.out = null;
Expand Down Expand Up @@ -739,7 +739,7 @@ export abstract class Client extends GameShell {
return new Jagfile(data);
};

protected setMidi = async (name: string, crc: number, length: number): Promise<void> => {
protected setMidi = async (name: string, crc: number, length: number, fade: boolean): Promise<void> => {
let data: Int8Array | undefined = await this.db?.cacheload(name + '.mid');
if (data && crc !== 12345678 && Packet.crc32(data) !== crc) {
data = undefined;
Expand All @@ -762,7 +762,7 @@ export abstract class Client extends GameShell {
await this.db?.cachesave(name + '.mid', data);
const uncompressedLength: number = new Packet(Uint8Array.from(data)).g4;
const uncompressed: Int8Array = Bzip.read(uncompressedLength, data, length, 4);
playMidi(uncompressed, this.midiVolume);
playMidi(uncompressed, this.midiVolume, fade);
};

protected drawError = (): void => {
Expand Down
18 changes: 9 additions & 9 deletions src/js/game.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ class Game extends Client {
}

if (!Client.lowMemory) {
await this.setMidi('scape_main', 12345678, 40000);
await this.setMidi('scape_main', 12345678, 40000, false);
}

const title: Jagfile = await this.loadArchive('title', 'title screen', this.archiveChecksums[1], 10);
Expand Down Expand Up @@ -950,7 +950,7 @@ class Game extends Client {
for (let i: number = 0; i < 5; i++) {
this.designColors[i] = 0;
}
stopMidi(); // custom fix :-)
stopMidi(true); // custom fix :-)
Client.oplogic1 = 0;
Client.oplogic2 = 0;
Client.oplogic3 = 0;
Expand Down Expand Up @@ -1117,7 +1117,7 @@ class Game extends Client {
}

if (this.nextMusicDelay === 0 && this.midiActive && !Client.lowMemory && this.currentMidi) {
await this.setMidi(this.currentMidi, this.midiCrc, this.midiSize);
await this.setMidi(this.currentMidi, this.midiCrc, this.midiSize, false);
}
}

Expand Down Expand Up @@ -4825,11 +4825,11 @@ class Game extends Client {
this.levelCollisionMap[level]?.reset();
}

stopMidi();
stopMidi(false);
this.currentMidi = null;
this.nextMusicDelay = 0;
if (!Client.lowMemory) {
await this.setMidi('scape_main', 12345678, 40000);
await this.setMidi('scape_main', 12345678, 40000, false);
}
};

Expand Down Expand Up @@ -5190,7 +5190,7 @@ class Game extends Client {
const crc: number = this.in.g4;
const length: number = this.in.g4;
if (!(name === this.currentMidi) && this.midiActive && !Client.lowMemory) {
await this.setMidi(name, crc, length);
await this.setMidi(name, crc, length, true);
}
this.currentMidi = name;
this.midiCrc = crc;
Expand Down Expand Up @@ -5456,7 +5456,7 @@ class Game extends Client {
const length: number = this.in.g4;
const remaining: number = this.packetSize - 6;
const uncompressed: Int8Array = Bzip.read(length, Int8Array.from(this.in.data), remaining, this.in.pos);
playMidi(uncompressed, this.midiVolume);
playMidi(uncompressed, this.midiVolume, false);
this.nextMusicDelay = delay;
}
this.packetType = -1;
Expand Down Expand Up @@ -6194,9 +6194,9 @@ class Game extends Client {
}
if (this.midiActive !== lastMidiActive) {
if (this.midiActive && this.currentMidi) {
await this.setMidi(this.currentMidi, this.midiCrc, this.midiSize);
await this.setMidi(this.currentMidi, this.midiCrc, this.midiSize, false);
} else {
stopMidi();
stopMidi(false);
}
this.nextMusicDelay = 0;
}
Expand Down
8 changes: 4 additions & 4 deletions src/js/jagex2/util/AudioUtil.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ export function setWaveVolume(vol) {
waveGain.gain.value = vol / 256;
}

export function playMidi(data, vol) {
export function playMidi(data, vol, fade) {
if (window._tinyMidiPlay) {
window._tinyMidiPlay(data, vol / 256);
window._tinyMidiPlay(data, vol / 256, fade);
}
}

Expand All @@ -35,8 +35,8 @@ export function setMidiVolume(vol) {
}
}

export function stopMidi() {
export function stopMidi(fade) {
if (window._tinyMidiStop) {
window._tinyMidiStop();
window._tinyMidiStop(fade);
}
}
53 changes: 41 additions & 12 deletions src/js/vendor/midi.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import TinyMidiPCM from './tinymidipcm/index.js';
const sampleRate = 44100;
const flushTime = 250;
const renderInterval = 30;
const fadeseconds = 2;

// let renderEndSeconds = 0;
// let currentMidiBuffer = null;
Expand Down Expand Up @@ -125,7 +126,15 @@ import TinyMidiPCM from './tinymidipcm/index.js';

let flushInterval;

window._tinyMidiStop = async () => {
function fadeGain(tovolume, callback) {
const currentTime = window.audioContext.currentTime;
gainNode.gain.cancelScheduledValues(currentTime);
gainNode.gain.setValueAtTime(gainNode.gain.value, currentTime);
gainNode.gain.linearRampToValueAtTime(tovolume, currentTime + fadeseconds);
setTimeout(callback, fadeseconds * 1000);
}

function stop() {
if (flushInterval) {
clearInterval(flushInterval);
}
Expand All @@ -142,28 +151,48 @@ import TinyMidiPCM from './tinymidipcm/index.js';
bufferSources = [];
gainNode.gain.value = temp;
}
}

function start(vol, midiBuffer) {
// vol -1 = reuse last volume level
if (vol !== -1) {
window._tinyMidiVolume(vol);
}

// currentMidiBuffer = midiBuffer;
// startTime = window.audioContext.currentTime;
lastTime = window.audioContext.currentTime;
flushInterval = setInterval(flush, flushTime);
tinyMidiPCM.render(midiBuffer);
}

window._tinyMidiStop = async fade => {
if (fade) {
fadeGain(0, () => {
stop();
});
} else {
stop();
}
};

window._tinyMidiVolume = (vol = 1) => {
gainNode.gain.value = vol;
};

window._tinyMidiPlay = async (midiBuffer, vol = 1) => {
window._tinyMidiPlay = async (midiBuffer, vol, fade) => {
if (!midiBuffer) {
return;
}

await window._tinyMidiStop();
await window._tinyMidiStop(fade);

// vol -1 = reuse last volume level
if (vol != -1) {
window._tinyMidiVolume(vol);
if (fade) {
setTimeout(() => {
start(vol, midiBuffer);
}, fadeseconds * 1000);
} else {
start(vol, midiBuffer);
}

// currentMidiBuffer = midiBuffer;
// startTime = window.audioContext.currentTime;
lastTime = window.audioContext.currentTime;
flushInterval = setInterval(flush, flushTime);
tinyMidiPCM.render(midiBuffer);
};
})();

0 comments on commit 92e74f1

Please sign in to comment.