Skip to content

Commit 082d433

Browse files
AudioGridVisualizer
1 parent a5c272f commit 082d433

File tree

10 files changed

+1371
-5
lines changed

10 files changed

+1371
-5
lines changed

app/ui/_components.tsx

Lines changed: 98 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33
import { useEffect, useMemo, useState } from 'react';
44
import { type VariantProps } from 'class-variance-authority';
55
import { Track } from 'livekit-client';
6+
import { RoomAudioRenderer, StartAudio } from '@livekit/components-react';
67
import {
78
type AgentState,
89
type TrackReference,
910
type TrackReferenceOrPlaceholder,
1011
useLocalParticipant,
12+
useVoiceAssistant,
1113
} from '@livekit/components-react';
1214
import { MicrophoneIcon } from '@phosphor-icons/react/dist/ssr';
1315
import { useSession } from '@/components/app/session-provider';
@@ -22,15 +24,13 @@ import {
2224
AudioBarVisualizer,
2325
audioBarVisualizerVariants,
2426
} from '@/components/livekit/audio-visualizer/audio-bar-visualizer/audio-bar-visualizer';
25-
import {
26-
AudioGridVisualizer,
27-
type GridOptions,
28-
} from '@/components/livekit/audio-visualizer/audio-grid-visualizer/audio-grid-visualizer';
27+
import { AudioGridVisualizer } from '@/components/livekit/audio-visualizer/audio-grid-visualizer/audio-grid-visualizer';
2928
import { gridVariants } from '@/components/livekit/audio-visualizer/audio-grid-visualizer/demos';
3029
import {
3130
AudioRadialVisualizer,
3231
audioRadialVisualizerVariants,
3332
} from '@/components/livekit/audio-visualizer/audio-radial-visualizer/audio-radial-visualizer';
33+
import { AudioShaderVisualizer } from '@/components/livekit/audio-visualizer/audio-shader-visualizer/audio-shader-visualizer';
3434
import { Button, buttonVariants } from '@/components/livekit/button';
3535
import { ChatEntry } from '@/components/livekit/chat-entry';
3636
import {
@@ -442,11 +442,11 @@ export const COMPONENTS = {
442442
'speaking',
443443
] as AgentState[];
444444

445-
const { microphoneTrack, localParticipant } = useLocalParticipant();
446445
const [rowCount, setRowCount] = useState(rowCounts[0]);
447446
const [columnCount, setColumnCount] = useState(columnCounts[0]);
448447
const [state, setState] = useState<AgentState>(states[0]);
449448
const [demoIndex, setDemoIndex] = useState(0);
449+
const { microphoneTrack, localParticipant } = useLocalParticipant();
450450

451451
const micTrackRef = useMemo<TrackReferenceOrPlaceholder | undefined>(() => {
452452
return state === 'speaking'
@@ -562,6 +562,99 @@ export const COMPONENTS = {
562562
);
563563
},
564564

565+
AudioShaderVisualizer: () => {
566+
const [presetIndex, setPresetIndex] = useState(3);
567+
568+
// speed
569+
const [a, setA] = useState(50);
570+
// // color scale
571+
const [h, setH] = useState(0.1);
572+
// // color position
573+
const [i, setI] = useState(0.15);
574+
// blur
575+
const [f, setF] = useState(0.1);
576+
// shape
577+
const [g, setG] = useState(1.0);
578+
579+
const {
580+
// state,
581+
audioTrack,
582+
} = useVoiceAssistant();
583+
584+
useMicrophone();
585+
586+
const fields = [
587+
['speed', a, setA, 0, 250, 10],
588+
['color position', i, setI, 0, 1, 0.01],
589+
['color scale', h, setH, 0, 1, 0.01],
590+
['blur', f, setF, 0, 2, 0.01],
591+
['shape', g, setG, 1, 5, 1],
592+
] as const;
593+
594+
return (
595+
<Container componentName="AudioShaderVisualizer">
596+
<StartAudio label="Start Audio" />
597+
<RoomAudioRenderer />
598+
<div className="grid grid-cols-2 gap-4">
599+
<AudioShaderVisualizer
600+
speed={a}
601+
blur={f}
602+
shape={g}
603+
colorScale={h}
604+
colorPosition={i}
605+
audioTrack={audioTrack}
606+
presetIndex={presetIndex}
607+
// className="bg-amber-100"
608+
/>
609+
<div>
610+
<div className="mb-4">
611+
<StoryTitle>Preset</StoryTitle>
612+
<Select
613+
value={String(presetIndex)}
614+
onValueChange={(value) => setPresetIndex(parseInt(value))}
615+
>
616+
<SelectTrigger id="presetIndex" className="w-full">
617+
<SelectValue placeholder="Select a preset" />
618+
</SelectTrigger>
619+
<SelectContent>
620+
<SelectItem value="0">Preset 1</SelectItem>
621+
<SelectItem value="1">Preset 2</SelectItem>
622+
<SelectItem value="2">Preset 3</SelectItem>
623+
<SelectItem value="3">Preset 4</SelectItem>
624+
</SelectContent>
625+
</Select>
626+
</div>
627+
628+
{fields.map(([name, value, setValue, min = 0.1, max = 10, step = 0.1]) => {
629+
// Use 0-1 range for color phase channels
630+
const isColorPhase = name.toString().startsWith('colorPhase');
631+
632+
return (
633+
<div key={name}>
634+
<div className="flex items-center justify-between">
635+
<StoryTitle>{name}</StoryTitle>
636+
<div className="text-muted-foreground mb-2 text-xs">
637+
{isColorPhase ? Number(value).toFixed(2) : String(value)}
638+
</div>
639+
</div>
640+
<input
641+
type="range"
642+
value={String(value)}
643+
min={min}
644+
max={max}
645+
step={step}
646+
onChange={(e) => setValue(parseFloat(e.target.value))}
647+
className="w-full"
648+
/>
649+
</div>
650+
);
651+
})}
652+
</div>
653+
</div>
654+
</Container>
655+
);
656+
},
657+
565658
// Agent control bar
566659
AgentControlBar: () => {
567660
useMicrophone();
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
'use client';
2+
3+
import {
4+
type TrackReference,
5+
type TrackReferenceOrPlaceholder,
6+
// useMultibandTrackVolume,
7+
useTrackVolume,
8+
} from '@livekit/components-react';
9+
import { AuroraShaders, type AuroraShadersProps } from '@/components/ui/shadcn-io/aurora-shaders';
10+
import { cn } from '@/lib/utils';
11+
12+
const PRESETS = [
13+
(volume: number) => ({
14+
amplitude: 0.3,
15+
scale: 0.3 - 0.1 * (volume * 1.5),
16+
frequency: 0.25,
17+
brightness: 0.5 + 2.5 * volume,
18+
}),
19+
(volume: number) => ({
20+
amplitude: 0.2 + 1 * volume,
21+
scale: 0.3 - 0.1 * (volume * 1.5),
22+
frequency: 0.25 + 5 * volume,
23+
brightness: 0.5 + 2.5 * volume,
24+
}),
25+
(volume: number) => ({
26+
amplitude: 0.5 + 0.1 * volume,
27+
scale: 0.2 + 0.1 * (volume * 1.5),
28+
frequency: 5 - 6 * volume,
29+
brightness: 0.5 + 2.5 * volume,
30+
}),
31+
(volume: number) => ({
32+
amplitude: 0.5 + 0.1 * volume,
33+
scale: 0.2 + 0.1 * volume * 0.5,
34+
frequency: 1 - 1 * volume,
35+
brightness: 0.5 + 2.5 * volume,
36+
}),
37+
];
38+
39+
export function AudioShaderVisualizer({
40+
speed = 1.0,
41+
// intensity = 0,
42+
blur = 0.2,
43+
shape = 1,
44+
colorPosition = 0.5,
45+
colorScale = 0.1,
46+
audioTrack,
47+
presetIndex = 0,
48+
className,
49+
}: AuroraShadersProps & { presetIndex?: number; audioTrack?: TrackReferenceOrPlaceholder }) {
50+
// const [volume] = useMultibandTrackVolume(audioTrack, {
51+
// bands: 1,
52+
// loPass: 100,
53+
// hiPass: 150,
54+
// });
55+
const volume = useTrackVolume(audioTrack as TrackReference, {
56+
fftSize: 2048,
57+
smoothingTimeConstant: 0.5,
58+
});
59+
60+
const { amplitude, scale, frequency, brightness } = PRESETS[presetIndex](volume);
61+
62+
return (
63+
<div className={cn('size-80 overflow-hidden rounded-full', className)}>
64+
<AuroraShaders
65+
speed={speed}
66+
// intensity={intensity}
67+
amplitude={amplitude}
68+
frequency={frequency}
69+
scale={scale}
70+
blur={blur}
71+
shape={shape}
72+
colorPosition={colorPosition}
73+
colorScale={colorScale}
74+
brightness={brightness}
75+
// colorPhaseEnd={colorPhaseEnd}
76+
/>
77+
</div>
78+
);
79+
}
80+
81+
// import {
82+
// CosmicWavesShaders,
83+
// type CosmicWavesShadersProps,
84+
// } from '@/components/ui/shadcn-io/cosmic-waves-shaders';
85+
86+
// export function AudioShaderVisualizer({
87+
// speed = 1.0,
88+
// amplitude = 1.0,
89+
// frequency = 1.0,
90+
// starDensity = 1.0,
91+
// colorShift = 1.0,
92+
// }: CosmicWavesShadersProps) {
93+
// return (
94+
// <div className="size-40 overflow-hidden rounded-full">
95+
// <CosmicWavesShaders
96+
// speed={speed}
97+
// amplitude={amplitude}
98+
// frequency={frequency}
99+
// starDensity={starDensity}
100+
// colorShift={colorShift}
101+
// />
102+
// </div>
103+
// );
104+
// }
105+
106+
// import {
107+
// SingularityShaders,
108+
// type SingularityShadersProps,
109+
// } from '@/components/ui/shadcn-io/singularity-shaders';
110+
111+
// export function AudioShaderVisualizer({
112+
// speed = 1.0,
113+
// intensity = 1.0,
114+
// size = 1.0,
115+
// waveStrength = 1.0,
116+
// colorShift = 1.0,
117+
// }: SingularityShadersProps) {
118+
// return (
119+
// <div className="size-40 overflow-hidden rounded-full">
120+
// <SingularityShaders
121+
// speed={speed}
122+
// intensity={intensity}
123+
// size={size}
124+
// waveStrength={waveStrength}
125+
// colorShift={colorShift}
126+
// />
127+
// </div>
128+
// );
129+
// }

0 commit comments

Comments
 (0)