Skip to content

Commit

Permalink
1. use svh to cope with mobile view port height.
Browse files Browse the repository at this point in the history
2. add a report link.
3. fix routing bug caused by unhandled clean up.
  • Loading branch information
Zilong-L committed Aug 31, 2024
1 parent abdfff6 commit 291daad
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 49 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"dev": "vite --host",
"build": "vite build",
"lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview",
Expand Down
12 changes: 7 additions & 5 deletions src/Components/EarTrainers/DegreeTrainer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,12 @@ const EarTrainer = () => {
})();
return ()=>{
console.log('midi is not deleted, but delete listener')
const inputs = midi.inputs.values();
for (let input = inputs.next(); input && !input.done; input = inputs.next()) {
input.value.onmidimessage = null
}
if(midi){
const inputs = midi.inputs.values();
for (let input = inputs.next(); input && !input.done; input = inputs.next()) {
input.value.onmidimessage = null
}
}
}
}, []);
const renderRecords = () => {
Expand Down Expand Up @@ -195,7 +197,7 @@ const EarTrainer = () => {
display: 'flex',
flexDirection: 'column',
justifyContent: 'space-between',
height: 'calc(100vh - 64px)',
height: 'calc(100svh - 64px)',
paddingY: '1rem',
paddingX: '1.5rem',
}}
Expand Down
20 changes: 14 additions & 6 deletions src/Components/EarTrainers/SequenceTrainer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,17 @@ const SequenceTrainer = () => {
startGame();
};

const handleReplay = () => {
playSequence(0); // 立即播放整个序列
};

useEffect(() => {
const handleKeyPress = (event) => {
const now = new Date();
console.log(`Current Date and Time: ${now.toISOString()}`);
const key = event.key;
if (key === 'r') {
playSequence(currentSequence);
handleReplay();
return;
}

Expand Down Expand Up @@ -106,9 +112,11 @@ const SequenceTrainer = () => {
})();
return () => {
console.log('midi is not deleted, but delete listener');
const inputs = midi.inputs.values();
for (let input = inputs.next(); input && !input.done; input = inputs.next()) {
input.value.onmidimessage = null;
if(midi){
const inputs = midi.inputs.values();
for (let input = inputs.next(); input && !input.done; input = inputs.next()) {
input.value.onmidimessage = null;
}
}
endGame();
};
Expand Down Expand Up @@ -208,7 +216,7 @@ const SequenceTrainer = () => {
display: 'flex',
flexDirection: 'column',
justifyContent: 'space-between',
height: 'calc(100vh - 64px)',
height: 'calc(100svh - 64px)',
paddingY: '1rem',
paddingX: '1.5rem',
}}
Expand Down Expand Up @@ -269,7 +277,7 @@ const SequenceTrainer = () => {
<Button
variant="contained"
color="primary"
onClick={() => playSequence(currentSequence)}
onClick={handleReplay}
fullWidth
sx={{
textTransform: 'none',
Expand Down
1 change: 0 additions & 1 deletion src/Components/EarTrainers/SequenceTrainerSettings.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ function SequenceTrainerSettings({
setShowStatistics(false);
setIsDeleteConfirmOpen(false);
saveSettings();

playSequence();
};

Expand Down
3 changes: 3 additions & 0 deletions src/Components/LayoutWrapper.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ const ThemedContent = () => {
<Route path="/ear-trainer/sequence-trainer" element={<SequenceTrainer />} /> {/* 新增的 Sequence Trainer 路由 */}
</Routes>

<Box sx={{ textAlign: 'center', padding: 2 }}>
<p>我是开源的,欢迎访问 <a href="https://github.com/Zilong-L/EarTrainer/issues" target="_blank" rel="noopener noreferrer" style={{ color: 'lightblue' }}>GitHub 仓库</a> 提出功能需求</p>
</Box>
</Box>
</ThemeProvider>
);
Expand Down
54 changes: 23 additions & 31 deletions src/hooks/useSequenceTrainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as Tone from 'tone';
import { degrees } from '@utils/Constants';
import { getPianoInstance, getDroneInstance } from '@utils/ToneInstance';
import useSequenceTrainerSettings from './useSequenceTrainerSettings';

import { playNotes, cancelAllSounds } from '@utils/ToneInstance';
const useSequenceTrainer = () => {
const {
bpm,
Expand Down Expand Up @@ -37,14 +37,15 @@ const useSequenceTrainer = () => {
const piano = getPianoInstance();
const drone = getDroneInstance();
const pianoSampler = piano.sampler;
const generateRandoSequenceBasedOnRoot = () => {
const sequence = [];
for (let i = 0; i < sequenceLength; i++) {
const randomIndex = Math.floor(Math.random() * possibleMidiList.length);
sequence.push(possibleMidiList[randomIndex]);
}
return sequence;
};
// const generateRandoSequenceBasedOnRoot = () => {
// const sequence = [];
// for (let i = 0; i < sequenceLength; i++) {
// const randomIndex = Math.floor(Math.random() * possibleMidiList.length);
// sequence.push(possibleMidiList[randomIndex]);
// }
// console.log('genertated',sequence);
// return sequence;
// };
useEffect(() => {
drone.updateRoot(rootNote);
drone.setVolume(droneVolume);
Expand Down Expand Up @@ -78,33 +79,23 @@ const useSequenceTrainer = () => {
}, [activeNote]);

const startGame = () => {
Tone.getTransport().stop();
Tone.getTransport().position = 0;
Tone.getTransport().cancel();
setGameStarted(true);
setDisabledNotes([]);
const sequence = generateRandoSequenceBasedOnRoot();
const sequence = generateRandomSequenceBasedOnRoot();
setCurrentSequence(sequence);
setSequenceIndex(0); // 重置序列索引
playSequence(sequence, 1);
playSequence(sequence,1);
drone.start();
Tone.getTransport().start();
};

const playSequence = (sequence = null, delay = 0) => {
Tone.getTransport().stop();
Tone.getTransport().position = 0;
Tone.getTransport().cancel();
if (!sequence) {
const playSequence = (sequence=null,delay=0) => {
if(!sequence){
sequence = currentSequence;
}
if (pianoSampler._buffers && pianoSampler._buffers.loaded) {
sequence.forEach((note, index) => {
pianoSampler.triggerAttackRelease(note, 60 / bpm, Tone.now() + delay + index * (60 / bpm));
});
}
playNotes(sequence, delay,bpm);
};


const generateRandomSequenceBasedOnRoot = () => {
if (possibleMidiList.length === 0) return [];
const sequence = [];
Expand All @@ -124,25 +115,28 @@ const useSequenceTrainer = () => {
setDisabledNotes([]);
updatePracticeRecords(guessedDegree, isCorrect);
setSequenceIndex((prevIndex) => {
pianoSampler.triggerAttackRelease(currentSequence[prevIndex], 60 / bpm);
const nextIndex = prevIndex + 1;

if (nextIndex >= currentSequence.length) {
const newSequence = generateRandomSequenceBasedOnRoot();
setCurrentSequence(newSequence);
playSequence(newSequence);
playSequence(newSequence,1);
return 0;
} else {
// playSequence(currentSequence.slice(nextIndex));
return nextIndex;
}
});
setActiveNote(null);
} else {
pianoSampler.triggerAttackRelease(guessedNote,60/bpm);
if (!disabledNotes.includes(guessedNote)) {
setDisabledNotes((prev) => [...prev, guessedNote]);
updatePracticeRecords(guessedDegree, isCorrect);
}
playSequence([guessedNote]);
}
const now = new Date();
console.log(`Current Date and Time: ${now.toISOString()}`);
setActiveNote(null);
};

Expand All @@ -157,9 +151,7 @@ const useSequenceTrainer = () => {
}, [possibleMidiList,sequenceLength]);

const endGame = () => {
Tone.getTransport().stop();
Tone.getTransport().position = 0;
Tone.getTransport().cancel();
cancelAllSounds();
setGameStarted(false);
setDisabledNotes([]);
drone.stop();
Expand Down
44 changes: 39 additions & 5 deletions src/utils/ToneInstance.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ import * as Tone from 'tone';
let pianoSampler = null;
let droneInstance = null;



let pianoGainNode = null
function getPianoGainNode() {
if (!pianoGainNode) {
Expand Down Expand Up @@ -37,8 +35,6 @@ function getPianoInstance() {
};
}



function getDroneInstance() {
let masterGainNode = null;
let rootMax = Tone.Frequency("C5").toMidi();
Expand Down Expand Up @@ -117,5 +113,43 @@ function getDroneInstance() {
}


function playNotes(input, delay = 0, bpm = 60) {
// 取消之前的播放
const activeTransport = Tone.getTransport();
if (activeTransport) {
activeTransport.stop();
activeTransport.cancel();
}

const pianoInstance = getPianoInstance();
const { sampler } = pianoInstance;

// 处理 MIDI 输入和音符字符串输入
const notes = Array.isArray(input) ? input : [input];

notes.forEach((note, index) => {
activeTransport.schedule((time) => {
if (sampler._buffers && sampler._buffers.loaded) {
// 检查是否为 MIDI 值
if (typeof note === 'number') {
sampler.triggerAttackRelease(Tone.Frequency(note, 'midi').toNote(), 60 / bpm, time);
} else {
sampler.triggerAttackRelease(note, 60 / bpm, time);
}
}
}, `+${index * (60 / bpm) + delay}`);
});

activeTransport.start();
}

function cancelAllSounds() {
const activeTransport = Tone.getTransport();

if (activeTransport) {
activeTransport.stop();
activeTransport.cancel();
}
}

export { getPianoInstance, getDroneInstance };
export { getPianoInstance, getDroneInstance, playNotes, cancelAllSounds };

0 comments on commit 291daad

Please sign in to comment.