Skip to content

Commit

Permalink
Fix all the remaining lints & Add font load error types
Browse files Browse the repository at this point in the history
  • Loading branch information
PolyMeilex committed Dec 28, 2024
1 parent d45fda1 commit 4d51130
Show file tree
Hide file tree
Showing 12 changed files with 109 additions and 77 deletions.
8 changes: 1 addition & 7 deletions oxisynth-reverb/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -361,13 +361,7 @@ impl Reverb {

/// Set the current reverb level
fn set_level(&mut self, value: f32) {
let value = if value < 0.0 {
0.0
} else if value > 1.0 {
1.0
} else {
value
};
let value = value.clamp(0.0, 1.0);
self.wet = value * 3.0;
}

Expand Down
2 changes: 1 addition & 1 deletion oxisynth/examples/real-time/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ fn main() -> Result<(), Box<dyn Error>> {
move |stamp, message, _| {
if message.len() == 3 {
let note = message[1];
if note >= 21 && note <= 108 {
if (21..=108).contains(&note) {
if message[0] == 128 || message[2] == 0 {
println!("NoteOff {}", message[1]);
synth_conn.note_off(0, message[1]);
Expand Down
26 changes: 11 additions & 15 deletions oxisynth/src/core/soundfont.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ use std::{
sync::Arc,
};

use crate::error::LoadError;

pub(crate) use {
instrument::InstrumentZone, preset::PresetZone, sample::Sample, sample_data::SampleData,
};
Expand All @@ -21,25 +23,19 @@ pub struct SoundFont {
}

impl SoundFont {
pub fn load<F: Read + Seek>(file: &mut F) -> Result<Self, ()> {
let sf2 = soundfont::SoundFont2::load(file);

let sf2 = match sf2 {
Ok(data) => data,
Err(err) => {
log::error!("{:#?}", err);
return Err(());
}
};
pub fn load<F: Read + Seek>(file: &mut F) -> Result<Self, LoadError> {
let sf2 = soundfont::SoundFont2::load(file)?;

#[cfg(feature = "sf3")]
let ver = 3;
let max_ver = 3;
#[cfg(not(feature = "sf3"))]
let ver = 2;
let max_ver = 2;

if sf2.info.version.major > ver {
log::error!("Unsupported version: {:?}", sf2.info.version);
return Err(());
if sf2.info.version.major > max_ver {
return Err(LoadError::Version {
version: sf2.info.version,
max: max_ver,
});
}

let sf2 = sf2.sort_presets();
Expand Down
8 changes: 1 addition & 7 deletions oxisynth/src/core/soundfont/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -748,12 +748,6 @@ fn get_default_values() -> [Generator; 60] {

pub(crate) fn gen_scale_nrpn(gen: i16, data: i32) -> f32 {
let value = data as f32 - 8192.0;
let value = if value < -8192.0 {
-8192.0
} else if value > 8192.0 {
8192.0
} else {
value
};
let value = value.clamp(-8192.0, 8192.0);
value * GEN_INFO[gen as usize].nrpn_scale as f32
}
9 changes: 5 additions & 4 deletions oxisynth/src/core/soundfont/instrument.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::error::LoadError;
use crate::GeneratorType;

use super::generator::GeneratorList;
Expand All @@ -18,7 +19,7 @@ impl Instrument {
sf2: &soundfont::SoundFont2,
inst: &soundfont::Instrument,
samples: &[Sample],
) -> Result<Self, ()> {
) -> Result<Self, LoadError> {
let name = if !inst.header.name.is_empty() {
inst.header.name.clone()
} else {
Expand Down Expand Up @@ -73,7 +74,7 @@ impl InstrumentZone {
sf2: &soundfont::SoundFont2,
zone: &soundfont::Zone,
samples: &[Sample],
) -> Result<InstrumentZone, ()> {
) -> Result<InstrumentZone, LoadError> {
let mut key_low = 0;
let mut key_high = 128;
let mut vel_low = 0;
Expand Down Expand Up @@ -122,8 +123,8 @@ impl InstrumentZone {
.cloned();

if sample.is_none() {
log::error!("Couldn't find sample name",);
return Err(());
log::error!("Couldn't find sample: {name:?}");
return Err(LoadError::SampleNotFound { name: name.clone() });
}

sample
Expand Down
6 changes: 4 additions & 2 deletions oxisynth/src/core/soundfont/preset.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use crate::error::LoadError;

use super::generator::{GeneratorList, GeneratorType};
use super::modulator::Mod;
use super::{instrument::Instrument, Sample};
Expand All @@ -17,7 +19,7 @@ impl Preset {
sf2: &soundfont::SoundFont2,
preset: &soundfont::Preset,
samples: &[Sample],
) -> Result<Self, ()> {
) -> Result<Self, LoadError> {
let name = if !preset.header.name.is_empty() {
preset.header.name.clone()
} else {
Expand Down Expand Up @@ -86,7 +88,7 @@ impl PresetZone {
sf2: &soundfont::SoundFont2,
zone: &soundfont::Zone,
samples: &[Sample],
) -> Result<Self, ()> {
) -> Result<Self, LoadError> {
let mut key_low = 0;
let mut key_high = 128;
let mut vel_low = 0;
Expand Down
7 changes: 6 additions & 1 deletion oxisynth/src/core/soundfont/sample.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ use std::sync::Arc;

use soundfont::raw::SampleLink;

use crate::error::LoadError;

use super::SampleData;

#[derive(Clone, Debug)]
Expand All @@ -28,7 +30,10 @@ pub(crate) struct Sample {
}

impl Sample {
pub fn import(sample: &soundfont::raw::SampleHeader, data: SampleData) -> Result<Sample, ()> {
pub fn import(
sample: &soundfont::raw::SampleHeader,
data: SampleData,
) -> Result<Sample, LoadError> {
let mut sample = Sample {
name: sample.name.clone().into(),
start: sample.start,
Expand Down
12 changes: 6 additions & 6 deletions oxisynth/src/core/soundfont/sample_data.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::{
io::{Read, Seek, SeekFrom},
io::{self, Read, Seek, SeekFrom},
sync::Arc,
};

Expand All @@ -14,13 +14,13 @@ impl SampleData {
Self(data)
}

pub fn load<F: Read + Seek>(file: &mut F, smpl: &SampleChunk) -> Result<Self, ()> {
pub fn load<F: Read + Seek>(file: &mut F, smpl: &SampleChunk) -> io::Result<Self> {
let sample_pos = smpl.offset;
let sample_size = smpl.len as usize;

if file.seek(SeekFrom::Start(sample_pos)).is_err() {
log::error!("Failed to seek position in data file",);
return Err(());
if let Err(err) = file.seek(SeekFrom::Start(sample_pos)) {
log::error!("Failed to seek position in data file: {err}");
return Err(err);
}

let mut data = vec![0i16; sample_size / 2];
Expand All @@ -30,7 +30,7 @@ impl SampleData {

if let Err(err) = file.read_exact(byte_slice) {
log::error!("Failed to read sample data: {err}");
return Err(());
return Err(err);
}
}

Expand Down
51 changes: 51 additions & 0 deletions oxisynth/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,53 @@ pub(crate) fn range_check<E, T: PartialOrd, C: std::ops::RangeBounds<T>>(
}
}

#[derive(Debug)]
pub enum LoadError {
Parsing(soundfont::Error),
Version {
version: soundfont::raw::Version,
max: u16,
},
Io(std::io::Error),
SampleNotFound {
name: String,
},
}

impl From<soundfont::Error> for LoadError {
fn from(err: soundfont::Error) -> Self {
Self::Parsing(err)
}
}

impl From<std::io::Error> for LoadError {
fn from(value: std::io::Error) -> Self {
Self::Io(value)
}
}

impl std::error::Error for LoadError {}
impl std::fmt::Display for LoadError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Parsing(error) => {
write!(f, "SoundFont parsing error: {error}")?;
}
Self::Version { version, max } => {
write!(f, "Unsupported version: {version:?}, max supported {max}")?;
}
Self::Io(error) => {
write!(f, "IO error while reading SoundFont: {error}")?;
}
Self::SampleNotFound { name } => {
write!(f, "Sample {name:?} not found")?;
}
}

Ok(())
}
}

#[derive(Debug)]
pub enum OxiError {
KeyOutOfRange,
Expand All @@ -29,6 +76,7 @@ pub enum OxiError {
preset_id: u8,
sfont_id: SoundFontId,
},
InvalidPolyphony,
}

impl std::error::Error for OxiError {}
Expand Down Expand Up @@ -73,6 +121,9 @@ impl std::fmt::Display for OxiError {
} => {
write!(f,"There is no preset with bank number {bank_id} and preset number {preset_id} in SoundFont {sfont_id:?}")?;
}
OxiError::InvalidPolyphony => {
write!(f, "Only polyphony >= 1 is allowed")?;
}
};

Ok(())
Expand Down
9 changes: 4 additions & 5 deletions oxisynth/src/synth/font.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,21 +35,20 @@ impl Synth {
}

/// Removes a SoundFont from the stack and deallocates it.
pub fn remove_font(&mut self, id: SoundFontId, reset_presets: bool) -> Result<(), ()> {
pub fn remove_font(&mut self, id: SoundFontId, reset_presets: bool) -> Option<SoundFont> {
let sfont = self.core.font_bank.remove_font(id);

if sfont.is_some() {
if let Some(font) = sfont {
if reset_presets {
self.program_reset();
} else {
self.update_presets();
}

Ok(())
Some(font)
} else {
log::error!("No SoundFont with id = {:?}", id);

Err(())
None
}
}

Expand Down
25 changes: 10 additions & 15 deletions oxisynth/src/synth/params.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::sync::Arc;

use crate::error::OxiError;
use crate::{Preset, Settings, Synth};

use crate::core::InterpolationMethod;
Expand All @@ -13,14 +14,8 @@ impl Synth {

/// Set the master gain
pub fn set_gain(&mut self, gain: f32) {
self.core.settings.gain = if gain < 0.0 {
0.0
} else if gain > 10.0 {
10.0
} else {
gain
};

let gain = gain.clamp(0.0, 10.0);
self.core.settings.gain = gain;
self.core.voices.set_gain(gain)
}

Expand All @@ -30,15 +25,15 @@ impl Synth {
}

/// Set the polyphony limit
pub fn set_polyphony(&mut self, polyphony: u16) -> Result<(), ()> {
pub fn set_polyphony(&mut self, polyphony: u16) -> Result<(), OxiError> {
if polyphony < 1 {
Err(())
} else {
self.core.settings.polyphony = polyphony;
self.core.voices.set_polyphony_limit(polyphony as usize);

Ok(())
return Err(OxiError::InvalidPolyphony);
}

self.core.settings.polyphony = polyphony;
self.core.voices.set_polyphony_limit(polyphony as usize);

Ok(())
}

/// Get the polyphony limit (FluidSynth >= 1.0.6)
Expand Down
23 changes: 9 additions & 14 deletions oxisynth/src/tuning.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,21 @@ impl Tuning {
tuning
}

/**
Create a new key-based tuning with given name, number, and
pitches. The array 'pitches' should have length 128 and contains
the pitch in cents of every key in cents. However, if 'pitches' is
NULL, a new tuning is created with the well-tempered scale.
*/

/// Create a new key-based tuning with given name, number, and
/// pitches. The array 'pitches' should have length 128 and contains
/// the pitch in cents of every key in cents. However, if 'pitches' is
/// NULL, a new tuning is created with the well-tempered scale.
pub fn new_key_tuning(bank: u32, prog: u32, pitch: &[f64; 128]) -> Self {
let mut tuning = Self::new(bank, prog);
tuning.set_all(pitch);
tuning
}

/**
Create a new octave-based tuning with given name, number, and
pitches. The array 'pitches' should have length 12 and contains
derivation in cents from the well-tempered scale. For example, if
pitches[0] equals -33, then the C-keys will be tuned 33 cents
below the well-tempered C.
*/
/// Create a new octave-based tuning with given name, number, and
/// pitches. The array 'pitches' should have length 12 and contains
/// derivation in cents from the well-tempered scale. For example, if
/// pitches[0] equals -33, then the C-keys will be tuned 33 cents
/// below the well-tempered C.
pub fn new_octave_tuning(bank: u32, prog: u32, pitch: &[f64; 12]) -> Self {
let mut tuning = Self::new(bank, prog);
tuning.set_octave(pitch);
Expand Down

0 comments on commit 4d51130

Please sign in to comment.