Skip to main content

rustysynth_ext/
sample_header.rs

1use std::io::Read;
2
3use crate::binary_reader::BinaryReader;
4use crate::error::SoundFontError;
5
6/// Represents a sample in the SoundFont.
7#[derive(Debug)]
8#[non_exhaustive]
9pub struct SampleHeader {
10    pub(crate) name: String,
11    pub(crate) start: i32,
12    pub(crate) end: i32,
13    pub(crate) start_loop: i32,
14    pub(crate) end_loop: i32,
15    pub(crate) sample_rate: i32,
16    pub(crate) original_pitch: u8,
17    pub(crate) pitch_correction: i8,
18    pub(crate) link: u16,
19    pub(crate) sample_type: u16,
20}
21
22impl SampleHeader {
23    fn new<R: Read>(reader: &mut R) -> Result<Self, SoundFontError> {
24        let name = BinaryReader::read_fixed_length_string(reader, 20)?;
25        let start = BinaryReader::read_i32(reader)?;
26        let end = BinaryReader::read_i32(reader)?;
27        let start_loop = BinaryReader::read_i32(reader)?;
28        let end_loop = BinaryReader::read_i32(reader)?;
29        let sample_rate = BinaryReader::read_i32(reader)?;
30        let original_pitch = BinaryReader::read_u8(reader)?;
31        let pitch_correction = BinaryReader::read_i8(reader)?;
32        let link = BinaryReader::read_u16(reader)?;
33        let sample_type = BinaryReader::read_u16(reader)?;
34
35        Ok(Self {
36            name,
37            start,
38            end,
39            start_loop,
40            end_loop,
41            sample_rate,
42            original_pitch,
43            pitch_correction,
44            link,
45            sample_type,
46        })
47    }
48
49    pub(crate) fn read_from_chunk<R: Read>(
50        reader: &mut R,
51        size: usize,
52    ) -> Result<Vec<SampleHeader>, SoundFontError> {
53        if size == 0 || !size.is_multiple_of(46) {
54            return Err(SoundFontError::InvalidSampleHeaderList);
55        }
56
57        let count = size / 46 - 1;
58
59        let mut headers: Vec<SampleHeader> = BinaryReader::reserve(count);
60        for _i in 0..count {
61            headers.push(SampleHeader::new(reader)?);
62        }
63
64        // The last one is the terminator.
65        SampleHeader::new(reader)?;
66
67        Ok(headers)
68    }
69
70    /// Gets the name of the sample.
71    pub fn get_name(&self) -> &str {
72        &self.name
73    }
74
75    /// Gets the start point of the sample in the sample data.
76    pub fn get_start(&self) -> i32 {
77        self.start
78    }
79
80    /// Gets the end point of the sample in the sample data.
81    pub fn get_end(&self) -> i32 {
82        self.end
83    }
84
85    /// Gets the loop start point of the sample in the sample data.
86    pub fn get_start_loop(&self) -> i32 {
87        self.start_loop
88    }
89
90    /// Gets the loop end point of the sample in the sample data.
91    pub fn get_end_loop(&self) -> i32 {
92        self.end_loop
93    }
94
95    /// Gets the sample rate of the sample.
96    pub fn get_sample_rate(&self) -> i32 {
97        self.sample_rate
98    }
99
100    /// Gets the key number of the recorded pitch of the sample.
101    pub fn get_original_pitch(&self) -> i32 {
102        self.original_pitch as i32
103    }
104
105    /// Gets the pitch correction in cents that should be applied to the sample on playback.
106    pub fn get_pitch_correction(&self) -> i32 {
107        self.pitch_correction as i32
108    }
109
110    /// Gets the link info.
111    pub fn get_link(&self) -> i32 {
112        self.link as i32
113    }
114
115    /// Gets the sample type.
116    pub fn get_sample_type(&self) -> i32 {
117        self.sample_type as i32
118    }
119}