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.
@@ -1662,6 +1662,12 @@ var AudioApi = class {
1662
1662
  }
1663
1663
  return this.music.play(track, { loop });
1664
1664
  }
1665
+ play_track(trackNum, loop = true) {
1666
+ if (!this.music) {
1667
+ return Promise.resolve();
1668
+ }
1669
+ return this.music.playTrack(trackNum);
1670
+ }
1665
1671
  pause_music() {
1666
1672
  this.music?.pause();
1667
1673
  }
@@ -4739,60 +4745,138 @@ var clamp01 = (value) => clamp(value, 0, 1);
4739
4745
 
4740
4746
  // src/audio/music.ts
4741
4747
  var MusicSystem = class {
4748
+ // Timer handle
4742
4749
  constructor(options) {
4743
4750
  this.createElement = options.createElement;
4744
4751
  this.resolveSource = options.resolveSource ?? (async (path) => path);
4745
4752
  this.volume = options.volume ?? 1;
4753
+ this.crossfadeDuration = options.crossfadeDuration ?? 1;
4754
+ }
4755
+ async playTrack(trackNum) {
4756
+ const trackName = `music/track${trackNum.toString().padStart(2, "0")}.ogg`;
4757
+ return this.play(trackName);
4746
4758
  }
4747
4759
  async play(track, { loop = true, restart = false } = {}) {
4748
- if (this.track === track && this.element) {
4749
- this.element.loop = loop;
4750
- this.element.volume = this.volume;
4760
+ if (this.track === track && this.currentElement) {
4761
+ this.currentElement.loop = loop;
4762
+ this.cancelFade();
4763
+ if (this.fadingElement) {
4764
+ this.fadingElement.pause();
4765
+ this.fadingElement = void 0;
4766
+ }
4767
+ this.currentElement.volume = this.volume;
4751
4768
  if (restart) {
4752
- this.element.currentTime = 0;
4769
+ this.currentElement.currentTime = 0;
4753
4770
  }
4754
- if (this.element.paused || restart) {
4755
- await this.element.play();
4771
+ if (this.currentElement.paused || restart) {
4772
+ await this.currentElement.play();
4756
4773
  }
4757
4774
  return;
4758
4775
  }
4759
4776
  const src = await this.resolveSource(track);
4777
+ this.cancelFade();
4778
+ if (this.fadingElement) {
4779
+ this.fadingElement.pause();
4780
+ this.fadingElement = void 0;
4781
+ }
4782
+ if (this.currentElement) {
4783
+ this.fadingElement = this.currentElement;
4784
+ this.currentElement = void 0;
4785
+ }
4760
4786
  const element = this.createElement();
4761
4787
  element.src = src;
4762
4788
  element.loop = loop;
4763
- element.volume = this.volume;
4789
+ element.volume = 0;
4764
4790
  element.currentTime = 0;
4765
4791
  element.load();
4766
- await element.play();
4767
- this.element = element;
4792
+ try {
4793
+ await element.play();
4794
+ } catch (e) {
4795
+ console.warn(`MusicSystem: Failed to play ${track}`, e);
4796
+ if (this.fadingElement) {
4797
+ }
4798
+ }
4799
+ this.currentElement = element;
4768
4800
  this.track = track;
4801
+ this.startCrossfade();
4769
4802
  }
4770
4803
  pause() {
4771
- if (!this.element || this.element.paused) return;
4772
- this.element.pause();
4804
+ this.cancelFade();
4805
+ if (this.currentElement && !this.currentElement.paused) {
4806
+ this.currentElement.pause();
4807
+ }
4808
+ if (this.fadingElement) {
4809
+ this.fadingElement.pause();
4810
+ this.fadingElement = void 0;
4811
+ }
4773
4812
  }
4774
4813
  async resume() {
4775
- if (!this.element || !this.element.paused) return;
4776
- await this.element.play();
4814
+ if (!this.currentElement || !this.currentElement.paused) return;
4815
+ await this.currentElement.play();
4816
+ this.currentElement.volume = this.volume;
4777
4817
  }
4778
4818
  stop() {
4779
- if (!this.element) return;
4780
- this.element.pause();
4781
- this.element.currentTime = 0;
4782
- this.element = void 0;
4819
+ this.cancelFade();
4820
+ if (this.currentElement) {
4821
+ this.currentElement.pause();
4822
+ this.currentElement.currentTime = 0;
4823
+ this.currentElement = void 0;
4824
+ }
4825
+ if (this.fadingElement) {
4826
+ this.fadingElement.pause();
4827
+ this.fadingElement = void 0;
4828
+ }
4783
4829
  this.track = void 0;
4784
4830
  }
4785
4831
  setVolume(volume) {
4786
4832
  this.volume = volume;
4787
- if (this.element) {
4788
- this.element.volume = volume;
4833
+ if (this.currentElement && !this.fadeInterval) {
4834
+ this.currentElement.volume = volume;
4789
4835
  }
4790
4836
  }
4791
4837
  getState() {
4792
- const playing = Boolean(this.element && !this.element.paused && !this.element.ended);
4793
- const paused = Boolean(this.element?.paused);
4838
+ const playing = Boolean(this.currentElement && !this.currentElement.paused && !this.currentElement.ended);
4839
+ const paused = Boolean(this.currentElement?.paused);
4794
4840
  return { track: this.track, paused, playing, volume: this.volume };
4795
4841
  }
4842
+ startCrossfade() {
4843
+ const stepTime = 50;
4844
+ const steps = this.crossfadeDuration * 1e3 / stepTime;
4845
+ const volStep = this.volume / steps;
4846
+ let currentVol = 0;
4847
+ let fadingVol = this.fadingElement ? this.fadingElement.volume : 0;
4848
+ const tick = () => {
4849
+ let active = false;
4850
+ if (this.currentElement) {
4851
+ currentVol = Math.min(this.volume, currentVol + volStep);
4852
+ this.currentElement.volume = currentVol;
4853
+ if (currentVol < this.volume) active = true;
4854
+ }
4855
+ if (this.fadingElement) {
4856
+ fadingVol = Math.max(0, fadingVol - volStep);
4857
+ this.fadingElement.volume = fadingVol;
4858
+ if (fadingVol > 0) {
4859
+ active = true;
4860
+ } else {
4861
+ this.fadingElement.pause();
4862
+ this.fadingElement = void 0;
4863
+ }
4864
+ }
4865
+ if (!active) {
4866
+ this.cancelFade();
4867
+ }
4868
+ };
4869
+ tick();
4870
+ if (this.currentElement && this.currentElement.volume < this.volume || this.fadingElement) {
4871
+ this.fadeInterval = setInterval(tick, stepTime);
4872
+ }
4873
+ }
4874
+ cancelFade() {
4875
+ if (this.fadeInterval) {
4876
+ clearInterval(this.fadeInterval);
4877
+ this.fadeInterval = void 0;
4878
+ }
4879
+ }
4796
4880
  };
4797
4881
 
4798
4882
  // src/render/context.ts