Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions smaf/src/chunks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,14 @@ pub fn parse_timebase(raw: u8) -> u8 {

pub fn parse_variable_number(input: &[u8]) -> IResult<&[u8], u32> {
let mut data = input;
let mut result = 0;
let (remaining, first) = u8(data)?;
data = remaining;

if first & 0b1000_0000 == 0 {
return Ok((data, (first & 0b0111_1111) as u32));
}

let mut result = (first & 0b0111_1111) as u32;
loop {
let (remaining, byte) = u8(data)?;
data = remaining;
Expand All @@ -34,9 +41,20 @@ pub fn parse_variable_number(input: &[u8]) -> IResult<&[u8], u32> {
Ok((data, result))
}

pub fn parse_handy_variable_number(input: &[u8]) -> IResult<&[u8], u32> {
let (remaining, first) = u8(input)?;
if first & 0b1000_0000 == 0 {
return Ok((remaining, first as u32));
}

let (remaining, second) = u8(remaining)?;
let result = ((((first & 0b0111_1111) as u32) + 1) << 7) | (second as u32);
Ok((remaining, result))
}

pub use self::{
content_info::ContentsInfoChunk,
optional_data::OptionalDataChunk,
pcm_audio_track::{PCMAudioSequenceData, PCMAudioSequenceEvent, PCMAudioTrack, PCMAudioTrackChunk},
score_track::{PCMDataChunk, ScoreTrack, ScoreTrackChunk, ScoreTrackSequenceEvent, SequenceData, WaveData},
score_track::{ChannelStatus, ChannelType, PCMDataChunk, ScoreTrack, ScoreTrackChunk, ScoreTrackSequenceEvent, SequenceData, WaveData},
};
52 changes: 31 additions & 21 deletions smaf/src/chunks/pcm_audio_track.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ use crate::{
constants::{BaseBit, Channel, PcmWaveFormat},
};

const SHORT_PITCH_BEND_VALUES: [u8; 15] = [0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38, 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70];
const SHORT_EXPRESSION_VALUES: [u8; 15] = [0x00, 0x00, 0x1f, 0x27, 0x2f, 0x37, 0x3f, 0x47, 0x4f, 0x57, 0x5f, 0x67, 0x6f, 0x77, 0x7f];

pub enum PCMAudioSequenceEvent {
WaveMessage { channel: u8, wave_number: u8, gate_time: u32 },
PitchBend { channel: u8, value: u8 },
Expand Down Expand Up @@ -90,55 +93,66 @@ impl PCMAudioSequenceData {
} else {
let (remaining, second_byte) = u8(data)?;
let channel = (second_byte & 0b1100_0000) >> 6;
if second_byte & 0b0011_1100 == 0b0011_0100 {
let (remaining, value) = u8(remaining)?;
let event_type = second_byte & 0b0011_1111;

if (0x01..=0x0e).contains(&event_type) {
data = remaining;

result.push(Self {
duration,
event: PCMAudioSequenceEvent::PitchBend { channel, value },
event: PCMAudioSequenceEvent::Expression {
channel,
value: SHORT_EXPRESSION_VALUES[event_type as usize],
},
})
} else if second_byte & 0b0011_0000 == 0b0011_0000 {
} else if (0x11..=0x1e).contains(&event_type) {
data = remaining;

let value = (second_byte & 0b0000_1111) * 8;
result.push(Self {
duration,
event: PCMAudioSequenceEvent::PitchBend {
channel,
value: SHORT_PITCH_BEND_VALUES[(event_type - 0x10) as usize],
},
})
} else if event_type == 0x34 {
let (remaining, value) = u8(remaining)?;
data = remaining;

result.push(Self {
duration,
event: PCMAudioSequenceEvent::PitchBend { channel, value },
})
} else if second_byte & 0b0011_0111 == 0b0011_0110 {
} else if event_type == 0x36 || event_type == 0x3b {
let (remaining, value) = u8(remaining)?;
data = remaining;

result.push(Self {
duration,
event: PCMAudioSequenceEvent::Volume { channel, value },
event: PCMAudioSequenceEvent::Expression { channel, value },
})
} else if second_byte & 0b0011_1010 == 0b0011_1010 {
} else if event_type == 0x37 {
let (remaining, value) = u8(remaining)?;
data = remaining;

result.push(Self {
duration,
event: PCMAudioSequenceEvent::Pan { channel, value },
event: PCMAudioSequenceEvent::Volume { channel, value },
})
} else if second_byte & 0b0011_1011 == 0b0011_1011 {
} else if event_type == 0x3a {
let (remaining, value) = u8(remaining)?;
data = remaining;

result.push(Self {
duration,
event: PCMAudioSequenceEvent::Expression { channel, value },
event: PCMAudioSequenceEvent::Pan { channel, value },
})
} else if second_byte & 0b0011_0000 == 0b0000_0000 {
} else if event_type == 0x00 {
data = remaining;

let value = ((second_byte & 0b0000_1111) - 1) * 31;

result.push(Self {
duration,
event: PCMAudioSequenceEvent::Expression { channel, value },
event: PCMAudioSequenceEvent::Nop,
})
} else {
panic!("Invalid second byte")
Expand All @@ -155,6 +169,7 @@ pub enum PCMAudioTrackChunk<'a> {
SetupData(&'a [u8]),
SequenceData(Vec<PCMAudioSequenceData>),
WaveData(u8, &'a [u8]),
Unknown(&'a [u8], &'a [u8]),
}

impl<'a> Parse<&'a [u8]> for PCMAudioTrackChunk<'a> {
Expand All @@ -165,12 +180,7 @@ impl<'a> Parse<&'a [u8]> for PCMAudioTrackChunk<'a> {
b"Atsu" => PCMAudioTrackChunk::SetupData(data),
b"Atsq" => PCMAudioTrackChunk::SequenceData(all_consuming(PCMAudioSequenceData::parse)(data)?.1),
&[b'A', b'w', b'a', x] => PCMAudioTrackChunk::WaveData(x, data),
_ => {
return Err(nom::Err::Error::<nom::error::Error<&'a [u8]>>(nom::error_position!(
data,
nom::error::ErrorKind::Switch
)))
}
_ => PCMAudioTrackChunk::Unknown(tag, data),
})
})(data)
}
Expand Down
Loading
Loading