_BASS_EXT_ChannelGetFFT Werte auslesen

  • Hallo Zusammen

    ich arbeite im Moment an so einer Art visuellen Darstellung von Musik, wie man sie zum Beispiel von Windows Media Player kennt.
    Dazu sollte ich vielleicht sagen, dass ich absoluter Bass.dll Neuling bin... :)

    Also ich möchte die Lautstärke der einzelnen Frequenzen der ausgewählten Musik graphisch darstellen, genau das macht die Funktion _BASS_EXT_ChannelGetFFT.
    Allerdings gibt die Funktion nicht die einzelnen Werte zur eigenen Verwendung mit GDI+ aus, sondern eine Struktur, die GDI+ per DllCall verwurstet, meine Frage ist also, wie bekomme ich die Werte aus der Struktur oder wie komme ich anders an sie heran?

    Skript:

    Spoiler anzeigen
    [autoit]

    #include <BASS.au3>
    #include <BASSExt.au3>
    #include <ProgressConstants.au3>
    #include <GDIPlus.au3>
    #include <Array.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Local $MusicHandle
    Local $playingState = -1

    [/autoit] [autoit][/autoit] [autoit]

    OnAutoItExitRegister("_EXIT")

    [/autoit] [autoit][/autoit] [autoit]

    _BASS_Startup()
    _BASS_EXT_Startup()
    _BASS_Init(0)
    $aFFT = _BASS_EXT_CreateFFT(30,10,10,300,360,1,True)

    [/autoit] [autoit][/autoit] [autoit]

    $hWnd = GUICreate("Sound dies das",340,460)
    $bPlayPause = GUICtrlCreateButton("Play/Pause",10,10,155,20)
    $bStop = GUICtrlCreateButton("Stop",175,10,155,20)
    $bPath = GUICtrlCreateButton("Pfad wählen",10,40,100,20)
    $lPfadAnzeige = GUICtrlCreateLabel("Nichts ausgewählt",120,40,210,20)

    [/autoit] [autoit][/autoit] [autoit]

    $bSpecial = GUICtrlCreateButton("",165,10,10,20)
    GUICtrlSetBkColor($bSpecial, "#FFFFFF")

    [/autoit] [autoit][/autoit] [autoit]

    _GDIPlus_Startup()
    $brushSchwarz = _GDIPlus_BrushCreateSolid(0xFF000000)
    $brushBlau = _GDIPlus_BrushCreateSolid(0xFF6077FF)

    [/autoit] [autoit][/autoit] [autoit]

    $graphic = _GDIPlus_GraphicsCreateFromHWND($hWnd)
    $bitmap = _GDIPlus_BitmapCreateFromGraphics(320, 380, $graphic)
    $buffer = _GDIPlus_ImageGetGraphicsContext($bitmap)

    [/autoit] [autoit][/autoit] [autoit]

    GUISetState(@SW_SHOW)

    [/autoit] [autoit][/autoit] [autoit]

    Do
    _GDIPlus_GraphicsFillRect($buffer, 0, 0, 320, 380, $brushSchwarz)

    [/autoit] [autoit][/autoit] [autoit]

    _BASS_EXT_ChannelGetFFT($MusicHandle, $aFFT)
    DllCall($ghGDIPDll, "int", "GdipFillPolygon", "handle", $buffer, "handle", $brushBlau, "ptr", $aFFT[0], "int", $aFFT[1], "int", "FillModeAlternate")

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    _GDIPlus_GraphicsDrawImageRect($graphic, $bitmap, 10, 70, 320, 380)

    [/autoit] [autoit][/autoit] [autoit]

    $msg = GUIGetMsg()
    Switch $msg
    Case $bPlayPause
    Switch $playingState
    Case -1 ;vorher gestoppt
    _BASS_ChannelPlay($MusicHandle,True)
    $playingState = 1
    Case 0 ;pause
    _BASS_ChannelPlay($MusicHandle,False)
    $playingState = 1
    Case 1
    _BASS_ChannelPause($MusicHandle)
    $playingState = 0
    EndSwitch
    Case $bStop
    _BASS_ChannelStop($MusicHandle)
    $playingState = -1
    Case $bPath
    _BASS_ChannelStop($MusicHandle)
    $file = FileOpenDialog("Open File","","Musik (*.MP3;*.MP2;*.MP1;*.OGG;*.WAV;*.AIFF;*.AIF)")
    $MusicHandle = _BASS_StreamCreateFile(False,$file,0,0,0)
    GUICtrlSetData($lPfadAnzeige,$file)
    $aFFT = _BASS_EXT_CreateFFT(30,10,10,300,360,1,True)
    Case $bSpecial
    _ArrayDisplay($aFFT)
    EndSwitch
    Until $msg = -3
    _BASS_Free()

    [/autoit] [autoit][/autoit] [autoit]

    Func _EXIT()
    _GDIPlus_BrushDispose($brushBlau)
    _GDIPlus_BrushDispose($brushSchwarz)
    _GDIPlus_GraphicsDispose($buffer)
    _GDIPlus_GraphicsDispose($graphic)
    _GDIPlus_Shutdown()
    _BASS_Free()
    EndFunc

    [/autoit]

    Wenn ihr irgendwann während des Lieds auf den schwarzen Knopf oben zwischen den anderen beiden Knöpfen klickt, seht ihr den Array, der zurückgegeben wird.

    Danke
    DFPWare

  • Die Werte liegen zwischen 0 und 1

    Das menschliche Gehör arbeitet logarithmisch.
    Deshalb sollte man erstens die Werte noch via _BASS_EXT_Level2dB umwandeln.

    Und zweitens die Frequenzbänder "anpassen"
    Ich hab mal versucht das hier zu erklären: FFT Bass.dll kleiner Lehrgang

    Spoiler anzeigen
    [autoit]

    #AutoIt3Wrapper_UseX64=n
    #include "Bass.au3"
    #include "BassExt.au3"

    [/autoit] [autoit][/autoit] [autoit]

    Opt("GUIOnEventMode", 1)

    [/autoit] [autoit][/autoit] [autoit]

    Global $sFile = FileOpenDialog("Open...", "", "playable formats (*.MP3;*.MP2;*.MP1;*.OGG;*.WAV;*.AIFF;*.AIF)")

    [/autoit] [autoit][/autoit] [autoit]

    Global $hGui = GUICreate("FFT", 1034, 220)
    GUISetOnEvent(-3, "_EXIT")
    Global $cDummy_1 = GUICtrlCreateDummy()
    For $i = 1 To 128
    GUICtrlCreateProgress(($i - 1) * 8 + 5, 10, 7, 100, 5)
    Next
    Global $cDummy_2 = GUICtrlCreateDummy()
    For $i = 1 To 128
    GUICtrlCreateProgress(($i - 1) * 8 + 5, 115, 7, 100, 5)
    Next
    GUISetState()

    [/autoit] [autoit][/autoit] [autoit]

    _BASS_Startup()
    _BASS_Init(0, -1, 44100, 0, "")

    [/autoit] [autoit][/autoit] [autoit]

    Global $hStream = _BASS_StreamCreateFile(False, $sFile, 0, 0, $BASS_SAMPLE_FLOAT)

    [/autoit] [autoit][/autoit] [autoit]

    Global $tFFT = DllStructCreate("float[128];")
    Global $pFFT = DllStructGetPtr($tFFT)
    Global $fdB, $adB_1[129], $adB_2[129], $iIdx

    [/autoit] [autoit][/autoit] [autoit]

    _BASS_ChannelPlay($hStream, True)

    [/autoit] [autoit][/autoit] [autoit]

    Global $iTimer = TimerInit()
    While _BASS_ChannelIsActive($hStream)
    If TimerDiff($iTimer) > 25 Then
    $iTimer = TimerInit()
    _BASS_ChannelGetData($hStream, $pFFT, $BASS_DATA_FFT256)

    [/autoit] [autoit][/autoit] [autoit]

    For $i = 1 To 128
    $fdB = _BASS_EXT_Level2dB(DllStructGetData($tFFT, 1, $i)) * 100
    If $fdB > $adB_1[$i] Then $adB_1[$i] = $fdB
    GUICtrlSetData($cDummy_1 + $i, $adB_1[$i])
    $adB_1[$i] -= 4

    [/autoit] [autoit][/autoit] [autoit]

    $iIdx = Round(10 ^ ($i * (Log(128) / Log(10)) / 128))
    $fdB = _BASS_EXT_Level2dB(DllStructGetData($tFFT, 1, $iIdx)) * 100
    If $fdB > $adB_2[$i] Then $adB_2[$i] = $fdB
    GUICtrlSetData($cDummy_2 + $i, $adB_2[$i])
    $adB_2[$i] -= 4
    Next

    [/autoit] [autoit][/autoit] [autoit]

    EndIf
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    _Exit()

    [/autoit] [autoit][/autoit] [autoit]

    Func _Exit()
    _BASS_StreamFree($hStream)
    _BASS_Free()
    Exit
    EndFunc ;==>_Exit

    [/autoit]

    E