pub struct Library<'a> {
pub header: Header,
/* private fields */
}Expand description
A piano library parsed: the prefix, and every stroke with its audio.
Strokes borrow their audio from the Piano they were parsed from, so a
transform that drops strokes copies nothing. The fields the container derives —
the stroke count, the per-root counts and every audio offset — are not stored in
the model at all; Library::to_body computes them from the stroke list, which
is what makes an unmodified library rebuild to the bytes it was read from.
Fields§
§header: HeaderThe container header, carried so a transform yields a whole file.
Implementations§
Source§impl<'a> Library<'a>
impl<'a> Library<'a>
Sourcepub fn borrow(file: &'a [u8]) -> Result<Library<'a>, Error>
pub fn borrow(file: &'a [u8]) -> Result<Library<'a>, Error>
A whole .npno file parsed over a borrowed slice: the body is taken as a
subslice, so every stroke’s audio points into file rather than a copy of it.
The container’s checksum is not verified here — the caller has inspected the container.
pub fn stream_version(&self) -> u16
pub fn channels(&self) -> u16
Sourcepub fn block_bytes(&self) -> usize
pub fn block_bytes(&self) -> usize
Bytes in one encoded block, 1022 × channels.
pub fn strokes(&self) -> &[Stroke<'a>]
Sourcepub fn without_audio(&self) -> Library<'static>
pub fn without_audio(&self) -> Library<'static>
This library’s prefix and stroke records with no audio behind them: what a
encode::Donor::Template reads, and nothing Library::to_body can lay out.
Sourcepub fn set_trim(&mut self, index: usize, decibels: u16) -> Result<(), Error>
pub fn set_trim(&mut self, index: usize, decibels: u16) -> Result<(), Error>
Retrim the index-th stroke, in the decibels Stroke::trim reads.
Sourcepub fn name(&self) -> (String, String)
pub fn name(&self) -> (String, String)
The (name, variant) pair, from the same field Piano::name reads.
Sourcepub fn key_map(&self) -> &[u8] ⓘ
pub fn key_map(&self) -> &[u8] ⓘ
The 128-entry key map: the root note that plays each key, or UNCOVERED.
Sourcepub fn key_root(&self, key: u8) -> Result<Option<u8>, Error>
pub fn key_root(&self, key: u8) -> Result<Option<u8>, Error>
The root note whose strokes play key, or None where the map leaves the
key uncovered.
Sourcepub fn keys_for(&self, root: u8) -> Vec<u8> ⓘ
pub fn keys_for(&self, root: u8) -> Vec<u8> ⓘ
The keys the map routes to root, ascending. A root the map never names —
including one outside the MIDI range — has no keys.
Sourcepub fn fine_tune(&self, key: u8) -> Result<i8, Error>
pub fn fine_tune(&self, key: u8) -> Result<i8, Error>
The per-key fine tune at 0x18c + key, in units worth
FINE_TUNE_CENTS_PER_UNIT each. Confirmed on hardware.
Sourcepub fn set_fine_tune(&mut self, key: u8, units: i8) -> Result<(), Error>
pub fn set_fine_tune(&mut self, key: u8, units: i8) -> Result<(), Error>
Retune one key, in the units Library::fine_tune reads.
The unit’s size and direction: Confirmed on hardware. That rewriting the byte retunes the key: Inferred from specimens; not confirmed on hardware.
pub fn set_gain(&mut self, tenths: i8)
Sourcepub fn damper_top(&self) -> u8
pub fn damper_top(&self) -> u8
The highest key the instrument damps at note-off, at 0x40d.
Sourcepub fn set_damper_top(&mut self, key: u8) -> Result<(), Error>
pub fn set_damper_top(&mut self, key: u8) -> Result<(), Error>
Move the damper limit. encode::ALL_KEYS_DAMPED leaves no key ringing; a
key past the last MIDI note is refused.
Sourcepub fn kind_code(&self) -> u8
pub fn kind_code(&self) -> u8
The instrument kind the library states at 0x18; encode::Kind::from_code
names it.
Sourcepub fn set_kind(&mut self, kind: Kind)
pub fn set_kind(&mut self, kind: Kind)
File the library under another kind of instrument.
The byte changes nothing a library sounds like. Confirmed on hardware.
Sourcepub fn long_name(&self) -> Option<String>
pub fn long_name(&self) -> Option<String>
The long name at 0x3c and the voicing at 0x5c, which only
[VERSION_SPLIT_NAME] streams carry. Both are None on the older stream.
They are their own fields, not a split of the Name#Variant one: a library can
spell the long name differently from the name before the #, and the voicing
holds neither the padding nor the size suffix the variant does. Inferred from
specimens; not confirmed on hardware.
pub fn voicing(&self) -> Option<String>
Sourcepub fn set_name(&mut self, name: &str) -> Result<(), Error>
pub fn set_name(&mut self, name: &str) -> Result<(), Error>
Rename the library, leaving the variant alone.
A name holding NAME_SEPARATOR, or text the field would not read back, is
refused; so is one too long for the field it shares with the variant. Nothing
is written unless every field the rename touches accepts its text.
On a stream that carries one, the long name is set to the same text: both are the library’s name, and a rename that moved only one would leave the old name showing wherever the instrument reads the other. Which of the two it reads: Inferred from specimens; not confirmed on hardware. That is why both move.
Sourcepub fn set_variant(&mut self, variant: &str) -> Result<(), Error>
pub fn set_variant(&mut self, variant: &str) -> Result<(), Error>
Replace the variant — the text after NAME_SEPARATOR, where the vendor
records the voicing and the library’s size — leaving both names alone. A
variant holding the separator itself is refused.
Sourcepub fn set_voicing(&mut self, voicing: &str) -> Result<(), Error>
pub fn set_voicing(&mut self, voicing: &str) -> Result<(), Error>
Replace the voicing at 0x5c. Refused on a stream with no such field.
Sourcepub fn set_key_root(&mut self, key: u8, root: Option<u8>) -> Result<(), Error>
pub fn set_key_root(&mut self, key: u8, root: Option<u8>) -> Result<(), Error>
Route key to root, or to nothing when root is None.
A root the directory does not record is refused: the instrument would have no stroke to play.
That the instrument follows a rewritten map — a key routed to another root, or to nothing: Inferred from specimens; not confirmed on hardware.
Sourcepub fn drop_bank(&mut self, bank: Bank) -> Change
pub fn drop_bank(&mut self, bank: Bank) -> Change
Drop every stroke of one bank — the resonance set turns a large library into a small one, the release set silences the note-off sample.
For Bank::Release, the instrument damps the note at note-off where the
library it came from plays a release tail. Confirmed on hardware.
Sourcepub fn keep_layers(&mut self, keep: &Layers) -> Change
pub fn keep_layers(&mut self, keep: &Layers) -> Change
Keep only the layers keep selects, per root and bank.
Confirmed on hardware. A library with its softest layers dropped plays the softest one left at the velocities they had, and is unchanged at loud ones.
Sourcepub fn retain_strokes(
&mut self,
keep: impl FnMut(&Stroke<'a>) -> bool,
) -> Change
pub fn retain_strokes( &mut self, keep: impl FnMut(&Stroke<'a>) -> bool, ) -> Change
Keep the strokes keep accepts and drop the rest, then uncover the keys whose
root has gone.
The selection every other transform here is a named case of, for a caller whose own is none of them — one layer on one root, say. A stroke carries its own predictor seeds and its blocks overlap only each other, so whichever subset is left re-lays into a library the writer can lay out.
Inferred from specimens; not confirmed on hardware. Library::drop_bank and
Library::keep_layers are the two selections a hardware read covers.
Sourcepub fn cut_range(&mut self, range: RangeInclusive<u8>) -> Result<Change, Error>
pub fn cut_range(&mut self, range: RangeInclusive<u8>) -> Result<Change, Error>
Uncover every key outside range, then drop the roots nothing plays any
more. Keys inside the range keep the roots they had.
That an uncovered key falls silent rather than reaching for a neighbouring root: Inferred from specimens; not confirmed on hardware.
Sourcepub fn split_at(&self, key: u8) -> Result<(Library<'a>, Library<'a>), Error>
pub fn split_at(&self, key: u8) -> Result<(Library<'a>, Library<'a>), Error>
Two libraries, one covering the keys below key and one covering key and
above, each cut the way Library::cut_range cuts.
A root whose keys straddle key lands in both halves — each half has to be
playable on its own — so the two together hold more strokes than the one they
came from. Each half carries Library::cut_range’s provenance.
Sourcepub fn to_body(&self) -> Result<Vec<u8>, Error>
pub fn to_body(&self) -> Result<Vec<u8>, Error>
Lay the body out: the prefix with its counts rewritten, the directory with every audio offset recomputed, the zero gap, then the audio spans in directory order.
Confirmed on hardware. A body laid out here, with a directory the transforms shortened and every span moved, is accepted by the instrument and plays at the level the library it came from plays at.
Sourcepub fn to_piano(&self) -> Result<Piano, Error>
pub fn to_piano(&self) -> Result<Piano, Error>
The library as a file, ready to write. The container recomputes its own checksum.
The u32 at body 0x06 is unique per file and is not a checksum, a size or a
hash of anything in it; with nothing to recompute it from, an edit carries
it over rather than inventing a value. The hardware evidence reaches no further
than this: a library carrying its source’s word loads and plays. Confirmed on
hardware. What the word means is open.