Jump to content
ripdad

Need help with DLL Call

Recommended Posts

I'm trying to get this new function to work in AutoIt -- but it causes a hard crash.

Any help would be appreciated.

Func _BASS_ChannelGetLevelEx($hStream)

    #cs
        BOOL BASS_ChannelGetLevelEx(
            DWORD handle,
            float *levels,
            float length,
            DWORD flags
        )
    #ce

    Local $aLevels[2]; levels array
    Local $fLength = 0.02; 2ms of data
    Local $BASS_LEVEL_STEREO = 2; stereo flag

    Local $aResult = DllCall($_ghBassDll, 'bool', 'BASS_ChannelGetLevelEx', 'dword', $hStream, 'float', $aLevels, 'float', $fLength, 'dword', $BASS_LEVEL_STEREO)
    If @error Then Return SetError(1, 1, 0)]
    
    ; additional code goes here for handling result
EndFunc

 


"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
Posted (edited)

Hello. Try something like this:

 

Local $aResult = DllCall($_ghBassDll, 'bool', 'BASS_ChannelGetLevelEx', 'dword', $hStream, 'ptr*', 0, 'float', $fLength, 'dword', $BASS_LEVEL_STEREO)
Local $paLevels=$aResult[2]
Local $tLevels=DllStructCreate("FLOAT LvLeft;FLOAT LvLRight",$paLevels)
Local $fLevelLeft=$tLevels.LvLeft
Local $fLevelRight=$tLevels.LvLRight
ConsoleWrite($fLevelLeft & @CRLF)
ConsoleWrite($fLevelRight & @CRLF)


 

 

PD 1: It's not a tested code. But I think is how it should look like.

PD 2:    I'll update syntax highlighter tag later. 

 

Saludos

 

Edited by Danyfirex

Share this post


Link to post
Share on other sites

Danyfirex,

No luck -- It also crashed.

 


"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
Posted (edited)

Nine,

Yes, v2.4.15.0

I tried a variation of it. Still no luck. It crashes on DllStructGetData.

Will try another variation in a little bit.

What is your "similar approach"?

--edit

I will put together a small script, if that doesn't get it.

 

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

Probably you need to allocate the floats before so create the structure before the call and pass the structure's pointer type ptr or the struct itself changing the parameter type to struct. I've not checked documentation yet. But I'll do later probably. But I'm sure it's not a big issue. Seems to be easy to implement checking with the library.

 

Saludos

Share this post


Link to post
Share on other sites
Local $fLength = 0.02    ; 2ms of data
Local $BASS_LEVEL_STEREO = 2    ; stereo flag
Local $aResult = DllCall("bass.dll", 'bool', 'BASS_ChannelGetLevelEx', 'dword', $hStream, 'struct*', 0, 'float', $fLength, 'dword', $BASS_LEVEL_STEREO)
ConsoleWrite(@error & @CRLF)
Local $tFloat = DllStructCreate("float[2]", $aResult[2])
_ArrayDisplay($aResult)
ConsoleWrite(DllStructGetData($tFloat, 1, 1) & "/" & DllStructGetData($tFloat, 1, 2) & @CRLF)

 

Share this post


Link to post
Share on other sites

Geeze guys,

I started to do a struct* --- but I said NO... it's expecting an array !

So much for logic.

Okay, I will test here shortly. Thanks.

 


"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
Posted (edited)

I meant something like this:

Local $tLevels=DllStructCreate("FLOAT LvLeft;FLOAT LvLRight")

Local $aResult = DllCall($_ghBassDll, 'bool', 'BASS_ChannelGetLevelEx', 'dword', $hStream, 'ptr',dllstructgetptr($tLevels), 'float', $fLength, 'dword', $BASS_LEVEL_STEREO)


Local $fLevelLeft=$tLevels.LvLeft
Local $fLevelRight=$tLevels.LvLRight
ConsoleWrite($fLevelLeft & @CRLF)
ConsoleWrite($fLevelRight & @CRLF)

Saludos

Edited by Danyfirex

Share this post


Link to post
Share on other sites

This works but you need the latest BASS.dll (v2.4.15.0)

Func _BASS_ChannelGetLevelEx($hStream, $fLength = 0.02, $iFlag = $BASS_LEVEL_STEREO)
    Local $tLevels = DllStructCreate("float levels[2]")
    Local $BASS_ret_ = DllCall($_ghBassDll, 'bool', 'BASS_ChannelGetLevelEx', 'dword', $hStream, 'struct*', $tLevels, 'float', $fLength, 'dword', $iFlag)
    If @error Then Return SetError(1, 1, 0)
    If $BASS_ret_[0] = 0 Then Return SetError(_BASS_ErrorGetCode(), 0, 0)
    Return $tLevels
EndFunc   ;==>_BASS_ChannelGetLevelEx

You can access the values

$tLevels = _BASS_ChannelGetLevelEx($hMusic)
ConsoleWrite($tLevels.levels(1) & ", " & $tLevels.levels(2) & @CRLF)

 


Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites
Posted (edited)

I do not think it is necessary to create a struct before the call since the dll will create its own space (as you do not send any information) and report the address.

Edited by Nine

Share this post


Link to post
Share on other sites

Thanks everyone for your time and skills.

I need to test these across versions AutoIt -- to see where each of them stands.

Will get back to this in a day or two. Thanks again.

 


"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
11 hours ago, Nine said:

I do not think it is necessary to create a struct before the call since the dll will create its own space (as you do not send any information) and report the address.

Might be but the result is the same to get the value from the call using your way.


Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites

@Nine No all the time. Sometimes You need to allocate the space before. this is one of the cases.

 

Saludos

Share this post


Link to post
Share on other sites
Posted (edited)

It's taken some time to go through various test. Thanks for your patience.

The primary purpose for this function was to be able to get the final output volume of a stream, after DSP processing. This includes VST's. On a recording stream, this doesn't seem to be an issue. But on a playing stream, it's quite a different thing. When _BASS_ChannelGetLevel() is used to get levels on a play stream, it's not doing it at the final output of the stream. It's doing it at some hardcoded FX Pin earlier in it.

Not really sure why the BASS developers did this, but there is a way to get that reading at the final output according to this post:

http://www.un4seen.com/forum/?topic=18949.0

So, I tested various ways to accomplish getting that reading. I found that setting a Volume FX at low priority works. Afterwards, I needed to work out a few things in the main script to accommodate the new function. It turned out very well. I'm very happy with it.

Okay, let's talk about what works and what doesn't.

Nine, I couldn't get your code to work on a 32bit machine, using AutoIt 3.3.8.1 (32bit). I needed it to be compatible back to that version. It probably works fine on a 64bit machine using a more up-to-date version of AutoIt.

I was having other problems in 32bit mode, with obtaining the levels using the object method. It would soft crash saying: "variable must be of type object"

After I changed the Danyfirex code and UEZ code to DllStructGetData() -- they both worked.

I used code lines from both of them to put together what was suitable for me on the project I'm working on, and added some of my own. Here is the result:

; #CUSTOM FUNCTION# ===================================================================================================
; .......Name.: _BASS_ChannelGetLevelEx($hStream, $fLength, $iFlag)
; Description.: Gets the volume level on a play or record stream and is more flexible than _BASS_ChannelGetLevel().
; DLL Version.: BASS.DLL v2.4.15.0
; ............:
; .Parameters.: $hStream - The handle returned by _BASS_RecordStart, _BASS_StreamCreateFile, RecordStart from BASS_CB.dll
; ............: $fLength - The amount of data to inspect to calculate the level, in seconds. Default = 20ms, Maximum = 1sec.
; ............:   $iFlag - BASS_LEVEL_MONO = 1, BASS_LEVEL_STEREO = 2 (Default), BASS_LEVEL_RMS = 4, BASS_LEVEL_VOLPAN = 8
; ............:
; ....Returns.: Success - Returns the volume level 0 to 100+  (this level is not clipped, so it could exceed 100 easily)
; ............: Failure - sets @error
; ............:
; .....Author.: ripdad (June 30, 2020) Thanks to Danyfirex and UEZ for their help in the making of this function.
; ...Modified.:
; ............:
; ....Remarks.: To get final output volume level for a stream, you must place an FX with priority = 0 on the stream.
; ............: See: _BASS_ChannelSetVolumeFX() and _BASS_FXSetVolumeParameters()
; ............:
; .......Link.: http://www.un4seen.com/doc/#bass/BASS_ChannelGetLevelEx.html
; ....Related.: _BASS_ChannelGetLevel
;======================================================================================================================
Func _BASS_ChannelGetLevelEx($hStream, $fLength = 0.02, $iFlag = 2)
    Local $tLevels = DllStructCreate('float fLeftLevel;float fRightLevel')
    Local $aResult = DllCall($_ghBassDll, 'bool', 'BASS_ChannelGetLevelEx', 'dword', $hStream, 'struct*', $tLevels, 'float', $fLength, 'dword', $iFlag)
    If @error Then Return SetError(1, 1, 0)
    If $aResult[0] = 0 Then Return SetError(_BASS_ErrorGetCode(), 0, 0)
    Local $nLeftLevel = Round(DllStructGetData($tLevels, 'fLeftLevel') * 100)
    Local $nRightLevel = Round(DllStructGetData($tLevels, 'fRightLevel') * 100)
    If $iFlag = 1 Then $nRightLevel = $nLeftLevel
    Return StringFormat('%02i%02i', $nLeftLevel, $nRightLevel)
EndFunc

To access the return from this function:  $LeftCH = StringLeft($iLevels, 2) and $RightCH = StringRight($iLevels, 2)

I want to thank everyone who pitched in on this effort. I appreciate it very much.

 

Edited by ripdad
corrected spelling and changed url to direct post link.

"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

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...