Results 1 to 7 of 7

Thread: failing to fail

  1. #1
    thinBasic MVPs
    Join Date
    May 2007
    Location
    UK
    Posts
    1,433
    Rep Power
    162

    failing to fail

    I'm working on a console script to run as a test bed for new routines but the pre parsing phase seems to be jump out if a variable is repeated or if keywords are used in the wrong place, this behaviour is as expected.

    The issue is I get no error report why it closed.

    I am currently blocking out sections of code and putting msgbox in several locations to find out where it fails
    Amiga 500
    Amiga 600 x 4
    Amiga 1200

    Windows stuff

  2. #2
    thinBasic author ErosOlmi's Avatar
    Join Date
    Sep 2004
    Location
    Milan - Italy
    Age
    58
    Posts
    8,890
    Rep Power
    10
    What thinBasic version are you using?
    Are you using latest 1.14 beta from here: https://www.thinbasic.com/community/...-1-14-0-0-BETA

    Have you a simple script showing the problem?
    I'm not able to simulate what you are experiencing at the moment.

    The only situation in which runtime error should not come out is when using interpolation function $ with some code execution inside a string.
    Last edited by ErosOlmi; 13-02-2026 at 06:14.
    www.thinbasic.com | www.thinbasic.com/community/ | help.thinbasic.com
    Windows 10 Pro for Workstations 64bit - 32 GB - Intel(R) Xeon(R) W-10855M CPU @ 2.80GHz - NVIDIA Quadro RTX 3000

  3. #3
    thinBasic MVPs
    Join Date
    May 2007
    Location
    UK
    Posts
    1,433
    Rep Power
    162
    not really short. Yes the beta.

    It was from an AI generated script, the output is great it doesnt follow keyword structure properly. It was supposed to be a quick way of generating some code.

    I have been tweaking the code as I go so dont expect the code to be very good.

    the subroutine MinMaxOptimizePhases seems to be my current point of failure.

    Debug opens and then just closes and the same with running the script.

    ' *****************************************************************************' Multisine Generator (Log Spaced, Min–Max Phase Optimization)
    ' - Frequency range: 1 mHz → 10 kHz (logarithmic spacing)
    ' - User-selectable number of tones (1–32)
    ' - User-selectable uniform amplitude (example: 1.0)
    ' - Min–Max phase optimization to reduce the maximum absolute sample (peak)
    ' *****************************************************************************
    USES "CONSOLE"
    USES "iComplex"
    
    
    %MAX_ENTRIES = 32
    
    
    ' -----------------------------
    ' Configuration
    ' -----------------------------
    LOCAL nSamples AS LONG   value = 1024         ' Increase for wider time window (benefits very low f)
    LOCAL fs       AS DOUBLE value = 50000        ' Must exceed 2 * fMax (Nyquist). Here fMax=10 kHz -> fs >= 20 kHz
    LOCAL pi       AS DOUBLE value = 4 * ATN(1)
    
    
    ' Min–Max optimizer settings
    LOCAL MAX_ITERS AS LONG  value  = 200         ' Iteration cap
    LOCAL TOL       AS DOUBLE Value = 1e-9        ' Stop if improvement < TOL
    
    
    ' Frequency range (log spaced)
    LOCAL fMin  AS DOUBLE value = 0.001   ' 1 mHz
    LOCAL fMax  AS DOUBLE value = 10000   ' 10 kHz
    
    
    ' Generated signal
    LOCAL Signal(nSamples) AS DOUBLE
    
    
    ' Generic variable
    LOCAL i , j , n  AS LONG   value = 0
    
    
    Console_SetCP(%CP_UTF8)               ' Set Input codepage to UTF8
    Console_SetOutputCP(%CP_UTF8)         ' Set Output codepage to UTF8
    
    
    ' -----------------------------
    ' User input: tone count and amplitude
    ' -----------------------------
    LOCAL activeCount AS LONG
    PRINT $CRLF & "Enter number of output frequencies (1-32): " : activecount = VAL(Console_ReadLine())
    IF activeCount < 1 OR activeCount > %MAX_ENTRIES THEN
        PRINTL "Invalid value. Must be 1–32."
        waitkey
        stop
    END IF
    
    
    LOCAL userAmp AS DOUBLE
    PRINT $CRLF & "Enter uniform amplitude for all tones (e.g., 1): " :  UserAmp = VAL(Console_ReadLine())
    IF userAmp <= 0 THEN userAmp = 1
    
    
    ' -----------------------------
    ' Data structures
    ' -----------------------------
    TYPE tFreqEntry
        f   AS DOUBLE
        amp AS DOUBLE
        ph  AS DOUBLE
    END TYPE
    
    
    LOCAL FreqTable(%MAX_ENTRIES) AS tFreqEntry
    
    
    ' -----------------------------
    ' Build logarithmically spaced frequency table
    ' f(k) = exp( log(fMin) + (k-1)/(N-1) * (log(fMax) - log(fMin)) )
    ' -----------------------------
    IF activeCount = 1 THEN
        FreqTable(1).f   = fMin
        FreqTable(1).amp = userAmp
        FreqTable(1).ph  = 0
    ELSE
        LOCAL dlogMin AS DOUBLE : dlogMin = LOG(fMin)
        LOCAL dlogMax AS DOUBLE : dlogMax = LOG(fMax)
        LOCAL dstep   AS DOUBLE : dstep   = (dlogMax - dlogMin) / (activeCount - 1)
        FOR i = 1 TO activeCount
            FreqTable(i).f   = EXP(dlogMin + (i - 1) * dstep)
            FreqTable(i).amp = userAmp
            FreqTable(i).ph  = 0                  ' Start phases at 0 for optimization
        NEXT
    END IF
    '
    ' -----------------------------
    ' Sanity checks
    ' -----------------------------
    IF fs < 2 * fMax THEN
        PRINTL "WARNING: fs < 2*fMax (Nyquist). Increase fs to at least " & (2 * fMax) & " Hz."
    END IF
    IF nSamples < 2 THEN
        PRINTL "ERROR: nSamples must be >= 2"
        END
    END IF
    
    
    ' -----------------------------
    ' Run optimization, synthesize, and report
    ' -----------------------------
    
    
    msgbox 0,"before"
    CALL MinMaxOptimizePhases(Signal,nSamples)
    
    
    ' Compute final stats
    'LOCAL dpeakVal AS DOUBLE value = 0
    'LOCAL dsumSq   AS DOUBLE value = 0
    
    
    'LOCAL dRMS     AS DOUBLE Value = 0
    
    
    msgbox 0," heelo"
    
    
    FOR i = 1 TO nSamples
        IF ABS(Signal(i)) > dpeakVal THEN dpeakVal = ABS(Signal(i))
        dsumSq = dsumSq + (Signal(i) * Signal(i))
    NEXT
    
    
    IF nSamples > 0 THEN
      drms = SQR(dsumSq / nSamples)
    ELSE 
      drms = 0
    END IF
    
    
    
    
    
    
    '
    ' -----------------------------
    ' Output table and stats
    ' -----------------------------
    PRINTL ""
    PRINTL "=== Multisine Configuration ==="
    'PRINTL "Samples: " & nSamples & ", fs: " & fs & " Hz"
    'PRINTL "Active tones: " & activeCount & ", Uniform amplitude: " & userAmp
    'PRINTL "Frequency range: " & fMin & " Hz to " & fMax & " Hz (log-spaced)"
    '
    'PRINTL ""
    'PRINTL "=== Frequency Table ==="
    'FOR i = 1 TO activeCount
    '    PRINTL USING$("Tone ##:  F=#########.######## Hz   Amp=#.###   Phi=#.###### rad", _
    '                  i, FreqTable(i).f, FreqTable(i).amp, FreqTable(i).ph)
    'NEXT
    '
    'PRINTL ""
    'PRINTL "=== Signal Stats ==="
    'PRINTL "Peak: " & FORMAT$(peakVal, "#.######")
    'PRINTL "RMS : " & FORMAT$(rms,    "#.######")
    'IF rms > 0 THEN
    '    PRINTL "Crest Factor: " & FORMAT$(peakVal / rms, "#.######") & " (" & FORMAT$(20 * LOG(peakVal / rms) / LOG(10), "#.##") & " dB)"
    'ELSE
    '    PRINTL "Crest Factor: N/A (RMS=0)"
    'END IF
    '
    'MSGBOX 0, "Multisine (log-spaced) with Min–Max phase optimization complete." & $CRLF & _
    '           "Tones: " & activeCount & ", Amp: " & FORMAT$(userAmp, "#.###") & $CRLF & _
    '           "Peak=" & FORMAT$(peakVal, "#.####") & ", RMS=" & FORMAT$(rms, "#.####")
    '           
    '
    ' -----------------------------
    ' Helper: compute signal samples given current phases
    ' -----------------------------
    
    
    SUB ComputeSignal(byref Signal(),byval nSamples)
    '  LOCAL i , j    AS LONG
    '  LOCAL t, theta AS DOUBLE
    '  LOCAL s AS DOUBLE
    
    
      msgbox 0, "compute"
      
      FOR i = 1 TO nSamples
        t = (i - 1) / fs
        ' Direct real sum; complex not required for real signal
        s = 0
        FOR j = 1 TO activeCount
          theta = 2 * pi * FreqTable(j).f * t + FreqTable(j).ph
          s = s + FreqTable(j).amp * COS(theta)
        NEXT
        Signal(i) = s
      NEXT
    END SUB
    '
    '
    '' -----------------------------
    '' Helper: crest factor computation
    '' -----------------------------
    'FUNCTION CrestFactorDB() AS DOUBLE
    '    LOCAL i AS LONG
    '    LOCAL peakVal AS DOUBLE, sumSq AS DOUBLE
    '    peakVal = 0 : sumSq = 0
    '    FOR i = 1 TO nSamples
    '        IF ABS(Signal(i)) > peakVal THEN peakVal = ABS(Signal(i))
    '        sumSq = sumSq + Signal(i) * Signal(i)
    '    NEXT
    '    LOCAL rms AS DOUBLE : rms = SQR(sumSq / nSamples)
    '    IF rms = 0 THEN
    '        FUNCTION = 0
    '    ELSE
    '        FUNCTION = 20 * LOG(peakVal / rms) / LOG(10)  ' CF in dB
    '    END IF
    'END FUNCTION
    
    
     -----------------------------
    ' Min–Max Phase Optimization
    ' Goal: minimize max |Signal| over the finite window by adjusting phases.
    ' Approach: Greedy coordinate updates focused at the current worst (peak) sample.
    ' For the current peak sample t*, for each tone k:
    '   s(t*) = R + A_k * cos(theta_k + phi_k), solve phi_k to minimize |s(t*)|.
    '   Optimal at that t*: cos(theta_k + phi_k) = clamp(-R / A_k, -1, 1).
    ' Iterate until improvement < TOL or MAX_ITERS reached.
    ' -----------------------------
    SUB MinMaxOptimizePhases(byref Signal(), nSamples)
    '    LOCAL it      AS LONG
    '    LOCAL i, k    AS LONG
    '    LOCAL imax    AS LONG
    '    LOCAL oldPeak, newPeak, sVal AS DOUBLE
    '    LOCAL tstar, theta_k   AS DOUBLE
    '    LOCAL R, A AS DOUBLE
    '    LOCAL c AS DOUBLE
    
    
    msgbox 0," MINMAX"
        ' Initial signal
        CALL ComputeSignal(signal,nSamples)
    
    
    
    
        ' Measure initial peak
        oldPeak = 0
        FOR i = 1 TO nSamples
            IF ABS(Signal(i)) > oldPeak THEN oldPeak = ABS(Signal(i))
        NEXT
    
    
        FOR it = 1 TO MAX_ITERS
    '        ' Find index of current worst sample
    '        imax = 1 : newPeak = ABS(Signal(1))
    '        FOR i = 2 TO nSamples
    '            sVal = ABS(Signal(i))
    '            IF sVal > newPeak THEN
    '                newPeak = sVal
    '                imax = i
    '            END IF
    '        NEXT
    '
    '        ' If peak improvement is tiny, stop
    '        IF it > 1 THEN
    '            IF oldPeak - newPeak < TOL THEN EXIT FOR
    '        END IF
    '        oldPeak = newPeak
    '
    '        ' Time at peak
    '        tstar = (imax - 1) / fs
    '
    '        ' For each tone, adjust phase to reduce the peak at tstar
    '        FOR k = 1 TO activeCount
    '            ' Residual excluding tone k at tstar
    '            ' s(t*) = sum_j A_j cos(theta_j + phi_j)
    '            ' R = s(t*) - A_k cos(theta_k + phi_k)
    '            theta_k = 2 * pi * FreqTable(k).f * tstar + FreqTable(k).ph
    '            A = FreqTable(k).amp
    '            R = Signal(imax) - A * COS(theta_k)
    '
    '            ' Best (local) choice at t* in the min-max sense:
    '            ' cos(theta_k + newPhi) = clamp( -R / A, -1, 1 )
    '            IF A > 0 THEN
    '                c = -R / A
    '                IF c > 1 THEN c = 1
    '                IF c < -1 THEN c = -1
    '
    '                ' Choose phase giving that cosine at t*
    '                ' newPhi = arccos(c) - (2*pi*f_k*t*), but theta_k = 2*pi*f_k*t* + oldPhi,
    '                ' -> newPhi = arccos(c) - 2*pi*f_k*t*
    '                ' We'll directly update FreqTable(k).ph
    '                FreqTable(k).ph = ACOS(c) - (2 * pi * FreqTable(k).f * tstar)
    '                ' Optional: keep phase in [-pi, pi] for neatness (cos periodic, not required)
    '                IF FreqTable(k).ph > pi THEN FreqTable(k).ph = FreqTable(k).ph - 2 * pi
    '                IF FreqTable(k).ph < -pi THEN FreqTable(k).ph = FreqTable(k).ph + 2 * pi
    '            END IF
    '        NEXT
    '
    '        ' Recompute signal after updating all phases
    '        CALL ComputeSignal()
    '    NEXT
    END SUB
    
    Last edited by Michael Clease; 16-02-2026 at 15:29.
    Amiga 500
    Amiga 600 x 4
    Amiga 1200

    Windows stuff

  4. #4
    Senior Member Lionheart008's Avatar
    Join Date
    Sep 2008
    Location
    Germany, Bad Sooden-Allendorf
    Age
    53
    Posts
    948
    Rep Power
    112
    ' may be a little help from lionheart :-)

    ' ============================================
    ' Simple Phase Optimization Example
    ' ============================================
    
    Uses "Console"
    
    ' --- Globale Variablen ---
    Global phases() As Double
    Global signalValue As Double
    
    ' ============================================
    ' MAIN
    ' ============================================
    
    Function TBMain()
    
        Local max_iters As Long
        
        max_iters = 50   
        
        ' Array initialisieren
        ReDim phases(10)   ' 10 Phasen (1-10)
        
        InitializePhases()
        
        OptimizePhases(max_iters)
        
        PrintL "Final Signal Value: "; signalValue
        WaitKey
        
    End Function
    
    
    ' ============================================
    ' Initialize phases with random values
    ' ============================================
    
    Sub InitializePhases()
        
        Local i As Long
        
        Randomize Timer
        
        For i = 1 To UBound(phases) ' not 0 to ubound(phases)
            phases(i) = Rnd * 360   ' Phase in Grad
        Next i
        
    End Sub
    
    
    ' ============================================
    ' Optimization Loop
    ' ============================================
    
    Sub OptimizePhases(ByVal max_iters As Long)
    
        Local iter As Long
        
        If max_iters <= 0 Then Exit Sub
        
        For iter = 1 To max_iters
            
            UpdatePhases()
            
            ' Recompute signal after updating all phases
            ComputeSignal()
            
            PrintL "Iteration " & iter & " -> Signal = " & signalValue
            
        Next iter
    
    End Sub
    
    
    ' ============================================
    ' Update phases (dummy logic)
    ' ============================================
    
    Sub UpdatePhases()
    
        Local i As Long
        
        For i = 1 To UBound(phases)
            ' Kleine zufällige Änderung
            phases(i) = phases(i) + (Rnd - 0.5) * 5
        Next i
        
    End Sub
    
    
    ' ============================================
    ' Compute signal (dummy calculation)
    ' ============================================
    
    Sub ComputeSignal()
    
        Local i As Long
        signalValue = 0
        
        For i = 1 To UBound(phases) 
            signalValue = signalValue + Cos(phases(i) * 3.14159265 / 180)
        Next i
    
    End Sub
    
    Last edited by Lionheart008; 16-02-2026 at 20:52.
    you can't always get what you want, but if you try sometimes you might find, you get what you need

  5. #5
    thinBasic MVPs
    Join Date
    May 2007
    Location
    UK
    Posts
    1,433
    Rep Power
    162
    While I appreciate your assistance that does not meet my exacting requirements.
    Amiga 500
    Amiga 600 x 4
    Amiga 1200

    Windows stuff

  6. #6
    Senior Member Lionheart008's Avatar
    Join Date
    Sep 2008
    Location
    Germany, Bad Sooden-Allendorf
    Age
    53
    Posts
    948
    Rep Power
    112
    '---Script created on 2026-02-17 17:54:03.149 by Lionheart, Frank

    hello michael, I have got only this error after fixing your code

    ACOS() error here because I dont know what's content of iComplex
    'FreqTable(k).ph = ACOS(c) - (2 * pi * FreqTable(k).f * tstar)
    Now this code example works for 95 percent

    regards, frank
    '
    ' *****************************************************************************
    ' Multisine Signal Generator
    ' - Frequency range: 1 mHz → 10 kHz (logarithmic spacing)
    ' - User-selectable number of tones (1–32)
    ' - User-selectable uniform amplitude (example: 1.0)
    ' - Min–Max phase optimization to reduce the maximum absolute sample (peak)
    ' *****************************************************************************
    
    USES "CONSOLE"
    USES "iComplex"
    
    %MAX_ENTRIES = 32
    
    ' -----------------------------
    ' Configuration
    ' -----------------------------
    LOCAL nSamples AS LONG   VALUE = 1024         ' Increase for wider time window (benefits very low f)
    LOCAL fs       AS DOUBLE VALUE = 50000        ' Must exceed 2 * fMax (Nyquist). Here fMax=10 kHz -> fs >= 20 kHz
    LOCAL pi       AS DOUBLE VALUE = 4 * ATN(1)
    
    ' Min–Max optimizer settings
    LOCAL MAX_ITERS AS LONG  VALUE  = 200         ' Iteration cap
    LOCAL TOL       AS DOUBLE VALUE = 1e-9        ' Stop if improvement < TOL
    
    ' Frequency range (log spaced)
    LOCAL fMin  AS DOUBLE VALUE = 0.001   ' 1 mHz
    LOCAL fMax  AS DOUBLE VALUE = 10000   ' 10 kHz
    
    ' Generated signal
    LOCAL Signal(nSamples) AS DOUBLE
    
    ' Generic variable
    LOCAL i, j, n AS LONG VALUE = 0
    
    Console_SetCP(%CP_UTF8)               ' Set Input codepage to UTF8
    Console_SetOutputCP(%CP_UTF8)         ' Set Output codepage to UTF8
    
    ' -----------------------------
    ' User input: tone count and amplitude
    ' -----------------------------
    LOCAL activeCount AS LONG
    PRINT $CRLF & "Enter number of output frequencies (1-32): " 
    activeCount = VAL(Console_ReadLine())
    IF activeCount < 1 OR activeCount > %MAX_ENTRIES THEN
        PRINTL "Invalid value. Must be 1–32."
        WAITKEY
        STOP
    END IF
    
    LOCAL userAmp AS DOUBLE
    PRINT $CRLF & "Enter uniform amplitude for all tones (e.g., 1): " 
    userAmp = VAL(Console_ReadLine())
    IF userAmp <= 0 THEN userAmp = 1
    
    ' -----------------------------
    ' Data structures
    ' -----------------------------
    TYPE tFreqEntry
        f   AS DOUBLE
        amp AS DOUBLE
        ph  AS DOUBLE
    END TYPE
    
    LOCAL FreqTable(%MAX_ENTRIES) AS tFreqEntry
    
    ' -----------------------------
    ' Build logarithmically spaced frequency table
    ' -----------------------------
    IF activeCount = 1 THEN
        FreqTable(1).f   = fMin
        FreqTable(1).amp = userAmp
        FreqTable(1).ph  = 0
    ELSE
        LOCAL dlogMin AS DOUBLE : dlogMin = LOG(fMin)
        LOCAL dlogMax AS DOUBLE : dlogMax = LOG(fMax)
        LOCAL dstep   AS DOUBLE : dstep   = (dlogMax - dlogMin) / (activeCount - 1)
        FOR i = 1 TO activeCount
            FreqTable(i).f   = EXP(dlogMin + (i - 1) * dstep)
            FreqTable(i).amp = userAmp
            FreqTable(i).ph  = 0                  ' Start phases at 0 for optimization
        NEXT
    END IF
    
    ' -----------------------------
    ' Sanity checks
    ' -----------------------------
    IF fs < 2 * fMax THEN
        PRINTL "WARNING: fs < 2*fMax (Nyquist). Increase fs to at least " & FORMAT$(2 * fMax, "#") & " Hz."
    END IF
    IF nSamples < 2 THEN
        PRINTL "ERROR: nSamples must be >= 2"
        STOP
    END IF
    
    ' -----------------------------
    ' Run optimization, synthesize, and report
    ' -----------------------------
    CALL MinMaxOptimizePhases(Signal, nSamples)
    
    ' Compute final stats
    LOCAL peakVal AS DOUBLE VALUE = 0
    LOCAL sumSq   AS DOUBLE VALUE = 0
    LOCAL rms     AS DOUBLE VALUE = 0
    
    FOR i = 1 TO nSamples
        IF ABS(Signal(i)) > peakVal THEN peakVal = ABS(Signal(i))
        sumSq = sumSq + (Signal(i) * Signal(i))
    NEXT
    
    IF nSamples > 0 THEN
        rms = SQR(sumSq / nSamples)
    ELSE
        rms = 0
    END IF
    
    ' -----------------------------
    ' Output table and stats
    ' -----------------------------
    PRINTL ""
    PRINTL "=== Multisine Configuration ==="
    PRINTL "Samples: " & nSamples & ", fs: " & fs & " Hz"
    PRINTL "Active tones: " & activeCount & ", Uniform amplitude: " & userAmp
    PRINTL "Frequency range: " & fMin & " Hz to " & fMax & " Hz (log-spaced)"
    
    PRINTL ""
    PRINTL "=== Frequency Table ==="
    FOR i = 1 TO activeCount
        PRINTL USING$("Tone ##:  F=#########.######## Hz   Amp=#.###   Phi=#.###### rad", _
                      i, FreqTable(i).f, FreqTable(i).amp, FreqTable(i).ph)
    NEXT
    
    PRINTL ""
    PRINTL "=== Signal Stats ==="
    PRINTL "Peak: " & FORMAT$(peakVal, "#.######")
    PRINTL "RMS : " & FORMAT$(rms,    "#.######")
    IF rms > 0 THEN
        LOCAL crest AS DOUBLE = peakVal / rms
        PRINTL "Crest Factor: " & FORMAT$(crest, "#.######") & " (" & FORMAT$(20 * LOG(crest) / LOG(10), "#.##") & " dB)"
    ELSE
        PRINTL "Crest Factor: N/A (RMS=0)"
    END IF
    
    MSGBOX 0, "Multisine (log-spaced) with Min–Max phase optimization complete." & $CRLF & _
               "Tones: " & activeCount & ", Amp: " & FORMAT$(userAmp, "#.###") & $CRLF & _
               "Peak=" & FORMAT$(peakVal, "#.####") & ", RMS=" & FORMAT$(rms, "#.####")
    
    ' -----------------------------
    ' Helper: compute signal samples given current phases
    ' -----------------------------
    SUB ComputeSignal(BYREF Signal() AS DOUBLE, BYVAL nSamples AS LONG)
        LOCAL i, j    AS LONG
        LOCAL t, theta, s AS DOUBLE
    
        FOR i = 1 TO nSamples
            t = (i - 1) / fs
            s = 0
            FOR j = 1 TO activeCount
                theta = 2 * pi * FreqTable(j).f * t + FreqTable(j).ph
                s = s + FreqTable(j).amp * COS(theta)
            NEXT
            Signal(i) = s
        NEXT
    END SUB
    
    ' -----------------------------
    ' Min–Max Phase Optimization
    ' -----------------------------
    SUB MinMaxOptimizePhases(BYREF Signal() AS DOUBLE, BYVAL nSamples AS LONG)
        LOCAL it      AS LONG
        LOCAL i, k    AS LONG
        LOCAL imax    AS LONG
        LOCAL oldPeak, newPeak, sVal AS DOUBLE
        LOCAL tstar, theta_k   AS DOUBLE
        LOCAL R, A, c AS DOUBLE
    
        ' Initial signal with phases = 0
        CALL ComputeSignal(Signal, nSamples)
    
        ' Measure initial peak
        oldPeak = 0
        FOR i = 1 TO nSamples
            IF ABS(Signal(i)) > oldPeak THEN oldPeak = ABS(Signal(i))
        NEXT
    
        FOR it = 1 TO MAX_ITERS
            ' Find current maximum (worst peak)
            imax = 1
            newPeak = ABS(Signal(1))
            FOR i = 2 TO nSamples
                sVal = ABS(Signal(i))
                IF sVal > newPeak THEN
                    newPeak = sVal
                    imax = i
                END IF
            NEXT
    
            ' Early stop if improvement too small
            IF it > 1 THEN
                IF oldPeak - newPeak < TOL THEN EXIT FOR
            END IF
            oldPeak = newPeak
    
            ' Time at current peak
            tstar = (imax - 1) / fs
    
            ' Adjust phase for each tone to cancel at tstar
            FOR k = 1 TO activeCount
                theta_k = 2 * pi * FreqTable(k).f * tstar + FreqTable(k).ph
                A = FreqTable(k).amp
                R = Signal(imax) - A * COS(theta_k)
    
                IF A > 0 THEN
                    c = -R / A
                    IF c > 1 THEN c = 1
                    IF c < -1 THEN c = -1
                   
                    ' ACOS() error here because I dont know what's content of iComplex
                    'FreqTable(k).ph = ACOS(c) - (2 * pi * FreqTable(k).f * tstar)
    
                    ' Normalize phase to [-pi, pi]
                    DO WHILE FreqTable(k).ph > pi
                        FreqTable(k).ph = FreqTable(k).ph - 2 * pi
                    LOOP
                    DO WHILE FreqTable(k).ph < -pi
                        FreqTable(k).ph = FreqTable(k).ph + 2 * pi
                    LOOP
                END IF
            NEXT
    
            ' Recompute full signal with new phases
            CALL ComputeSignal(Signal, nSamples)
        NEXT
    END SUB
    
    Last edited by Lionheart008; 17-02-2026 at 19:04.
    you can't always get what you want, but if you try sometimes you might find, you get what you need

  7. #7
    Senior Member Lionheart008's Avatar
    Join Date
    Sep 2008
    Location
    Germany, Bad Sooden-Allendorf
    Age
    53
    Posts
    948
    Rep Power
    112
    post again that's for me ok :-) fixed with acos() problem, now it's running fine for me michael,

    frank

    '
    ' *****************************************************************************
    ' Multisine Signal Generator
    ' - Frequency range: 1 mHz → 10 kHz (logarithmic spacing)
    ' - User-selectable number of tones (1–32)
    ' - User-selectable uniform amplitude (example: 1.0)
    ' - Min–Max phase optimization to reduce the maximum absolute sample (peak)
    ' *****************************************************************************
    
    USES "CONSOLE"
    USES "iComplex"
    
    %MAX_ENTRIES = 32
    
    ' -----------------------------
    ' Configuration
    ' -----------------------------
    LOCAL nSamples AS LONG   VALUE = 1024         ' Increase for wider time window (benefits very low f)
    LOCAL fs       AS DOUBLE VALUE = 50000        ' Must exceed 2 * fMax (Nyquist). Here fMax=10 kHz -> fs >= 20 kHz
    LOCAL pi       AS DOUBLE VALUE = 4 * ATN(1)
    
    ' Min–Max optimizer settings
    LOCAL MAX_ITERS AS LONG  VALUE  = 200         ' Iteration cap
    LOCAL TOL       AS DOUBLE VALUE = 1e-9        ' Stop if improvement < TOL
    
    ' Frequency range (log spaced)
    LOCAL fMin  AS DOUBLE VALUE = 0.001   ' 1 mHz
    LOCAL fMax  AS DOUBLE VALUE = 10000   ' 10 kHz
    
    ' Generated signal
    LOCAL Signal(nSamples) AS DOUBLE
    
    ' Generic variable
    LOCAL i, j, n AS LONG VALUE = 0
    
    Console_SetCP(%CP_UTF8)               ' Set Input codepage to UTF8
    Console_SetOutputCP(%CP_UTF8)         ' Set Output codepage to UTF8
    
    ' -----------------------------
    ' User input: tone count and amplitude
    ' -----------------------------
    LOCAL activeCount AS LONG
    PRINT $CRLF & "Enter number of output frequencies (1-32): "
    activeCount = VAL(Console_ReadLine())
    IF activeCount < 1 OR activeCount > %MAX_ENTRIES THEN
        PRINTL "Invalid value. Must be 1–32."
        WAITKEY
        STOP
    END IF
    
    LOCAL userAmp AS DOUBLE
    PRINT $CRLF & "Enter uniform amplitude for all tones (e.g., 1): "
    userAmp = VAL(Console_ReadLine())
    IF userAmp <= 0 THEN userAmp = 1
    
    ' -----------------------------
    ' Data structures
    ' -----------------------------
    TYPE tFreqEntry
        f   AS DOUBLE
        amp AS DOUBLE
        ph  AS DOUBLE
    END TYPE
    
    LOCAL FreqTable(%MAX_ENTRIES) AS tFreqEntry
    
    ' -----------------------------
    ' Build logarithmically spaced frequency table
    ' -----------------------------
    IF activeCount = 1 THEN
        FreqTable(1).f   = fMin
        FreqTable(1).amp = userAmp
        FreqTable(1).ph  = 0
    ELSE
        LOCAL dlogMin AS DOUBLE : dlogMin = LOG(fMin)
        LOCAL dlogMax AS DOUBLE : dlogMax = LOG(fMax)
        LOCAL dstep   AS DOUBLE : dstep   = (dlogMax - dlogMin) / (activeCount - 1)
        FOR i = 1 TO activeCount
            FreqTable(i).f   = EXP(dlogMin + (i - 1) * dstep)
            FreqTable(i).amp = userAmp
            FreqTable(i).ph  = 0                  ' Start phases at 0 for optimization
        NEXT
    END IF
    
    ' -----------------------------
    ' Sanity checks
    ' -----------------------------
    IF fs < 2 * fMax THEN
        PRINTL "WARNING: fs < 2*fMax (Nyquist). Increase fs to at least " & FORMAT$(2 * fMax, "#") & " Hz."
    END IF
    IF nSamples < 2 THEN
        PRINTL "ERROR: nSamples must be >= 2"
        STOP
    END IF
    
    ' -----------------------------
    ' Run optimization, synthesize, and report
    ' -----------------------------
    CALL MinMaxOptimizePhases(Signal, nSamples)
    
    ' Compute final stats
    LOCAL peakVal AS DOUBLE VALUE = 0
    LOCAL sumSq   AS DOUBLE VALUE = 0
    LOCAL rms     AS DOUBLE VALUE = 0
    
    FOR i = 1 TO nSamples
        IF ABS(Signal(i)) > peakVal THEN peakVal = ABS(Signal(i))
        sumSq = sumSq + (Signal(i) * Signal(i))
    NEXT
    
    IF nSamples > 0 THEN
        rms = SQR(sumSq / nSamples)
    ELSE
        rms = 0
    END IF
    
    ' -----------------------------
    ' Output table and stats
    ' -----------------------------
    PRINTL ""
    PRINTL "=== Multisine Configuration ==="
    PRINTL "Samples: " & nSamples & ", fs: " & fs & " Hz"
    PRINTL "Active tones: " & activeCount & ", Uniform amplitude: " & userAmp
    PRINTL "Frequency range: " & fMin & " Hz to " & fMax & " Hz (log-spaced)"
    
    PRINTL ""
    PRINTL "=== Frequency Table ==="
    FOR i = 1 TO activeCount
        PRINTL USING$("Tone ##:  F=#########.######## Hz   Amp=#.###   Phi=#.###### rad", _
                      i, FreqTable(i).f, FreqTable(i).amp, FreqTable(i).ph)
    NEXT
    
    PRINTL ""
    PRINTL "=== Signal Stats ==="
    PRINTL "Peak: " & FORMAT$(peakVal, "#.######")
    PRINTL "RMS : " & FORMAT$(rms,    "#.######")
    IF rms > 0 THEN
        LOCAL crest AS DOUBLE = peakVal / rms
        PRINTL "Crest Factor: " & FORMAT$  (crest, "#.######") & " (" & FORMAT$  (20 * LOG(crest) / LOG(10), "#.##") & " dB)"
    ELSE
        PRINTL "Crest Factor: N/A (RMS=0)"
    END IF
    
    MSGBOX 0, "Multisine (log-spaced) with Min–Max phase optimization complete." & $CRLF & _
               "Tones: " & activeCount & ", Amp: " & FORMAT$(userAmp, "#.###") & $CRLF & _
               "Peak=" & FORMAT$  (peakVal, "#.####") & ", RMS=" & FORMAT$  (rms, "#.####")
    
    ' -----------------------------
    ' Helper: compute signal samples given current phases
    ' -----------------------------
    SUB ComputeSignal(BYREF Signal() AS DOUBLE, BYVAL nSamples AS LONG)
        LOCAL i, j    AS LONG
        LOCAL t, theta, s AS DOUBLE
    
        FOR i = 1 TO nSamples
            t = (i - 1) / fs
            s = 0
            FOR j = 1 TO activeCount
                theta = 2 * pi * FreqTable(j).f * t + FreqTable(j).ph
                s = s + FreqTable(j).amp * COS(theta)
            NEXT
            Signal(i) = s
        NEXT
    END SUB
    
    ' -----------------------------
    ' Min–Max Phase Optimization
    ' -----------------------------
    SUB MinMaxOptimizePhases(BYREF Signal() AS DOUBLE, BYVAL nSamples AS LONG)
        LOCAL it      AS LONG
        LOCAL i, k    AS LONG
        LOCAL imax    AS LONG
        LOCAL oldPeak, newPeak, sVal AS DOUBLE
        LOCAL tstar, theta_k   AS DOUBLE
        LOCAL R, A, c AS DOUBLE
    
        ' Initial signal with phases = 0
        CALL ComputeSignal(Signal, nSamples)
    
        ' Measure initial peak
        oldPeak = 0
        FOR i = 1 TO nSamples
            IF ABS(Signal(i)) > oldPeak THEN oldPeak = ABS(Signal(i))
        NEXT
    
        FOR it = 1 TO MAX_ITERS
            ' Find current maximum (worst peak)
            imax = 1
            newPeak = ABS(Signal(1))
            FOR i = 2 TO nSamples
                sVal = ABS(Signal(i))
                IF sVal > newPeak THEN
                    newPeak = sVal
                    imax = i
                END IF
            NEXT
    
            ' Early stop if improvement too small
            IF it > 1 THEN
                IF oldPeak - newPeak < TOL THEN EXIT FOR
            END IF
            oldPeak = newPeak
    
            ' Time at current peak
            tstar = (imax - 1) / fs
    
            ' Adjust phase for each tone to cancel at tstar
            FOR k = 1 TO activeCount
                theta_k = 2 * pi * FreqTable(k).f * tstar + FreqTable(k).ph
                A = FreqTable(k).amp
                R = Signal(imax) - A * COS(theta_k)
                
                IF A <= 0 THEN
                'IF A > 0 THEN
                    c = -R / A
                    'IF c > 1 THEN c = 1
                    'IF c < -1 THEN c = -1
                   
                   ' === KRITISCHER FIX: sicheres Clamping ===
                IF c > 1  THEN c = 1
                IF c < -1 THEN c = -1
                c = MAX(-1, MIN(1, c))   ' doppelt hält besser
                
                   
                    ' ACOS() error here because I dont know what's content of iComplex
                    'FreqTable(k).ph = ACOS(c) - (2 * pi * FreqTable(k).f * tstar)
                     ' Jetzt ist c garantiert im Bereich [-1, +1]
                   FreqTable(k).ph = ACOS(c) - (2 * pi * FreqTable(k).f * tstar)
    
                    ' Normalize phase to [-pi, pi]
                    DO WHILE FreqTable(k).ph > pi
                        FreqTable(k).ph = FreqTable(k).ph - 2 * pi
                    LOOP
                    DO WHILE FreqTable(k).ph < -pi
                        FreqTable(k).ph = FreqTable(k).ph + 2 * pi
                    LOOP
                END IF
            NEXT
    
            ' Recompute full signal with new phases
            CALL ComputeSignal(Signal, nSamples)
        NEXT
    END SUB
    
    you can't always get what you want, but if you try sometimes you might find, you get what you need

Similar Threads

  1. Printl with multiple parenthesis blocks failing
    By TheInsider in forum Console
    Replies: 1
    Last Post: 14-06-2025, 09:16
  2. brackets fail
    By DirectuX in forum thinBasic General
    Replies: 9
    Last Post: 16-05-2020, 15:44
  3. Replies: 3
    Last Post: 31-03-2009, 23:16

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •