-- v2: dmusic: Parse preset modulators. dmusic: Parse instrument modulators. dmusic: Add default modulators. dmusic: Convert generators to DLS connections.
From: Anton Baskanov baskanov@gmail.com
--- dlls/dmusic/instrument.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-)
diff --git a/dlls/dmusic/instrument.c b/dlls/dmusic/instrument.c index f92e3afa976..570af0ee647 100644 --- a/dlls/dmusic/instrument.c +++ b/dlls/dmusic/instrument.c @@ -646,7 +646,19 @@ static HRESULT instrument_add_soundfont_instrument(struct instrument *This, stru }
for (oper = 0; oper < SF_GEN_END_OPER; ++oper) + { + if (oper == SF_GEN_KEY_RANGE || oper == SF_GEN_VEL_RANGE) + { + generators.amount[oper].range.low = max( + generators.amount[oper].range.low, + preset_generators->amount[oper].range.low); + generators.amount[oper].range.high = min( + generators.amount[oper].range.high, + preset_generators->amount[oper].range.high); + continue; + } generators.amount[oper].value += preset_generators->amount[oper].value; + }
hr = instrument_add_soundfont_region(This, soundfont, &generators); } @@ -658,7 +670,14 @@ HRESULT instrument_create_from_soundfont(struct soundfont *soundfont, UINT index struct collection *collection, DMUS_OBJECTDESC *desc, IDirectMusicInstrument **ret_iface) { struct sf_preset *preset = soundfont->phdr + index; - struct sf_generators global_generators = {0}; + struct sf_generators global_generators = + { + .amount = + { + [SF_GEN_KEY_RANGE] = {.range = {.low = 0, .high = 127}}, + [SF_GEN_VEL_RANGE] = {.range = {.low = 0, .high = 127}}, + }, + }; IDirectMusicInstrument *iface; struct instrument *This; HRESULT hr;
From: Anton Baskanov baskanov@gmail.com
--- dlls/dmusic/instrument.c | 78 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+)
diff --git a/dlls/dmusic/instrument.c b/dlls/dmusic/instrument.c index 570af0ee647..c4bce662d63 100644 --- a/dlls/dmusic/instrument.c +++ b/dlls/dmusic/instrument.c @@ -558,17 +558,95 @@ static BOOL parse_soundfont_generators(struct soundfont *soundfont, UINT index, return TRUE; }
+static const USHORT gen_to_conn_dst[SF_GEN_END_OPER] = +{ + [SF_GEN_MOD_LFO_TO_PITCH] = CONN_DST_PITCH, + [SF_GEN_VIB_LFO_TO_PITCH] = CONN_DST_PITCH, + [SF_GEN_MOD_ENV_TO_PITCH] = CONN_DST_PITCH, + [SF_GEN_INITIAL_FILTER_FC] = CONN_DST_FILTER_CUTOFF, + [SF_GEN_INITIAL_FILTER_Q] = CONN_DST_FILTER_Q, + [SF_GEN_MOD_LFO_TO_FILTER_FC] = CONN_DST_FILTER_CUTOFF, + [SF_GEN_MOD_ENV_TO_FILTER_FC] = CONN_DST_FILTER_CUTOFF, + [SF_GEN_MOD_LFO_TO_VOLUME] = CONN_DST_GAIN, + [SF_GEN_CHORUS_EFFECTS_SEND] = CONN_DST_CHORUS, + [SF_GEN_REVERB_EFFECTS_SEND] = CONN_DST_REVERB, + [SF_GEN_PAN] = CONN_DST_PAN, + [SF_GEN_DELAY_MOD_LFO] = CONN_DST_LFO_STARTDELAY, + [SF_GEN_FREQ_MOD_LFO] = CONN_DST_LFO_FREQUENCY, + [SF_GEN_DELAY_VIB_LFO] = CONN_DST_VIB_STARTDELAY, + [SF_GEN_FREQ_VIB_LFO] = CONN_DST_VIB_FREQUENCY, + [SF_GEN_DELAY_MOD_ENV] = CONN_DST_EG2_DELAYTIME, + [SF_GEN_ATTACK_MOD_ENV] = CONN_DST_EG2_ATTACKTIME, + [SF_GEN_HOLD_MOD_ENV] = CONN_DST_EG2_HOLDTIME, + [SF_GEN_DECAY_MOD_ENV] = CONN_DST_EG2_DECAYTIME, + [SF_GEN_SUSTAIN_MOD_ENV] = CONN_DST_EG2_SUSTAINLEVEL, + [SF_GEN_RELEASE_MOD_ENV] = CONN_DST_EG2_RELEASETIME, + [SF_GEN_KEYNUM_TO_MOD_ENV_HOLD] = CONN_DST_NONE, + [SF_GEN_KEYNUM_TO_MOD_ENV_DECAY] = CONN_DST_NONE, + [SF_GEN_DELAY_VOL_ENV] = CONN_DST_EG1_DELAYTIME, + [SF_GEN_ATTACK_VOL_ENV] = CONN_DST_EG1_ATTACKTIME, + [SF_GEN_HOLD_VOL_ENV] = CONN_DST_EG1_HOLDTIME, + [SF_GEN_DECAY_VOL_ENV] = CONN_DST_EG1_DECAYTIME, + [SF_GEN_SUSTAIN_VOL_ENV] = CONN_DST_EG1_SUSTAINLEVEL, + [SF_GEN_RELEASE_VOL_ENV] = CONN_DST_EG1_RELEASETIME, + [SF_GEN_KEYNUM_TO_VOL_ENV_HOLD] = CONN_DST_EG1_HOLDTIME, + [SF_GEN_KEYNUM_TO_VOL_ENV_DECAY] = CONN_DST_EG1_DECAYTIME, + [SF_GEN_INITIAL_ATTENUATION] = CONN_DST_GAIN, +}; + +static const USHORT gen_to_conn_src[SF_GEN_END_OPER] = +{ + [SF_GEN_MOD_LFO_TO_PITCH] = CONN_SRC_LFO, + [SF_GEN_VIB_LFO_TO_PITCH] = CONN_SRC_VIBRATO, + [SF_GEN_MOD_ENV_TO_PITCH] = CONN_SRC_EG2, + [SF_GEN_MOD_LFO_TO_FILTER_FC] = CONN_SRC_LFO, + [SF_GEN_MOD_ENV_TO_FILTER_FC] = CONN_SRC_EG2, + [SF_GEN_MOD_LFO_TO_VOLUME] = CONN_SRC_LFO, + [SF_GEN_KEYNUM_TO_VOL_ENV_HOLD] = CONN_SRC_KEYNUMBER, + [SF_GEN_KEYNUM_TO_VOL_ENV_DECAY] = CONN_SRC_KEYNUMBER, +}; + static HRESULT instrument_add_soundfont_region(struct instrument *This, struct soundfont *soundfont, struct sf_generators *generators) { UINT start_loop, end_loop, unity_note, sample_index = generators->amount[SF_GEN_SAMPLE_ID].value; struct sf_sample *sample = soundfont->shdr + sample_index; + struct articulation *articulation; struct region *region; double attenuation; + sf_generator oper;
if (!(region = calloc(1, sizeof(*region)))) return E_OUTOFMEMORY; list_init(®ion->articulations);
+ if (!(articulation = calloc(1, offsetof(struct articulation, connections[SF_GEN_END_OPER])))) + { + free(region); + return E_OUTOFMEMORY; + } + articulation->list.cbSize = sizeof(CONNECTIONLIST); + + for (oper = 0; oper < SF_GEN_END_OPER; ++oper) + { + CONNECTION *conn = &articulation->connections[articulation->list.cConnections]; + USHORT dst = gen_to_conn_dst[oper]; + + if (dst == CONN_DST_NONE || dst == CONN_DST_GAIN) + continue; + + conn->usSource = gen_to_conn_src[oper]; + conn->usDestination = dst; + + if (oper == SF_GEN_SUSTAIN_MOD_ENV || oper == SF_GEN_SUSTAIN_VOL_ENV) + conn->lScale = (1000 - (SHORT)generators->amount[oper].value) * 65536; + else + conn->lScale = (SHORT)generators->amount[oper].value * 65536; + + ++articulation->list.cConnections; + } + + list_add_tail(®ion->articulations, &articulation->entry); + region->header.RangeKey.usLow = generators->amount[SF_GEN_KEY_RANGE].range.low; region->header.RangeKey.usHigh = generators->amount[SF_GEN_KEY_RANGE].range.high; region->header.RangeVelocity.usLow = generators->amount[SF_GEN_VEL_RANGE].range.low;
From: Anton Baskanov baskanov@gmail.com
--- dlls/dmusic/instrument.c | 182 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 179 insertions(+), 3 deletions(-)
diff --git a/dlls/dmusic/instrument.c b/dlls/dmusic/instrument.c index c4bce662d63..4fcc9a8ed18 100644 --- a/dlls/dmusic/instrument.c +++ b/dlls/dmusic/instrument.c @@ -510,6 +510,82 @@ static const struct sf_generators SF_DEFAULT_GENERATORS = } };
+static const struct sf_mod SF_DEFAULT_MODULATORS[] = +{ + { + .src_mod = SF_MOD_CTRL_GEN_VELOCITY | SF_MOD_DIR_DECREASING | SF_MOD_SRC_CONCAVE, + .dest_gen = SF_GEN_INITIAL_ATTENUATION, + .amount = 960, + }, + { + .src_mod = SF_MOD_CTRL_GEN_VELOCITY | SF_MOD_DIR_DECREASING, + .dest_gen = SF_GEN_INITIAL_FILTER_FC, + .amount = -2400, + .amount_src_mod = SF_MOD_CTRL_GEN_VELOCITY | SF_MOD_DIR_DECREASING | SF_MOD_SRC_SWITCH, + }, + { + .src_mod = SF_MOD_CTRL_GEN_CHAN_PRESSURE, + .dest_gen = SF_GEN_VIB_LFO_TO_PITCH, + .amount = 50, + }, + { + .src_mod = 1 | SF_MOD_CTRL_MIDI, + .dest_gen = SF_GEN_VIB_LFO_TO_PITCH, + .amount = 50, + }, + { + .src_mod = 7 | SF_MOD_CTRL_MIDI | SF_MOD_DIR_DECREASING | SF_MOD_SRC_CONCAVE, + .dest_gen = SF_GEN_INITIAL_ATTENUATION, + .amount = 960, + }, + { + .src_mod = 10 | SF_MOD_CTRL_MIDI | SF_MOD_POL_BIPOLAR, + .dest_gen = SF_GEN_PAN, + .amount = 1000, + }, + { + .src_mod = 11 | SF_MOD_CTRL_MIDI | SF_MOD_DIR_DECREASING | SF_MOD_SRC_CONCAVE, + .dest_gen = SF_GEN_INITIAL_ATTENUATION, + .amount = 960, + }, + { + .src_mod = 91 | SF_MOD_CTRL_MIDI, + .dest_gen = SF_GEN_REVERB_EFFECTS_SEND, + .amount = 200, + }, + { + .src_mod = 93 | SF_MOD_CTRL_MIDI, + .dest_gen = SF_GEN_CHORUS_EFFECTS_SEND, + .amount = 200, + }, +}; + +struct sf_modulators +{ + UINT count; + UINT capacity; + struct sf_mod *mods; +}; + +static void copy_modulators(struct sf_modulators *dst, const struct sf_mod *mods, UINT count) +{ + if (dst->capacity < count) + { + struct sf_mod *mods; + + if (!(mods = malloc(count * sizeof(struct sf_mod)))) + return; + + free(dst->mods); + + dst->mods = mods; + dst->capacity = count; + } + + memcpy(dst->mods, mods, count * sizeof(struct sf_mod)); + dst->count = count; +} + static BOOL parse_soundfont_generators(struct soundfont *soundfont, UINT index, BOOL preset, struct sf_generators *generators) { @@ -606,20 +682,74 @@ static const USHORT gen_to_conn_src[SF_GEN_END_OPER] = [SF_GEN_KEYNUM_TO_VOL_ENV_DECAY] = CONN_SRC_KEYNUMBER, };
+static const USHORT mod_ctrl_to_conn_src[] = +{ + [SF_MOD_CTRL_GEN_NONE] = CONN_SRC_NONE, + [SF_MOD_CTRL_GEN_VELOCITY] = CONN_SRC_KEYONVELOCITY, + [SF_MOD_CTRL_GEN_KEY] = CONN_SRC_KEYNUMBER, + [SF_MOD_CTRL_GEN_POLY_PRESSURE] = CONN_SRC_POLYPRESSURE, + [SF_MOD_CTRL_GEN_CHAN_PRESSURE] = CONN_SRC_CHANNELPRESSURE, + [SF_MOD_CTRL_GEN_PITCH_WHEEL] = CONN_SRC_PITCHWHEEL, + [SF_MOD_CTRL_GEN_PITCH_WHEEL_SENSITIVITY] = CONN_SRC_RPN0, +}; + +static USHORT mod_src_to_conn_src(sf_modulator src) +{ + if (src & SF_MOD_CTRL_MIDI) + return CONN_SRC_CC1 - 1 + (src & 0x7f); + + if ((src & 0x7f) >= ARRAYSIZE(mod_ctrl_to_conn_src)) + return CONN_SRC_NONE; + + return mod_ctrl_to_conn_src[src & 0x7f]; +} + +static USHORT mod_src_to_conn_transform(sf_modulator src) +{ + USHORT transform = 0; + + if (src & SF_MOD_DIR_DECREASING) + transform |= CONN_TRN_INVERT; + + if (src & SF_MOD_POL_BIPOLAR) + transform |= CONN_TRN_BIPOLAR; + + switch (src & 0xc00) + { + case SF_MOD_SRC_LINEAR: + transform |= CONN_TRN_NONE; + break; + case SF_MOD_SRC_CONCAVE: + transform |= CONN_TRN_CONCAVE; + break; + case SF_MOD_SRC_CONVEX: + transform |= CONN_TRN_CONVEX; + break; + case SF_MOD_SRC_SWITCH: + transform |= CONN_TRN_SWITCH; + break; + } + + return transform; +} + static HRESULT instrument_add_soundfont_region(struct instrument *This, struct soundfont *soundfont, - struct sf_generators *generators) + struct sf_generators *generators, struct sf_modulators *modulators) { UINT start_loop, end_loop, unity_note, sample_index = generators->amount[SF_GEN_SAMPLE_ID].value; struct sf_sample *sample = soundfont->shdr + sample_index; struct articulation *articulation; + DWORD connection_count; struct region *region; double attenuation; sf_generator oper; + UINT i;
if (!(region = calloc(1, sizeof(*region)))) return E_OUTOFMEMORY; list_init(®ion->articulations);
- if (!(articulation = calloc(1, offsetof(struct articulation, connections[SF_GEN_END_OPER])))) + connection_count = SF_GEN_END_OPER + modulators->count; + if (!(articulation = calloc(1, offsetof(struct articulation, connections[connection_count])))) { free(region); return E_OUTOFMEMORY; @@ -645,6 +775,47 @@ static HRESULT instrument_add_soundfont_region(struct instrument *This, struct s ++articulation->list.cConnections; }
+ for (i = 0; i < modulators->count; ++i) + { + CONNECTION *conn = &articulation->connections[articulation->list.cConnections]; + struct sf_mod *mod = &modulators->mods[i]; + USHORT src_transform, ctrl_transform; + + if (mod->dest_gen >= ARRAYSIZE(gen_to_conn_dst)) + continue; + conn->usDestination = gen_to_conn_dst[mod->dest_gen]; + + if (gen_to_conn_src[mod->dest_gen] == CONN_SRC_NONE) + { + conn->usSource = mod_src_to_conn_src(mod->src_mod); + conn->usControl = mod_src_to_conn_src(mod->amount_src_mod); + src_transform = mod_src_to_conn_transform(mod->src_mod); + ctrl_transform = mod_src_to_conn_transform(mod->amount_src_mod); + } + else if (mod_src_to_conn_src(mod->amount_src_mod) == CONN_SRC_NONE) + { + conn->usSource = gen_to_conn_src[mod->dest_gen]; + conn->usControl = mod_src_to_conn_src(mod->src_mod); + src_transform = CONN_TRN_NONE; + ctrl_transform = mod_src_to_conn_transform(mod->src_mod); + } + else + { + FIXME("Modulator requires a three-input connection.\n"); + continue; + } + conn->usTransform = (src_transform << 10) | (ctrl_transform << 4); + + if (mod->dest_gen == SF_GEN_SUSTAIN_MOD_ENV || mod->dest_gen == SF_GEN_SUSTAIN_VOL_ENV) + conn->lScale = mod->amount * -65536; + else if (mod->dest_gen == SF_GEN_MOD_LFO_TO_VOLUME && mod->src_mod == SF_MOD_CTRL_GEN_CHAN_PRESSURE) + conn->lScale = mod->amount * 655360; + else + conn->lScale = mod->amount * 65536; + + ++articulation->list.cConnections; + } + list_add_tail(®ion->articulations, &articulation->entry);
region->header.RangeKey.usLow = generators->amount[SF_GEN_KEY_RANGE].range.low; @@ -706,10 +877,13 @@ static HRESULT instrument_add_soundfont_instrument(struct instrument *This, stru { struct sf_generators global_generators = SF_DEFAULT_GENERATORS; struct sf_instrument *instrument = soundfont->inst + index; + struct sf_modulators global_modulators = {}; UINT i = instrument->bag_ndx; sf_generator oper; HRESULT hr = S_OK;
+ copy_modulators(&global_modulators, SF_DEFAULT_MODULATORS, ARRAYSIZE(SF_DEFAULT_MODULATORS)); + for (i = instrument->bag_ndx; SUCCEEDED(hr) && i < (instrument + 1)->bag_ndx; i++) { struct sf_generators generators = global_generators; @@ -738,9 +912,11 @@ 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); + hr = instrument_add_soundfont_region(This, soundfont, &generators, &global_modulators); }
+ free(global_modulators.mods); + return hr; }
From: Anton Baskanov baskanov@gmail.com
--- dlls/dmusic/instrument.c | 68 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 67 insertions(+), 1 deletion(-)
diff --git a/dlls/dmusic/instrument.c b/dlls/dmusic/instrument.c index 4fcc9a8ed18..43d225f93dd 100644 --- a/dlls/dmusic/instrument.c +++ b/dlls/dmusic/instrument.c @@ -586,6 +586,45 @@ static void copy_modulators(struct sf_modulators *dst, const struct sf_mod *mods dst->count = 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) { @@ -634,6 +673,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, @@ -878,6 +936,7 @@ static HRESULT instrument_add_soundfont_instrument(struct instrument *This, stru struct sf_generators global_generators = SF_DEFAULT_GENERATORS; struct sf_instrument *instrument = soundfont->inst + index; struct sf_modulators global_modulators = {}; + struct sf_modulators modulators = {}; UINT i = instrument->bag_ndx; sf_generator oper; HRESULT hr = S_OK; @@ -888,12 +947,18 @@ static HRESULT instrument_add_soundfont_instrument(struct instrument *This, stru { struct sf_generators generators = global_generators;
+ copy_modulators(&modulators, global_modulators.mods, global_modulators.count); + + 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.mods, modulators.count); + } continue; }
@@ -912,9 +977,10 @@ 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); }
+ free(modulators.mods); free(global_modulators.mods);
return hr;
From: Anton Baskanov baskanov@gmail.com
--- dlls/dmusic/instrument.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-)
diff --git a/dlls/dmusic/instrument.c b/dlls/dmusic/instrument.c index 43d225f93dd..5cfbce5f999 100644 --- a/dlls/dmusic/instrument.c +++ b/dlls/dmusic/instrument.c @@ -931,7 +931,7 @@ static HRESULT instrument_add_soundfont_region(struct instrument *This, struct s }
static HRESULT instrument_add_soundfont_instrument(struct instrument *This, struct soundfont *soundfont, - UINT index, struct sf_generators *preset_generators) + UINT index, struct sf_generators *preset_generators, struct sf_modulators *preset_modulators) { struct sf_generators global_generators = SF_DEFAULT_GENERATORS; struct sf_instrument *instrument = soundfont->inst + index; @@ -940,6 +940,7 @@ static HRESULT instrument_add_soundfont_instrument(struct instrument *This, stru UINT i = instrument->bag_ndx; sf_generator oper; HRESULT hr = S_OK; + UINT j;
copy_modulators(&global_modulators, SF_DEFAULT_MODULATORS, ARRAYSIZE(SF_DEFAULT_MODULATORS));
@@ -977,6 +978,18 @@ static HRESULT instrument_add_soundfont_instrument(struct instrument *This, stru generators.amount[oper].value += preset_generators->amount[oper].value; }
+ for (j = 0; j < preset_modulators->count; ++j) + { + struct sf_mod *preset_mod = &preset_modulators->mods[j]; + struct sf_mod *mod; + if ((mod = find_modulator(&modulators, preset_mod))) + { + mod->amount += preset_mod->amount; + continue; + } + add_modulator(&modulators, preset_mod); + } + hr = instrument_add_soundfont_region(This, soundfont, &generators, &modulators); }
@@ -998,6 +1011,8 @@ HRESULT instrument_create_from_soundfont(struct soundfont *soundfont, UINT index [SF_GEN_VEL_RANGE] = {.range = {.low = 0, .high = 127}}, }, }; + struct sf_modulators global_modulators = {}; + struct sf_modulators modulators = {}; IDirectMusicInstrument *iface; struct instrument *This; HRESULT hr; @@ -1020,19 +1035,28 @@ HRESULT instrument_create_from_soundfont(struct soundfont *soundfont, UINT index struct sf_generators generators = global_generators; UINT instrument;
+ copy_modulators(&modulators, global_modulators.mods, global_modulators.count); + + parse_soundfont_modulators(soundfont, i, TRUE, &modulators); if (parse_soundfont_generators(soundfont, i, TRUE, &generators)) { if (i > preset->bag_ndx) WARN("Ignoring preset zone without an instrument\n"); else + { global_generators = generators; + copy_modulators(&global_modulators, modulators.mods, modulators.count); + } continue; }
instrument = generators.amount[SF_GEN_INSTRUMENT].value; - hr = instrument_add_soundfont_instrument(This, soundfont, instrument, &generators); + hr = instrument_add_soundfont_instrument(This, soundfont, instrument, &generators, &modulators); }
+ free(modulators.mods); + free(global_modulators.mods); + if (FAILED(hr)) { IDirectMusicInstrument_Release(iface);
On Thu Nov 27 09:57:49 2025 +0000, Rémi Bernon wrote:
`-32768 * 65536 = 0x80000000`, why the special case?
Done.
On Thu Nov 27 18:51:56 2025 +0000, Anton Baskanov wrote:
changed this line in [version 2 of the diff](/wine/wine/-/merge_requests/9607/diffs?diff_id=228180&start_sha=37d29f98cda8f796127753ac126bbef264154ebe#10f65150261f79fd17205ded12c05be754cd4053_875_871)
Done.
v2: - Remove special handling for `-32768`. - Don't store pointer to a static data in `struct sf_modulators`. - Print a `FIXME` for modulators requiring three-input connections.
As you need a dynamic array later it's probably better to just introduce it here already and make a copy right away.
Done.
I'd suggest to use flexible array member for `mods`, and variable size struct for the `sf_modulators`
This would require either a double pointer indirection or returning the new pointer from `copy_modulators`/`add_modulator`, both of which seem to be less readable than the current version. Or am I missing something?
it would make cleaning up as simple as `free(modulators)` instead of having to check `capacity` as a hint to whether it has been dynamically allocated or not.
It's now `free(modulators.mods)` which is close.
On Thu Nov 27 09:57:49 2025 +0000, Rémi Bernon wrote:
Should we really have usSource == usDestination and usControl set to the SF2 source? I'm pretty outdated on SF2 but it would feel more natural for connections to follow `<src> -> <dst>` or `<src> mod <ctrl> -> <dst>` patterns, rather than a seemingly recursive `<dst> mod <ctrl> -> <dst>`?
Some SF2 generators already map to `<src> -> <dst>` connections, e.g. `SF_GEN_VIB_LFO_TO_PITCH` is mapped to `CONN_SRC_VIBRATO -> CONN_DST_PITCH`. There are also modulators that output to such generators, e.g. `SF_MOD_CTRL_GEN_CHAN_PRESSURE -> SF_GEN_VIB_LFO_TO_PITCH` which is mapped to `CONN_SRC_VIBRATO mod CONN_SRC_CHANNELPRESSURE -> CONN_DST_PITCH`. It's the latter case that is handled by this `else` branch.
On Thu Nov 27 18:53:59 2025 +0000, Anton Baskanov wrote:
Some SF2 generators already map to `<src> -> <dst>` connections, e.g. `SF_GEN_VIB_LFO_TO_PITCH` is mapped to `CONN_SRC_VIBRATO -> CONN_DST_PITCH`. There are also modulators that output to such generators, e.g. `SF_MOD_CTRL_GEN_CHAN_PRESSURE -> SF_GEN_VIB_LFO_TO_PITCH` which is mapped to `CONN_SRC_VIBRATO mod CONN_SRC_CHANNELPRESSURE -> CONN_DST_PITCH`. It's the latter case that is handled by this `else` branch.
Right, sorry I misread `gen_to_conn_src` as `gen_to_conn_dst`.
On Thu Nov 27 18:53:59 2025 +0000, Anton Baskanov wrote:
As you need a dynamic array later it's probably better to just
introduce it here already and make a copy right away. Done.
I'd suggest to use flexible array member for `mods`, and variable size
struct for the `sf_modulators` This would require either a double pointer indirection or returning the new pointer from `copy_modulators`/`add_modulator`, both of which seem to be less readable than the current version. Or am I missing something?
it would make cleaning up as simple as `free(modulators)` instead of
having to check `capacity` as a hint to whether it has been dynamically allocated or not. It's now `free(modulators.mods)` which is close.
I think you could tweak things in order to avoid having to reallocate the array and always just need a `struct sf_modulators` return pointer, or you could even pre-iterate over the instruments bags and mods to find the maximum number of modulators that would fit every possible case.
Anyway, I'm fine with current code too.
This merge request was approved by Rémi Bernon.
This merge request was approved by Michael Stefaniuc.