Assignment 4
Home Up Assignment 1 Assignment 2 Assignment 3 Assignment 4 Assignment 5 Assignment 6 Assignment 7 Assignment 8

 

Self-Similar Music

Due: Friday Oct 10 at noon.

Read Chapter 7 in HSOM.  After updating your Haskore installation, you should be able to load the code via "import Haskore.SelfSimilar".  You can also copy snippets of the code for purposes of modifying it as requested below, by looking in the file: "Haskore/src/Haskore/SelfSimilar.lhs".

  1. Experiment with the self-similar program in Chapter 7.  Compose an "interesting" piece of music through a judicious choice of starting melody, depth of recursion, instrumentation, etc.
  2. Define an alternative version of simToMusic that interprets the music differently.  For example:
    bulletInterpret the pitch as an index into a scale -- e.g., as an index into the C major scale, so that 0 corresponds to C, 1 to D, 2 to E, 3 to F, ..., 7 to B, 8 to C in the next octave, and so on.
    bulletInterpret the pitch as duration, and the duration as pitch.
  3. Modify the self-similar code in the following ways:
    bulletAdd a Volume component to SNote (in other words, define it as a triple instead of a pair), and redefine addmult so that it takes two of these triples and combines them in a suitable way.  Then modify the rest of the code so that the result is a Music1 value.  With this modifications, compose something "interesting" that highlights the changes in volume.
    bulletChange the Pitch field in SNote to be a list of Pitches, to be interpreted ultimately as a chord.  Figure out some way to combine them in addmult, and compose something "interesting."
  4. Consider this sequence of 8 numbers:

    s1 = [ 1, 5, 3, 6, 5, 0, 1, 1 ]

    One might interpret this as a sequence of pitches, i.e. a melody.  Another way to represent this sequence is as a sequence of 7 intervals:

    s2 = [ 4, -2, 3, -1, -5, 1, 0 ]

    Together with the starting pitch (i.e. 1), this sequence of intervals can be used to reconstruct the original melody. But, with a suitable transposition to eliminate negative numbers, it can also be viewed as another melody.  Indeed, we can repeat the process: s2 can be represented by this sequence of 6 intervals:

    s3 = [ -6, 5, -4, -4, 6, -1 ]

    Together with the starting number (i.e. 4), s3 can be used to reconstruct s2.  Let's continue the process:

    s4 = [ 11, -9, 0, 10, -7 ]
    s5 = [ -20, 9, 10, -17 ]
    s6 = [ 29, 1, -27 ]
    s7 = [ -28, -28 ]
    s8 = [ 0 ]

    Now, if we take the first element of each of these sequences to form this 8-number sequence:

    ic = [ 0, -28, 29, -20, 11, -6, 4, 1 ]

    then it alone can be used to re-create the original 8-number sequence in its entirety. Of course, it can also be used as the original melody was used, and we could derive another 8-note sequence from it -- and so on.  We will refer to the list ic as the interval closure of the original list s1.

    In problems (a) - (d) below, you should define your functions non-recursively using polymorphic higher-order functions.  Indeed, each of my solutions consists of one line of code (plus a type signature) -- you should strive to do the same.  (Hint:  I used the following standard functions: head, tail, map, zipWith, take, length, iterate, reverse, (.), ($), and a few arithmetic operators.)
    1. Define a function toIntervals that takes a list of n numbers, and generates a list of n lists, such that the ith list is the sequence si as we defined them above.
    2. Define a function getHeads that takes a list of n lists and returns a list of n numbers such that the ith element is the head of the ith list.
    3. Compose the above two functions in a suitable way to define a function intervalClosure that takes an n-element list and returns its interval closure.
    4. Define a function intervalClosures that takes an n-element list and returns an infinite sequence of interval closures.
    5. Now for the open-ended part of this problem: Interpret the outputs of any of the functions above to create some "interesting" music.

      (Note: The numbers in the interval closures can become quite large after a few iterations -- if you decide to use them for music, you will want to figure out a way to map them into a suitable musical range.  For example, define a function normalize such that normalize range xs transforms xs into a sequence of numbers between 0 and range-1.  You can then transpose the result as desired.)