From: Anton Baskanov baskanov@gmail.com
--- dlls/dmusic/instrument.c | 96 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 95 insertions(+), 1 deletion(-)
diff --git a/dlls/dmusic/instrument.c b/dlls/dmusic/instrument.c index 5e22f46339f..34012fc5542 100644 --- a/dlls/dmusic/instrument.c +++ b/dlls/dmusic/instrument.c @@ -563,9 +563,74 @@ static const struct sf_mod SF_DEFAULT_MODULATORS[] = struct sf_modulators { UINT count; + UINT capacity; struct sf_mod *mods; };
+static void destroy_modulators(struct sf_modulators *modulators) +{ + if (modulators->capacity) + free(modulators->mods); +} + +static void copy_modulators(struct sf_modulators *dst, struct sf_modulators *src) +{ + if (dst->capacity < src->count) + { + struct sf_mod *mods; + + if (!(mods = malloc(src->count * sizeof(struct sf_mod)))) + return; + + destroy_modulators(dst); + + dst->mods = mods; + dst->capacity = src->count; + } + + memcpy(dst->mods, src->mods, src->count * sizeof(struct sf_mod)); + dst->count = src->count; +} + +static struct sf_mod *add_modulator(struct sf_modulators *modulators, struct sf_mod *mod) +{ + struct sf_mod *new_mod; + + if (modulators->capacity < modulators->count + 1) + { + UINT new_capacity = max(modulators->count + 1, modulators->capacity * 2); + struct sf_mod *mods; + + if (!(mods = realloc(modulators->mods, new_capacity * sizeof(struct sf_mod)))) + return NULL; + modulators->capacity = new_capacity; + modulators->mods = mods; + } + + new_mod = &modulators->mods[modulators->count]; + *new_mod = *mod; + ++modulators->count; + return new_mod; +} + +static struct sf_mod *find_modulator(struct sf_modulators *modulators, struct sf_mod *mod) +{ + UINT i; + for (i = 0; i < modulators->count; ++i) + { + if (modulators->mods[i].dest_gen != mod->dest_gen) + continue; + if (modulators->mods[i].src_mod != mod->src_mod) + continue; + if (modulators->mods[i].amount_src_mod != mod->amount_src_mod) + continue; + if (modulators->mods[i].transform != mod->transform) + continue; + return &modulators->mods[i]; + } + return NULL; +} + static BOOL parse_soundfont_generators(struct soundfont *soundfont, UINT index, BOOL preset, struct sf_generators *generators) { @@ -614,6 +679,25 @@ static BOOL parse_soundfont_generators(struct soundfont *soundfont, UINT index, return TRUE; }
+static void parse_soundfont_modulators(struct soundfont *soundfont, UINT index, BOOL preset, + struct sf_modulators *modulators) +{ + struct sf_bag *bag = (preset ? soundfont->pbag : soundfont->ibag) + index; + struct sf_mod *mod, *mods = preset ? soundfont->pmod : soundfont->imod; + struct sf_mod *modulator; + + for (mod = mods + bag->mod_ndx; mod < mods + (bag + 1)->mod_ndx; mod++) + { + if ((modulator = find_modulator(modulators, mod))) + { + *modulator = *mod; + continue; + } + if (!add_modulator(modulators, mod)) + return; + } +} + static const USHORT gen_to_conn_dst[SF_GEN_END_OPER] = { [SF_GEN_MOD_LFO_TO_PITCH] = CONN_DST_PITCH, @@ -861,6 +945,7 @@ static HRESULT instrument_add_soundfont_instrument(struct instrument *This, stru .mods = (struct sf_mod *)SF_DEFAULT_MODULATORS, }; struct sf_instrument *instrument = soundfont->inst + index; + struct sf_modulators modulators = {}; UINT i = instrument->bag_ndx; sf_generator oper; HRESULT hr = S_OK; @@ -869,12 +954,18 @@ static HRESULT instrument_add_soundfont_instrument(struct instrument *This, stru { struct sf_generators generators = global_generators;
+ copy_modulators(&modulators, &global_modulators); + + parse_soundfont_modulators(soundfont, i, FALSE, &modulators); if (parse_soundfont_generators(soundfont, i, FALSE, &generators)) { if (i > instrument->bag_ndx) WARN("Ignoring instrument zone without a sample id\n"); else + { global_generators = generators; + copy_modulators(&global_modulators, &modulators); + } continue; }
@@ -893,9 +984,12 @@ static HRESULT instrument_add_soundfont_instrument(struct instrument *This, stru generators.amount[oper].value += preset_generators->amount[oper].value; }
- hr = instrument_add_soundfont_region(This, soundfont, &generators, &global_modulators); + hr = instrument_add_soundfont_region(This, soundfont, &generators, &modulators); }
+ destroy_modulators(&modulators); + destroy_modulators(&global_modulators); + return hr; }