From: Anton Baskanov baskanov@gmail.com
--- dlls/dmsynth/synth.c | 56 ++++++++++++++++++++++++++++++++++++ dlls/dmsynth/tests/dmsynth.c | 18 ++++++------ 2 files changed, 65 insertions(+), 9 deletions(-)
diff --git a/dlls/dmsynth/synth.c b/dlls/dmsynth/synth.c index a1fb2cfa696..5f4b005f5e6 100644 --- a/dlls/dmsynth/synth.c +++ b/dlls/dmsynth/synth.c @@ -342,6 +342,8 @@ struct synth IKsControl IKsControl_iface; LONG ref;
+ LONG volume0; + LONG volume1; DMUS_PORTCAPS caps; DMUS_PORTPARAMS params; BOOL active; @@ -450,6 +452,12 @@ static ULONG WINAPI synth_Release(IDirectMusicSynth8 *iface) return ref; }
+static void update_channel_volume(struct synth *This, int chan) +{ + double attenuation = (This->volume0 + This->volume1) * -0.1; + fluid_synth_set_gen(This->fluid_synth, chan, GEN_ATTENUATION, attenuation); +} + static void synth_reset_default_values(struct synth *This) { BYTE chan; @@ -493,6 +501,8 @@ static void synth_reset_default_values(struct synth *This)
fluid_synth_cc(This->fluid_synth, chan | 0xb0 /* CONTROL_CHANGE */, 0x64 /* RPN_LSB */, 127); fluid_synth_cc(This->fluid_synth, chan | 0xb0 /* CONTROL_CHANGE */, 0x65 /* RPN_MSB */, 127); + + update_channel_volume(This, chan); } }
@@ -1107,10 +1117,13 @@ static HRESULT WINAPI synth_Render(IDirectMusicSynth8 *iface, short *buffer, { struct synth *This = impl_from_IDirectMusicSynth8(iface); struct event *event, *next; + int chan;
TRACE("(%p, %p, %ld, %I64d)\n", This, buffer, length, position);
EnterCriticalSection(&This->cs); + for (chan = 0; chan < 0x10; chan++) + update_channel_volume(This, chan); LIST_FOR_EACH_ENTRY_SAFE(event, next, &This->events, struct event, entry) { BYTE status = event->midi[0] & 0xf0, chan = event->midi[0] & 0x0f; @@ -1331,10 +1344,44 @@ static ULONG WINAPI synth_control_Release(IKsControl* iface) static HRESULT WINAPI synth_control_KsProperty(IKsControl* iface, PKSPROPERTY Property, ULONG PropertyLength, LPVOID PropertyData, ULONG DataLength, ULONG* BytesReturned) { + struct synth *This = impl_from_IKsControl(iface); + TRACE("(%p, %p, %lu, %p, %lu, %p)\n", iface, Property, PropertyLength, PropertyData, DataLength, BytesReturned);
TRACE("Property = %s - %lu - %lu\n", debugstr_guid(&Property->Set), Property->Id, Property->Flags);
+ if (Property->Flags == KSPROPERTY_TYPE_SET) + { + if (DataLength < sizeof(LONG)) + return E_NOT_SUFFICIENT_BUFFER; + + if (IsEqualGUID(&Property->Set, &GUID_DMUS_PROP_Volume)) + { + LONG volume = max(DMUS_VOLUME_MIN, min(DMUS_VOLUME_MAX, *(LONG*)PropertyData)); + + if (Property->Id == 0) + { + EnterCriticalSection(&This->cs); + This->volume0 = volume; + LeaveCriticalSection(&This->cs); + } + else if (Property->Id == 1) + { + EnterCriticalSection(&This->cs); + This->volume1 = volume; + LeaveCriticalSection(&This->cs); + } + else + return DMUS_E_UNKNOWN_PROPERTY; + } + else + { + FIXME("Unknown property %s\n", debugstr_guid(&Property->Set)); + } + + return S_OK; + } + if (Property->Flags != KSPROPERTY_TYPE_GET) { FIXME("Property flags %lu not yet supported\n", Property->Flags); @@ -1369,6 +1416,12 @@ static HRESULT WINAPI synth_control_KsProperty(IKsControl* iface, PKSPROPERTY Pr *(DWORD*)PropertyData = FALSE; *BytesReturned = sizeof(DWORD); } + else if (IsEqualGUID(&Property->Set, &GUID_DMUS_PROP_Volume)) + { + if (Property->Id >= 2) + return DMUS_E_UNKNOWN_PROPERTY; + return DMUS_E_GET_UNSUPPORTED; + } else { FIXME("Unknown property %s\n", debugstr_guid(&Property->Set)); @@ -1977,6 +2030,9 @@ HRESULT synth_create(IUnknown **ret_iface) obj->IKsControl_iface.lpVtbl = &synth_control_vtbl; obj->ref = 1;
+ obj->volume0 = 0; + obj->volume1 = 600; + obj->caps.dwSize = sizeof(DMUS_PORTCAPS); obj->caps.dwFlags = DMUS_PC_DLS | DMUS_PC_SOFTWARESYNTH | DMUS_PC_DIRECTSOUND | DMUS_PC_DLS2 | DMUS_PC_AUDIOPATH | DMUS_PC_WAVE; obj->caps.guidPort = CLSID_DirectMusicSynth; diff --git a/dlls/dmsynth/tests/dmsynth.c b/dlls/dmsynth/tests/dmsynth.c index 32e5c1d1e35..7662f26ec4b 100644 --- a/dlls/dmsynth/tests/dmsynth.c +++ b/dlls/dmsynth/tests/dmsynth.c @@ -1743,27 +1743,27 @@ static void test_IKsControl(void) property.Id = 0; property.Flags = KSPROPERTY_TYPE_GET; hr = IKsControl_KsProperty(control, &property, sizeof(property), &volume, sizeof(volume), &volume_size); - todo_wine ok(hr == DMUS_E_GET_UNSUPPORTED, "got hr %#lx.\n", hr); + ok(hr == DMUS_E_GET_UNSUPPORTED, "got hr %#lx.\n", hr);
property.Set = GUID_DMUS_PROP_Volume; property.Id = 1; property.Flags = KSPROPERTY_TYPE_GET; hr = IKsControl_KsProperty(control, &property, sizeof(property), &volume, sizeof(volume), &volume_size); - todo_wine ok(hr == DMUS_E_GET_UNSUPPORTED, "got hr %#lx.\n", hr); + ok(hr == DMUS_E_GET_UNSUPPORTED, "got hr %#lx.\n", hr);
/* out of range id results in DMUS_E_UNKNOWN_PROPERTY */ property.Set = GUID_DMUS_PROP_Volume; property.Id = 2; property.Flags = KSPROPERTY_TYPE_GET; hr = IKsControl_KsProperty(control, &property, sizeof(property), &volume, sizeof(volume), &volume_size); - todo_wine ok(hr == DMUS_E_UNKNOWN_PROPERTY, "got hr %#lx.\n", hr); + ok(hr == DMUS_E_UNKNOWN_PROPERTY, "got hr %#lx.\n", hr);
volume = 0; property.Set = GUID_DMUS_PROP_Volume; property.Id = 2; property.Flags = KSPROPERTY_TYPE_SET; hr = IKsControl_KsProperty(control, &property, sizeof(property), &volume, sizeof(volume), &volume_size); - todo_wine ok(hr == DMUS_E_UNKNOWN_PROPERTY, "got hr %#lx.\n", hr); + ok(hr == DMUS_E_UNKNOWN_PROPERTY, "got hr %#lx.\n", hr);
/* default value for volume 0 is 0 */ check_volume_envelope(synth, &default_instrument_download, &default_midi, &default_volume_envelope, TRUE); @@ -1773,7 +1773,7 @@ static void test_IKsControl(void) property.Id = 0; property.Flags = KSPROPERTY_TYPE_SET; hr = IKsControl_KsProperty(control, &property, sizeof(property), &volume, sizeof(volume), &volume_size); - todo_wine ok(hr == S_OK, "got hr %#lx.\n", hr); + ok(hr == S_OK, "got hr %#lx.\n", hr); check_volume_envelope(synth, &default_instrument_download, &default_midi, &default_volume_envelope, TRUE);
/* total voice gain is limited to 6 dB */ @@ -1782,7 +1782,7 @@ static void test_IKsControl(void) property.Id = 0; property.Flags = KSPROPERTY_TYPE_SET; hr = IKsControl_KsProperty(control, &property, sizeof(property), &volume, sizeof(volume), &volume_size); - todo_wine ok(hr == S_OK, "got hr %#lx.\n", hr); + ok(hr == S_OK, "got hr %#lx.\n", hr); envelope = default_volume_envelope; envelope.gain = 60.; envelope.channel_gain[0] = 0.; @@ -1795,7 +1795,7 @@ static void test_IKsControl(void) property.Id = 0; property.Flags = KSPROPERTY_TYPE_SET; hr = IKsControl_KsProperty(control, &property, sizeof(property), &volume, sizeof(volume), &volume_size); - todo_wine ok(hr == S_OK, "got hr %#lx.\n", hr); + ok(hr == S_OK, "got hr %#lx.\n", hr); envelope = default_volume_envelope; envelope.gain -= 60.; check_volume_envelope(synth, &default_instrument_download, &default_midi, &envelope, TRUE); @@ -1806,7 +1806,7 @@ static void test_IKsControl(void) property.Id = 1; property.Flags = KSPROPERTY_TYPE_SET; hr = IKsControl_KsProperty(control, &property, sizeof(property), &volume, sizeof(volume), &volume_size); - todo_wine ok(hr == S_OK, "got hr %#lx.\n", hr); + ok(hr == S_OK, "got hr %#lx.\n", hr); envelope = default_volume_envelope; envelope.gain -= 60.; check_volume_envelope(synth, &default_instrument_download, &default_midi, &envelope, TRUE); @@ -1817,7 +1817,7 @@ static void test_IKsControl(void) property.Id = 1; property.Flags = KSPROPERTY_TYPE_SET; hr = IKsControl_KsProperty(control, &property, sizeof(property), &volume, sizeof(volume), &volume_size); - todo_wine ok(hr == S_OK, "got hr %#lx.\n", hr); + ok(hr == S_OK, "got hr %#lx.\n", hr); envelope = default_volume_envelope; envelope.gain -= 120.; check_volume_envelope(synth, &default_instrument_download, &default_midi, &envelope, TRUE);