Discussion:
Basking in Boccherini
(too old to reply)
Bohgosity BumaskiL
2011-12-01 12:01:05 UTC
Permalink
' This iz the background sound of:
' http://ecn.ab.ca/~brewhaha/finance/Manual_Spam_Control.htm

' I started reading the ChucK manual, and I ran into a
' lot of questions, like "How do I neatly put ratio names
' in?", "How do I feed source back into ChucK.?",
' and "How would I make ChucK read data from FRACTINT?".
' Since I answered the first two questions in BASIC,
' and I can see my way to answering the third question,
' I think I will stick with this synthesizer for a bit
' longer.
'
' In order of panning...
' parallel harmonic on left, then right...
DATA 8, 12, 18, 24, 36, 48, 72, 84, 54, 36, 27, 16, 12, 9
' A theme of multiples of twelve is in that, so I will
' use twelve in some later calculations to put it into
' the key of E. IOW, x= 440 / 2 ^ (1 / 12) ^ 151 / 640 / 12
'
' These are the first two octaves of a just intonation.
' A neat thing about it being that the second octave
' is an inversion, on 720, of the first octave, which
' means that ratios going down from 720 are reciprocals
' of ratios going up from 720, except 500 and 1000.
' F# G G# A A# B C C# D D# E F
' 360,384,405,432,450,480, 500, 540, 576, 600, 640, 675
' 720,768,810,864,900,960,1000,1080,1152,1200,1280,1350
' Number signs work in the QBASIC [PLAY ""] command,
' although a plus sign is in documentation.

' Note, length, glide fraction (1/length)
DATA 0,2,0
DATA 640,6,0
' Minor Semitone
DATA 600,3,0
' Minor Second
DATA 540,6,0
' Perfect Fourth
DATA 720,3,0
' Major Second
DATA 640,6,0,0,4,0
' Octave
DATA 320,15,0
' Pythagorean Major Third
DATA 405,12,4,0,3,0
' Perfect Fourth
DATA 540,6,0,0,2,0
' Major Second
DATA 480,8,0
' Perfect Fifth
DATA 320,4,0,0,1,0
' Acute Fourth
DATA 432,8,0
DATA 0,12,0

DATA 480,6,0
' Minor Second
DATA 432,3,0
' Minor Semitone
DATA 405,6,0
' Perfect Fourth
DATA 540,3,0
' Major Second
DATA 480,6,0,0,4,0
' Octave
DATA 240,15,9
' Perfect Fourth
DATA 360,12,4,0,3,0
' Perfect Fourth
DATA 480,6,0,0,2,0
' Minor Second
DATA 432,8,0
' Perfect Fourth
DATA 324,4,0,0,1,0
' Major Third
DATA 405,8,0
DATA 0,12,0

' Pythagorean Minor Sixth
DATA 640,6,0
' Minor Diatonic Semitone
DATA 600,3,0
' Minor Whole Tone
DATA 540,6,0
' Perfect Fourth
DATA 720,3,0
' Major Second
DATA 640,6,0
DATA 0,3,0
' Octave
DATA 320,8,5
DATA 0,2,0
DATA 360,8,0
' Major Whole Tone
DATA 320,8,0,0,6,0

' Major Niinth
DATA 720,6,0
' Major Second
DATA 640,3,0
' Pythagorean Minor Third
DATA 540,6,0
' Perfect Fifth
DATA 810,3,0
' Major Second
DATA 720,6,0
DATA 0,3,0
' Octave
DATA 360,4,5
DATA 0,2,0

' Major Second
DATA 405,8,0
' Major Whole Tone
DATA 360,8,0,0,6,0

' Major Sixth
DATA 600,8,0
' Pythagorean Minor Third
DATA 540,4,0
' Major Second
DATA 480,8,0
' Perfect Fourth
DATA 640,4,0
' Minor Semitone
DATA 600,8,0
DATA 0,4,0

' Perfect Fourth
DATA 480,12,0
' Perfect Fourth
DATA 360,12,0
' Perfect Fifth
DATA 540,12,10,0,4,0

' Unison
DATA 540,6,0
' Major Second
DATA 480,3,0
' Minor Whole Tone (Minor Second)
DATA 432,6,0
' Major Third
DATA 540,3,0
' Major Second
DATA 480,6,0
DATA 0,12,0

' Perfect Fourth
DATA 640,8,0
DATA 0,2,0
' Pythagorean Minor Sixth
DATA 405,6,0
' [576:405]
DATA 576,8,9
DATA 0,8,0

' Minor Whole Tone
DATA 640,6,0
DATA 0,3,0
' Minor Second
DATA 576,8,0
DATA 0,2,0
' 575:405 would be [115:81], which is not listed, either.
DATA 405,6,0
' Perfect Fourth
DATA 540,12,6
DATA 0,8,0

' Pythagorean Minor Third
DATA 640,8,0
DATA 0,2,0
' Pythagorean Minor Third
DATA 540,6,0
' Major Second
DATA 480,12,3
DATA 0,8,0

' Minor Third
DATA 576,8,0
' Minor Second
DATA 640,12,2
DATA 0,6,0
' Minor Second
DATA 576,6,0
DATA 0,6,0
' Classic Diminished Third
DATA 500,4,0
DATA 0,3,0
' Semi-augmented Whole Tone
DATA 432,12,0

DATA 0,51,0

' Many things distinguish this piece from Luigi Boccherini's:
' 1. My version contains varying glides and a deccellerando.
' 2. Some of my notes are different.
' 3. Boccherini's piece is longer (4:30>
' 4. Luigi's piece is not designed to loop.
' 5. All of the above are still blasphemy.

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

Test = "0"
numharmonics = 14
pi = 3.141592653589793#
TwoPi = pi * 2
SampleRate = 44100
BeatsPerSecond = 17#
lastnote = 0

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

' 640 * 12 = 7860, so scale 7860 down to a 12-TET E.
temp = (440 * 2 ^ (1 / 12) ^ 7) / 7860
FOR k = 1 TO numharmonics
READ harmonics(k)
harmonics(k) = harmonics(k) * temp
NEXT k

ampleft = 12000
ampright = 11000
temp = temp - temp
DropAngle(1) = 1 / numharmonics
k = 1
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)
NEXT k

OPEN "con" FOR APPEND AS #3

100
FOR g = 1 TO 97
READ note, length, glide

IF g > 0 THEN
' SOUND note, length
PRINT #3, USING "DATA ###-,###-,###"; note; length; glide

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
Bohgosity BumaskiL
2011-12-01 13:44:29 UTC
Permalink
On 2011-12-01 5:01 AM, I wrote that 600:480 iz a perfect fourth.
It iz very exactly a major third -- 5:4.

Loading...