ubbhjbj
This commit is contained in:
8192
frontend/src/pages/test/ews-component-master/spectrum.txt
Normal file
8192
frontend/src/pages/test/ews-component-master/spectrum.txt
Normal file
File diff suppressed because it is too large
Load Diff
@@ -15,24 +15,68 @@ export function RetroSoundTest() {
|
||||
return audioCtxRef.current;
|
||||
};
|
||||
|
||||
const playSound = (freq: number, type: OscillatorType, duration: number, vol: number, fade: boolean = false) => {
|
||||
// Helper: Create audio chain (oscillator → filter → gain → output)
|
||||
const createFilteredOscillator = (
|
||||
ctx: AudioContext,
|
||||
startTime: number,
|
||||
hz: number,
|
||||
volume: number,
|
||||
oscType: OscillatorType,
|
||||
filterFreq: number
|
||||
) => {
|
||||
const osc = ctx.createOscillator();
|
||||
const gain = ctx.createGain();
|
||||
const filter = ctx.createBiquadFilter();
|
||||
|
||||
osc.type = oscType;
|
||||
osc.frequency.setValueAtTime(hz, startTime);
|
||||
|
||||
filter.type = 'lowpass';
|
||||
filter.frequency.setValueAtTime(filterFreq, startTime);
|
||||
filter.Q.setValueAtTime(1, startTime);
|
||||
|
||||
gain.gain.setValueAtTime(volume, startTime);
|
||||
|
||||
osc.connect(filter).connect(gain).connect(ctx.destination);
|
||||
|
||||
return { osc, gain };
|
||||
};
|
||||
|
||||
const playSound = (
|
||||
freq: number,
|
||||
type: OscillatorType,
|
||||
duration: number,
|
||||
vol: number,
|
||||
fade: boolean = false,
|
||||
useFilter: boolean = false,
|
||||
filterFreq: number = 800
|
||||
) => {
|
||||
const ctx = getAudioCtx();
|
||||
const startTime = ctx.currentTime;
|
||||
|
||||
if (useFilter) {
|
||||
const { osc, gain } = createFilteredOscillator(ctx, startTime, freq, vol, type, filterFreq);
|
||||
if (fade) {
|
||||
gain.gain.exponentialRampToValueAtTime(0.0001, startTime + duration);
|
||||
}
|
||||
osc.start(startTime);
|
||||
osc.stop(startTime + duration);
|
||||
} else {
|
||||
const osc = ctx.createOscillator();
|
||||
const gain = ctx.createGain();
|
||||
|
||||
osc.type = type;
|
||||
osc.frequency.setValueAtTime(freq, ctx.currentTime);
|
||||
osc.frequency.setValueAtTime(freq, startTime);
|
||||
gain.gain.setValueAtTime(vol, startTime);
|
||||
|
||||
gain.gain.setValueAtTime(vol, ctx.currentTime);
|
||||
if (fade) {
|
||||
gain.gain.exponentialRampToValueAtTime(0.0001, ctx.currentTime + duration);
|
||||
gain.gain.exponentialRampToValueAtTime(0.0001, startTime + duration);
|
||||
}
|
||||
|
||||
osc.connect(gain);
|
||||
gain.connect(ctx.destination);
|
||||
|
||||
osc.start();
|
||||
osc.stop(ctx.currentTime + duration);
|
||||
osc.connect(gain).connect(ctx.destination);
|
||||
osc.start(startTime);
|
||||
osc.stop(startTime + duration);
|
||||
}
|
||||
};
|
||||
|
||||
// White noise (for 8-bit style noise)
|
||||
@@ -62,8 +106,8 @@ export function RetroSoundTest() {
|
||||
|
||||
// Play sound repeatedly with random delays
|
||||
const playRepeating = () => {
|
||||
// Play the sound
|
||||
playSound(1000, 'sawtooth', 0.08, 0.1);
|
||||
// Play the sound - triangle wave with low-pass filter for dull, machine-like tone
|
||||
playSound(1000, 'triangle', 0.08, 0.1, false, true, 800);
|
||||
playNoise(0.09, 0.02);
|
||||
|
||||
// Schedule next play with random delay (0-1000ms)
|
||||
@@ -96,72 +140,143 @@ export function RetroSoundTest() {
|
||||
};
|
||||
}, []);
|
||||
|
||||
// Crew Bailout Alarm - 90s style aggressive buzzer
|
||||
const crewBailout = (durationSeconds: number) => {
|
||||
// Beep composer - creates sequential beeps with automatic timing
|
||||
const createBeepSequence = () => {
|
||||
const ctx = getAudioCtx();
|
||||
const startTime = ctx.currentTime;
|
||||
const endTime = startTime + durationSeconds;
|
||||
let currentTime = ctx.currentTime;
|
||||
|
||||
// Timing constants
|
||||
const beepDuration = 0.06; // 60ms ON
|
||||
const pauseDuration = 0.06; // 60ms OFF
|
||||
const cycleDuration = beepDuration + pauseDuration; // 120ms total ~ 8 beeps/sec
|
||||
return {
|
||||
beep: (
|
||||
hz: number,
|
||||
duration: number,
|
||||
fade: boolean = false,
|
||||
autoOffset: boolean = true,
|
||||
oscType: OscillatorType = 'triangle',
|
||||
volume: number = 0.12,
|
||||
filterFreq: number = 800,
|
||||
addNoise: boolean = false
|
||||
) => {
|
||||
const { osc, gain } = createFilteredOscillator(ctx, currentTime, hz, volume, oscType, filterFreq);
|
||||
|
||||
const oscillators: OscillatorNode[] = [];
|
||||
const gainNodes: GainNode[] = [];
|
||||
|
||||
let currentTime = startTime;
|
||||
|
||||
// Generate beeps for the entire duration
|
||||
while (currentTime < endTime) {
|
||||
// Create two oscillators for beating effect
|
||||
const osc1 = ctx.createOscillator();
|
||||
const osc2 = ctx.createOscillator();
|
||||
const gain = ctx.createGain();
|
||||
|
||||
osc1.type = 'square';
|
||||
osc2.type = 'square';
|
||||
osc1.frequency.setValueAtTime(2850, currentTime);
|
||||
osc2.frequency.setValueAtTime(2855, currentTime); // 5Hz difference for beating
|
||||
|
||||
// Envelope
|
||||
const attackTime = 0.002; // 2ms attack
|
||||
const releaseTime = 0.01; // 10ms release
|
||||
|
||||
// Attack
|
||||
gain.gain.setValueAtTime(0, currentTime);
|
||||
gain.gain.linearRampToValueAtTime(0.15, currentTime + attackTime);
|
||||
|
||||
// Sustain
|
||||
gain.gain.setValueAtTime(0.15, currentTime + beepDuration - releaseTime);
|
||||
|
||||
// Release
|
||||
gain.gain.linearRampToValueAtTime(0, currentTime + beepDuration);
|
||||
|
||||
// Connect nodes
|
||||
osc1.connect(gain);
|
||||
osc2.connect(gain);
|
||||
gain.connect(ctx.destination);
|
||||
|
||||
// Start and stop
|
||||
osc1.start(currentTime);
|
||||
osc2.start(currentTime);
|
||||
osc1.stop(currentTime + beepDuration);
|
||||
osc2.stop(currentTime + beepDuration);
|
||||
|
||||
// Store for cleanup
|
||||
oscillators.push(osc1, osc2);
|
||||
gainNodes.push(gain);
|
||||
|
||||
// Move to next beep
|
||||
currentTime += cycleDuration;
|
||||
if (fade) {
|
||||
gain.gain.exponentialRampToValueAtTime(0.0001, currentTime + duration);
|
||||
}
|
||||
|
||||
// Cleanup after completion
|
||||
osc.start(currentTime);
|
||||
osc.stop(currentTime + duration + 0.05);
|
||||
|
||||
// Add vintage noise/hiss for realism
|
||||
if (addNoise) {
|
||||
const noiseBufferSize = ctx.sampleRate * duration;
|
||||
const noiseBuffer = ctx.createBuffer(1, noiseBufferSize, ctx.sampleRate);
|
||||
const noiseOutput = noiseBuffer.getChannelData(0);
|
||||
|
||||
for (let i = 0; i < noiseBufferSize; i++) {
|
||||
noiseOutput[i] = (Math.random() * 2 - 1) * 0.02; // Low-level noise
|
||||
}
|
||||
|
||||
const noiseSource = ctx.createBufferSource();
|
||||
noiseSource.buffer = noiseBuffer;
|
||||
|
||||
const noiseGain = ctx.createGain();
|
||||
noiseGain.gain.setValueAtTime(0.8, currentTime);
|
||||
|
||||
noiseSource.connect(noiseGain).connect(ctx.destination);
|
||||
noiseSource.start(currentTime);
|
||||
}
|
||||
|
||||
if (autoOffset) currentTime += duration;
|
||||
return currentTime;
|
||||
},
|
||||
|
||||
// Multi-tone beep (plays multiple frequencies simultaneously)
|
||||
multiBeep: (
|
||||
frequencies: number[],
|
||||
duration: number,
|
||||
fade: boolean = false,
|
||||
autoOffset: boolean = true,
|
||||
oscType: OscillatorType | OscillatorType[] = 'square',
|
||||
volume: number = 0.08,
|
||||
filterFreq: number = 1200,
|
||||
addNoise: boolean = true
|
||||
) => {
|
||||
// Play multiple oscillators at once
|
||||
frequencies.forEach((hz, index) => {
|
||||
const vol = volume * (index === 0 ? 1 : 0.7); // First tone louder
|
||||
const type = Array.isArray(oscType) ? oscType[index] || oscType[0] : oscType;
|
||||
const { osc, gain } = createFilteredOscillator(ctx, currentTime, hz, vol, type, filterFreq);
|
||||
|
||||
if (fade) {
|
||||
gain.gain.exponentialRampToValueAtTime(0.0001, currentTime + duration);
|
||||
}
|
||||
|
||||
osc.start(currentTime);
|
||||
osc.stop(currentTime + duration + 0.05);
|
||||
});
|
||||
|
||||
// Add noise
|
||||
if (addNoise) {
|
||||
const noiseBufferSize = ctx.sampleRate * duration;
|
||||
const noiseBuffer = ctx.createBuffer(1, noiseBufferSize, ctx.sampleRate);
|
||||
const noiseOutput = noiseBuffer.getChannelData(0);
|
||||
|
||||
for (let i = 0; i < noiseBufferSize; i++) {
|
||||
noiseOutput[i] = (Math.random() * 2 - 1) * 0.006; // Much quieter vintage hiss
|
||||
}
|
||||
|
||||
const noiseSource = ctx.createBufferSource();
|
||||
noiseSource.buffer = noiseBuffer;
|
||||
|
||||
const noiseGain = ctx.createGain();
|
||||
noiseGain.gain.setValueAtTime(0.3, currentTime); // Reduced from 1.0
|
||||
|
||||
noiseSource.connect(noiseGain).connect(ctx.destination);
|
||||
noiseSource.start(currentTime);
|
||||
}
|
||||
|
||||
if (autoOffset) currentTime += duration;
|
||||
return currentTime;
|
||||
},
|
||||
|
||||
gap: (duration: number) => {
|
||||
currentTime += duration;
|
||||
return currentTime;
|
||||
},
|
||||
|
||||
getTime: () => currentTime,
|
||||
setTime: (time: number) => { currentTime = time; }
|
||||
};
|
||||
};
|
||||
|
||||
// Patlabor notification pattern - authentic multi-tone from spectrum analysis
|
||||
const patlaborPattern = () => {
|
||||
const seq = createBeepSequence();
|
||||
// Timing from spectrogram: 0.8s beep, 0.1s gap, 0.8s beep, 0.1s gap, 1.5s beep
|
||||
seq.multiBeep([1000, 3000], 0.7, false, true, 'sawtooth'); // First beep with dual tones
|
||||
seq.multiBeep([800, 2500], 0.35, false, true, 'sawtooth');
|
||||
seq.multiBeep([1000, 3000], 0.7, false, true, 'sawtooth');
|
||||
seq.multiBeep([800, 2500], 0.35, false, true, 'sawtooth');
|
||||
seq.multiBeep([1000, 3000], 2.85, false, true, 'sawtooth');
|
||||
};
|
||||
|
||||
// Custom demo pattern (high-low-high with square waves)
|
||||
const customPattern = () => {
|
||||
const seq = createBeepSequence();
|
||||
seq.beep(1400, 0.6, false, true, 'square');
|
||||
seq.gap(0.2);
|
||||
seq.beep(700, 0.6, false, true, 'square');
|
||||
seq.gap(0.2);
|
||||
seq.beep(1400, 1.0, true, true, 'square');
|
||||
};
|
||||
|
||||
// Rising beeps sweep
|
||||
const risingBeeps = () => {
|
||||
for (let i = 0; i < 8; i++) {
|
||||
setTimeout(() => {
|
||||
oscillators.forEach(osc => osc.disconnect());
|
||||
gainNodes.forEach(gain => gain.disconnect());
|
||||
}, durationSeconds * 1000 + 100);
|
||||
playSound(1800 + i * 50, 'square', 0.03, 0.08);
|
||||
playNoise(0.03, 0.015);
|
||||
}, i * 40);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -176,71 +291,12 @@ export function RetroSoundTest() {
|
||||
<h3 style={{ margin: '0 0 10px 0' }}>Preset Sound</h3>
|
||||
<button
|
||||
style={{ padding: '10px 20px', backgroundColor: '#7f8c8d', color: 'white', border: 'none', borderRadius: '4px', cursor: 'pointer', fontWeight: 'bold' }}
|
||||
onClick={() => {
|
||||
for (let i = 0; i < 8; i++) {
|
||||
setTimeout(() => {
|
||||
playSound(1800 + i * 50, 'square', 0.03, 0.08);
|
||||
playNoise(0.03, 0.015);
|
||||
}, i * 40);
|
||||
}
|
||||
}}
|
||||
onClick={risingBeeps}
|
||||
>
|
||||
RISING BEEPS (sweep)
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Crew Bailout Alarm - 90s Style */}
|
||||
<div style={{ marginTop: '20px', padding: '15px', backgroundColor: '#c0392b', borderRadius: '8px' }}>
|
||||
<h3 style={{ margin: '0 0 10px 0', color: 'white' }}>🚨 Crew Bailout Alarm (90s)</h3>
|
||||
<p style={{ fontSize: '12px', color: 'white', margin: '0 0 10px 0' }}>
|
||||
Agresivní mechanický bzučák: 2850 Hz + 2855 Hz square, 8 beeps/sec
|
||||
</p>
|
||||
<div style={{ display: 'flex', gap: '10px', flexWrap: 'wrap' }}>
|
||||
<button
|
||||
style={{
|
||||
padding: '10px 20px',
|
||||
backgroundColor: '#a93226',
|
||||
color: 'white',
|
||||
border: '2px solid white',
|
||||
borderRadius: '4px',
|
||||
cursor: 'pointer',
|
||||
fontWeight: 'bold'
|
||||
}}
|
||||
onClick={() => crewBailout(2)}
|
||||
>
|
||||
⚠️ 2 sekundy
|
||||
</button>
|
||||
<button
|
||||
style={{
|
||||
padding: '10px 20px',
|
||||
backgroundColor: '#922b21',
|
||||
color: 'white',
|
||||
border: '2px solid white',
|
||||
borderRadius: '4px',
|
||||
cursor: 'pointer',
|
||||
fontWeight: 'bold'
|
||||
}}
|
||||
onClick={() => crewBailout(5)}
|
||||
>
|
||||
🚨 5 sekund
|
||||
</button>
|
||||
<button
|
||||
style={{
|
||||
padding: '10px 20px',
|
||||
backgroundColor: '#7b241c',
|
||||
color: 'white',
|
||||
border: '2px solid white',
|
||||
borderRadius: '4px',
|
||||
cursor: 'pointer',
|
||||
fontWeight: 'bold'
|
||||
}}
|
||||
onClick={() => crewBailout(10)}
|
||||
>
|
||||
💀 10 sekund
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Repeating Sound Toggle */}
|
||||
<div style={{ marginTop: '20px', padding: '15px', backgroundColor: isRepeating ? '#e74c3c' : '#27ae60', borderRadius: '8px' }}>
|
||||
<h3 style={{ margin: '0 0 10px 0', color: 'white' }}>🔁 Test</h3>
|
||||
@@ -259,22 +315,43 @@ export function RetroSoundTest() {
|
||||
>
|
||||
{isRepeating ? '⏹ STOP' : '▶ START'} Random Buzzer
|
||||
</button>
|
||||
<h3 style={{ margin: '0 0 10px 0', color: 'white' }}>Patlabor notify effect</h3>
|
||||
<h3 style={{ margin: '15px 0 10px 0', color: 'white' }}>🤖 Patlabor Notify Pattern</h3>
|
||||
<p style={{ fontSize: '12px', color: 'white', margin: '0 0 10px 0' }}>
|
||||
0.8s → 0.1s gap → 0.8s → 0.1s gap → 1.5s | 1000Hz+3000Hz | Total: 3.3s
|
||||
</p>
|
||||
<div style={{ display: 'flex', gap: '10px', flexWrap: 'wrap' }}>
|
||||
<button
|
||||
style={{
|
||||
padding: '12px 24px',
|
||||
backgroundColor: isRepeating ? '#c0392b' : '#229954',
|
||||
backgroundColor: '#1e5a8e',
|
||||
color: 'white',
|
||||
border: '2px solid blue',
|
||||
border: '2px solid #3498db',
|
||||
borderRadius: '4px',
|
||||
cursor: 'pointer',
|
||||
fontWeight: 'bold',
|
||||
fontSize: '16px'
|
||||
}}
|
||||
onClick={() => playSound(380, 'square', 0.1, 0.1)}
|
||||
onClick={patlaborPattern}
|
||||
>
|
||||
Patlabor Notify
|
||||
🔔 Pattern Notify
|
||||
</button>
|
||||
|
||||
<button
|
||||
style={{
|
||||
padding: '12px 24px',
|
||||
backgroundColor: '#2e7d32',
|
||||
color: 'white',
|
||||
border: '2px solid #4caf50',
|
||||
borderRadius: '4px',
|
||||
cursor: 'pointer',
|
||||
fontWeight: 'bold',
|
||||
fontSize: '16px'
|
||||
}}
|
||||
onClick={customPattern}
|
||||
>
|
||||
🎵 Custom Pattern
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Raw Noise Test */}
|
||||
@@ -286,10 +363,10 @@ export function RetroSoundTest() {
|
||||
key={freq}
|
||||
style={{ padding: '8px 15px', backgroundColor: '#34495e', color: 'white', border: 'none', borderRadius: '4px' }}
|
||||
onClick={() => {
|
||||
playSound(freq, 'sawtooth', 2, 0.1);
|
||||
playSound(freq, 'triangle', 2, 0.1, false, true, 800);
|
||||
}}
|
||||
>
|
||||
{freq} Hz
|
||||
{freq} Hz triangle+filter
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user