Enter you process ID here:
Code: Select all
CreateThread(@main(), 27336) ; change process ID to match a process that outputs audio.
As usual, enjoy

Code: Select all
EnableExplicit
;- AUDIOCLIENT_ACTIVATION_TYPE
Enumeration
#AUDIOCLIENT_ACTIVATION_TYPE_DEFAULT
#AUDIOCLIENT_ACTIVATION_TYPE_PROCESS_LOOPBACK
EndEnumeration
;- PROCESS_LOOPBACK_MODE
Enumeration
#PROCESS_LOOPBACK_MODE_INCLUDE_TARGET_PROCESS_TREE
#PROCESS_LOOPBACK_MODE_EXCLUDE_TARGET_PROCESS_TREE
EndEnumeration
#CLSCTX_ALL = #CLSCTX_INPROC_SERVER | #CLSCTX_INPROC_HANDLER | #CLSCTX_LOCAL_SERVER | #CLSCTX_REMOTE_SERVER
#AUDCLNT_SHAREMODE_EXCLUSIVE = 1
#AUDCLNT_STREAMFLAGS_EVENTCALLBACK = $00040000
#AUDCLNT_STREAMFLAGS_LOOPBACK = $00020000
Interface IAudioClient Extends IUnknown
Initialize(ShareMode.l, StreamFlags.l, hnsBufferDuration.q, hnsPeriodicity.q, *pFormat, *pSessionGuid)
GetBufferSize(*pNumBufferFrames)
GetStreamLatency(*phnsLatency)
GetCurrentPadding(*pNumPaddingFrames)
IsFormatSupported(ShareMode.l, *pFormat, *ppClosestMatch)
GetMixFormat(*ppDeviceFormat)
GetDevicePeriod(*phnsDefaultDevicePeriod, *phnsMinimumDevicePeriod)
Start()
Stop()
Reset()
SetEventHandle(*EventHandle)
GetService(*riid, *ppv)
EndInterface
Interface IAudioCaptureClient Extends IUnknown
GetBuffer(*ppData, *pNumFramesToRead, *pdwFlags, *pu64DevicePosition, *pu64QPCPosition)
ReleaseBuffer(NumFramesRead.l)
GetNextPacketSize(*pNumFramesInNextPacket)
EndInterface
Interface IActivateAudioInterfaceAsyncOperation Extends IUnknown
GetActivateResult(activateResult.i, activatedInterface.i)
EndInterface
Structure BLOB Align #PB_Structure_AlignC
cbSize.l
pBlobData.i
EndStructure
Structure PROPVARIANT Align #PB_Structure_AlignC
vt.w
wReserved1.w
wReserved2.w
wReserved3.w
blob.BLOB
EndStructure
Structure AUDIOCLIENT_PROCESS_LOOPBACK_PARAMS Align #PB_Structure_AlignC
TargetProcessId.l
ProcessLoopbackMode.l
EndStructure
Structure AUDIOCLIENT_ACTIVATION_PARAMS Align #PB_Structure_AlignC
ActivationType.l
ProcessLoopbackParams.AUDIOCLIENT_PROCESS_LOOPBACK_PARAMS
EndStructure
Structure IUnknownVtbl
QueryInterface.i
AddRef.i
Release.i
EndStructure
Structure ActivateCompletionHandlerVtbl Extends IUnknownVtbl
ActivateCompleted.i
EndStructure
Global.ActivateCompletionHandlerVtbl g_ActivateCompletionHandlerVtbl
Structure ActivateCompletionHandlerObj
*vt.ActivateCompletionHandlerVtbl
refCount.i
EndStructure
Procedure.i ACH_Free(*this.ActivateCompletionHandlerObj)
Debug #PB_Compiler_Procedure
FreeMemory(*this)
EndProcedure
Procedure.l ACH_QueryInterface(*this.ActivateCompletionHandlerObj, *iid.IID, *Obj.Integer)
*Obj\i = *this
*this\refCount + 1
ProcedureReturn #S_OK
EndProcedure
Procedure.l ACH_AddRef(*this.ActivateCompletionHandlerObj)
*this\refCount + 1
ProcedureReturn #S_OK
EndProcedure
Procedure.l ACH_Release(*this.ActivateCompletionHandlerObj)
Protected.l refCount
*this\refCount - 1
refCount = *this\refCount
If *this\refCount = 0
ACH_Free(*this)
EndIf
ProcedureReturn refCount
EndProcedure
#WAVE_FORMAT_IEEE_FLOAT = 3
Procedure SetWaveFormatPCM44100Stereo16(*wf.WAVEFORMATEX)
*wf\wFormatTag = #WAVE_FORMAT_IEEE_FLOAT
*wf\nChannels = 2
*wf\nSamplesPerSec = 44100
*wf\wBitsPerSample = 32
*wf\nBlockAlign = *wf\nChannels * (*wf\wBitsPerSample / 8)
*wf\nAvgBytesPerSec = *wf\nSamplesPerSec * *wf\nBlockAlign
*wf\cbSize = 0
EndProcedure
Procedure.l ACH_ActivateCompleted(*this.ActivateCompletionHandlerObj, activateOperation.IActivateAudioInterfaceAsyncOperation)
Protected.l result
Protected.IAudioClient activatedInterface
Protected.IAudioCaptureClient captureClient
Protected streamFlags.l = #AUDCLNT_STREAMFLAGS_EVENTCALLBACK | #AUDCLNT_STREAMFLAGS_LOOPBACK
Protected waveFmt, hr, bufferFrames
activateOperation\GetActivateResult(@result, @activatedInterface)
Debug #PB_Compiler_Procedure
If result = #S_OK
SetWaveFormatPCM44100Stereo16(@waveFmt)
hr = activatedInterface\Initialize(0, streamFlags, 50000, 0, @waveFmt, #Null)
If hr <> #S_OK
Debug "Initialize() failed hr=" + Hex(hr)
EndIf
Protected hEvent.i = CreateEvent_(#Null, 0, 0, #Null)
If hEvent = 0
Debug "CreateEvent_ failed"
EndIf
hr = activatedInterface\SetEventHandle(hEvent)
If hr <> #S_OK
Debug "SetEventHandle() failed hr=" + Hex(hr)
CloseHandle_(hEvent)
EndIf
hr = activatedInterface\GetService(?IID_IAudioCaptureClient, @captureClient)
If hr <> #S_OK
Debug "GetService(IAudioRenderClient) failed hr=" + Hex(hr)
CloseHandle_(hEvent)
EndIf
hr = activatedInterface\Start()
If hr <> #S_OK
Debug "IAudioClient\Start() failed hr=" + Hex(hr)
CloseHandle_(hEvent)
EndIf
Protected numPadding.l, numFramesAvailable.l, flags.l, pNumFramesInNextPacket.l, *Data
Repeat
Protected waitRes = WaitForSingleObject_(hEvent, 500)
If waitRes = #WAIT_OBJECT_0
hr = captureClient\GetBuffer(@*data, @numFramesAvailable, @flags, #Null, #Null)
;Debug numFramesAvailable
Debug PeekF(*Data)
captureClient\ReleaseBuffer(numFramesAvailable)
EndIf
ForEver
EndIf
ProcedureReturn #S_OK
EndProcedure
g_ActivateCompletionHandlerVtbl\QueryInterface = @ACH_QueryInterface()
g_ActivateCompletionHandlerVtbl\AddRef = @ACH_AddRef()
g_ActivateCompletionHandlerVtbl\Release = @ACH_Release()
g_ActivateCompletionHandlerVtbl\ActivateCompleted = @ACH_ActivateCompleted()
Procedure.i ACH_New()
Protected.ActivateCompletionHandlerObj *this
*this = AllocateMemory(SizeOf(ActivateCompletionHandlerObj))
*this\vt = @g_ActivateCompletionHandlerVtbl
*this\refCount = 1
ProcedureReturn *this
EndProcedure
Global ActivateAudioInterfaceAsync
Prototype.i ActivateAudioInterfaceAsync(deviceInterfacePath.s, *riid.IID, *activationParams.PROPVARIANT, completionHandler.i, activationOperation.i)
If OpenLibrary(0, "Mmdevapi.dll")
ActivateAudioInterfaceAsync.ActivateAudioInterfaceAsync = GetFunction(0, "ActivateAudioInterfaceAsync")
EndIf
Procedure main(processId)
Protected.IActivateAudioInterfaceAsyncOperation asyncOp
Protected.l hr
Protected.s VIRTUAL_AUDIO_DEVICE_PROCESS_LOOPBACK
Protected.AUDIOCLIENT_ACTIVATION_PARAMS audioclientActivationParams
Protected.PROPVARIANT activateParams
Protected.ActivateCompletionHandlerObj *ach
Protected.s deviceID
Protected.i is
hr = CoInitializeEx_(#Null, #COINIT_MULTITHREADED)
If hr <> #S_OK
Debug "CoInitialize_ failed, hr=" + Hex(hr)
End
EndIf
*ach = ACH_New()
audioclientActivationParams\ProcessLoopbackParams\ProcessLoopbackMode = #PROCESS_LOOPBACK_MODE_INCLUDE_TARGET_PROCESS_TREE
audioclientActivationParams\ProcessLoopbackParams\TargetProcessId = processId
audioclientActivationParams\ActivationType = #AUDIOCLIENT_ACTIVATION_TYPE_PROCESS_LOOPBACK
activateParams\vt = #VT_BLOB
activateParams\blob\cbSize = SizeOf(AUDIOCLIENT_ACTIVATION_PARAMS)
activateParams\blob\pBlobData = @audioclientActivationParams
hr = ActivateAudioInterfaceAsync("VAD\Process_Loopback", ?IID_IAudioClient, @activateParams, *ach, @asyncOp)
ACH_Release(*ach)
If asyncOp
asyncOp\Release()
EndIf
If hr <> #S_OK
Debug "ActivateAudioInterfaceAsync() failed hr=" + Hex(hr)
End
EndIf
EndProcedure
CreateThread(@main(), 27336) ; change process ID to match a process that outputs audio.
Repeat
Delay(1000)
; add exit code here
ForEver
DataSection
IID_IAudioClient:
Data.l $1CB9AD4C
Data.w $DBFA,$4c32
Data.b $B1, $78, $C2, $F5, $68, $A7, $03, $B2
EndDataSection
DataSection
IID_IAudioCaptureClient:
Data.l $C8ADBD64
Data.w $E71E,$48A0
Data.b $A4,$DE,$18,$5C,$39,$5C,$D3,$17
EndDataSection
CloseLibrary(0)