fix: make spectrogram background match frequency analyzer

Changed spectrogram to use transparency for low values
instead of interpolating from background color:

- Low signal values (0-64) fade from transparent to blue
- Background color shows through transparent areas
- Now matches FrequencyAnalyzer theme behavior
- Both analyzers use bg-muted/30 wrapper for consistent theming

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-19 01:48:36 +01:00
parent 3818d93696
commit 90f9218ed3

View File

@@ -30,13 +30,6 @@ export function Spectrogram({ analyserNode, className }: SpectrogramProps) {
const bufferLength = analyserNode.frequencyBinCount; const bufferLength = analyserNode.frequencyBinCount;
const dataArray = new Uint8Array(bufferLength); const dataArray = new Uint8Array(bufferLength);
// Get background color from computed styles
const bgColorStr = getComputedStyle(canvas.parentElement!).backgroundColor;
const bgMatch = bgColorStr.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);
const bgR = bgMatch ? parseInt(bgMatch[1]) : 240;
const bgG = bgMatch ? parseInt(bgMatch[2]) : 240;
const bgB = bgMatch ? parseInt(bgMatch[3]) : 240;
// Initialize spectrogram data // Initialize spectrogram data
spectrogramDataRef.current = ctx.createImageData(rect.width, rect.height); spectrogramDataRef.current = ctx.createImageData(rect.width, rect.height);
@@ -57,7 +50,7 @@ export function Spectrogram({ analyserNode, className }: SpectrogramProps) {
imageData.data[targetIndex] = imageData.data[sourceIndex]; imageData.data[targetIndex] = imageData.data[sourceIndex];
imageData.data[targetIndex + 1] = imageData.data[sourceIndex + 1]; imageData.data[targetIndex + 1] = imageData.data[sourceIndex + 1];
imageData.data[targetIndex + 2] = imageData.data[sourceIndex + 2]; imageData.data[targetIndex + 2] = imageData.data[sourceIndex + 2];
imageData.data[targetIndex + 3] = 255; imageData.data[targetIndex + 3] = imageData.data[sourceIndex + 3];
} }
} }
@@ -68,36 +61,40 @@ export function Spectrogram({ analyserNode, className }: SpectrogramProps) {
const freqIndex = Math.floor((1 - y / rect.height) * bufferLength); const freqIndex = Math.floor((1 - y / rect.height) * bufferLength);
const value = dataArray[freqIndex]; const value = dataArray[freqIndex];
// Color mapping: background color (0) -> blue -> cyan -> green -> yellow -> red (255) // Color mapping with transparency: transparent (0) -> blue -> cyan -> green -> yellow -> red (255)
let r, g, b; let r, g, b, a;
if (value < 64) { if (value < 64) {
// Background to blue // Transparent to blue
const t = value / 64; const t = value / 64;
r = Math.round(bgR * (1 - t)); r = 0;
g = Math.round(bgG * (1 - t)); g = 0;
b = Math.round(bgB * (1 - t) + 255 * t); b = Math.round(255 * t);
a = Math.round(255 * t);
} else if (value < 128) { } else if (value < 128) {
// Blue to cyan // Blue to cyan
r = 0; r = 0;
g = (value - 64) * 4; g = (value - 64) * 4;
b = 255; b = 255;
a = 255;
} else if (value < 192) { } else if (value < 192) {
// Cyan to green // Cyan to green
r = 0; r = 0;
g = 255; g = 255;
b = 255 - (value - 128) * 4; b = 255 - (value - 128) * 4;
a = 255;
} else { } else {
// Green to yellow to red // Green to yellow to red
r = (value - 192) * 4; r = (value - 192) * 4;
g = 255; g = 255;
b = 0; b = 0;
a = 255;
} }
const index = ((y * rect.width) + x) * 4; const index = ((y * rect.width) + x) * 4;
imageData.data[index] = r; imageData.data[index] = r;
imageData.data[index + 1] = g; imageData.data[index + 1] = g;
imageData.data[index + 2] = b; imageData.data[index + 2] = b;
imageData.data[index + 3] = 255; imageData.data[index + 3] = a;
} }
// Draw the spectrogram // Draw the spectrogram