public static void main(String[] args) throws IOException, WavFileException
   {
      // Debug information
      System.out.println("Target number of frames: " + (int)(NUM_BEATS * FRAMES_PER_BEAT));
      System.out.println("Ideal number of frames : " + (int)(DURATION * SAMPLE_RATE));

      // Open file, determine num channels
      WavFile inFile = WavFile.openWavFile(new File(IN_FILE));
      numChannels = inFile.getNumChannels();

      double[][] buffer;

      // Read all of the file, and store it into an arraylist
      // for easy beat-based random-access later
      while (inFile.getFramesRemaining() > FRAMES_PER_BEAT)
      {
         buffer = new double[numChannels][FRAMES_PER_BEAT];
         inFile.readFrames(buffer, FRAMES_PER_BEAT);

         beats.add(buffer);
      }

      inFile.close();
      
      // initialize a beat to start at a random location
      currentBeat = (int)(Math.random() * beats.size());

      // Create the output file
      WavFile outFile = WavFile.newWavFile(new File(OUT_FILE), numChannels,
            (long) (NUM_BEATS * FRAMES_PER_BEAT), 16, SAMPLE_RATE);

      // Fill the output file
      for (int i = 0; i < NUM_BEATS; i++)
      {
         double[][] beat = null;

         switch (state)
         {
            // Nothing special. Increment our beat number
            case forward:
               beat = getForwardBeat(currentBeat);
               currentBeat++;
               if (currentBeat >= beats.size()) currentBeat = 0;
               break;

            // Reverse this beat. Decrement our beat number
            case backward:
               beat = getBackwardBeat(currentBeat);
               currentBeat--;
               if (currentBeat < 0) currentBeat = beats.size() - 1;
               break;

            // Jump to a new beat in the song
            // get new state and repeat count,
            // decrement our loop counter because we aren't writing this iteration
            case jump:
               currentBeat = (int) (Math.random() * beats.size());
               state = getState();
               repeat = getRepeat();
               i--;
               continue;
         }

         // If we have done our third repeat, get a new state
         switch (repeat)
         {
            case three:
               state = getState();
         }

         // Increments repeat, or randomizes if necessary
         repeat = getRepeat();

         // Write this beat to the file
         if (beat != null) outFile.writeFrames(beat, FRAMES_PER_BEAT);
      }

      outFile.close();
   }