'
https://soundcloud.com/jay-litwyn/jesus-christ-superstar-who-in-the-hell-do-you-think-you-are
' It is a two part mixed solo, with a synth lead
' having the same tune, parts exchanged:
' CC-BY-NC-ND
' The bayse (left column, right channel) is even,
' and in the case, it was easier to work out kinks at half.
' Name of concert ratio is in throwaway string variable.
' Right channel pitch, left channel, length, ratio name:
DATA 0 , 0 , 15 ,"Jerminal Rest"
DATA 45 , 70 , 12 ,"Septimal Minor Sixth"
DATA 60 , 55 , 6 ,"Undecimal Neutral Second, tails in"
DATA 65 , 40 , 9 ,"Tridecimal Neutral Sixth, tails in"
DATA 0 , 0 , 9 ,"Rest"
DATA 45 , 75 , 12 ,"Major Sixth"
DATA 60 , 60 , 6 ,"Unison"
DATA 75 , 45 , 9 ,"Major Sixth, tails in"
DATA 0 , 0 , 9 ,"Rest"
DATA 45 , 75 , 9 ,"Major Sixth"
DATA 60 , 60 , 6 ,"Unison"
DATA 65 , 75 , 6 ,"Tridecimal Major Third"
DATA 75 , 70 , 12 ,"Major Diatonic Semitone"
DATA 65 , 60 , 6 ,"Tridecimal Semitone"
DATA 60 , 55 , 6 ,"Undecimal Neutral Second"
DATA 75 , 60 , 12 ,"Major Third"
DATA 65 , 50 , 6 ,"Tridecimal Semi-diminished Fifth"
DATA 60 , 40 , 12 ,"Perfect Fifth"
DATA 0 , 0 , 15 ,"Terminal Rest"
OPTION BASE 1
DIM TwoPi AS DOUBLE
DIM pi AS DOUBLE
DIM temp AS DOUBLE
DIM BeatsPerSecond AS DOUBLE
DIM Angle(2) AS DOUBLE
DIM Velocity(2) AS DOUBLE
DIM Acceleration(2) AS DOUBLE
DIM Phase(2) AS DOUBLE
DIM note(2) AS INTEGER
DIM LastNote(2) AS INTEGER
DIM length AS INTEGER
DIM harmonics(2) AS DOUBLE
DIM Samples AS LONG
DIM t AS LONG
DIM SampleRate AS LONG
DIM k AS INTEGER
DIM g AS INTEGER
DIM amp AS INTEGER
DIM basis AS INTEGER
DIM NumHarmonics AS INTEGER
DIM Sign(2) AS INTEGER
DIM glide AS INTEGER
DIM GlideTrim AS LONG
DIM test AS STRING
DIM rationame AS STRING
DIM TerminalAngle(2) AS DOUBLE
DIM DropAngle(2) AS DOUBLE
DIM PhaseDir(2) AS DOUBLE
PRINT
test = "0"
' I frequently flip that.
NumHarmonics = 2
BeatsPerSecond = 18#
pi = 3.141592653589793#
TwoPi = pi * 2
SampleRate = 44100
IF test = "0" THEN
OPEN "\sox\jesus3.raw" FOR OUTPUT AS #4
END IF
' This is where I write a batch file that assumes where
' your FreeBasic and your Sound Exchange are.
OPEN "jesus3.bat" FOR OUTPUT AS #1
PRINT #1, "\progra~2\freebasic\fbc -lang qb jesus3.bas"
PRINT #1, "jesus3.exe"
PRINT #1, "cd \sox"
PRINT #1, "sox -c 2 -r"; SampleRate; " -sw jesus3.raw jesus3.wav stat"
CLOSE #1
' Fundamental Frequency of right and left channels.
harmonics(1) = 4.25
harmonics(2) = 4.25
FOR k = 1 TO NumHarmonics
note(k) = 0
LastNote(k) = 0
NEXT k
OPEN "con" FOR APPEND AS #2
' Change filename for feedback into this code.
glide = 30
100
FOR g = 1 TO 19
READ note(1), note(2), length, rationame
rationame = CHR$(34) + rationame + CHR$(34)
' PRINT #2, USING "DATA ###-,###-,###, ,&"; note(1) * 4; note(2)
* 4; length; rationame
IF g > 0 THEN
' SOUND note(1) * 4.25, length
END IF
IF test = "0" THEN
IF note(1) = 0 AND LastNote(1) = 0 THEN
Samples = SampleRate * length / BeatsPerSecond
GOSUB 300
GOTO 75
END IF
IF note(1) = 0 AND LastNote(1) <> 0 THEN
GOSUB 250
FOR k = 1 TO NumHarmonics
LastNote(k) = note(k)
NEXT k
Samples = SampleRate * length / BeatsPerSecond
GOSUB 300
GOTO 75
END IF
IF LastNote(1) = 0 AND note(1) <> 0 THEN
FOR k = 1 TO NumHarmonics
LastNote(k) = note(k)
NEXT k
Samples = SampleRate * length / BeatsPerSecond
GOSUB 275
GOTO 75
END IF
IF note(1) <> 0 AND LastNote(1) <> 0 THEN
Samples = SampleRate * length / BeatsPerSecond
/ glide
GlideTrim = Samples
GOSUB 300
Samples = SampleRate * length / BeatsPerSecond
- GlideTrim
FOR k = 1 TO NumHarmonics
LastNote(k) = note(k)
NEXT k
GOSUB 300
GOTO 75
END IF
END IF
75 NEXT g
CLOSE #4
END
' *Neat* Silencer -- finishes a wave like 275 starts one.
' When it reaches a peak or a trough, then it cuts amplitude in half
' and biases it by half.
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) = 1
DropAngle(k) = pi * 2.5
ELSEIF Angle(k) > pi / 2 THEN
TerminalAngle(k) = pi * 2.5
PhaseDir(k) = 0
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 1
IF Angle(k) >= DropAngle(k) THEN
Phase(k) = Phase(k) / 2 + .5
END IF
CASE 0
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(k) * harmonics(k) / SampleRate
Acceleration(k) = (TwoPi * note(k) * 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
' Calculate constants of change for write loop.
FOR k = 1 TO NumHarmonics
Velocity(k) = TwoPi * LastNote(k) * harmonics(k) / SampleRate
Acceleration(k) = (TwoPi * note(k) * harmonics(k) / SampleRate
- Velocity(k)) / Samples
NEXT k
' Main write loop. Static Phases problem solved at 250.
FOR t = 1 TO Samples
FOR k = 1 TO NumHarmonics
Phase(k) = SIN(Angle(k))
NEXT k
GOSUB 400
FOR k = 1 TO NumHarmonics
Angle(k) = Angle(k) + Velocity(k)
Velocity(k) = Velocity(k) + Acceleration(k)
NEXT k
NEXT t
RETURN
400
' Write a sample.
' Bayse is on right for a change.
amp = CINT(Phase(2) * 32000)
PRINT #4, CHR$(amp AND 255);
PRINT #4, CHR$((amp AND 65280) / 256);
amp = CINT(Phase(1) * -32000)
PRINT #4, CHR$(amp AND 255);
PRINT #4, CHR$((amp AND 65280) / 256);
RETURN