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
- };