Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SF2: Fix loop offsets + tuning #81

Merged
merged 5 commits into from
Aug 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@

.env
env.sh
env.bat
env.bat
shell.nix
3 changes: 3 additions & 0 deletions core/src/voice.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
#![allow(dead_code)]
#![allow(non_camel_case_types)] // For the SIMD library

mod envelopes;
pub(crate) use envelopes::*;

Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion kdmapi/build.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
fn main() {
if cfg!(windows) {
println!("cargo:rustc-cdylib-link-arg=/DEF:Ordinals.def")
println!("cargo:rustc-cdylib-link-arg=/DEF:./kdmapi/Ordinals.def")
}
}
36 changes: 21 additions & 15 deletions soundfonts/src/sf2/preset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,22 +76,28 @@ impl Sf2ParsedPreset {
.loop_mode
.unwrap_or(subzone.loop_mode.unwrap_or(LoopMode::NoLoop)),
loop_start: {
let v = (sample.loop_start as i32
+ subzone.loop_start_offset.unwrap_or(0) as i32)
as u32;
let offset = subzone.loop_start_offset.unwrap_or(0) as i32
+ (subzone.loop_start_offset_coarse.unwrap_or(0) as i32
* 32768);
let v = (sample.loop_start as i32 + offset) as u32;
convert_sample_index(v, sample.sample_rate, sample_rate)
},
loop_end: {
let v = (sample.loop_end as i32
+ subzone.loop_end_offset.unwrap_or(0) as i32)
as u32;
let offset = subzone.loop_end_offset.unwrap_or(0) as i32
+ (subzone.loop_end_offset_coarse.unwrap_or(0) as i32
* 32768);
let v = (sample.loop_end as i32 + offset) as u32;
convert_sample_index(v, sample.sample_rate, sample_rate)
},
offset: convert_sample_index(
subzone.offset.unwrap_or(0) as u32,
sample.sample_rate,
sample_rate,
),
offset: {
let zone_offset = subzone.offset.unwrap_or(0) as u32
+ subzone.offset_coarse.unwrap_or(0) as u32 * 32768;
convert_sample_index(
zone_offset,
sample.sample_rate,
sample_rate,
)
},
cutoff: subzone.cutoff.map(|v| {
2f32.powf(v as f32 / 1200.0)
* 8.176
Expand All @@ -100,11 +106,11 @@ impl Sf2ParsedPreset {
resonance: zone.resonance.unwrap_or(subzone.resonance.unwrap_or(0))
as f32
/ 10.0,
fine_tune: zone.fine_tune.unwrap_or(subzone.fine_tune.unwrap_or(0))
fine_tune: zone.fine_tune.unwrap_or(0)
+ subzone.fine_tune.unwrap_or(0)
+ sample.pitchadj as i16,
coarse_tune: zone
.coarse_tune
.unwrap_or(subzone.coarse_tune.unwrap_or(0)),
coarse_tune: zone.coarse_tune.unwrap_or(0)
+ subzone.coarse_tune.unwrap_or(0),
ampeg_envelope: AmpegEnvelopeParams {
ampeg_start: 0.0,
ampeg_delay: subzone.env_delay.unwrap_or(0.0)
Expand Down
61 changes: 33 additions & 28 deletions soundfonts/src/sf2/zone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ use std::ops::RangeInclusive;
pub struct Sf2Zone {
pub index: Option<u16>,
pub offset: Option<i16>,
pub offset_coarse: Option<i16>,
pub loop_start_offset: Option<i16>,
pub loop_start_offset_coarse: Option<i16>,
pub loop_end_offset: Option<i16>,
pub loop_end_offset_coarse: Option<i16>,
pub loop_mode: Option<LoopMode>,
pub cutoff: Option<i16>,
pub resonance: Option<i16>,
Expand All @@ -34,76 +37,78 @@ impl Sf2Zone {
for (i, zone) in zones.iter().enumerate() {
let mut region = global_region.clone();

for r#gen in &zone.gen_list {
match r#gen.ty {
GeneratorType::StartAddrsOffset => {
region.offset = r#gen.amount.as_i16().copied()
for gen in &zone.gen_list {
match gen.ty {
GeneratorType::StartAddrsOffset => region.offset = gen.amount.as_i16().copied(),
GeneratorType::StartAddrsCoarseOffset => {
region.offset_coarse = gen.amount.as_i16().copied()
}
GeneratorType::StartloopAddrsOffset => {
region.loop_start_offset = r#gen.amount.as_i16().copied()
region.loop_start_offset = gen.amount.as_i16().copied()
}
GeneratorType::StartloopAddrsCoarseOffset => {
region.loop_start_offset_coarse = gen.amount.as_i16().copied()
}
GeneratorType::EndloopAddrsOffset => {
region.loop_end_offset = r#gen.amount.as_i16().copied()
region.loop_end_offset = gen.amount.as_i16().copied()
}
GeneratorType::InitialFilterFc => {
region.cutoff = r#gen.amount.as_i16().copied()
GeneratorType::EndloopAddrsCoarseOffset => {
region.loop_end_offset_coarse = gen.amount.as_i16().copied()
}
GeneratorType::InitialFilterFc => region.cutoff = gen.amount.as_i16().copied(),
GeneratorType::InitialFilterQ => {
region.resonance = r#gen.amount.as_i16().copied()
region.resonance = gen.amount.as_i16().copied()
}
GeneratorType::Pan => region.pan = r#gen.amount.as_i16().copied(),
GeneratorType::Pan => region.pan = gen.amount.as_i16().copied(),
GeneratorType::DelayVolEnv => {
region.env_delay =
r#gen.amount.as_i16().map(|v| 2f32.powf(*v as f32 / 1200.0))
gen.amount.as_i16().map(|v| 2f32.powf(*v as f32 / 1200.0))
}
GeneratorType::AttackVolEnv => {
region.env_attack =
r#gen.amount.as_i16().map(|v| 2f32.powf(*v as f32 / 1200.0))
gen.amount.as_i16().map(|v| 2f32.powf(*v as f32 / 1200.0))
}
GeneratorType::HoldVolEnv => {
region.env_hold =
r#gen.amount.as_i16().map(|v| 2f32.powf(*v as f32 / 1200.0))
region.env_hold = gen.amount.as_i16().map(|v| 2f32.powf(*v as f32 / 1200.0))
}
GeneratorType::DecayVolEnv => {
region.env_decay =
r#gen.amount.as_i16().map(|v| 2f32.powf(*v as f32 / 1200.0))
gen.amount.as_i16().map(|v| 2f32.powf(*v as f32 / 1200.0))
}
GeneratorType::SustainVolEnv => {
region.env_sustain = r#gen
region.env_sustain = gen
.amount
.as_i16()
.map(|v| 10f32.powf(-1.0 * *v as f32 / 200.0) * 100.0)
}
GeneratorType::ReleaseVolEnv => {
region.env_release =
r#gen.amount.as_i16().map(|v| 2f32.powf(*v as f32 / 1200.0))
gen.amount.as_i16().map(|v| 2f32.powf(*v as f32 / 1200.0))
}
GeneratorType::KeyRange => {
let range = r#gen.amount.as_range().copied();
let range = gen.amount.as_range().copied();
region.keyrange = range.map(|v| v.low..=v.high)
}
GeneratorType::VelRange => {
let range = r#gen.amount.as_range().copied();
let range = gen.amount.as_range().copied();
region.velrange = range.map(|v| v.low..=v.high)
}
GeneratorType::InitialAttenuation => {
region.attenuation = r#gen.amount.as_i16().copied()
}
GeneratorType::CoarseTune => {
region.coarse_tune = r#gen.amount.as_i16().copied()
region.attenuation = gen.amount.as_i16().copied()
}
GeneratorType::FineTune => region.fine_tune = r#gen.amount.as_i16().copied(),
GeneratorType::SampleID => region.index = r#gen.amount.as_u16().copied(),
GeneratorType::Instrument => region.index = r#gen.amount.as_u16().copied(),
GeneratorType::CoarseTune => region.coarse_tune = gen.amount.as_i16().copied(),
GeneratorType::FineTune => region.fine_tune = gen.amount.as_i16().copied(),
GeneratorType::SampleID => region.index = gen.amount.as_u16().copied(),
GeneratorType::Instrument => region.index = gen.amount.as_u16().copied(),
GeneratorType::SampleModes => {
region.loop_mode = r#gen.amount.as_i16().map(|v| match v {
region.loop_mode = gen.amount.as_i16().map(|v| match v {
1 => LoopMode::LoopContinuous,
3 => LoopMode::LoopSustain,
_ => LoopMode::NoLoop,
})
}
GeneratorType::OverridingRootKey => {
region.root_override = r#gen.amount.as_i16().copied()
region.root_override = gen.amount.as_i16().copied()
}
_ => {}
}
Expand Down
40 changes: 0 additions & 40 deletions soundfonts/src/sfz/grammar/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,24 +56,6 @@ bnf! {
ParseOpcodeValuePart = text:(parse_opcode_value_simd);
}

impl<'a> Root<'a> {
pub fn parse_full(s: &'a str) -> Result<Self, ParseError> {
let parser = StringParser::new(s);
let result = Self::parse(parser);

result.map(|(r, _)| r)
}
}

impl<'a> ErrorTolerantRoot<'a> {
pub fn parse_full(s: &'a str) -> Result<Self, ParseError> {
let parser = StringParser::new(s);
let result = Self::parse(parser);

result.map(|(r, _)| r)
}
}

impl<'a> OpcodeValue<'a> {
pub fn as_string(&self) -> Cow<'a, str> {
if self.rest.is_empty() {
Expand All @@ -88,28 +70,6 @@ impl<'a> OpcodeValue<'a> {
}
}

impl<'a> Token<'a> {
pub fn parse_as_iter(s: &'a str) -> impl Iterator<Item = Result<Token<'a>, ParseError>> {
let mut parser = StringParser::new(s);
std::iter::from_fn(move || {
let result = Self::parse(parser);

if let Err(e) = result {
if parser.is_empty() {
return None;
} else {
return Some(Err(e));
}
}

Some(result.map(|(r, p)| {
parser = p;
r
}))
})
}
}

impl<'a> ErrorTolerantToken<'a> {
pub fn parse_as_iter(s: &'a str) -> impl Iterator<Item = Result<Token<'a>, ParseError>> {
let mut parser = StringParser::new(s);
Expand Down
Loading