Harsh noise soundbox made as a love statement to all weird noises, hums, audio glitches and ominous textures. Be careful, lower your volume! Tweak some parameters!
-
KEYBOARD SHORTCUTS
+
+
KEYBOARD SHORTCUTS
-
-
-
- | KEY |
- ACTION |
-
-
-
-
- | SPACE |
- Play/Stop current tile |
-
-
- | ARROWS |
- Navigate tiles |
-
-
- | SHIFT + ARROWS |
- Jump 10 tiles |
-
-
- | ENTER |
- Queue tile (play after current) |
-
-
- | DOUBLE ENTER |
- Play immediately |
-
-
- | R |
- Regenerate current tile |
-
-
- | SHIFT + R |
- Randomize all tiles |
-
-
- | C |
- Randomize current tile params |
-
-
- | SHIFT + C |
- Randomize all params (CHAOS) |
-
-
- | ESC |
- Exit mapping mode |
-
-
-
+
+
+
+
+ | KEY |
+ ACTION |
+
+
+
+
+ | SPACE |
+ Play/Stop current tile |
+
+
+ | ARROWS |
+ Navigate tiles |
+
+
+ | SHIFT + ARROWS |
+ Jump 10 tiles |
+
+
+ | ENTER |
+ Queue tile (play after current) |
+
+
+ | DOUBLE ENTER |
+ Play immediately |
+
+
+ | R |
+ Regenerate current tile |
+
+
+ | SHIFT + R |
+ Randomize all tiles |
+
+
+ | C |
+ Randomize current tile params |
+
+
+ | SHIFT + C |
+ Randomize all params (CHAOS) |
+
+
+ | ESC |
+ Exit mapping mode |
+
+
+
+
{showStartButton ? (
) : (
diff --git a/src/components/Knob.tsx b/src/components/Knob.tsx
index 6cd2f8dc..f1f62fcc 100644
--- a/src/components/Knob.tsx
+++ b/src/components/Knob.tsx
@@ -45,6 +45,8 @@ export function Knob({
const normalizedValue = (value - min) / (max - min)
const angle = -225 + normalizedValue * 270
+ const fontSize = size <= 32 ? 'text-[7px]' : size <= 36 ? 'text-[8px]' : 'text-[9px]'
+
const handleMouseDown = (e: React.MouseEvent) => {
if (isInMappingMode && paramId && mappingModeState.activeLFO !== null && onMapClick) {
onMapClick(paramId, mappingModeState.activeLFO)
@@ -135,7 +137,7 @@ export function Knob({
-
+
{isDragging ? displayValue : label.toUpperCase()}
diff --git a/src/components/LFOPanel.tsx b/src/components/LFOPanel.tsx
index 58fd3aa3..c1878b6e 100644
--- a/src/components/LFOPanel.tsx
+++ b/src/components/LFOPanel.tsx
@@ -36,11 +36,11 @@ export function LFOPanel({ onChange, onUpdateDepth, onRemoveMapping }: LFOPanelP
return (
-
+
{lfoConfigs.map(({ key, index }) => {
const lfo = lfoValues[key]
return (
-
+
(null)
const mappingModeState = useStore(mappingMode)
+ const [canvasWidth, setCanvasWidth] = useState(340)
const getLFOValueAtPhase = useCallback((phaseVal: number): number => {
const normalizedPhase = phaseVal % 1
@@ -65,6 +65,26 @@ export function LFOScope({ lfoIndex, waveform, frequency, phase, mappings, onCha
}
}, [frequency, phase, waveform])
+ useEffect(() => {
+ const canvas = canvasRef.current
+ if (!canvas) return
+
+ const updateCanvasSize = () => {
+ const rect = canvas.getBoundingClientRect()
+ const width = Math.floor(rect.width)
+ setCanvasWidth(width)
+ canvas.width = width
+ canvas.height = CANVAS_HEIGHT
+ }
+
+ updateCanvasSize()
+ window.addEventListener('resize', updateCanvasSize)
+
+ return () => {
+ window.removeEventListener('resize', updateCanvasSize)
+ }
+ }, [])
+
useEffect(() => {
const canvas = canvasRef.current
if (!canvas) return
@@ -78,13 +98,13 @@ export function LFOScope({ lfoIndex, waveform, frequency, phase, mappings, onCha
if (!lfoRef.current) return
ctx.fillStyle = '#000000'
- ctx.fillRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT)
+ ctx.fillRect(0, 0, canvasWidth, CANVAS_HEIGHT)
ctx.strokeStyle = '#ffffff'
ctx.lineWidth = 2
ctx.beginPath()
- const samples = CANVAS_WIDTH
+ const samples = canvasWidth
const centerY = CANVAS_HEIGHT / 2
for (let x = 0; x < samples; x++) {
@@ -119,7 +139,7 @@ export function LFOScope({ lfoIndex, waveform, frequency, phase, mappings, onCha
cancelAnimationFrame(animationRef.current)
}
}
- }, [frequency, waveform, phase, getLFOValueAtPhase])
+ }, [frequency, waveform, phase, getLFOValueAtPhase, canvasWidth])
const handleMouseDown = (e: React.MouseEvent) => {
if (e.button === 2) return
@@ -185,12 +205,10 @@ export function LFOScope({ lfoIndex, waveform, frequency, phase, mappings, onCha