1 2 Previous Next 18 Replies Latest reply: Nov 23, 2010 8:31 PM by Tekker RSS

    Multiple MIDI Sequencers In Java Applet?

    Tekker
      Hi all,

      I'm working on a music applet and need to have multiple MIDI sequencers playing simultaneously. I have some test code and it works in my IDE (I'm using JGrasp) but when I try to open the applet in a web browser, it doesn't play the sequencers at the same time. It only plays one sequencer at a time and switches (seems to be random) back and forth between them instead of just letting them both play together. Is there any reason why two (or more) sequencers won't play together in an applet when they do in JGrasp? Is this just simply a limitation within applets or is there some kind of work around to fix this?

      I know you can do different tracks/channels in a single sequencer, but I really need it to be separate sequencers playing simultaneously... Without getting into too much music/drum theory, I'm making a polyrhythm metronome and need to have different sequencers playing at different tempos (which you can't do with a single sequencer). If anyone has any ideas on how to get multiple sequencers to play nicely together in an applet that would be greatly appreciated.

      Here is my sample program:
      import java.util.*;
      import javax.swing.*;
      import javax.sound.midi.*; 
       
      public class MetronomeTestApplet extends JApplet
      {
           public void init()
           {
                MetronomeTest metTest = new MetronomeTest();
                metTest.play();
           }
      }
       
      class MetronomeTest
      {
           Sequencer sequencer1=null;
           Sequencer sequencer2=null;
           
           Sequence sequence1=null;
           Sequence sequence2=null;
           
           Track track1=null;
           Track track2=null;
           
           MidiEvent newEvent=null;
           
           int volume = 90;     
           int tempo     = 100;
           
           public MetronomeTest()
           {     
                try
                {     // SEQUENCER 1
                     sequencer1 = MidiSystem.getSequencer();
                     sequencer1.open();
                     sequence1 = new Sequence(Sequence.PPQ, 16);
                     track1 = sequence1.createTrack();
                     
                     ShortMessage instrumentMsg = new ShortMessage();
                     instrumentMsg.setMessage(ShortMessage.PROGRAM_CHANGE, 0, 115, 0);          // 115 == woodblock
                     track1.add(new MidiEvent(instrumentMsg, 0));
                     
                     // SEQUENCER 2
                     sequencer2 = MidiSystem.getSequencer();
                     sequencer2.open();
                     sequence2 = new Sequence(Sequence.PPQ, 16);
                     track2 = sequence2.createTrack();
                     
                     instrumentMsg = new ShortMessage();
                     instrumentMsg.setMessage(ShortMessage.PROGRAM_CHANGE, 0, 117, 0);          // 117 == melodic tom
                     track2.add(new MidiEvent(instrumentMsg, 0));
                }
                catch (Exception e) { e.printStackTrace(); }
           }
           
           public void destroy()
           {
                sequencer1.stop();
                sequencer1.close();
                
                sequencer2.stop();
                sequencer2.close();
           }
           
           public void play()
           {
                try
                {               
                     // LOAD SEQUENCE 1               
                     for (int i=0; i<4; i++)
                     {
                          ShortMessage noteOnMsg = new ShortMessage();
                          noteOnMsg.setMessage(ShortMessage.NOTE_ON, 0, 60, volume);
                          track1.add(new MidiEvent(noteOnMsg, 0 + 16*i));
                          
                          ShortMessage noteOffMsg = new ShortMessage();
                          noteOffMsg.setMessage(ShortMessage.NOTE_OFF, 0, 60, volume);
                          track1.add(new MidiEvent(noteOffMsg, 16 + 16*i));
                     }
                     
                     // LOAD SEQUENCE 2               
                     for (int i=0; i<8; i++)
                     {
                          ShortMessage noteOnMsg = new ShortMessage();
                          noteOnMsg.setMessage(ShortMessage.NOTE_ON, 0, 60, volume);
                          track2.add(new MidiEvent(noteOnMsg, 0 + 8*i));
                          
                          ShortMessage noteOffMsg = new ShortMessage();
                          noteOffMsg.setMessage(ShortMessage.NOTE_OFF, 0, 60, volume);
                          track2.add(new MidiEvent(noteOffMsg, 8 + 8*i));
                     }
                     
                     // LOAD AND START SEQUENCERS
                     sequencer1.setSequence(sequence1);
                     sequencer1.setTempoInBPM(tempo);
                     sequencer1.setLoopCount(Sequencer.LOOP_CONTINUOUSLY);
                     
                     sequencer2.setSequence(sequence2);
                     sequencer2.setTempoInBPM(tempo);
                     sequencer2.setLoopCount(Sequencer.LOOP_CONTINUOUSLY);
                                    
                     sequencer1.start();
                     sequencer2.start();
                }
                catch (Exception e) { e.printStackTrace(); }
           }
      }
      And the code for my html document:
      <html>
      <body>
      <CENTER><applet code="MetronomeTestApplet.class" width="1000" height="700"></applet></CENTER>
      </body>
      </html>
      Thanks,
      -tkr

      Edited by: Tekker on Nov 21, 2010 5:45 PM
        • 1. Re: Multiple MIDI Sequencers In Java Applet?
          793415
          My first advice to you would be "Don't swallow exceptions" (http://pscode.org/javafaq.html#stacktrace).

          When I ran the applet and got no sound whatsoever, it was only after getting the stack trace that I knew why.
          • 2. Re: Multiple MIDI Sequencers In Java Applet?
            Tekker
            Hi Andrew,

            Thanks for your response. That's strange that you got no sound, because the sound works here. In JGrasp it works perfectly, exactly like I want it too with both Sequencers running simultaneously. I also get sound when I open the applet in a web browser (I'm using Firefox) but the two sequencers don't play together at the same time but randomly switches between the two... So the sound is working here, but the two sequencers aren't functioning correctly when opened in a web browser.

            I added in the "e.printStackTrace()" in both of the catches but it didn't show any errors when I ran the applet in JGrasp. I'll update the code in my original post to include these.

            Thanks again,
            -tkr
            • 3. Re: Multiple MIDI Sequencers In Java Applet?
              793415
              Tekker wrote:
              ..That's strange that you got no sound, because the sound works here.
              javax.sound.midi.MidiUnavailableException: MIDI OUT transmitter not available
                      at com.sun.media.sound.AbstractMidiDevice.createTransmitter(AbstractMidiDevice.java:444)
                      at com.sun.media.sound.AbstractMidiDevice.getTransmitter(AbstractMidiDevice.java:299)
                      at javax.sound.midi.MidiSystem.getSequencer(MidiSystem.java:451)
                      at javax.sound.midi.MidiSystem.getSequencer(MidiSystem.java:348)
                      at MetronomeTest.<init>(MetronomeTestApplet.java:34)
              ...
              :-(
              ..In JGrasp it works perfectly, exactly like I want it too with both Sequencers running simultaneously. I also get sound when I open the applet in a web browser (I'm using Firefox) but the two sequencers don't play together at the same time but randomly switches between the two... So the sound is working here, but the two sequencers aren't functioning correctly when opened in a web browser.
              You've only tested one browser so far? (chuckle) You'll probably find no two browsers do the same thing. And that is the thing about both Java Sound and Applets. There are many inconsistent implementations.

              As far as why JGrasp is playing it OK but FF not, you might look into the exact Java micro-versions used by each (dump the properties in the init() section).

              OTOH I think that even your little demo, which acts differently in 3 different environments, does not bode well for playing MIDI in an applet.
              • 4. Re: Multiple MIDI Sequencers In Java Applet?
                DarrylBurke
                First of all, I would try running the two sequencers on separate threads.

                I don't see the exact same problem you posted, but whether running from the IDE (NetBeans) via AppletViewer, or in a browser, some beats are occasionally missed, presumably because both sequencers requested their events on the exact same clock tick. Multithreading may  solve that, or not.

                db
                • 5. Re: Multiple MIDI Sequencers In Java Applet?
                  Tekker
                  Hi Andrew,

                  RE: The "MidiUnavailableException"... According to the error you posted it looks like it's crashing on line 34, which appears to be "sequencer1 = MidiSystem.getSequencer();". But I'm not quite sure why that caused a problem because I included the javax.sound.midi package and declared sequencer1. So as far as I can tell that line should (theoretically) work. Do you have any ideas on what caused that?

                  IE and Flock also produce the same results as Firefox (only one sequencer playing and switching randomly back and forth between them).

                  Thanks again,
                  -tkr
                  • 6. Re: Multiple MIDI Sequencers In Java Applet?
                    Tekker
                    Hi Darryl,

                    Putting the sequencers in separate threads is a great idea, I'll give that a try and report back. :)

                    Thanks,
                    -tkr
                    • 7. Re: Multiple MIDI Sequencers In Java Applet?
                      DarrylBurke
                      IE and Flock also produce the same results as Firefox (only one sequencer playing and switching randomly back and forth between them).
                      More and more, it looks like the problem/s are at least to some extent hardware (and maybe OS) dependent. I tested on a quad core 2.66 running Win7, and there was no random switching.

                      db
                      • 8. Re: Multiple MIDI Sequencers In Java Applet?
                        Tekker
                        I just tried implementing the sequencers in their own threads but unfortunately it gives exactly the same results, where it works in JGrasp but not in the web browser.

                        Here's the threaded version:
                        import java.util.*;
                        import javax.swing.*;
                        import javax.sound.midi.*; 
                         
                        public class MetronomeTestApplet extends JApplet
                        {
                             MetronomeTest metronome1;
                             MetronomeTest metronome2;
                             
                             public void init()
                             {
                                  metronome1 = new MetronomeTest(50, 115);          // (tempo, instrument)          115 = woodblock
                                  metronome2 = new MetronomeTest(100, 117);          // (tempo, instrument)          117 = melodic tom     
                                  
                                  metronome1.start();
                                  metronome2.start();
                             }
                             
                             public void destroy()
                             {
                                  metronome1.close();
                                  metronome2.close();
                             }
                        }
                        
                        class MetronomeTest extends Thread
                        {
                             Sequencer sequencer=null;
                             Sequence sequence=null;
                             Track track=null;
                             
                             MidiEvent newEvent=null;
                             
                             int volume = 90;     
                             int tempo = 100;
                             
                             public MetronomeTest(int tempo, int instrument)
                             {
                                  this.tempo = tempo;
                                  
                                  try
                                  {     sequencer = MidiSystem.getSequencer();
                                       sequencer.open();
                                       sequence = new Sequence(Sequence.PPQ, 16);
                                       track = sequence.createTrack();
                                       
                                       ShortMessage instrumentMsg = new ShortMessage();
                                       instrumentMsg.setMessage(ShortMessage.PROGRAM_CHANGE, 0, instrument, 0);
                                       track.add(new MidiEvent(instrumentMsg, 0));
                                  }
                                  catch (Exception e) { e.printStackTrace(); }
                             }
                             
                             public void close()
                             {
                                  sequencer.stop();
                                  sequencer.close();
                             }
                             
                             public void run()
                             {
                                  try
                                  {     for (int i=0; i<4; i++)
                                       {     ShortMessage noteOnMsg = new ShortMessage();
                                            noteOnMsg.setMessage(ShortMessage.NOTE_ON, 0, 60, volume);
                                            track.add(new MidiEvent(noteOnMsg, 0 + 16*i));
                                            
                                            ShortMessage noteOffMsg = new ShortMessage();
                                            noteOffMsg.setMessage(ShortMessage.NOTE_OFF, 0, 60, volume);
                                            track.add(new MidiEvent(noteOffMsg, 16 + 16*i));
                                       }
                                       
                                       sequencer.setSequence(sequence);
                                       sequencer.setTempoInBPM(tempo);
                                       sequencer.setLoopCount(Sequencer.LOOP_CONTINUOUSLY);
                                  
                                       sequencer.start();
                                  }
                                  catch (Exception e) { e.printStackTrace(); }
                             }
                        }
                        If you have more things I can try, I'd greatly appreciate it. :)

                        Thanks,
                        -tkr
                        • 9. Re: Multiple MIDI Sequencers In Java Applet?
                          Tekker
                          Wow, really? Did you hear both sounds playing together or just one of the sounds? Also, did you let it play for a while? Because sometimes it takes a good amount of time for it to switch sounds from one sound to the other.

                          Thanks,
                          -tkr
                          • 10. Re: Multiple MIDI Sequencers In Java Applet?
                            DarrylBurke
                            Yes, I let it play for a while and heard both sounds together, but occasionally, instead of a 'double' sound only the higher note sounds.

                            What's your hardware configuration? Do you have access to another machine with considerably different hardware (preferably a faster machine) to test on?

                            db
                            • 11. Re: Multiple MIDI Sequencers In Java Applet?
                              Tekker
                              Here is my hardware setup:

                              Windows XP Pro
                              Mobo: Gigabyte EP45-UD3P
                              Processor: Intel Core2 Quad Q6700
                              Memory: 4GB Kingston High Speed (Gaming) RAM
                              Sound: Mobo's on-board sound and M-Audio Profire 2626 (which is an external audio recording interface that connects to the computer via firewire)

                              I just tested it on another computer which has a very different hardware configuration, AMD dual core processor, ASUS mobo, and 2GB of RAM, but it has the same OS (Windows XP Pro) and it produced the same result in the web browser.

                              Thanks,
                              -tkr
                              • 12. Re: Multiple MIDI Sequencers In Java Applet?
                                captfoss
                                Tekker wrote:
                                If anyone has any ideas on how to get multiple sequencers to play nicely together in an applet that would be greatly appreciated.
                                I'd imagine it's simply a resource issue... It wouldn't suprise me if applets were limited to a single sequencer. You might be able to play with the security settings and such, but, you'd be in "tinker with it" territory there.

                                Might I suggest converting your applet to a web start application?
                                • 13. Re: Multiple MIDI Sequencers In Java Applet?
                                  Tekker
                                  captfoss, I'm not sure if it's an applet limitation or what it is... Darry said he was able to get it working in windows 7 and heard both sounds playing together (but it skipped every once in a while). So if this is some kind of OS issue, then that's way over my head to try to figure out. :(

                                  But on the plus side, I was able to get it working with a single sequencer by adjusting the resolution (PPQ) of the sequencer and doing some calculations to figure out where to put each beat in the sequencer to "simulate" different tempos within the one sequencer. This was the first method I had tried, but for whatever reason I wasn't able to get it to work before and so I started working on the multiple sequencer method. But after reading captfoss' post the multiple-sequencer method in an applet appeared to be a lost cause, so I started over from scratch on my original method and actually got it working this time. I'm not sure what I did different, but I'm happy it works now! :)

                                  Thanks again for your help Andrew, Darry, and captfoss!

                                  -tkr
                                  • 14. Re: Multiple MIDI Sequencers In Java Applet?
                                    DarrylBurke
                                    Tekker wrote:
                                    Thanks again for your help Andrew, Darry, and captfoss!
                                    You're welcome, and I'm happy you had a workaround already in mind!

                                    db
                                    1 2 Previous Next