Skip to main content

rustysynth_ext/
soundfont_info.rs

1use std::io::Read;
2
3use crate::binary_reader::BinaryReader;
4use crate::error::SoundFontError;
5use crate::four_cc::FourCC;
6use crate::read_counter::ReadCounter;
7use crate::soundfont_version::SoundFontVersion;
8
9/// The information of a SoundFont.
10#[derive(Debug)]
11#[non_exhaustive]
12pub struct SoundFontInfo {
13    pub(crate) version: SoundFontVersion,
14    pub(crate) target_sound_engine: String,
15    pub(crate) bank_name: String,
16    pub(crate) rom_name: String,
17    pub(crate) rom_version: SoundFontVersion,
18    pub(crate) creation_date: String,
19    pub(crate) author: String,
20    pub(crate) target_product: String,
21    pub(crate) copyright: String,
22    pub(crate) comments: String,
23    pub(crate) tools: String,
24}
25
26impl SoundFontInfo {
27    pub(crate) fn new<R: Read>(reader: &mut R) -> Result<Self, SoundFontError> {
28        let chunk_id = BinaryReader::read_four_cc(reader)?;
29        if chunk_id != b"LIST" {
30            return Err(SoundFontError::ListChunkNotFound);
31        }
32
33        let end = BinaryReader::read_u32(reader)? as usize;
34        let reader = &mut ReadCounter::new(reader);
35
36        let list_type = BinaryReader::read_four_cc(reader)?;
37        if list_type != b"INFO" {
38            return Err(SoundFontError::InvalidListChunkType {
39                expected: FourCC::from_bytes(*b"INFO"),
40                actual: list_type,
41            });
42        }
43
44        let mut version: Option<SoundFontVersion> = None;
45        let mut target_sound_engine: Option<String> = None;
46        let mut bank_name: Option<String> = None;
47        let mut rom_name: Option<String> = None;
48        let mut rom_version: Option<SoundFontVersion> = None;
49        let mut creation_date: Option<String> = None;
50        let mut author: Option<String> = None;
51        let mut target_product: Option<String> = None;
52        let mut copyright: Option<String> = None;
53        let mut comments: Option<String> = None;
54        let mut tools: Option<String> = None;
55
56        while reader.bytes_read() < end {
57            let id = BinaryReader::read_four_cc(reader)?;
58            let size = BinaryReader::read_u32(reader)? as usize;
59
60            match id.as_bytes() {
61                b"ifil" => version = Some(SoundFontVersion::new(reader, size)?),
62                b"isng" => {
63                    target_sound_engine =
64                        Some(BinaryReader::read_fixed_length_string(reader, size)?)
65                }
66                b"INAM" => bank_name = Some(BinaryReader::read_fixed_length_string(reader, size)?),
67                b"irom" => rom_name = Some(BinaryReader::read_fixed_length_string(reader, size)?),
68                b"iver" => rom_version = Some(SoundFontVersion::new(reader, size)?),
69                b"ICRD" => {
70                    creation_date = Some(BinaryReader::read_fixed_length_string(reader, size)?)
71                }
72                b"IENG" => author = Some(BinaryReader::read_fixed_length_string(reader, size)?),
73                b"IPRD" => {
74                    target_product = Some(BinaryReader::read_fixed_length_string(reader, size)?)
75                }
76                b"ICOP" => copyright = Some(BinaryReader::read_fixed_length_string(reader, size)?),
77                b"ICMT" => comments = Some(BinaryReader::read_fixed_length_string(reader, size)?),
78                b"ISFT" => tools = Some(BinaryReader::read_fixed_length_string(reader, size)?),
79                _ => return Err(SoundFontError::ListContainsUnknownId(id)),
80            }
81
82            BinaryReader::skip_chunk_padding(
83                reader,
84                size,
85                end.saturating_sub(reader.bytes_read()),
86            )?;
87        }
88
89        let version = version.unwrap_or_else(SoundFontVersion::default);
90        let target_sound_engine = target_sound_engine.unwrap_or_default();
91        let bank_name = bank_name.unwrap_or_default();
92        let rom_name = rom_name.unwrap_or_default();
93        let rom_version = rom_version.unwrap_or_else(SoundFontVersion::default);
94        let creation_date = creation_date.unwrap_or_default();
95        let author = author.unwrap_or_default();
96        let target_product = target_product.unwrap_or_default();
97        let copyright = copyright.unwrap_or_default();
98        let comments = comments.unwrap_or_default();
99        let tools = tools.unwrap_or_default();
100
101        Ok(Self {
102            version,
103            target_sound_engine,
104            bank_name,
105            rom_name,
106            rom_version,
107            creation_date,
108            author,
109            target_product,
110            copyright,
111            comments,
112            tools,
113        })
114    }
115
116    /// Gets the version of the SoundFont.
117    pub fn get_version(&self) -> &SoundFontVersion {
118        &self.version
119    }
120
121    /// Gets the target sound engine of the SoundFont.
122    pub fn get_target_sound_engine(&self) -> &str {
123        &self.target_sound_engine
124    }
125
126    /// Gets the bank name of the SoundFont.
127    pub fn get_bank_name(&self) -> &str {
128        &self.bank_name
129    }
130
131    /// Gets the ROM name of the SoundFont.
132    pub fn get_rom_name(&self) -> &str {
133        &self.rom_name
134    }
135
136    /// Gets the ROM version of the SoundFont.
137    pub fn get_rom_version(&self) -> &SoundFontVersion {
138        &self.rom_version
139    }
140
141    /// Gets the creation date of the SoundFont.
142    pub fn get_creation_date(&self) -> &str {
143        &self.creation_date
144    }
145
146    /// Gets the author of the SoundFont.
147    pub fn get_author(&self) -> &str {
148        &self.author
149    }
150
151    /// Gets the target product of the SoundFont.
152    pub fn get_target_product(&self) -> &str {
153        &self.target_product
154    }
155
156    /// Gets the copyright message for the SoundFont.
157    pub fn get_copyright(&self) -> &str {
158        &self.copyright
159    }
160
161    /// Gets the comments for the SoundFont.
162    pub fn get_comments(&self) -> &str {
163        &self.comments
164    }
165
166    /// Gets the tools used to create the SoundFont.
167    pub fn get_tools(&self) -> &str {
168        &self.tools
169    }
170}