@newgameplusinc/odyssey-audio-video-sdk-dev 1.0.21 → 1.0.23

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.
package/README.md CHANGED
@@ -84,27 +84,27 @@ sdk.setListenerFromLSD(listenerPos, cameraPos, lookAtPos);
84
84
  #### Noise-Cancellation Stack (What’s Included)
85
85
  1. **Adaptive denoiser worklet** – learns each participant’s noise floor in real time, then applies a multi-band downward expander plus dynamic low/high-pass shaping.
86
86
  2. **Optional voice enhancement** – autocorrelation-derived confidence (inspired by the tuner article) can raise the reduction floor when speech is present to keep vocals bright.
87
- 3. **Silence gate** – if energy stays below `silenceFloor` for a configurable hold window, the track ramps to true silence, removing hiss when nobody speaks.
87
+ 3. **Silence gate** – if energy stays below `silenceFloor` for a configurable hold window, the track ramps to true silence, then wakes instantly once voice energy returns.
88
88
  4. **Classic filters** – fixed high-pass/low-pass filters shave off rumble and hiss before signals reach the HRTF panner.
89
89
 
90
90
  These layers run entirely in Web Audio, so you can ship “AirPods-style” background rejection in any browser without native code.
91
91
  ```ts
92
92
  const sdk = new OdysseySpatialComms(serverUrl, {
93
93
  denoiser: {
94
- threshold: 0.0085,
95
- maxReduction: 0.94,
96
- hissCut: 0.7,
97
- holdMs: 180,
98
- voiceBoost: 0.7,
99
- voiceSensitivity: 0.3,
94
+ threshold: 0.0088,
95
+ maxReduction: 0.92,
96
+ hissCut: 0.58,
97
+ holdMs: 210,
98
+ voiceBoost: 0.65,
99
+ voiceSensitivity: 0.33,
100
100
  voiceEnhancement: true,
101
- silenceFloor: 0.001,
102
- silenceHoldMs: 220,
103
- silenceReleaseMs: 160,
101
+ silenceFloor: 0.00085,
102
+ silenceHoldMs: 320,
103
+ silenceReleaseMs: 140,
104
104
  },
105
105
  });
106
106
  ```
107
- Voice enhancement (autocorrelation-based speech detection) is **off by default** to keep the gate extra quiet; enable it when you want brighter close-talk voicing. Tweak these knobs if you need even more “AirPods Pro” style isolation.
107
+ Voice enhancement (autocorrelation-based speech detection) is **off by default** to keep the gate extra quiet; enable it when you want brighter close-talk voicing. Tweak `silenceFloor` / `silenceHoldMs` if you need either more aggressive hiss removal or softer gating.
108
108
 
109
109
  #### How Spatial Audio Is Built
110
110
  1. **Telemetry ingestion** – each LSD packet is passed through `setListenerFromLSD(listenerPos, cameraPos, lookAtPos)` so the Web Audio listener matches the player’s real head/camera pose.
@@ -510,8 +510,8 @@ class SpatialAudioManager extends EventManager_1.EventManager {
510
510
  return;
511
511
  }
512
512
  const clarityScore = this.calculateClarityScore(distance, vectorToSource);
513
- const targetGain = 0.55 + clarityScore * 0.6; // 0.55 → 1.15
514
- const targetLowpass = 3200 + clarityScore * 4200; // 3.2kHz → ~7.4kHz
513
+ const targetGain = 0.48 + clarityScore * 0.72; // 0.48 → 1.20
514
+ const targetLowpass = 3600 + clarityScore * 4600; // 3.6kHz → ~8.2kHz
515
515
  nodes.proximityGain.gain.setTargetAtTime(targetGain, this.audioContext.currentTime, 0.08);
516
516
  nodes.dynamicLowpass.frequency.setTargetAtTime(targetLowpass, this.audioContext.currentTime, 0.12);
517
517
  if (Math.random() < 0.005) {
@@ -530,8 +530,8 @@ class SpatialAudioManager extends EventManager_1.EventManager {
530
530
  return this.clamp(0.2 + proximityWeight * 0.6 + focusWeight * 0.2, 0, 1);
531
531
  }
532
532
  calculateProximityWeight(distance) {
533
- const closeRange = 1.2;
534
- const fadeRange = 12;
533
+ const closeRange = 0.85;
534
+ const fadeRange = 18;
535
535
  if (distance <= closeRange) {
536
536
  return 1;
537
537
  }
@@ -603,11 +603,11 @@ class SpatialAudioManager extends EventManager_1.EventManager {
603
603
  this.voiceBoost = this._sanitize(cfg.voiceBoost, 0, 1, 0.6);
604
604
  this.voiceSensitivity = this._sanitize(cfg.voiceSensitivity, 0.05, 0.9, 0.35);
605
605
  this.voiceEnhancement = cfg.voiceEnhancement === true;
606
- this.silenceFloor = this._sanitize(cfg.silenceFloor, 0.0002, 0.02, 0.0012);
606
+ this.silenceFloor = this._sanitize(cfg.silenceFloor, 0.0002, 0.02, 0.00085);
607
607
  this.silenceHoldSamples = Math.max(
608
608
  8,
609
609
  Math.round(
610
- sampleRate * this._sanitize(cfg.silenceHoldMs, 40, 1200, 260) / 1000
610
+ sampleRate * this._sanitize(cfg.silenceHoldMs, 40, 1200, 320) / 1000
611
611
  )
612
612
  );
613
613
  this.silenceReleaseSamples = Math.max(
@@ -748,10 +748,11 @@ class SpatialAudioManager extends EventManager_1.EventManager {
748
748
  state.quietSamples = 0;
749
749
  }
750
750
 
751
- if (state.envelope < this.silenceFloor && speechPresence < 0.2) {
751
+ const belowFloor = state.envelope < this.silenceFloor;
752
+ if (belowFloor && speechPresence < 0.25) {
752
753
  state.silenceSamples++;
753
754
  } else {
754
- state.silenceSamples = Math.max(0, state.silenceSamples - 2);
755
+ state.silenceSamples = Math.max(0, state.silenceSamples - 3);
755
756
  }
756
757
 
757
758
  if (!state.isSilenced && state.silenceSamples > this.silenceHoldSamples) {
@@ -760,19 +761,22 @@ class SpatialAudioManager extends EventManager_1.EventManager {
760
761
  }
761
762
 
762
763
  if (state.isSilenced) {
763
- if (
764
- state.envelope > this.silenceFloor * 1.8 ||
765
- speechPresence > 0.35
766
- ) {
764
+ const wakeFromEnergy = state.envelope > this.silenceFloor * 1.35;
765
+ const wakeFromVoice = speechPresence > 0.25;
766
+ if (wakeFromEnergy || wakeFromVoice) {
767
+ state.isSilenced = false;
768
+ state.silenceSamples = 0;
769
+ state.silenceReleaseCounter = 0;
770
+ } else {
767
771
  state.silenceReleaseCounter++;
768
772
  if (state.silenceReleaseCounter > this.silenceReleaseSamples) {
769
773
  state.isSilenced = false;
770
774
  state.silenceSamples = 0;
771
775
  state.silenceReleaseCounter = 0;
772
776
  }
773
- } else {
774
- state.silenceReleaseCounter = 0;
775
777
  }
778
+ } else {
779
+ state.silenceReleaseCounter = 0;
776
780
  }
777
781
 
778
782
  const ratio = state.noise / Math.max(state.envelope, 1e-6);
@@ -805,7 +809,7 @@ class SpatialAudioManager extends EventManager_1.EventManager {
805
809
  processed = state.lpState + highComponent * hissGain;
806
810
 
807
811
  const muteTarget = state.isSilenced ? 0 : 1;
808
- state.muteGain += (muteTarget - state.muteGain) * 0.35;
812
+ state.muteGain += (muteTarget - state.muteGain) * 0.25;
809
813
  processed *= state.muteGain;
810
814
 
811
815
  outChannel[i] = processed;
@@ -845,20 +849,20 @@ registerProcessor('odyssey-denoise', OdysseyDenoiseProcessor);
845
849
  };
846
850
  const denoiserDefaults = {
847
851
  enabled: true,
848
- threshold: 0.009,
849
- noiseFloor: 0.0025,
850
- release: 0.24,
851
- attack: 0.25,
852
- holdMs: 150,
852
+ threshold: 0.0088,
853
+ noiseFloor: 0.0024,
854
+ release: 0.26,
855
+ attack: 0.3,
856
+ holdMs: 210,
853
857
  maxReduction: 0.92,
854
- hissCut: 0.62,
855
- expansionRatio: 2.35,
856
- learnRate: 0.06,
857
- voiceBoost: 0.6,
858
- voiceSensitivity: 0.35,
858
+ hissCut: 0.58,
859
+ expansionRatio: 2.25,
860
+ learnRate: 0.055,
861
+ voiceBoost: 0.65,
862
+ voiceSensitivity: 0.33,
859
863
  voiceEnhancement: false,
860
- silenceFloor: 0.0012,
861
- silenceHoldMs: 260,
864
+ silenceFloor: 0.00085,
865
+ silenceHoldMs: 320,
862
866
  silenceReleaseMs: 140,
863
867
  };
864
868
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@newgameplusinc/odyssey-audio-video-sdk-dev",
3
- "version": "1.0.21",
3
+ "version": "1.0.23",
4
4
  "description": "Odyssey Spatial Audio & Video SDK using MediaSoup for real-time communication",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",