1. Dashboard
  2. Mitglieder
    1. Letzte Aktivitäten
    2. Benutzer online
    3. Team
    4. Mitgliedersuche
  3. Forenregeln
  4. Forum
    1. Unerledigte Themen
  • Anmelden
  • Registrieren
  • Suche
Alles
  • Alles
  • Artikel
  • Seiten
  • Forum
  • Erweiterte Suche
  1. AutoIt.de - Das deutschsprachige Forum.
  2. Mitglieder
  3. Simpel

Beiträge von Simpel

  • R128 Lautheitsmesser

    • Simpel
    • 12. Februar 2018 um 13:26

    Wow,

    da bin ich mit diesem doch noch halbwegs übersichtlichen Code über die 20.000 Zeichen Beschränkung gekommen? Habe ordentlich was löschen müssen (Kommentarzeilen und Leerzeilen für die Übersichtlichkeit). In Word werden die Zeichen wohl anders gezählt, denn da war ich mit dem Original-Code knapp unter 20.000 - hier wurde es aber nicht akzeptiert.

    Gruß, Conrad

  • R128 Lautheitsmesser

    • Simpel
    • 12. Februar 2018 um 13:19

    Moin.

    Ich habe über's Wochenende die verschiedenen Kanäle hinzufügen können:

    AutoIt
    AutoIt#include <Array.au3>
    #include <StringConstants.au3>
    #include <FileConstants.au3>
    Local $filename ; EBU-Test-Set: https://tech.ebu.ch/publications/ebu_loudness_test_set
    $filename = @ScriptDir & "\EBU-Test-Set\1kHz Sine -20 LUFS-16bit.wav" ; 20 Sek
    
    Local $h = FileOpen($filename, $FO_BINARY) ; binary
    If $h = -1 Then _ErrorMessage(@error, @extended, @ScriptLineNumber - 1, "Could not open wav-file.", True, $h, "$h") ; ausführlichere Fehler-Meldung
    Local $sHeader = FileRead($h, 2000) ; 2000 Byte sollten für den Headerteil erstmal reichen
    Local $iPosition_fmt = StringInStr($sHeader, "666D7420") ; hier wird die Position von "fmt " ("666D7420" in HEX) gesucht - definierter Teil des WAV-Headers
    $iPosition_fmt = ($iPosition_fmt - 3) / 2 ; das Ergebnis wird in Position der Bytes gewandelt
    Local $iPosition_AudioStream = $iPosition_fmt + 44 ; für RIFF WAVE die Position des Starts der Audiodaten
    If StringInStr($sHeader, "466169726C69676874") Then ; hier wird Fairlight in HEX gesucht, denn dann ist
        ConsoleWrite("!Fairlight-File    ")
        $iPosition_AudioStream = $iPosition_fmt + 68 ; die Position des Starts der Audiodaten anders
    EndIf
    FileSetPos($h, $iPosition_fmt + 10, 0)
    Local $iChannels = Number(FileRead($h, 2)) ; fmt + 10, 2byte für Kanalanzahl
    ConsoleWrite('CH: ' & $iChannels & "   ")
    Local $iSamples = Number(FileRead($h, 4)) ; direkt danach, 4byte für die Samplerate
    ConsoleWrite('SR: ' & $iSamples & "   ")
    FileSetPos($h, $iPosition_fmt + 22, 0)
    Local $iBitrate = Number(FileRead($h, 2)) ; fmt + 22, 2byte für die Bitrate
    ConsoleWrite('BR: ' & $iBitrate & "   ")
    FileSetPos($h, $iPosition_fmt + 28, 0)
    Local $iLengthDataBlock = Number(FileRead($h, 4)) ; fmt + 28, 4 byte aus denen später die Länge des Files berechnet werden
    Local $i100msSampleCount = $iSamples / 10 ; Anzahl der Samples für 1/10 Sekunde - 100ms-Fenster - Verschiebung des 400ms-Fensters
    Local $iNumberOfAll100msRuns = Floor($iLengthDataBlock / (($iBitrate / 8) * $i100msSampleCount * $iChannels)) ; Anzahl aller 100ms Proben bis das ganze File gescannt ist
    ConsoleWrite("L: " & $iNumberOfAll100msRuns / 10 & "s   " & $filename)
    ; Declare further variable
    Local $iCounterOf100msRuns = 0 ; Zähler für jeden 100ms Durchgang
    Local $s100msReadOut ; 100ms ausgelesene Bytes aus dem File
    Local $a100msHexArray ; Array der 100ms Samples in Hex
    Local $iInteger ; aktuell ausgelesenes Sample
    Local $a100msInteger[0] ; Array aller Samples innerhalb eines 100ms-Fensters
    Local $a400msIntegerCh1[$i100msSampleCount * 4] ; Array aller Samples innerhalb des 400ms-Fenster für Lautheit Momentary für Kanal 1
    Local $a400msIntegerCh2[$i100msSampleCount * 4] ; Array aller Samples innerhalb des 400ms-Fenster für Lautheit Momentary für Kanal 2
    Local $a400msIntegerCh3[$i100msSampleCount * 4] ; Array aller Samples innerhalb des 400ms-Fenster für Lautheit Momentary für Kanal 3
    Local $a400msIntegerCh4[$i100msSampleCount * 4] ; Array aller Samples innerhalb des 400ms-Fenster für Lautheit Momentary für Kanal 4
    Local $a400msIntegerCh5[$i100msSampleCount * 4] ; Array aller Samples innerhalb des 400ms-Fenster für Lautheit Momentary für Kanal 5
    Local $a400msIntegerCh6[$i100msSampleCount * 4] ; Array aller Samples innerhalb des 400ms-Fenster für Lautheit Momentary für Kanal 6
    Local $s100IntegerFilterKette; String aller K-gefilterten Samples innerhalb eines 100ms-Fensters
    Local $xnK1_2, $xnK1_1, $ynK1_2, $ynK1, $ynK1_1, $xnK1 ; Variablen für K-Filter Stage 1 - x[n], x[n-1], x[n-2], y[n], y[n-1], y[n-2]
    Local $xnK2_2, $xnK2_1, $ynK2_2, $ynK2, $ynK2_1, $xnK2 ; Variablen für K-Filter Stage 2 - x[n], x[n-1], x[n-2], y[n], y[n-1], y[n-2]
    Local $iMeanSquare400ms ; Effektivwert aller 400ms-Samples
    Global $g_aAllMomentaryDecibel[$iNumberOfAll100msRuns - 3] ; die ersten drei 100ms-Fenster ergeben noch keine 400ms-Fenster zusammen, so daß noch kein Momentary-Wert berechnet werden kann
    Local $aActualMomentaryForAllChannel[$iChannels] ; enthält in Decibel den Effektivwert des aktuellen Momentary pro Kanal
    ; variables for channel order - this maybe can be user adaptable in further developments
    Global $g_CHANNEL_LEFT = 1
    Global $g_CHANNEL_RIGHT = 2
    Global $g_CHANNEL_CENTER = 3
    Global $g_CHANNEL_LFE = 4
    Global $g_CHANNEL_LEFT_SURROUND = 5
    Global $g_CHANNEL_RIGHT_SURROUND = 6
    Local $iHex
    Local $iChangedEndian
    FileSetPos($h, $iPosition_AudioStream, 0)
    Local $hTimerStart = TimerInit() ; Start Zeitnahme Ermittelung sämtlicher Momentary
    ProgressOn("File-Scan - Length of file: " & $iNumberOfAll100msRuns / 10 & "s", "Please wait...", "", @DesktopWidth - 350, @DesktopHeight - 220) ; Progress während des Programmierens und Debuggings rechts unten in die Ecke um die _ArrayDisplays zu sehen
    While 1
        If Mod($iCounterOf100msRuns, 250) = 0 Then ConsoleWrite(@CRLF) ; nächste Zeile in der Konsolen-Ausgabe
        ConsoleWrite(".") ; Fortschritt zeigen
        ProgressSet($iCounterOf100msRuns * 100 / $iNumberOfAll100msRuns, Floor($iCounterOf100msRuns * 100 / $iNumberOfAll100msRuns) & "%") ; Progress refreshen
        $s100msReadOut = FileRead($h, ($iBitrate / 8) * $i100msSampleCount * $iChannels) ; nächste 100ms des Files auslesen - $iBitrate/8 ergibt die Bytes pro Sample - mal die Anzahl der Kanäle, da die interleaved, also immer im Wechsel kommen
        If @extended < ($iBitrate / 8) * $i100msSampleCount * $iChannels Then ; wenn die Anzahl der ausgelesenen Bytes kleiner sind als für 100ms benötigt (das File ist also zu Ende)
            ExitLoop ; kein kompletter 100ms Readout mehr möglich, deshalb Daten verwerfen (laut R128)
        EndIf
        $s100msReadOut = StringTrimLeft($s100msReadOut, 2) ; "0x" entfernen um die Regex nicht zu verwirren
        $a100msHexArray = StringRegExp($s100msReadOut, "([\x00-\xff]{" & 2 * $iBitrate / 8 & "})", 3) ; sucht nach HEX-Werten 2 Zeichen pro Byte für Bitrate/8 Byte
        For $i = 1 To $iChannels
            If $i = $g_CHANNEL_LFE Then
                ; do nothing
            Else
                $xnK1_2 = 0
                $xnK1_1 = 0
                $ynK1_2 = 0
                $ynK1 = 0
                $ynK1_1 = 0
                $xnK1 = 0 ; Variablen für K-Filter Stage 1 - x[n], x[n-1], x[n-2], y[n], y[n-1], y[n-2] leeren
                $xnK2_2 = 0
                $xnK2_1 = 0
                $ynK2_2 = 0
                $ynK2 = 0
                $ynK2_1 = 0
                $xnK2 = 0 ; Variablen für K-Filter Stage 2 - x[n], x[n-1], x[n-2], y[n], y[n-1], y[n-2] leeren
                For $j = 1 To $i100msSampleCount ; für jedes Sample innerhalb 100ms pro Kanal
                    $iInteger = $a100msHexArray[($j * $iChannels - ($iChannels - $i)) - 1] ; nächster HEX-Wert des Kanals
                    ; make little endian to big endian
                    $iChangedEndian = ""
                    For $k = 1 To StringLen($iInteger) / 2
                        $iChangedEndian &= StringRight($iInteger, 2) ; die hinteren nach vorne setzen
                        $iInteger = StringTrimRight($iInteger, 2) ; vom ursprünglichen gesamten LittleEndian-Hex-wert die ersten beiden Stellen löschen
                    Next
                    $iInteger = "0x" & $iChangedEndian
                    $iInteger = Number($iInteger) ; Integer daraus machen
                    ; make signed integer
                    If $iInteger > ((2 ^ ($iBitrate - 1)) - 1) Then ; wenn Wert größer als die Hälfte der gesamten Integer (dann sind es die negativen Samples)
                        $iInteger = Number($iInteger - (2 ^ $iBitrate)) ; soll die untere Hälfte ein negatives Vorzeichen bekommen - wird sonst automatisch Unsigned Integer angenommen
                    Else
                        $iInteger = Number($iInteger)
                    EndIf
        ;~             ConsoleWrite($iInteger & @CRLF)
                    ; K-filter stage 1 - high shelving 1kHz +4dB
                    $xnK1_2 = $xnK1_1 ; die Werte für x[n], x[n-1], x[n-2], y[n], y[n-1], y[n-2] stage 1 rücken eins weiter in die Vergangenheit
                    $xnK1_1 = $xnK1
                    $ynK1_2 = $ynK1_1
                    $ynK1_1 = $ynK1
                    $xnK1 = $iInteger
                    $ynK1 = Int(1.53512485958697 * $xnK1 - 2.69169618940638 * $xnK1_1 + 1.19839281085285 * $xnK1_2 + 1.69065929318241 * $ynK1_1 - 0.73248077421585 * $ynK1_2) ; Koeffizienten für stage 1 hard gecoded und nicht als Variablen wegen Geschwindigkeit
                    ; K-filter stage 2 - low cut 100Hz
                    $xnK2_2 = $xnK2_1 ; die Werte für x[n], x[n-1], x[n-2], y[n], y[n-1], y[n-2] stage 2 rücken eins weiter in die Vergangenheit
                    $xnK2_1 = $xnK2
                    $ynK2_2 = $ynK2_1
                    $ynK2_1 = $ynK2
                    $xnK2 = $ynK1
                    $ynK2 = Int($xnK2 - 2 * $xnK2_1 + $xnK2_2 + 1.99004745483398 * $ynK2_1 - 0.99007225036621 * $ynK2_2) ; Koeffizienten für stage 2 hard gecoded und nicht als Variablen wegen Geschwindigkeit
                    $s100IntegerFilterKette &= $ynK2 & "|" ; gefiltertes Sample an die Kette hängen mit | als Trenner
                Next
                ; after all Samples needed for 100ms
                $s100IntegerFilterKette = StringTrimRight($s100IntegerFilterKette, 1) ; letztes | entfernen
                $a100msInteger = StringSplit($s100IntegerFilterKette, "|", $STR_NOCOUNT) ; ein Array aus der 100ms-Kette machen ohne Index
                $s100IntegerFilterKette = "" ; Filterkette löschen
                $iMeanSquare400ms = 0 ; Effektiv-Wert resetten
                ; fill up all 400ms-Arrays per channel
                Switch $i
                    Case $g_CHANNEL_LEFT
                        _ArrayDelete($a400msIntegerCh1, "0-" & ($i100msSampleCount - 1) & "") ; aus dem 400ms-Array (also Momentary) die obersten 100ms entfernen
                        _ArrayAdd($a400msIntegerCh1, $a100msInteger) ; die aktuellen 100ms hinzufügen
                    Case $g_CHANNEL_RIGHT
                        _ArrayDelete($a400msIntegerCh2, "0-" & ($i100msSampleCount - 1) & "") ; aus dem 400ms-Array (also Momentary) die obersten 100ms entfernen
                        _ArrayAdd($a400msIntegerCh2, $a100msInteger) ; die aktuellen 100ms hinzufügen
                    Case $g_CHANNEL_CENTER
                        _ArrayDelete($a400msIntegerCh3, "0-" & ($i100msSampleCount - 1) & "") ; aus dem 400ms-Array (also Momentary) die obersten 100ms entfernen
                        _ArrayAdd($a400msIntegerCh3, $a100msInteger) ; die aktuellen 100ms hinzufügen
                    Case $g_CHANNEL_LEFT_SURROUND
                        _ArrayDelete($a400msIntegerCh5, "0-" & ($i100msSampleCount - 1) & "") ; aus dem 400ms-Array (also Momentary) die obersten 100ms entfernen
                        _ArrayAdd($a400msIntegerCh5, $a100msInteger) ; die aktuellen 100ms hinzufügen
                    Case $g_CHANNEL_RIGHT_SURROUND
                        _ArrayDelete($a400msIntegerCh6, "0-" & ($i100msSampleCount - 1) & "") ; aus dem 400ms-Array (also Momentary) die obersten 100ms entfernen
                        _ArrayAdd($a400msIntegerCh6, $a100msInteger) ; die aktuellen 100ms hinzufügen
                    Case $g_CHANNEL_LFE
                        ; aktuell nichts tun, denn LFE soll bisher nicht beachtet werden
                EndSwitch
                ; calculate mean square in decibel
                If $iCounterOf100msRuns > 2 Then ; erst wenn die ersten 400ms voll sind (nach 3 Runden 100ms)
                    Switch $i
                        Case $g_CHANNEL_LEFT
                            $aActualMomentaryForAllChannel[$i -1] = _Decibel(_MeanSquare($a400msIntegerCh1)) ; berechnet aus den gefilterten Samples den Effektivwert und rechnet das in Dezibel um
                        Case $g_CHANNEL_RIGHT
                            $aActualMomentaryForAllChannel[$i -1] = _Decibel(_MeanSquare($a400msIntegerCh2))
                        Case $g_CHANNEL_CENTER
                            $aActualMomentaryForAllChannel[$i -1] = _Decibel(_MeanSquare($a400msIntegerCh3))
                        Case $g_CHANNEL_LEFT_SURROUND
                            $aActualMomentaryForAllChannel[$i -1] = _Decibel(_MeanSquare($a400msIntegerCh5) * 1.41) ; die Surrounds werden mit 1,5dB oder Faktor 1,41 lauter bewertet
                        Case $g_CHANNEL_RIGHT_SURROUND
                            $aActualMomentaryForAllChannel[$i -1] = _Decibel(_MeanSquare($a400msIntegerCh6) * 1.41)
                        Case $g_CHANNEL_LFE
                            ; aktuell nichts tun, denn LFE soll bisher nicht beachtet werden
                    EndSwitch
                EndIf
            EndIf
        Next
        ; Addition of channel decibel
        If $iCounterOf100msRuns > 2 Then ; erst wenn die ersten 400ms voll sind (nach 3 Runden 100ms)
            $iMeanSquare400ms = _AdditionDecibel($aActualMomentaryForAllChannel) ; Addition der Pegel aller Kanäle zu einem Wert
    ;~         ConsoleWrite($iMeanSquare400ms & @CRLF)
            $g_aAllMomentaryDecibel[$iCounterOf100msRuns - 3] = $iMeanSquare400ms
        EndIf
        $iCounterOf100msRuns += 1 ; Anzahl der durchgelaufenen 100ms Berechnungen um 1 erhöhen
    WEnd
    ; file is read out and all Momentary are calculated
    FileClose($h) ; File wird nicht mehr gebraucht und geschlossen
    ProgressOff()
    ConsoleWrite(" " & $iCounterOf100msRuns & @CRLF)
    ConsoleWrite("Timer: " & Round(TimerDiff($hTimerStart) / 1000) & @CRLF) ; dieses war der zeitkritische Bereich, da die meisten Berechnungen hier mit den Samples oder alle 100ms berechnet werden
    ; delete last empty row
    _ArraySort($g_aAllMomentaryDecibel, 1) ; damit die niedrigen Werte unten liegen
    Local $aEmptyFields = _ArrayFindAll($g_aAllMomentaryDecibel, "") ; manchmal ist das letzte Feld leer
    If Not @error Then
        For $i = UBound($aEmptyFields) - 1 To 0 Step -1
            _ArrayDelete($g_aAllMomentaryDecibel, $aEmptyFields[$i])
        Next
    EndIf
    _ArrayDisplay($g_aAllMomentaryDecibel, "All sorted")
    ; AVERAGE MOMENTARY
    Local $iTresholdAbsolut = -70 ; alle Momentary unter -70dBFS sollen verworfen werden
    Local $iIndexTresholdAbsolut
    For $i = 0 To UBound($g_aAllMomentaryDecibel) - 1
        If $g_aAllMomentaryDecibel[$i] < $iTresholdAbsolut Then
            $iIndexTresholdAbsolut = $i ; ermittelt den ArrayIndex, ab dem Momentary nur noch unter -70dBFS zu finden sind
            ExitLoop
        EndIf
    Next
    Local $iLoudnessAverage ; durchschnittliche Lautheit ohne alle Werte unter -70dBFS
    Local $sRangeToDelete ; um im Array alle Werte unterhalb des Thresholds zu löschen
    If IsNumber($iIndexTresholdAbsolut) Then
        If $iIndexTresholdAbsolut = 0 Then ; alle Werte unter -70dBFS
            $iLoudnessAverage = "-INFINITE"
        Else
            $sRangeToDelete = $iIndexTresholdAbsolut & "-" & UBound($g_aAllMomentaryDecibel) - 1 ; Range ab dem Index Threshold Absolut bis zum Ende des Arrays
            ConsoleWrite("Delete Indicies Absolut: " & $sRangeToDelete & @CRLF)
            _ArrayDelete($g_aAllMomentaryDecibel, $sRangeToDelete) ; alle Werte unter -70dBFS löschen
            _ArrayDisplay($g_aAllMomentaryDecibel, "All minus -70")
            $iLoudnessAverage = _AverageDecibel($g_aAllMomentaryDecibel) ; Mittelwert der aller Momentary in Dezibel ermitteln
            $iLoudnessAverage = Round($iLoudnessAverage, 3) ; 3 Stellen nach dem Komma - bei Release nur noch 1 Stelle nach dem Komma
        EndIf
    Else ; nichts kleiner -70dBFS gefunden
        $iLoudnessAverage = _AverageDecibel($g_aAllMomentaryDecibel)
        $iLoudnessAverage = Round($iLoudnessAverage, 3)
    EndIf
    ConsoleWrite("LK Average: " & $iLoudnessAverage & @CRLF)
    ; INTEGRATED
    Local $iLoudnessIntegrated ; Lautheit Integrated
    If IsNumber($iLoudnessAverage) Then
        Local $iTresholdRelative = $iLoudnessAverage - 10 ; der Threshold für Integrated liegt 10dB unter dem Mittelwert - alle Werte darunter werden verworfen
        Local $iIndexTresholdRelative
        For $i = 0 To UBound($g_aAllMomentaryDecibel) - 1
            If $g_aAllMomentaryDecibel[$i] < $iTresholdRelative Then ; ermittelt ArrayIndex, ab dem Momentary kleiner Relativ-Threshold
                $iIndexTresholdRelative = $i
                ExitLoop
            EndIf
        Next
        If $iIndexTresholdRelative <> "" Then ; wenn Werte unterhalb des relativen Threshold gefunden werden
            $sRangeToDelete = $iIndexTresholdRelative & "-" & UBound($g_aAllMomentaryDecibel) - 1 ; Range ab dem Index Threshold Relativ bis zum Ende des Arrays
            ConsoleWrite("Delete Indicies Relative: " & $sRangeToDelete & @CRLF)
            _ArrayDelete($g_aAllMomentaryDecibel, $sRangeToDelete) ; alle Werte unter Threshold Relativ löschen
            _ArrayDisplay($g_aAllMomentaryDecibel, "All minus relative")
            $iLoudnessIntegrated = _AverageDecibel($g_aAllMomentaryDecibel) ; Mittelwert aller restlichen Momentary in Dezibel ermitteln
            $iLoudnessIntegrated = Round($iLoudnessIntegrated, 3) ; 3 Stellen nach dem Komma - bei Release nur noch 1 Stelle nach dem Komma
        Else ; keine Werte unterhalb Threshold Relativ
            $iLoudnessIntegrated = $iLoudnessAverage
        EndIf
    Else ; LK Average = "-INFINITE", also alle Samples unter -70dBFS
        $iLoudnessIntegrated = $iLoudnessAverage
    EndIf
    ConsoleWrite("LK Integrated: " & $iLoudnessIntegrated & @CRLF)
    Exit
    ; ############################################################
    Func _MeanSquare(ByRef $aInteger)
        Local $iNumerator ; Zähler
        For $i = 0 To UBound($aInteger) - 1
            $iNumerator += ($aInteger[$i] ^ 2) ; alle Samples erst quadrieren und dann addieren
        Next
        Local $iMeanSquare = Sqrt($iNumerator / UBound($aInteger)) ; alle quadrierten und addierten Samples durch die Anzahl Samples teilen und die Wurzel ziehen
        Return $iMeanSquare
    EndFunc   ;==>_MeanSquare
    
    Func _AdditionDecibel($aArray) ; math by http://personal.cityu.edu.hk/~bsapplec/manipula.htm - Addiert Dezibel
        If UBound($aArray) >= $g_CHANNEL_LFE Then
            _ArrayDelete($aArray, ($g_CHANNEL_LFE - 1))
        EndIf
    ;~     _ArrayDisplay($aArray)
        Local $iLog_1
        For $i = 0 To UBound($aArray) - 1
            $iLog_1 += (10 ^ ($aArray[$i] / 10))
        Next
        Local $iL_Addition = 10 * Log10($iLog_1)
        Return $iL_Addition
    EndFunc   ;==>_AdditionDecibel
    
    Func _AverageDecibel($aArray) ; math by http://personal.cityu.edu.hk/~bsapplec/manipula.htm - Errechnet den Mittelwert aus Dezibel-Werten
        Local $iAnzahl = UBound($aArray)
        Local $iLog_1
        For $i = 0 To UBound($aArray) - 1
            $iLog_1 += (10 ^ ($aArray[$i] / 10))
        Next
        $iLog_1 *= (1 / $iAnzahl)
        Local $iL_Average = 10 * Log10($iLog_1)
        Return $iL_Average
    EndFunc   ;==>_AverageDecibel
    
    Func Log10($fNb) ; Funktion für Logarithmus zur Basis 10 - AutoIt hat nur einen Logarithmus zur Basis 2: Log()
        Return Log($fNb) / Log(10)
    EndFunc   ;==>Log10
    
    Func _Decibel($iInteger)
    ;~     Return Round(10 * Log10($iInteger / (2 ^ ($iBitrate - 1))), 3) - 0.691 ; <--- das soll der richtige Algorithmus sein laut EBU und ITU, aber der macht viel zuviel Ergebnis (die setzen ihn evtl. an anderer Stelle ein)
        Return Round(20 * Log10($iInteger / (2 ^ ($iBitrate - 1))), 3) - 0.691 ; -0.691 ist ein LKFS-Korrektor laut EBU
    EndFunc   ;==>_Decibel
    
    Func _ErrorMessage($iError, $iExtended, $iScrpitLineNumber, $sMessage = "", $bForcedExit = False, $vVariable = 0, $sVariableName = "")
        Local $iFlag = 262148
        Local $sOutro = "Continue?"
        If $bForcedExit Then
            $iFlag = 262144
            $sOutro = "Program exits!"
        EndIf
        Local $iMB = MsgBox($iFlag, "Error", $sMessage & @CRLF & @CRLF & 'Debug Line: ' & $iScrpitLineNumber & @CRLF & 'Error: ' & $iError & @CRLF & 'Extended: ' & $iExtended & @CRLF & 'Variable: ' & $sVariableName & @CRLF & 'Content: ' & $vVariable & @CRLF & @CRLF & $sOutro)
        If $iMB = 7 Or $bForcedExit = True Then Exit
        Return
    EndFunc   ;==>_ErrorMessage
    Alles anzeigen

    Es gibt noch etwas, was man vielleicht generell mit bedenken sollte. Für die Berechnung der Lautheitsrange braucht man aus den 100ms-Momentary-Werten auch ein 3s-Fenster (und nicht nur das 400ms-Fenster für Integrated). Die Daten dürfen also nicht wieder zu früh entlassen werden, sondern auch das 3s-Fenster füllen.

    Was meinst Du mit der universalen Berechnung?

    Gruß, Conrad

  • R128 Lautheitsmesser

    • Simpel
    • 12. Februar 2018 um 00:19

    Moin Andy,

    da bin ich ja sehr gespannt drauf. Die Wav-Datei komplett einzulesen hatte ich auch überlegt, aber wenn das Ding mal ne Stunde oder mehr lang ist plus max. 6-8 Kanäle hat habe ich Sorge, dass das den Speicher überfüllt.

    Aber wie gesagt, ich freue mich auf Deine Ideen und bin gespannt, wie fix das werden kann.

    Gruß, Conrad

  • R128 Lautheitsmesser

    • Simpel
    • 10. Februar 2018 um 19:28

    Moin.

    Aufgrund einer PM von AndyG im englischsprachigen AutoIt-Forum habe ich mich entschlossen für mein Projekt in das deutsche Forum zu wechseln. Ich möchte einen Lautheitsmesser (offline als auch im Stream) programmieren. Grundlage sind EBU Tech 3341 für Lautheit allgemein, EBU Tech 3342 für Berechnung Lautheitsrange und ITU-R BS.1770-4 als Basis von Tech 3341.

    Einer meiner ersten Ansätze war dieser hier:

    AutoIt
    #include <Array.au3>
    #include <StringConstants.au3>
    #include <FileConstants.au3>
    
    Local $filename ; EBU-Test-Set: https://tech.ebu.ch/publications/ebu_loudness_test_set
    ;~ $filename = @ScriptDir & "\EBU-Test-Set\EBU-reference_listening_signal_pinknoise_500Hz_2kHz_R128.wav" ; 120 Sekunden
    $filename = @ScriptDir & "\EBU-Test-Set\1kHz Sine -20 LUFS-16bit.wav" ; 20 Sek
    ;~ $filename = @ScriptDir & "\EBU-Test-Set\1kHz Sine -26 LUFS-16bit.wav" ; 20 Sek
    ;~ $filename = @ScriptDir & "\EBU-Test-Set\1kHz Sine -40 LUFS-16bit.wav" ; 20 Sek
    ;~ $filename = @ScriptDir & "\EBU-Test-Set\seq-3341-12-24bit.wav" ; Piepen 10 Sekunden
    
    ; Read out file "metadata"
    Local $h = FileOpen($filename, $FO_BINARY) ; binary
    If $h = -1 Then _ErrorMessage(@error, @extended, @ScriptLineNumber - 1, "Could not open wav-file.", True, $h, "$h") ; ausführlichere Fehler-Meldung
    Local $sHeader = FileRead($h, 2000) ; 2000 Byte sollten für den Headerteil erstmal reichen
    Local $iPosition_fmt = StringInStr($sHeader, "666D7420") ; hier wird die Position von "fmt " ("666D7420" in HEX) gesucht - definierter Teil des WAV-Headers
    $iPosition_fmt = ($iPosition_fmt - 3) / 2 ; das Ergebnis wird in Position der Bytes gewandelt
    FileSetPos($h, $iPosition_fmt + 10, 0)
    Local $iChannels = Number(FileRead($h, 2)) ; fmt + 10, 2byte für Kanalanzahl
    ConsoleWrite('CH: ' & $iChannels & "   ")
    Local $iSamples = Number(FileRead($h, 4)) ; direkt danach, 4byte für die Samplerate
    ConsoleWrite('SR: ' & $iSamples & "   ")
    FileSetPos($h, $iPosition_fmt + 22, 0)
    Local $iBitrate = Number(FileRead($h, 2)) ; fmt + 22, 2byte für die Bitrate
    ConsoleWrite('BR: ' & $iBitrate & "   ")
    FileSetPos($h, $iPosition_fmt + 28, 0)
    Local $iLengthDataBlock = Number(FileRead($h, 4)) ; fmt + 28, 4 byte aus denen später die Länge des Files berechnet werden
    Local $i100msSampleCount = $iSamples / 10 ; Anzahl der Samples für 1/10 Sekunde - 100ms-Fenster - Verschiebung des 400ms-Fensters
    Local $iNumberOfAll100msRuns = Floor($iLengthDataBlock / (($iBitrate / 8) * $i100msSampleCount * $iChannels)) ; Anzahl aller 100ms Proben bis das ganze File gescannt ist
    ConsoleWrite("L: " & $iNumberOfAll100msRuns / 10 & "s   " & $filename & @CRLF)
    
    ; Declare further variable
    Local $iCounterOf100msRuns = 0 ; Zähler für jeden 100ms Durchgang
    Local $s100msReadOut ; 100ms ausgelesene Bytes aus dem File
    Local $a100msHexArray ; Array der 100ms Samples in Hex
    Local $iInteger ; aktuell ausgelesenes Sample
    Local $a100msInteger[0] ; Array aller Samples innerhalb eines 100ms-Fensters
    Local $a400msInteger[$i100msSampleCount * 4] ; Array aller Samples innerhalb des 400ms-Fenster für Lautheit Momentary
    Local $s100IntegerFilterKette ; String aller K-gefilterten Samples innerhalb eines 100ms-Fensters
    Local $xnK1_2, $xnK1_1, $ynK1_2, $ynK1, $ynK1_1, $xnK1 ; Variablen für K-Filter Stage 1 - x[n], x[n-1], x[n-2], y[n], y[n-1], y[n-2]
    Local $xnK2_2, $xnK2_1, $ynK2_2, $ynK2, $ynK2_1, $xnK2 ; Variablen für K-Filter Stage 2 - x[n], x[n-1], x[n-2], y[n], y[n-1], y[n-2]
    Local $iMeanSquare400ms ; Effektivwert aller 400ms-Samples
    Global $g_aAllMomentaryDecibel[$iNumberOfAll100msRuns - 3] ; die ersten drei 100ms-Fenster ergeben noch keine 400ms-Fenster zusammen, so daß noch kein Momentary-Wert berechnet werden kann
    Local $aActualMomentaryForAllChannel[0] ; enthält in Decibel den Effektivwert des aktuellen Momentary pro Kanal
    
    ; Start calculate all Momentary
    Local $hTimerStart = TimerInit() ; Start Zeitnahme Ermittelung sämtlicher Momentary
    ProgressOn("File-Scan - Length of file: " & $iNumberOfAll100msRuns / 10 & "s", "Please wait...", "", @DesktopWidth - 350, @DesktopHeight - 220) ; Progress während des Programmierens und Debuggings rechts unten in die Ecke um die _ArrayDisplays zu sehen
    While 1
        ProgressSet($iCounterOf100msRuns * 100 / $iNumberOfAll100msRuns, Floor($iCounterOf100msRuns * 100 / $iNumberOfAll100msRuns) & "%") ; Progress refreshen
        $s100msReadOut = FileRead($h, ($iBitrate / 8) * $i100msSampleCount * $iChannels) ; nächste 100ms des Files auslesen - $iBitrate/8 ergibt die Bytes pro Sample - mal die Anzahl der Kanäle, da die interleaved, also immer im Wechsel kommen
        If @extended < ($iBitrate / 8) * $i100msSampleCount * $iChannels Then ; wenn die Anzahl der ausgelesenen Bytes kleiner sind als für 100ms benötigt (das File ist also zu Ende)
            ExitLoop ; kein kompletter 100ms Readout mehr möglich, deshalb Daten verwerfen (laut R128)
        EndIf
        $s100msReadOut = StringTrimLeft($s100msReadOut, 2) ; "0x" entfernen um die Regex nicht zu verwirren
        $a100msHexArray = StringRegExp($s100msReadOut, "([\x00-\xff]{" & 2 * $iBitrate / 8 & "})", 3) ; sucht nach HEX-Werten 2 Zeichen pro Byte für Bitrate/8 Byte
    ;~     _ArrayDisplay($a100msHexArray,"Zeile " & @ScriptLineNumber)
        For $i = 0 To $i100msSampleCount - 1 ; für jedes Sample innerhalb 100ms
            For $j = 1 To 1;$iChannels - !!!!!!! nach Umbau von Arrays auf Variablen kann ich spontan erstmal nur einen Kanal berechnen, wenn dieser Part fertig ist, dann wird er pro Kanal dupliziert mit erweiterten Variablen
                $iInteger = $a100msHexArray[$i] ; nächster HEX-Wert
                $iInteger = _ChangeEndian($iInteger) ; aus LittleEndian BigEndian machen - AutoIt rechnet mit BigEndian-HEX
                $iInteger = Number($iInteger) ; Integer daraus machen
                $iInteger = _SignedInteger($iInteger, $iBitrate) ; Integer mit Vorzeichen daraus machen, da Audio Samples in positiven und negativen Werten in Samples gerechnet werden
                ; K-filter stage 1 - high shelving 1kHz +4dB
                $xnK1_2 = $xnK1_1 ; die Werte für x[n], x[n-1], x[n-2], y[n], y[n-1], y[n-2] stage 1 rücken eins weiter in die Vergangenheit
                $xnK1_1 = $xnK1
                $ynK1_2 = $ynK1_1
                $ynK1_1 = $ynK1
                $xnK1 = $iInteger
                $ynK1 = Int(1.53512485958697 * $xnK1 - 2.69169618940638 * $xnK1_1 + 1.19839281085285 * $xnK1_2 + 1.69065929318241 * $ynK1_1 - 0.73248077421585 * $ynK1_2) ; Koeffizienten für stage 1 hard gecoded und nicht als Variablen wegen Geschwindigkeit
                ; K-filter stage 2 - low cut 100Hz
                $xnK2_2 = $xnK2_1 ; die Werte für x[n], x[n-1], x[n-2], y[n], y[n-1], y[n-2] stage 2 rücken eins weiter in die Vergangenheit
                $xnK2_1 = $xnK2
                $ynK2_2 = $ynK2_1
                $ynK2_1 = $ynK2
                $xnK2 = $ynK1
                $ynK2 = Int($xnK2 - 2 * $xnK2_1 + $xnK2_2 + 1.99004745483398 * $ynK2_1 - 0.99007225036621 * $ynK2_2) ; Koeffizienten für stage 2 hard gecoded und nicht als Variablen wegen Geschwindigkeit
                $s100IntegerFilterKette &= $ynK2 & "|" ; gefiltertes Sample an die Kette hängen mit | als Trenner
            Next
        Next
        ; after all Samples needed for 100ms
        $s100IntegerFilterKette = StringTrimRight($s100IntegerFilterKette, 1) ; letztes | entfernen
        $a100msInteger = StringSplit($s100IntegerFilterKette, "|", $STR_NOCOUNT) ; ein Array aus der 100ms-Kette machen ohne Index
    ;~     _ArrayDisplay($a100msInteger, "IntegerKette")
        _ArrayDelete($a400msInteger, "0-" & ($i100msSampleCount - 1) & "") ; aus dem 400ms-Array (also Momentary) die obersten 100ms entfernen
        _ArrayAdd($a400msInteger, $a100msInteger) ; die aktuellen 100ms hinzufügen
    ;~     _ArrayDisplay($a400msInteger, "400ms")
        $iMeanSquare400ms = 0 ; Effektiv-Wert resetten
        If $iCounterOf100msRuns > 2 Then ; erst wenn die ersten 400ms voll sind (nach 3 Runden 100ms)
            ReDim $aActualMomentaryForAllChannel[$iChannels] ; !!! bei Surround > 5.0 wird von folgender Kanalreihenfolge ausgegangen L, R, C, LFE, Ls, Rs - Broadcast-Standard EBU
            For $i = 0 To $iChannels - 1 ; was passiert hier mit dem LFE, der nicht berechnet werden darf???????                          ######################
                If $i < 3 Then ; L R C
                    $aActualMomentaryForAllChannel[$i] = _Decibel(_MeanSquare($a400msInteger)) ; berechnet aus den gefilterten Samples den Effektivwert und rechnet das in Dezibel um
                ElseIf $i = 3 And $iChannels > 5 Then ; LFE
                    ; nothing
                Else ; Ls Rs
                    $aActualMomentaryForAllChannel[$i] = _Decibel(_MeanSquare($a400msInteger) * 1.41) ; die Surrounds werden mit 1,5dB oder Faktor 1,41 lauter bewertet
                EndIf
            Next
    ;~         _ArrayDisplay($aActualMomentaryForAllChannel)
            $iMeanSquare400ms = _AdditionDecibel($aActualMomentaryForAllChannel) ; Addition der Pegel aller Kanäle zu einem Wert
            $g_aAllMomentaryDecibel[$iCounterOf100msRuns - 3] = $iMeanSquare400ms
        EndIf
        $iCounterOf100msRuns += 1 ; Anzahl der durchgelaufenen 100ms Berechnungen um 1 erhöhen
        $s100IntegerFilterKette = "" ; Filterkette löschen
    WEnd
    FileClose($h) ; File wird nicht mehr gebraucht und geschlossen
    ProgressOff()
    ConsoleWrite("Timer: " & Round(TimerDiff($hTimerStart) / 1000) & @CRLF) ; dieses war der zeitkritische Bereich, da die meisten Berechnungen hier mit den Samples oder alle 100ms berechnet werden
    
    _ArraySort($g_aAllMomentaryDecibel, 1) ; damit die niedrigen Werte unten liegen
    _ArrayDisplay($g_aAllMomentaryDecibel, "All sorted")
    Local $iTresholdAbsolut = -70 ; alle Momentary unter -70dBFS sollen verworfen werden
    Local $iIndexTresholdAbsolut
    For $i = 0 To UBound($g_aAllMomentaryDecibel) - 1
        If $g_aAllMomentaryDecibel[$i] < $iTresholdAbsolut Then
            $iIndexTresholdAbsolut = $i ; ermittelt den ArrayIndex, ab dem Momentary nur noch unter -70dBFS zu finden sind
            ExitLoop
        EndIf
    Next
    Local $iLoudnessAverage ; durchschnittliche Lautheit ohne alle Werte unter -70dBFS
    Local $sRangeToDelete ; um im Array alle Werte unterhalb des Thresholds zu löschen
    If IsNumber($iIndexTresholdAbsolut) Then
        If $iIndexTresholdAbsolut = 0 Then ; alle Werte unter -70dBFS
            $iLoudnessAverage = "-INFINITE"
        Else
            $sRangeToDelete = $iIndexTresholdAbsolut & "-" & UBound($g_aAllMomentaryDecibel) - 1 ; Range ab dem Index Threshold Absolut bis zum Ende des Arrays
            ConsoleWrite("Delete Indicies Absolut: " & $sRangeToDelete & @CRLF)
            _ArrayDelete($g_aAllMomentaryDecibel, $sRangeToDelete) ; alle Werte unter -70dBFS löschen
            _ArrayDisplay($g_aAllMomentaryDecibel, "All minus -70")
            $iLoudnessAverage = _AverageDecibel($g_aAllMomentaryDecibel) ; Mittelwert der aller Momentary in Dezibel ermitteln
            $iLoudnessAverage = Round($iLoudnessAverage, 3) ; 3 Stellen nach dem Komma - bei Release nur noch 1 Stelle nach dem Komma
        EndIf
    Else ; nichts kleiner -70dBFS gefunden
        $iLoudnessAverage = _AverageDecibel($g_aAllMomentaryDecibel)
        $iLoudnessAverage = Round($iLoudnessAverage, 3)
    EndIf
    ConsoleWrite("LK Average: " & $iLoudnessAverage & @CRLF)
    
    Local $iLoudnessIntegrated ; Lautheit Integrated
    If IsNumber($iLoudnessAverage) Then
        Local $iTresholdRelative = $iLoudnessAverage - 10 ; der Threshold für Integrated liegt 10dB unter dem Mittelwert - alle Werte darunter werden verworfen
        Local $iIndexTresholdRelative
        For $i = 0 To UBound($g_aAllMomentaryDecibel) - 1
            If $g_aAllMomentaryDecibel[$i] < $iTresholdRelative Then ; ermittelt ArrayIndex, ab dem Momentary kleiner Relativ-Threshold
                $iIndexTresholdRelative = $i
                ExitLoop
            EndIf
        Next
        If $iIndexTresholdRelative <> "" Then ; wenn Werte unterhalb des relativen Threshold gefunden werden
            $sRangeToDelete = $iIndexTresholdRelative & "-" & UBound($g_aAllMomentaryDecibel) - 1 ; Range ab dem Index Threshold Relativ bis zum Ende des Arrays
            ConsoleWrite("Delete Indicies Relative: " & $sRangeToDelete & @CRLF)
            _ArrayDelete($g_aAllMomentaryDecibel, $sRangeToDelete) ; alle Werte unter Threshold Relativ löschen
            _ArrayDisplay($g_aAllMomentaryDecibel, "All minus relative")
            $iLoudnessIntegrated = _AverageDecibel($g_aAllMomentaryDecibel) ; Mittelwert aller restlichen Momentary in Dezibel ermitteln
            $iLoudnessIntegrated = Round($iLoudnessIntegrated, 3) ; 3 Stellen nach dem Komma - bei Release nur noch 1 Stelle nach dem Komma
        Else ; keine Werte unterhalb Threshold Relativ
            $iLoudnessIntegrated = $iLoudnessAverage
        EndIf
    Else ; LK Average = "-INFINITE", also alle Samples unter -70dBFS
        $iLoudnessIntegrated = $iLoudnessAverage
    EndIf
    ConsoleWrite("LK Integrated: " & $iLoudnessIntegrated & @CRLF)
    Exit
    
    
    #Region - Funcs
    Func _MeanSquare(ByRef $aInteger)
        Local $iNumerator ; Zähler
        For $i = 0 To UBound($aInteger) - 1
            $iNumerator += ($aInteger[$i] ^ 2) ; alle Samples erst quadrieren und dann addieren
        Next
        Local $iMeanSquare = Sqrt($iNumerator / UBound($aInteger)) ; alle quadrierten und addierten Samples durch die Anzahl Samples teilen und die Wurzel ziehen
        Return $iMeanSquare
    EndFunc   ;==>_MeanSquare
    
    Func _AdditionDecibel($aArray) ; math by http://personal.cityu.edu.hk/~bsapplec/manipula.htm - Addiert Dezibel
        Local $iLog_1
        For $i = 0 To UBound($aArray) - 1
            $iLog_1 += (10 ^ ($aArray[$i] / 10))
        Next
        Local $iL_Addition = 10 * Log10($iLog_1)
        Return $iL_Addition
    EndFunc   ;==>_AdditionDecibel
    
    Func _AverageDecibel($aArray) ; math by http://personal.cityu.edu.hk/~bsapplec/manipula.htm - Errechnet den Mittelwert aus Dezibel-Werten
        Local $iAnzahl = UBound($aArray)
        Local $iLog_1
        For $i = 0 To UBound($aArray) - 1
            $iLog_1 += (10 ^ ($aArray[$i] / 10))
        Next
        $iLog_1 *= (1 / $iAnzahl)
        Local $iL_Average = 10 * Log10($iLog_1)
        Return $iL_Average
    EndFunc   ;==>_AverageDecibel
    
    Func Log10($fNb) ; Funktion für Logarithmus zur Basis 10 - AutoIt hat nur einen Logarithmus zur Basis 2: Log()
        Return Log($fNb) / Log(10)
    EndFunc   ;==>Log10
    
    Func _Decibel($iInteger)
    ;~     Return Round(10 * Log10($iInteger / (2 ^ ($iBitrate - 1))), 3) - 0.691 ; <--- das soll der richtige Algorithmus sein laut EBU und ITU, aber der macht viel zuviel Ergebnis (die setzen ihn evtl. an anderer Stelle ein)
        Return Round(20 * Log10($iInteger / (2 ^ ($iBitrate - 1))), 3) - 0.691 ; -0.691 ist ein LKFS-Korrektor laut EBU
    EndFunc   ;==>_Decibel
    
    Func _SignedInteger($iInteger, $iBitrate)
        If $iInteger > ((2 ^ ($iBitrate - 1)) - 1) Then ; wenn Wert größer als die Hälfte der gesamten Integer (dann sind es die negativen Samples
            $iInteger = Number($iInteger - (2 ^ $iBitrate)) ; soll die untere Hälfte ein negatives Vorzeichen bekommen - ist wird sonst automatisch Unsigned Integer angenommen
        Else
            $iInteger = Number($iInteger)
        EndIf
        Return $iInteger
    EndFunc   ;==>_SignedInteger
    
    Func _ChangeEndian($iHex)
        Local $iChangedEndian
        For $i = 1 To StringLen($iHex) / 2
            $iChangedEndian &= StringRight($iHex, 2) ; die hinteren nach vorne setzen
            $iHex = StringTrimRight($iHex, 2) ; vom ursprünglichen gesamten LittleEndian-Hex-wert die ersten beiden Stellen löschen
        Next
        Return "0x" & $iChangedEndian
    EndFunc   ;==>_ChangeEndian
    
    Func _ErrorMessage($iError, $iExtended, $iScrpitLineNumber, $sMessage = "", $bForcedExit = False, $vVariable = 0, $sVariableName = "")
        Local $iFlag = 262148
        Local $sOutro = "Continue?"
        If $bForcedExit Then
            $iFlag = 262144
            $sOutro = "Program exits!"
        EndIf
        Local $iMB = MsgBox($iFlag, "Error", $sMessage & @CRLF & @CRLF & 'Debug Line: ' & $iScrpitLineNumber & @CRLF & 'Error: ' & $iError & @CRLF & 'Extended: ' & $iExtended & @CRLF & 'Variable: ' & $sVariableName & @CRLF & 'Content: ' & $vVariable & @CRLF & @CRLF & $sOutro)
        If $iMB = 7 Or $bForcedExit = True Then Exit
        Return
    EndFunc   ;==>_ErrorMessage
    
    #cs ; dieses war die ursprüngliche Funktion für K-Filter Stage 1 und 2 - da das Kopieren in eine Funktion aber relativ viel Zeit in Anspruch nimmt (und zwar für jedes einzelne Sample) wird diese Berechnung hard gecoded
        Func _K_Filter_Stage_1($xn, $xn_1, $xn_2, $yn_1, $yn_2)
        ;Global Const $g_a1K1 = -1.69065929318241
        ;Global Const $g_a2K1 = 0.73248077421585
        ;Global Const $g_b0K1 = 1.53512485958697
        ;Global Const $g_b1K1 = -2.69169618940638
        ;Global Const $g_b2K1 = 1.19839281085285
    
        ;Local $yn = $g_b0K1 * $xn + $g_b1K1 * $xn_1 + $g_b2K1 * $xn_2 - $g_a1K1 * $yn_1 - $g_a2K1 * $yn_2
        Local $yn = $g_b0K1 * $xn + $g_b1K1 * $xn_1 + $g_b2K1 * $xn_2 - $g_a1K1 * $yn_1 - $g_a2K1 * $yn_2
        Return Int($yn)
        EndFunc
    
        Func _K_Filter_Stage_2($xn, $xn_1, $xn_2, $yn_1, $yn_2)
        ;Global Const $g_a1K2 = -1.99004745483398 ; -199004745483398  14 Nullen
        ;Global Const $g_a2K2 = 0.99007225036621 ; 14 Nullen
        ;Global Const $g_b0K2 = 1.0
        ;Global Const $g_b1K2 = -2.0
        ;Global Const $g_b2K2 = 1.0
    
        Local $yn = $g_b0K2 * $xn + $g_b1K2 * $xn_1 + $g_b2K2 * $xn_2 - $g_a1K2 * $yn_1 - $g_a2K2 * $yn_2
        ;~     Local $yn = $xn - 2 * $xn_1 + $xn_2 + 199004745483398 * $yn_1 - 99007225036621 * $yn_2 / 1e28
        Return Int($yn)
        EndFunc
    #ce
    #EndRegion - Funcs
    Alles anzeigen

    In diesem Code fehlt noch die Berechnung für alle Kanäle größer 1 (wegen eines Umbau des Codes erstmal weggefallen). Es wird auch noch kein 3s-Fenster berechnet, daß nötig wäre für die Lautheitsrange. Auch TruePeak ist noch nicht programmiert. Das ist alles nachrangig, denn die Berechnung für 2-kanaliges Stereo (die aufwändiges K-Filter werden nämlich schon für alle Kanäle berechnet) dauert etwas mehr als doppelte Echtzeit. Das ist natürlich nicht akzeptabel.

    Hat irgendwer Ideen, wie sich die Rechenzeit runter bekommen läßt? Richtig auswirken würden sich Verbesserungen des Codes erstmal nur zwischen While1 - Wend. Denn diese Schleife berechnet alle Samples des Files.

    Was ich zur Geschwindigkeitsoptimierung bereits herausgefunden und zum größten Teil beherzigt habe ist:

    - Schreiben und Lesen in Variablen geht deutlich schneller als in Arrays

    - Funktionsaufrufe für "kleine" aber häufige Berechnungen fressen mehr Zeit als hart im Main-Skript gecoded

    Gruß, Conrad

  • Geschwindigkeit ist (k)eine Hexerei oder wo läuft der Code?

    • Simpel
    • 9. November 2017 um 13:18

    Moin.

    Bei mir war es das gemappte Laufwerk.

    Siehe auch hier: https://www.autoitscript.com/forum/topic/18…very-long-time/

    Gruß, Conrad

  • Geschwindigkeit ist (k)eine Hexerei oder wo läuft der Code?

    • Simpel
    • 9. November 2017 um 10:36

    Moin.

    Ich habe festgestellt, daß z.B. für PDFtk die Ausführung auf Netzlaufwerken die Festlegung eines Arbeitsverzeichnisses auf dem Laufwerk zu erheblichen Geschwindigkeitszuwächsen führt.

    Gruß, Conrad

  • GUICtrlClock

    • Simpel
    • 26. September 2017 um 21:17

    Moin.

    Ich habe die UDF so modifiziert, damit die Punkte blinken oder nicht blinken können:

    AutoIt
    ;===============================================================================
    ; Function Name:   _GUICtrlClock_SetTime
    ; Description:     Mit dieser Funktion wird die Zeit eingetragen und die Doppelpunkte
    ;                  blinken. Dazu muss diese Funktion aber regelmaessig aufgerufen
    ;                  werden (am besten mittels "_Timer_SetTimer()" alle 100 ms).
    ; Parameter(s):    $aidClock ist das Rueckgabe-Array von _GUICtrlClock_Create
    ;                  $sTime ist ein DATE/TIME-String im Format: YYYY/MM/DD HH:MM:SS
    ;                  $bBlink ist ein Bool - True wenn die Doppelpunkte blinken sollen - ######## hinzugefügt
    ; Requirement(s):  ---
    ; Return Value(s): Bei Erfolg = 1, ansonsten 0 und @error = 1
    ; Author(s):       Oscar (www.autoit.de)
    ;===============================================================================
    Func _GUICtrlClock_SetTime(ByRef $aidClock, $sTime = Default, $bBlink = True) ; ######## letzten Parameter hinzugefügt
        If Not IsArray($aidClock) Then Return SetError(1, 0, 0)
        Local Enum $H1 = 12, $H2, $M1 = 15, $M2, $S1 = 18, $S2
        If $sTime = '' Or $sTime = Default Then $sTime = StringFormat('%04d/%02d/%02d %02d:%02d:%02d', @YEAR, @MON, @WDAY, @HOUR, @MIN, @SEC)
        Local $aTime[6] = [ _
                StringMid($sTime, $H1, 1), StringMid($sTime, $H2, 1), _
                StringMid($sTime, $M1, 1), StringMid($sTime, $M2, 1), _
                StringMid($sTime, $S1, 1), StringMid($sTime, $S2, 1)]
        Local $fBlink = (BitAND(GUICtrlGetState($aidClock[6]), $GUI_SHOW) = $GUI_SHOW)
        If GUICtrlRead($aidClock[5]) <> $aTime[5] Or TimerDiff($aidClock[10]) - $aidClock[11] > 500 Then
            $aidClock[11] = TimerDiff($aidClock[10])
            If $bBlink Then $fBlink = Not $fBlink ; ######### If Then ergänzt
            For $i = 6 To 9
                GUICtrlSetState($aidClock[$i], $fBlink ? $GUI_SHOW : $GUI_HIDE)
            Next
        EndIf
        For $i = 0 To 5
            If GUICtrlRead($aidClock[$i]) <> $aTime[$i] Then GUICtrlSetData($aidClock[$i], $aTime[$i])
        Next
        Return 1
    EndFunc   ;==>_GUICtrlClock_SetTime
    Alles anzeigen

    Die Zeile Code im Example wäre dann so:

    AutoIt
    _GUICtrlClock_SetTime($aClock1, Default, False)

    Gruß, Conrad

  • Forenupdate - September 2017 - Probleme / Anregungen / Feedback - Sammelthread

    • Simpel
    • 18. September 2017 um 11:34

    Alles klar. Jetzt reagiert es wie gewohnt. Dann muss ich tatsächlich exakt den Zeitpunkt erwischt haben, als es wieder online war. Als ich dann gestern statt die "ungelesen"-URL zu refreshen nämlich nur noch die Domain eintippte war ich wieder auf dem Forum.

  • Forenupdate - September 2017 - Probleme / Anregungen / Feedback - Sammelthread

    • Simpel
    • 18. September 2017 um 11:20

    Ich hate die ganze Zeit https://autoit.de/index.php?unread-thread-list/ im Browser und habe nur refreshed. Wenn keine Themen waren hat die Software die Seite angezeigt, jedoch ohne Themen (was ja klar ist). Gestern dann fraß sich der Link fest. Nach dem Refreshen wurde mir gar nichts mehr angezeigt, es gab allerdings auch nicht den üblichen Timeout "konnte nicht gefunden werden".

    Ich werde jetzt mal alle "ungelesenen" lesen und dann mal beobachten, was dann passiert.

  • Forenupdate - September 2017 - Probleme / Anregungen / Feedback - Sammelthread

    • Simpel
    • 18. September 2017 um 02:59

    Moin.

    Seit ein paar Stunden finde ich nicht mehr die "Ungelesenen" Themen. Sind die verschwunden oder nur woanders hin gewandert?

    Gruß, Conrad

  • Autoit Programm mit Hilfe der Seite virustotal.com Scannen

    • Simpel
    • 26. August 2017 um 15:04

    Moin.

    Das kommt bei Virustotal leider oft vor. Eine Erklärung dazu kann man auf Englisch hier finden: http://www.csoonline.com/article/321676…as-harmful.html

    Ob dann am Ende die echten Virusscanner auf dem Rechner auch anschlagen ist nicht immer klar (bei Virustotal sind öfter auch andere Versionen im Einsatz als dann im echten Leben). Bei uns auf Arbeit reagiert der Virusscanner z.B. nicht darauf.

    Gruß, Conrad

Spenden

Jeder Euro hilft uns, Euch zu helfen.

Download

AutoIt Tutorial
AutoIt Buch
Onlinehilfe
AutoIt Entwickler
  1. Datenschutzerklärung
  2. Impressum
  3. Shoutbox-Archiv
Community-Software: WoltLab Suite™