quake2ts 0.0.483 → 0.0.484

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1868,6 +1868,12 @@ var AudioApi = class {
1868
1868
  }
1869
1869
  return this.music.play(track, { loop });
1870
1870
  }
1871
+ play_track(trackNum, loop = true) {
1872
+ if (!this.music) {
1873
+ return Promise.resolve();
1874
+ }
1875
+ return this.music.playTrack(trackNum);
1876
+ }
1871
1877
  pause_music() {
1872
1878
  this.music?.pause();
1873
1879
  }
@@ -4945,60 +4951,138 @@ var clamp01 = (value) => clamp(value, 0, 1);
4945
4951
 
4946
4952
  // src/audio/music.ts
4947
4953
  var MusicSystem = class {
4954
+ // Timer handle
4948
4955
  constructor(options) {
4949
4956
  this.createElement = options.createElement;
4950
4957
  this.resolveSource = options.resolveSource ?? (async (path) => path);
4951
4958
  this.volume = options.volume ?? 1;
4959
+ this.crossfadeDuration = options.crossfadeDuration ?? 1;
4960
+ }
4961
+ async playTrack(trackNum) {
4962
+ const trackName = `music/track${trackNum.toString().padStart(2, "0")}.ogg`;
4963
+ return this.play(trackName);
4952
4964
  }
4953
4965
  async play(track, { loop = true, restart = false } = {}) {
4954
- if (this.track === track && this.element) {
4955
- this.element.loop = loop;
4956
- this.element.volume = this.volume;
4966
+ if (this.track === track && this.currentElement) {
4967
+ this.currentElement.loop = loop;
4968
+ this.cancelFade();
4969
+ if (this.fadingElement) {
4970
+ this.fadingElement.pause();
4971
+ this.fadingElement = void 0;
4972
+ }
4973
+ this.currentElement.volume = this.volume;
4957
4974
  if (restart) {
4958
- this.element.currentTime = 0;
4975
+ this.currentElement.currentTime = 0;
4959
4976
  }
4960
- if (this.element.paused || restart) {
4961
- await this.element.play();
4977
+ if (this.currentElement.paused || restart) {
4978
+ await this.currentElement.play();
4962
4979
  }
4963
4980
  return;
4964
4981
  }
4965
4982
  const src = await this.resolveSource(track);
4983
+ this.cancelFade();
4984
+ if (this.fadingElement) {
4985
+ this.fadingElement.pause();
4986
+ this.fadingElement = void 0;
4987
+ }
4988
+ if (this.currentElement) {
4989
+ this.fadingElement = this.currentElement;
4990
+ this.currentElement = void 0;
4991
+ }
4966
4992
  const element = this.createElement();
4967
4993
  element.src = src;
4968
4994
  element.loop = loop;
4969
- element.volume = this.volume;
4995
+ element.volume = 0;
4970
4996
  element.currentTime = 0;
4971
4997
  element.load();
4972
- await element.play();
4973
- this.element = element;
4998
+ try {
4999
+ await element.play();
5000
+ } catch (e) {
5001
+ console.warn(`MusicSystem: Failed to play ${track}`, e);
5002
+ if (this.fadingElement) {
5003
+ }
5004
+ }
5005
+ this.currentElement = element;
4974
5006
  this.track = track;
5007
+ this.startCrossfade();
4975
5008
  }
4976
5009
  pause() {
4977
- if (!this.element || this.element.paused) return;
4978
- this.element.pause();
5010
+ this.cancelFade();
5011
+ if (this.currentElement && !this.currentElement.paused) {
5012
+ this.currentElement.pause();
5013
+ }
5014
+ if (this.fadingElement) {
5015
+ this.fadingElement.pause();
5016
+ this.fadingElement = void 0;
5017
+ }
4979
5018
  }
4980
5019
  async resume() {
4981
- if (!this.element || !this.element.paused) return;
4982
- await this.element.play();
5020
+ if (!this.currentElement || !this.currentElement.paused) return;
5021
+ await this.currentElement.play();
5022
+ this.currentElement.volume = this.volume;
4983
5023
  }
4984
5024
  stop() {
4985
- if (!this.element) return;
4986
- this.element.pause();
4987
- this.element.currentTime = 0;
4988
- this.element = void 0;
5025
+ this.cancelFade();
5026
+ if (this.currentElement) {
5027
+ this.currentElement.pause();
5028
+ this.currentElement.currentTime = 0;
5029
+ this.currentElement = void 0;
5030
+ }
5031
+ if (this.fadingElement) {
5032
+ this.fadingElement.pause();
5033
+ this.fadingElement = void 0;
5034
+ }
4989
5035
  this.track = void 0;
4990
5036
  }
4991
5037
  setVolume(volume) {
4992
5038
  this.volume = volume;
4993
- if (this.element) {
4994
- this.element.volume = volume;
5039
+ if (this.currentElement && !this.fadeInterval) {
5040
+ this.currentElement.volume = volume;
4995
5041
  }
4996
5042
  }
4997
5043
  getState() {
4998
- const playing = Boolean(this.element && !this.element.paused && !this.element.ended);
4999
- const paused = Boolean(this.element?.paused);
5044
+ const playing = Boolean(this.currentElement && !this.currentElement.paused && !this.currentElement.ended);
5045
+ const paused = Boolean(this.currentElement?.paused);
5000
5046
  return { track: this.track, paused, playing, volume: this.volume };
5001
5047
  }
5048
+ startCrossfade() {
5049
+ const stepTime = 50;
5050
+ const steps = this.crossfadeDuration * 1e3 / stepTime;
5051
+ const volStep = this.volume / steps;
5052
+ let currentVol = 0;
5053
+ let fadingVol = this.fadingElement ? this.fadingElement.volume : 0;
5054
+ const tick = () => {
5055
+ let active = false;
5056
+ if (this.currentElement) {
5057
+ currentVol = Math.min(this.volume, currentVol + volStep);
5058
+ this.currentElement.volume = currentVol;
5059
+ if (currentVol < this.volume) active = true;
5060
+ }
5061
+ if (this.fadingElement) {
5062
+ fadingVol = Math.max(0, fadingVol - volStep);
5063
+ this.fadingElement.volume = fadingVol;
5064
+ if (fadingVol > 0) {
5065
+ active = true;
5066
+ } else {
5067
+ this.fadingElement.pause();
5068
+ this.fadingElement = void 0;
5069
+ }
5070
+ }
5071
+ if (!active) {
5072
+ this.cancelFade();
5073
+ }
5074
+ };
5075
+ tick();
5076
+ if (this.currentElement && this.currentElement.volume < this.volume || this.fadingElement) {
5077
+ this.fadeInterval = setInterval(tick, stepTime);
5078
+ }
5079
+ }
5080
+ cancelFade() {
5081
+ if (this.fadeInterval) {
5082
+ clearInterval(this.fadeInterval);
5083
+ this.fadeInterval = void 0;
5084
+ }
5085
+ }
5002
5086
  };
5003
5087
 
5004
5088
  // src/render/context.ts