pub struct MidiSequencer {
pub file: Arc<MidiFile>,
pub time: f64,
pub index: usize,
pub loop_point: Option<(f64, usize)>,
pub loop_play: bool,
pub paused: bool,
pub finished: bool,
held: Vec<(u8, u8)>,
silent: bool,
}Expand description
One sequence, its clock and where it loops.
The gameplay world owns it as a component and advances it once a frame, so
playback state is ordinary data in the world that asks for it: pausing is a
field. Nothing here touches the audio thread; MidiSequencer::advance
sends it midi_jobs.
The voice a sequence plays into is shared with every other sequence in the scene, so anything that cuts a pass short — a rewind, a pause, a loop back to the marker — releases the notes this sequence pressed and leaves the rest alone, instead of letting them ring into the next pass.
Fields§
§file: Arc<MidiFile>The sequence being played.
time: f64Seconds since the sequence started.
index: usizeThe index of the next event to send.
loop_point: Option<(f64, usize)>Where the sequence returns to once it reaches its end: seconds and event
index, from the file’s loop marker. None until a marker is reached,
in which case the sequence repeats from its start.
Written by hand, it loops a passage the file never marked; see
MidiSequencer::advance.
loop_play: boolWhether reaching the end returns to the loop point instead of stopping.
paused: boolWhether the clock stands still.
finished: boolWhether the sequence reached its end and stayed there.
held: Vec<(u8, u8)>The notes this sequence pressed and has not released, by channel and key. A shared voice is why the exact notes are remembered rather than silenced wholesale: an all-notes-off would cut another sequence’s music too.
silent: boolWhether the next advance has to release those notes before it plays anything, because a rewind cut a pass short since the last one.
Implementations§
Source§impl MidiSequencer
impl MidiSequencer
Sourcepub fn rewind(&mut self)
pub fn rewind(&mut self)
Puts the sequence back at its start, playing.
loop_point is left alone, because a hand-written one has no marker to
be restored from. The notes the pass left sounding are released on the
next MidiSequencer::advance: a rewind has no sender to reach the
voice with, and they must not ring into the new pass.
Sourcepub fn advance(&mut self, delta: f64, voice: Entity, audio: &JobSender)
pub fn advance(&mut self, delta: f64, voice: Entity, audio: &JobSender)
Sends every event that came due in the last delta seconds to voice,
and loops or stops when the sequence runs out.
A message’s delay keeps its distance from the start of the frame, so
events due within one frame still reach the synthesizer in order and at
their own offsets. The audio thread can only place them within the fill
it renders, so an event lands closer to its moment than one frame but
not exactly on it.
The voice is shared with every other sequence in the scene, so a note held across the end of a pass would ring into the next one, and a note held when the clock stops would ring through the pause. Reaching the end, looping, pausing and rewinding all release the notes this sequence pressed, and leave the other sequences’ notes sounding.
Sourcefn due(&self) -> Option<(f64, MidiMessage)>
fn due(&self) -> Option<(f64, MidiMessage)>
The event at the cursor, once the clock has reached it.
Read through a borrow that ends with the call, so the advance is free to change the sequence between two events.
Sourcefn pressed(&mut self, kind: MidiEventKind)
fn pressed(&mut self, kind: MidiEventKind)
Records what kind does to the notes this sequence holds sounding.
Auto Trait Implementations§
impl Forget for MidiSequencer
impl Freeze for MidiSequencer
impl RefUnwindSafe for MidiSequencer
impl Send for MidiSequencer
impl Sync for MidiSequencer
impl Unpin for MidiSequencer
impl UnsafeUnpin for MidiSequencer
impl UnwindSafe for MidiSequencer
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
impl<T> Component for Twhere
T: 'static,
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.§impl<T> DowncastSend for T
impl<T> DowncastSend for T
§impl<T> DowncastSync for T
impl<T> DowncastSync for T
§impl<T> DowncastSync for T
impl<T> DowncastSync for T
impl<S, T> Duplex<S> for Twhere
T: FromSample<S> + ToSample<S>,
§impl<S> FromSample<S> for S
impl<S> FromSample<S> for S
fn from_sample_(s: S) -> S
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more§impl<F, T> IntoSample<T> for Fwhere
T: FromSample<F>,
impl<F, T> IntoSample<T> for Fwhere
T: FromSample<F>,
fn into_sample(self) -> T
impl<T> MaybeSync for T
impl<T> Read<Exclusive, BecauseExclusive> for Twhere
T: ?Sized,
§impl<F, T, S> SimdInto<T, S> for Fwhere
T: SimdFrom<F, S>,
S: Simd,
impl<F, T, S> SimdInto<T, S> for Fwhere
T: SimdFrom<F, S>,
S: Simd,
§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self from the equivalent element of its
superset. Read more§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
self is actually part of its subset T (and can be converted to it).§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset but without any property checks. Always succeeds.§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self to the equivalent element of its superset.