# In the Hall of the Mountain King, from Peer Gynt (Edvard Grieg) - for one beeper - https://lab.glossema.dev/play/mountain-king/code # It plays the notes of https://lab.glossema.dev/play/mountain-king, tone for tone. # Grieg states one four-bar tune eighteen times, low and quiet at first, then # higher, louder and faster, and a coda of fifteen bars breaks it off. This plays # seven of the statements and the whole coda, each in the orchestra's own octave. # The tune is written twice, on B and on F sharp, as steps up a table of # semitones; each statement names its keynote, and a tempo list sets its eighth. { # Every semitone from B2 up to D7, in Hz, an octave to a row. :local hz { 123;131;139;147;156;165;175;185;196;208;220;233; 247;262;277;294;311;330;349;370;392;415;440;466; 494;523;554;587;622;659;698;740;784;831;880;932; 988;1047;1109;1175;1245;1319;1397;1480;1568;1661;1760;1865; 1976;2093;2217;2349} # The eighth of each part: 217 ms for the first three, the print's 138 # quarters a minute, then each part a step faster. :local tempo {217ms;217ms;217ms;205ms;190ms;180ms;172ms;166ms;160ms} # The bass strokes, each letter in the octave from C3 up to B3, in Hz. :local stroke {"B"=247;"D"=147;"F#"=185;"G"=196} # share: the bass strikes its letter in front of a note or a rest and pays for # it out of that slot; it hands back what is left of the slot. :local share do={ :beep frequency=$bass length=$hit :delay $gap :return ($slot - $gap) } # graced: the piccolo's B6, led in by G#6, A6 and A#6, paid out of its slot. :local graced do={ :local left $slot :foreach g in={1661;1760;1865} do={ :beep frequency=$g length=25ms :delay 30ms :set left ($left - 30ms) } :beep frequency=1976 length=$tone :return $left } # The tune, eight eighths to a bar as the ff parts strike them. Each eighth is # a step up the table from the keynote, or hold: the last note or rest goes on. :local hold -1 :local onB { {0;2;3;5;7;3;7;7}; {6;2;6;6;5;1;5;5}; {0;2;3;5;7;3;7;12}; {10;7;3;7;10;$hold;$hold;$hold}} # On F sharp the third is major, the third bar repeats the first, and the # second and fourth bars are its own. :local riseFsharp {0;2;4;5;7;4;7;7} :local onFsharp {$riseFsharp; {8;4;8;8;7;4;7;7}; $riseFsharp; {8;4;8;8;7;$hold;$hold;$hold}} # The last statement closes on B. :local closing {($onB->0);($onB->1);($onB->2);{7;3;7;12;0;$hold;$hold;$hold}} # The coda's phrase: twice the piccolo answers the bass (grace), then the # tune's third bar and a close on B. :local grace -2 :local answer {$hold;$hold;$grace;$hold;$hold;$hold;$hold;$hold} :local coda {$answer;$answer;($onB->2);{11;7;11;14;12;$hold;$hold;$hold}} # The bass letter on beats one and three of every bar, "-" where it rests. :local bassTacet {"-";"-";"-";"-";"-";"-";"-";"-"} :local bassOnB {"B";"B";"B";"B";"B";"B";"D";"D"} :local bassOnFsharp {"F#";"F#";"D";"F#";"F#";"F#";"D";"F#"} :local bassClosing {"B";"B";"B";"B";"B";"B";"B";"B"} :local bassCoda {"B";"-";"B";"-";"G";"F#";"F#";"B"} # The form: the words each part prints, its bars, its keynote as a step up the # table (0 is B2, 7 is F#3, and every octave up adds 12), ff or not, its tone # lengths (plain, accented, the closing half, the graced B) and its bass. # In the creeping parts the tune is itself the bass. :local parts { {say="Bars 1-4: the tune, low, pizzicato"; bars=$onB; key=0; ff=false; tones={76ms;119ms}; bass=$bassTacet}; {say="Bars 9-12: the tune on F sharp"; bars=$onFsharp; key=7; ff=false; tones={76ms;119ms}; bass=$bassTacet}; {say="Bars 25-28: two octaves up, the violins"; bars=$onB; key=24; ff=false; tones={76ms;119ms}; bass=$bassOnB}; {say="Bars 33-36: cresc. e stretto poco a poco"; bars=$onFsharp; key=31; ff=false; tones={92ms;133ms}; bass=$bassOnFsharp}; {say="Bars 49-52: piu vivo"; bars=$onB; key=36; ff=true; tones={114ms;152ms;646ms}; bass=$bassOnB}; {say="Bars 57-60: an octave higher"; bars=$onFsharp; key=43; ff=true; tones={108ms;144ms;612ms}; bass=$bassOnFsharp}; {say="Bars 69-72: the tune closes on B"; bars=$closing; key=36; ff=true; tones={103ms;136ms;585ms}; bass=$bassClosing}; {say="Bars 73-80: the coda"; bars=($coda, $coda); key=36; ff=true; tones={100ms;130ms;564ms;149ms}; bass=($bassCoda, $bassCoda)}} :for n from=0 to=([:len $parts] - 1) do={ :local part ($parts->$n) :put ($part->"say") :local unit ($tempo->$n) :local bars ($part->"bars") :local key ($part->"key") :local ff ($part->"ff") :local tones ($part->"tones") :local bass ($part->"bass") :local last $hold :for b from=0 to=([:len $bars] - 1) do={ :local bar ($bars->$b) :for i from=0 to=([:len $bar] - 1) do={ :local step ($bar->$i) :local slot $unit # beats one and three: the bass stroke :if (($i % 4) = 0) do={ :local letter ($bass->(($b * 2) + ($i / 4))) :if ($letter != "-") do={ :set slot [$share bass=($stroke->$letter) hit=30ms gap=35ms slot=$slot] } } :if ($step = $grace) do={ :set slot [$graced tone=($tones->3) slot=$slot] } else={ # the quiet parts sound a repeated eighth only once, as a quarter :if (($step != $hold) && ($ff || ($step != $last))) do={ # accents on beat three, and on beat one of every second bar; # in the ff parts a note on beat three that goes on is the closing half :local tone ($tones->0) :if (($i = 4) || (($i = 0) && (($b % 2) = 1))) do={ :set tone ($tones->1) } :if ($ff && ($i = 4) && (($bar->5) = $hold)) do={ :set tone ($tones->2) } :beep frequency=($hz->($key + $step)) length=$tone } } :set last $step :delay $slot } } } # The last part, written out: two answers, the crescendo, the roll, the last B. :put "Bars 81-87: to the end" :local unit ($tempo->8) # Two more answers. :for bar from=1 to=2 do={ :delay [$share bass=($stroke->"B") hit=30ms gap=35ms slot=($unit * 2)] :delay [$graced tone=144ms slot=($unit * 2)] :delay ($unit * 4) } # p cresc. molto: the graced B on every beat after the first, then on all # four, each one 16 ms longer than the one before. :delay [$share bass=($stroke->"B") hit=30ms gap=35ms slot=($unit * 2)] :for k from=0 to=6 do={ :delay [$graced tone=(64ms + (16ms * $k)) slot=($unit * 2)] } # The timpani roll on B from beat three: two pulses to an eighth, and every # eighth 3 ms longer, from 7 to 40. :delay ($unit * 4) :for e from=0 to=11 do={ :for pulse from=1 to=2 do={ :beep frequency=($stroke->"B") length=(7ms + (3ms * $e)) :delay ($unit / 2) } } # fff: the last stroke, 40 ms, and the last B, 230 ms, all the graces leave # of its slot. :delay [$share bass=($stroke->"B") hit=40ms gap=40ms slot=($unit * 2)] :delay [$graced tone=230ms slot=($unit * 2)] }