From 689dbaab722e9f483f2d9ae01ca3d0439828440f Mon Sep 17 00:00:00 2001 From: Diego Szychowski Date: Sat, 31 Aug 2024 09:10:04 -0300 Subject: [PATCH] feat: Add support for initializing audio client with extended format Based on the PR: https://github.com/moutend/go-wca/pull/20 --- pkg/wca/IAudioClient.go | 10 +++++++ pkg/wca/IAudioClient_func.go | 8 ++++++ pkg/wca/IAudioClient_windows.go | 36 +++++++++++++++++++++++-- pkg/wca/WAVEFORMATEX.go | 47 +++++++++++++++++++++++++++++++++ 4 files changed, 99 insertions(+), 2 deletions(-) diff --git a/pkg/wca/IAudioClient.go b/pkg/wca/IAudioClient.go index d4e2a57..797480b 100644 --- a/pkg/wca/IAudioClient.go +++ b/pkg/wca/IAudioClient.go @@ -35,6 +35,11 @@ func (v *IAudioClient) Initialize(shareMode, streamFlags uint32, nsBufferDuratio return } +func (v *IAudioClient) InitializeWithFormatEx(shareMode, streamFlags uint32, nsBufferDuration, nsPeriodicity REFERENCE_TIME, format *WAVEFORMATEXTENSIBLE, audioSessionGUID *ole.GUID) (err error) { + err = acInitializeEx(v, shareMode, streamFlags, nsBufferDuration, nsPeriodicity, format, audioSessionGUID) + return +} + func (v *IAudioClient) GetBufferSize(bufferFrameSize *uint32) (err error) { err = acGetBufferSize(v, bufferFrameSize) return @@ -59,6 +64,11 @@ func (v *IAudioClient) GetMixFormat(wfx **WAVEFORMATEX) (err error) { return } +func (v *IAudioClient) GetMixFormatEx(wfe **WAVEFORMATEXTENSIBLE) (err error) { + err = acGetMixFormatEx(v, wfe) + return +} + func (v *IAudioClient) GetDevicePeriod(nsDefaultDevicePeriod, nsMinimumDevicePeriod *REFERENCE_TIME) (err error) { err = acGetDevicePeriod(v, nsDefaultDevicePeriod, nsMinimumDevicePeriod) return diff --git a/pkg/wca/IAudioClient_func.go b/pkg/wca/IAudioClient_func.go index 562444b..352b901 100644 --- a/pkg/wca/IAudioClient_func.go +++ b/pkg/wca/IAudioClient_func.go @@ -11,6 +11,10 @@ func acInitialize(ac *IAudioClient, shareMode, streamFlags uint32, nsBufferDurat return ole.NewError(ole.E_NOTIMPL) } +func acInitializeEx(ac *IAudioClient, shareMode, streamFlags uint32, nsBufferDuration, nsPeriodicity REFERENCE_TIME, format *WAVEFORMATEXTENSIBLE, audioSessionGUID *ole.GUID) (err error) { + return ole.NewError(ole.E_NOTIMPL) +} + func acGetBufferSize(ac *IAudioClient, bufferFrameSize *uint32) (err error) { return ole.NewError(ole.E_NOTIMPL) } @@ -31,6 +35,10 @@ func acGetMixFormat(ac *IAudioClient, wfx **WAVEFORMATEX) (err error) { return ole.NewError(ole.E_NOTIMPL) } +func acGetMixFormatEx(ac *IAudioClient, wfe **WAVEFORMATEXTENSIBLE) (err error) { + return ole.NewError(ole.E_NOTIMPL) +} + func acGetDevicePeriod(ac *IAudioClient, nsDefaultDevicePeriod, nsMinimumDevicePeriod *REFERENCE_TIME) (err error) { return ole.NewError(ole.E_NOTIMPL) } diff --git a/pkg/wca/IAudioClient_windows.go b/pkg/wca/IAudioClient_windows.go index e890843..e2bb0e7 100644 --- a/pkg/wca/IAudioClient_windows.go +++ b/pkg/wca/IAudioClient_windows.go @@ -12,7 +12,26 @@ import ( ) func acInitialize(ac *IAudioClient, shareMode, streamFlags uint32, nsBufferDuration, nsPeriodicity REFERENCE_TIME, format *WAVEFORMATEX, audioSessionGUID *ole.GUID) (err error) { - hr, _, _ := syscall.Syscall9( + hr, _, _ := syscall.SyscallN( + ac.VTable().Initialize, + 7, + uintptr(unsafe.Pointer(ac)), + uintptr(shareMode), + uintptr(streamFlags), + uintptr(nsBufferDuration), + uintptr(nsPeriodicity), + uintptr(unsafe.Pointer(format)), + uintptr(unsafe.Pointer(audioSessionGUID)), + 0, + 0) + if hr != 0 { + err = ole.NewError(hr) + } + return +} + +func acInitializeEx(ac *IAudioClient, shareMode, streamFlags uint32, nsBufferDuration, nsPeriodicity REFERENCE_TIME, format *WAVEFORMATEXTENSIBLE, audioSessionGUID *ole.GUID) (err error) { + hr, _, _ := syscall.SyscallN( ac.VTable().Initialize, 7, uintptr(unsafe.Pointer(ac)), @@ -86,7 +105,7 @@ func acIsFormatSupported(ac *IAudioClient, shareMode uint32, wfx *WAVEFORMATEX, } func acGetMixFormat(ac *IAudioClient, wfx **WAVEFORMATEX) (err error) { - hr, _, _ := syscall.Syscall( + hr, _, _ := syscall.SyscallN( ac.VTable().GetMixFormat, 2, uintptr(unsafe.Pointer(ac)), @@ -98,6 +117,19 @@ func acGetMixFormat(ac *IAudioClient, wfx **WAVEFORMATEX) (err error) { return } +func acGetMixFormatEx(ac *IAudioClient, wfe **WAVEFORMATEXTENSIBLE) (err error) { + hr, _, _ := syscall.SyscallN( + ac.VTable().GetMixFormat, + 2, + uintptr(unsafe.Pointer(ac)), + uintptr(unsafe.Pointer(wfe)), + 0) + if hr != 0 { + err = ole.NewError(hr) + } + return +} + func acGetDevicePeriod(ac *IAudioClient, nsDefaultDevicePeriod, nsMinimumDevicePeriod *REFERENCE_TIME) (err error) { hr, _, _ := syscall.Syscall( ac.VTable().GetDevicePeriod, diff --git a/pkg/wca/WAVEFORMATEX.go b/pkg/wca/WAVEFORMATEX.go index 3b7652b..161be04 100644 --- a/pkg/wca/WAVEFORMATEX.go +++ b/pkg/wca/WAVEFORMATEX.go @@ -1,5 +1,9 @@ package wca +import "github.com/go-ole/go-ole" + +// WAVEFORMATEX structure defines the format of waveform-audio data +// https://learn.microsoft.com/en-us/windows/win32/api/mmreg/ns-mmreg-waveformatex type WAVEFORMATEX struct { WFormatTag uint16 NChannels uint16 @@ -9,3 +13,46 @@ type WAVEFORMATEX struct { WBitsPerSample uint16 CbSize uint16 } + +// WAVEFORMATEXTENSIBLE structure extends WAVEFORMATEX +// See: https://learn.microsoft.com/en-us/windows/win32/api/mmreg/ns-mmreg-waveformatextensible +type WAVEFORMATEXTENSIBLE struct { + Format WAVEFORMATEX + Samples uint16 // union { ValidBitsPerSample or SamplesPerBlock or Reserved } + DwChannelMask uint32 + SubFormat ole.GUID +} + +var ( + // KSDATAFORMAT_SUBTYPE_PCM PCM Audio Data Format + KSDATAFORMAT_SUBTYPE_PCM = &ole.GUID{ + Data1: 0x00000001, + Data2: 0x0000, + Data3: 0x0010, + Data4: [8]byte{0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}, + } + + // KSDATAFORMAT_SUBTYPE_IEEE_FLOAT IEEE Float Audio Data Format + KSDATAFORMAT_SUBTYPE_IEEE_FLOAT = &ole.GUID{ + Data1: 0x00000003, + Data2: 0x0000, + Data3: 0x0010, + Data4: [8]byte{0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}, + } + + // KSDATAFORMAT_SUBTYPE_ALAW ALAW Audio Data Format + KSDATAFORMAT_SUBTYPE_ALAW = &ole.GUID{ + Data1: 0x00000006, + Data2: 0x0000, + Data3: 0x0010, + Data4: [8]byte{0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}, + } + + // KSDATAFORMAT_SUBTYPE_MULAW MULAW Audio Data Format + KSDATAFORMAT_SUBTYPE_MULAW = &ole.GUID{ + Data1: 0x00000007, + Data2: 0x0000, + Data3: 0x0010, + Data4: [8]byte{0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}, + } +)