diff --git a/src/ds-api.c b/src/ds-api.c index a45d6d7..9f9d14a 100644 --- a/src/ds-api.c +++ b/src/ds-api.c @@ -431,9 +431,9 @@ static IDirectSound8Vtbl ds_api_vtbl = { .VerifyCertification = ds_api_verify_certification, }; -/* DirectSound API entry point, exported as DirectSoundCreate8 */ +/* DirectSound8 API entry point, exported as DirectSoundCreate8 */ -HRESULT __stdcall ds_api_create( +HRESULT __stdcall ds_api_create8( const GUID *guid_device, IDirectSound8 **out, IUnknown *outer) @@ -479,3 +479,13 @@ HRESULT __stdcall ds_api_create( return hr; } + +/* DirectSound API entry point, exported as DirectSoundCreate */ + +HRESULT __stdcall ds_api_create( + const GUID *guid_device, + IDirectSound **out, + IUnknown *outer) +{ + return ds_api_create8(guid_device, (IDirectSound8 **) out, outer); +} diff --git a/src/ds-buffer.c b/src/ds-buffer.c index db29df8..d337a8a 100644 --- a/src/ds-buffer.c +++ b/src/ds-buffer.c @@ -40,6 +40,8 @@ struct ds_buffer { bool buf_owned; bool playing; bool looping; + LONG volume; + LONG pan; }; static bool ds_buffer_requires_conversion(const struct ds_buffer *self); @@ -465,9 +467,16 @@ static __stdcall HRESULT ds_buffer_get_pan( IDirectSoundBuffer *com, LONG *out) { - trace("%s(%p) [stub]", __func__, out); + struct ds_buffer *self; + + if (out == NULL) { + return E_POINTER; + } + + self = ds_buffer_downcast(com); + *out = self->pan; - return E_NOTIMPL; + return S_OK; } static __stdcall HRESULT ds_buffer_get_status( @@ -508,9 +517,16 @@ static __stdcall HRESULT ds_buffer_get_volume( IDirectSoundBuffer *com, LONG *out) { - trace("%s(%p)", __func__, out); + struct ds_buffer *self; + + if (out == NULL) { + return E_POINTER; + } + + self = ds_buffer_downcast(com); + *out = self->volume; - return E_NOTIMPL; + return S_OK; } static __stdcall HRESULT ds_buffer_initialize( @@ -635,12 +651,15 @@ static __stdcall HRESULT ds_buffer_play( if (r < 0) { return hr_from_errno(r); } - - self->playing = true; + self->looping = flags & DSBPLAY_LOOPING; - snd_command_play(cmd, self->stm, self->looping); - snd_client_cmd_submit(self->cli, cmd); + if (!self->playing) { + self->playing = true; + + snd_command_play(cmd, self->stm, self->looping); + snd_client_cmd_submit(self->cli, cmd); + } return S_OK; } @@ -690,13 +709,48 @@ static __stdcall HRESULT ds_buffer_set_frequency( return S_OK; } +static HRESULT ds_buffer_apply_volume(struct ds_buffer *self) +{ + struct snd_command *cmd; + int16_t left_vol; + int16_t right_vol; + LONG left_mb; + LONG right_mb; + int r; + + left_mb = self->volume - (self->pan > 0 ? self->pan : 0); + right_mb = self->volume + (self->pan < 0 ? self->pan : 0); + + left_vol = 256.0 * pow(10.0, left_mb / 2000.0); + right_vol = 256.0 * pow(10.0, right_mb / 2000.0); + + r = snd_client_cmd_alloc(self->cli, &cmd); + + if (r < 0) { + return hr_from_errno(r); + } + + snd_command_set_volume(cmd, self->stm, 0, left_vol); + snd_command_set_volume(cmd, self->stm, 1, right_vol); + snd_client_cmd_submit(self->cli, cmd); + + return S_OK; +} + static __stdcall HRESULT ds_buffer_set_pan( IDirectSoundBuffer *com, LONG pan) { - // stub + struct ds_buffer *self; - return S_OK; + if (pan < -10000 || pan > 10000) { + return E_INVALIDARG; + } + + self = ds_buffer_downcast(com); + self->pan = pan; + + return ds_buffer_apply_volume(self); } static __stdcall HRESULT ds_buffer_set_volume( @@ -704,9 +758,6 @@ static __stdcall HRESULT ds_buffer_set_volume( LONG millibels) { struct ds_buffer *self; - struct snd_command *cmd; - int16_t linear_vol; - int r; if (millibels < -10000 || millibels > 0) { trace("%s: Attenutation param out of range: %li", millibels); @@ -715,19 +766,9 @@ static __stdcall HRESULT ds_buffer_set_volume( } self = ds_buffer_downcast(com); - linear_vol = 256.0 * pow(10.0, millibels / 2000.0); - - r = snd_client_cmd_alloc(self->cli, &cmd); + self->volume = millibels; - if (r < 0) { - return hr_from_errno(r); - } - - snd_command_set_volume(cmd, self->stm, 0, linear_vol); - snd_command_set_volume(cmd, self->stm, 1, linear_vol); - snd_client_cmd_submit(self->cli, cmd); - - return S_OK; + return ds_buffer_apply_volume(self); } static __stdcall HRESULT ds_buffer_stop(IDirectSoundBuffer *com) diff --git a/src/dsound.def b/src/dsound.def index 4b928e2..98408e0 100644 --- a/src/dsound.def +++ b/src/dsound.def @@ -1,4 +1,5 @@ LIBRARY dsound EXPORTS - DirectSoundCreate8=ds_api_create@12 @11 + DirectSoundCreate=ds_api_create@12 @1 + DirectSoundCreate8=ds_api_create8@12 @11 diff --git a/src/snd-service.c b/src/snd-service.c index 409dfd7..3ff4cc9 100644 --- a/src/snd-service.c +++ b/src/snd-service.c @@ -132,7 +132,7 @@ void snd_command_set_volume( struct snd_command *cmd, struct snd_stream *stm, size_t channel_no, - uint8_t value) + uint16_t value) { assert(cmd != NULL); diff --git a/src/snd-service.h b/src/snd-service.h index 8ae9adf..4c85137 100644 --- a/src/snd-service.h +++ b/src/snd-service.h @@ -23,7 +23,7 @@ void snd_command_set_volume( struct snd_command *cmd, struct snd_stream *stm, size_t channel_no, - uint8_t value); + uint16_t value); void snd_command_set_callback( struct snd_command *cmd, snd_callback_t callback, diff --git a/src/snd-stream.c b/src/snd-stream.c index 4e74cc2..f3a0906 100644 --- a/src/snd-stream.c +++ b/src/snd-stream.c @@ -109,11 +109,13 @@ bool snd_stream_render( pos = pos_end; + if (pos >= buf_nsamples && stm->looping) { + pos = 0; + } + if (dest_nsamples == 0 || !stm->looping) { break; } - - pos = 0; } atomic_store(&stm->pos, pos);