camenduru commited on
Commit
e335e0e
β€’
1 Parent(s): 4ff60bb

Update .eslintrc.json, .gitattributes, and 71 more files...

Browse files
This view is limited to 50 files because it contains too many changes. Β  See raw diff
Files changed (50) hide show
  1. .eslintrc.json +0 -4
  2. .gitattributes +0 -41
  3. .gitignore +0 -36
  4. Dockerfile +2 -3
  5. LICENSE +0 -16
  6. README.md +0 -10
  7. components/AudioPlayer.tsx +0 -133
  8. components/DebugView.tsx +0 -88
  9. components/FallingBehindWarning.tsx +0 -12
  10. components/HeightMapImage.tsx +0 -52
  11. components/ImagePlane.tsx +0 -25
  12. components/Info.tsx +0 -119
  13. components/ModelInference.tsx +0 -214
  14. components/PageHead.tsx +0 -49
  15. components/Pause.tsx +0 -41
  16. components/PromptEntry.tsx +0 -271
  17. components/PromptPanel.tsx +0 -360
  18. components/RotatingBox.tsx +0 -41
  19. components/Settings.tsx +0 -289
  20. components/Share.tsx +0 -319
  21. components/SpectrogramViewer.tsx +0 -110
  22. components/ThreeCanvas.tsx +0 -39
  23. components/about/CaptionedImage.tsx +0 -25
  24. components/about/ToApp.tsx +0 -44
  25. external/unmute.js +0 -340
  26. next.config.js +0 -6
  27. package-lock.json +0 -0
  28. pages/_app.tsx +0 -14
  29. pages/about.tsx +0 -584
  30. pages/api/baseten.js +0 -17
  31. pages/api/server.js +0 -17
  32. pages/index.tsx +0 -384
  33. postcss.config.js +0 -6
  34. public/about/acoustic_folk_fiddle_solo.mp3 +0 -0
  35. public/about/acoustic_folk_fiddle_solo.png +0 -0
  36. public/about/arabic_gospel.mp3 +0 -0
  37. public/about/astronaut.gif +0 -3
  38. public/about/church_bells_to_electronic_beats.mp3 +0 -0
  39. public/about/detroit_rap_to_jazz_denoising_0_6_seed_50.mp3 +0 -0
  40. public/about/fantasy_ballad_to_teen_boy_pop_star.mp3 +0 -0
  41. public/about/fourier_transform.png +0 -0
  42. public/about/funky_sax.gif +0 -3
  43. public/about/funky_sax.mp3 +0 -0
  44. public/about/funky_sax.png +0 -0
  45. public/about/funky_sax_to_piano.mp3 +0 -0
  46. public/about/funky_sax_to_piano.png +0 -0
  47. public/about/hand_drawn.mp3 +0 -0
  48. public/about/hand_drawn_spectrogram.png +0 -0
  49. public/about/happy_cows_interpolation.gif +0 -3
  50. public/about/img2img_example.png +0 -3
.eslintrc.json DELETED
@@ -1,4 +0,0 @@
1
- {
2
- "extends": "next/core-web-vitals",
3
- "rules": { "react/no-unescaped-entities": 0 }
4
- }
 
 
 
 
.gitattributes DELETED
@@ -1,41 +0,0 @@
1
- *.7z filter=lfs diff=lfs merge=lfs -text
2
- *.arrow filter=lfs diff=lfs merge=lfs -text
3
- *.bin filter=lfs diff=lfs merge=lfs -text
4
- *.bz2 filter=lfs diff=lfs merge=lfs -text
5
- *.ckpt filter=lfs diff=lfs merge=lfs -text
6
- *.ftz filter=lfs diff=lfs merge=lfs -text
7
- *.gz filter=lfs diff=lfs merge=lfs -text
8
- *.h5 filter=lfs diff=lfs merge=lfs -text
9
- *.joblib filter=lfs diff=lfs merge=lfs -text
10
- *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
- *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
- *.model filter=lfs diff=lfs merge=lfs -text
13
- *.msgpack filter=lfs diff=lfs merge=lfs -text
14
- *.npy filter=lfs diff=lfs merge=lfs -text
15
- *.npz filter=lfs diff=lfs merge=lfs -text
16
- *.onnx filter=lfs diff=lfs merge=lfs -text
17
- *.ot filter=lfs diff=lfs merge=lfs -text
18
- *.parquet filter=lfs diff=lfs merge=lfs -text
19
- *.pb filter=lfs diff=lfs merge=lfs -text
20
- *.pickle filter=lfs diff=lfs merge=lfs -text
21
- *.pkl filter=lfs diff=lfs merge=lfs -text
22
- *.pt filter=lfs diff=lfs merge=lfs -text
23
- *.pth filter=lfs diff=lfs merge=lfs -text
24
- *.rar filter=lfs diff=lfs merge=lfs -text
25
- *.safetensors filter=lfs diff=lfs merge=lfs -text
26
- saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
- *.tar.* filter=lfs diff=lfs merge=lfs -text
28
- *.tflite filter=lfs diff=lfs merge=lfs -text
29
- *.tgz filter=lfs diff=lfs merge=lfs -text
30
- *.wasm filter=lfs diff=lfs merge=lfs -text
31
- *.xz filter=lfs diff=lfs merge=lfs -text
32
- *.zip filter=lfs diff=lfs merge=lfs -text
33
- *.zst filter=lfs diff=lfs merge=lfs -text
34
- *tfevents* filter=lfs diff=lfs merge=lfs -text
35
- public/about/astronaut.gif filter=lfs diff=lfs merge=lfs -text
36
- public/about/funky_sax.gif filter=lfs diff=lfs merge=lfs -text
37
- public/about/happy_cows_interpolation.gif filter=lfs diff=lfs merge=lfs -text
38
- public/about/img2img_example.png filter=lfs diff=lfs merge=lfs -text
39
- public/about/latent_space_interpolation.png filter=lfs diff=lfs merge=lfs -text
40
- public/about/spectrogram_label.png filter=lfs diff=lfs merge=lfs -text
41
- public/about/web_app_screenshot.png filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
.gitignore DELETED
@@ -1,36 +0,0 @@
1
- # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2
-
3
- # dependencies
4
- /node_modules
5
- /.pnp
6
- .pnp.js
7
- .env
8
- # testing
9
- /coverage
10
-
11
- # next.js
12
- /.next/
13
- /out/
14
-
15
- # production
16
- /build
17
-
18
- # misc
19
- .DS_Store
20
- *.pem
21
-
22
- # debug
23
- npm-debug.log*
24
- yarn-debug.log*
25
- yarn-error.log*
26
- .pnpm-debug.log*
27
-
28
- # local env files
29
- .env*.local
30
-
31
- # vercel
32
- .vercel
33
-
34
- # typescript
35
- *.tsbuildinfo
36
- next-env.d.ts
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Dockerfile CHANGED
@@ -6,9 +6,8 @@ WORKDIR /app
6
  RUN chown -R app /app
7
  RUN chmod -R 777 /app
8
  USER app
9
- # RUN git clone https://github.com/riffusion/riffusion-app ./
10
- # COPY package.json package-lock.json ./
11
- COPY . ./
12
  RUN npm ci
13
  COPY . .
14
 
6
  RUN chown -R app /app
7
  RUN chmod -R 777 /app
8
  USER app
9
+ RUN git clone https://github.com/riffusion/riffusion-app ./
10
+ COPY package.json ./
 
11
  RUN npm ci
12
  COPY . .
13
 
LICENSE DELETED
@@ -1,16 +0,0 @@
1
- Copyright 2022 Hayk Martiros and Seth Forsgren
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
4
- associated documentation files (the "Software"), to deal in the Software without restriction,
5
- including without limitation the rights to use, copy, modify, merge, publish, distribute,
6
- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
7
- furnished to do so, subject to the following conditions:
8
-
9
- The above copyright notice and this permission notice shall be included in all copies or substantial
10
- portions of the Software.
11
-
12
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
13
- NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
14
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
15
- OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16
- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
README.md DELETED
@@ -1,10 +0,0 @@
1
- ---
2
- title: Test2
3
- emoji: 🌍
4
- colorFrom: purple
5
- colorTo: blue
6
- sdk: docker
7
- pinned: false
8
- ---
9
-
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
components/AudioPlayer.tsx DELETED
@@ -1,133 +0,0 @@
1
- import { useEffect, useState } from "react";
2
-
3
- import * as Tone from "tone";
4
-
5
- import { InferenceResult } from "../types";
6
-
7
- interface AudioPlayerProps {
8
- paused: boolean;
9
- inferenceResults: InferenceResult[];
10
- nowPlayingCallback: (result: InferenceResult, playerTime: number) => void;
11
- playerIsBehindCallback: (isBehind: boolean) => void;
12
- }
13
-
14
- /**
15
- * Audio player with Tone.js
16
- *
17
- * TODO(hayk): Look into https://github.com/E-Kuerschner/useAudioPlayer as an alternative.
18
- */
19
- export default function AudioPlayer({
20
- paused,
21
- inferenceResults,
22
- nowPlayingCallback,
23
- playerIsBehindCallback,
24
- }: AudioPlayerProps) {
25
- const [tonePlayer, setTonePlayer] = useState<Tone.Player>(null);
26
-
27
- const [numClipsPlayed, setNumClipsPlayed] = useState(0);
28
- const [prevNumClipsPlayed, setPrevNumClipsPlayed] = useState(0);
29
-
30
- const [resultCounter, setResultCounter] = useState(0);
31
-
32
- // On load, create a player synced to the tone transport
33
- useEffect(() => {
34
- if (tonePlayer) {
35
- return;
36
- }
37
-
38
- if (inferenceResults.length === 0) {
39
- return;
40
- }
41
-
42
- const result = inferenceResults[0];
43
-
44
- const player = new Tone.Player(result.audio, () => {
45
- player.loop = true;
46
- player.sync().start(0);
47
-
48
- // Set up a callback to increment numClipsPlayed at the edge of each clip
49
- const bufferLength = player.sampleTime * player.buffer.length;
50
-
51
- // TODO(hayk): Set this callback up to vary each time using duration_s
52
- Tone.Transport.scheduleRepeat((time) => {
53
- setNumClipsPlayed((n) => n + 1);
54
- }, bufferLength);
55
-
56
- setTonePlayer(player);
57
-
58
- // Make further load callbacks do nothing.
59
- player.buffer.onload = () => {};
60
- }).toDestination();
61
- }, [tonePlayer, inferenceResults]);
62
-
63
- // On play/pause button, play/pause the audio with the tone transport
64
- useEffect(() => {
65
- if (!paused) {
66
- if (Tone.context.state == "suspended") {
67
- Tone.context.resume();
68
- }
69
-
70
- if (tonePlayer) {
71
- Tone.Transport.start();
72
- }
73
- } else {
74
- if (tonePlayer) {
75
- Tone.Transport.pause();
76
- }
77
- }
78
- }, [paused, tonePlayer]);
79
-
80
- // If there is a new clip, switch to it
81
- useEffect(() => {
82
- if (numClipsPlayed == prevNumClipsPlayed) {
83
- return;
84
- }
85
-
86
- const maxResultCounter = Math.max(
87
- ...inferenceResults.map((r) => r.counter)
88
- );
89
-
90
- if (maxResultCounter < resultCounter) {
91
- console.info(
92
- "No new result available, looping previous clip",
93
- resultCounter,
94
- maxResultCounter
95
- );
96
- playerIsBehindCallback(true);
97
- return;
98
- }
99
-
100
- playerIsBehindCallback(false);
101
-
102
- const result = inferenceResults.find(
103
- (r: InferenceResult) => r.counter == resultCounter
104
- );
105
-
106
- setResultCounter((c) => c + 1);
107
-
108
- tonePlayer.load(result.audio).then(() => {
109
- // Re-jigger the transport so it stops playing old buffers. It seems like this doesn't
110
- // introduce a gap, but watch out for that.
111
- Tone.Transport.pause();
112
- if (!paused) {
113
- Tone.Transport.start();
114
- }
115
-
116
- const playerTime = Tone.Transport.seconds;
117
- nowPlayingCallback(result, playerTime);
118
- });
119
-
120
- setPrevNumClipsPlayed(numClipsPlayed);
121
- }, [
122
- numClipsPlayed,
123
- prevNumClipsPlayed,
124
- resultCounter,
125
- inferenceResults,
126
- paused,
127
- nowPlayingCallback,
128
- playerIsBehindCallback,
129
- tonePlayer,
130
- ]);
131
-
132
- return null;
133
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
components/DebugView.tsx DELETED
@@ -1,88 +0,0 @@
1
- import { Dialog } from "@headlessui/react";
2
- import { useState } from "react";
3
- import { ImStatsBars } from "react-icons/im";
4
- import styled from "styled-components";
5
-
6
- import { InferenceResult, PromptInput } from "../types";
7
-
8
- interface DebugViewProps {
9
- promptInputs: PromptInput[];
10
- inferenceResults: InferenceResult[];
11
- nowPlayingResult: InferenceResult;
12
- open: boolean;
13
- setOpen: (open: boolean) => void;
14
- }
15
-
16
- const ModalContainer = styled.div`
17
- position: absolute;
18
- top: 0;
19
- left: 0;
20
- width: 100vw;
21
- height: 100vh;
22
- background: rgba(0, 0, 0, 0.5);
23
- display: flex;
24
- align-items: center;
25
- justify-content: center;
26
- `;
27
-
28
- export default function DebugView({
29
- promptInputs,
30
- inferenceResults,
31
- nowPlayingResult,
32
- open,
33
- setOpen,
34
- }: DebugViewProps) {
35
- return (
36
- <>
37
- <Dialog
38
- open={open}
39
- onClose={() => setOpen(false)}
40
- as="div"
41
- className="fixed inset-0 z-30"
42
- key="debug-dialog"
43
- >
44
- <ModalContainer key="debug-modal">
45
- <div className="px-4 text-center text-sm whitespace-nowrap h-[40rem] w-[70rem] overflow-x-scroll">
46
- <div className="my-8 inline-block transform rounded-2xl bg-white p-6 text-left align-middle shadow-xl transition-all">
47
- <Dialog.Panel>
48
- <h2 className="text-xl font-medium leading-6 text-gray-900 pb-2">
49
- Prompt Inputs
50
- </h2>
51
- <div className="mt-4 font-mono">
52
- {promptInputs.map((promptInput) => (
53
- <div key={promptInput.prompt}>
54
- "{promptInput.prompt}" - {promptInput.transitionCounter}
55
- </div>
56
- ))}
57
- </div>
58
- <h2 className="text-xl font-medium leading-6 text-gray-900 pb-2">
59
- Inference Results
60
- </h2>
61
- <div className="mt-4 font-mono">
62
- <ul>
63
- {inferenceResults.map((result) => (
64
- <li
65
- key={result.counter}
66
- className={
67
- result.counter === nowPlayingResult?.counter
68
- ? "text-red-700"
69
- : "text-black"
70
- }
71
- >
72
- <b>#{result.counter}</b> - Alpha{" "}
73
- {result.input.alpha.toFixed(2)} from ("
74
- {result.input.start.prompt}", {result.input.start.seed})
75
- to ("
76
- {result.input.end.prompt}", {result.input.end.seed})
77
- </li>
78
- ))}
79
- </ul>
80
- </div>
81
- </Dialog.Panel>
82
- </div>
83
- </div>
84
- </ModalContainer>
85
- </Dialog>
86
- </>
87
- );
88
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
components/FallingBehindWarning.tsx DELETED
@@ -1,12 +0,0 @@
1
- export default function FallingBehindWarning() {
2
- return (
3
- <div
4
- className="fixed z-20 top-8 left-12 bg-yellow-50 border border-yellow-600 text-yellow-700 px-4 py-3 rounded"
5
- role="alert"
6
- >
7
- <span className="block sm:inline mr-8">
8
- <b>Uh oh!</b> Servers are behind, scaling up...
9
- </span>
10
- </div>
11
- );
12
- }
 
 
 
 
 
 
 
 
 
 
 
 
components/HeightMapImage.tsx DELETED
@@ -1,52 +0,0 @@
1
- import { DoubleSide, RepeatWrapping, sRGBEncoding } from "three";
2
- import {
3
- useTexture,
4
- } from "@react-three/drei";
5
-
6
- import { vertexShader, fragmentShader } from "../shaders";
7
-
8
- interface HeightMapImageProps {
9
- url: string;
10
- position: [number, number, number];
11
- rotation: [number, number, number];
12
- scale: [number, number, number];
13
- }
14
-
15
- export default function HeightMapImage(props: HeightMapImageProps) {
16
- const url = props.url;
17
-
18
- // Load the heightmap image
19
- const heightMap = useTexture(url);
20
- heightMap.wrapS = RepeatWrapping;
21
- heightMap.wrapT = RepeatWrapping;
22
-
23
- // Load the texture map
24
- const textureMap = useTexture(url);
25
- textureMap.wrapS = RepeatWrapping;
26
- textureMap.wrapT = RepeatWrapping;
27
-
28
- return (
29
- <mesh
30
- position={props.position}
31
- rotation={props.rotation}
32
- scale={props.scale}
33
- >
34
- {/* TODO hayk reduce */}
35
- <planeGeometry args={[1, 1, 256, 256]} />
36
- <shaderMaterial
37
- uniforms={{
38
- // Feed the heightmap
39
- bumpTexture: { value: heightMap },
40
- // Feed the scaling constant for the heightmap
41
- bumpScale: { value: -0.5 },
42
- // Feed the texture map
43
- terrainTexture: { value: textureMap },
44
- }}
45
- // Feed the shaders as strings
46
- vertexShader={vertexShader}
47
- fragmentShader={fragmentShader}
48
- side={DoubleSide}
49
- />
50
- </mesh>
51
- );
52
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
components/ImagePlane.tsx DELETED
@@ -1,25 +0,0 @@
1
- import * as THREE from "three";
2
- import React, { Suspense } from "react";
3
- import { useLoader } from "@react-three/fiber";
4
-
5
- interface ImagePlaneProps {
6
- url: string;
7
- height: number;
8
- duration: number;
9
- }
10
-
11
- /**
12
- * Draw an image on a plane geometry.
13
- */
14
- export default function ImagePlane(props: ImagePlaneProps) {
15
- const texture = useLoader(THREE.TextureLoader, props.url);
16
-
17
- return (
18
- <Suspense fallback={null}>
19
- <mesh rotation-z={-Math.PI / 2} position-y={props.height}>
20
- <planeGeometry attach="geometry" args={[props.duration, 5]} />
21
- <meshBasicMaterial attach="material" map={texture} />
22
- </mesh>
23
- </Suspense>
24
- );
25
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
components/Info.tsx DELETED
@@ -1,119 +0,0 @@
1
- import { Dialog, Transition } from "@headlessui/react";
2
- import { Fragment, useState } from "react";
3
- import { FiInfo } from "react-icons/fi";
4
- import styled, { css } from "styled-components";
5
-
6
- const ModalContainer = styled.div`
7
- position: absolute;
8
- top: 0;
9
- left: 0;
10
- width: 100vw;
11
- height: 100vh;
12
- background: rgba(0, 0, 0, 0.5);
13
- display: flex;
14
- align-items: center;
15
- justify-content: center;
16
- `;
17
-
18
- export default function Info() {
19
- const [open, setOpen] = useState(false);
20
-
21
- var classNameCondition = ""
22
- if (open) {
23
- classNameCondition = "fixed z-20 top-44 right-4 md:top-48 md:right-8 bg-sky-400 w-14 h-14 rounded-full drop-shadow-lg flex justify-center items-center text-white text-2xl hover:bg-sky-500 hover:drop-shadow-2xl"
24
- } else {
25
- classNameCondition = "fixed z-20 top-44 right-4 md:top-48 md:right-8 bg-slate-100 w-14 h-14 rounded-full drop-shadow-lg flex justify-center items-center text-sky-900 text-2xl hover:text-white hover:bg-sky-600 hover:drop-shadow-2xl"
26
- }
27
-
28
- return (
29
- <>
30
- <button
31
- title="Info"
32
- className={classNameCondition}
33
- onClick={() => setOpen(true)}
34
- >
35
- <FiInfo />
36
- </button>
37
-
38
- <Transition appear show={open} as={Fragment}>
39
- <Dialog
40
- as="div"
41
- className="fixed inset-0 z-20 overflow-y-auto"
42
- onClose={() => setOpen(false)}
43
- >
44
- <div className="min-h-screen px-4 text-center">
45
- <Transition.Child
46
- as={Fragment}
47
- enter="ease-out duration-300"
48
- enterFrom="opacity-0"
49
- enterTo="opacity-100"
50
- leave="ease-in duration-200"
51
- leaveFrom="opacity-100"
52
- leaveTo="opacity-0"
53
- >
54
- <Dialog.Overlay className="fixed inset-0" />
55
- </Transition.Child>
56
-
57
- <span
58
- className="inline-block h-screen align-middle"
59
- aria-hidden="true"
60
- >
61
- &#8203;
62
- </span>
63
- <Transition.Child
64
- as={Fragment}
65
- enter="ease-out duration-300"
66
- enterFrom="opacity-0 scale-95"
67
- enterTo="opacity-100 scale-100"
68
- leave="ease-in duration-200"
69
- leaveFrom="opacity-100 scale-100"
70
- leaveTo="opacity-0 scale-95"
71
- >
72
- <ModalContainer>
73
- <div className="my-8 inline-block w-full max-w-md transform overflow-hidden rounded-2xl bg-white p-6 text-left align-middle shadow-xl transition-all">
74
- <Dialog.Title
75
- as="h1"
76
- className="text-3xl font-medium leading-6 text-gray-900 pb-2"
77
- >
78
- Welcome to Riffusion
79
- </Dialog.Title>
80
- <div className="mt-4">
81
- <p className="text-sm text-gray-500">
82
- Riffusion generates endless new jams from any text prompt. Try typing in your favorite artist or genre, and you'll hear the music gradually transform.<br></br>
83
- <br></br>
84
- The diffusion model first creates images from your prompt, and then converts them into music. Learn more about surfing the latent space of sound below.<br></br>
85
- </p>
86
- </div>
87
-
88
- <div className="mt-6">
89
-
90
- <button
91
- className="relative inline-flex items-center justify-center p-0.5 mb-2 mr-2 overflow-hidden text-sm font-medium text-gray-900 rounded-lg group bg-sky-500 group-hover:from-sky-600 group-hover:to-sky-500 hover:text-white"
92
- onClick={() => {
93
- window.open("/about", "_blank");
94
- setOpen(false);
95
- }}
96
- >
97
- <span className="relative px-5 py-2 transition-all ease-in duration-75 bg-white rounded-md group-hover:bg-opacity-0">
98
- Surfing the what?
99
- </span>
100
- </button>
101
-
102
- <button
103
- type="button"
104
- className="text-white bg-gradient-to-br from-purple-600 to-sky-500 hover:bg-gradient-to-bl font-medium rounded-lg text-sm px-5 py-2.5 text-center mr-2 mb-2"
105
- onClick={() => setOpen(false)}
106
- >
107
- Let&apos;s Riff 🎸
108
- </button>
109
-
110
- </div>
111
- </div>
112
- </ModalContainer>
113
- </Transition.Child>
114
- </div>
115
- </Dialog>
116
- </Transition>
117
- </>
118
- );
119
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
components/ModelInference.tsx DELETED
@@ -1,214 +0,0 @@
1
- import { useRouter } from "next/router";
2
- import { useCallback, useEffect, useState } from "react";
3
-
4
- import {
5
- AppState,
6
- InferenceInput,
7
- InferenceResult,
8
- PromptInput,
9
- } from "../types";
10
-
11
- interface ModelInferenceProps {
12
- alpha: number;
13
- alphaRollover: boolean;
14
- seed: number;
15
- appState: AppState;
16
- promptInputs: PromptInput[];
17
- nowPlayingResult: InferenceResult;
18
- newResultCallback: (input: InferenceInput, result: InferenceResult) => void;
19
- useBaseten: boolean;
20
- denoising: number;
21
- seedImageId: string;
22
- }
23
-
24
- /**
25
- * Calls the server to run model inference.
26
- *
27
- *
28
- */
29
- export default function ModelInference({
30
- alpha,
31
- alphaRollover,
32
- seed,
33
- appState,
34
- promptInputs,
35
- nowPlayingResult,
36
- newResultCallback,
37
- useBaseten,
38
- denoising,
39
- seedImageId,
40
- }: ModelInferenceProps) {
41
- // Create parameters for the inference request
42
- const [guidance, setGuidance] = useState(7.0);
43
- const [numInferenceSteps, setNumInferenceSteps] = useState(50);
44
- const [maskImageId, setMaskImageId] = useState(null);
45
-
46
- const [initializedUrlParams, setInitializedUrlParams] = useState(false);
47
- const [numRequestsMade, setNumRequestsMade] = useState(0);
48
- const [numResponsesReceived, setNumResponsesReceived] = useState(0);
49
-
50
- useEffect(() => {
51
- console.log("Using baseten: ", useBaseten);
52
- }, [useBaseten]);
53
-
54
- // Set initial params from URL query strings
55
- const router = useRouter();
56
- useEffect(() => {
57
- if (router.query.guidance) {
58
- setGuidance(parseFloat(router.query.guidance as string));
59
- }
60
-
61
- if (router.query.numInferenceSteps) {
62
- setNumInferenceSteps(parseInt(router.query.numInferenceSteps as string));
63
- }
64
-
65
- if (router.query.maskImageId) {
66
- if (router.query.maskImageId === "none") {
67
- setMaskImageId("");
68
- } else {
69
- setMaskImageId(router.query.maskImageId as string);
70
- }
71
- }
72
-
73
- setInitializedUrlParams(true);
74
- }, [router.query]);
75
-
76
- // Memoized function to kick off an inference request
77
- const runInference = useCallback(
78
- async (
79
- alpha: number,
80
- seed: number,
81
- appState: AppState,
82
- promptInputs: PromptInput[]
83
- ) => {
84
- const startPrompt = promptInputs[promptInputs.length - 3].prompt;
85
- const endPrompt = promptInputs[promptInputs.length - 2].prompt;
86
-
87
- const transitioning = appState == AppState.TRANSITION;
88
-
89
- const inferenceInput = {
90
- alpha: alpha,
91
- num_inference_steps: numInferenceSteps,
92
- seed_image_id: seedImageId,
93
- mask_image_id: maskImageId,
94
- start: {
95
- prompt: startPrompt,
96
- seed: seed,
97
- denoising: denoising,
98
- guidance: guidance,
99
- },
100
- end: {
101
- prompt: transitioning ? endPrompt : startPrompt,
102
- seed: transitioning ? seed : seed + 1,
103
- denoising: denoising,
104
- guidance: guidance,
105
- },
106
- };
107
-
108
- console.log(`Inference #${numRequestsMade}: `, {
109
- alpha: alpha,
110
- prompt_a: inferenceInput.start.prompt,
111
- seed_a: inferenceInput.start.seed,
112
- prompt_b: inferenceInput.end.prompt,
113
- seed_b: inferenceInput.end.seed,
114
- appState: appState,
115
- });
116
-
117
- setNumRequestsMade((n) => n + 1);
118
-
119
- // Customize for baseten
120
- const apiHandler = useBaseten ? "/api/baseten" : "/api/server";
121
- const payload = useBaseten
122
- ? { worklet_input: inferenceInput }
123
- : inferenceInput;
124
-
125
- const response = await fetch(apiHandler, {
126
- method: "POST",
127
- body: JSON.stringify(payload),
128
- });
129
-
130
- const data = await response.json();
131
-
132
- console.log(`Got result #${numResponsesReceived}`);
133
-
134
- if (useBaseten) {
135
- if (data?.worklet_output?.model_output) {
136
- newResultCallback(
137
- inferenceInput,
138
- JSON.parse(data.worklet_output.model_output)
139
- );
140
- }
141
- // Note, data is currently wrapped in a data field
142
- else if (data?.data?.worklet_output?.model_output) {
143
- newResultCallback(
144
- inferenceInput,
145
- JSON.parse(data.data.worklet_output.model_output)
146
- );
147
- } else {
148
- console.error("Baseten call failed: ", data);
149
- }
150
- } else {
151
- // Note, data is currently wrapped in a data field
152
- newResultCallback(inferenceInput, data.data);
153
- }
154
-
155
- setNumResponsesReceived((n) => n + 1);
156
- },
157
- [
158
- denoising,
159
- guidance,
160
- maskImageId,
161
- numInferenceSteps,
162
- seedImageId,
163
- newResultCallback,
164
- numRequestsMade,
165
- numResponsesReceived,
166
- useBaseten,
167
- ]
168
- );
169
-
170
- // Kick off inference requests
171
- useEffect(() => {
172
- // Make sure things are initialized properly
173
- if (
174
- !initializedUrlParams ||
175
- appState == AppState.UNINITIALIZED ||
176
- promptInputs.length == 0
177
- ) {
178
- return;
179
- }
180
-
181
- // Wait for alpha rollover to resolve.
182
- if (alphaRollover) {
183
- return;
184
- }
185
-
186
- if (numRequestsMade == 0) {
187
- // Kick off the first request
188
- runInference(alpha, seed, appState, promptInputs);
189
- } else if (numRequestsMade == numResponsesReceived) {
190
- // Otherwise buffer ahead a few from where the audio player currently is
191
- // TODO(hayk): Replace this with better buffer management
192
-
193
- const nowPlayingCounter = nowPlayingResult ? nowPlayingResult.counter : 0;
194
- const numAhead = numRequestsMade - nowPlayingCounter;
195
-
196
- if (numAhead < 3) {
197
- runInference(alpha, seed, appState, promptInputs);
198
- }
199
- }
200
- }, [
201
- initializedUrlParams,
202
- alpha,
203
- alphaRollover,
204
- seed,
205
- appState,
206
- promptInputs,
207
- nowPlayingResult,
208
- numRequestsMade,
209
- numResponsesReceived,
210
- runInference,
211
- ]);
212
-
213
- return null;
214
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
components/PageHead.tsx DELETED
@@ -1,49 +0,0 @@
1
- import Head from "next/head";
2
-
3
- export default function PageHead() {
4
- return (
5
- <Head>
6
- <title>Riffusion</title>
7
- <meta property="og:site_name" content="Riffusion" />
8
-
9
- <meta
10
- property="article:author"
11
- content="Seth Forsgren and Hayk Martiros"
12
- />
13
-
14
- <meta property="article:tag" content="music" />
15
- <meta property="article:tag" content="machine learning" />
16
- <meta property="article:tag" content="artificial intelligence" />
17
- <meta property="article:tag" content="generative music" />
18
-
19
- <meta property="og:title" content="Riffusion" />
20
- <meta name="twitter:title" content="Riffusion" />
21
-
22
- <meta
23
- name="description"
24
- content="Stable diffusion for real-time music generation"
25
- />
26
- <meta
27
- name="og:description"
28
- content="Stable diffusion for real-time music generation"
29
- />
30
- <meta
31
- name="twitter:description"
32
- content="Stable diffusion for real-time music generation"
33
- />
34
-
35
- <meta name="twitter:card" content="summary" />
36
-
37
- <meta property="og:image" content="https://i.imgur.com/fywZpQ7.jpeg" />
38
- <meta name="twitter:image" content="https://i.imgur.com/fywZpQ7.jpeg" />
39
-
40
- <meta property="og:type" content="website" />
41
-
42
- <meta property="og:url" content="http://www.riffusion." />
43
- <meta property="og:locale" content="en_US" />
44
- <meta property="og:website" content="http://wwww.riffusion" />
45
-
46
- <link rel="icon" href="/favicon.ico" />
47
- </Head>
48
- );
49
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
components/Pause.tsx DELETED
@@ -1,41 +0,0 @@
1
- import { useEffect } from "react";
2
- import { FiPause, FiPlay } from "react-icons/fi";
3
-
4
- interface PauseProps {
5
- paused: boolean;
6
- setPaused: (value: boolean) => void;
7
- }
8
-
9
- export default function Pause({
10
- paused,
11
- setPaused,
12
- }: PauseProps) {
13
-
14
- // Print the state into the console
15
- useEffect(() => {
16
- if (paused) {
17
- console.log("Pause");
18
- } else {
19
- console.log("Play");
20
- }
21
- }, [paused]);
22
-
23
- var classNameCondition = ""
24
- if (paused) {
25
- classNameCondition="animate-pulse fixed z-20 top-4 right-4 md:top-8 md:right-8 w-14 h-14 rounded-full drop-shadow-lg flex justify-center items-center text-white text-2xl bg-red-500 hover:bg-red-600 ring-4 ring-red-700 focus:outline-none hover:drop-shadow-2xl"
26
- } else {
27
- classNameCondition="fixed z-20 top-4 right-4 md:top-8 md:right-8 bg-slate-100 w-14 h-14 rounded-full drop-shadow-lg flex justify-center items-center text-sky-900 text-2xl hover:text-white hover:bg-sky-600 hover:drop-shadow-2xl"
28
- }
29
-
30
- return (
31
- <>
32
- <button
33
- title="Pause"
34
- className= {classNameCondition}
35
- onClick={() => setPaused(!paused)}
36
- >
37
- {paused ? <FiPlay /> : <FiPause />}
38
- </button>
39
- </>
40
- );
41
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
components/PromptEntry.tsx DELETED
@@ -1,271 +0,0 @@
1
- import { InferenceInput, InferenceResult, PlayingState } from "../types";
2
- import { IoMdClose } from "react-icons/io";
3
- import Pause from "./Pause";
4
-
5
- interface PromptEntryProps {
6
- prompt: string;
7
- index: number;
8
- className: string;
9
- playingState: PlayingState;
10
- resetCallback: () => void;
11
- inferenceResults: InferenceResult[];
12
- nowPlayingResult: InferenceResult;
13
- setPaused: (value: boolean) => void;
14
- }
15
-
16
- export default function PromptEntry({
17
- prompt,
18
- index,
19
- className,
20
- playingState,
21
- resetCallback,
22
- inferenceResults,
23
- nowPlayingResult,
24
- setPaused
25
- }: PromptEntryProps) {
26
-
27
- const getPromptCopy = (prompt: string) => {
28
- switch (playingState) {
29
- case PlayingState.UNINITIALIZED:
30
- case PlayingState.SAME_PROMPT:
31
- switch (index) {
32
- case 0:
33
- return (
34
- <div className="tooltip text-left" data-tip="βͺ Jump to previous prompt?" onClick={() => { jumpToPrompt(prompt, inferenceResults, setPaused, nowPlayingResult) }} >
35
- <p className={className}>{prompt}</p>
36
- </div>
37
- );
38
- case 1:
39
- return (
40
- <div className="tooltip text-left" data-tip="βͺ Jump to previous prompt?" onClick={() => { jumpToPrompt(prompt, inferenceResults, setPaused, nowPlayingResult) }} >
41
- <p className={className}>{prompt}</p>
42
- </div>
43
- );
44
- case 2:
45
- // active prompt
46
- if (prompt == " " || prompt == "") {
47
- return <span className="text-slate-600">{"<enter prompt>"}</span>;
48
- } else {
49
- return (
50
- <div className="tooltip text-left" data-tip="πŸ” Restart current prompt?" onClick={() => { jumpToPrompt(prompt, inferenceResults, setPaused, nowPlayingResult) }} >
51
- <p className={className}>{prompt}</p>
52
- </div>
53
- )
54
- }
55
- case 3:
56
- if (prompt == " " || prompt == "") {
57
- return <p className={className}>...</p>
58
- } else {
59
- return (
60
- <div className="tooltip text-left" data-tip="πŸš€ Jump to upcoming prompt?" onClick={() => { jumpToPrompt(prompt, inferenceResults, setPaused, nowPlayingResult) }} >
61
- <p className={className}>{prompt}</p>
62
- </div>
63
- )
64
- }
65
- case 4:
66
- if (prompt == " " || prompt == "") {
67
- return <p className={className}>UP NEXT: Anything you want</p>;
68
- } else {
69
- return (
70
- <div className="tooltip text-left" data-tip="πŸš€ Jump to upcoming prompt?" onClick={() => { jumpToPrompt(prompt, inferenceResults, setPaused, nowPlayingResult) }} >
71
- <p className={className}>UP NEXT: {prompt}</p>
72
- </div>
73
- )
74
- }
75
- default: {
76
- console.log("UNHANDLED default");
77
- return <p className={className}>{prompt}</p>;
78
- }
79
- }
80
- case PlayingState.TRANSITION:
81
- switch (index) {
82
- case 0:
83
- return (
84
- <div className="tooltip text-left" data-tip="βͺ Jump to previous prompt?" onClick={() => { jumpToPrompt(prompt, inferenceResults, setPaused, nowPlayingResult) }} >
85
- <p className={className}>{prompt}</p>
86
- </div>
87
- );
88
- case 1:
89
- return (
90
- <div className="tooltip text-left" data-tip="βͺ Jump to previous prompt?" onClick={() => { jumpToPrompt(prompt, inferenceResults, setPaused, nowPlayingResult) }} >
91
- <p className={className}>{prompt}</p>
92
- </div>
93
- );
94
- case 2:
95
- return (
96
- <div className="tooltip text-left" data-tip="πŸ” Restart outgoing prompt?" onClick={() => { jumpToPrompt(prompt, inferenceResults, setPaused, nowPlayingResult) }} >
97
- <p className={className}>{prompt}</p>
98
- </div>
99
- )
100
- case 3:
101
- if (prompt == " " || prompt == "") {
102
- return <p className={className}> -enter prompt- </p>;
103
- } else {
104
- return (
105
- <div className="tooltip text-left" data-tip="πŸš€ Jump to incoming prompt?" onClick={() => { jumpToPrompt(prompt, inferenceResults, setPaused, nowPlayingResult) }} >
106
- <p className={className}>{prompt}</p>
107
- </div>
108
- )
109
- }
110
- case 4:
111
- if (prompt == " " || prompt == "") {
112
- return <p className={className}>...</p>;
113
- } else {
114
- return (
115
- <div className="tooltip text-left" data-tip="πŸš€ Jump to upcoming prompt?" onClick={() => { jumpToPrompt(prompt, inferenceResults, setPaused, nowPlayingResult) }} >
116
- <p className={className}>{prompt}</p>
117
- </div>
118
- )
119
- }
120
- case 5:
121
- if (prompt == " " || prompt == "") {
122
- return <p className={className}>UP NEXT: Anything you want</p>;
123
- } else {
124
- return (
125
- <div className="tooltip text-left" data-tip="πŸš€ Jump to upcoming prompt?" onClick={() => { jumpToPrompt(prompt, inferenceResults, setPaused, nowPlayingResult) }} >
126
- <p className={className}>UP NEXT: {prompt}</p>
127
- </div>
128
- )
129
- }
130
- default: {
131
- console.log("UNHANDLED default");
132
- return <p className={className}>{prompt}</p>;
133
- }
134
- }
135
- }
136
- };
137
-
138
- return (
139
- <div className="flex cursor-pointer">
140
- {getPromptCopy(prompt)}
141
-
142
- {/* TODO(hayk): Re-enable this when it's working. */}
143
- {/* {index == 2 ? (
144
- <IoMdClose
145
- className="w-6 h-6 ml-2 text-gray-400"
146
- onClick={() => {
147
- resetCallback();
148
- }}
149
- />
150
- ) : null} */}
151
- </div >
152
- );
153
- }
154
-
155
- export function jumpToPrompt(prompt: String, inferenceResults: InferenceResult[], setPaused: (value: boolean) => void, nowPlayingResult?: InferenceResult) {
156
-
157
- // Pause player since this function will open new tab that user will interact with
158
- setPaused(true)
159
-
160
- let firstTimePromptAppears = -1;
161
- for (let i = 0; i < inferenceResults.length; i++) {
162
- if (inferenceResults[i].input.start.prompt === prompt) {
163
- firstTimePromptAppears = i;
164
- break;
165
- }
166
- }
167
- if (firstTimePromptAppears == -1) {
168
- let url = generateLinkToUpcomingPrompt(prompt, nowPlayingResult)
169
- window.location.href = url;
170
- }
171
- else {
172
- let url = generateLinkToPreviousInput(inferenceResults[firstTimePromptAppears].input)
173
- window.location.href = url;
174
- }
175
- }
176
-
177
- export function generateLinkToUpcomingPrompt(prompt, nowPlayingResult?: InferenceResult) {
178
-
179
- var promptString = "&prompt=" + prompt;
180
- promptString = promptString.replace(/ /g, "+");
181
-
182
- if (nowPlayingResult != null) {
183
- var denoisingString = "&denoising=" + nowPlayingResult.input.start.denoising;
184
- var seedImageIdString = "&seedImageId=" + nowPlayingResult.input.seed_image_id;
185
- } else {
186
- denoisingString = "";
187
- seedImageIdString = "";
188
- }
189
-
190
- var baseUrl = window.location.origin + "/?";
191
- var url = baseUrl + promptString + denoisingString + seedImageIdString;
192
- return url;
193
- }
194
-
195
- // Todo: DRY this and share functions
196
- export function generateLinkToPreviousInput(selectedInput: InferenceInput) {
197
- var prompt;
198
- var seed;
199
- var denoising;
200
- var maskImageId;
201
- var seedImageId;
202
- var guidance;
203
- var numInferenceSteps;
204
- var alphaVelocity;
205
-
206
- prompt = selectedInput.start.prompt;
207
- seed = selectedInput.start.seed;
208
- denoising = selectedInput.start.denoising;
209
- maskImageId = selectedInput.mask_image_id;
210
- seedImageId = selectedInput.seed_image_id;
211
-
212
- var baseUrl = window.location.origin + "/?";
213
-
214
- if (prompt != null) {
215
- var promptString = "&prompt=" + prompt;
216
- } else {
217
- promptString = "";
218
- }
219
- if (seed != null) {
220
- var seedString = "&seed=" + seed;
221
- } else {
222
- seedString = "";
223
- }
224
- if (denoising != null) {
225
- var denoisingString = "&denoising=" + denoising;
226
- } else {
227
- denoisingString = "";
228
- }
229
- if (maskImageId != null) {
230
- var maskImageIdString = "&maskImageId=" + maskImageId;
231
- } else {
232
- maskImageIdString = "";
233
- }
234
- if (seedImageId != null) {
235
- var seedImageIdString = "&seedImageId=" + seedImageId;
236
- } else {
237
- seedImageIdString = "";
238
- }
239
- if (guidance != null) {
240
- var guidanceString = "&guidance=" + guidance;
241
- } else {
242
- guidanceString = "";
243
- }
244
- if (numInferenceSteps != null) {
245
- var numInferenceStepsString = "&numInferenceSteps=" + numInferenceSteps;
246
- } else {
247
- numInferenceStepsString = "";
248
- }
249
- if (alphaVelocity != null) {
250
- var alphaVelocityString = "&alphaVelocity=" + alphaVelocity;
251
- } else {
252
- alphaVelocityString = "";
253
- }
254
-
255
- // Format strings to have + in place of spaces for ease of sharing, note this is only necessary for prompts currently
256
- promptString = promptString.replace(/ /g, "+");
257
-
258
- // create url string with the variables above combined
259
- var shareUrl =
260
- baseUrl +
261
- promptString +
262
- seedString +
263
- denoisingString +
264
- maskImageIdString +
265
- seedImageIdString +
266
- guidanceString +
267
- numInferenceStepsString +
268
- alphaVelocityString;
269
-
270
- return shareUrl;
271
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
components/PromptPanel.tsx DELETED
@@ -1,360 +0,0 @@
1
- import PromptEntry from "./PromptEntry";
2
-
3
- import { AppState, PlayingState, InferenceResult, PromptInput } from "../types";
4
- import { useRef } from "react";
5
- import { samplePrompts, rollTheDicePrompts } from "../samplePrompts";
6
-
7
- interface PromptPanelProps {
8
- prompts: PromptInput[];
9
- inferenceResults: InferenceResult[];
10
- nowPlayingResult: InferenceResult;
11
- appState: AppState;
12
- changePrompt: (prompt: string, index: number) => void;
13
- resetCallback: () => void;
14
- setPaused: (paused: boolean) => void;
15
- }
16
-
17
- export default function PromptPanel({
18
- prompts,
19
- inferenceResults,
20
- nowPlayingResult,
21
- appState,
22
- changePrompt,
23
- resetCallback,
24
- setPaused,
25
- }: PromptPanelProps) {
26
- const inputPrompt = useRef(null);
27
-
28
- var playingState: PlayingState;
29
-
30
- const getDisplayPrompts = () => {
31
- var displayPrompts = [];
32
-
33
- if (nowPlayingResult == null) {
34
- playingState = PlayingState.UNINITIALIZED;
35
- } else if (
36
- nowPlayingResult.input.start.prompt == nowPlayingResult.input.end.prompt
37
- ) {
38
- playingState = PlayingState.SAME_PROMPT;
39
- } else {
40
- playingState = PlayingState.TRANSITION;
41
- }
42
-
43
- // Add the last 4 prompts from playedResults
44
- // filter inferenceResults to only include results that have been played
45
- const playedResults = inferenceResults.filter((r) => r.played);
46
-
47
- // filter playedResults to include only results where alpha is 0.25 (the first alpha of a new transition)
48
- const playedResultsAlpha = playedResults.filter(
49
- (r) => r.input.alpha == 0.25
50
- );
51
-
52
- // filter playedResultsAlpha to include only results where playedResultsAlpha.input.start.prompt is not the same as playedResultsAlpha.input.end.prompt
53
- const playedResultsAlphaTransition = playedResultsAlpha.filter(
54
- (r) => r.input.start.prompt != r.input.end.prompt
55
- );
56
-
57
- // select the last 4 results
58
- const lastPlayedResultsAlphaTransition =
59
- playedResultsAlphaTransition.slice(-4);
60
-
61
- // add the most recent end prompts to the displayPrompts
62
- lastPlayedResultsAlphaTransition.forEach((result) => {
63
- displayPrompts.push({ prompt: result.input.end.prompt });
64
- });
65
-
66
- // Handle the case where there are less than 4 played results (i.e. the initial state)
67
- if (displayPrompts.length < 4) {
68
- const promptsToAdd = prompts.slice(displayPrompts.length, 4);
69
- displayPrompts = [...promptsToAdd, ...displayPrompts];
70
- }
71
-
72
- // Add in the upNext and staged prompts
73
- // select the last 2 prompts from prompts
74
- const lastPrompts = prompts.slice(-2);
75
-
76
- // make a copy of the lastPrompts with new pointers
77
- const lastPromptsCopy = lastPrompts.map((p) => ({ ...p }));
78
-
79
- // if any of the lastPrompts have a transitionCounter, replace them with "" because they are already represented in the displayPrompts
80
- lastPromptsCopy.forEach((prompt, index) => {
81
- if (prompt.transitionCounter != null) {
82
- lastPromptsCopy[index].prompt = "";
83
- lastPromptsCopy[index].transitionCounter = null;
84
- }
85
- });
86
-
87
- // add the prompts to the displayPrompts
88
- lastPromptsCopy.forEach((p) => {
89
- displayPrompts.push(p);
90
- });
91
-
92
- // if playingState == PlayingState.SAME_PROMPT or playingState == PlayingState.UNINITIALIZED, remove the first prompt from displayPrompts
93
- if (
94
- playingState == PlayingState.SAME_PROMPT ||
95
- playingState == PlayingState.UNINITIALIZED
96
- ) {
97
- displayPrompts.shift();
98
- }
99
-
100
- return displayPrompts;
101
- };
102
-
103
- const getPromptEntryClassName = (index: number) => {
104
- switch (playingState) {
105
- case PlayingState.UNINITIALIZED:
106
- return promptEntryClassNames_5_0[index];
107
- case PlayingState.SAME_PROMPT:
108
- if (appState != AppState.TRANSITION) {
109
- return promptEntryClassNames_5_0[index];
110
- } else {
111
- switch (nowPlayingResult.input.alpha) {
112
- case 0:
113
- return promptEntryClassNames_5_0[index];
114
- case 0.25:
115
- return promptEntryClassNames_5_25[index];
116
- case 0.5:
117
- return promptEntryClassNames_5_50[index];
118
- case 0.75:
119
- return promptEntryClassNames_5_75[index];
120
- case 1:
121
- return promptEntryClassNames_5_1[index];
122
- }
123
- }
124
- case PlayingState.TRANSITION:
125
- switch (nowPlayingResult.input.alpha) {
126
- case 0:
127
- return promptEntryClassNames_6_0[index];
128
- case 0.25:
129
- return promptEntryClassNames_6_25[index];
130
- case 0.5:
131
- return promptEntryClassNames_6_50[index];
132
- case 0.75:
133
- return promptEntryClassNames_6_75[index];
134
- case 1:
135
- return promptEntryClassNames_6_1[index];
136
- }
137
- default:
138
- // These states are reached if alpha is greater than 1 but the new inference is not ready
139
- if (appState != AppState.TRANSITION) {
140
- return promptEntryClassNames_5_0[index];
141
- } else if (playingState == PlayingState.SAME_PROMPT) {
142
- return promptEntryClassNames_5_1[index];
143
- } else {
144
- return promptEntryClassNames_6_1[index];
145
- }
146
- }
147
- };
148
-
149
- const rollTheDice = () => {
150
- const prompts = [...samplePrompts, ...rollTheDicePrompts];
151
-
152
- const selectedPrompt = prompts[Math.floor(Math.random() * prompts.length)];
153
-
154
- inputPrompt.current.value = selectedPrompt;
155
- };
156
-
157
- return (
158
- <>
159
- <main className="z-10 fixed w-full md:static md:w-2/3 md:min-h-screen">
160
- <div className="pl-10 pr-10 md:pl-20">
161
- <div className="h-[78vh] landscape:sm:max-[750px]:h-[62vh] md:h-[80vh] flex flex-col justify-around pt-[10vh] pr-5">
162
- {getDisplayPrompts().map((prompt, index) => (
163
- <PromptEntry
164
- prompt={prompt.prompt}
165
- className={getPromptEntryClassName(index)}
166
- index={index}
167
- key={index}
168
- playingState={playingState}
169
- resetCallback={resetCallback}
170
- inferenceResults={inferenceResults}
171
- nowPlayingResult={nowPlayingResult}
172
- setPaused={setPaused}
173
- />
174
- ))}
175
- </div>
176
-
177
- {/* // Form trims spaces, and only submits if the remaining prompt is more than 0 characters */}
178
- <form
179
- noValidate={true}
180
- onSubmit={(e) => {
181
- e.preventDefault();
182
- const prompt = e.currentTarget.prompt.value;
183
- const trimmedPrompt = prompt.trimStart();
184
- if (trimmedPrompt.length > 0) {
185
- changePrompt(trimmedPrompt, prompts.length - 1);
186
- inputPrompt.current.value = "";
187
- } else {
188
- inputPrompt.current.value = "";
189
- }
190
- }}
191
- >
192
- <input
193
- className="flex w-full md:fixed md:w-5/12 h-12 pl-3 pr-3 text-lg text-sky-900 dark:text-sky-100 rounded-lg border-sky-700 border-4 hover:border-sky-600 focus:outline-none focus:border-sky-400"
194
- ref={inputPrompt}
195
- type="text"
196
- id="prompt"
197
- name="prompt"
198
- placeholder="What do you want to hear next?"
199
- maxLength={150}
200
- minLength={2}
201
- required={true}
202
- autoComplete="off"
203
- />
204
- </form>
205
- <div className="hidden md:block">
206
- <div>
207
- <button
208
- className="flex -ml-8 pt-2 h-12 w-12 text-xl text-white"
209
- onClick={() => {
210
- rollTheDice();
211
- }}
212
- >
213
- 🎲
214
- </button>
215
- </div>
216
- </div>
217
- </div>
218
- </main>
219
- </>
220
- );
221
- }
222
-
223
- export function refreshPage() {
224
- window.location.reload();
225
- }
226
-
227
- const promptEntryClassNameDict = {
228
- 0: "font-extralight text-xs text-gray-500 text-opacity-20",
229
- 1: "font-extralight text-xs text-gray-400 text-opacity-20",
230
- 2: "font-extralight text-sm text-gray-300 text-opacity-30",
231
- 3: "font-extralight text-sm text-gray-200 text-opacity-30",
232
- 4: "font-light text-sm text-gray-200 text-opacity-40",
233
- 5: "font-light text-base text-gray-200 text-opacity-40",
234
- 6: "font-light text-base text-gray-100 text-opacity-50",
235
- 7: "font-light text-base text-gray-100 text-opacity-50", // starter for 0
236
-
237
- 8: "font-light text-base text-gray-100 text-opacity-50",
238
- 9: "font-light text-lg text-gray-100 text-opacity-50",
239
- 10: "font-light text-lg text-gray-100 text-opacity-60",
240
- 11: "font-normal text-lg text-gray-100 text-opacity-60",
241
- 12: "font-normal text-xl text-gray-100 text-opacity-60",
242
- 13: "font-normal text-xl text-gray-100 text-opacity-70",
243
- 14: "font-normal text-xl text-gray-100 text-opacity-70",
244
- 15: "font-normal text-xl text-gray-100 text-opacity-70", // starter for 1
245
-
246
- 16: "font-medium text-2xl text-gray-100 text-opacity-80", // 0%
247
- 17: "font-medium text-3xl text-gray-100 text-opacity-90", // 25%
248
- 18: "font-semibold text-4xl text-white", // 50%
249
- 19: "font-bold text-4xl text-white", // 75%
250
- 20: "font-bold text-5xl text-white",
251
- 21: "font-bold text-5xl text-white",
252
- 22: "font-bold text-5xl text-white",
253
- 23: "font-bold text-5xl text-white", // starter for 2 "start"
254
-
255
- 24: "font-bold text-5xl text-white",
256
- 25: "font-bold text-4xl text-white", // 75%
257
- 26: "font-semibold text-4xl text-white", // 50%
258
- 27: "font-medium text-3xl text-gray-100 text-opacity-90", // 25%
259
- 28: "font-normal text-2xl text-gray-100 text-opacity-80",
260
- 29: "font-normal text-l text-gray-100 text-opacity-70",
261
- 30: "font-normal text-l text-gray-100 text-opacity-70",
262
- 31: "font-normal text-l text-gray-100 text-opacity-70", // starter for 3 "end"
263
-
264
- 32: "font-normal text-base text-gray-100 text-opacity-70",
265
- 33: "font-normal text-base text-gray-100 text-opacity-60",
266
- 34: "font-normal text-base text-gray-100 text-opacity-60",
267
- 35: "font-normal text-base text-gray-100 text-opacity-60", // starter for 4 when "staging"
268
-
269
- 36: "font-normal text-base text-gray-100 text-opacity-60", // starter for 4 and 5 "Up Next"
270
- };
271
-
272
- // ClassNames below
273
- // Note that 6_0 and 5_25 are never reached in current stucture
274
-
275
- const promptEntryClassNames_5_0 = {
276
- 0: promptEntryClassNameDict[7],
277
- 1: promptEntryClassNameDict[15],
278
- 2: promptEntryClassNameDict[23], // This is the start and end prompt
279
- 3: promptEntryClassNameDict[31], // This is the staged prompt
280
- 4: promptEntryClassNameDict[36], // This is the UP NEXT prompt
281
- };
282
-
283
- const promptEntryClassNames_5_25 = {
284
- // This is not reached unless user has poor connection or delayed server response
285
- 0: promptEntryClassNameDict[7],
286
- 1: promptEntryClassNameDict[15],
287
- 2: promptEntryClassNameDict[23], // This is the start and end prompt
288
- 3: promptEntryClassNameDict[31], // This is the staged prompt
289
- 4: promptEntryClassNameDict[36], // This is the UP NEXT prompt
290
- };
291
-
292
- const promptEntryClassNames_5_50 = {
293
- 0: promptEntryClassNameDict[6],
294
- 1: promptEntryClassNameDict[14],
295
- 2: promptEntryClassNameDict[22],
296
- 3: promptEntryClassNameDict[30],
297
- 4: promptEntryClassNameDict[36],
298
- };
299
-
300
- const promptEntryClassNames_5_75 = {
301
- 0: promptEntryClassNameDict[5],
302
- 1: promptEntryClassNameDict[13],
303
- 2: promptEntryClassNameDict[21],
304
- 3: promptEntryClassNameDict[29],
305
- 4: promptEntryClassNameDict[36],
306
- };
307
-
308
- const promptEntryClassNames_5_1 = {
309
- 0: promptEntryClassNameDict[4],
310
- 1: promptEntryClassNameDict[12],
311
- 2: promptEntryClassNameDict[20],
312
- 3: promptEntryClassNameDict[28],
313
- 4: promptEntryClassNameDict[36],
314
- };
315
-
316
- const promptEntryClassNames_6_0 = {
317
- // This is not reached unless user has poor connection or delayed server response
318
- 0: promptEntryClassNameDict[3],
319
- 1: promptEntryClassNameDict[11],
320
- 2: promptEntryClassNameDict[19],
321
- 3: promptEntryClassNameDict[27],
322
- 4: promptEntryClassNameDict[35],
323
- 5: promptEntryClassNameDict[36],
324
- };
325
-
326
- const promptEntryClassNames_6_25 = {
327
- 0: promptEntryClassNameDict[3],
328
- 1: promptEntryClassNameDict[11],
329
- 2: promptEntryClassNameDict[19],
330
- 3: promptEntryClassNameDict[27],
331
- 4: promptEntryClassNameDict[35],
332
- 5: promptEntryClassNameDict[36],
333
- };
334
-
335
- const promptEntryClassNames_6_50 = {
336
- 0: promptEntryClassNameDict[2],
337
- 1: promptEntryClassNameDict[10],
338
- 2: promptEntryClassNameDict[18],
339
- 3: promptEntryClassNameDict[26],
340
- 4: promptEntryClassNameDict[34],
341
- 5: promptEntryClassNameDict[36],
342
- };
343
-
344
- const promptEntryClassNames_6_75 = {
345
- 0: promptEntryClassNameDict[1],
346
- 1: promptEntryClassNameDict[9],
347
- 2: promptEntryClassNameDict[17],
348
- 3: promptEntryClassNameDict[25],
349
- 4: promptEntryClassNameDict[33],
350
- 5: promptEntryClassNameDict[36],
351
- };
352
-
353
- const promptEntryClassNames_6_1 = {
354
- 0: promptEntryClassNameDict[0],
355
- 1: promptEntryClassNameDict[8],
356
- 2: promptEntryClassNameDict[16],
357
- 3: promptEntryClassNameDict[24],
358
- 4: promptEntryClassNameDict[32],
359
- 5: promptEntryClassNameDict[36],
360
- };