AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Vista Audio Control Functions v2.1
Goto page Previous  1, 2, 3, 4, 5, 6, 7, 8, 9, 10  Next
 
Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
maximo3491



Joined: 10 Feb 2007
Posts: 92

PostPosted: Wed Mar 03, 2010 8:32 pm    Post subject: Reply with quote

I'm trying to get the active levels of my microphone, however, there seems to be something wrong with VA_IAudioMeterInformation_GetPeakValue(audioMeter, peakValue) as it always returns null

Here is my code

Code:
#SingleInstance, Force
MeterLength = 30
COM_Init()

device := VA_GetDevice("Microphone Array")
audioMeter := VA_GetAudioMeter(device)

VA_IAudioMeterInformation_GetMeteringChannelCount(audioMeter, channelCount)

; "The peak value for each channel is recorded over one device
;  period and made available during the subsequent device period."
VA_GetDevicePeriod("playback", devicePeriod)

Loop
{
    ; Get the peak value across all channels.
    VA_IAudioMeterInformation_GetPeakValue(audioMeter, peakValue)   
   meter := MakeMeter(peakValue, MeterLength)
   
    ; Get the peak values of all channels.
    VarSetCapacity(peakValues, channelCount*4)
    VA_IAudioMeterInformation_GetChannelsPeakValues(audioMeter, channelCount, &peakValues)
   Loop %channelCount%
        meter .= "`n" MakeMeter(NumGet(peakValues, A_Index*4-4, "float"), MeterLength)

    ToolTip, %meter%
    Sleep, %devicePeriod%
}

MakeMeter(fraction, size)
{
    global MeterLength
   Loop % fraction*size
        meter .= "|"
    Loop % (1-fraction)*size
        meter .= "."
    meter .= "  " fraction
    return meter
}


I have the right device selected as VA_GetDeviceName returns the name of my recording microphone.

Any ideas?
Back to top
View user's profile Send private message
Lexikos



Joined: 17 Oct 2006
Posts: 7299
Location: Australia

PostPosted: Thu Mar 04, 2010 12:57 pm    Post subject: Reply with quote

VA_GetAudioMeter expects a device_desc, the same as VA_GetDevice's first parameter. When you pass it a pointer value, it is misinterpreted as a numeric index. In retrospect, a pointer value is extremely unlikely to ever be in the range of a valid index, so VA_GetDevice (which is used internally by functions such as VA_GetAudioMeter) could simply return the value it is given as-is. However, in this case you have no need for the device pointer anyway.

Instead pass the device name directly to VA_GetAudioMeter, or pass "capture" to use your default recording device.

Also, the "playback" in VA_GetDevicePeriod("playback",...) should be changed to whatever device_desc is passed to VA_GetAudioMeter.


Edit: I've updated VA.zip so that VA_GetDevice(device_pointer) will return device_pointer. I also fixed a "pointer leak" in VA_GetAudioMeter.
Back to top
View user's profile Send private message Visit poster's website
maximo3491



Joined: 10 Feb 2007
Posts: 92

PostPosted: Thu Mar 04, 2010 4:51 pm    Post subject: Reply with quote

Ahh, that works perfectly. Thank you Very Happy
Back to top
View user's profile Send private message
maximo3491



Joined: 10 Feb 2007
Posts: 92

PostPosted: Thu Mar 04, 2010 8:33 pm    Post subject: Reply with quote

Sorry for the double post, but I noticed something odd. The levels are only displayed if another program starts up the capture drivers. For example, if I load up Audacity and hit record, or open up recording devices (which has a meter next to ever device) only then does this script show the meters.

If I close out all programs that, upon exit, disable the record drivers, the meters for this script go back down to 0.

I'm no expert at calling the proper drivers so how exactly do I load up my main capture device driver?
Back to top
View user's profile Send private message
Lexikos



Joined: 17 Oct 2006
Posts: 7299
Location: Australia

PostPosted: Fri Mar 05, 2010 2:31 pm    Post subject: Reply with quote

I wrote:
The peak meter only reports meaningful values when something is actually capturing audio. I'm not sure how it is done, and haven't spent the necessary time to find out as I don't have a need to detect sound input.
Source: Microphone Peak Value - Vista Audio (Lexikos)
Sorry.
Back to top
View user's profile Send private message Visit poster's website
maximo3491



Joined: 10 Feb 2007
Posts: 92

PostPosted: Fri Mar 05, 2010 6:49 pm    Post subject: Reply with quote

Ahh gotcha Lexikos, didn't really read that. Thanks for the script nontheless. Works like a charm for output devices. I'll try to find a way to load the input device and will post my solution when (and if) I find it.
Back to top
View user's profile Send private message
rokky



Joined: 13 Mar 2010
Posts: 2

PostPosted: Sat Mar 13, 2010 7:58 am    Post subject: Reply with quote

Hi,
First of all thanks for the script, it makes the move to windows 7 seem a bit less painful. :p

I'm having a small problem though. I use hotkeys to control the volume on line in coming from my ps3. It works great except for when I lower the volume down to 0 and then press twice on the volume down key. The sound level goes up to 89 and it'll get ear shatteringly loud. The same thing doesn't happen if I try to increase the volume over 100, not that it'd matter much if it did. :>

Here's my code, hope you can help me.

Code:
COM_Init()

+Volume_Mute::
VA_SetMute(!VA_GetMute(4),4)
return

+Volume_Up::VA_SetVolume(VA_GetVolume(4) + 1, 4)

+Volume_Down::VA_SetVolume(VA_GetVolume(4) - 1, 4)
Back to top
View user's profile Send private message
Lexikos



Joined: 17 Oct 2006
Posts: 7299
Location: Australia

PostPosted: Sat Mar 13, 2010 1:22 pm    Post subject: Reply with quote

Thanks for the bug report. I've fixed a divide-by-zero error in VA_SetVolume which seemed to be the cause. Please download and try again.
Back to top
View user's profile Send private message Visit poster's website
rokky



Joined: 13 Mar 2010
Posts: 2

PostPosted: Sun Mar 14, 2010 2:28 am    Post subject: Reply with quote

Seems to work flawlessly now. Thanks for the quick response!
Back to top
View user's profile Send private message
duveit



Joined: 08 Dec 2009
Posts: 9

PostPosted: Tue May 11, 2010 12:57 pm    Post subject: Application specific sound control in windows 7 Reply with quote

Is it possible with application specific sound control in windows 7 with this script?

Lets say if you only want to mute the sound in a specific program, but let others stay the same volume.
Back to top
View user's profile Send private message
undin



Joined: 10 Jun 2010
Posts: 6

PostPosted: Thu Jun 10, 2010 9:13 pm    Post subject: Re: Er, problem solved Reply with quote

Dustin wrote:
Sorry, I'm pretty new to this stuff so I don't really understand much.

With that said, I think I've solved it.

I used this line
Code:

F11::VA_SetMasterMute(!VA_GetMasterMute("capture"), "capture")


This appears to just toggle mute the default input device, exactly what I need! If there's some way I can get it to mute just the mic instead of the default input device, that would be better. But really, this is just splitting hairs and I'm just overjoyed to actually have it working!

Much thanks!

i've used your finding as base for the following
Code:
COM_Init()




startup=1
while startup=1
{
mutestatus := VA_GetMasterMute("microphone")
if (mutestatus = 0)
{
menu, tray, icon, ON.ico,,1
}

else
{
menu, tray, icon, OFF.ico,,1
}
startup=0
}
return




YOURHOTKEY::
mutestatus := VA_GetMasterMute("microphone")
if (mutestatus = 1)
{
VA_SetMasterMute(0, "microphone")
menu, tray, icon, ON.ico,,1
CoordMode, ToolTip, Screen
Tooltip, ON, 0, 0
}

else
{
VA_SetMasterMute(1, "microphone")
menu, tray, icon, OFF.ico,,1
CoordMode, ToolTip, Screen
Tooltip, OFF, 0, 0
}

SetTimer, RemoveToolTip, 1500
Return




RemoveToolTip:
  SetTimer, RemoveToolTip, Off
  ToolTip
return

in addition to just toggling it always show the current mute status in the traybar with custom icons (even when just started)
and it shows the status as a tooltip when you toggle (handy at fullscreen games)





it would be nice if someone could help me with my own audio problem:
i need to find a way to change the windows 7 speaker setup (2.0 speakers, 5.1 speakers, etc) with a hotkey
but i have found nothing about how one could do it for hours

my old thread in the help forum:
http://www.autohotkey.com/forum/topic59091.html
Back to top
View user's profile Send private message
Ivan68



Joined: 15 Jun 2010
Posts: 13

PostPosted: Fri Jul 16, 2010 11:30 am    Post subject: Reply with quote

maximo3491 wrote:
I'm trying to get the active levels of my microphone, however, there seems to be something wrong with VA_IAudioMeterInformation_GetPeakValue(audioMeter, peakValue) as it always returns null

Here is my code

Code:
#SingleInstance, Force
MeterLength = 30
COM_Init()

device := VA_GetDevice("Microphone Array")
audioMeter := VA_GetAudioMeter(device)

VA_IAudioMeterInformation_GetMeteringChannelCount(audioMeter, channelCount)

; "The peak value for each channel is recorded over one device
;  period and made available during the subsequent device period."
VA_GetDevicePeriod("playback", devicePeriod)

Loop
{
    ; Get the peak value across all channels.
    VA_IAudioMeterInformation_GetPeakValue(audioMeter, peakValue)   
   meter := MakeMeter(peakValue, MeterLength)
   
    ; Get the peak values of all channels.
    VarSetCapacity(peakValues, channelCount*4)
    VA_IAudioMeterInformation_GetChannelsPeakValues(audioMeter, channelCount, &peakValues)
   Loop %channelCount%
        meter .= "`n" MakeMeter(NumGet(peakValues, A_Index*4-4, "float"), MeterLength)

    ToolTip, %meter%
    Sleep, %devicePeriod%
}

MakeMeter(fraction, size)
{
    global MeterLength
   Loop % fraction*size
        meter .= "|"
    Loop % (1-fraction)*size
        meter .= "."
    meter .= "  " fraction
    return meter
}


I have the right device selected as VA_GetDeviceName returns the name of my recording microphone.

Any ideas?


I would like to do something like that. So, what is the final code? How can I get microphone peak levels? TY

EDIT: I found the problem. "capure" device must be opened, in some way. If I run the code with "Recording Devices" window opened from volume icon, it works correctly. So, ho can I "open" the device?
Back to top
View user's profile Send private message
Lexikos



Joined: 17 Oct 2006
Posts: 7299
Location: Australia

PostPosted: Fri Jul 16, 2010 2:03 pm    Post subject: Reply with quote

From the device pointer (IMMDevice Interface), you need to create and initialize an audio client (IAudioClient Interface). It can be tricky to call the interface functions correctly, so I've written a complete example:
Code:
COM_Init()
; Get the device which we'll be monitoring.
device := VA_GetDevice("capture")

; Get IAudioClient interface.
VA_IMMDevice_Activate(device, IID_IAudioClient:="{1CB9AD4C-DBFA-4c32-B178-C2F568A703B2}", 7, 0, audioClient)
; Get mixer format to pass to Initialize.
VA_IAudioClient_GetMixFormat(audioClient, format)
; Initialize audio client to ensure peak meter is active.
VA_IAudioClient_Initialize(audioClient, 0, 0, 0, 0, format, 0)

; Get IAudioMeterInformation interface.
audioMeter := VA_GetAudioMeter(device)
; No longer needed, so free it:
COM_Release(device)

MeterLength = 30

; "The peak value for each channel is recorded over one device
;  period and made available during the subsequent device period."
VA_GetDevicePeriod("capture", devicePeriod)

Loop
{
    VA_IAudioMeterInformation_GetPeakValue(audioMeter, peakValue)   
   
    meter =
    ; Make the meter.
    Loop % peakValue*MeterLength
        meter .= "|"
    Loop % (1-peakValue)*MeterLength
        meter .= "."
    meter .= "  " peakValue

    ToolTip, %meter%
    Sleep, %devicePeriod%
}

/* To clean up:
COM_Release(audioMeter)
COM_Release(audioClient)
*/

;
; IAudioClient
;
VA_IAudioClient_Initialize(this, ShareMode, StreamFlags, BufferDuration, Periodicity, Format, AudioSessionGuid) {
    return DllCall(NumGet(NumGet(this+0)+12), "uint", this, "int", ShareMode, "uint", StreamFlags, "int64", BufferDuration, "int64", Periodicity, "uint", Format, "uint", SubStr(AudioSessionGuid,1,1)="{" ? COM_GUID4String(AudioSessionGuid,AudioSessionGuid) : AudioSessionGuid)
}
VA_IAudioClient_GetBufferSize(this, ByRef NumBufferFrames) {
    return DllCall(NumGet(NumGet(this+0)+16), "uint", this, "uint*", NumBufferFrames)
}
VA_IAudioClient_GetStreamLatency(this, ByRef Latency) {
    return DllCall(NumGet(NumGet(this+0)+20), "uint", this, "int64*", Latency)
}
VA_IAudioClient_GetCurrentPadding(this, ByRef NumPaddingFrames) {
    return DllCall(NumGet(NumGet(this+0)+24), "uint", this, "uint*", NumPaddingFrames)
}
VA_IAudioClient_IsFormatSupported(this, ShareMode, Format, ByRef ClosestMatch) {
    return DllCall(NumGet(NumGet(this+0)+28), "uint", this, "int", ShareMode, "uint", Format, "uint*", ClosestMatch)
}
VA_IAudioClient_GetMixFormat(this, ByRef Format) {
    return DllCall(NumGet(NumGet(this+0)+32), "uint", this, "uint*", Format)
}
VA_IAudioClient_GetDevicePeriod(this, ByRef DefaultDevicePeriod, ByRef MinimumDevicePeriod) {
    return DllCall(NumGet(NumGet(this+0)+36), "uint", this, "int64*", DefaultDevicePeriod, "int64*", MinimumDevicePeriod)
}
VA_IAudioClient_Start(this) {
    return DllCall(NumGet(NumGet(this+0)+40), "uint", this)
}
VA_IAudioClient_Stop(this) {
    return DllCall(NumGet(NumGet(this+0)+44), "uint", this)
}
VA_IAudioClient_Reset(this) {
    return DllCall(NumGet(NumGet(this+0)+48), "uint", this)
}
VA_IAudioClient_SetEventHandle(this, eventHandle) {
    return DllCall(NumGet(NumGet(this+0)+52), "uint", this, "uint", eventHandle)
}
VA_IAudioClient_GetService(this, iid, ByRef Service) {
    return DllCall(NumGet(NumGet(this+0)+56), "uint", this, "uint", COM_GUID4String(iid,iid), "uint*", Service)
}

I had attempted this previously but had overlooked IAudioClient::GetMixFormat, which is needed to get the stream format to pass to IAudioClient::Initialize.
Back to top
View user's profile Send private message Visit poster's website
element



Joined: 02 Apr 2010
Posts: 24

PostPosted: Sat Jul 17, 2010 1:32 am    Post subject: Per app volume level? Reply with quote

Can this library be used to set app-specific volume levels visible in the Win7 audio mixer? My mp3/TV/video players produce uneven audio levels. When a particular player starts, I'd like to set the relevant application volume to, say, 50% of current master volume. I can do this manually in the mixer and it works. However, every now and then I may inadvertently hit an app-specific volume hotkey, and the app will reset its volume level to 100%. Then I have to adjust the level manually again. I want to automate this.
Back to top
View user's profile Send private message
Lexikos



Joined: 17 Oct 2006
Posts: 7299
Location: Australia

PostPosted: Sat Jul 17, 2010 7:59 am    Post subject: Re: Per app volume level? Reply with quote

element wrote:
Can this library be used to set app-specific volume levels visible in the Win7 audio mixer?
No.

After spending several hours researching it, wrapping various COM interfaces and experimenting I'm able to enumerate audio sessions and determine which app owns them, but not control their volume. Basically, I got to the same point as this guy before realising it was impossible.
Anton Hansson wrote:
According to Larry Osterman
"There is no publicly documented mechanism for doing what you're trying to do."

Source: Controlling the volume of other applications - Stack Overflow
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   
Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Goto page Previous  1, 2, 3, 4, 5, 6, 7, 8, 9, 10  Next
Page 7 of 10

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group