old school music tracker audio backend
at main 45 lines 1.5 kB view raw
1use err::LoadErr; 2use impulse_format::{header, pattern}; 3 4use crate::project::song::Song; 5 6pub mod err; 7pub mod impulse_format; 8 9#[derive(Debug, Clone, Copy)] 10pub struct InFilePtr(pub(crate) std::num::NonZeroU32); 11 12impl InFilePtr { 13 /// Move the Read Cursor to the value of the file ptr 14 pub fn move_to_self<S: std::io::Seek>(self, seeker: &mut S) -> Result<(), std::io::Error> { 15 seeker 16 .seek(std::io::SeekFrom::Start(self.0.get().into())) 17 .map(|_| ()) 18 } 19} 20 21/// Default parsing of a song. Should be fine for most usecases. If you want more customization use the different parsing functions directly. 22/// 23/// R should be buffered in some way and not do a syscall on every read. 24/// If you ever find yourself using multiple different reader and/or handlers please open an issue on Github, i will change this to take &dyn. 25pub fn parse_song<R: std::io::Read + std::io::Seek>(reader: &mut R) -> Result<Song, LoadErr> { 26 //ignore defects 27 let mut defect_handler = |_| (); 28 let header = header::ImpulseHeader::parse(reader, &mut defect_handler)?; 29 let mut song = Song::default(); 30 song.copy_values_from_header(&header); 31 32 // parse patterns 33 for (idx, ptr) in header 34 .pattern_offsets 35 .iter() 36 .enumerate() 37 .flat_map(|(idx, ptr)| ptr.map(|ptr| (idx, ptr))) 38 { 39 ptr.move_to_self(reader)?; 40 let pattern = pattern::parse_pattern(reader, &mut defect_handler)?; 41 song.patterns[idx] = pattern; 42 } 43 44 Ok(song) 45}