oxisynth 0.0.4

Rust soundfont synthesizer
Documentation
pub mod generator;
mod instrument;
pub(crate) mod modulator;
mod preset;
mod sample;
mod sample_data;

use std::{
    io::{Read, Seek},
    sync::Arc,
};

pub(crate) use {
    instrument::InstrumentZone, preset::PresetZone, sample::Sample, sample_data::SampleData,
};

pub use preset::Preset;

pub struct SoundFont {
    presets: Vec<Arc<Preset>>,
}

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(());
            }
        };

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

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

        let sf2 = sf2.sort_presets();

        let smpl = sf2.sample_data.smpl.as_ref().unwrap();

        let sample_pos = smpl.offset() + 8;
        let sample_size = smpl.len() as usize;

        let sample_data = Arc::new(SampleData::load(file, sample_pos, sample_size)?);

        let mut samples = Vec::new();

        for sfsample in sf2.sample_headers.iter() {
            let sample = Sample::import(sfsample, sample_data.clone())?.optimize_sample();
            samples.push(Arc::new(sample));
        }

        let mut presets = Vec::new();
        for sfpreset in sf2.presets.iter() {
            let preset = Preset::import(&sf2, sfpreset, &samples)?;
            presets.push(Arc::new(preset));
        }

        Ok(Self { presets })
    }

    pub fn preset(&self, bank: u32, prenum: u8) -> Option<Arc<Preset>> {
        self.presets
            .iter()
            .find(|p| p.banknum() == bank && p.num() == prenum as u32)
            .cloned()
    }
}