#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Run_Au3Stripper=y
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

#include <GDIPlus.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>
#include <BASS.au3>

_BASS_Startup()
_BASS_Init(0)

GLobal $hStream = _BASS_StreamCreateFile(False, FileOpenDialog("Song auswählen", @DesktopDir, "All Files (*.*)"), 0, 0, $BASS_SAMPLE_FLOAT)
_BASS_ChannelPlay($hStream, 0)


Global $tBuffer = DllStructCreate("float [2048]")
Global $pBuffer = DllStructGetPtr($tBuffer)
Global $iBuffer = DllStructGetSize($tBuffer)

Global $tRect = DllStructCreate($tagRECT)
_WinAPI_SystemParametersInfo(0x30, 0, DllStructGetPtr($tRect)) ; 0x30 = SPI_GETWORKAREA

Global Const $iWidthGUI = @DesktopWidth / 3
Global Const $iHeightGUI = @DesktopHeight / 3
Global Const $iTaskbarHeight = @DesktopHeight - $tRect.Bottom

Global Const $iVisualizerHeight = $iHeightGUI * 0.7

Global Const $aStrayFrequencies[] = [30, 40, 50, 60, 70, 80, 90, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000, 20000]
Global Const $aFrequencies = _SubdivideFrequencies($aStrayFrequencies)
Global $aAmplitudes[UBound($aFrequencies)]

_GDIPlus_Startup()

Opt("GUIOnEventMode", 1)
$hVisualizerGUI = GUICreate("", $iWidthGUI, $iHeightGUI, 0, @DesktopHeight - $iHeightGUI - $iTaskbarHeight, $WS_POPUP, $WS_EX_LAYERED)
GUISetBkColor(0xABCDEF, $hVisualizerGUI)
GUISetOnEvent(-3, "_ExitVisualizer")
_WinAPI_SetLayeredWindowAttributes($hVisualizerGUI, 0xABCDEF, 255)

GUISetState(@SW_SHOW, $hVisualizerGUI)

$hGraphics = _GDIPlus_GraphicsCreateFromHWND($hVisualizerGUI)
$hBitmap = _GDIPlus_BitmapCreateFromGraphics($iWidthGUI, $iHeightGUI, $hGraphics)
$hBuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)

$hRedBrush = _GDIPlus_BrushCreateSolid(0xFFFF0000)
$hGreenBrush = _GDIPlus_BrushCreateSolid(0xFF00FF00)

Local $aLinePoints[UBound($aFrequencies) + 1 + 2][2]
$aLinePoints[0][0] = UBound($aFrequencies) + 2

While _BASS_ChannelIsActive($hStream)
	_GDIPlus_GraphicsClear($hBuffer, 0xFFABCDEF)

	$iBuffer = _BASS_ChannelGetData($hStream, $pBuffer, $BASS_DATA_FFT4096)

	For $i = 0 To UBound($aFrequencies) - 1
		$iBarWidth = $iWidthGUI / UBound($aFrequencies)

		$iAmplitude = _FrequencyGetAmplitude($aFrequencies[$i], 44100, $tBuffer)
		$aAmplitudes[$i] = ($iAmplitude + $aAmplitudes[$i]) / 2

		$aLinePoints[$i + 1][0] = $i * $iBarWidth
		$aLinePoints[$i + 1][1] = $iHeightGUI - $iVisualizerHeight * $iAmplitude
	Next

	$aLinePoints[UBound($aLinePoints) - 2][0] = $iWidthGUI
	$aLinePoints[UBound($aLinePoints) - 2][1] = $iHeightGUI

	$aLinePoints[UBound($aLinePoints) - 1][0] = 0
	$aLinePoints[UBound($aLinePoints) - 1][1] = $iHeightGUI

	_GDIPlus_GraphicsDrawPolygon($hBuffer, $aLinePoints)
	_GDIPlus_GraphicsFillPolygon($hBuffer, $aLinePoints, $hGreenBrush)

	_GDIPlus_GraphicsDrawImage($hGraphics, $hBitmap, 0, 0)
WEnd

_ExitVisualizer()

Func _SubdivideFrequencies($aFrequencies, $iDivision = 10)
	Local $aSubfrequencies[(UBound($aFrequencies) - 1) * $iDivision]

	For $i = 0 To UBound($aFrequencies) - 2
		For $j = 0 To $iDivision - 1
			$aSubfrequencies[$i * $iDivision + $j] = $aFrequencies[$i] + $j * ($aFrequencies[$i + 1] - $aFrequencies[$i]) / $iDivision
		Next
	Next

	Return $aSubfrequencies
EndFunc

Func _Abbreviate($i)
	If $i >= 10000 Then Return Floor($i / 1000) & "k"
	If $i >= 1000 Then Return " " & Floor($i / 1000) & "k"
	If $i < 100 Then Return " " & $i
	Return $i
EndFunc

Func _FrequencyGetAmplitude($iFrequency, $iChannelFrequency, $tBuffer)
	Return (DllStructGetData($tBuffer, 1, $iFrequency * 4096 / $iChannelFrequency) * 2) ^ (1/3) / (2 ^ (1/3))
EndFunc

Func _ExitVisualizer()
	_BASS_ChannelStop($hStream)
	_BASS_StreamFree($hStream)
	_BASS_Free()
	_GDIPlus_Shutdown()
	Exit 0
EndFunc