Skip to content

Commit 7b57d01

Browse files
committed
More improvements
1 parent 39ae19a commit 7b57d01

File tree

1 file changed

+38
-43
lines changed

1 file changed

+38
-43
lines changed

neothesia/src/scene/playing_scene/midi_player.rs

Lines changed: 38 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::{
55
song::{PlayerConfig, Song},
66
};
77
use std::{
8-
collections::{HashSet, VecDeque},
8+
collections::{HashMap, HashSet},
99
time::{Duration, Instant},
1010
};
1111

@@ -194,21 +194,24 @@ pub enum MidiEventSource {
194194
User,
195195
}
196196

197+
type NoteId = u8;
198+
197199
#[derive(Debug)]
198-
struct UserPress {
200+
struct NotePress {
199201
timestamp: Instant,
200-
note_id: u8,
201202
}
202203

203204
#[derive(Debug)]
204205
pub struct PlayAlong {
205206
user_keyboard_range: piano_math::KeyboardRange,
206207

207-
required_notes: HashSet<u8>,
208-
209-
// List of user key press events that happened in last 500ms,
210-
// used for play along leeway logic
211-
user_pressed_recently: VecDeque<UserPress>,
208+
/// Notes required to proggres further in the song
209+
required_notes: HashMap<NoteId, NotePress>,
210+
/// List of user key press events that happened in last 500ms,
211+
/// used for play along leeway logic
212+
user_pressed_recently: HashMap<NoteId, NotePress>,
213+
/// File notes that had NoteOn event, but no NoteOff yet
214+
in_proggres_file_notes: HashSet<NoteId>,
212215
}
213216

214217
impl PlayAlong {
@@ -217,61 +220,51 @@ impl PlayAlong {
217220
user_keyboard_range,
218221
required_notes: Default::default(),
219222
user_pressed_recently: Default::default(),
223+
in_proggres_file_notes: Default::default(),
220224
}
221225
}
222226

223227
fn update(&mut self) {
228+
// Instead of calling .elapsed() per item let's fetch `now` once, and subtract it ourselves
224229
let now = Instant::now();
225230
let threshold = Duration::from_millis(500);
226231

227232
// Retain only the items that are within the threshold
228-
self.user_pressed_recently.retain(|item| {
229-
let elapsed = now - item.timestamp;
230-
elapsed <= threshold
231-
});
233+
self.user_pressed_recently
234+
.retain(|_, item| now.duration_since(item.timestamp) <= threshold);
232235
}
233236

234237
fn user_press_key(&mut self, note_id: u8, active: bool) {
235-
if active {
236-
let timestamp = Instant::now();
237-
// Check if note_id already exists in the collection
238-
if let Some(item) = self
239-
.user_pressed_recently
240-
.iter_mut()
241-
.find(|item| item.note_id == note_id)
242-
{
243-
// Update the timestamp for existing note_id
244-
item.timestamp = timestamp;
245-
} else {
246-
// Push a new UserPress
247-
self.user_pressed_recently
248-
.push_back(UserPress { timestamp, note_id });
249-
}
238+
let timestamp = Instant::now();
250239

251-
// Check if note_id is in required_notes
252-
if self.required_notes.contains(&note_id) {
253-
// If it's in required_notes, remove it from presed_recently to avoid skips/repeated count
240+
if active {
241+
// Check if note has already been played by a file
242+
if self.required_notes.remove(&note_id).is_none() {
243+
// This note was not played by file yet, place it in recents
254244
self.user_pressed_recently
255-
.retain(|item| item.note_id != note_id);
245+
.insert(note_id, NotePress { timestamp });
256246
}
257-
self.required_notes.remove(&note_id);
258247
}
259248
}
260249

261250
fn file_press_key(&mut self, note_id: u8, active: bool) {
251+
let timestamp = Instant::now();
262252
if active {
263-
if let Some((id, _)) = self
264-
.user_pressed_recently
265-
.iter()
266-
.enumerate()
267-
.find(|(_, item)| item.note_id == note_id)
268-
{
269-
self.user_pressed_recently.remove(id);
270-
} else {
271-
self.required_notes.insert(note_id);
253+
// Check if note got pressed earlier 500ms (user_pressed_recently)
254+
if self.user_pressed_recently.remove(&note_id).is_none() {
255+
// Player never pressed that note, let it reach required_notes
256+
257+
// Ignore overlapping notes
258+
if self.in_proggres_file_notes.contains(&note_id) {
259+
return;
260+
}
261+
262+
self.required_notes.insert(note_id, NotePress { timestamp });
272263
}
264+
265+
self.in_proggres_file_notes.insert(note_id);
273266
} else {
274-
self.required_notes.remove(&note_id);
267+
self.in_proggres_file_notes.remove(&note_id);
275268
}
276269
}
277270

@@ -295,7 +288,9 @@ impl PlayAlong {
295288
}
296289

297290
pub fn clear(&mut self) {
298-
self.required_notes.clear()
291+
self.required_notes.clear();
292+
self.user_pressed_recently.clear();
293+
self.in_proggres_file_notes.clear();
299294
}
300295

301296
pub fn are_required_keys_pressed(&self) -> bool {

0 commit comments

Comments
 (0)