A very basic formula to transform a sequence of notes into a signal would be:
$$ x(t) = A\cos( 2 \pi (2^{current\_note}/12) t) $$ where $current\_note$ is $notes[\lfloor t / period\_per\_note\rfloor]$ and $a[k]$ is the indexing operation into a string; in this case into a sequence of numerical values representing notes on a chromatic scale.
However, when making a signal like this, whenever the frequency changes (when moving from one note to the next), the function is discontinuous, often starting at a completely different amplitude because in general, the periods of the two sinusoids with different frequencies end up being very different (not being a multiple of the same 'base frequency')-
This can also clearly be heard in the example, as 'clicks'.
Now the question: How can we make sure that the sinusoid with the 'new' frequency starts at the same value of x
as the one with the old frequency?
I am guessing that this somehow involves keeping track of the current 'phase', so that we can time-shift the new frequency to make sure their amplitudes match up. But I have no idea how to approach this, neither from a mathematical nor from a programmatic perspective.