Spaces:
Build error
Build error
Commit
·
c2a47f9
1
Parent(s):
05426cb
Web real-time reverb, remove other controls
Browse files- web/package-lock.json +44 -3
- web/package.json +2 -0
- web/public/test-clips/skibidi-toilet.mp3 +0 -0
- web/src/app/audio-clip.tsx +133 -0
- web/src/app/globals.css +16 -5
- web/src/app/page.tsx +25 -59
web/package-lock.json
CHANGED
@@ -8,6 +8,7 @@
|
|
8 |
"name": "web",
|
9 |
"version": "0.1.0",
|
10 |
"dependencies": {
|
|
|
11 |
"@types/node": "20.4.2",
|
12 |
"@types/react": "18.2.15",
|
13 |
"@types/react-dom": "18.2.7",
|
@@ -19,6 +20,7 @@
|
|
19 |
"react": "18.2.0",
|
20 |
"react-dom": "18.2.0",
|
21 |
"tailwindcss": "3.3.3",
|
|
|
22 |
"typescript": "5.1.6"
|
23 |
}
|
24 |
},
|
@@ -104,6 +106,14 @@
|
|
104 |
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
105 |
}
|
106 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
107 |
"node_modules/@humanwhocodes/config-array": {
|
108 |
"version": "0.11.10",
|
109 |
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz",
|
@@ -708,6 +718,18 @@
|
|
708 |
"resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz",
|
709 |
"integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag=="
|
710 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
711 |
"node_modules/autoprefixer": {
|
712 |
"version": "10.4.14",
|
713 |
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.14.tgz",
|
@@ -3611,6 +3633,16 @@
|
|
3611 |
"node": ">=0.10.0"
|
3612 |
}
|
3613 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3614 |
"node_modules/streamsearch": {
|
3615 |
"version": "1.1.0",
|
3616 |
"resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
|
@@ -3909,6 +3941,15 @@
|
|
3909 |
"node": ">=8.0"
|
3910 |
}
|
3911 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3912 |
"node_modules/ts-interface-checker": {
|
3913 |
"version": "0.1.13",
|
3914 |
"resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
|
@@ -3926,9 +3967,9 @@
|
|
3926 |
}
|
3927 |
},
|
3928 |
"node_modules/tslib": {
|
3929 |
-
"version": "2.6.
|
3930 |
-
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.
|
3931 |
-
"integrity": "sha512-
|
3932 |
},
|
3933 |
"node_modules/tsutils": {
|
3934 |
"version": "3.21.0",
|
|
|
8 |
"name": "web",
|
9 |
"version": "0.1.0",
|
10 |
"dependencies": {
|
11 |
+
"@heroicons/react": "^2.0.18",
|
12 |
"@types/node": "20.4.2",
|
13 |
"@types/react": "18.2.15",
|
14 |
"@types/react-dom": "18.2.7",
|
|
|
20 |
"react": "18.2.0",
|
21 |
"react-dom": "18.2.0",
|
22 |
"tailwindcss": "3.3.3",
|
23 |
+
"tone": "^14.7.77",
|
24 |
"typescript": "5.1.6"
|
25 |
}
|
26 |
},
|
|
|
106 |
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
107 |
}
|
108 |
},
|
109 |
+
"node_modules/@heroicons/react": {
|
110 |
+
"version": "2.0.18",
|
111 |
+
"resolved": "https://registry.npmjs.org/@heroicons/react/-/react-2.0.18.tgz",
|
112 |
+
"integrity": "sha512-7TyMjRrZZMBPa+/5Y8lN0iyvUU/01PeMGX2+RE7cQWpEUIcb4QotzUObFkJDejj/HUH4qjP/eQ0gzzKs2f+6Yw==",
|
113 |
+
"peerDependencies": {
|
114 |
+
"react": ">= 16"
|
115 |
+
}
|
116 |
+
},
|
117 |
"node_modules/@humanwhocodes/config-array": {
|
118 |
"version": "0.11.10",
|
119 |
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz",
|
|
|
718 |
"resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz",
|
719 |
"integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag=="
|
720 |
},
|
721 |
+
"node_modules/automation-events": {
|
722 |
+
"version": "6.0.8",
|
723 |
+
"resolved": "https://registry.npmjs.org/automation-events/-/automation-events-6.0.8.tgz",
|
724 |
+
"integrity": "sha512-OXI9rEbA0LwWr+Tmvka4EHtVHBIVw8KD2NM7fIGjd4dyGnuiM3ULZL+Jlo4aKXZDY98raT4R4rEDOHAbz8Jm9A==",
|
725 |
+
"dependencies": {
|
726 |
+
"@babel/runtime": "^7.22.6",
|
727 |
+
"tslib": "^2.6.1"
|
728 |
+
},
|
729 |
+
"engines": {
|
730 |
+
"node": ">=16.1.0"
|
731 |
+
}
|
732 |
+
},
|
733 |
"node_modules/autoprefixer": {
|
734 |
"version": "10.4.14",
|
735 |
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.14.tgz",
|
|
|
3633 |
"node": ">=0.10.0"
|
3634 |
}
|
3635 |
},
|
3636 |
+
"node_modules/standardized-audio-context": {
|
3637 |
+
"version": "25.3.54",
|
3638 |
+
"resolved": "https://registry.npmjs.org/standardized-audio-context/-/standardized-audio-context-25.3.54.tgz",
|
3639 |
+
"integrity": "sha512-1b5YTivCBc52MFlg3yUFdbfQZBb4wyFUjbvzBn6JD1FJM1nd3RTg3ddyGWRT8XVOC0KUwY2h4R9YrqLpQ04JPQ==",
|
3640 |
+
"dependencies": {
|
3641 |
+
"@babel/runtime": "^7.22.6",
|
3642 |
+
"automation-events": "^6.0.7",
|
3643 |
+
"tslib": "^2.6.0"
|
3644 |
+
}
|
3645 |
+
},
|
3646 |
"node_modules/streamsearch": {
|
3647 |
"version": "1.1.0",
|
3648 |
"resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
|
|
|
3941 |
"node": ">=8.0"
|
3942 |
}
|
3943 |
},
|
3944 |
+
"node_modules/tone": {
|
3945 |
+
"version": "14.7.77",
|
3946 |
+
"resolved": "https://registry.npmjs.org/tone/-/tone-14.7.77.tgz",
|
3947 |
+
"integrity": "sha512-tCfK73IkLHyzoKUvGq47gyDyxiKLFvKiVCOobynGgBB9Dl0NkxTM2p+eRJXyCYrjJwy9Y0XCMqD3uOYsYt2Fdg==",
|
3948 |
+
"dependencies": {
|
3949 |
+
"standardized-audio-context": "^25.1.8",
|
3950 |
+
"tslib": "^2.0.1"
|
3951 |
+
}
|
3952 |
+
},
|
3953 |
"node_modules/ts-interface-checker": {
|
3954 |
"version": "0.1.13",
|
3955 |
"resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
|
|
|
3967 |
}
|
3968 |
},
|
3969 |
"node_modules/tslib": {
|
3970 |
+
"version": "2.6.1",
|
3971 |
+
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz",
|
3972 |
+
"integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig=="
|
3973 |
},
|
3974 |
"node_modules/tsutils": {
|
3975 |
"version": "3.21.0",
|
web/package.json
CHANGED
@@ -9,6 +9,7 @@
|
|
9 |
"lint": "next lint"
|
10 |
},
|
11 |
"dependencies": {
|
|
|
12 |
"@types/node": "20.4.2",
|
13 |
"@types/react": "18.2.15",
|
14 |
"@types/react-dom": "18.2.7",
|
@@ -20,6 +21,7 @@
|
|
20 |
"react": "18.2.0",
|
21 |
"react-dom": "18.2.0",
|
22 |
"tailwindcss": "3.3.3",
|
|
|
23 |
"typescript": "5.1.6"
|
24 |
}
|
25 |
}
|
|
|
9 |
"lint": "next lint"
|
10 |
},
|
11 |
"dependencies": {
|
12 |
+
"@heroicons/react": "^2.0.18",
|
13 |
"@types/node": "20.4.2",
|
14 |
"@types/react": "18.2.15",
|
15 |
"@types/react-dom": "18.2.7",
|
|
|
21 |
"react": "18.2.0",
|
22 |
"react-dom": "18.2.0",
|
23 |
"tailwindcss": "3.3.3",
|
24 |
+
"tone": "^14.7.77",
|
25 |
"typescript": "5.1.6"
|
26 |
}
|
27 |
}
|
web/public/test-clips/skibidi-toilet.mp3
ADDED
Binary file (186 kB). View file
|
|
web/src/app/audio-clip.tsx
ADDED
@@ -0,0 +1,133 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import * as Tone from "tone";
|
2 |
+
import { useState, useRef, useEffect} from "react";
|
3 |
+
import { PlayCircleIcon, StopCircleIcon } from '@heroicons/react/24/solid'
|
4 |
+
|
5 |
+
|
6 |
+
const SAMPLE_RATE = 32000;
|
7 |
+
const REVERB_ROOM = 0.8;
|
8 |
+
const GAIN_AMOUNT = -10;
|
9 |
+
const LENGTH = 10;
|
10 |
+
function AudioClip(props: any) {
|
11 |
+
const [reverbAmount, setReverbAmount] = useState(50);
|
12 |
+
const [playing, setPlaying] = useState(false);
|
13 |
+
const [progress, setProgress] = useState(0);
|
14 |
+
|
15 |
+
const player = useRef<Tone.Player | null>(null);
|
16 |
+
const reverb = useRef<Tone.Freeverb | null>(null);
|
17 |
+
const gain = useRef<Tone.Gain<"decibels"> | null>(null);
|
18 |
+
// const interval = useRef<any>(null);
|
19 |
+
|
20 |
+
|
21 |
+
useEffect(() => {
|
22 |
+
player.current = new Tone.Player(props.src.filename)
|
23 |
+
reverb.current = new Tone.Freeverb(REVERB_ROOM);
|
24 |
+
gain.current = new Tone.Gain(GAIN_AMOUNT, "decibels");
|
25 |
+
|
26 |
+
player.current.connect(reverb.current);
|
27 |
+
player.current.volume.value = -6;
|
28 |
+
reverb.current.connect(gain.current);
|
29 |
+
gain.current.toDestination();
|
30 |
+
|
31 |
+
player.current.loop = true;
|
32 |
+
player.current.setLoopPoints(0, 10);
|
33 |
+
|
34 |
+
|
35 |
+
}, []);
|
36 |
+
|
37 |
+
|
38 |
+
useEffect(() => {
|
39 |
+
const interval = setInterval(() => {
|
40 |
+
if (player.current) {
|
41 |
+
if (progress >= 100 || !playing) {
|
42 |
+
setProgress(0);
|
43 |
+
} else {
|
44 |
+
setProgress(progress + 1);
|
45 |
+
}
|
46 |
+
}
|
47 |
+
}, 90);
|
48 |
+
return () => clearInterval(interval);
|
49 |
+
}, [playing, progress]);
|
50 |
+
|
51 |
+
|
52 |
+
|
53 |
+
const handleClick = async () => {
|
54 |
+
await Tone.start();
|
55 |
+
if (player.current && player.current.state === "started") {
|
56 |
+
player.current.stop();
|
57 |
+
setPlaying(false);
|
58 |
+
|
59 |
+
|
60 |
+
} else if (player.current && player.current.state === "stopped") {
|
61 |
+
player.current.start();
|
62 |
+
setPlaying(true);
|
63 |
+
|
64 |
+
} else {
|
65 |
+
console.log("player not ready");
|
66 |
+
setPlaying(false);
|
67 |
+
}
|
68 |
+
|
69 |
+
};
|
70 |
+
|
71 |
+
|
72 |
+
|
73 |
+
const handleDownload = async () => {
|
74 |
+
await Tone.start();
|
75 |
+
await Tone.Offline(
|
76 |
+
() => {
|
77 |
+
const offlinePlayer = new Tone.Player(props.src)
|
78 |
+
const offlineReverb = new Tone.Freeverb(REVERB_ROOM)
|
79 |
+
const offlineGain = new Tone.Gain(GAIN_AMOUNT, "decibels").toDestination();
|
80 |
+
offlinePlayer.connect(offlineReverb);
|
81 |
+
offlineReverb.connect(offlineGain);
|
82 |
+
Tone.Transport.start();
|
83 |
+
Tone.Transport.scheduleOnce(() => {
|
84 |
+
Tone.Transport.stop();
|
85 |
+
}, offlinePlayer.buffer.duration);
|
86 |
+
},
|
87 |
+
LENGTH,
|
88 |
+
1,
|
89 |
+
SAMPLE_RATE
|
90 |
+
).then((renderedBuffer) => {
|
91 |
+
const url = URL.createObjectURL(
|
92 |
+
new Blob([renderedBuffer.getChannelData(0)], { type: "audio/wav" })
|
93 |
+
);
|
94 |
+
const downloadLink = document.createElement("a");
|
95 |
+
downloadLink.href = url;
|
96 |
+
downloadLink.download = "processed_audio.wav";
|
97 |
+
downloadLink.click();
|
98 |
+
});
|
99 |
+
};
|
100 |
+
|
101 |
+
const handleReverbChange = (event: any) => {
|
102 |
+
setReverbAmount(event.target.value);
|
103 |
+
if (reverb.current)
|
104 |
+
reverb.current.wet.value = parseInt(event.target.value) / 100;
|
105 |
+
}
|
106 |
+
let width = `w-[${progress}%]`;
|
107 |
+
return (
|
108 |
+
<div className="flex flex-col justify-center p-5" >
|
109 |
+
<div className="flex items-center">
|
110 |
+
{playing ?
|
111 |
+
<StopCircleIcon className="h-6 w-6 text-blue-500 cursor-pointer mr-2 hover:text-blue-600" onClick={handleClick}/> :
|
112 |
+
<PlayCircleIcon className="h-6 w-6 text-blue-500 cursor-pointer mr-2 hover:text-blue-600" onClick={handleClick}/>
|
113 |
+
}
|
114 |
+
<progress value={progress} max="100"/>
|
115 |
+
</div>
|
116 |
+
<div className="flex justify-around text-gray-500 my-2">
|
117 |
+
<div>{props.src.key}</div>
|
118 |
+
<div>{props.src.bpm}</div>
|
119 |
+
</div>
|
120 |
+
<div className="flex flex-col justify-center my-2">
|
121 |
+
<label className="flex justify-center my-2">Reverb</label>
|
122 |
+
<input className="cursor-pointer" type="range" value={reverbAmount} onChange={handleReverbChange} min={0} max={100}/>
|
123 |
+
</div>
|
124 |
+
<button
|
125 |
+
className="flex items-center justify-center border-2 border-black rounded-lg px-10 py-1 hover:bg-black hover:text-white my-2 dark:bg-gray-800 dark:text-white dark:hover:bg-white dark:hover:text-black"
|
126 |
+
onClick={handleDownload}
|
127 |
+
>
|
128 |
+
Download
|
129 |
+
</button>
|
130 |
+
</div>
|
131 |
+
);
|
132 |
+
}
|
133 |
+
export default AudioClip;
|
web/src/app/globals.css
CHANGED
@@ -18,10 +18,21 @@
|
|
18 |
|
19 |
body {
|
20 |
color: rgb(var(--foreground-rgb));
|
21 |
-
background: linear-gradient(
|
22 |
-
to bottom,
|
23 |
transparent,
|
24 |
-
rgb(var(--background-end-rgb))
|
25 |
-
)
|
26 |
-
rgb(var(--background-start-rgb));
|
27 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
|
19 |
body {
|
20 |
color: rgb(var(--foreground-rgb));
|
21 |
+
background: linear-gradient(to bottom,
|
|
|
22 |
transparent,
|
23 |
+
rgb(var(--background-end-rgb))) rgb(var(--background-start-rgb));
|
|
|
|
|
24 |
}
|
25 |
+
|
26 |
+
progress[value]::-webkit-progress-value {
|
27 |
+
background-image:
|
28 |
+
-webkit-linear-gradient(-45deg,
|
29 |
+
transparent 33%, rgba(0, 0, 0, .1) 33%,
|
30 |
+
rgba(0, 0, 0, .1) 66%, transparent 66%),
|
31 |
+
-webkit-linear-gradient(top,
|
32 |
+
rgba(255, 255, 255, .25),
|
33 |
+
rgba(0, 0, 0, .25)),
|
34 |
+
-webkit-linear-gradient(left, #09c, #f44);
|
35 |
+
|
36 |
+
border-radius: 2px;
|
37 |
+
background-size: 35px 20px, 100% 100%, 100% 100%;
|
38 |
+
}
|
web/src/app/page.tsx
CHANGED
@@ -1,22 +1,13 @@
|
|
1 |
"use client";
|
2 |
|
3 |
-
import Image from "next/image";
|
4 |
import { useState } from "react";
|
|
|
5 |
|
6 |
export default function Home() {
|
7 |
-
const [
|
8 |
-
const [BPM, setBPM] = useState(120);
|
9 |
-
const [style, setStyle] = useState("");
|
10 |
const [loading, setLoading] = useState(false);
|
11 |
const [finished, setFinished] = useState(false);
|
12 |
-
const [clips, setClips] = useState<
|
13 |
-
|
14 |
-
function onLengthChange(e: React.ChangeEvent<HTMLInputElement>) {
|
15 |
-
setLength(Number(e.target.value));
|
16 |
-
}
|
17 |
-
function onBPMChange(e: React.ChangeEvent<HTMLInputElement>) {
|
18 |
-
setBPM(Number(e.target.value));
|
19 |
-
}
|
20 |
|
21 |
function handleStyleClick(style: string) {
|
22 |
setStyle(style);
|
@@ -34,7 +25,7 @@ export default function Home() {
|
|
34 |
setFinished(true);
|
35 |
setLoading(false);
|
36 |
setClips(testClips);
|
37 |
-
},
|
38 |
}
|
39 |
|
40 |
function downloadFile(url: string) {
|
@@ -64,7 +55,7 @@ export default function Home() {
|
|
64 |
<main className="flex min-h-screen flex-col items-center">
|
65 |
<h1 className="text-6xl font-bold text-center mt-10">SoundSauce</h1>
|
66 |
<div className="flex flex-col items-center justify-center">
|
67 |
-
Your unique flavor
|
68 |
</div>
|
69 |
<div className="flex flex-col items-center justify-center m-20 w-full">
|
70 |
<div>Select a style</div>
|
@@ -72,11 +63,11 @@ export default function Home() {
|
|
72 |
{styles.map((s) => {
|
73 |
let background = "bg-inherit";
|
74 |
if (s === style) {
|
75 |
-
background = "bg-white";
|
76 |
}
|
77 |
return (
|
78 |
<button
|
79 |
-
className={`flex items-center justify-center border-2 border-white rounded-lg px-4 py-1 hover:bg-white ${background}`}
|
80 |
onClick={() => handleStyleClick(s)}
|
81 |
key={s}
|
82 |
>
|
@@ -85,32 +76,6 @@ export default function Home() {
|
|
85 |
);
|
86 |
})}
|
87 |
</div>
|
88 |
-
<div className="flex justify-around w-1/3 m-5">
|
89 |
-
<div className="flex flex-col items-center justify-center">
|
90 |
-
<div>Length</div>
|
91 |
-
<input
|
92 |
-
type="range"
|
93 |
-
min={1}
|
94 |
-
max={20}
|
95 |
-
step={1}
|
96 |
-
value={length}
|
97 |
-
onChange={onLengthChange}
|
98 |
-
/>
|
99 |
-
<div>{length} seconds</div>
|
100 |
-
</div>
|
101 |
-
<div className="flex flex-col items-center justify-center">
|
102 |
-
<div>BPM</div>
|
103 |
-
<input
|
104 |
-
type="range"
|
105 |
-
min={60}
|
106 |
-
max={180}
|
107 |
-
step={1}
|
108 |
-
value={BPM}
|
109 |
-
onChange={onBPMChange}
|
110 |
-
/>
|
111 |
-
<div>{BPM}</div>
|
112 |
-
</div>
|
113 |
-
</div>
|
114 |
<button
|
115 |
className="flex items-center justify-center border-2 border-green-500 rounded-lg px-10 py-1 hover:bg-green-500"
|
116 |
onClick={handleGenerationStart}
|
@@ -130,20 +95,6 @@ export default function Home() {
|
|
130 |
);
|
131 |
}
|
132 |
|
133 |
-
function AudioClip(props: any) {
|
134 |
-
return (
|
135 |
-
<div className="flex flex-col justify-center p-5">
|
136 |
-
<audio controls src={props.src} />
|
137 |
-
<button
|
138 |
-
className="flex items-center justify-center border-2 border-black rounded-lg px-10 py-1 mt-2 hover:bg-black hover:text-white"
|
139 |
-
onClick={() => props.downloadFile(props.src)}
|
140 |
-
>
|
141 |
-
Download
|
142 |
-
</button>
|
143 |
-
</div>
|
144 |
-
);
|
145 |
-
}
|
146 |
-
|
147 |
let styles = [
|
148 |
"Travis Scott",
|
149 |
"Drake",
|
@@ -154,7 +105,22 @@ let styles = [
|
|
154 |
];
|
155 |
|
156 |
let testClips = [
|
157 |
-
|
158 |
-
|
159 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
160 |
];
|
|
|
1 |
"use client";
|
2 |
|
|
|
3 |
import { useState } from "react";
|
4 |
+
import AudioClip from "./audio-clip";
|
5 |
|
6 |
export default function Home() {
|
7 |
+
const [style, setStyle] = useState("d");
|
|
|
|
|
8 |
const [loading, setLoading] = useState(false);
|
9 |
const [finished, setFinished] = useState(false);
|
10 |
+
const [clips, setClips] = useState<Object[]>([]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
|
12 |
function handleStyleClick(style: string) {
|
13 |
setStyle(style);
|
|
|
25 |
setFinished(true);
|
26 |
setLoading(false);
|
27 |
setClips(testClips);
|
28 |
+
}, 1);
|
29 |
}
|
30 |
|
31 |
function downloadFile(url: string) {
|
|
|
55 |
<main className="flex min-h-screen flex-col items-center">
|
56 |
<h1 className="text-6xl font-bold text-center mt-10">SoundSauce</h1>
|
57 |
<div className="flex flex-col items-center justify-center">
|
58 |
+
Your unique melody flavor
|
59 |
</div>
|
60 |
<div className="flex flex-col items-center justify-center m-20 w-full">
|
61 |
<div>Select a style</div>
|
|
|
63 |
{styles.map((s) => {
|
64 |
let background = "bg-inherit";
|
65 |
if (s === style) {
|
66 |
+
background = "bg-white dark:text-black";
|
67 |
}
|
68 |
return (
|
69 |
<button
|
70 |
+
className={`flex items-center justify-center border-2 border-white rounded-lg px-4 py-1 dark:hover:text-black hover:bg-white ${background}`}
|
71 |
onClick={() => handleStyleClick(s)}
|
72 |
key={s}
|
73 |
>
|
|
|
76 |
);
|
77 |
})}
|
78 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
79 |
<button
|
80 |
className="flex items-center justify-center border-2 border-green-500 rounded-lg px-10 py-1 hover:bg-green-500"
|
81 |
onClick={handleGenerationStart}
|
|
|
95 |
);
|
96 |
}
|
97 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
98 |
let styles = [
|
99 |
"Travis Scott",
|
100 |
"Drake",
|
|
|
105 |
];
|
106 |
|
107 |
let testClips = [
|
108 |
+
{
|
109 |
+
filename: "./test-clips/chipmunk.wav",
|
110 |
+
key: "G Maj",
|
111 |
+
bpm: 120,
|
112 |
+
length: 10,
|
113 |
+
},
|
114 |
+
{
|
115 |
+
filename: "./test-clips/skibidi-toilet.mp3",
|
116 |
+
key: "A Min",
|
117 |
+
bpm: 144,
|
118 |
+
length: 11.5,
|
119 |
+
},
|
120 |
+
{
|
121 |
+
filename: "./test-clips/chipmunk.wav",
|
122 |
+
key: "G Maj",
|
123 |
+
bpm: 120,
|
124 |
+
length: 10
|
125 |
+
},
|
126 |
];
|