Skip to content

Commit

Permalink
web app: Created training component
Browse files Browse the repository at this point in the history
* Piano loading improvement
* Deactivated volume settings
* #8
  • Loading branch information
PhilippDehner committed Feb 4, 2023
1 parent 0a96855 commit 41c9176
Show file tree
Hide file tree
Showing 8 changed files with 225 additions and 130 deletions.
43 changes: 28 additions & 15 deletions web-app/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,37 @@ import "./App.css";
import Layout from "./components/Layout";
import Home from "./pages/Home";
import Pitch from "./pages/Pitch";
import { useState } from "react";

let init = true;
let piano = new Piano({
velocities: 1,
release: true,
pedal: true
});

function App() {
let piano = new Piano();
piano.toDestination(); //connect it to the speaker output
piano.load().then(() => {
console.log("loaded!");
});
const [pianoReadyState, setPianoReadyState] = useState(false);

if (init) {
piano.toDestination(); //connect it to the speaker output
piano.load().then(_ => {
init = false;
setPianoReadyState(true);
console.info("Piano loaded");
});
}

return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Layout />}>
<Route index element={<Home />} />
<Route path="Pitch" element={<Pitch piano={piano} />} />
</Route>
</Routes>
</BrowserRouter>
);
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Layout />}>
<Route index element={<Home />} />
<Route path="Pitch" element={<Pitch piano={piano} pianoLoaded={pianoReadyState} />} />
</Route>
</Routes>
</BrowserRouter>
);
}

export default App;
11 changes: 4 additions & 7 deletions web-app/src/components/GeneralSettings.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import Form from "react-bootstrap/Form";
import { useState } from "react";
import Container from "react-bootstrap/Container";
import Row from "react-bootstrap/Row";
Expand All @@ -13,8 +12,6 @@ class Settings {
ToneRange: ToneRange = new ToneRange();
}

const DefaultToneRange = new ToneRange()

interface Props {
settings: Settings;
OnChanged(settings: Settings): void;
Expand Down Expand Up @@ -58,8 +55,8 @@ function GeneralSettings(props: Props) {

return (
<div>
<Container>
<Row>
<Container className="mt-3">
{/* <Row>
<Col md="auto">
<Form.Label>Volume {volume}%</Form.Label>
</Col>
Expand All @@ -71,8 +68,8 @@ function GeneralSettings(props: Props) {
max={100}
/>
</Col>
</Row>
<Row>
</Row> */}
<Row md={'auto'}>
<Col>
<ToneSelector
label="Tiefster Ton"
Expand Down
8 changes: 4 additions & 4 deletions web-app/src/components/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ function api<T>(url: string): Promise<T> {
return fetch(url)
.then(response => {
if (!response.ok) {
throw new Error(response.statusText)
console.warn(response.statusText)
}
return response.json()
})
Expand All @@ -35,12 +35,12 @@ const Layout = () => {
<Stack direction="horizontal" >
<Alert variant="light">{currentVersion}</Alert>
<Alert variant="light">
<a href="https://github.com/PhilippDehner/music-ear-trainer">GitHub</a>
<a target="_blank" rel="noreferrer" href="https://github.com/PhilippDehner/music-ear-trainer">GitHub</a>
</Alert>
{latestVersion!=null &&latestVersion!== currentVersion
{latestVersion != null && latestVersion !== currentVersion
? <Alert variant="light">
Newer version available! Download&nbsp;
<a target="_blank" href="https://github.com/PhilippDehner/music-ear-trainer/releases/latest">
<a target="_blank" rel="noreferrer" href="https://github.com/PhilippDehner/music-ear-trainer/releases/latest">
here
</a>.
</Alert>
Expand Down
2 changes: 0 additions & 2 deletions web-app/src/components/ToneSelector.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import Button from "react-bootstrap/Button";
import Form from "react-bootstrap/Form";
import InputGroup from "react-bootstrap/InputGroup";
import React from "react";

import { Tone } from "../types/Tone";
import { ToneRange } from "../types/ToneRange";
Expand Down
2 changes: 1 addition & 1 deletion web-app/src/pages/Home.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { Button, Container } from 'react-bootstrap';
import { Container } from 'react-bootstrap';


import en from "../languages/en.json";
Expand Down
143 changes: 51 additions & 92 deletions web-app/src/pages/Pitch.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
import React, { useState } from "react";
import Button from "react-bootstrap/Button";
import { useState } from "react";
import Alert from "react-bootstrap/Alert";
import Stack from "react-bootstrap/Stack";
import Container from "react-bootstrap/Container";
import Row from "react-bootstrap/Row";
import Col from "react-bootstrap/Col";

import GeneralSettings, { Settings } from "../components/GeneralSettings";
import { Tone } from "../types/Tone";
import ToneSelector from "../components/ToneSelector";
import { Piano } from "@tonejs/piano";
import Trainer from "../types/Trainer";

let generalSettings: Settings = new Settings();
interface Props {
piano: Piano;
pianoLoaded: boolean;
}

enum Result {
Expand All @@ -24,121 +20,84 @@ enum Result {
}

function Pitch(props: Props) {
const [showResult, setShowResult] = useState(false);
const [tonePlaying, setTonePlaying] = useState(
generalSettings.ToneRange.GetRandomTone()
);
const [activePlayButton, setActivePlayButton] = useState<boolean>(true);
const [playedOnce, setPlayedOnce] = useState<boolean>(false);
const [selectorState, setSelectorState] = useState<boolean>(false);
const [selectedTone, setSelectedTone] = useState<Tone | undefined>(undefined);
const [result, setResult] = useState<Result>(Result.undefined);

const sleep = (seconds: number) => {
return new Promise(resolve => setTimeout(resolve, seconds * 1000))
}
const [solutionSelected, setSolutionSelected] = useState(false);

function play() {
tonePlaying.play(props.piano, generalSettings.Volume);
setPlayedOnce(true);
setActivePlayButton(false);
sleep(5).then(r => {
stopPlaying();
})
}

function stopPlaying() {
setActivePlayButton(true)
console.debug("Pitch: stopPlaying function")
tonePlaying.keyUp(props.piano);
}

function SuggestedToneSelected(tone: Tone): void {
console.debug("Pitch: SuggestedToneSelected function")
setSolutionSelected(true);
setSelectedTone(tone);
}

function ClickShowSolution() {
setShowResult(true);
if (tonePlaying.Equals(selectedTone!)) setResult(Result.success);
else if (tonePlaying.Tone === selectedTone?.Tone) setResult(Result.toneRight);
else setResult(Result.false);
console.info("Show solution");
}

function GeneralSettingsChanged() {
console.debug("General settings changed");
console.debug("Pitch: General settings changed");
if (!generalSettings.ToneRange.IsInRange(tonePlaying)) {
setTonePlaying(generalSettings.ToneRange.GetRandomTone());
}
}

function NewToneSet() {
console.debug("Pitch: NewToneSet function")
setTonePlaying(generalSettings.ToneRange.GetRandomTone());
setShowResult(false);
stopPlaying();
}
}

function getResult() {
console.debug("Pitch: getResult function")
let result = Result.undefined

if (tonePlaying.Equals(selectedTone!)) result = Result.success;
else if (tonePlaying.Tone === selectedTone?.Tone) result = Result.toneRight;
else result = Result.false;

let alert;
switch (result) {
case Result.success:
alert = <Alert variant="success">Richtige Tonhöhe!</Alert>; break;
case Result.toneRight:
alert = alert = <Alert variant="warning">Richtiger Ton, falsche Oktave. Es war {tonePlaying.Name}.</Alert>;
break;
case Result.false:
alert = <Alert variant="danger">Falsche Tonhöhe! Es war {tonePlaying.Name}.</Alert>;
break;
default: <Alert hidden />;
}
return alert;
}

let selector = <ToneSelector
label={"Gehörter Ton"}
disabled={!selectorState}
toneRange={generalSettings!.ToneRange}
OnToneSelected={SuggestedToneSelected}
defaultValue="Wähle die Tonhöhe aus, die Du gehört hast"
/>

return (
<>
<GeneralSettings
settings={generalSettings}
OnChanged={GeneralSettingsChanged}
/>
<Stack direction="vertical">
<Container>
<Row>
<Col>
<Button disabled={!activePlayButton} onClick={play}>Abspielen</Button>
</Col>
<Col>
<ToneSelector
label={"Gehörter Ton"}
disabled={!playedOnce}
toneRange={generalSettings!.ToneRange}
OnToneSelected={SuggestedToneSelected}
defaultValue="Wähle die Tonhöhe aus, die Du gehört hast"
/>
</Col>
</Row>
</Container>
<Container>
<Row>
<Col>
<Button
disabled={!(!showResult && selectedTone)}
onClick={ClickShowSolution}
>
Lösung anzeigen
</Button>
</Col>
<Col>
{(() => {
let alert;
switch (result) {
case Result.success:
alert = <Alert variant="success">Richtige Tonhöhe!</Alert>; break;
case Result.toneRight:
alert = alert = <Alert variant="warning">Richtiger Ton, falsche Oktave. Es war {tonePlaying.Name}.</Alert>;
break;
case Result.false:
alert = <Alert variant="danger">Falsche Tonhöhe! Es war {tonePlaying.Name}.</Alert>;
break;
default: <Alert hidden />;
}
return showResult ? alert
: <></>;
})()}
</Col>
</Row>
</Container>
<Container className="mt-3">
{/* <Row>
<Col> */}
<Button disabled={!playedOnce} onClick={NewToneSet}>
Neuer Ton
</Button>
{/* </Col>
</Row> */}
</Container>
</Stack>
<Trainer piano={props.piano}
tonesPlaying={[tonePlaying]}
selector={selector}
ShowSolution={getResult}
CreateNewTask={NewToneSet}
solutionSelected={solutionSelected}
playTonesSimultaneously={false}
SetSelectorStatus={setSelectorState}
pianoLoaded={props.pianoLoaded} />
</>
);
}
Expand Down
13 changes: 4 additions & 9 deletions web-app/src/types/Tone.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,14 @@ class Tone {
}
}

public play(piano: Piano, volume: number = 100) {
// let audio = new Audio(
// require("./../resources/sounds/" + this.Name + ".mp3")
// );
// audio.volume = volume / 100;
// console.info("Play sound:", this.Name);
// audio.play();

public play(piano: Piano, volume: number = 100, secondsplaying: number | undefined = undefined) {
// piano.pedalDown();
piano.keyDown({
note: this.Name,
// time: "+1"
// velocity: 2//Math.round(volume / 20)
});
if (secondsplaying != null && secondsplaying > 0)
piano.keyUp({ note: this.Name, time: "+" + secondsplaying });
console.info("Played tone", this.Name);
}

Expand Down
Loading

0 comments on commit 41c9176

Please sign in to comment.