mirror of
https://github.com/JorySeverijnse/ui-fixer-supreme.git
synced 2026-01-29 16:18:38 +00:00
Changes
This commit is contained in:
parent
cc2612918c
commit
6e3d0e8918
@ -82,19 +82,13 @@ export function ControlPanel({
|
||||
<div className="flex items-center space-x-3">
|
||||
<RadioGroupItem value="combined" id="live-combined" className="border-primary" />
|
||||
<Label htmlFor="live-combined" className="font-mono-crt text-sm cursor-pointer">
|
||||
Combined (L+R merged)
|
||||
Combined (L+R waveform)
|
||||
</Label>
|
||||
</div>
|
||||
<div className="flex items-center space-x-3">
|
||||
<RadioGroupItem value="separate" id="live-separate" className="border-primary" />
|
||||
<Label htmlFor="live-separate" className="font-mono-crt text-sm cursor-pointer">
|
||||
Separate (L/R stacked)
|
||||
</Label>
|
||||
</div>
|
||||
<div className="flex items-center space-x-3">
|
||||
<RadioGroupItem value="all" id="live-all" className="border-primary" />
|
||||
<Label htmlFor="live-all" className="font-mono-crt text-sm cursor-pointer">
|
||||
All (L/R + XY below)
|
||||
<RadioGroupItem value="all" id="live-xy" className="border-primary" />
|
||||
<Label htmlFor="live-xy" className="font-mono-crt text-sm cursor-pointer">
|
||||
XY Mode (Lissajous)
|
||||
</Label>
|
||||
</div>
|
||||
</RadioGroup>
|
||||
|
||||
@ -57,6 +57,7 @@ export function OscilloscopeDisplay({
|
||||
const lineThickness = liveSettings?.lineThickness ?? 2;
|
||||
const showGrid = liveSettings?.showGrid ?? true;
|
||||
const glowIntensity = liveSettings?.glowIntensity ?? 1;
|
||||
const liveDisplayMode = liveSettings?.displayMode ?? 'combined';
|
||||
|
||||
const drawGraticule = useCallback((ctx: CanvasRenderingContext2D) => {
|
||||
if (!showGrid) return;
|
||||
@ -122,10 +123,6 @@ export function OscilloscopeDisplay({
|
||||
liveData[i] = (dataArray[i] - 128) / 128; // Normalize to -1 to 1
|
||||
}
|
||||
|
||||
samplesPerFrame = liveData.length;
|
||||
startSample = 0;
|
||||
endSample = liveData.length;
|
||||
|
||||
// Apply glow effect
|
||||
if (glowIntensity > 0) {
|
||||
ctx.shadowColor = primaryColor;
|
||||
@ -134,28 +131,49 @@ export function OscilloscopeDisplay({
|
||||
ctx.shadowBlur = 0;
|
||||
}
|
||||
|
||||
// Draw live data directly
|
||||
ctx.strokeStyle = primaryColor;
|
||||
ctx.lineWidth = lineThickness;
|
||||
ctx.beginPath();
|
||||
|
||||
const sliceWidth = WIDTH / samplesPerFrame;
|
||||
let x = 0;
|
||||
// Draw based on live display mode
|
||||
if (liveDisplayMode === 'all') {
|
||||
// XY / Lissajous mode - treat odd/even samples as L/R
|
||||
ctx.beginPath();
|
||||
const centerX = WIDTH / 2;
|
||||
const centerY = HEIGHT / 2;
|
||||
const scale = Math.min(WIDTH, HEIGHT) * 0.4;
|
||||
|
||||
for (let i = 0; i < samplesPerFrame; i++) {
|
||||
const v = liveData[i];
|
||||
const y = (v * HEIGHT) / 2 + HEIGHT / 2;
|
||||
for (let i = 0; i < liveData.length - 1; i += 2) {
|
||||
const x = centerX + liveData[i] * scale;
|
||||
const y = centerY - liveData[i + 1] * scale;
|
||||
|
||||
if (i === 0) {
|
||||
ctx.moveTo(x, y);
|
||||
} else {
|
||||
ctx.lineTo(x, y);
|
||||
if (i === 0) {
|
||||
ctx.moveTo(x, y);
|
||||
} else {
|
||||
ctx.lineTo(x, y);
|
||||
}
|
||||
}
|
||||
ctx.stroke();
|
||||
} else {
|
||||
// Combined waveform mode (default)
|
||||
ctx.beginPath();
|
||||
const sliceWidth = WIDTH / liveData.length;
|
||||
let x = 0;
|
||||
|
||||
x += sliceWidth;
|
||||
for (let i = 0; i < liveData.length; i++) {
|
||||
const v = liveData[i];
|
||||
const y = (v * HEIGHT) / 2 + HEIGHT / 2;
|
||||
|
||||
if (i === 0) {
|
||||
ctx.moveTo(x, y);
|
||||
} else {
|
||||
ctx.lineTo(x, y);
|
||||
}
|
||||
|
||||
x += sliceWidth;
|
||||
}
|
||||
ctx.stroke();
|
||||
}
|
||||
|
||||
ctx.stroke();
|
||||
ctx.shadowBlur = 0;
|
||||
|
||||
// Request next frame for real-time
|
||||
@ -337,7 +355,7 @@ export function OscilloscopeDisplay({
|
||||
}
|
||||
|
||||
animationRef.current = requestAnimationFrame(drawFrame);
|
||||
}, [audioData, micAnalyzer, liveAnalyzer, mode, drawGraticule, onPlaybackEnd, isPlaying, playbackSpeed, isLooping, seekPosition, lineThickness, glowIntensity]);
|
||||
}, [audioData, micAnalyzer, liveAnalyzer, mode, drawGraticule, onPlaybackEnd, isPlaying, playbackSpeed, isLooping, seekPosition, lineThickness, glowIntensity, liveDisplayMode]);
|
||||
|
||||
// Initialize canvas
|
||||
useEffect(() => {
|
||||
|
||||
@ -16,8 +16,9 @@ export const AudioAnalyzerProvider = ({ children }: { children: ReactNode }) =>
|
||||
const analyzerRef = useRef<AnalyserNode | null>(null);
|
||||
const sourceMapRef = useRef<Map<HTMLAudioElement, MediaElementAudioSourceNode>>(new Map());
|
||||
const [isReady, setIsReady] = useState(false);
|
||||
const [, forceUpdate] = useState(0);
|
||||
|
||||
// Initialize audio context lazily on first user interaction
|
||||
// Initialize audio context - call immediately but handle suspended state
|
||||
const initAudioContext = useCallback(() => {
|
||||
if (audioContextRef.current) return audioContextRef.current;
|
||||
|
||||
@ -33,6 +34,7 @@ export const AudioAnalyzerProvider = ({ children }: { children: ReactNode }) =>
|
||||
analyzerRef.current = analyzer;
|
||||
|
||||
setIsReady(true);
|
||||
forceUpdate(n => n + 1); // Force re-render to update context value
|
||||
return ctx;
|
||||
} catch (e) {
|
||||
console.error('Failed to create AudioContext:', e);
|
||||
@ -40,6 +42,11 @@ export const AudioAnalyzerProvider = ({ children }: { children: ReactNode }) =>
|
||||
}
|
||||
}, []);
|
||||
|
||||
// Initialize immediately on mount
|
||||
useEffect(() => {
|
||||
initAudioContext();
|
||||
}, [initAudioContext]);
|
||||
|
||||
// Connect an audio element to the analyzer
|
||||
const connectAudioElement = useCallback((element: HTMLAudioElement) => {
|
||||
const ctx = initAudioContext();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user