From: Anton Baskanov baskanov@gmail.com
--- dlls/dmsynth/synth.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+)
diff --git a/dlls/dmsynth/synth.c b/dlls/dmsynth/synth.c index a4196f29a8a..aee76af5302 100644 --- a/dlls/dmsynth/synth.c +++ b/dlls/dmsynth/synth.c @@ -320,6 +320,13 @@ struct event BYTE midi[3]; };
+struct voice +{ + struct list entry; + fluid_voice_t *fluid_voice; + struct wave *wave; +}; + struct synth { IDirectMusicSynth8 IDirectMusicSynth8_iface; @@ -336,6 +343,7 @@ struct synth struct list instruments; struct list waves; struct list events; + struct list voices;
fluid_settings_t *fluid_settings; fluid_sfont_t *fluid_sfont; @@ -584,6 +592,8 @@ static HRESULT WINAPI synth_Open(IDirectMusicSynth8 *iface, DMUS_PORTPARAMS *par static HRESULT WINAPI synth_Close(IDirectMusicSynth8 *iface) { struct synth *This = impl_from_IDirectMusicSynth8(iface); + struct voice *voice; + void *next;
TRACE("(%p)\n", This);
@@ -597,6 +607,14 @@ static HRESULT WINAPI synth_Close(IDirectMusicSynth8 *iface) fluid_synth_remove_sfont(This->fluid_synth, This->fluid_sfont); delete_fluid_synth(This->fluid_synth); This->fluid_synth = NULL; + + LIST_FOR_EACH_ENTRY_SAFE(voice, next, &This->voices, struct voice, entry) + { + list_remove(&voice->entry); + wave_release(voice->wave); + free(voice); + } + This->open = FALSE; LeaveCriticalSection(&This->cs);
@@ -1742,6 +1760,7 @@ static int synth_preset_noteon(fluid_preset_t *fluid_preset, fluid_synth_t *flui { struct articulation *articulation; struct wave *wave = region->wave; + struct voice *voice;
if (key < region->key_range.usLow || key > region->key_range.usHigh) continue; if (vel < region->vel_range.usLow || vel > region->vel_range.usHigh) continue; @@ -1763,6 +1782,29 @@ static int synth_preset_noteon(fluid_preset_t *fluid_preset, fluid_synth_t *flui return FLUID_FAILED; }
+ LIST_FOR_EACH_ENTRY(voice, &synth->voices, struct voice, entry) + { + if (voice->fluid_voice == fluid_voice) + { + wave_release(voice->wave); + break; + } + } + + if (&voice->entry == &synth->voices) + { + if (!(voice = calloc(1, sizeof(struct voice)))) + { + delete_fluid_sample(fluid_sample); + return FLUID_FAILED; + } + voice->fluid_voice = fluid_voice; + list_add_tail(&synth->voices, &voice->entry); + } + + voice->wave = wave; + wave_addref(voice->wave); + set_default_voice_connections(fluid_voice); if (region->wave_sample.cSampleLoops) { @@ -1885,6 +1927,7 @@ HRESULT synth_create(IUnknown **ret_iface) list_init(&obj->instruments); list_init(&obj->waves); list_init(&obj->events); + list_init(&obj->voices);
if (!(obj->fluid_settings = new_fluid_settings())) goto failed; if (!(obj->fluid_sfont = new_fluid_sfont(synth_sfont_get_name, synth_sfont_get_preset,
From: Anton Baskanov baskanov@gmail.com
--- dlls/dmsynth/synth.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/dmsynth/synth.c b/dlls/dmsynth/synth.c index aee76af5302..556947fc30a 100644 --- a/dlls/dmsynth/synth.c +++ b/dlls/dmsynth/synth.c @@ -1739,7 +1739,6 @@ static void set_default_voice_connections(fluid_voice_t *fluid_voice) fluid_voice_gen_set(fluid_voice, GEN_KEYNUM, -1.); fluid_voice_gen_set(fluid_voice, GEN_VELOCITY, -1.); fluid_voice_gen_set(fluid_voice, GEN_SCALETUNE, 100.0); - fluid_voice_gen_set(fluid_voice, GEN_OVERRIDEROOTKEY, -1.);
add_voice_connections(fluid_voice, &list, connections); } @@ -1773,7 +1772,6 @@ static int synth_preset_noteon(fluid_preset_t *fluid_preset, fluid_synth_t *flui
fluid_sample_set_sound_data(fluid_sample, wave->samples, NULL, wave->sample_count, wave->format.nSamplesPerSec, TRUE); - fluid_sample_set_pitch(fluid_sample, region->wave_sample.usUnityNote, region->wave_sample.sFineTune);
if (!(fluid_voice = fluid_synth_alloc_voice(synth->fluid_synth, fluid_sample, chan, key, vel))) { @@ -1823,6 +1821,8 @@ static int synth_preset_noteon(fluid_preset_t *fluid_preset, fluid_synth_t *flui fluid_voice_gen_set(fluid_voice, GEN_STARTLOOPADDROFS, 8 + loop->ulStart); fluid_voice_gen_set(fluid_voice, GEN_ENDLOOPADDROFS, 8 + loop->ulStart + loop->ulLength); } + fluid_voice_gen_set(fluid_voice, GEN_OVERRIDEROOTKEY, region->wave_sample.usUnityNote); + fluid_voice_gen_set(fluid_voice, GEN_FINETUNE, region->wave_sample.sFineTune); LIST_FOR_EACH_ENTRY(articulation, &instrument->articulations, struct articulation, entry) add_voice_connections(fluid_voice, &articulation->list, articulation->connections); LIST_FOR_EACH_ENTRY(articulation, ®ion->articulations, struct articulation, entry)
From: Anton Baskanov baskanov@gmail.com
--- dlls/dmsynth/synth.c | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-)
diff --git a/dlls/dmsynth/synth.c b/dlls/dmsynth/synth.c index 556947fc30a..f936d51e02e 100644 --- a/dlls/dmsynth/synth.c +++ b/dlls/dmsynth/synth.c @@ -209,6 +209,8 @@ struct wave LONG ref; UINT id;
+ fluid_sample_t *fluid_sample; + WAVEFORMATEX format; UINT sample_count; short samples[]; @@ -224,7 +226,11 @@ static void wave_addref(struct wave *wave) static void wave_release(struct wave *wave) { ULONG ref = InterlockedDecrement(&wave->ref); - if (!ref) free(wave); + if (!ref) + { + delete_fluid_sample(wave->fluid_sample); + free(wave); + } }
struct articulation @@ -825,6 +831,16 @@ static HRESULT synth_download_wave(struct synth *This, DMUS_DOWNLOADINFO *info, } }
+ if (!(wave->fluid_sample = new_fluid_sample())) + { + WARN("Failed to allocate FluidSynth sample\n"); + free(wave); + return FLUID_FAILED; + } + + fluid_sample_set_sound_data(wave->fluid_sample, wave->samples, NULL, wave->sample_count, + wave->format.nSamplesPerSec, TRUE); + EnterCriticalSection(&This->cs); list_add_tail(&This->waves, &wave->entry); LeaveCriticalSection(&This->cs); @@ -1747,7 +1763,6 @@ static int synth_preset_noteon(fluid_preset_t *fluid_preset, fluid_synth_t *flui { struct instrument *instrument = fluid_preset_get_data(fluid_preset); struct synth *synth = instrument->synth; - fluid_sample_t *fluid_sample; fluid_voice_t *fluid_voice; struct region *region;
@@ -1764,19 +1779,9 @@ static int synth_preset_noteon(fluid_preset_t *fluid_preset, fluid_synth_t *flui if (key < region->key_range.usLow || key > region->key_range.usHigh) continue; if (vel < region->vel_range.usLow || vel > region->vel_range.usHigh) continue;
- if (!(fluid_sample = new_fluid_sample())) - { - WARN("Failed to allocate FluidSynth sample\n"); - return FLUID_FAILED; - } - - fluid_sample_set_sound_data(fluid_sample, wave->samples, NULL, wave->sample_count, - wave->format.nSamplesPerSec, TRUE); - - if (!(fluid_voice = fluid_synth_alloc_voice(synth->fluid_synth, fluid_sample, chan, key, vel))) + if (!(fluid_voice = fluid_synth_alloc_voice(synth->fluid_synth, wave->fluid_sample, chan, key, vel))) { WARN("Failed to allocate FluidSynth voice\n"); - delete_fluid_sample(fluid_sample); return FLUID_FAILED; }
@@ -1792,10 +1797,7 @@ static int synth_preset_noteon(fluid_preset_t *fluid_preset, fluid_synth_t *flui if (&voice->entry == &synth->voices) { if (!(voice = calloc(1, sizeof(struct voice)))) - { - delete_fluid_sample(fluid_sample); return FLUID_FAILED; - } voice->fluid_voice = fluid_voice; list_add_tail(&synth->voices, &voice->entry); }
From: Anton Baskanov baskanov@gmail.com
We always set the data. --- dlls/dmsynth/synth.c | 5 ----- 1 file changed, 5 deletions(-)
diff --git a/dlls/dmsynth/synth.c b/dlls/dmsynth/synth.c index f936d51e02e..6d747980cbd 100644 --- a/dlls/dmsynth/synth.c +++ b/dlls/dmsynth/synth.c @@ -1398,7 +1398,6 @@ static int synth_preset_get_num(fluid_preset_t *fluid_preset)
TRACE("(%p)\n", fluid_preset);
- if (!instrument) return 0; return instrument->patch; }
@@ -1768,8 +1767,6 @@ static int synth_preset_noteon(fluid_preset_t *fluid_preset, fluid_synth_t *flui
TRACE("(%p, %p, %u, %u, %u)\n", fluid_preset, fluid_synth, chan, key, vel);
- if (!instrument) return FLUID_FAILED; - LIST_FOR_EACH_ENTRY(region, &instrument->regions, struct region, entry) { struct articulation *articulation; @@ -1857,8 +1854,6 @@ static fluid_preset_t *synth_sfont_get_preset(fluid_sfont_t *fluid_sfont, int ba
TRACE("(%p, %d, %d)\n", fluid_sfont, bank, patch);
- if (!synth) return NULL; - EnterCriticalSection(&synth->cs);
LIST_FOR_EACH_ENTRY(instrument, &synth->instruments, struct instrument, entry)
From: Anton Baskanov baskanov@gmail.com
FluidSynth never calls synth_preset_free(), causing preset and instrument leaks. --- dlls/dmsynth/synth.c | 69 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 58 insertions(+), 11 deletions(-)
diff --git a/dlls/dmsynth/synth.c b/dlls/dmsynth/synth.c index 6d747980cbd..b3c624b5b6b 100644 --- a/dlls/dmsynth/synth.c +++ b/dlls/dmsynth/synth.c @@ -319,6 +319,17 @@ static void instrument_release(struct instrument *instrument) } }
+struct preset +{ + struct list entry; + int bank; + int patch; + + fluid_preset_t *fluid_preset; + + struct instrument *instrument; +}; + struct event { struct list entry; @@ -350,6 +361,7 @@ struct synth struct list waves; struct list events; struct list voices; + struct list presets;
fluid_settings_t *fluid_settings; fluid_sfont_t *fluid_sfont; @@ -598,6 +610,7 @@ static HRESULT WINAPI synth_Open(IDirectMusicSynth8 *iface, DMUS_PORTPARAMS *par static HRESULT WINAPI synth_Close(IDirectMusicSynth8 *iface) { struct synth *This = impl_from_IDirectMusicSynth8(iface); + struct preset *preset; struct voice *voice; void *next;
@@ -621,6 +634,14 @@ static HRESULT WINAPI synth_Close(IDirectMusicSynth8 *iface) free(voice); }
+ LIST_FOR_EACH_ENTRY_SAFE(preset, next, &This->presets, struct preset, entry) + { + list_remove(&preset->entry); + instrument_release(preset->instrument); + delete_fluid_preset(preset->fluid_preset); + free(preset); + } + This->open = FALSE; LeaveCriticalSection(&This->cs);
@@ -1394,11 +1415,11 @@ static int synth_preset_get_bank(fluid_preset_t *fluid_preset)
static int synth_preset_get_num(fluid_preset_t *fluid_preset) { - struct instrument *instrument = fluid_preset_get_data(fluid_preset); + struct preset *preset = fluid_preset_get_data(fluid_preset);
TRACE("(%p)\n", fluid_preset);
- return instrument->patch; + return preset->patch; }
static BOOL gen_from_connection(const CONNECTION *conn, UINT *gen) @@ -1760,7 +1781,8 @@ static void set_default_voice_connections(fluid_voice_t *fluid_voice)
static int synth_preset_noteon(fluid_preset_t *fluid_preset, fluid_synth_t *fluid_synth, int chan, int key, int vel) { - struct instrument *instrument = fluid_preset_get_data(fluid_preset); + struct preset *preset = fluid_preset_get_data(fluid_preset); + struct instrument *instrument = preset->instrument; struct synth *synth = instrument->synth; fluid_voice_t *fluid_voice; struct region *region; @@ -1836,9 +1858,6 @@ static int synth_preset_noteon(fluid_preset_t *fluid_preset, fluid_synth_t *flui
static void synth_preset_free(fluid_preset_t *fluid_preset) { - struct instrument *instrument = fluid_preset_get_data(fluid_preset); - fluid_preset_set_data(fluid_preset, NULL); - if (instrument) instrument_release(instrument); }
static const char *synth_sfont_get_name(fluid_sfont_t *fluid_sfont) @@ -1851,11 +1870,21 @@ static fluid_preset_t *synth_sfont_get_preset(fluid_sfont_t *fluid_sfont, int ba struct synth *synth = fluid_sfont_get_data(fluid_sfont); struct instrument *instrument; fluid_preset_t *fluid_preset; + struct preset *preset;
TRACE("(%p, %d, %d)\n", fluid_sfont, bank, patch);
EnterCriticalSection(&synth->cs);
+ LIST_FOR_EACH_ENTRY(preset, &synth->presets, struct preset, entry) + { + if (preset->bank == bank && preset->patch == patch) + { + LeaveCriticalSection(&synth->cs); + return preset->fluid_preset; + } + } + LIST_FOR_EACH_ENTRY(instrument, &synth->instruments, struct instrument, entry) { if (bank == 128 && instrument->patch == (0x80000000 | patch)) break; @@ -1864,18 +1893,35 @@ static fluid_preset_t *synth_sfont_get_preset(fluid_sfont_t *fluid_sfont, int ba
if (&instrument->entry == &synth->instruments) { - fluid_preset = NULL; WARN("Could not find instrument with patch %#x\n", patch); + LeaveCriticalSection(&synth->cs); + return NULL; } - else if ((fluid_preset = new_fluid_preset(fluid_sfont, synth_preset_get_name, synth_preset_get_bank, + + if (!(fluid_preset = new_fluid_preset(fluid_sfont, synth_preset_get_name, synth_preset_get_bank, synth_preset_get_num, synth_preset_noteon, synth_preset_free))) { - fluid_preset_set_data(fluid_preset, instrument); - instrument_addref(instrument); + LeaveCriticalSection(&synth->cs); + return NULL; + }
- TRACE("Created fluid_preset %p for instrument %p\n", fluid_preset, instrument); + if (!(preset = calloc(1, sizeof(struct preset)))) + { + delete_fluid_preset(fluid_preset); + LeaveCriticalSection(&synth->cs); + return NULL; }
+ preset->bank = bank; + preset->patch = patch; + preset->fluid_preset = fluid_preset; + preset->instrument = instrument; + fluid_preset_set_data(fluid_preset, preset); + instrument_addref(instrument); + list_add_tail(&synth->presets, &preset->entry); + + TRACE("Created fluid_preset %p for instrument %p\n", fluid_preset, instrument); + LeaveCriticalSection(&synth->cs);
return fluid_preset; @@ -1925,6 +1971,7 @@ HRESULT synth_create(IUnknown **ret_iface) list_init(&obj->waves); list_init(&obj->events); list_init(&obj->voices); + list_init(&obj->presets);
if (!(obj->fluid_settings = new_fluid_settings())) goto failed; if (!(obj->fluid_sfont = new_fluid_sfont(synth_sfont_get_name, synth_sfont_get_preset,
From: Anton Baskanov baskanov@gmail.com
--- dlls/dmsynth/synth.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/dlls/dmsynth/synth.c b/dlls/dmsynth/synth.c index b3c624b5b6b..410fb59089e 100644 --- a/dlls/dmsynth/synth.c +++ b/dlls/dmsynth/synth.c @@ -1607,6 +1607,7 @@ static void add_mod_from_connection(fluid_voice_t *fluid_voice, const CONNECTION fluid_mod_set_amount(mod, value);
fluid_voice_add_mod(fluid_voice, mod, FLUID_VOICE_OVERWRITE); + delete_fluid_mod(mod); }
static void add_voice_connections(fluid_voice_t *fluid_voice, const CONNECTIONLIST *list,
On Thu Nov 9 13:07:43 2023 +0000, Rémi Bernon wrote:
c4f42a68f09842a00daaff108992ff369b416cd0 somehow breaks in-game music in FF VIII after the first time a track is played (for instance after transitioning out and back in a zone), I think you should drop it for now.
Done.
This merge request was approved by Rémi Bernon.
This merge request was approved by Michael Stefaniuc.
Unrelated test failures in win.c and device8.c