Skip to content

Commit

Permalink
Fix SF2 sample length errors (#87)
Browse files Browse the repository at this point in the history
  • Loading branch information
MyBlackMIDIScore authored Aug 10, 2024
1 parent e601e4c commit 91963dd
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 15 deletions.
3 changes: 1 addition & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion soundfonts/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@ lazy-regex = "3.2.0"
regex-bnf = "0.1.2"
simdeez = "2.0.0-dev3"
thiserror = "1.0.63"
soundfont = "0.0.3"
soundfont = { git = "https://github.com/PolyMeilex/OxiSynth", tag = "0.0.5" }
rubato = "0.15.0"
7 changes: 4 additions & 3 deletions soundfonts/src/sf2/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ pub enum Sf2ParseError {
FailedToReadFile(PathBuf),

#[error("Failed to parse file")]
FailedToParseFile,
FailedToParseFile(String),
}

/// Structure that holds the generator and modulator parameters of an SF2 region.
#[derive(Clone)]
#[derive(Clone, Debug)]
pub struct Sf2Region {
pub sample: Arc<[Arc<[f32]>]>,
pub sample_rate: u32,
Expand All @@ -40,6 +40,7 @@ pub struct Sf2Region {
}

/// Structure that holds the parameters of an SF2 preset.
#[derive(Clone, Debug)]
pub struct Sf2Preset {
pub bank: u16,
pub preset: u16,
Expand All @@ -59,7 +60,7 @@ pub fn load_soundfont(
.map_err(|_| Sf2ParseError::FailedToReadFile(sf2_path.clone()))?;
let file = &mut file;
let sf2 = soundfont::SoundFont2::load(file)
.map_err(|_| Sf2ParseError::FailedToParseFile)?
.map_err(|e| Sf2ParseError::FailedToParseFile(format!("{:#?}", e)))?
.sort_presets();

let sample_data = sample::Sf2Sample::parse_sf2_samples(
Expand Down
26 changes: 17 additions & 9 deletions soundfonts/src/sf2/sample.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,24 +25,32 @@ impl Sf2Sample {
sample_rate: u32,
) -> Result<Vec<Self>, Sf2ParseError> {
let smpl = if let Some(data) = data.smpl {
data.read_contents(file)
.map_err(|_| Sf2ParseError::FailedToParseFile)?
data.read_contents(file).map_err(|_| {
Sf2ParseError::FailedToParseFile("Error reading sample contents".to_string())
})?
} else {
return Err(Sf2ParseError::FailedToParseFile);
return Err(Sf2ParseError::FailedToParseFile(
"Soundfont does not contain samples".to_string(),
));
};

let mut samples = Vec::new();

if let Some(sm24) = data.sm24 {
// SF2 is 24-bit
let extra = sm24
.read_contents(file)
.map_err(|_| Sf2ParseError::FailedToParseFile)?;
if smpl.len() / 2 != extra.len() {
return Err(Sf2ParseError::FailedToParseFile);
let extra = sm24.read_contents(file).map_err(|_| {
Sf2ParseError::FailedToParseFile("Error reading extra sample contents".to_string())
})?;

let smpllen = smpl.len() / 2;
let extralen = extra.len() - (smpllen % 2);
if smpllen != extralen {
return Err(Sf2ParseError::FailedToParseFile(
"Invalid sample length".to_string(),
));
}

for i in 0..extra.len() {
for i in 0..extralen {
let n0 = 0;
let n1 = extra[i];
let n2 = smpl[i * 2];
Expand Down

0 comments on commit 91963dd

Please sign in to comment.