Jump to content

sound level sampling


Recommended Posts

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.

Link to comment
Share on other sites

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

Link to comment
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

Link to comment
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?

Link to comment
Share on other sites

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

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

Link to comment
Share on other sites

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

Link to comment
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   ;=
Link to comment
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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

  • 7 years later...

The code works very well and very elegant. However, I need to read the numeric value of the sound level. If I do a msbox showing $mciLevel[2], it is always 0, no matter what. Does anyone know why?

Link to comment
Share on other sites

The code I referred to is the one by Ripdad

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

Link to comment
Share on other sites

On 7/26/2018 at 4:04 PM, zeng said:

The code works very well and very elegant. However, I need to read the numeric value of the sound level. If I do a msbox showing $mciLevel[2], it is always 0, no matter what. Does anyone know why?

You say it's working well -- then it should provide the numeric value as well. Can you post your script, so we can see where it's failing on the msgbox?

---

Here is another script, fully exposing two channels, left and right...

Local $nLeft, $nRight, $mciLevel
Local $mciDll = DllOpen('winmm.dll')
If @error Then Exit
mciSendString('open new type waveaudio alias myStatus buffer 2')
If @error Then Exit
mciSendString('set myStatus bitspersample 8 channels 2 samplespersec 11025')
If @error Then Exit

Local $ui = GUICreate('Audio Levels', 160, 200, -1, -1, Default, 0x00000008)
GUICtrlCreateLabel('L', 52, 20, 34, 22)
GUICtrlCreateLabel('R', 82, 20, 34, 22)
Local $ProgressBarL = GUICtrlCreateProgress(50, 40, 14, 100, 0x04)
Local $ProgressBarR = GUICtrlCreateProgress(80, 40, 14, 100, 0x04)
Local $InputL = GUICtrlCreateLabel('', 50, 150, 34, 22)
Local $InputR = GUICtrlCreateLabel('', 80, 150, 34, 22)
GUISetState(@SW_SHOW, $ui)
GUISetOnEvent(-3, '_Exit')
Opt('GUIOnEventMode', 1)
;
While 1
    $mciLevel = mciSendString('status myStatus level')
    If @error Then _Exit()
    $nLeft = Round(_LoWord($mciLevel) / 128 * 100) - 1
    $nRight = Round(_HiWord($mciLevel) / 128 * 100) - 1
    GUICtrlSetData($ProgressBarL, $nLeft)
    GUICtrlSetData($ProgressBarR, $nRight)
    GUICtrlSetData($InputL, $nLeft); <-- Left numeric audio level
    GUICtrlSetData($InputR, $nRight); <-- Right numeric audio level
    Sleep(10); <-- increase to 100 or 200 for a slower speed
WEnd
;
Func _Exit()
    GUIDelete($ui)
    Exit
EndFunc
;
Func mciSendString($string = ''); Custom MCI Command and Error Function
    Local $mciMsg = DllCall($mciDll, 'long', 'mciSendStringA', 'str', $string, 'str', '', 'int', 180, 'ptr', 0)
    If @error Then Return SetError(@error)
    If $mciMsg[0] <> 0 Then
        Local $eMsg = DllCall($mciDll, 'long', 'mciGetErrorStringA', 'int', $mciMsg[0], 'str', '', 'int', 180)
        If @error Then Return SetError(@error)
        MsgBox(8208, 'Audio Levels', 'MCI Error: ' & $mciMsg[0] & @CRLF & $eMsg[2])
        Return SetError(-1)
    EndIf
    Return SetError(0, 0, $mciMsg[2])
EndFunc
;
Func _HiWord($value); From WinAPI.au3
    Return BitShift($value, 16)
EndFunc
;
Func _LoWord($value); From WinAPI.au3
    Return BitAND($value, 0xFFFF)
EndFunc
;

 

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

Link to comment
Share on other sites

This thread was already resurrected, so I'll hop on board.

Here is my script after changing the result to just a MsgBox.  When I run this the 3rd part of the array is nothing (MsgBox for 3rd item in array).  The reason it's nothing is that when I change it to MsgBox the first part of the mciLevel array it is equal to 328 which is why the script just exists if I don't comment out the mciLevel[0]<>0 statement.

Any insight on what it means if mciLevel[0] = 328?

 

#include <WindowsConstants.au3>
#include <GUIConstants.au3>
#include <GUIConstantsEx.au3>
#include <ProgressConstants.au3>
#include <MsgBoxConstants.au3>


;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
    MsgBox(64, 'Levels', $mciLevel[2])
    ;GUICtrlSetData($ProgressBar, $mciLevel[2]); <-- here is the numeric audio level
;Until GUIGetMsg() = -3
;
;GUIDelete($ui)
Exit

 

Link to comment
Share on other sites

Error 328 = MCIERR_WAVE_INPUTSUNSUITABLE

"No installed waveform device can record files in the current format.
Use the Drivers option from the Control Panel to install a suitable
waveform recording device."

---

MCI Code Resource:

https://www.autoitscript.com/forum/topic/122284-mci-showerrorau3/

 

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

Link to comment
Share on other sites

Adapt to your needs.

Audiometer2.rar

Spoiler

Renamer - Rename files and folders, remove portions of text from the filename etc.

GPO Tool - Export/Import Group policy settings.

MirrorDir - Synchronize/Backup/Mirror Folders

BeatsPlayer - Music player.

Params Tool - Right click an exe to see it's parameters or execute them.

String Trigger - Triggers pasting text or applications or internet links on specific strings.

Inconspicuous - Hide files in plain sight, not fully encrypted.

Regedit Control - Registry browsing history, quickly jump into any saved key.

Time4Shutdown - Write the time for shutdown in minutes.

Power Profiles Tool - Set a profile as active, delete, duplicate, export and import.

Finished Task Shutdown - Shuts down pc when specified window/Wndl/process closes.

NetworkSpeedShutdown - Shuts down pc if download speed goes under "X" Kb/s.

IUIAutomation - Topic with framework and examples

Au3Record.exe

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...