Update app/page.tsx
Browse files- app/page.tsx +14 -14
app/page.tsx
CHANGED
|
@@ -13,7 +13,7 @@ import {
|
|
| 13 |
import { Button } from "@/components/ui/button"
|
| 14 |
import { Sparkles, Music, TreePine, RainbowIcon as Unicorn } from "lucide-react"
|
| 15 |
|
| 16 |
-
//
|
| 17 |
const SCALES = {
|
| 18 |
ionian: [0, 2, 4, 5, 7, 9, 11, 12],
|
| 19 |
dorian: [0, 2, 3, 5, 7, 9, 10, 12],
|
|
@@ -26,10 +26,10 @@ const SCALES = {
|
|
| 26 |
melodicMinor: [0, 2, 3, 5, 7, 9, 11, 12],
|
| 27 |
} as const
|
| 28 |
|
| 29 |
-
//
|
| 30 |
const ROOTS = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]
|
| 31 |
|
| 32 |
-
// 8
|
| 33 |
const KEY_COLORS = [
|
| 34 |
"bg-red-400 hover:bg-red-500",
|
| 35 |
"bg-orange-400 hover:bg-orange-500",
|
|
@@ -41,12 +41,12 @@ const KEY_COLORS = [
|
|
| 41 |
"bg-purple-400 hover:bg-purple-500",
|
| 42 |
]
|
| 43 |
|
| 44 |
-
// Keyboard mapping for A
|
| 45 |
const KEY_MAPPING = ["a", "s", "d", "f", "g", "h", "j", "k"]
|
| 46 |
|
| 47 |
-
//
|
| 48 |
export default function Fairyland() {
|
| 49 |
-
//
|
| 50 |
const [synth, setSynth] = useState<Tone.PolySynth | null>(null)
|
| 51 |
|
| 52 |
// Scale/Root/Octave
|
|
@@ -77,7 +77,7 @@ export default function Fairyland() {
|
|
| 77 |
const delayRef = useRef<Tone.FeedbackDelay | null>(null)
|
| 78 |
const reverbRef = useRef<Tone.Reverb | null>(null)
|
| 79 |
|
| 80 |
-
//
|
| 81 |
useEffect(() => {
|
| 82 |
// Create delay
|
| 83 |
const delay = new Tone.FeedbackDelay({
|
|
@@ -146,7 +146,7 @@ export default function Fairyland() {
|
|
| 146 |
window.removeEventListener("keydown", handleFirstInteraction)
|
| 147 |
// No missing dependencies because we're removing only local references
|
| 148 |
}
|
| 149 |
-
|
| 150 |
}, [
|
| 151 |
forestOn,
|
| 152 |
forestPlaying,
|
|
@@ -158,7 +158,7 @@ export default function Fairyland() {
|
|
| 158 |
release
|
| 159 |
])
|
| 160 |
|
| 161 |
-
//
|
| 162 |
useEffect(() => {
|
| 163 |
const forest = forestRef.current
|
| 164 |
if (!forest) return
|
|
@@ -177,7 +177,7 @@ export default function Fairyland() {
|
|
| 177 |
}
|
| 178 |
}, [forestOn, forestPlaying])
|
| 179 |
|
| 180 |
-
//
|
| 181 |
useEffect(() => {
|
| 182 |
if (!synth) return
|
| 183 |
synth.set({
|
|
@@ -190,7 +190,7 @@ export default function Fairyland() {
|
|
| 190 |
})
|
| 191 |
}, [synth, attack, decay, sustain, release])
|
| 192 |
|
| 193 |
-
//
|
| 194 |
useEffect(() => {
|
| 195 |
if (delayRef.current) {
|
| 196 |
delayRef.current.wet.value = delayWet
|
|
@@ -203,7 +203,7 @@ export default function Fairyland() {
|
|
| 203 |
}
|
| 204 |
}, [reverbWet])
|
| 205 |
|
| 206 |
-
//
|
| 207 |
// Build scale notes
|
| 208 |
const scaleNotes = useMemo(() => {
|
| 209 |
const intervals = SCALES[scale as keyof typeof SCALES] || [0, 2, 4, 5, 7, 9, 11, 12]
|
|
@@ -252,7 +252,7 @@ export default function Fairyland() {
|
|
| 252 |
}
|
| 253 |
}, [synth, scaleNotes])
|
| 254 |
|
| 255 |
-
//
|
| 256 |
return (
|
| 257 |
<div
|
| 258 |
className="min-h-screen relative overflow-hidden flex flex-col items-center justify-center p-4"
|
|
@@ -483,7 +483,7 @@ export default function Fairyland() {
|
|
| 483 |
)
|
| 484 |
}
|
| 485 |
|
| 486 |
-
//
|
| 487 |
function OnScreenKeys({
|
| 488 |
synth,
|
| 489 |
scale,
|
|
|
|
| 13 |
import { Button } from "@/components/ui/button"
|
| 14 |
import { Sparkles, Music, TreePine, RainbowIcon as Unicorn } from "lucide-react"
|
| 15 |
|
| 16 |
+
// Scales
|
| 17 |
const SCALES = {
|
| 18 |
ionian: [0, 2, 4, 5, 7, 9, 11, 12],
|
| 19 |
dorian: [0, 2, 3, 5, 7, 9, 10, 12],
|
|
|
|
| 26 |
melodicMinor: [0, 2, 3, 5, 7, 9, 11, 12],
|
| 27 |
} as const
|
| 28 |
|
| 29 |
+
// Root notes
|
| 30 |
const ROOTS = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]
|
| 31 |
|
| 32 |
+
// 8 colors for on-screen keys
|
| 33 |
const KEY_COLORS = [
|
| 34 |
"bg-red-400 hover:bg-red-500",
|
| 35 |
"bg-orange-400 hover:bg-orange-500",
|
|
|
|
| 41 |
"bg-purple-400 hover:bg-purple-500",
|
| 42 |
]
|
| 43 |
|
| 44 |
+
// Keyboard mapping for A-K (0-7)
|
| 45 |
const KEY_MAPPING = ["a", "s", "d", "f", "g", "h", "j", "k"]
|
| 46 |
|
| 47 |
+
// Main component
|
| 48 |
export default function Fairyland() {
|
| 49 |
+
// States
|
| 50 |
const [synth, setSynth] = useState<Tone.PolySynth | null>(null)
|
| 51 |
|
| 52 |
// Scale/Root/Octave
|
|
|
|
| 77 |
const delayRef = useRef<Tone.FeedbackDelay | null>(null)
|
| 78 |
const reverbRef = useRef<Tone.Reverb | null>(null)
|
| 79 |
|
| 80 |
+
// 1) Initialize Synth + Effects + Forest
|
| 81 |
useEffect(() => {
|
| 82 |
// Create delay
|
| 83 |
const delay = new Tone.FeedbackDelay({
|
|
|
|
| 146 |
window.removeEventListener("keydown", handleFirstInteraction)
|
| 147 |
// No missing dependencies because we're removing only local references
|
| 148 |
}
|
| 149 |
+
|
| 150 |
}, [
|
| 151 |
forestOn,
|
| 152 |
forestPlaying,
|
|
|
|
| 158 |
release
|
| 159 |
])
|
| 160 |
|
| 161 |
+
// Toggling forestOn
|
| 162 |
useEffect(() => {
|
| 163 |
const forest = forestRef.current
|
| 164 |
if (!forest) return
|
|
|
|
| 177 |
}
|
| 178 |
}, [forestOn, forestPlaying])
|
| 179 |
|
| 180 |
+
// Envelope changes (Synth)
|
| 181 |
useEffect(() => {
|
| 182 |
if (!synth) return
|
| 183 |
synth.set({
|
|
|
|
| 190 |
})
|
| 191 |
}, [synth, attack, decay, sustain, release])
|
| 192 |
|
| 193 |
+
// Delay & Reverb updates
|
| 194 |
useEffect(() => {
|
| 195 |
if (delayRef.current) {
|
| 196 |
delayRef.current.wet.value = delayWet
|
|
|
|
| 203 |
}
|
| 204 |
}, [reverbWet])
|
| 205 |
|
| 206 |
+
// Keyboard (A..K => scaleNotes)
|
| 207 |
// Build scale notes
|
| 208 |
const scaleNotes = useMemo(() => {
|
| 209 |
const intervals = SCALES[scale as keyof typeof SCALES] || [0, 2, 4, 5, 7, 9, 11, 12]
|
|
|
|
| 252 |
}
|
| 253 |
}, [synth, scaleNotes])
|
| 254 |
|
| 255 |
+
// RENDER
|
| 256 |
return (
|
| 257 |
<div
|
| 258 |
className="min-h-screen relative overflow-hidden flex flex-col items-center justify-center p-4"
|
|
|
|
| 483 |
)
|
| 484 |
}
|
| 485 |
|
| 486 |
+
// OnScreenKeys COMPONENT
|
| 487 |
function OnScreenKeys({
|
| 488 |
synth,
|
| 489 |
scale,
|