Finch Dances to Midi

In this assignment, you will program the Finch to play Midi files and dance to them.  To help you do this, your teacher will provide you with a wrapper class, called MidiPlayer.java, that you should copy into your project. You can view the commented source of this file for information on how to use the methods of the class. To complete the program you will need to use the following methods from the MidiPlayer class:

  • public Sequence getSequence (File file) throws IOException, InvalidMidiDataException, Exception Gets the sequence from the file object sent to the method.  The sequence generated is then passed to the play method.
  • public void play(Sequence sequence, boolean loop) throws InvalidMidiDataException Plays the Midi file encapsulated in sequence.  The second argument is whether to loop play of the file (true for looping, false for no looping).
  • public int getBeatInterval() This method returns the interval, in milliseconds, between beats of the song.
  • public void close() This closes the sequence and shuts down the player.

To write your program, you should create two methods in a class – playMidi( ), which gets the midi filename from the user and starts the Finch dancing, and dance(), which contains a series of steps that play will select from. Their method declarations are:

  • public void playMidi( )
  • public void dance(int step)

The main() method of your program should instantiate an object of the class containing dance() and playMidi(), call the playMidi() method, and invoke System.exit(0). The playMidi() method should instantiate globally defined MidiPlayer and Finch objects.  It should request the name of a Midi file from a console prompt. Using the Scanner class, assign the file name to a String.  The playMidi() method should then convert the String into a File object using the File class.  At this point, you will need to use the File object as an argument in the getSequence() method of the Midiplayer class.  This method returns a Sequence class object which is needed to call the play() method of the MidiPlayer class. Notice that getSequence() throws three exceptions.  Your program should distinguish between these exceptions as follows:

  • If an IOException is caught, the user entered in a bad filename, and the program should loop back to where the user was asked to enter a filename.
  • If an InvalidMidiDataException is caught, the Midi file was corrupt.  The program should exit using System.exit(0) and print an error message like “Data corrupt”.
  • If a general Exception is caught, the program should exit and print an error message like “Unknown Error”.

Once a Sequence class object is generated, you should call the MidiPlayer’s play() method.  Note that it too throws an exception, and you will need to catch this in the same way you caught the InvalidMidiDataException for the getSequence() method.

The playMidi() method should use the getBeatInterval() method to determine the time between beats. This value will be used by the Finch to move to the beat. Start the Finch in a loop that occurs so long as its beak is not pointed up.  The dance() method (see below) will be called using one of six step values as an argument.  Finally close the MidiPlayer and quit the Finch to end the playMidi() method.

Create a dance() method that switches between six different steps, and use the loop to go through these steps in order.  The steps are up to you, but they should look fairly different and each should have its own LED color.  Use the setWheelVelocities() and setLED() methods to accomplish this.  Time the steps to go with the beats by moving to the next one at the interval between beats.

Once the Finch is picked up and pointed with beak up, the MidiPlayer should close and the Finch should quit. Again, this functionality is built into the playMidi() method.

We have provided you with four midi files (and a corrupt file for testing).  Place these in the directory for your Finch code. You can get more midi files at http://free.mididb.com/.