[PATCH v4 0/3] MR9373: dmusic,dmsynth: Reduce memory usage part 2
-- v4: dmsynth: Remove format and sample_count from struct wave. dmsynth: Allow zero-copy access to the sample data. https://gitlab.winehq.org/wine/wine/-/merge_requests/9373
From: Anton Baskanov <baskanov(a)gmail.com> --- dlls/dmusic/port.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/dlls/dmusic/port.c b/dlls/dmusic/port.c index 84a9e759ab2..1945bf82c4f 100644 --- a/dlls/dmusic/port.c +++ b/dlls/dmusic/port.c @@ -29,6 +29,7 @@ struct download_entry struct list entry; IDirectMusicDownload *download; HANDLE handle; + BOOL can_free; DWORD id; }; @@ -522,6 +523,7 @@ static HRESULT WINAPI synth_port_download_Download(IDirectMusicPortDownload *ifa IDirectMusicDownload_AddRef(download); entry->id = info->dwDLId; entry->handle = handle; + entry->can_free = can_free; list_add_tail(&This->downloads, &entry->entry); } @@ -529,11 +531,19 @@ static HRESULT WINAPI synth_port_download_Download(IDirectMusicPortDownload *ifa return hr; } +static HRESULT CALLBACK unload_callback(HANDLE handle, HANDLE user_data) +{ + IDirectMusicDownload *download = (IDirectMusicDownload *)user_data; + IDirectMusicDownload_Release(download); + return S_OK; +} + static HRESULT WINAPI synth_port_download_Unload(IDirectMusicPortDownload *iface, IDirectMusicDownload *download) { struct synth_port *This = synth_from_IDirectMusicPortDownload(iface); struct download_entry *entry; HANDLE handle = 0; + BOOL can_free; TRACE("(%p/%p)->(%p)\n", iface, This, download); @@ -544,15 +554,21 @@ static HRESULT WINAPI synth_port_download_Unload(IDirectMusicPortDownload *iface if (entry->download == download) { list_remove(&entry->entry); - IDirectMusicDownload_Release(entry->download); handle = entry->handle; + can_free = entry->can_free; free(entry); break; } } if (!handle) return S_OK; - return IDirectMusicSynth_Unload(This->synth, handle, NULL, NULL); + + if (can_free) + { + IDirectMusicDownload_Release(download); + return IDirectMusicSynth_Unload(This->synth, handle, NULL, NULL); + } + return IDirectMusicSynth_Unload(This->synth, handle, unload_callback, download); } static const IDirectMusicPortDownloadVtbl synth_port_download_vtbl = { -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9373
From: Anton Baskanov <baskanov(a)gmail.com> --- dlls/dmsynth/synth.c | 16 +++++++++------- dlls/dmsynth/tests/dmsynth.c | 2 +- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/dlls/dmsynth/synth.c b/dlls/dmsynth/synth.c index cc095a5e89d..b354ba9d0be 100644 --- a/dlls/dmsynth/synth.c +++ b/dlls/dmsynth/synth.c @@ -823,6 +823,8 @@ static HRESULT synth_download_wave(struct synth *This, DMUS_DOWNLOADINFO *info, DMUS_WAVEDATA *wave_data = (DMUS_WAVEDATA *)(data + offsets[wave_info->ulWaveDataIdx]); struct wave *wave; UINT sample_count; + short *samples; + size_t size; if (TRACE_ON(dmsynth)) { @@ -841,12 +843,15 @@ static HRESULT synth_download_wave(struct synth *This, DMUS_DOWNLOADINFO *info, if (wave_info->WaveformatEx.wFormatTag != WAVE_FORMAT_PCM) return DMUS_E_NOTPCM; sample_count = wave_data->cbSize / wave_info->WaveformatEx.nBlockAlign; - if (!(wave = calloc(1, offsetof(struct wave, samples[sample_count])))) return E_OUTOFMEMORY; + size = wave_info->WaveformatEx.nBlockAlign == 2 ? sizeof(struct wave) + : offsetof(struct wave, samples[sample_count]); + if (!(wave = calloc(1, size))) return E_OUTOFMEMORY; wave->ref = 1; wave->id = info->dwDLId; wave->format = wave_info->WaveformatEx; wave->sample_count = sample_count; + samples = wave->samples; if (wave_info->WaveformatEx.nBlockAlign == 1) { while (sample_count--) @@ -857,11 +862,7 @@ static HRESULT synth_download_wave(struct synth *This, DMUS_DOWNLOADINFO *info, } else if (wave_info->WaveformatEx.nBlockAlign == 2) { - while (sample_count--) - { - short sample = ((short *)wave_data->byData)[sample_count]; - wave->samples[sample_count] = sample; - } + samples = (short *)wave_data->byData; } else if (wave_info->WaveformatEx.nBlockAlign == 4) { @@ -881,7 +882,7 @@ static HRESULT synth_download_wave(struct synth *This, DMUS_DOWNLOADINFO *info, /* Although the doc says there should be 8-frame padding around the data, * FluidSynth doesn't actually require this since version 1.0.8. */ - fluid_sample_set_sound_data(wave->fluid_sample, wave->samples, NULL, wave->sample_count, + fluid_sample_set_sound_data(wave->fluid_sample, samples, NULL, wave->sample_count, wave->format.nSamplesPerSec, FALSE); EnterCriticalSection(&This->cs); @@ -922,6 +923,7 @@ static HRESULT WINAPI synth_Download(IDirectMusicSynth8 *iface, HANDLE *ret_hand case DMUS_DOWNLOADINFO_INSTRUMENT2: return synth_download_instrument(This, info, offsets, data, ret_handle); case DMUS_DOWNLOADINFO_WAVE: + *ret_free = FALSE; return synth_download_wave(This, info, offsets, data, ret_handle); case DMUS_DOWNLOADINFO_WAVEARTICULATION: FIXME("Download type DMUS_DOWNLOADINFO_WAVEARTICULATION not yet supported\n"); diff --git a/dlls/dmsynth/tests/dmsynth.c b/dlls/dmsynth/tests/dmsynth.c index b0dd4d8838b..696eceda612 100644 --- a/dlls/dmsynth/tests/dmsynth.c +++ b/dlls/dmsynth/tests/dmsynth.c @@ -1200,7 +1200,7 @@ static void test_IDirectMusicSynth(void) hr = IDirectMusicSynth_Download(synth, &wave_handle, &wave_download, &can_free); ok(hr == S_OK, "got %#lx\n", hr); ok(!!wave_handle, "got %p\n", wave_handle); - todo_wine ok(can_free == FALSE, "got %u\n", can_free); + ok(can_free == FALSE, "got %u\n", can_free); can_free = 0xdeadbeef; instrument_handle = NULL; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9373
From: Anton Baskanov <baskanov(a)gmail.com> --- dlls/dmsynth/synth.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/dlls/dmsynth/synth.c b/dlls/dmsynth/synth.c index b354ba9d0be..d6d633429e2 100644 --- a/dlls/dmsynth/synth.c +++ b/dlls/dmsynth/synth.c @@ -216,9 +216,6 @@ struct wave HANDLE user_data; fluid_sample_t *fluid_sample; - - WAVEFORMATEX format; - UINT sample_count; short samples[]; }; @@ -825,6 +822,7 @@ static HRESULT synth_download_wave(struct synth *This, DMUS_DOWNLOADINFO *info, UINT sample_count; short *samples; size_t size; + int i; if (TRACE_ON(dmsynth)) { @@ -848,16 +846,14 @@ static HRESULT synth_download_wave(struct synth *This, DMUS_DOWNLOADINFO *info, if (!(wave = calloc(1, size))) return E_OUTOFMEMORY; wave->ref = 1; wave->id = info->dwDLId; - wave->format = wave_info->WaveformatEx; - wave->sample_count = sample_count; samples = wave->samples; if (wave_info->WaveformatEx.nBlockAlign == 1) { - while (sample_count--) + for (i = 0; i < sample_count; ++i) { - short sample = (wave_data->byData[sample_count] - 0x80) << 8; - wave->samples[sample_count] = sample; + short sample = (wave_data->byData[i] - 0x80) << 8; + wave->samples[i] = sample; } } else if (wave_info->WaveformatEx.nBlockAlign == 2) @@ -866,10 +862,10 @@ static HRESULT synth_download_wave(struct synth *This, DMUS_DOWNLOADINFO *info, } else if (wave_info->WaveformatEx.nBlockAlign == 4) { - while (sample_count--) + for (i = 0; i < sample_count; ++i) { - short sample = ((UINT *)wave_data->byData)[sample_count] >> 16; - wave->samples[sample_count] = sample; + short sample = ((UINT *)wave_data->byData)[i] >> 16; + wave->samples[i] = sample; } } @@ -882,8 +878,8 @@ static HRESULT synth_download_wave(struct synth *This, DMUS_DOWNLOADINFO *info, /* Although the doc says there should be 8-frame padding around the data, * FluidSynth doesn't actually require this since version 1.0.8. */ - fluid_sample_set_sound_data(wave->fluid_sample, samples, NULL, wave->sample_count, - wave->format.nSamplesPerSec, FALSE); + fluid_sample_set_sound_data(wave->fluid_sample, samples, NULL, sample_count, + wave_info->WaveformatEx.nSamplesPerSec, FALSE); EnterCriticalSection(&This->cs); list_add_tail(&This->waves, &wave->entry); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9373
On Fri Nov 7 04:47:00 2025 +0000, Anton Baskanov wrote:
changed this line in [version 4 of the diff](/wine/wine/-/merge_requests/9373/diffs?diff_id=221922&start_sha=2148498278b2d35937bf1f39e42f63e3620faf9b#898da1162f66a862545683e41dd74655e665af7c_842_844) Thanks for pointing out, the code is indeed simpler this way. Done.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/9373#note_121131
v4: - Keep the single allocation for `struct wave` and the samples. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9373#note_121130
This merge request was approved by Michael Stefaniuc. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9373
participants (3)
-
Anton Baskanov -
Anton Baskanov (@baskanov) -
Michael Stefaniuc (@mstefani)