Musical Console: Part 1 [Katy King]

I decided to have a little fun with one of the new Console features.  I wrote a quick program that will load a text file containing a series of {freqeuency, duration} pairs and play it using Console.Beep().  The program loads the integer data into a Song class.  A Song consists of an array of Note types, which are {frequency, duration} pairs.  Frequency is in Hertz; duration is in milliseconds; a zero frequency represents a rest.  Playing a Song calls Note.Play on each Note, which either calls Thread.Sleep() for a rest or Console.Beep() for a note.

I included two data files: “twinkle.dat” is “Twinkle, Twinkle, Little Star” (also the A-B-C song) and “teapot.dat” is “I'm a Little Teapot.”  You can download the code and data files from https://msdn.microsoft.com/netframework/downloads/samples/bclsamples/. Of course, you can also easily make your own dat files.

Caveats:

  • This was quick-and-dirty, not polished code.  There is no error checking, so an invalid filename or file format is going to give you an exception.  Beep() requires that the frequency must be between 37 and 32767, inclusive, and that the duration must be positive.  I'm using a zero-frequency Note to represent a rest, but past that, an invalid frequency or duration will cause an exception.
  • Frequencies must be integer, and so will be very slightly (<1Hz – not enough to be noticeable) off the true notes.  (See https://www.techlib.com/reference/musical_note_frequencies.htm for a table and explanation of musical note frequencies.).
  • I did the songs from memory, so if the notes or timing isn't quite the way you know them, I'll take the blame. :-)

So, the title says Part 1, indicating some room to consider improvements. Here are some of the ideas I’ve had for making this better in Part 2:

  • Error checking. :-)
  • Allow data files to specify note names (A, C, F#) instead of frequencies (440, 262, 370).  This just requires a table lookup, and a means to specify which octave you want the note to be in. We would probably use generic collections for this.
  • Allow data files to specify the length of notes in musical terms such as “whole note” or “quarter note” instead of milliseconds.  The song or the player can set the tempo for the song.
  • Allow the tempo to be easily adjusted with an extra command line argument (for example, passing in 2 would double the tempo).
  • Read data from a MIDI file or other type of music or sound file instead of a text file.  This would also require some conversion, as the capabilities for a sound file are beyond those of a Beep().
  • Have some cool console color logic with the playing of the song
  • Turn a computer keyboard into a (primitive) musical keyboard, reading key presses as notes.  An interesting limitation, considering these are new features, is that Console does not include the KeyDown and KeyUp events, so you can’t tell how long the key was held down.