• clarity.bas

    From brewjay@spamcop.net@21:1/5 to All on Mon Nov 28 04:39:59 2016
    ' https://soundcloud.com/jay-litwyn/clarity

    DATA 2, 5, 13, 34, 89, 144, 377, 1597, 987, 610, 233, 121, 55, 21, 8, 3

    DATA 0,9
    DATA 43,9,0,3,39,12,26,6,36,9,0,6
    DATA 26,9,0,3,36,12,42,6,54,9,0,6
    DATA 39,9,0,3,36,12,24,6,32,9,0,6
    DATA 24,9,0,3,32,12,39,6,48,9,0,6
    DATA 39,9,0,3,36,12,24,6,30,9,0,6
    DATA 30,9,0,3,45,12,30,6,40,9,0,6
    DATA 50,9,0,3,36,12,0,6,40,12,0,18

    DIM NumHarmonics AS INTEGER
    NumHarmonics = 16

    OPTION BASE 1
    DIM harmonics(NumHarmonics) AS DOUBLE
    DIM chanamp(2, NumHarmonics) AS DOUBLE
    DIM Velocity(NumHarmonics) AS DOUBLE
    DIM Acceleration(NumHarmonics) AS DOUBLE
    DIM Angle(NumHarmonics) AS DOUBLE
    DIM Phase(NumHarmonics) AS DOUBLE
    DIM TerminalAngle(NumHarmonics) AS DOUBLE
    DIM DropAngle(NumHarmonics) AS DOUBLE
    DIM PhaseDir(NumHarmonics) AS INTEGER
    DIM sign(NumHarmonics) AS INTEGER
    DIM BeatsPerSecond AS DOUBLE
    DIM ampleft AS LONG
    DIM ampright AS LONG
    DIM temp AS DOUBLE
    DIM TwoPi AS DOUBLE
    DIM SampleRate, t, samples AS LONG
    DIM lastnote AS INTEGER
    DIM note AS INTEGER
    DIM length, glide AS INTEGER
    DIM k, g AS INTEGER
    DIM Test AS STRING

    Test = "0"
    pi = 3.141592653589793#
    TwoPi = pi * 2
    SampleRate = 44100
    BeatsPerSecond = 18#
    lastnote = 0

    OPEN "\sox\clarity.raw" FOR OUTPUT AS #2
    OPEN "clarity.bat" FOR OUTPUT AS #1
    PRINT #1, "fbc -lang qb clarity.bas"
    PRINT #1, "clarity.exe"
    PRINT #1, "cd \sox"
    PRINT #1, "sox -c 2 -r"; SampleRate; " -sw clarity.raw clarity.wav stat"
    CLOSE #1

    FOR k = 1 TO NumHarmonics
    READ harmonics(k)
    Angle(k) = 0
    NEXT k
    basis = harmonics(5)

    ampleft = 60000
    ampright = 40000
    temp = temp - temp
    DropAngle(1) = 1 / NumHarmonics
    FOR k = 1 TO NumHarmonics
    chanamp(1, k) = ampleft / harmonics(k) * temp
    chanamp(2, k) = ampright / harmonics(k) * (1 - temp)
    IF k MOD 2 = 0 THEN
    chanamp(1, k) = -chanamp(1, k)
    ELSE
    chanamp(2, k) = -chanamp(2, k)
    END IF
    temp = temp + DropAngle(1)
    harmonics(k) = harmonics(k) * 39.15 / 42
    NEXT k

    100
    FOR g = 1 TO 43
    READ note, length

    IF g > 0 THEN
    ' SOUND note * 6, length
    END IF
    IF Test = "0" THEN
    IF note = 0 AND lastnote = 0 THEN
    samples = SampleRate * length / BeatsPerSecond
    GOSUB 300
    GOTO 75
    END IF
    IF note = 0 AND lastnote <> 0 THEN
    GOSUB 250
    FOR k = 1 TO NumHarmonics
    lastnote = note
    NEXT k
    samples = SampleRate * length / BeatsPerSecond
    GOSUB 300
    GOTO 75
    END IF
    IF note <> 0 AND lastnote = 0 THEN
    FOR k = 1 TO NumHarmonics
    lastnote = note
    NEXT k
    samples = SampleRate * length / BeatsPerSecond
    GOSUB 275
    GOTO 75
    END IF
    IF note <> 0 AND lastnote <> 0 THEN
    IF glide > 0 THEN
    samples = SampleRate * length /
    BeatsPerSecond / glide
    GOSUB 300
    samples = SampleRate * length /
    BeatsPerSecond - samples
    ELSE
    samples = SampleRate * length /
    BeatsPerSecond
    END IF
    FOR k = 1 TO NumHarmonics
    lastnote = note
    NEXT k
    GOSUB 300
    GOTO 75
    END IF
    END IF
    75 NEXT g

    IF Test = "1" THEN END

    CLOSE #2
    END

    250
    FOR k = 1 TO NumHarmonics
    temp = Angle(k) / TwoPi
    Angle(k) = (temp - FIX(temp)) * TwoPi
    IF Angle(k) > pi * 3 / 2 THEN
    TerminalAngle(k) = pi * 3.5
    PhaseDir(k) = 2
    DropAngle(k) = pi * 2.5
    ELSEIF Angle(k) > pi / 2 THEN
    TerminalAngle(k) = pi * 2.5
    PhaseDir(k) = 1
    DropAngle(k) = pi * 3 / 2
    ELSE
    TerminalAngle(k) = pi * 3 / 2
    PhaseDir(k) = -1
    DropAngle(k) = pi / 2
    END IF
    NEXT k

    260
    FOR k = 1 TO NumHarmonics
    Phase(k) = SIN(Angle(k))
    SELECT CASE PhaseDir(k)
    CASE 2
    IF Angle(k) >= DropAngle(k) THEN
    Phase(k) = Phase(k) / 2 + .5
    END IF
    CASE 1
    IF Angle(k) >= DropAngle(k) THEN
    Phase(k) = Phase(k) / 2 - .5
    END IF
    CASE -1
    IF Angle(k) >= DropAngle(k) THEN
    Phase(k) = Phase(k) / 2 + .5
    END IF
    END SELECT
    IF Angle(k) < TerminalAngle(k) THEN
    Angle(k) = Angle(k) + Velocity(k)
    ELSE
    Angle(k) = TerminalAngle(k)
    END IF
    NEXT k
    GOSUB 400

    FOR k = 1 TO NumHarmonics
    IF Angle(k) < TerminalAngle(k) THEN GOTO 260
    NEXT k
    FOR k = 1 TO NumHarmonics
    Angle(k) = Angle(k) - Angle(k)
    NEXT k

    RETURN

    275
    ' This starts a wave from zero, using half the amplitude, a start
    ' from where sin(angle) = -1, and a bias of half. This cuts
    ' a leading click that I can hear on some equipment with some tunes.
    FOR k = 1 TO NumHarmonics
    Velocity(k) = TwoPi * lastnote * harmonics(k) / SampleRate
    Acceleration(k) = (TwoPi * note * harmonics(k) / SampleRate - Velocity(k)) / samples
    PhaseDir(k) = 1
    Angle(k) = 3 / 2 * pi
    NEXT k

    280
    FOR k = 1 TO NumHarmonics
    IF PhaseDir(k) = 1 THEN
    Phase(k) = SIN(Angle(k)) / 2 + .5
    ELSE
    Phase(k) = SIN(Angle(k))
    END IF
    Angle(k) = Angle(k) + Velocity(k)
    Velocity(k) = Velocity(k) + Acceleration(k)
    NEXT k
    samples = samples - 1
    GOSUB 400

    FOR k = 1 TO NumHarmonics
    IF PhaseDir(k) = 1 THEN
    Phase(k) = (Phase(k) - .5) * 2
    END IF
    IF Phase(k) > SIN(Angle(k)) THEN
    PhaseDir(k) = -1
    END IF
    NEXT k

    FOR k = 1 TO NumHarmonics
    IF PhaseDir(k) = 1 GOTO 280
    NEXT k

    300
    FOR k = 1 TO NumHarmonics
    Velocity(k) = TwoPi * lastnote * harmonics(k) / SampleRate
    Acceleration(k) = (TwoPi * note * harmonics(k) / SampleRate - Velocity(k)) / samples
    NEXT k

    FOR t = 1 TO samples
    FOR k = 1 TO NumHarmonics
    Velocity(k) = Velocity(k) + Acceleration(k)
    Angle(k) = Angle(k) + Velocity(k)
    Phase(k) = SIN(Angle(k))
    NEXT k
    GOSUB 400
    NEXT t
    RETURN

    400
    ampleft = ampleft - ampleft
    ampright = ampright - ampright
    FOR k = 1 TO NumHarmonics
    ampleft = ampleft + CINT(Phase(k) * chanamp(1, k))
    ampright = ampright + CINT(Phase(k) * chanamp(2, k))
    NEXT k

    PRINT #2, CHR$(ampleft AND 255); CHR$((ampleft AND 65280) / 256);
    PRINT #2, CHR$(ampright AND 255); CHR$((ampright AND 65280) / 256);

    RETURN

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)