将声音输出到音频设备

时间:2017-04-05 08:00:11

标签: windows batch-file audio autohotkey

我正在尝试创建一个脚本,当按下热键时会触发声音效果,这可能看起来不太难,但我也希望能够将它输出到特定的音频设备,虚拟音频线在我的情况下。

我在互联网上看了一下,我看到了许多可能的解决方案,但没有一个解决方案(还)。看来AHK中的普通SoundPlay功能无法输出到特定的音频设备,但我也在寻找其他选项,比如通过wmplayer或其他媒体播放器的批处理脚本播放声音,但我找不到让我将声音输出到特定音频设备的解决方案...

所以我的问题是,对于特定的非默认音频设备(虚拟音频线)播放声音的最佳方法是什么?这可以在命令提示符内或在autohotkey内部完成?

编辑:我找到了解决方案,请参阅下面的答案。

3 个答案:

答案 0 :(得分:2)

所以我设法做了我想要完成的事情。我会告诉你我是怎么做到的:

在互联网上搜索一下后,我遇到了一个名为IrrKlang的C#库。使用IrrKlang我做了一个小控制台应用程序,我可以通过playsound soundfile.mp3 0调用,playound是.exe的名称,第一个参数是来自playsound.exe位置的声音文件的路径,以及最后一个参数是一个用于选择音频设备的数字,这个数字应该仍然可以猜测,但经过一些试验和错误后,你可以找到你的虚拟音频线或其他音频设备的数量。

对于将来来这里的人,我已将我的代码放在github上。

答案 1 :(得分:0)

您需要的一切都在这里:

Lexikos的Vista音频控制功能

注意:AutoHotkey v1.1.10及更高版本上的SoundSet和SoundGet本身支持Vista及更高版本。除非您想使用SoundSet / SoundGet不支持的高级功能,否则您不需要VA.ahk。

https://autohotkey.com/board/topic/21984-vista-audio-control-functions/

要更改默认输出设备,您可以在cpanel中编写声音属性脚本:

Run, mmsys.cpl
WinWait, Sound
    ControlSend, SysListView321,{Down num}  ' num matches device position
    Sleep, 100
    ControlClick, &Set Default
    Sleep, 100
    ControlClick, OK
WinWaitClose, Sound

H个,

答案 2 :(得分:0)

我修改了找到的一个代码,并增加了音量。 您必须输入device1和device2名称

  • Alt +向上滚轮=增大音量
  • Alt +降低音量=降低音量
  • Ctrl + F12 =机会设备

glhf!

device1:="Speakers / Headphones"
device2:="Communications Headphones"
; http://www.daveamenta.com/2011-05/programmatically-or-command-line-change-the-default-sound-playback-device-in-windows-7/
Devices := {}
IMMDeviceEnumerator := ComObjCreate("{BCDE0395-E52F-467C-8E3D-C4579291692E}", "{A95664D2-9614-4F35-A746-DE8DB63617E6}")

; IMMDeviceEnumerator::EnumAudioEndpoints
; eRender = 0, eCapture, eAll
; 0x1 = DEVICE_STATE_ACTIVE
DllCall(NumGet(NumGet(IMMDeviceEnumerator+0)+3*A_PtrSize), "UPtr", IMMDeviceEnumerator, "UInt", 0, "UInt", 0x1, "UPtrP", IMMDeviceCollection, "UInt")
ObjRelease(IMMDeviceEnumerator)

; IMMDeviceCollection::GetCount
DllCall(NumGet(NumGet(IMMDeviceCollection+0)+3*A_PtrSize), "UPtr", IMMDeviceCollection, "UIntP", Count, "UInt")
Loop % (Count)
{
    ; IMMDeviceCollection::Item
    DllCall(NumGet(NumGet(IMMDeviceCollection+0)+4*A_PtrSize), "UPtr", IMMDeviceCollection, "UInt", A_Index-1, "UPtrP", IMMDevice, "UInt")

    ; IMMDevice::GetId
    DllCall(NumGet(NumGet(IMMDevice+0)+5*A_PtrSize), "UPtr", IMMDevice, "UPtrP", pBuffer, "UInt")
    DeviceID := StrGet(pBuffer, "UTF-16"), DllCall("Ole32.dll\CoTaskMemFree", "UPtr", pBuffer)

    ; IMMDevice::OpenPropertyStore
    ; 0x0 = STGM_READ
    DllCall(NumGet(NumGet(IMMDevice+0)+4*A_PtrSize), "UPtr", IMMDevice, "UInt", 0x0, "UPtrP", IPropertyStore, "UInt")
    ObjRelease(IMMDevice)

    ; IPropertyStore::GetValue
    VarSetCapacity(PROPVARIANT, A_PtrSize == 4 ? 16 : 24)
    VarSetCapacity(PROPERTYKEY, 20)
    DllCall("Ole32.dll\CLSIDFromString", "Str", "{A45C254E-DF1C-4EFD-8020-67D146A850E0}", "UPtr", &PROPERTYKEY)
    NumPut(14, &PROPERTYKEY + 16, "UInt")
    DllCall(NumGet(NumGet(IPropertyStore+0)+5*A_PtrSize), "UPtr", IPropertyStore, "UPtr", &PROPERTYKEY, "UPtr", &PROPVARIANT, "UInt")
    DeviceName := StrGet(NumGet(&PROPVARIANT + 8), "UTF-16")    ; LPWSTR PROPVARIANT.pwszVal
    DllCall("Ole32.dll\CoTaskMemFree", "UPtr", NumGet(&PROPVARIANT + 8))    ; LPWSTR PROPVARIANT.pwszVal
    ObjRelease(IPropertyStore)

    ObjRawSet(Devices, DeviceName, DeviceID)
}
ObjRelease(IMMDeviceCollection)
Return

$!WheelUp::Send {Volume_Up 5}
$!WheelDown::Send {Volume_Down 5}
currentDevice:=false
^F12:: 
    currentDevice:=!currentDevice
    if currentDevice
        SetDefaultEndpoint( GetDeviceID(Devices, device1) )
    else
        SetDefaultEndpoint( GetDeviceID(Devices, device2) )
return

SetDefaultEndpoint(DeviceID)
{
    IPolicyConfig := ComObjCreate("{870af99c-171d-4f9e-af0d-e63df40c2bc9}", "{F8679F50-850A-41CF-9C72-430F290290C8}")
    DllCall(NumGet(NumGet(IPolicyConfig+0)+13*A_PtrSize), "UPtr", IPolicyConfig, "UPtr", &DeviceID, "UInt", 0, "UInt")
    ObjRelease(IPolicyConfig)
}

GetDeviceID(Devices, Name)
{
    For DeviceName, DeviceID in Devices
        If (InStr(DeviceName, Name))
            Return DeviceID
}