swf_parser/complete/
sound.rs

1use nom::number::complete::{le_u16 as parse_le_u16, le_u32 as parse_le_u32, le_u8 as parse_u8};
2use nom::IResult as NomResult;
3use swf_types as swf;
4
5pub fn sound_rate_from_code(sound_rate_code: u8) -> Result<swf::SoundRate, ()> {
6  match sound_rate_code {
7    0 => Ok(swf::SoundRate::SoundRate5500),
8    1 => Ok(swf::SoundRate::SoundRate11000),
9    2 => Ok(swf::SoundRate::SoundRate22000),
10    3 => Ok(swf::SoundRate::SoundRate44000),
11    _ => Err(()),
12  }
13}
14
15pub fn audio_coding_format_from_code(audio_codec_code: u8) -> Result<swf::AudioCodingFormat, ()> {
16  match audio_codec_code {
17    0 => Ok(swf::AudioCodingFormat::UncompressedNativeEndian),
18    1 => Ok(swf::AudioCodingFormat::Adpcm),
19    2 => Ok(swf::AudioCodingFormat::Mp3),
20    3 => Ok(swf::AudioCodingFormat::UncompressedLittleEndian),
21    4 => Ok(swf::AudioCodingFormat::Nellymoser16),
22    5 => Ok(swf::AudioCodingFormat::Nellymoser8),
23    6 => Ok(swf::AudioCodingFormat::Nellymoser),
24    11 => Ok(swf::AudioCodingFormat::Speex),
25    _ => Err(()),
26  }
27}
28
29// TODO: Move this to a method on `swf::AudioCodingFormat`
30pub fn is_uncompressed_audio_coding_format(format: swf::AudioCodingFormat) -> bool {
31  matches!(format, swf::AudioCodingFormat::UncompressedNativeEndian | swf::AudioCodingFormat::UncompressedLittleEndian)
32}
33
34pub fn parse_sound_info(input: &[u8]) -> NomResult<&[u8], swf::SoundInfo> {
35  use nom::combinator::cond;
36  use nom::multi::count;
37
38  let (input, flags) = parse_u8(input)?;
39  #[allow(clippy::identity_op)]
40  let has_in_point = (flags & (1 << 0)) != 0;
41  let has_out_point = (flags & (1 << 1)) != 0;
42  let has_loops = (flags & (1 << 2)) != 0;
43  let has_envelope = (flags & (1 << 3)) != 0;
44  let sync_no_multiple = (flags & (1 << 4)) != 0;
45  let sync_stop = (flags & (1 << 5)) != 0;
46  // Bits [6, 7] are reserved
47  let (input, in_point) = cond(has_in_point, parse_le_u32)(input)?;
48  let (input, out_point) = cond(has_out_point, parse_le_u32)(input)?;
49  let (input, loop_count) = cond(has_loops, parse_le_u16)(input)?;
50  let (input, envelope_records) = if has_envelope {
51    let (input, record_count) = parse_u8(input)?;
52    let (input, envelope_records) = count(parse_sound_envelope, usize::from(record_count))(input)?;
53    (input, Some(envelope_records))
54  } else {
55    (input, None)
56  };
57
58  Ok((
59    input,
60    swf::SoundInfo {
61      sync_stop,
62      sync_no_multiple,
63      in_point,
64      out_point,
65      loop_count,
66      envelope_records,
67    },
68  ))
69}
70
71pub fn parse_sound_envelope(input: &[u8]) -> NomResult<&[u8], swf::SoundEnvelope> {
72  let (input, pos44) = parse_le_u32(input)?;
73  let (input, left_level) = parse_le_u16(input)?;
74  let (input, right_level) = parse_le_u16(input)?;
75  Ok((
76    input,
77    swf::SoundEnvelope {
78      pos44,
79      left_level,
80      right_level,
81    },
82  ))
83}