Skip to content

Commit

Permalink
feat: Add support for initializing audio client with extended format
Browse files Browse the repository at this point in the history
Based on the PR: moutend#20
  • Loading branch information
diegosz committed Aug 31, 2024
1 parent 3aee4f9 commit 689dbaa
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 2 deletions.
10 changes: 10 additions & 0 deletions pkg/wca/IAudioClient.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
8 changes: 8 additions & 0 deletions pkg/wca/IAudioClient_func.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand All @@ -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)
}
Expand Down
36 changes: 34 additions & 2 deletions pkg/wca/IAudioClient_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)),
Expand Down Expand Up @@ -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)),
Expand All @@ -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,
Expand Down
47 changes: 47 additions & 0 deletions pkg/wca/WAVEFORMATEX.go
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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},
}
)

0 comments on commit 689dbaa

Please sign in to comment.