Fix midi tracks recording previews
This commit is contained in:
parent
3bc980d08d
commit
be8514e2e6
|
|
@ -416,13 +416,23 @@ impl Engine {
|
||||||
if let Some(recording) = &self.midi_recording_state {
|
if let Some(recording) = &self.midi_recording_state {
|
||||||
let current_time = self.playhead as f64 / self.sample_rate as f64;
|
let current_time = self.playhead as f64 / self.sample_rate as f64;
|
||||||
let duration = current_time - recording.start_time;
|
let duration = current_time - recording.start_time;
|
||||||
let notes = recording.get_notes().to_vec();
|
let notes = recording.get_notes_with_active(current_time);
|
||||||
let _ = self.event_tx.push(AudioEvent::MidiRecordingProgress(
|
let _ = self.event_tx.push(AudioEvent::MidiRecordingProgress(
|
||||||
recording.track_id,
|
recording.track_id,
|
||||||
recording.clip_id,
|
recording.clip_id,
|
||||||
duration,
|
duration,
|
||||||
notes,
|
notes,
|
||||||
));
|
));
|
||||||
|
// Keep the snapshot up to date so the UI can display a growing clip bar.
|
||||||
|
let track_id = recording.track_id;
|
||||||
|
let clip_id = recording.clip_id;
|
||||||
|
if let Some(crate::audio::track::TrackNode::Midi(track)) = self.project.get_track_mut(track_id) {
|
||||||
|
if let Some(instance) = track.clip_instances.iter_mut().find(|i| i.clip_id == clip_id) {
|
||||||
|
instance.internal_end = duration;
|
||||||
|
instance.external_duration = duration;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.refresh_clip_snapshot();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -253,6 +253,18 @@ impl MidiRecordingState {
|
||||||
self.completed_notes.len()
|
self.completed_notes.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get all completed notes plus currently-held notes with a provisional duration.
|
||||||
|
/// Used for live preview during recording so held notes appear immediately.
|
||||||
|
pub fn get_notes_with_active(&self, current_time: f64) -> Vec<(f64, u8, u8, f64)> {
|
||||||
|
let mut notes = self.completed_notes.clone();
|
||||||
|
for active in self.active_notes.values() {
|
||||||
|
let time_offset = active.start_time - self.start_time;
|
||||||
|
let provisional_dur = (current_time - active.start_time).max(0.0);
|
||||||
|
notes.push((time_offset, active.note, active.velocity, provisional_dur));
|
||||||
|
}
|
||||||
|
notes
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the note numbers of all currently held (active) notes
|
/// Get the note numbers of all currently held (active) notes
|
||||||
pub fn active_note_numbers(&self) -> Vec<u8> {
|
pub fn active_note_numbers(&self) -> Vec<u8> {
|
||||||
self.active_notes.keys().copied().collect()
|
self.active_notes.keys().copied().collect()
|
||||||
|
|
|
||||||
|
|
@ -5164,6 +5164,29 @@ impl eframe::App for EditorApp {
|
||||||
.filter(|lid| self.recording_layer_ids.contains(lid))
|
.filter(|lid| self.recording_layer_ids.contains(lid))
|
||||||
.copied();
|
.copied();
|
||||||
if let Some(layer_id) = midi_layer_id {
|
if let Some(layer_id) = midi_layer_id {
|
||||||
|
// Lazily create the doc clip + instance on the first progress event
|
||||||
|
// (there is no MidiRecordingStarted event from the backend).
|
||||||
|
let already_exists = self.clip_instance_to_backend_map.values().any(|v| {
|
||||||
|
matches!(v, lightningbeam_core::action::BackendClipInstanceId::Midi(id) if *id == clip_id)
|
||||||
|
});
|
||||||
|
if !already_exists {
|
||||||
|
use lightningbeam_core::clip::{AudioClip, ClipInstance};
|
||||||
|
let clip = AudioClip::new_recording("Recording...");
|
||||||
|
let doc_clip_id = self.action_executor.document_mut().add_audio_clip(clip);
|
||||||
|
let clip_instance = ClipInstance::new(doc_clip_id)
|
||||||
|
.with_timeline_start(self.recording_start_time);
|
||||||
|
let clip_instance_id = clip_instance.id;
|
||||||
|
if let Some(layer) = self.action_executor.document_mut().get_layer_mut(&layer_id) {
|
||||||
|
if let lightningbeam_core::layer::AnyLayer::Audio(audio_layer) = layer {
|
||||||
|
audio_layer.clip_instances.push(clip_instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.clip_instance_to_backend_map.insert(
|
||||||
|
clip_instance_id,
|
||||||
|
lightningbeam_core::action::BackendClipInstanceId::Midi(clip_id),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let doc_clip_id = {
|
let doc_clip_id = {
|
||||||
let document = self.action_executor.document();
|
let document = self.action_executor.document();
|
||||||
document.get_layer(&layer_id)
|
document.get_layer(&layer_id)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue