| |
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".
- 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.
- Define an alternative version of simToMusic
that interprets the music differently. For example:
 | Interpret 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. |
 | Interpret the pitch as duration, and the duration as pitch. |
Modify the self-similar code in the following ways:
 | Add 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. |
 | Change 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." |
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.)
- 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.
- 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.
- 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.
- Define a function intervalClosures that
takes an n-element list and returns an infinite sequence of interval closures.
- 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.)
|