First audio tests
All checks were successful
Publish Docker image / Push Docker image to Docker Hub (push) Successful in 1m18s

This commit is contained in:
2025-02-27 21:34:07 +01:00
parent a2340ca1de
commit d98dceee75
2 changed files with 405 additions and 5 deletions

View File

@ -1,13 +1,164 @@
import "./styles.sass";
import {StateContext} from "@/common/contexts/StateContext";
import {useContext} from "react";
import {useContext, useState, useEffect, useRef} from "react";
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faMusic } from '@fortawesome/free-solid-svg-icons';
const songs = ["Twinkle Twinkle Little Star", "Happy Birthday", "Jingle Bells", "Mary Had a Little Lamb", "Old MacDonald Had a Farm"];
export const Home = () => {
const {setCurrentState} = useContext(StateContext);
const [frequency, setFrequency] = useState(440);
const [isPlaying, setIsPlaying] = useState(false);
const [currentSong, setCurrentSong] = useState(songs[Math.floor(Math.random() * songs.length)]);
const [dragging, setDragging] = useState(false);
const audioContextRef = useRef(null);
const oscillatorRef = useRef(null);
const gainNodeRef = useRef(null);
const sliderRef = useRef(null);
const [messages, setMessages] = useState([]);
const [inputValue, setInputValue] = useState("");
const messageEndRef = useRef(null);
const startAudio = () => {
if (!audioContextRef.current) {
audioContextRef.current = new (window.AudioContext || window.webkitAudioContext)();
}
if (!oscillatorRef.current) {
oscillatorRef.current = audioContextRef.current.createOscillator();
oscillatorRef.current.type = 'sine';
oscillatorRef.current.frequency.setValueAtTime(frequency, audioContextRef.current.currentTime);
gainNodeRef.current = audioContextRef.current.createGain();
gainNodeRef.current.gain.setValueAtTime(0.5, audioContextRef.current.currentTime);
oscillatorRef.current.connect(gainNodeRef.current);
gainNodeRef.current.connect(audioContextRef.current.destination);
oscillatorRef.current.start();
} else {
oscillatorRef.current.frequency.setValueAtTime(frequency, audioContextRef.current.currentTime);
}
setIsPlaying(true);
};
const stopAudio = () => {
if (oscillatorRef.current) {
oscillatorRef.current.stop();
oscillatorRef.current.disconnect();
oscillatorRef.current = null;
}
setIsPlaying(false);
};
const handleMouseDown = (e) => {
setDragging(true);
startAudio();
handleFrequencyChange(e);
};
const handleMouseUp = () => {
setDragging(false);
stopAudio();
};
const handleFrequencyChange = (e) => {
if (isPlaying || dragging) {
const rect = sliderRef.current.getBoundingClientRect();
const x = e.clientX - rect.left; // x position within the element.
const newFrequency = 20 + (x / rect.width) * 1980; // Scale to frequency range
setFrequency(newFrequency);
}
};
useEffect(() => {
if (isPlaying) {
if (oscillatorRef.current) {
oscillatorRef.current.frequency.setValueAtTime(frequency, audioContextRef.current.currentTime);
}
}
}, [frequency, isPlaying]);
useEffect(() => {
messageEndRef.current?.scrollIntoView({ behavior: "smooth" });
}, [messages]);
const handleSendMessage = () => {
if (inputValue.trim()) {
setMessages([...messages, { sender: "User", text: inputValue }]);
setInputValue("");
}
};
return (
<div className="home-page">
<h2>ToneGuessr</h2>
<div className="background-elements">
<FontAwesomeIcon icon={faMusic} className="music-note note-1" />
<FontAwesomeIcon icon={faMusic} className="music-note note-2" />
<FontAwesomeIcon icon={faMusic} className="music-note note-3" />
</div>
<div className="main-content">
<div className="song-display">
<h2>Play this song:</h2>
<div className="song-card">
<img src="https://place-hold.it/500x500" alt="Song" />
<div className="song-info">
<div className="song-name">{currentSong}</div>
<div className="song-description">A beautiful classic song for you to play on the Otamatone.</div>
</div>
</div>
</div>
<div className="chat-window">
<div className="chat-header">
<div className="account-icon"></div>
<div className="chat-title">Chat</div>
</div>
<div className="chat-messages">
{messages.map((message, index) => (
<div key={index} className="message">
<span className="message-sender">{message.sender}:</span>
<span className="message-text">{message.text}</span>
</div>
))}
<div ref={messageEndRef}></div>
</div>
<div className="chat-input">
<input
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
onKeyPress={(e) => e.key === 'Enter' && handleSendMessage()}
placeholder="Type your message..."
/>
<button onClick={handleSendMessage}>Send</button>
</div>
</div>
</div>
<div className="otamatone-container">
<div
className="otamatone"
onMouseDown={handleMouseDown}
onMouseUp={handleMouseUp}
onMouseMove={handleFrequencyChange}
onMouseLeave={handleMouseUp}
>
<div className="otamatone-neck" ref={sliderRef}>
<div className="frequency-indicator" style={{ left: `${(frequency - 20) / 1980 * 100}%` }}></div>
<div className="note-marker" style={{left: '10%', pointerEvents: 'none'}}></div>
<div className="note-marker" style={{left: '50%', pointerEvents: 'none'}}></div>
<div className="note-marker" style={{left: '90%', pointerEvents: 'none'}}></div>
</div>
<div className="otamatone-face">
<div
className="otamatone-mouth"
style={{ height: `${10 + (frequency / 2000) * 40}px`, width: `${10 + (frequency / 2000) * 40}px` }}
></div>
<div className="otamatone-eyes">
<div className="eye left-eye"></div>
<div className="eye right-eye"></div>
</div>
</div>
</div>
</div>
</div>
);
}
}