Implement Phase 3 audio gaps: bespoke telemetry era engines (who/bioship/belter)

This commit is contained in:
Claude
2026-09-04 09:38:06 -07:00
parent 71252ff84f
commit 42d6007445
3 changed files with 336 additions and 57 deletions
-4
View File
@@ -298,12 +298,8 @@ document.addEventListener('DOMContentLoaded', () => {
}
// Phase 2 audio_gaps.md rows #25-#45
if (activeUniverseId === 'whoniverse' && presetId.indexOf('tardis-') === 0) {
whoniverseAudio.startConsoleTypeTelemetry(2800, 6500); // #25
}
if (presetId === 'bio-vorlon') expandedAudio.startVorlonSong(); // #26
if (presetId === 'bio-wraith') expandedAudio.startHullRegen(); // #28
if (presetId === 'sta-ceres' || presetId === 'sta-tycho') expandedAudio.startBelterTelemetry(); // #29
if (presetId === 'deep-event-horizon' || presetId === 'deep-icarus-ii') expandedAudio.startHullStrainMoans(); // #30
if (presetId === 'deep-icarus-ii') expandedAudio.startIcarusBeacon(); // #31
if (presetId === 'deep-event-horizon' || presetId === 'deep-nightflyer') expandedAudio.startVoidWhispers(); // #32
+320 -37
View File
@@ -811,7 +811,7 @@ class TelemetrySynth {
this.params = {
volume: 0.4,
density: 0.5, // How often background telemetry chirps occur (0 = off, 1 = busy bridge)
era: 'tng', // 'tng', 'voyager', 'tos', 'ds9', 'nx'
era: 'tng', // 'tng', 'voyager', 'tos', 'ds9', 'nx', 'who', 'bioship', 'belter'
reverbMix: 0.25
};
@@ -877,6 +877,15 @@ class TelemetrySynth {
if (this.isMuted || this.params.volume <= 0.01 || !this.am.ctx) return;
switch (this.params.era) {
case 'who':
this.synthesizeWhoMechanicalTelemetry_();
break;
case 'bioship':
this.synthesizeBioshipOrganicTelemetry_();
break;
case 'belter':
this.synthesizeBelterJuryRiggedTelemetry_();
break;
case 'tos':
Math.random() > 0.4 ? this.synthesizeTOSWarble() : this.synthesizeTOSRelayClick();
break;
@@ -1253,6 +1262,312 @@ class TelemetrySynth {
osc2.stop(now + 0.7);
}
/**
* Whoniverse Mechanical Telemetry Engine (audio_gaps.md #25, Phase 3 era)
* The TARDIS console never chirps like Starfleet gear: each tick emits a
* 0.25-0.6 s cluster of mechanical foley - dual-filtered toggle snaps,
* low 60-120 Hz spring-lever clicks and damped rotary selector pings
* (no electronic beeps). All transients scheduled on absolute ctx time so
* the single scheduler timeout can never orphan nodes.
*/
synthesizeWhoMechanicalTelemetry_() {
const ctx = this.am.ctx;
if (!ctx || !this.gainNode) return;
const now = ctx.currentTime;
const strikeCount = 2 + Math.floor(Math.random() * 4); // 2-5 transients
let cursor = Math.random() * 0.12;
// Toggle snap: dual-filtered short noise pulse (20-45 ms body)
const toggleSnap = (t, peak) => {
const buf = this.am.createNoiseBuffer('white', 0.06);
const noise = ctx.createBufferSource();
noise.buffer = buf;
const bpLo = ctx.createBiquadFilter();
bpLo.type = 'bandpass';
bpLo.frequency.setValueAtTime(300 + Math.random() * 200, t);
bpLo.Q.setValueAtTime(6, t);
const bpHi = ctx.createBiquadFilter();
bpHi.type = 'bandpass';
bpHi.frequency.setValueAtTime(900 + Math.random() * 500, t);
bpHi.Q.setValueAtTime(4, t);
const env = ctx.createGain();
env.gain.setValueAtTime(0.001, t);
env.gain.linearRampToValueAtTime(peak, t + 0.004);
env.gain.exponentialRampToValueAtTime(0.001, t + 0.02 + Math.random() * 0.025);
noise.connect(bpLo);
bpLo.connect(env);
noise.connect(bpHi);
bpHi.connect(env);
env.connect(this.gainNode);
noise.start(t);
noise.stop(t + 0.06);
};
// Spring lever snap: dull square click collapsing in pitch (60-120 Hz)
const springLever = (t, peak) => {
const osc = ctx.createOscillator();
osc.type = 'square';
const f0 = 60 + Math.random() * 60;
osc.frequency.setValueAtTime(f0, t);
osc.frequency.exponentialRampToValueAtTime(f0 * 0.5, t + 0.03);
const env = ctx.createGain();
env.gain.setValueAtTime(peak, t);
env.gain.exponentialRampToValueAtTime(0.001, t + 0.03 + Math.random() * 0.02);
osc.connect(env);
env.connect(this.gainNode);
osc.start(t);
osc.stop(t + 0.055);
};
// Rotary selector clunk: short damped mechanical ping, never a clean beep
const rotaryClunk = (t, peak) => {
const osc = ctx.createOscillator();
osc.type = 'sine';
const f0 = 180 + Math.random() * 260;
osc.frequency.setValueAtTime(f0, t);
osc.frequency.exponentialRampToValueAtTime(f0 * 0.7, t + 0.06);
const env = ctx.createGain();
env.gain.setValueAtTime(0.001, t);
env.gain.linearRampToValueAtTime(peak, t + 0.003);
env.gain.exponentialRampToValueAtTime(0.001, t + 0.06 + Math.random() * 0.08);
osc.connect(env);
env.connect(this.gainNode);
osc.start(t);
osc.stop(t + 0.16);
};
for (let i = 0; i < strikeCount; i++) {
const r = Math.random();
if (r < 0.5) toggleSnap(cursor, 0.08 + Math.random() * 0.08);
else if (r < 0.8) springLever(cursor, 0.07 + Math.random() * 0.06);
else rotaryClunk(cursor, 0.09 + Math.random() * 0.07);
cursor += 0.04 + Math.random() * 0.14;
}
}
/**
* Bioship Organic Telemetry Engine (audio_gaps.md #47, Phase 3 era)
* Living-ship telemetry is wet and pulse-driven, never electronic: vascular
* surges (30-90 Hz asymmetric sine thumps, sometimes lub-dub double beats),
* chitinous joint snaps, bioplasmic fluid pops and membrane flutters.
* One 0.5-1.1 s phrase of 2-4 events on absolute ctx time.
*/
synthesizeBioshipOrganicTelemetry_() {
const ctx = this.am.ctx;
if (!ctx || !this.gainNode) return;
const now = ctx.currentTime;
const eventCount = 2 + Math.floor(Math.random() * 3); // 2-4 events
let cursor = Math.random() * 0.2;
const fireEvent = (t) => {
const r = Math.random();
if (r < 0.35) {
// Vascular surge: asymmetric sine thump with pitch drop + lub-dub echo
const f0 = 30 + Math.random() * 60;
const dur = 0.2 + Math.random() * 0.15;
const surge = (st, peak, freq) => {
const osc = ctx.createOscillator();
osc.type = 'sine';
osc.frequency.setValueAtTime(freq, st);
osc.frequency.linearRampToValueAtTime(freq * 0.82, st + dur * 0.7);
const env = ctx.createGain();
env.gain.setValueAtTime(0.001, st);
env.gain.linearRampToValueAtTime(peak, st + 0.06 + Math.random() * 0.05);
env.gain.exponentialRampToValueAtTime(0.001, st + dur);
osc.connect(env);
env.connect(this.gainNode);
osc.start(st);
osc.stop(st + dur + 0.05);
};
surge(t, 0.14 + Math.random() * 0.06, f0);
if (Math.random() < 0.5) {
surge(t + 0.22 + Math.random() * 0.06, 0.09, f0 * 0.9); // lub-dub
}
} else if (r < 0.6) {
// Chitin snap: very short high-Q bandpass noise tick
const buf = this.am.createNoiseBuffer('white', 0.03);
const noise = ctx.createBufferSource();
noise.buffer = buf;
const bp = ctx.createBiquadFilter();
bp.type = 'bandpass';
bp.frequency.setValueAtTime(1200 + Math.random() * 1400, t);
bp.Q.setValueAtTime(10 + Math.random() * 4, t);
const env = ctx.createGain();
env.gain.setValueAtTime(0.12 + Math.random() * 0.06, t);
env.gain.exponentialRampToValueAtTime(0.001, t + 0.008 + Math.random() * 0.01);
noise.connect(bp);
bp.connect(env);
env.connect(this.gainNode);
noise.start(t);
noise.stop(t + 0.03);
} else if (r < 0.85) {
// Bioplasmic fluid pop: bandpass wet impulse with resonant tail
const buf = this.am.createNoiseBuffer('pink', 0.08);
const noise = ctx.createBufferSource();
noise.buffer = buf;
const bp = ctx.createBiquadFilter();
bp.type = 'bandpass';
bp.frequency.setValueAtTime(500 + Math.random() * 900, t);
bp.frequency.exponentialRampToValueAtTime(380, t + 0.05);
bp.Q.setValueAtTime(3 + Math.random() * 2, t);
const env = ctx.createGain();
env.gain.setValueAtTime(0.001, t);
env.gain.linearRampToValueAtTime(0.14, t + 0.008);
env.gain.exponentialRampToValueAtTime(0.001, t + 0.05);
noise.connect(bp);
bp.connect(env);
env.connect(this.gainNode);
noise.start(t);
noise.stop(t + 0.09);
} else {
// Membrane flutter: pink noise AM-stepped between 300-700 Hz
const buf = this.am.createNoiseBuffer('pink', 0.2);
const noise = ctx.createBufferSource();
noise.buffer = buf;
const bp = ctx.createBiquadFilter();
bp.type = 'bandpass';
bp.frequency.setValueAtTime(300 + Math.random() * 400, t);
bp.Q.setValueAtTime(2, t);
const env = ctx.createGain();
const flutterRate = 18 + Math.random() * 12;
const flutterDur = 0.08 + Math.random() * 0.07;
env.gain.setValueAtTime(0.001, t);
let step = 0;
while (step < flutterDur) {
env.gain.linearRampToValueAtTime(0.09 + Math.random() * 0.05, t + step + (1 / flutterRate) * 0.6);
env.gain.linearRampToValueAtTime(0.001, t + step + (1 / flutterRate));
step += 1 / flutterRate;
}
env.gain.setValueAtTime(0.001, t + flutterDur + 0.02);
noise.connect(bp);
bp.connect(env);
env.connect(this.gainNode);
noise.start(t);
noise.stop(t + flutterDur + 0.05);
}
};
for (let i = 0; i < eventCount; i++) {
fireEvent(cursor);
cursor += 0.16 + Math.random() * 0.3;
}
}
/**
* Belter Jury-Rigged Telemetry Engine (audio_gaps.md #29, Phase 3 era)
* Rattling relays, worn copper contactors and erratic voltage on Ceres /
* Tycho / Rocinante hardware: jittered square pulses with randomized
* micro-dropouts, contact-bounce double clicks, harsh metallic ticks and
* unstable clock pings. One 3-6 event volley on absolute ctx time, with an
* occasional late sub-cluster to mimic an unsteady clock.
*/
synthesizeBelterJuryRiggedTelemetry_() {
const ctx = this.am.ctx;
if (!ctx || !this.gainNode) return;
const now = ctx.currentTime;
let cursor = 0.05 + Math.random() * 0.25;
const relayPulse = (t) => {
const osc = ctx.createOscillator();
osc.type = 'square';
const baseFreq = 60 + Math.random() * 60;
osc.frequency.setValueAtTime(baseFreq, t);
osc.frequency.linearRampToValueAtTime(baseFreq * 0.8, t + 0.06);
const lp = ctx.createBiquadFilter();
lp.type = 'lowpass';
lp.frequency.setValueAtTime(420, t);
const env = ctx.createGain();
// Erratic voltage: randomized micro-dropouts in the pulse body
env.gain.setValueAtTime(0.15, t);
env.gain.setValueAtTime(0.001, t + 0.012 + Math.random() * 0.015);
env.gain.setValueAtTime(0.12, t + 0.026 + Math.random() * 0.02);
env.gain.setValueAtTime(0.001, t + 0.05 + Math.random() * 0.025);
env.gain.setValueAtTime(0.09, t + 0.07);
env.gain.exponentialRampToValueAtTime(0.001, t + 0.1);
osc.connect(lp);
lp.connect(env);
env.connect(this.gainNode);
osc.start(t);
osc.stop(t + 0.11);
};
const contactBounce = (t) => {
const clicks = 2 + (Math.random() < 0.35 ? 1 : 0);
for (let i = 0; i < clicks; i++) {
const ct = t + i * (0.001 + Math.random() * 0.002);
const osc = ctx.createOscillator();
osc.type = 'square';
osc.frequency.setValueAtTime(500 + Math.random() * 500, ct);
osc.frequency.exponentialRampToValueAtTime(120, ct + 0.008);
const env = ctx.createGain();
env.gain.setValueAtTime(0.12, ct);
env.gain.exponentialRampToValueAtTime(0.001, ct + 0.012);
osc.connect(env);
env.connect(this.gainNode);
osc.start(ct);
osc.stop(ct + 0.015);
}
};
const metallicTick = (t) => {
const buf = this.am.createNoiseBuffer('white', 0.05);
const noise = ctx.createBufferSource();
noise.buffer = buf;
const bp = ctx.createBiquadFilter();
bp.type = 'bandpass';
bp.frequency.setValueAtTime(400 + Math.random() * 1400, t);
bp.Q.setValueAtTime(6, t);
const env = ctx.createGain();
env.gain.setValueAtTime(0.08, t);
env.gain.exponentialRampToValueAtTime(0.001, t + 0.02);
noise.connect(bp);
bp.connect(env);
env.connect(this.gainNode);
noise.start(t);
noise.stop(t + 0.025);
};
const clockPing = (t) => {
// Unstable clock: dulled square collapsing hard, like a dying oscillator
const osc = ctx.createOscillator();
osc.type = 'square';
osc.frequency.setValueAtTime(700 + Math.random() * 400, t);
osc.frequency.exponentialRampToValueAtTime(200, t + 0.025);
const env = ctx.createGain();
env.gain.setValueAtTime(0.05, t);
env.gain.exponentialRampToValueAtTime(0.001, t + 0.04);
osc.connect(env);
env.connect(this.gainNode);
osc.start(t);
osc.stop(t + 0.045);
};
const fireEvent = (t) => {
const r = Math.random();
if (r < 0.35) relayPulse(t);
else if (r < 0.6) contactBounce(t);
else if (r < 0.85) metallicTick(t);
else clockPing(t);
};
const eventCount = 3 + Math.floor(Math.random() * 4); // 3-6 events
for (let i = 0; i < eventCount; i++) {
fireEvent(cursor);
cursor += 0.06 + Math.random() * 0.16; // jittered clock drift
}
// Occasional second volley: the station clock skips then catches up
if (Math.random() < 0.35) {
const volleyBase = cursor + 0.1 + Math.random() * 0.4;
const volleyCount = 2 + Math.floor(Math.random() * 2);
for (let i = 0; i < volleyCount; i++) {
fireEvent(volleyBase + i * (0.04 + Math.random() * 0.1));
}
}
}
applyPreset(config) {
if (config.volume !== undefined) this.params.volume = config.volume;
if (config.density !== undefined) this.setDensity(config.density);
@@ -1557,7 +1872,6 @@ class WhoniverseAudioSynth {
this.gainNode = null;
this.activeCloister = false;
this.cloisterTimer = null;
this.typeTelemetryTimer = null;
}
init() {
@@ -2096,34 +2410,12 @@ class WhoniverseAudioSynth {
}
/**
* Ambient Loop: TARDIS Console "Type" Input Telemetry (#25)
* Recursive random-window clatter while any TARDIS console room is engaged.
*/
startConsoleTypeTelemetry(minIntervalMs = 2800, maxIntervalMs = 6500) {
this.stopConsoleTypeTelemetry();
const scheduleNext = () => {
const delay = minIntervalMs + Math.random() * (maxIntervalMs - minIntervalMs);
this.typeTelemetryTimer = setTimeout(() => {
this.synthesizeTypeClatter();
scheduleNext();
}, delay);
};
scheduleNext();
}
stopConsoleTypeTelemetry() {
if (this.typeTelemetryTimer) {
clearTimeout(this.typeTelemetryTimer);
this.typeTelemetryTimer = null;
}
}
/**
* Stops all automated Whoniverse ambient loops. Cloister bell is an
* interactive toggle and keeps its own explicit call sites.
* Stops all automated Whoniverse ambient loops. Phase 3 moved console
* "type" telemetry (audio_gaps.md #25) into TelemetrySynth era 'who'
* routing, which is stopped via telemetry.stop() / FULL STOP. Hook
* retained because js/app.js calls it at three ambience switch points.
*/
stopAmbientLoops() {
this.stopConsoleTypeTelemetry();
}
}
@@ -3995,15 +4287,6 @@ class ExpandedSciFiAudioSynth {
}
}
/**
* Ambient Loop: Intermittent jury-rigged telemetry on Belter stations
*/
startBelterTelemetry(minIntervalMs = 1800, maxIntervalMs = 4500) {
this._scheduleLoop('belterTelemetry', minIntervalMs, maxIntervalMs, () => {
this.synthesizeBelterTelemetryJitter();
});
}
/**
* True Hull Strain Moan (Deep Space, audio_gaps.md #30)
* Massive structural groan of stressed bulkheads flexing under gravitational
+16 -16
View File
@@ -211,7 +211,7 @@ const UniverseRegistry = {
hull: { volume: 0.5, baseFreq: 68, filterCutoff: 150, resonance: 2.8, noiseMix: 0.35, harmonicSpread: 1.04 },
warp: { volume: 0.65, bpm: 52, carrierFreq: 96, filterCutoff: 210, pulseShape: 'tos', resonance: 3.5, swirlMix: 0.2 },
lifeSupport: { volume: 0.45, noiseType: 'pink', highpassFreq: 220, lowpassFreq: 1800, airflowModSpeed: 0.08, airflowModDepth: 0.06 },
telemetry: { volume: 0.55, density: 0.6, era: 'tos' }
telemetry: { volume: 0.55, density: 0.6, era: 'who' }
},
'tardis-victorian': {
id: 'tardis-victorian',
@@ -223,7 +223,7 @@ const UniverseRegistry = {
hull: { volume: 0.65, baseFreq: 44, filterCutoff: 85, resonance: 1.8, noiseMix: 0.45, harmonicSpread: 1.015 },
warp: { volume: 0.3, bpm: 40, carrierFreq: 50, filterCutoff: 120, pulseShape: 'nx', resonance: 2.0, swirlMix: 0.15 },
lifeSupport: { volume: 0.55, noiseType: 'brown', highpassFreq: 110, lowpassFreq: 1200, airflowModSpeed: 0.07, airflowModDepth: 0.12 },
telemetry: { volume: 0.35, density: 0.4, era: 'nx' }
telemetry: { volume: 0.35, density: 0.4, era: 'who' }
},
'tardis-coral': {
id: 'tardis-coral',
@@ -235,7 +235,7 @@ const UniverseRegistry = {
hull: { volume: 0.75, baseFreq: 52, filterCutoff: 135, resonance: 3.2, noiseMix: 0.5, harmonicSpread: 1.03 },
warp: { volume: 0.9, bpm: 48, carrierFreq: 64, filterCutoff: 230, pulseShape: 'tng', resonance: 4.0, swirlMix: 0.45 },
lifeSupport: { volume: 0.6, noiseType: 'pink', highpassFreq: 160, lowpassFreq: 1700, airflowModSpeed: 0.18, airflowModDepth: 0.15 },
telemetry: { volume: 0.45, density: 0.5, era: 'tng' }
telemetry: { volume: 0.45, density: 0.5, era: 'who' }
},
'tardis-copper': {
id: 'tardis-copper',
@@ -247,7 +247,7 @@ const UniverseRegistry = {
hull: { volume: 0.6, baseFreq: 56, filterCutoff: 125, resonance: 2.5, noiseMix: 0.4, harmonicSpread: 1.02 },
warp: { volume: 0.7, bpm: 62, carrierFreq: 72, filterCutoff: 210, pulseShape: 'voyager', resonance: 3.6, swirlMix: 0.35 },
lifeSupport: { volume: 0.65, noiseType: 'white', highpassFreq: 220, lowpassFreq: 2200, airflowModSpeed: 0.15, airflowModDepth: 0.1 },
telemetry: { volume: 0.55, density: 0.7, era: 'voyager' }
telemetry: { volume: 0.55, density: 0.7, era: 'who' }
},
'tardis-cold-machine': {
id: 'tardis-cold-machine',
@@ -259,7 +259,7 @@ const UniverseRegistry = {
hull: { volume: 0.6, baseFreq: 50, filterCutoff: 110, resonance: 2.2, noiseMix: 0.38, harmonicSpread: 1.02 },
warp: { volume: 0.75, bpm: 56, carrierFreq: 68, filterCutoff: 190, pulseShape: 'tng', resonance: 3.2, swirlMix: 0.3 },
lifeSupport: { volume: 0.5, noiseType: 'pink', highpassFreq: 200, lowpassFreq: 1600, airflowModSpeed: 0.12, airflowModDepth: 0.08 },
telemetry: { volume: 0.4, density: 0.5, era: 'ds9' }
telemetry: { volume: 0.4, density: 0.5, era: 'who' }
},
'tardis-crystal': {
id: 'tardis-crystal',
@@ -271,7 +271,7 @@ const UniverseRegistry = {
hull: { volume: 0.7, baseFreq: 46, filterCutoff: 100, resonance: 3.5, noiseMix: 0.5, harmonicSpread: 1.04 },
warp: { volume: 0.8, bpm: 44, carrierFreq: 88, filterCutoff: 260, pulseShape: 'defiant', resonance: 4.4, swirlMix: 0.4 },
lifeSupport: { volume: 0.55, noiseType: 'pink', highpassFreq: 180, lowpassFreq: 1900, airflowModSpeed: 0.16, airflowModDepth: 0.14 },
telemetry: { volume: 0.5, density: 0.6, era: 'voyager' }
telemetry: { volume: 0.5, density: 0.6, era: 'who' }
},
'tardis-infinite-white': {
id: 'tardis-infinite-white',
@@ -283,7 +283,7 @@ const UniverseRegistry = {
hull: { volume: 0.65, baseFreq: 48, filterCutoff: 95, resonance: 2.0, noiseMix: 0.42, harmonicSpread: 1.01 },
warp: { volume: 0.6, bpm: 50, carrierFreq: 60, filterCutoff: 160, pulseShape: 'tng', resonance: 2.8, swirlMix: 0.3 },
lifeSupport: { volume: 0.7, noiseType: 'white', highpassFreq: 160, lowpassFreq: 2600, airflowModSpeed: 0.14, airflowModDepth: 0.12 },
telemetry: { volume: 0.45, density: 0.6, era: 'tng' }
telemetry: { volume: 0.45, density: 0.6, era: 'who' }
}
}
},
@@ -371,7 +371,7 @@ const UniverseRegistry = {
hull: { volume: 0.8, baseFreq: 64, filterCutoff: 145, resonance: 3.4, noiseMix: 0.55, harmonicSpread: 1.035 },
warp: { volume: 0.9, bpm: 58, carrierFreq: 84, filterCutoff: 250, pulseShape: 'defiant', resonance: 4.2, swirlMix: 0.4 },
lifeSupport: { volume: 0.6, noiseType: 'white', highpassFreq: 200, lowpassFreq: 2100, airflowModSpeed: 0.18, airflowModDepth: 0.14 },
telemetry: { volume: 0.5, density: 0.65, era: 'voyager' }
telemetry: { volume: 0.5, density: 0.75, era: 'belter' }
},
'ind-eagle': {
id: 'ind-eagle',
@@ -429,7 +429,7 @@ const UniverseRegistry = {
hull: { volume: 0.75, baseFreq: 45, filterCutoff: 110, resonance: 3.2, noiseMix: 0.5, harmonicSpread: 1.03 },
warp: { volume: 0.85, bpm: 38, carrierFreq: 58, filterCutoff: 180, pulseShape: 'tng', resonance: 4.2, swirlMix: 0.45 },
lifeSupport: { volume: 0.65, noiseType: 'pink', highpassFreq: 150, lowpassFreq: 1600, airflowModSpeed: 0.08, airflowModDepth: 0.2 },
telemetry: { volume: 0.4, density: 0.4, era: 'tng' }
telemetry: { volume: 0.4, density: 0.4, era: 'bioship' }
},
'bio-talyn': {
id: 'bio-talyn',
@@ -439,7 +439,7 @@ const UniverseRegistry = {
hull: { volume: 0.8, baseFreq: 58, filterCutoff: 140, resonance: 3.6, noiseMix: 0.52, harmonicSpread: 1.04 },
warp: { volume: 0.9, bpm: 64, carrierFreq: 76, filterCutoff: 240, pulseShape: 'defiant', resonance: 4.6, swirlMix: 0.4 },
lifeSupport: { volume: 0.55, noiseType: 'pink', highpassFreq: 180, lowpassFreq: 1800, airflowModSpeed: 0.16, airflowModDepth: 0.16 },
telemetry: { volume: 0.45, density: 0.5, era: 'ds9' }
telemetry: { volume: 0.45, density: 0.5, era: 'bioship' }
},
'bio-lexx': {
id: 'bio-lexx',
@@ -449,7 +449,7 @@ const UniverseRegistry = {
hull: { volume: 0.85, baseFreq: 38, filterCutoff: 90, resonance: 2.8, noiseMix: 0.6, harmonicSpread: 1.02 },
warp: { volume: 0.7, bpm: 34, carrierFreq: 48, filterCutoff: 140, pulseShape: 'nx', resonance: 3.4, swirlMix: 0.35 },
lifeSupport: { volume: 0.6, noiseType: 'brown', highpassFreq: 120, lowpassFreq: 1300, airflowModSpeed: 0.06, airflowModDepth: 0.22 },
telemetry: { volume: 0.35, density: 0.3, era: 'nx' }
telemetry: { volume: 0.35, density: 0.4, era: 'bioship' }
},
'bio-vorlon': {
id: 'bio-vorlon',
@@ -459,7 +459,7 @@ const UniverseRegistry = {
hull: { volume: 0.65, baseFreq: 74, filterCutoff: 160, resonance: 3.8, noiseMix: 0.35, harmonicSpread: 1.05 },
warp: { volume: 0.8, bpm: 52, carrierFreq: 104, filterCutoff: 260, pulseShape: 'voyager', resonance: 4.5, swirlMix: 0.5 },
lifeSupport: { volume: 0.5, noiseType: 'pink', highpassFreq: 220, lowpassFreq: 2200, airflowModSpeed: 0.12, airflowModDepth: 0.1 },
telemetry: { volume: 0.5, density: 0.6, era: 'voyager' }
telemetry: { volume: 0.5, density: 0.6, era: 'bioship' }
},
'bio-wraith': {
id: 'bio-wraith',
@@ -469,7 +469,7 @@ const UniverseRegistry = {
hull: { volume: 0.85, baseFreq: 34, filterCutoff: 85, resonance: 2.5, noiseMix: 0.65, harmonicSpread: 1.015 },
warp: { volume: 0.6, bpm: 32, carrierFreq: 44, filterCutoff: 120, pulseShape: 'nx', resonance: 3.0, swirlMix: 0.25 },
lifeSupport: { volume: 0.65, noiseType: 'brown', highpassFreq: 90, lowpassFreq: 900, airflowModSpeed: 0.06, airflowModDepth: 0.22 },
telemetry: { volume: 0.3, density: 0.25, era: 'nx' }
telemetry: { volume: 0.3, density: 0.4, era: 'bioship' }
},
'bio-species-8472': {
id: 'bio-species-8472',
@@ -479,7 +479,7 @@ const UniverseRegistry = {
hull: { volume: 0.7, baseFreq: 68, filterCutoff: 150, resonance: 3.5, noiseMix: 0.45, harmonicSpread: 1.035 },
warp: { volume: 0.85, bpm: 56, carrierFreq: 88, filterCutoff: 230, pulseShape: 'defiant', resonance: 4.4, swirlMix: 0.45 },
lifeSupport: { volume: 0.5, noiseType: 'pink', highpassFreq: 200, lowpassFreq: 1900, airflowModSpeed: 0.14, airflowModDepth: 0.12 },
telemetry: { volume: 0.45, density: 0.55, era: 'voyager' }
telemetry: { volume: 0.45, density: 0.55, era: 'bioship' }
}
}
},
@@ -939,7 +939,7 @@ const UniverseRegistry = {
hull: { volume: 0.8, baseFreq: 48, filterCutoff: 110, resonance: 2.8, noiseMix: 0.55, harmonicSpread: 1.025 },
warp: { volume: 0.65, bpm: 42, carrierFreq: 66, filterCutoff: 180, pulseShape: 'defiant', resonance: 3.5, swirlMix: 0.3 },
lifeSupport: { volume: 0.65, noiseType: 'pink', highpassFreq: 160, lowpassFreq: 1700, airflowModSpeed: 0.12, airflowModDepth: 0.14 },
telemetry: { volume: 0.45, density: 0.5, era: 'voyager' }
telemetry: { volume: 0.45, density: 0.65, era: 'belter' }
},
'sta-ceres': {
id: 'sta-ceres',
@@ -949,7 +949,7 @@ const UniverseRegistry = {
hull: { volume: 0.85, baseFreq: 42, filterCutoff: 95, resonance: 2.6, noiseMix: 0.62, harmonicSpread: 1.02 },
warp: { volume: 0.45, bpm: 38, carrierFreq: 54, filterCutoff: 135, pulseShape: 'nx', resonance: 3.0, swirlMix: 0.2 },
lifeSupport: { volume: 0.7, noiseType: 'brown', highpassFreq: 120, lowpassFreq: 1400, airflowModSpeed: 0.08, airflowModDepth: 0.16 },
telemetry: { volume: 0.35, density: 0.35, era: 'nx' }
telemetry: { volume: 0.35, density: 0.6, era: 'belter' }
},
'sta-gateway': {
id: 'sta-gateway',