3

I have an applet which creates music using the JFugue API and plays it for the user. It allows the user to input a music phrase which the piece will be based on, or lets them choose to have a phrase generated randomly. I had been using the following method (successfully) to simply stop and start the music, which runs in a thread using the Player class from JFugue.

I generate the music using my classes and user input from the applet GUI...then...

private playerThread pthread;
private Thread threadPlyr;
private Player player;
(from variables declaration)

public void startMusic(Pattern p) // pattern is a JFugue object which holds the generated music
{
if (pthread == null)
{ pthread = new playerThread(); }
else
{
    pthread = null;
    pthread = new playerThread();
}
if (threadPlyr == null)
{ threadPlyr = new Thread(pthread); }
else
{
    threadPlyr = null;
    threadPlyr = new Thread(pthread);
}
pthread.setPattern(p);
threadPlyr.start();

}

class playerThread implements Runnable // plays midi using jfugue Player
    {
        private Pattern pt;
        public void setPattern(Pattern p)
        {
            pt = p;
        }
        @Override
        public void run()
        {
                try
                {
                    player.play(pt); // takes a couple mins or more to execute
                    resetGUI();
                }
                catch (Exception exception)
                {
                }
        }
    }

And the following to stop music when user presses the stop/start button while Player.isPlaying() is true:

    public void stopMusic()
{
threadPlyr.interrupt();
threadPlyr = null;
pthread = null;
player.stop();
}

Now I want to implement a feature which will allow the user to change parameters while the music is playing, create an updated music pattern, and then play THAT pattern. Basically, the idea is to make it simulate "real time" adjustments to the generated music for the user.

Well, I have been beating my head against the wall on this for a couple of weeks. I've read all the standard java documentation, researched, read, and searched forums, and I have tried many different ideas, none of which have succeeded.

The problem I've run into with all approaches I've tried is that when I start the new thread with the new, updated musical pattern, all the old threads ALSO start, and there is a cacophony of unintelligible noise instead of my desired output.

From what I've gathered, the issue seems to be that all the methods I've come across require that the thread is able to periodically check the value of a "flag" variable and then shut itself down from within its "run" block in response to that variable. However, since my thread makes a call that takes several minutes minimum to execute (playing the music), and I need to terminate it WHILE it is executing this, there is really no safe way to do so.

So, I'm wondering if there is something I'm missing when it comes to threads, or if perhaps I can accomplish my goal using a totally different approach. Any ideas or guidance is greatly appreciated! Thank you!

granmoe
  • 312
  • 1
  • 11
  • Depending on how the long running method is written, you **may** be able to interrupt the thread. – Patricia Shanahan Nov 12 '12 at 05:17
  • Actually, I can successfully _interrupt_ the thread. The problem arises from my being unable to kill this thread. (see above) I am trying to start a new thread with different parameters, as a "replacement" for the original thread. Kill the old one, start a fresh new one. BUT, I have been unable to terminate this kind of thread. – granmoe Nov 12 '12 at 20:04
  • Can you interrupt it in the sense of being able to catch the InterruptedException at the top level? If so, you should be able to return from the run method, which would terminate it. – Patricia Shanahan Nov 12 '12 at 20:54
  • @PatriciaShanahan, I tried catching an InterruptedException, but I can't do that and still implement runnable since runnable doesn't throw that kind of exception. Any advice? – granmoe Nov 16 '12 at 23:15

1 Answers1

1

Instead of playing the entire sequence, play a short part of it. Then check for abort, and if not play the next part. You could use the sub pattern interface, the tokenizing interface, or even carefully stream fragments to the pattern from another thread maybe.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
  • This is a very interesting idea...I'm going to mess with it tomorrow. As long as there are no "hiccups" that affect it musically, I think this could possibly work. – granmoe Nov 12 '12 at 05:58
  • OK, this may work. So far, I've done a test of this form with JFugue's StreamingPlayer: for (int i = 0; i < 3; i++) { player.play("Cq Gq "); } And it seems to be working as promised with no delays between iterations. Can you give any more detail on the sub pattern interface? I'm not super familiar with the guts of the JFugue API. I am also confused about how to stream fragments from one thread to the thread that is playing the fragments. – granmoe Nov 13 '12 at 02:18