pub struct EnvelopeLayer {Show 22 fields
pub notes: Vec<NoteEnvelope>,
pub pooled: Vec<bool>,
pub attack: Estimate<Stats<Seconds>, Seconds>,
pub hold: Estimate<Stats<Seconds>, Seconds>,
pub decay: Estimate<Stats<Seconds>, Seconds>,
pub sustain: Estimate<Stats<Decibels>, Decibels>,
pub note_off_offset: Estimate<Stats<Seconds>, Seconds>,
pub release: Estimate<Stats<Seconds>, Seconds>,
pub tail_rt60: Estimate<Stats<Seconds>, Seconds>,
pub tail_weight: Estimate<Stats<Ratio>, Ratio>,
pub release_confidence: Option<Level>,
pub tail_votes: TailVotes,
pub level_spread: Estimate<Decibels, NoSpread>,
pub levels: Vec<Option<Decibels>>,
pub ripple: Option<Decibels>,
pub residual: Option<Decibels>,
pub pump: Option<Pump>,
pub overlap_fraction: f64,
pub flags: EnvelopeFlags,
pub confidence: Confidence<NoSpread>,
pub counts: EnvelopeCounts,
pub silent: Vec<(Seconds, MidiPitch)>,
}Expand description
The envelope layer of a stem.
Fields§
§notes: Vec<NoteEnvelope>The envelope of each read note, in note order.
pooled: Vec<bool>Which of notes form the pool.
attack: Estimate<Stats<Seconds>, Seconds>The attack over the pool: 0 to 100 % for a linear ramp.
hold: Estimate<Stats<Seconds>, Seconds>The hold over the pool.
decay: Estimate<Stats<Seconds>, Seconds>The decay over the pool.
sustain: Estimate<Stats<Decibels>, Decibels>The sustain level from the peak over the pool.
note_off_offset: Estimate<Stats<Seconds>, Seconds>The note’s end in the list minus its knee, over the pooled notes with a knee.
release: Estimate<Stats<Seconds>, Seconds>The linear release over the pool; no estimate when the tail hides it.
tail_rt60: Estimate<Stats<Seconds>, Seconds>The RT60 of the tail over the pooled notes that have one.
tail_weight: Estimate<Stats<Ratio>, Ratio>The weight of the tail over the pooled notes with a fit.
release_confidence: Option<Level>How far to trust the release: low when no release is written; None
when no pooled note has a tail fit.
tail_votes: TailVotesThe votes that the tail is reverb.
level_spread: Estimate<Decibels, NoSpread>The 90th minus the 10th percentile of the full-band levels of the
pooled notes. read_levels sets it; before,
it holds no estimate.
levels: Vec<Option<Decibels>>The full-band level of each note of the list, in list order; None
when its span holds no frame. Unlike peak_db, it compares notes
that read different harmonics. read_levels
sets it; before, it is empty.
ripple: Option<Decibels>The median ripple over the pool.
residual: Option<Decibels>The median fit residual over the pool.
pump: Option<Pump>The pump read; None with fewer than PUMP_BEATS_MIN sustained
beats.
overlap_fraction: f64The share of the notes in the list that overlap another.
flags: EnvelopeFlagsThe flags.
confidence: Confidence<NoSpread>The confidence of the layer as a whole; no estimate without notes.
counts: EnvelopeCountsThe counts behind the summary.
silent: Vec<(Seconds, MidiPitch)>The onset and pitch of each note whose amp proxy peaks at the silence floor.
Implementations§
Source§impl EnvelopeLayer
impl EnvelopeLayer
Sourcepub fn of(input: &EnvelopeInput<'_>) -> Result<Self, EnvelopeError>
pub fn of(input: &EnvelopeInput<'_>) -> Result<Self, EnvelopeError>
Reads the envelope layer of a stem.
A 220 Hz sine held from 0.1 s, released linearly from 0.8 to 0.9 s, reads one note at a sustain near its peak, with its note-off knee where the release starts:
use sound_to_patch::audio::{BeatGrid, SampleRate};
use sound_to_patch::estimate::envelope::{EnvelopeInput, EnvelopeLayer};
use sound_to_patch::notes::{Note, NoteList};
use sound_to_patch::units::{Bpm, MidiPitch, Seconds};
let rate = SampleRate::new(22_050)?;
let mono: Vec<f64> = (0..22_050)
.map(|n| {
let t = f64::from(n) / 22_050.0;
let gain = if t < 0.1 { 0.0 } else { ((0.9 - t) / 0.1).clamp(0.0, 1.0) };
0.5 * gain * (std::f64::consts::TAU * 220.0 * t).sin()
})
.collect();
let note = Note::new(Seconds::new(0.1)?, Seconds::new(0.9)?, MidiPitch::new(57.0)?)?;
let notes = NoteList::new(vec![note]);
let grid = BeatGrid::new(Bpm::new(120.0)?, Seconds::new(0.0)?);
let layer = EnvelopeLayer::of(&EnvelopeInput { stereo: None, mono: &mono, rate, notes: ¬es, grid })?;
assert_eq!(layer.counts.read, 1);
let sustain = layer.sustain.value().map(|s| s.median().get());
assert!(sustain.is_some_and(|s| s > -1.0));
let knee = layer.notes[0].knee.map(Seconds::get);
assert!(knee.is_some_and(|k| (k - 0.8).abs() < 0.01));§Errors
Returns an EnvelopeError when a harmonic band reaches the
Nyquist frequency, or a confidence cannot be built.
Sourcepub fn read_levels(
&mut self,
input: &EnvelopeInput<'_>,
mono_line: bool,
) -> Result<(), EnvelopeError>
pub fn read_levels( &mut self, input: &EnvelopeInput<'_>, mono_line: bool, ) -> Result<(), EnvelopeError>
Reads the full-band level of each note and their spread over the
pool, as LEVEL_SPREAD_CONVENTION defines them. The levels wait
for the voices layer, which reads this layer first: mono_line is
the one voicing the final notes use, and on a mono line a level’s
span ends at the next later onset.
§Errors
Returns an EnvelopeError when the spread’s confidence cannot be
built.
Trait Implementations§
Source§impl Clone for EnvelopeLayer
impl Clone for EnvelopeLayer
Source§impl Debug for EnvelopeLayer
impl Debug for EnvelopeLayer
Source§impl PartialEq for EnvelopeLayer
impl PartialEq for EnvelopeLayer
impl StructuralPartialEq for EnvelopeLayer
Auto Trait Implementations§
impl Freeze for EnvelopeLayer
impl RefUnwindSafe for EnvelopeLayer
impl Send for EnvelopeLayer
impl Sync for EnvelopeLayer
impl Unpin for EnvelopeLayer
impl UnsafeUnpin for EnvelopeLayer
impl UnwindSafe for EnvelopeLayer
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> CloneAny for T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§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
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