Sign in to follow this  
Followers 0
mattfaust

sound level sampling

14 posts in this topic

I want to trigger an action when the output of my soundcard is above a certain level, is their a simple way to do this.

I dont care about the max setting set in the mixer, I need to detect when a certain threshold is passed when music is playing.

Share this post


Link to post
Share on other sites



#3 ·  Posted (edited)

This... and other great stuff is in "Autoit Wrappers" See Example Scripts Forum

;Get Wav Sound Volume
; Author gafrost

#include <GUIConstants.au3>

MsgBox(0,"", _SoundGetWaveVolume())

Func _SoundGetWaveVolume()
    Local $WaveVol = -1, $p, $ret
    Const $MMSYSERR_NOERROR = 0
    $p = DllStructCreate ("dword")
    If @error Then
        SetError(2)
        Return -2
    EndIf
    $ret = DllCall("winmm.dll", "long", "waveOutGetVolume", "long", -1, "long", DllStructGetPtr ($p))
    If ($ret[0] == $MMSYSERR_NOERROR) Then
        $WaveVol = Round(Dec(StringRight(Hex(DllStructGetData ($p, 1), 8), 4)) / 0xFFFF * 100)
    Else
        SetError(1)
    EndIf
    $Struct=0 
    Return $WaveVol
EndFunc;==>_SoundGetWaveVolume

Then,,, you can use... SoundSetWaveVolume() see help

8)

Edited by Valuater

NEWHeader1.png

Share this post


Link to post
Share on other sites

Thanks for the reply but Im looking for something different.

Rather than detecting what level the volume control is current set, I need to detect when actual sound reaches a certain level.

Basically like a eq would flash a bar only when a level is reached.

As far as the OS, I can use any that autoit supports plus some

Share this post


Link to post
Share on other sites

$Struct=0

Wheres $Struct?

Minesweeper

A minesweeper game created in autoit, source available.

_Mouse_UDF

An UDF for registering functions to mouse events, made in pure autoit.

2D Hitbox Editor

A 2D hitbox editor for quick creation of 2D sphere and rectangle hitboxes.

Share this post


Link to post
Share on other sites

The function _SoundGetWaveVolume() always returns 100 no matter where I have set the volume slider. I ran this on both Windows 7 x64 and Windows XP x86. I did while a media player was running and when it was paused. Maybe I don't understand the intention of the function?

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

in xp x86 go to control panel --> sound/audio devices --> select the audio tab --> hit volume under sound playback --> adjust the 'wave' slider to see an effect

Master Volume slider is not the same. All apologies if these were the steps being taken

Edited by iamtheky

,-. .--. ________ .-. .-. ,---. ,-. .-. .-. .-.
|(| / /\ \ |\ /| |__ __||| | | || .-' | |/ / \ \_/ )/
(_) / /__\ \ |(\ / | )| | | `-' | | `-. | | / __ \ (_)
| | | __ | (_)\/ | (_) | | .-. | | .-' | | \ |__| ) (
| | | | |)| | \ / | | | | | |)| | `--. | |) \ | |
`-' |_| (_) | |\/| | `-' /( (_)/( __.' |((_)-' /(_|
'-' '-' (__) (__) (_) (__)

Share this post


Link to post
Share on other sites

#8 ·  Posted (edited)

I think what mattfaust is after - is the live stream to the sound card.

Something on the order of "Direct Stream Capture" and then converting to numeric.

Only thing that comes close is something like this:

http://www.autoitscript.com/forum/index.php?showtopic=34625&view=findpost&p=256418

It only returns the input to the "Stereo Mix - one channel".

Run the OP code. Follow the thread and you'll come to a conclusion.

Perhaps it will help you - maybe not.

On another note - It's amazing how Windows will return TONS of information about the network,

but hardly anything on audio, with the exception of mixer controls - which is useless in your case.

Edited by ripdad

"The mediocre teacher tells. The Good teacher explains. The superior teacher demonstrates. The great teacher inspires." -William Arthur Ward

Share this post


Link to post
Share on other sites

Maybe you can use the Bass UDF to get the samples?

Share this post


Link to post
Share on other sites

Maybe you can use the Bass UDF to get the samples?

Actually, I have made a bit of progess - using the BASS UDF.

let me explain what Im doing, perhaps someone will have a better way to go about it.

I am creating a "Avatar" for my home automation projects. Basically a computer will accept voice commands, then replay with text to speech output.

Where this lil script will come into play, I found these great little animated models that display a face, and accept key commands for controlling the facial features aswell as opening the mouth.

Here is a link to the models

So my though was to make a simple little script that will simulate a SHIFT keypress, when audio is played. That way I could run my TTS separate and the model would react to whatever the computer plays.

The BASS UDF has a example which I have hacked up but it roughly does what I need, I will post below.

What I still need to work on, I would like the script to see any audio that the computer plays - right now it must be played from the BASS dll.

TTS is gonna be tough because instead of just letting the TTS "talk", Im gonna have to save the TTS output to a wav - then play the wav with BASS.

If anyone has any other ideas, I welcome any help!

#include <Bass.au3>
#include <BassConstants.au3>
#include <GUIConstantsEx.au3>
Global $playing_state = -1
;Open Bass.DLL.  Required for all function calls.
_BASS_STARTUP ("BASS.dll")

;Initalize bass.  Required for most functions.
_BASS_Init (0, -1, 44100, 0, "")

;Check if bass iniated.  If not, we cannot continue.
If @error Then
    MsgBox(0, "Error", "Could not initialize audio")
    Exit
EndIf

;Prompt the user to select a MP3 file
;$file = FileOpenDialog("Open...", "", "MP3 Files (*.*)")
$file = ("testmusic.mp3")
;Create a stream from that file.
$MusicHandle = _BASS_StreamCreateFile (False, $file, 0, 0, 0)

;Check if we opened the file correctly.
If @error Then
    MsgBox(0, "Error", "Could not load audio file" & @CR & "Error = " & @error)
    Exit
EndIf

;Create GUI and controls
$Form1 = GUICreate("Example 2", 380, 190, 193, 115)
$lblFileName = GUICtrlCreateLabel($file, 8, 8, 379, 17)
$progress_slider = GUICtrlCreateSlider(8, 32, 374, 29)
GUICtrlSetLimit(-1, 100, 0)
$rightVol = GUICtrlCreateProgress(8, 88, 366, 17)
GUICtrlSetLimit(-1, 100, 0)
$LeftVol = GUICtrlCreateProgress(8, 136, 366, 17)
GUICtrlSetLimit(-1, 100, 0)
GUICtrlCreateLabel("Right Channel Volume Level", 8, 64, 150, 17)
GUICtrlCreateLabel("Left Channel Volume Level", 8, 112, 150, 17)
$Close = GUICtrlCreateButton("Close", 296, 160, 75, 25, 0)
$Play_pause = GUICtrlCreateButton("Play/Pause", 216, 160, 75, 25, 0)
$Stop = GUICtrlCreateButton("Stop", 136, 160, 75, 25, 0)
;Show GUI
GUISetState(@SW_SHOW)
run("mirror.exe")
;Get the length of the song in bytes.
$song_length = _BASS_ChannelGetLength ($MusicHandle, $BASS_POS_BYTE)

While 1
    ;Get Current playback position
    $current = _BASS_ChannelGetPosition ($MusicHandle, $BASS_POS_BYTE)
    ;Calculate the percentage
;   $percent = Round(($current / $song_length) * 100, 0)
    ;Set the slider to show percent
;   GUICtrlSetData($progress_slider, $percent)

    ;Get Right/Left Playback Levels
    $levels = _BASS_ChannelGetLevel ($MusicHandle)
    ;Get Right and calculate percentage
;   $rightChLvl = _LoWord ($levels)
;   $rightChLvlper = Round(($rightChLvl / 32768) * 100, 0)
    ;Get Left and calculate percentage
    $LeftChLvl = _HiWord ($levels)
    $leftChLvlper = Round(($LeftChLvl / 32768) * 100, 0)
    ;Set the levels on GUI.
;   GUICtrlSetData($rightVol, $rightChLvlper)
;   GUICtrlSetData($LeftVol, $leftChLvlper)
;if $leftChLvlper > 50 Then
;   Send("{RSHIFT down}")
;Else
;   Send("{RSHIFT up}")
;EndIf
if $leftChLvlper > 60 Then
    Send("{RSHIFT}")
EndIf
    ;Get GUI Message
    $nMsg = GUIGetMsg()
    Switch $nMsg
        ;If Close button or red x, then exit.  Alway remember to free resources
        Case $GUI_EVENT_CLOSE, $Close
            Exit
        Case $Play_pause
            ;Check if playing or paused, then take appropriate action
            Switch $playing_state
                Case 0; Song Paused, Resume.
                    ;Resume Song
                    _BASS_Pause ()
                    $playing_state = 1
                Case - 1 ; Song stopped, start from begining.
                    ;Play Song
                    _BASS_ChannelPlay ($MusicHandle, 1)
                    $playing_state = 1
                Case 1 ; Song Playing, Pause
                    ;Pause song
                    _BASS_Pause ()
                    $playing_state = 0
            EndSwitch
        Case $Stop
            ;Stop Song
            _BASS_ChannelStop ($MusicHandle)
            $playing_state = -1
    EndSwitch
WEnd

Func OnAutoItExit()
    ;Free Resources
    _BASS_Free()
EndFunc   ;=

Share this post


Link to post
Share on other sites

Look at the link ripdad posted.

Actually, I read that thread prior to posting this one, From what I saw they said it would be very difficult to implement and it kinda ended there.

Did I miss something?

Share this post


Link to post
Share on other sites

Need to add this to top of script to bring it up to date:

#include <WindowsConstants.au3>

#include <ProgressConstants.au3>

The data you're looking for is here ---> $mciError[2] in the While loop

At bottom of loop try ---> MsgBox(0, '', $mciError[2], 1)

Mind you ... this is "Record Input" not "Wave Out"

It gets the numeric input level to "Stereo Mix" -- so, you might have to

activate and/or adjust the recording mixer controls.


"The mediocre teacher tells. The Good teacher explains. The superior teacher demonstrates. The great teacher inspires." -William Arthur Ward

Share this post


Link to post
Share on other sites

#14 ·  Posted (edited)

I've managed to drastically reduce the code -- it's much easier to understand.

Local $ui = GUICreate('Level', 110, 160, -1, -1, Default, 0x00000008)
Local $ProgressBar = GUICtrlCreateProgress(50, 20, 10, 120, 0x04)
GUISetState(@SW_SHOW, $ui)
;
Local $mciLevel, $lpszReturnString
Local $mciInit = DllCall('winmm.dll', 'long', 'mciSendStringA', 'str', 'open new type waveaudio alias mywave', 'str', $lpszReturnString, 'long', 64, 'long', 0)
If $mciInit[0] <> 0 Then Exit
;
Do
    $mciLevel = DllCall('winmm.dll', 'long', 'mciSendStringA', 'str', 'status mywave level', 'str', $lpszReturnString, 'long', 64, 'long', 0)
    If $mciLevel[0] <> 0 Then Exit
    ; If $mciLevel[2] > 60 Then MsgBox(64, 'Levels', 'Peaked > 60')
    GUICtrlSetData($ProgressBar, $mciLevel[2]); <-- here is the numeric audio level
Until GUIGetMsg() = -3
;
GUIDelete($ui)
Exit
Edited by ripdad

"The mediocre teacher tells. The Good teacher explains. The superior teacher demonstrates. The great teacher inspires." -William Arthur Ward

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0