I have a problem and I hope to get here an answer. I want to create many midi sounds without saving them on the client pc, because this should work in an Applet. The creating sound part isn't the problem, the problem is to play these sound simultaneously. I searched now more than 3 days for an asnwer, but couldn't find one that helped me.

Here is what i have at the moment:
My Sound (found part of it in an open-spurce project):
import java.io.*;
import javax.sound.sampled.*;
import java.net.URL;
import javax.sound.*;
 
public class Sound {
 
    /**
     *  The sample rate - 44,100 Hz for CD quality audio.
     */
    public static int channels = 2;
 
 
 
 
    public static final int SAMPLE_RATE = 44100;
 
    private static final int BYTES_PER_SAMPLE = 4;                // 16-bit audio
    private static final int BITS_PER_SAMPLE = 16;                // 16-bit audio
    private static final double MAX_16_BIT = Short.MAX_VALUE;     // 32,767
    private static final int SAMPLE_BUFFER_SIZE = 4096;
 
 
    static SourceDataLine[] line = new SourceDataLine[channels];    // to play the         sound
    private static byte[][] buffer = new byte[2][];         // our internal buffer
    private static int i = 0;             // number of samples currently in internal buffer
    private static int i2 = 0;
 
    public static Mixer mainmix;
 
    // static initializer
   public Sound()
   {
       init();
   }
 
    // open up an audio stram
    static void init() {
        try {
 
            Mixer.Info[] mixerinfo = AudioSystem.getMixerInfo();    
 
            mainmix = AudioSystem.getMixer(mixerinfo[0]);
 
            Line.Info lineinf[] = mainmix.getSourceLineInfo();
 
            // 44,100 samples per second, 16-bit audio, mono, signed PCM, little Endian
            AudioFormat format = new AudioFormat((float) SAMPLE_RATE, BITS_PER_SAMPLE, 2, true, false);
            DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
 
 
            line[0] = (SourceDataLine) mainmix.getLine(info);
            line[1] = (SourceDataLine) mainmix.getLine(info);
            //line[2] = (SourceDataLine) mainmix.getLine(info);
 
            Control[] linectrl = line[0].getControls();
            Control[] linectrl1 = line[1].getControls();
 
 
 
            //line = (SourceDataLine) AudioSystem.getLine(info);
            line[0].open(format, SAMPLE_BUFFER_SIZE * BYTES_PER_SAMPLE);
            line[1].open(format, SAMPLE_BUFFER_SIZE * BYTES_PER_SAMPLE);
           // line[2].open(format, SAMPLE_BUFFER_SIZE * BYTES_PER_SAMPLE);
            //line[1].open(format, SAMPLE_BUFFER_SIZE * BYTES_PER_SAMPLE);
 
 
 
            // the internal buffer is a fraction of the actual buffer size, this choice is arbitrary
            // it gets diveded because we can't expect the buffered data to line up exactly with when
            // the sound card decides to push out its samples.
            buffer[0] = new byte[SAMPLE_BUFFER_SIZE * BYTES_PER_SAMPLE];
            buffer[1] = new byte[SAMPLE_BUFFER_SIZE * BYTES_PER_SAMPLE];
            //buffer[2] = new byte[SAMPLE_BUFFER_SIZE * BYTES_PER_SAMPLE];
        } catch (Exception e) {
            System.out.println(e.getMessage());
            System.exit(1);
    }
 
 
        // no sound gets made before this call
        line[0].flush();
        line[0].start();
        line[1].flush();
        line[1].start();
}
 
    /**
     * Close standard audio.
     */
    public final void close() {
        line[0].drain();
        line[0].stop();
 
       line[1].drain();
       line[1].stop();        
    }
 
    public final void play(double in) {
 
        // clip if outside [-1, +1]
        if (in < -1.0) in = -1.0;
        if (in > +1.0) in = +1.0;
 
        // convert to bytes
        short s = (short) (MAX_16_BIT * in);
        buffer[0][i++] = (byte) s;
        buffer[0][i++] = (byte) (s >> 8);   // little Endian
        buffer[0][i++] = (byte) s;
        buffer[0][i++] = (byte) (s >> 8);   // little Endian
 
 
        // send to sound card if buffer is full        
        if (i >= buffer.length) {
            line[0].write(buffer[0], 0, 4);
 
            i = 0;
        }
    }
 
    public void play(double[] input) {
        for (int i = 0; i < input.length; i++) {
            play(input[i]);
 
        }
    }
 
    public final void play(double in, double an) {
 
 
        // clip if outside [-1, +1]
        if (in < -1.0) in = -1.0;
        if (in > +1.0) in = +1.0;
 
        // convert to bytes
        short s = (short) (MAX_16_BIT * in);
        buffer[1][i++] = (byte) s;
        buffer[1][i++] = (byte) (s >> 8);   // little Endian
        buffer[1][i++] = (byte) s;
        buffer[1][i++] = (byte) (s >> 8);   // little Endian
 
        // clip if outside [-1, +1]
        if (an < -1.0) an = -1.0;
        if (an > +1.0) an = +1.0;
 
        // convert to bytes
        short a = (short) (MAX_16_BIT * an);
        buffer[0][i2++] = (byte) a;
        buffer[0][i2++] = (byte) (a >> 8);   // little Endian
        buffer[0][i2++] = (byte) a;
        buffer[0][i2++] = (byte) (a >> 8);   // little Endian
 
        // send to sound card if buffer is full        
        if (i >= buffer.length) {
 
            line[1].write(buffer[1], 0, 4);
            line[0].write(buffer[0], 0, 4);
 
 
            i2 = 0;
            i = 0;
        }
    }
 
 public void play(double[] input,double[] input1) {
        for (int i = 0; i < input.length; i++) {
            play(input[i],input1[i]);
 
        }
    }
}

This is where i create my sound:
public class Note {
    private final int SAMPLE_RATE = 44100;
    private double[] tone;
    public Note(double hz, double duration, double amplitude)
    {
        int N = (int) Math.round(SAMPLE_RATE * duration);
        tone = new double[N+1];
        for (int i = 0; i <= N; i++)
            tone[i] = amplitude * Math.sin(2 * Math.PI * i * hz / SAMPLE_RATE);
    }
 
    public double[] getTone()
    {
        return tone;
    }
 
}

Here my Temporary Main class:
 
public class test {
public static void main(String[] args) {
        Sound sound = new Sound();
 
        //Note(hz (freg),seconds (duration),vol(amplitude))
        Note note1 = new Note(50.0,3.0,6);
        Note note2 = new Note(10.0,3.0,6);
        sound.play(note1.getTone(),note2.getTone());
    }
 
}

I thought about Threads but I don't think if I have 20-30++ Thread, that won't be simultaneously and the perfomance wouldn't be that good. I saw examples were they played sounds simultaneously, but then they loaded the sounds from a file and when I tried it with midi it didn't work.