BEAT COMPOSE

Cos 325 project - Daniel Iglesia

Question: can a melody be described as a sum of sine waves? The sine waves starting not at random points in the melody, but all starting at the same time?

The crux of the problem, to me, is getting a particular frequency to appear when you want it and have it be canceled out the rest of the time. This requires the amplitude of a particular sine wave (with the frequency of the desired tone) to grow and recede predictably.
My first attempts were basic: strech out the amplitude modulation of the "beat" phenomenon really long (as long as the desired clip length), and then change the phase so that the amplitude of a particular wave starts growing at the right time.
An early (bad) example of the opening chord of Thus Spake Zarathustra:
Bad early attempt at opening notes to "Thus Spake Zarathustra"
float stretch=.3;/*here, stretch is the definition of the difference between sine freqs.*/
int phase1=-30000;
int phase2=-60000;
...
  • temp=sin(i*200*TWO_PI/SRATE)+sin(i*(200+stretch)*TWO_PI/SRATE);
  • temp+=sin(i*300*TWO_PI/SRATE)+sin((i+phase1)*(300+stretch)*TWO_PI/SRATE);
  • temp+=sin(i*400*TWO_PI/SRATE)+sin((i+phase2)*(400+stretch)*TWO_PI/SRATE);

  • The problems are obvious: to get a tone to appear halfway through the clip, we need to hear the part in front of it, the decay of the previous amplitude modulation. If we try to cheat by streching the note out even more, the attack of the note becomes so gradual as to be useless.
    The goal is to have a combination of waves that produces an (amplitude modulation) spike with a resulting period of zeroes.

    First Approach

    I used a program, Audiomulch, that has a window with 10 sliders representing the first 10 harmonics, and a window showing the shape of the resulting waveform. I played around and found a combination that yields a sharper positive wave, a period of around zero, and then a sharp negative wave the magnitudes of the harmonics:
    1:0.298 2:0.436 3:0.362 4:0.202 5:0.064 6:0.021
    amplitude modulation of a Wave with above weights on first 6 harmonics (20 seconds)

    So even if I have to stretch this wave out a bit, hopefully the longer silence and the sharper attack will yield a better result. The code for a tune is a sum of sin waves, one for each note in the melody, with a phase defined as the lag time, in samples, for when the note should appear. In addition, the volumes of the notes can be modified(to create accents) by putting a coefficient in front of the amplitude modulation

    attempts:

    Better attempt at Thus Spake
    float stretch=.1;
    int phase1=-30000;
    int phase2=-60000;
    ...
  • temp=sin(i*200*TWO_PI/SRATE)*(.298+(.436*cos(i*2*TWO_PI*stretch/SRATE))+(.362*cos(i*4*TWO_PI*stretch/SRATE))+(.202*cos(i*6*TWO_PI*stretch/SRATE))+(.064*cos(i*8*TWO_PI*stretch/SRATE))+(.021*cos(i*10*TWO_PI*stretch/SRATE)));
  • temp+=sin(i*300*TWO_PI/SRATE)*(.298+(.436*cos((i+phase1)*2*TWO_PI*stretch/SRATE))+(.362*cos((i+phase1)*4*TWO_PI*stretch/SRATE))+(.202*cos((i+phase1)*6*TWO_PI*stretch/SRATE))+(.064*cos((i+phase1)*8*TWO_PI*stretch/SRATE))+(.021*cos((i+phase1)*10*TWO_PI*stretch/SRATE)));
  • temp+=sin(i*400*TWO_PI/SRATE)*(.298+(.436*cos((i+phase2)*2*TWO_PI*stretch/SRATE))+(.362*cos((i+phase2)*4*TWO_PI*stretch/SRATE))+(.202*cos((i+phase2)*6*TWO_PI*stretch/SRATE))+(.064*cos((i+phase2)*8*TWO_PI*stretch/SRATE))+(.021*cos((i+phase2)*10*TWO_PI*stretch/SRATE)));
  • A nice major scale arpeggio
    Plus, I put a slight weight on the amplitude modulation of the strong beats, creating a slight accent
    A poor excuse for "Row Row Row Your Boat" 's first line
    notice by now the melody is becoming too long and the note envelopes are bleeding too much into one another

    So basically, this works for melodies of a few seconds long, but anything longer, the wave is so stretched that the attack of the note becomes to gradual and loses any defenition.

    Better Approach

    A better wave to use as the amplitude modulation: I want a spike, and I reasoned that I could create one with a series of odd harmonics (like a plucked string). So I add a bunch of (odd) cosine waves (cos(xt)+cos(3xt)+cos(5xt)...). The more items in the series, the more defined the spike.
    sum of first 5 odd harmonics

    good
    sum of first 10 odd harmonics

    better, though with more computation

    Great, this is exactly what we want, plus we know that we can always make the spike more sharply defined by adding more and more odd harmonics to the cosine formula that dfines the amplitude modulation. Let's try to build a melody by streching this wave out and layering it with other tones

    attempts:

    A much better "row row row your boat"
    _
    The first half of "Happy Birthday"
    An attempt at all of "Happy Birthday"
    It's not too bad, but the new addition of higher frequency notes puts a lot more annoying high frequencies in the background over the whole clip

    Making it Even More Awesome

    The more odd harmonics in our amplitude modulation, the sharper the spike and the quieter the surrounding non-spike. So I tried running the last program with a whopping 16 harmonics (first through thirty-first odd harmonics). It took a long time to run (a few minutes), but the improvement is very noticable. Background noise is greatly diminished, and the note envelopes are sharper and clearer.
    awesome "Happy Birthday"

    The Formula

    Basically, each tone in the melody is its own sine wave of that frequency. Each tone is multiplied by an amplitude modulation that makes the amplitude zero except for a spike. The period of this amplitude oscillation must be longer than the attempted melody.

    The code, in the framework of beats.c:
    float stretch= (a small number, like .1, that causes the period of the amplitude modulation to be the desired length of the melody);
    int beat= (in number of samples, the subdivision that the rythms of the notes will be based upon); (now, phase N defines the offset of each note. the phase for the first note is zero, assuming it starts at the start of the clip*/
    int phase1=-1*beat;/*starts a quarter note away from the start*/
    int phase2=-2*beat;/*eighth*/
    int phase3=-2.5*beat;/*eighth*/
    int phase4=-3*beat;/*half*/
    int phase5=-5*beat;
    ...
    (now, for N tones, define each sine wave. A=amplitude weighting)
    temp=sin(N*i*TWO_PI/SRATE)*(A*(cos(i*TWO_PI*stretch/SRATE)+cos(i*3*TWO_PI.../*etc through many odd harmonics*/
    temp+=sin(N*i*TWO_PI/SRATE)*(A*(cos((i+phase N)*TWO_PI*stretch/SRATE)+cos((i+phase N)*3*TWO_PI...
    temp+=sin(N*i*TWO_PI/SRATE)*(A*(cos((i+phase N)*TWO_PI*stretch/SRATE)+cos((i+phase N)*3*TWO_PI...

    Final example

    This piece was created with another program that I wrote. I fed it the wavelengths of twelve tones in an octave, and then had it spit out a series of thirty waves with different entrances and pitches. This output was then used in the other programs to create two files, one lower and shorter in duration and one higher and a little longer in duration. These pieces were combined into R and L stereo tracks and looped. So behold the best twelve-tone piece ever written: "Milton Babbitt is Still On the Music Faculty but I've Never Seen Him in Woolworth". .mp3 format (933 KB)

    the sine waves of the left (high) channel
    the sine waves of the right (low) channel