Skip to content

Commit

Permalink
SF2: Fix loop offsets + tuning (#81)
Browse files Browse the repository at this point in the history
  • Loading branch information
MyBlackMIDIScore authored Aug 5, 2024
1 parent cd6f007 commit 62ed54b
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 43 deletions.
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

0 comments on commit 62ed54b

Please sign in to comment.