Visuelle Darstellung von wav Audiodateien

  • Hatte mal eine Idee einen simplen Audioeditor in Autoit zu schreiben, allerdings weiss ich nicht so recht ob Autoit dafür geeigenet ist und wo ich da anfangen könnte.
    Für die GUI würde ich jedenfalls gerne eine grafische Ansicht der Audiospuren haben. Jemand Ideen wie man sowas hinbekommt?

    Möglich sein soll fürs erste ein einfaches splitten der Datei in mehrere Teildateien, also z.B. einen 10sek clip in fünf Clips zu je 2sek teilen. Dafür gibt es sicher cmdline basierte Tools die einem das abnehmen können.
    Später wäre es natürlich sinnvoll wenn man über die gui anhand optischer Merkmale die Stellen an denen gecuttet werden soll festlegen könnte.

    Sehr wichtig ist mir eine automatische Erkennung in welchen Bereichen die Tonspur still ist, also grafisch betrachtet eine null Linie hat, um automatisiert Stille oder sehr leise Stellen aus dem Track zu entfernen.
    Da ist die Frage ob man dazu auf Funktionen / UDFs zurückgreifen kann, das ganze anhand grafischer Merkmale macht oder ob man das ganze vielleicht eher bitbasiert anhand der Formatspezifikationen angehen sollte. Letzteres wäre wohl sehr aufwendig, vorallem wenn auch andere Formate unterstützt werden sollen. Selbst beim wav Format gibt es ja schon jedemenge Variationen, je nachnem ob komprimierte oder unkomprimierte PCM Daten enthalten sind, oder ob mehrere Spuren in der Datei sind.

    Vorschläge und Anregungen sind willkommen. Hinweise auf bereits vorhandene Projekte in dieser Richtung oder Hinweise zu cmdline basierten Audio-Cutting- und Audio-Analyse-Tools usw. wären hilfreich.

  • Hier ist das Beispiel zu der Funktion _BASS_EXT_ChannelGetWaveformDecode:

    Spoiler anzeigen
    [autoit]

    #AutoIt3Wrapper_UseX64=n
    #include "Bass.au3"
    #include "BassExt.au3"
    #include <GDIPlus.au3>

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

    Opt("GUIOnEventMode", 1)

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

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

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

    $hGui = GUICreate("WaveformDecode", 800, 250)
    GUISetOnEvent(-3, "_EXIT")
    GUISetState()

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

    _GDIPlus_Startup()
    $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGui)
    $hBmpBuffer = _GDIPlus_BitmapCreateFromGraphics(800, 250, $hGraphics)
    $hGfxBuffer = _GDIPlus_ImageGetGraphicsContext($hBmpBuffer)

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

    $hBmpBk = _GDIPlus_BitmapCreateFromGraphics(800, 250, $hGraphics)
    $hGfxBk = _GDIPlus_ImageGetGraphicsContext($hBmpBk)
    _GDIPlus_GraphicsSetSmoothingMode($hGfxBk, 2)

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

    $hPenL = _GDIPlus_PenCreate(0xFF00FF00, 1)
    $hPenR = _GDIPlus_PenCreate(0xFFFF0000, 1)
    $hBrushL = _GDIPlus_BrushCreateSolid(0xBB00BB00)
    $hBrushR = _GDIPlus_BrushCreateSolid(0xBBBB0000)
    $hPenPos = _GDIPlus_PenCreate(0xFF000099, 3)
    $hPenPos2 = _GDIPlus_PenCreate(0x99FFFF00, 1)

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

    _BASS_Startup(@ScriptDir & "\bass.dll")
    ___Debug(@error, "load bass.dll")

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

    _BASS_EXT_Startup(@ScriptDir & "\bassExt.dll")
    ___Debug(@error, "load bassext.dll")

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

    _BASS_Init(0, -1, 44100, 0, "")
    ___Debug(@error, "initialize bass")

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

    $hStreamDecode = _BASS_StreamCreateFile(False, $sFile, 0, 0, $BASS_STREAM_DECODE)
    ___Debug(@error, "create stream from file")

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

    $hStreamPlay = _BASS_StreamCreateFile(False, $sFile, 0, 0, 0)
    ___Debug(@error, "create stream from file")

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

    $iBytes = _BASS_ChannelGetLength($hStreamDecode, $BASS_POS_BYTE)
    $iLength = _BASS_ChannelBytes2Seconds($hStreamDecode, $iBytes)

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

    $iRes = 88; polygon segments per second

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

    $iWidth = $iLength * $iRes
    $aWave = _BASS_EXT_ChannelGetWaveformDecode($hStreamDecode, $iWidth, 200, 0, $iLength, $iRes, "_WaveformGetProc")

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

    _BASS_StreamFree($hStreamDecode)

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

    $hBmpWave = _BASS_EXT_GDIpBitmapCreateWaveform($hGraphics, $aWave, $hBrushL, $hPenL, $hBrushR, $hPenR, 0, 1)
    ToolTip("")

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

    _GDIPlus_GraphicsClear($hGfxBk, 0xFF000000)
    Switch $iWidth
    Case 0 To 30000
    _GDIPlus_GraphicsDrawImageRect($hGfxBk, $hBmpWave, 0, 200, 800, 50)
    Case Else
    For $i = 0 To $iWidth Step 30000
    _GDIPlus_GraphicsDrawImageRectRect($hGfxBk, $hBmpWave, $i, 0, 30000, 200, Round($i * 800 / $iWidth), 200, Ceiling(30000 * 800 / $iWidth), 50)
    Next
    EndSwitch

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

    _BASS_ChannelPlay($hStreamPlay, True)
    ___Debug(@error, "start stream")

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

    GUIRegisterMsg(0x000F, "WM_PAINT")
    GUIRegisterMsg(0x0014, "WM_ERASEBKGND")

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

    $iTimer = TimerInit()
    While _BASS_ChannelIsActive($hStreamPlay)
    If TimerDiff($iTimer) > 20 Then
    $iTimer = TimerInit()
    $iPosByte = _BASS_ChannelGetPosition($hStreamPlay, $BASS_POS_BYTE)
    $iPosSec = _BASS_ChannelBytes2Seconds($hStreamPlay, $iPosByte)
    $iOffset = Round($iPosSec * $iRes)
    _GDIPlus_GraphicsDrawImage($hGfxBuffer, $hBmpBk, 0, 0)
    _GDIPlus_GraphicsDrawLine($hGfxBuffer, 400, 2, 400, 198, $hPenPos)
    _GDIPlus_GraphicsDrawLine($hGfxBuffer, 800 * $iOffset / $iWidth, 202, 800 * $iOffset / $iWidth, 248, $hPenPos2)
    Select
    Case $iOffset < 400
    _GDIPlus_GraphicsDrawImageRectRect($hGfxBuffer, $hBmpWave, 0, 0, 800, $aWave[6] * 4, 400 - $iOffset, 0, 800, $aWave[6] * 4)
    Case $iOffset >= $iWidth - 800
    _GDIPlus_GraphicsDrawImageRectRect($hGfxBuffer, $hBmpWave, $iWidth - ($iWidth - $iOffset) - 400, 0, $iWidth - $iOffset + 400, $aWave[6] * 4, 0, 0, $iWidth - $iOffset + 400, $aWave[6] * 4)
    Case Else
    _GDIPlus_GraphicsDrawImageRectRect($hGfxBuffer, $hBmpWave, $iOffset - 400, 0, 800, $aWave[6] * 4, 0, 0, 800, $aWave[6] * 4)
    EndSelect
    _GDIPlus_GraphicsDrawImage($hGraphics, $hBmpBuffer, 0, 0)
    EndIf
    Sleep(10)
    WEnd

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

    _Exit()

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

    Func _WaveformGetProc($handle, $percent)
    ToolTip("Get Waveform: " & $percent & "%")
    EndFunc ;==>_WaveformGetProc

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

    Func _Exit()
    _BASS_ChannelStop($hStreamPlay)
    ___Debug(@error, "stop stream")

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

    _BASS_StreamFree($hStreamPlay)
    ___Debug(@error, "free stream")

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

    _BASS_Free()
    ___Debug(@error, "free bass")

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

    GUIRegisterMsg(0x000F, "")
    GUIRegisterMsg(0x0014, "")
    _GDIPlus_PenDispose($hPenL)
    _GDIPlus_PenDispose($hPenR)
    _GDIPlus_BrushDispose($hBrushL)
    _GDIPlus_BrushDispose($hBrushR)
    _GDIPlus_PenDispose($hPenPos)
    _GDIPlus_PenDispose($hPenPos2)
    _GDIPlus_BitmapDispose($hBmpBk)
    _GDIPlus_GraphicsDispose($hGfxBk)
    _GDIPlus_BitmapDispose($hBmpWave)
    _GDIPlus_GraphicsDispose($hGfxBuffer)
    _GDIPlus_BitmapDispose($hBmpBuffer)
    _GDIPlus_GraphicsDispose($hGraphics)
    _GDIPlus_Shutdown()
    Exit
    EndFunc ;==>_Exit

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

    Func WM_PAINT($hWnd, $uMsgm, $wParam, $lParam)
    _GDIPlus_GraphicsDrawImage($hGraphics, $hBmpBuffer, 0, 0)
    Return 'GUI_RUNDEFMSG'
    EndFunc ;==>WM_PAINT

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

    Func WM_ERASEBKGND($hWnd, $uMsgm, $wParam, $lParam)
    _GDIPlus_GraphicsDrawImage($hGraphics, $hBmpBuffer, 0, 0)
    Return True
    EndFunc ;==>WM_ERASEBKGND

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

    Func ___DeBug($iError, $sAction)
    Switch $iError
    Case -1
    ConsoleWrite(@CRLF & "-" & $sAction & @CRLF)
    Case 0
    ConsoleWrite(@CRLF & "+" & $sAction & " - OK" & @CRLF)
    Case Else
    ConsoleWrite(@CRLF & "!" & $sAction & " - FAILED" & @CRLF)
    Exit
    EndSwitch
    EndFunc ;==>___DeBug

    [/autoit]

    Die benötigten Dateien findest du beim Link, den UEZ gepostet hat

    E

  • Hi

    Es wird in naher Zukunft eine Hilfe geben.
    Das gepostete Script ist z.B. schon ein Teil davon.

    Sie wird mit dann mit der Bass.au3 Version 10 veröffentlicht - das zieht sich jedoch noch etwas hin, da BrettF momentan zu wenig Zeit hat.
    Vielleicht wird das Paket noch in diesem Jahr fertig :whistling:

    E