mapWobbleToDetune

This commit is contained in:
2026-01-25 10:31:42 +00:00
parent 705e2a0311
commit a40ddef687
2 changed files with 19 additions and 2 deletions

View File

@@ -5,7 +5,14 @@ import { Toggle } from "@/components/ui/toggle";
import { useAudioContext } from "@/hooks/useAudioContext"; import { useAudioContext } from "@/hooks/useAudioContext";
import { useShapeState } from "@/hooks/useShapeState"; import { useShapeState } from "@/hooks/useShapeState";
import { useSynth } from "@/hooks/useSynth"; import { useSynth } from "@/hooks/useSynth";
import { mapGrainToNoise, mapPresetToOscType, mapRoundnessToFade, mapSizeToGain } from "@/lib/audio/mapping"; import { useWobbleAnimation } from "@/hooks/useWobbleAnimation";
import {
mapGrainToNoise,
mapPresetToOscType,
mapRoundnessToFade,
mapSizeToGain,
mapWobbleToDetune,
} from "@/lib/audio/mapping";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import * as Tone from "tone"; import * as Tone from "tone";
import Layout from "./Layout"; import Layout from "./Layout";
@@ -35,6 +42,7 @@ function Index() {
const [state, setState] = useShapeState(centerX, centerY); const [state, setState] = useShapeState(centerX, centerY);
const { isMuted, toggleMute } = useAudioContext(); const { isMuted, toggleMute } = useAudioContext();
const synthRef = useSynth(); const synthRef = useSynth();
const pitchTime = useWobbleAnimation(state.wobbleSpeed);
useEffect(() => { useEffect(() => {
if (!synthRef.current) return; if (!synthRef.current) return;
@@ -43,11 +51,15 @@ function Index() {
nodes.oscillatorA.type = mapPresetToOscType(state.preset); nodes.oscillatorA.type = mapPresetToOscType(state.preset);
nodes.crossFade.fade.value = mapRoundnessToFade(state.roundness); nodes.crossFade.fade.value = mapRoundnessToFade(state.roundness);
nodes.gain.gain.value = Tone.dbToGain(mapSizeToGain(state.size)); nodes.gain.gain.value = Tone.dbToGain(mapSizeToGain(state.size));
const detuneDepth = mapWobbleToDetune(state.wobble);
const detune = Math.sin(pitchTime * Math.PI * 2) * detuneDepth;
nodes.oscillatorA.detune.value = detune;
nodes.oscillatorB.detune.value = detune;
const grain = mapGrainToNoise(state.grain); const grain = mapGrainToNoise(state.grain);
const noiseDb = grain === 0 ? Number.NEGATIVE_INFINITY : -40 + (-12 - -40) * grain; const noiseDb = grain === 0 ? Number.NEGATIVE_INFINITY : -40 + (-12 - -40) * grain;
nodes.noise.volume.value = noiseDb; nodes.noise.volume.value = noiseDb;
}, [state.preset, state.roundness, state.size, state.grain, synthRef]); }, [state.preset, state.roundness, state.size, state.wobble, state.grain, synthRef, pitchTime]);
const sidebarContent = ( const sidebarContent = (
<div className="flex flex-col gap-4"> <div className="flex flex-col gap-4">

View File

@@ -26,6 +26,11 @@ export function mapGrainToNoise(grain: number): number {
return clamp01(grain / 100); return clamp01(grain / 100);
} }
export function mapWobbleToDetune(wobble: number): number {
const maxCents = 50;
return clamp01(wobble / 100) * maxCents;
}
function clamp01(value: number) { function clamp01(value: number) {
return Math.min(1, Math.max(0, value)); return Math.min(1, Math.max(0, value));
} }