CECS Home | ANU Home | Search ANU
The Australian National University
ANU College of Engineering and Computer Science
School of Computer Science
Printer Friendly Version of this Document

UniSAFE

COMP2720 • 2008
Assignment 2

Due week 13 (Tuesday 21 October, 18:00 EDST)

Draft — elaborations and clarifications may follow

This assignment is worth 15% of your total course mark. It will be marked out of 15 as indicated below.

The estimated time we expect you to spend on this assignment is around 15 hours in total (1 hour per mark).

 


A Synaesthetic Étude: Music in Colours


Objectives

This assignment is a (very) modest attempt at creating a piece of synthetic art, which combines music and visual imagery. You are given a few files containing sequences of (pitch,amplitude,duration) data which can be performed by the JES function playNote(). These files are single track extractions from midi files, which means they are not complete music tracks, but rather mangled pieces of such. Your task is to write a Python program which will extract the information about pitch, duration and amplitude of every sound from a given sequence file, and to map these data into the visual objects, characterized by colour, shape and size. You will create a picture object and store it in a separate file for a group of notes in the given sequence. This way, a melody represented by a note sequence will be performed in colour, as a motion picture made of frames which are represented by the above pictures.

The Linux version of JES which we use in the labs, does not allow you to save the movie in one of the standard movie formats (though, JES on Mac and Windows does allow this), but if named and organized correctly, these image files can be assembled into a movie and played by JES.

Prior musical knowledge assumed: none 

Background

Syneasthesia is a rare (perhaps not too rare as the recent article in NewScientist, 9 August 2008, p. 17 indicates — added on 05.09.2008) psychological phenomenon which consists in sensing an impression with organs different from those by which this impression is normally stimulated. For example, to see colours when hearing sound, and vice versa — colour-hearing. Several composers are known to have possessed such colour-hearing abilities — Richard Wagner, Nikolai Rimsky-Korsakov, Olivier Messiaen, and most particlularly the Russian composer Alexander Scriabin. In the scores of his 1910 symphonic work "Prometheus, or the Poem of Fire", Scriabin included the part called luce (pronounced loõ-che — Italian for "light"; compare the English word lucent) which was to be performed on a then non-existed colour-tonal instrument.

Scriabin associated every musical note with a particular colour. In a simplified form the colour notes are represented on this picture:

Colour Keyboard

Your task in this assignment is to "perform" a melody provided as a sequence of notes by considering groups of successive notes from the sequence, and using the above notes →colours correspondance, generate shapes on a canvas and save the resulting picture as a frame of a movie. When these picture files are properly named and stored, JES can be used to play them as a single movie (on Linux; on Mac and Window a movie file, in the QuickTime or AVI, respectively, can be actually created). The details of the process are provided below, in the tasks section.

Note sequences and midi files

Normally, the music visualization is performed on audio files (wav, mp3, aiff etc) when the music characteristics like volume, balance (for stereo sounds), melody, rate and mood are extracted, often with the help of sophisticated techniques like spectral (using the Fast Fourier Transform, FFT) and other analyses. Usually, some of these analyses (especially mood and melody) are faked: visual effects are achieved using pattern generated engines which operate more or less randomly.

This difficulty is not surprising since genuine visualization of music is possible only through its adequate description which exists as musical scores written by music's composers (even scores are not enough — that's why performers are artists too, and every good performer is co-creator of the performed music). Such adequate description of digital music does indeed exist. Just like an image can be described in a vector graphics format, a music piece can be faithfully represented in a special digital format called MIDI, which is more or less a music score in binary form.

The MIDI format involves one or several tracks, each being a collection of data chunks — an uninterrupted data stream. Each chunk carries information about a music event — the time stamp (when the event takes place), the actual note (pitch), its volume and the character of the event (note-on, note-off, and some other to help imitate various basic instruments). Since normally note events overlap, it is more convenient to include multiple tracks in one MIDI file (tacks are stored in a MIDI file one after another), though any sequence of overlapping note events can be represented by a single track.

For this assignment, several existing classical music pieces were converted from the original MIDI files into so-called comma-separated values (.csv) files which are essentially one-track extractions from the original MIDIs. The reason we cannot use the MIDI files is that JES cannot read them (though, it may change soon, since JES is created on the top of Java which does have MIDI capabilities — the Java sound.midi package is already used in JES to handle sounds). Therefore, if we want to use "real" melodies in our colour-music experiments, we must compromise and simplify the MIDI-melodies so JES can play and make further use of them.

The assignment tasks

0. "Musical theory"

Below under Note (capital 'N') we mean the full set of data from one line in the sequence file — the musical note (AKA 'key') and octave, duration and volume. The key (one of the values C, C#, D, D#, E, F, F#, G, G#, A, A#, B) and octave (-1,0,1,…8,9) are derived from the value of pitch (0…127) using the same MIDI table, which is used in the Lab 4. Remember, that the last octave is shortened, it has only eight keys (C,…,G).

1. The note–colour dictionary

Begin with creating a dictionary of (note,colour) pairs using the colour scheme in this picture. Simply, create a picture object in JES by loading the picture file, open it in the Media Tools, read the (R,G,B)-values of all twelve "colour-notes", and then use them to create colour constants. (Name them like colourC, colourDsharp, etc.) Introduce the dictionary variable and fill it with the appropriate (key,value) entries.

Colour Keyboard

2. Mapping sounds to shapes

Next, start reading the music sequence file line by line, parsing it and determining the pitch, duration and amplitude (volume) of every sound. Use the MIDInotes.csv file from the lab 4 to map every pitch to the (note,octave) pair (reversed to what you will have done in the lab 4 exercise 2). You will have to separate the note and octave values for later use.

Once the (note,octave,duration,volume) values are determined, the Note can be be transformed into an image. You can use one and the same shape for every note, a simple one, like a circle or a square, which JES can generated easily. But depending on the pitch (note and octave) the colour and size of generating shapes will be different. To set the colour, you will use the note-colour dictionary created earlier, while the size will be determined by the note octave. The low sounds from the Octave number -1 (pitch 0…11) should be the largest, the sounds from higher Octaves should progressively get smaller, with the sounds from the Octave 9 should be the smallest.

The position of shapes on the canvas will be chosen randomly.

3. "The melody"

The effect of successively played notes will be achieved by retaining the shapes from the previous sounds on the next frame. Every frame will contain up to seven shapes — one from the current note and others from the previously played notes. To express attenuation of played notes, the present shapes on the current frame will fade their original colour proportionally to their "age" and "life span".

The note life is determined by the duration value: you will have to establish the note with a shortest duration durmin in the sequence, and the note with the longest duration durmax. Then, you will break the interval [durmin,…,durmax] into seven equal sub-intervals. Thus, every note in the sequence will have a duration from one of the sub-intervals. The sub-interval number will determine the note life span — the number of frames on which the note will be present. The note luminance will be the highest on the first frame (when the note is "youngest"). With every consecutive frame the note luminance will decrease according to its life span, eg, the note with the duration from the fifth duration sub-intervals will "live" for five frames, loosing 20% of its original luminance every consecutive frame, and disappearing after five frames. The longest sounding notes will live for seven frames.

Some notes in a sequence ma have zero duration (they fake silent pauses). These notes will not be represented by a shape, the frame corresponding to such note event, will be created as usual (on such frames, the present shapes will be "aged" shapes which where already generated on the preceding frames.

Thus, every "shape-note" will undergo a fading transition from the original full colour to the pure white in up to seven steps. When the last note in the sequence is played, the "colour-music" will last several (up to six) more frames until the shape created by the last played note dissolves in the canvas white background.

4. The movie

The frames will have to be successively numbered and saved in a special directory named as the sequence file (without .csv suffix, eg, the sequence from satie_gymnopedie-1.csv will generate frames stored in the directory satie_gymnopedie-1). The movie can be played by creating a movie abject and adding frames to it from the directory which contains the frames.

5. Advanced effects

The successively generated shape must not obscure (completely overlap) one another. This would require putting some constraint on the position where a newly created shape is placed. Try modify the random algorithm of selecting the new shape position which takes into account the already present shapes so that the new shape fits (if possible) in between the old shapes, and does not completely covers some of them.

More details about program tasks and the structure of luce.py program are given in the assignment elaboration on tasks and hints below (to follow…).


The music sequences

Below is some music sequences which you can use in this assignment work:

The original midi file The sequence csv file
mussorgsky_PE-1.midi mussorgsky_PE-1.csv
prokofiev_VF-8.midi prokofiev_VF-8.csv
satie_gymnopedie-1.midi satie_gymnopedie-1.csv
scriabin_op74-2.midi scriabin_op74-2.csv
no original midi chizhik.csv
no original midi fourth-octave.csv

You can play midi-files using QuickTime or similar software, and you can play the sequence csv-files using the JES function playSequence.py Python function by loading it in JES. Compare how crude and mangled the original midi-sound becomes in the sequence. The sequence files were created from the original midi-files by Ben Swift to whom I am very thankful. The midi-file are used here (by the virtue of their Artistic License) courtesy of Classical Piano Midi Pages.

Submission

You will have to submit one program file in this assignment and one sequence note csv file, one of those provided in The music sequences or one of your own (it can be fun to write them, even if you do have formal musical training):

  1. The Python/JES program, named luce.py, that contains all manipulation functions you implemented. This program should be based on the program skeleton luce.py. (Added on 1 October 2008: Since you will need the dictionary file MIDInotes.csv, you can define luce() function with three parameters — the directory name, the sequence file name and the dictionary file. Alternatively, you can define luce() with two arguments (as in the original template) but include setMediaPath() command into you program and then open MIDInotes.csv file. Needless to say, you will also need to submit this file alongside with the other two).

    Make sure that you fill in the preamble at the beginning of the luce.py program with your details!

    Any program file submitted without a completed preamble will be rejected without being marked.

  2. One csv file containing the note sequence which luce.py will "perform in colour". When we will run your program for marking, we can use a different csv file. So it is important to make your luce.py be able to work with any correctly formatted sequence file. One constraint, though — it sould not be too long (200-300 lines/notes is enough).


Submission protocol

To submit you work, you will have to use the command-line interface (ie, to open the Konsole and execute the submission command by typing and hitting the return button.)

Log into your DCS account (ground floor computer rooms), and execute the following steps:

  1. Start the Terminal (aka Konsole) application.

  2. cd into your assignment folder, something like this (replace u1234567 with your Uni ID):
         cd ~/u1234567/comp2720/ass2
         

  3. Now you can use the submit command to submit your assignment files:
         submit comp2720 ass2 luce.py
         submit comp2720 ass2 mymusic.csv
         submit comp2720 ass2 MIDInotes.csv (optional)
         
    Note that submit will only accept these three file names (case sensitive, so you must use lowercase!).

  4. Note that you can submit a file many times, we will always keep the last two submissions.

  5. Finally, you can check your assignment submission on https://cs.anu.edu.au/streams/ (click on View Marks button).

If you work on a different machine (your home computer or on one of the InfoCommons computers) and need to log in to your DCS account or transfer file to your DCS account (using the network, not a USB memory stick), you can achieve this by opening the Terminal or shell application and then use the following commands:

  1. To connect to you DCS account (replace u1234567 with your Uni ID):
         ssh  u1234567@partch.anu.edu.au
         
    and answer "yes" if required and type in your password. Upon logging in, you can navigate you directory using cd command.

  2. To copy files to the DCS directory from a computer outside DCS, do one of the following commands (assuming you are inside the folder which contains the file myfile.py you want to transfer):
    	scp myfile.py u1234567@partch.anu.edu.au:comp2720/myfolder/
         
    or, alternatively, to transfer all files in the current folder to the DCS account:
    	rsync -avuz * u1234567@partch.anu.edu.au:comp2720/myfolder/
         

 

All files must be submitted by Tuesday 21 October, 18:00 DLST


Extensions

Students will only be granted an extension on the submission deadline in exceptional circumstances. Work and sporting commitments are normally NOT sufficient grounds. If you think you have grounds for an extension, you should notify the course coordinator as soon as possible and provide written evidence in support of your case (e.g. medical certificate). The course coordinator will then decide whether to grant an extension and inform you as soon as practical.


Late Penalties

Penalties for late submissions are as follows.

How late less than 6 hours 6 to 24 hours 24 to 48 hours 48 to 72 hours 72 to 96 hours more than 96 hours
Penalty from 15 marks -0.5 -1 -2 -4 -8 -15 (forget it!)

Late penalties apply even if you submit just one file after the deadline.


Plagiarism

You should read the chapter in the Department of Computer Science Student Handbook that discusses assessment (Chapter 6, pages 17-25), particularly the sections headed Misconduct in examinations (which also applies to assignments and other forms of assessment) and Guidelines for assignments.

We will compare all submissions electronically, with any that are suspiciously similar being investigated by the lecturer. If such similarities cannot be satisfactorily explained, appropriate action (see the penalties mentioned in the handbook) will be taken.


Elaboration on Tasks and Hints

That's how a movie with the "colour sound track" may look like:

Colour Music

The movie was generated for about one third of initial sound track of Modest Mussorsgsky's Pictures at the Exhibition, Promenade–1 (to be honest, I have duplicated every frame several times to get approximately the same duration for the movie as the original sound track, and I also included the original MIDI sound track into the movie; the Assignment does not ask you to do the tall this — one movie frame per one note from the corresponding sequence file and no sound).

Now, I have been planning to provide additional elaborations and hints for this assignment long time ago, but as I looked at the assignment paper, it was clear to me that the original task descriptions were clear enough and detailed enough already. As I said at the beginning, the assignment 2 in terms of computational complexity is simpler (and the code should be shorter) than the assignment 1. But the assignment 2 is more advanced, meaning that you are expected to have better knowledge of Python programming techniques and overall programming skills. If this is the case, the effective ("awesome") list manipulation facilities of Python make the assignment 2 tasks easy to accomplish. Instead of going through every task and giving you hints how at could be tackled, I would ask you a few questions:

  • Have you followed the top-down programming approach while working on this assignment? Formulate the high level operations which the luce() function must execute (like open the sequence file, read the lines, determine the duration intervals, read the MIDInotes.csv file and build the (pitch->(key,octave)) dictionary, read every line in the sequence file: parse every line and determine the note pitch and duration, convert the pitch into the key and octave, and calculate the colour primaries and size of the corresponding colour shape, set the value of the shape's life span and its age, randomly generate the positions of the note on the canvas frame, put all those values into the shape-list, add the shape to the existing list of shapes; don't forget to fade the older shapes colour and age them, draw all the shapes from the shape list on the canvas, name the frame file appropriately and write the canvas into that file,… go on to the next note from the sequence). That's it (I told you this was going to be easy-:)! Once you identified an operation which the luce() function will use, define the corresponding function — give it a name and arguments, determine whether it should return a value, and if so, return an arbitrary value of the right type:

    def getShapeSize(duration, durIntervals):
    	return 1
    
    By this, you've created a function stab sufficient for the main function to execute, but the actual implementation of the function (its body) can be worked out later.

  • Did you separate the data which you need to describe and modify the coloured shapes which are displayed on the movie frames? Most of the data manipulations involve numbers, lists, perhaps tuples, but not the JES image objects. No need to drag them along while you are doing all that fading, ageing, etc.

  • How do you describe the colour shape object which represents a Note on the movie frame — using a list with the elements of colour, size, duration (life span), age, horizontal and vertical position? If so, this is a reasonable approach. But if you used classes (we shall talk about classes and Object-Oriented programming in Python at the very end of the course), then it is also OK.

  • How do you describe the whole collection of colour shapes which you draw on the current movie frame? Using list of shapes? If your shape is encoded as list (see previous item), then "current shapes" are represented as a list of lists. Don't be scared — we dealt with nested lists already: look up the lectures slides, check the textbook.

  • You can process the shapes list (or what data structure you use to describe shapes) when you need to fade or age the shape elements using the standard list looping technique. But in Python you can use functional programming techniques to efficiently process lists in just one line of code. Let's say you have a list of integers and you want to weed out all elements which are divisible by three. Here is how you can do it (I use randomly generated integers):

    from random import randint
    mylist = []
    for i in range(50):
    	mylist.append(randint(1,100))
    #mylist now has 50 randomly generated integers each between 1 and 100
    #define the function to determine whether the number is divisible by 3
    def not_divisible(x): return x % 3 != 0 
    #now I remove all element divisible by 3 elements by using the filter function
    mylist = filter(not_divisible,mylist)
    
    That's all! If you know how to define functions without naming them (so called lambda notations, we shall talk about this in lectures soon), this code can be made even shorter. Apart from filter() another very useful function for doing this sort of things is map(). Read about them (using the resources links from the course web page), and make use of them. All this is not necessary though — the good old loops will do as well.

    You may ask how to define, say, the fading function or the ageing function to use them with the above approach? But... this is what assignments are for — stretching your brain a little, isn't! Good luck, don't snap it!


Marking

The assignment marks will be awarded as follows:

0. For creating the program structure, including the movie object, reading the value of colour notes and including them into the program 2 point
1. For reading the sequence file and determining the duration intervals 1.5 point
2. For mapping note pitch to the octave and key, and for mapping the octave to sizes and keys to colours 2.5 points
3. For creating shapes matching the note pitch and
randomly placing them on the frame without going "overbaord"
2.5 points
4. For implementing the aging (fading note-shapes) effect 1.5 point
5. For numbering, naming and writing to frame files 1.5 point
6. For implementing advanced shapes non-overlapping effect 3.5 points

Last modified: 17/10/2008, 21:05