Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
10 kB · 304 lines
Rust
at sans-io
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305use crate::file::{SansIO, err};use crate::project::event_command::NoteCommand;use crate::project::note_event::{Note, NoteEvent, VolumeEffect};use crate::project::pattern::{InPatternPosition, Pattern};use core::error::Error;use core::fmt::Display;use std::io::Read;
use core::mem;
/// reader should be buffered in some way and not do a syscall on every read call.////// This function does a lot of read callspub fn parse_pattern<R: Read>(reader: &mut R) -> Result<Pattern, err::LoadErr> { const PATTERN_HEADER_SIZE: usize = 8;
let (length, num_rows) = { let mut header = [0; PATTERN_HEADER_SIZE]; reader.read_exact(&mut header)?; ( u64::from(u16::from_le_bytes([header[0], header[1]])) + PATTERN_HEADER_SIZE as u64, u16::from_le_bytes([header[2], header[3]]), ) };
// a guarantee given by the impulse tracker "specs" if length >= 64_000 { return Err(err::LoadErr::Invalid); }
if !(32..=200).contains(&num_rows) { return Err(err::LoadErr::Invalid); }
let mut pattern = Pattern::new(num_rows);
let mut row_num: u16 = 0;
let mut last_mask = [0; 64]; let mut last_event = [NoteEvent::default(); 64];
let mut scratch = [0; 1];
while row_num < num_rows { let channel_variable = scratch[0];
if channel_variable == 0 { row_num += 1; continue; }
let channel = (channel_variable - 1) & 63; // 64 channels, 0 based let channel_id = usize::from(channel);
let maskvar = if (channel_variable & 0b10000000) != 0 { reader.read_exact(&mut scratch)?; let val = scratch[0]; last_mask[channel_id] = val; val } else { last_mask[channel_id] };
let mut event = NoteEvent::default();
// Note if (maskvar & 0b00000001) != 0 { reader.read_exact(&mut scratch)?; // let note = match Note::new(scratch[0]) { // Ok(n) => n, // Err(_) => { // // defect_handler(LoadDefect::OutOfBoundsValue); // Note::default() // } // }; let note = Note::new(scratch[0]).unwrap_or_default();
event.note = note; last_event[channel_id].note = note; }
// Instrument / Sample if (maskvar & 0b00000010) != 0 { reader.read_exact(&mut scratch)?; let instrument = scratch[0];
event.sample_instr = instrument; last_event[channel_id].sample_instr = instrument; }
// Volume if (maskvar & 0b00000100) != 0 { reader.read_exact(&mut scratch)?; // let vol_pan = match vol_pan_raw.try_into() { // Ok(v) => v, // Err(_) => { // // defect_handler(LoadDefect::OutOfBoundsValue); // VolumeEffect::default() // } // }; let vol_pan = volumeeffect_try_from(scratch[0]).unwrap_or_default();
last_event[channel_id].vol = vol_pan; event.vol = vol_pan; }
// Effect if (maskvar & 0b00001000) != 0 { reader.read_exact(&mut scratch)?; let command = scratch[0]; reader.read_exact(&mut scratch)?; let cmd_val = scratch[0];
// let cmd = match NoteCommand::try_from((command, cmd_val)) { // Ok(cmd) => cmd, // Err(_) => { // // defect_handler(LoadDefect::OutOfBoundsValue); // NoteCommand::default() // } // }; let cmd = note_command_try_from((command, cmd_val)).unwrap_or_default();
last_event[channel_id].command = cmd; event.command = cmd; }
// Same note if (maskvar & 0b00010000) != 0 { event.note = last_event[channel_id].note; }
// Same Instr / Sample if (maskvar & 0b00100000) != 0 { event.sample_instr = last_event[channel_id].sample_instr; }
// Same volume if (maskvar & 0b01000000) != 0 { event.vol = last_event[channel_id].vol; }
// Same Command if (maskvar & 0b10000000) != 0 { event.command = last_event[channel_id].command; }
pattern.set_event( InPatternPosition { row: row_num, channel, }, event, ); }
Ok(pattern)}
#[derive(Debug, Clone, Copy)]pub struct InvalidVolumeEffect;
impl Display for InvalidVolumeEffect { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "Invalid Volume Effect") }}
impl Error for InvalidVolumeEffect {}
/// IT Tracker Format Conversion/// no way to get None, as then it just doesn't get setfn volumeeffect_try_from(value: u8) -> Result<VolumeEffect, InvalidVolumeEffect> { match value { 0..=64 => Ok(VolumeEffect::Volume(value)), 65..=74 => Ok(VolumeEffect::FineVolSlideUp(value - 65)), 75..=84 => Ok(VolumeEffect::FineVolSlideDown(value - 75)), 85..=94 => Ok(VolumeEffect::VolSlideUp(value - 85)), 95..=104 => Ok(VolumeEffect::VolSlideDown(value - 95)), 105..=114 => Ok(VolumeEffect::PitchSlideDown(value - 105)), 115..=124 => Ok(VolumeEffect::PitchSlideUp(value - 115)), 128..=192 => Ok(VolumeEffect::Panning(value - 128)), 193..=202 => Ok(VolumeEffect::SlideToNoteWithSpeed(value - 193)), 203..=212 => Ok(VolumeEffect::VibratoWithSpeed(value - 203)), _ => Err(InvalidVolumeEffect), }}
#[derive(Debug, Clone, Copy)]pub struct UnknownNoteCommand;
impl Display for UnknownNoteCommand { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "Unknown Note Command") }}
impl Error for UnknownNoteCommand {}
fn note_command_try_from( (command_type, command_value): (u8, u8),) -> Result<NoteCommand, UnknownNoteCommand> { match command_type { 0 => Ok(NoteCommand::None), 1 => Ok(NoteCommand::SetTempo(command_value)), 2 => Ok(NoteCommand::JumpToOrder(command_value)), 3 => Ok(NoteCommand::BreakToRow(command_value)), 4 => Ok(NoteCommand::VolumeSlideDown(command_value)), 5 => Ok(NoteCommand::PitchSlideDown(command_value)), 6 => Ok(NoteCommand::PitchSlideUp(command_value)), 7 => Ok(NoteCommand::SlideToNote(command_value)), 8 => Ok(NoteCommand::Vibrato(command_value)), 9 => Ok(NoteCommand::Tremor(command_value)), 10 => Ok(NoteCommand::Arpeggio(command_value)), 11 => Ok(NoteCommand::VibratoAndVolSlideDown(command_value)), 12 => Ok(NoteCommand::SlideToNoteAndVolSlideDown(command_value)), 13 => Ok(NoteCommand::SetChannelVol(command_value)), 14 => Ok(NoteCommand::ChannelVolumeSlideDown(command_value)), 15 => Ok(NoteCommand::SetSampleOffset(command_value)), 16 => Ok(NoteCommand::PanningSlide(command_value)), 17 => Ok(NoteCommand::RetriggerNote(command_value)), 18 => Ok(NoteCommand::Tremolo(command_value)), 19 => Ok(NoteCommand::AlmostEverything(command_value)), 20 => Ok(NoteCommand::TempoChange(command_value)), 21 => Ok(NoteCommand::FineVibrato(command_value)), 22 => Ok(NoteCommand::SetGlobalVolume(command_value)), 23 => Ok(NoteCommand::GlobalVolumeSlide(command_value)), 24 => Ok(NoteCommand::SetPanning(command_value)), 25 => Ok(NoteCommand::Panbrello(command_value)), 26 => Ok(NoteCommand::MIDIMacros(command_value)), _ => Err(UnknownNoteCommand), }}
pub struct PatternParser { length: u64, num_rows: u16, // changed while parsing pattern: Pattern, curren_row: u16, last_mask: [u8; 64], last_event: [NoteEvent; 64],}
impl PatternParser { const PATTERN_HEADER_SIZE: usize = 8;
pub fn new(header: &[u8; Self::PATTERN_HEADER_SIZE]) -> Result<Self, err::LoadErr2> { let (length, num_rows) = ( u64::from(u16::from_le_bytes([header[0], header[1]])) + Self::PATTERN_HEADER_SIZE as u64, u16::from_le_bytes([header[2], header[3]]), );
// a guarantee given by the impulse tracker "specs" if length >= 64_000 { return Err(err::LoadErr2::Invalid); }
if !(32..=200).contains(&num_rows) { return Err(err::LoadErr2::Invalid); }
Ok(Self { length, num_rows, pattern: Pattern::new(num_rows), curren_row: 0, last_mask: [0; _], last_event: [NoteEvent::default(); _], }) }
/// needs at most 7 bytes at once pub fn parse(&mut self, mut buf: &[u8]) -> SansIO<Pattern> { let mut read = 0; while self.curren_row < self.num_rows { let Some(&channel_variable) = buf.split_off_first() else { return SansIO::Pending(read); }; read += 1; if channel_variable == 0 { self.curren_row += 1; continue; } let channel = (channel_variable - 1) & 63; // 64 channels, 0 based let channel_id = usize::from(channel);
let maskvar = if (channel_variable & 0b10000000) != 0 { let Some(&val) = buf.split_off_first() else { return SansIO::Pending(read); }; read += 1; self.last_mask[channel_id] = val; val } else { self.last_mask[channel_id] };
let mut event = NoteEvent::default(); } let finished = mem::replace(&mut self.pattern, Pattern::new(self.num_rows)); SansIO::Finished(finished, read) }}