aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Chris Xiong <chirs241097@gmail.com> 2025-03-02 21:21:56 -0500
committerGravatar Chris Xiong <chirs241097@gmail.com> 2025-03-02 21:21:56 -0500
commit473d6e1d506cb6e0ac3c763871c5c8f9e4395ae5 (patch)
treec5f0397f6899fdb3603c393ed2bf3fcd0fa1572f
parente9aaf095a805f08fccc4407c8f1dc60780382f63 (diff)
downloadit2midi-473d6e1d506cb6e0ac3c763871c5c8f9e4395ae5.tar.xz
Sample loading and conversion.
-rw-r--r--src/itfile.rs42
-rw-r--r--src/main.rs6
2 files changed, 46 insertions, 2 deletions
diff --git a/src/itfile.rs b/src/itfile.rs
index 311207b..a4b2d83 100644
--- a/src/itfile.rs
+++ b/src/itfile.rs
@@ -171,24 +171,62 @@ pub struct SampHeader
pub struct Samp
{
- pub header: SampHeader
+ pub header: SampHeader,
+ pub data: Vec<u8>
}
impl Samp
{
+ // This does NOT load the actual sample data!
pub fn load(f: &mut File) -> Result<Samp, self::Error>
{
let header: SampHeader = read_struct(f)?;
- Ok(Samp{header})
+ let mut ret = Samp{header, data: Vec::new()};
+ f.seek(SeekFrom::Start(ret.header.samp_ptr.into()))?;
+ if !ret.is_compressed()
+ {
+ let data_len = ret.header.length * ret.num_channels() as u32 * ret.bits_per_sample() as u32 / 8;
+ ret.data.resize(data_len as usize, 0);
+ f.read_exact(&mut ret.data[..]).map_err(|e| Error::IOError(e))?;
+ }
+ Ok(ret)
}
pub fn sample_name(self: &Self) -> String
{ String::from_utf8_lossy(terminate_cstr(&self.header.sample_name)).into_owned() }
pub fn filename(self: &Self) -> String
{ String::from_utf8_lossy(terminate_cstr(&self.header.dos_filename)).into_owned() }
pub fn is_compressed(self: &Self) -> bool { self.header.flag & 0x8 != 0 }
+ pub fn is_signed(self: &Self) -> bool { self.header.convert & 0x1 != 0 }
pub fn num_channels(self: &Self) -> u8 { if self.header.flag & 0x4 != 0 { 2 } else { 1 }}
pub fn bits_per_sample(self: &Self) -> u8 { if self.header.flag & 0x2 != 0 { 16 } else { 8 }}
pub fn default_vol(self: &Self) -> u8 { self.header.default_volume }
+ pub fn convert_samples(self: &Self) -> Vec<f32> {
+ let mut ret = Vec::<f32>::new();
+ ret.resize(self.header.length as usize, 0.);
+ for i in 0..ret.len() {
+ if self.bits_per_sample() == 16 {
+ let data_slice:&[u8; 2] = &self.data[i * 2 .. i * 2 + 2].try_into().unwrap();
+ if self.is_signed() {
+ let val = i16::from_le_bytes(*data_slice);
+ ret[i] = val as f32 / i16::MAX as f32;
+ } else {
+ let val = u16::from_le_bytes(*data_slice);
+ ret[i] = val as f32 / u16::MAX as f32;
+ ret[i] = (ret[i] - 0.5) * 2.;
+ }
+ } else {
+ if self.is_signed() {
+ let val = i8::from_le_bytes([self.data[i]]);
+ ret[i] = val as f32 / i8::MAX as f32;
+ } else {
+ let val = self.data[i];
+ ret[i] = val as f32 / u8::MAX as f32;
+ ret[i] = (ret[i] - 0.5) * 2.;
+ }
+ }
+ }
+ ret
+ }
}
#[derive(Copy, Clone, Default)]
diff --git a/src/main.rs b/src/main.rs
index 8ae139b..6ad1421 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -20,6 +20,12 @@ fn main() -> Result<(), itfile::Error> {
}?;*/
match itfile::load("/home/chrisoft/Music/mods/nb_tear of the sun.it") {
Ok(f) => {
+ for s in &f.samps {
+ let converted = s.convert_samples();
+ for v in converted {
+ std::io::Write::write(&mut std::io::stderr(), &v.to_le_bytes()).unwrap();
+ }
+ }
let player = player::BasePlayer::new(&f);
player::Player::play(&player);
Ok(())