 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
maximo3491
Joined: 10 Feb 2007 Posts: 92
|
Posted: Wed Mar 03, 2010 8:32 pm Post subject: |
|
|
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 |
|
 |
Lexikos
Joined: 17 Oct 2006 Posts: 7299 Location: Australia
|
Posted: Thu Mar 04, 2010 12:57 pm Post subject: |
|
|
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 |
|
 |
maximo3491
Joined: 10 Feb 2007 Posts: 92
|
Posted: Thu Mar 04, 2010 4:51 pm Post subject: |
|
|
Ahh, that works perfectly. Thank you  |
|
| Back to top |
|
 |
maximo3491
Joined: 10 Feb 2007 Posts: 92
|
Posted: Thu Mar 04, 2010 8:33 pm Post subject: |
|
|
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 |
|
 |
Lexikos
Joined: 17 Oct 2006 Posts: 7299 Location: Australia
|
Posted: Fri Mar 05, 2010 2:31 pm Post subject: |
|
|
| 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 |
|
 |
maximo3491
Joined: 10 Feb 2007 Posts: 92
|
Posted: Fri Mar 05, 2010 6:49 pm Post subject: |
|
|
| 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 |
|
 |
rokky
Joined: 13 Mar 2010 Posts: 2
|
Posted: Sat Mar 13, 2010 7:58 am Post subject: |
|
|
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 |
|
 |
Lexikos
Joined: 17 Oct 2006 Posts: 7299 Location: Australia
|
Posted: Sat Mar 13, 2010 1:22 pm Post subject: |
|
|
| 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 |
|
 |
rokky
Joined: 13 Mar 2010 Posts: 2
|
Posted: Sun Mar 14, 2010 2:28 am Post subject: |
|
|
| Seems to work flawlessly now. Thanks for the quick response! |
|
| Back to top |
|
 |
duveit
Joined: 08 Dec 2009 Posts: 9
|
Posted: Tue May 11, 2010 12:57 pm Post subject: Application specific sound control in windows 7 |
|
|
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 |
|
 |
undin
Joined: 10 Jun 2010 Posts: 6
|
Posted: Thu Jun 10, 2010 9:13 pm Post subject: Re: Er, problem solved |
|
|
| 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 |
|
 |
Ivan68
Joined: 15 Jun 2010 Posts: 13
|
Posted: Fri Jul 16, 2010 11:30 am Post subject: |
|
|
| 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 |
|
 |
Lexikos
Joined: 17 Oct 2006 Posts: 7299 Location: Australia
|
Posted: Fri Jul 16, 2010 2:03 pm Post subject: |
|
|
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 |
|
 |
element
Joined: 02 Apr 2010 Posts: 24
|
Posted: Sat Jul 17, 2010 1:32 am Post subject: Per app volume level? |
|
|
| 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 |
|
 |
Lexikos
Joined: 17 Oct 2006 Posts: 7299 Location: Australia
|
Posted: Sat Jul 17, 2010 7:59 am Post subject: Re: Per app volume level? |
|
|
| 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.
|
|
| Back to top |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|