riffusion-app/components/SpectrogramViewer.tsx

111 lines
3.1 KiB
TypeScript
Raw Permalink Normal View History

import { useRef } from "react";
import { useFrame, useThree } from "@react-three/fiber";
2022-11-25 00:26:44 -07:00
import { Box } from "@react-three/drei";
import { InferenceResult } from "../types";
2022-11-24 11:43:11 -07:00
import HeightMapImage from "./HeightMapImage";
import ImagePlane from "./ImagePlane";
2022-11-27 14:53:22 -07:00
// import { Effects } from "@react-three/drei";
// import { ShaderPass, VerticalTiltShiftShader} from "three-stdlib";
// extend({ ShaderPass });
// Fun shaders:
// RGBShiftShader
// VerticalBlurShader
// VerticalTiltShiftShader
interface SpectrogramViewerProps {
paused: boolean;
inferenceResults: InferenceResult[];
getTime: () => number;
2022-11-24 11:43:11 -07:00
use_height_map?: boolean;
}
/**
* Spectrogram drawing code.
*/
2022-11-24 11:43:11 -07:00
export default function SpectrogramViewer({
paused,
inferenceResults,
getTime,
2022-11-24 11:43:11 -07:00
use_height_map = true,
}: SpectrogramViewerProps) {
2022-11-27 14:19:01 -07:00
const { camera } = useThree();
const playheadRef = useRef(null);
// Move the camera based on the clock
useFrame(() => {
const time = getTime();
const velocity = -1.0; // [m/s]
const position = velocity * time; // [m]
camera.position.y = position;
playheadRef.current.position.y = camera.position.y;
});
2022-11-25 22:17:29 -07:00
const playbarShift = 3.6; // [m]
2022-12-08 17:54:01 -07:00
// NOTE: this is a hacky way to constrict image and box width to fit in the window for responsiveness
2022-12-09 10:14:14 -07:00
// if window is between 768px and 1350px, this scales the image to fit using a scaler
const imageScaler = window.innerHeight / 3.40;
const boxScaler = window.innerHeight / 3.76;
2022-12-09 10:13:54 -07:00
const spectrogramImageScale = window.innerWidth > 767 && window.innerWidth < 1350 ? window.innerWidth / imageScaler : 5;
const spectrogramBoxScale = window.innerWidth > 767 && window.innerWidth < 1350 ? window.innerWidth / boxScaler : 5.5;
return (
<group>
2022-11-27 14:53:22 -07:00
{/* <Effects
multisamping={8}
renderIndex={1}
disableGamma={false}
disableRenderPass={false}
disableRender={false}
>
<shaderPass attachArray="passes" args={[VerticalTiltShiftShader]} />
</Effects> */}
{inferenceResults.map((result: InferenceResult, index: number) => {
const duration_s = result.duration_s;
const position = duration_s * (-0.55 - result.counter) + playbarShift;
2022-11-24 11:43:11 -07:00
if (use_height_map) {
return (
<HeightMapImage
2022-11-27 14:53:22 -07:00
url={result.image}
2022-11-25 22:17:29 -07:00
position={[0, position, 0]}
2022-11-24 11:43:11 -07:00
rotation={[0, 0, -Math.PI / 2]}
scale={[duration_s, spectrogramImageScale, 1]}
2022-11-24 11:43:11 -07:00
key={index}
/>
);
} else {
2022-11-25 00:26:44 -07:00
return (
<ImagePlane
2022-11-27 14:53:22 -07:00
url={result.image}
2022-11-25 22:17:29 -07:00
height={position}
2022-11-27 14:53:22 -07:00
duration={duration_s}
2022-11-25 00:26:44 -07:00
key={index}
/>
);
2022-11-24 11:43:11 -07:00
}
})}
2022-11-27 14:19:01 -07:00
{/* Playhead as as transparent red box. */}
{/* TODO(hayk): Synchronize this better with the audio. */}
<group ref={playheadRef}>
2022-11-25 00:26:44 -07:00
<Box
args={[spectrogramBoxScale, 2.0, 0.15]}
2022-11-25 22:17:29 -07:00
rotation={[Math.PI / 2 - 0.2, 0, 0]}
position={[0, playbarShift, -0.5]}
>
2022-11-25 22:17:29 -07:00
<meshBasicMaterial color="#ee2211" transparent opacity={0.8} />
2022-11-25 00:26:44 -07:00
</Box>
</group>
</group>
);
}