; 应用示例代码
Loop {
  ToolTip % "声音判断:" IsAudioPlaying()
  Sleep 100
}

Esc::ExitApp

; https://www.autohotkey.com/boards/viewtopic.php?f=76&t=41872
IsAudioPlaying() {
  AudioLevel := 0.0
  VA_IAudioMeterInformation_GetPeakValue(VA_GetAudioMeter(), AudioLevel)
  return (Round(AudioLevel, 4) > 0)  ; 判断音量
}

;---------------------------------------------------------
;VA code credited to Lexikos, I merely cut it down to the minimum I needed.
VA_GetAudioMeter(device_desc="playback") {
  if ! device := VA_GetDevice(device_desc)
    return 0
  VA_IMMDevice_Activate(device, "{C02216F6-8C67-4B5B-9D00-D008E73E0064}", 7, 0, audioMeter)
  ObjRelease(device)
  return audioMeter
}

VA_GetDevice(device_desc="playback") {
  static CLSID_MMDeviceEnumerator := "{BCDE0395-E52F-467C-8E3D-C4579291692E}"
    , IID_IMMDeviceEnumerator := "{A95664D2-9614-4F35-A746-DE8DB63617E6}"
  if !(deviceEnumerator := ComObjCreate(CLSID_MMDeviceEnumerator, IID_IMMDeviceEnumerator))
    return 0
  
  device := 0
  
  if VA_IMMDeviceEnumerator_GetDevice(deviceEnumerator, device_desc, device) = 0
    goto VA_GetDevice_Return
  
  if device_desc is integer
  {
    m2 := device_desc
    if m2 >= 4096 ; Probably a device pointer, passed here indirectly via VA_GetAudioMeter or such.
    {
      ObjAddRef(device := m2)
      goto VA_GetDevice_Return
    }
  } else
    RegExMatch(device_desc, "(.*?)\s*(?::(\d+))?$", m)
  
  if m1 in playback,p
    m1 := "", flow := 0 ; eRender
  else if m1 in capture,c
    m1 := "", flow := 1 ; eCapture
  else if (m1 . m2) = ""  ; no name or number specified
    m1 := "", flow := 0 ; eRender (default)
  else
    flow := 2 ; eAll
  
  if (m1 . m2) = ""   ; no name or number (maybe "playback" or "capture")
  {
    VA_IMMDeviceEnumerator_GetDefaultAudioEndpoint(deviceEnumerator, flow, 0, device)
    goto VA_GetDevice_Return
  }

  VA_IMMDeviceEnumerator_EnumAudioEndpoints(deviceEnumerator, flow, 1, devices)
  
  if m1 =
  {
    VA_IMMDeviceCollection_Item(devices, m2-1, device)
    goto VA_GetDevice_Return
  }
  
  VA_IMMDeviceCollection_GetCount(devices, count)
  index := 0
  Loop % count
    if VA_IMMDeviceCollection_Item(devices, A_Index-1, device) = 0
      if InStr(VA_GetDeviceName(device), m1) && (m2 = "" || ++index = m2)
        goto VA_GetDevice_Return
      else
        ObjRelease(device), device:=0

VA_GetDevice_Return:
  ObjRelease(deviceEnumerator)
  if (devices)
    ObjRelease(devices)
  
  return device ; may be 0
}

VA_GetDeviceName(device) {
  static PKEY_Device_FriendlyName
  if !VarSetCapacity(PKEY_Device_FriendlyName)
    VarSetCapacity(PKEY_Device_FriendlyName, 20)
    ,VA_GUID(PKEY_Device_FriendlyName :="{A45C254E-DF1C-4EFD-8020-67D146A850E0}")
    ,NumPut(14, PKEY_Device_FriendlyName, 16)
  VarSetCapacity(prop, 16)
  VA_IMMDevice_OpenPropertyStore(device, 0, store)
  ; store->GetValue(.., [out] prop)
  DllCall(NumGet(NumGet(store+0)+5*A_PtrSize), "ptr", store, "ptr", &PKEY_Device_FriendlyName, "ptr", &prop)
  ObjRelease(store)
  VA_WStrOut(deviceName := NumGet(prop,8))
  return deviceName
}

VA_WStrOut(ByRef str) {
  str := StrGet(ptr := str, "UTF-16")
  DllCall("ole32\CoTaskMemFree", "ptr", ptr)  ; FREES THE STRING.
}

VA_GUID(ByRef guid_out, guid_in="%guid_out%") {
  if (guid_in == "%guid_out%")
    guid_in :=   guid_out
  if  guid_in is integer
    return guid_in
  VarSetCapacity(guid_out, 16, 0)
  DllCall("ole32\CLSIDFromString", "wstr", guid_in, "ptr", &guid_out)
  return &guid_out
}

VA_IMMDevice_OpenPropertyStore(this, Access, ByRef Properties) {
  return DllCall(NumGet(NumGet(this+0)+4*A_PtrSize), "ptr", this, "uint", Access, "ptr*", Properties)
}

VA_IMMDevice_Activate(this, iid, ClsCtx, ActivationParams, ByRef Interface) {
  return DllCall(NumGet(NumGet(this+0)+3*A_PtrSize), "ptr", this, "ptr", VA_GUID(iid), "uint", ClsCtx, "uint", ActivationParams, "ptr*", Interface)
}

VA_IMMDeviceEnumerator_GetDevice(this, id, ByRef Device) {
  return DllCall(NumGet(NumGet(this+0)+5*A_PtrSize), "ptr", this, "wstr", id, "ptr*", Device)
}

VA_IMMDeviceEnumerator_GetDefaultAudioEndpoint(this, DataFlow, Role, ByRef Endpoint) {
  return DllCall(NumGet(NumGet(this+0)+4*A_PtrSize), "ptr", this, "int", DataFlow, "int", Role, "ptr*", Endpoint)
}

VA_IMMDeviceEnumerator_EnumAudioEndpoints(this, DataFlow, StateMask, ByRef Devices) {
  return DllCall(NumGet(NumGet(this+0)+3*A_PtrSize), "ptr", this, "int", DataFlow, "uint", StateMask, "ptr*", Devices)
}

VA_IMMDeviceCollection_GetCount(this, ByRef Count) {
  return DllCall(NumGet(NumGet(this+0)+3*A_PtrSize), "ptr", this, "uint*", Count)
}

VA_IMMDeviceCollection_Item(this, Index, ByRef Device) {
  return DllCall(NumGet(NumGet(this+0)+4*A_PtrSize), "ptr", this, "uint", Index, "ptr*", Device)
}

VA_IAudioMeterInformation_GetPeakValue(this, ByRef Peak) {
  return DllCall(NumGet(NumGet(this+0)+3*A_PtrSize), "ptr", this, "float*", Peak)
}

 

声明:站内资源为整理优化好的代码上传分享与学习研究,如果是开源代码基本都会标明出处,方便大家扩展学习路径。请不要恶意搬运,破坏站长辛苦整理维护的劳动成果。本站为爱好者分享站点,所有内容不作为商业行为。如若本站上传内容侵犯了原著者的合法权益,请联系我们进行删除下架。