問題があり、ここで答えを得たいと思っています。アプレットで動作するはずなので、クライアント PC に保存せずに多くの MIDI サウンドを作成したいと考えています。音を作る部分が問題ではなく、これらの音を同時に鳴らすことが問題なのです。私は3日以上答えを探しましたが、私を助けるものを見つけることができませんでした.
これが私が現時点で持っているものです:
My Sound (open-spur プロジェクトでその一部を見つけました):
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]);
}
}
}
これは私が自分のサウンドを作成する場所です:
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;
}
}
ここで私の一時的なメインクラス: 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());
}
}
スレッドについて考えましたが、20 ~ 30++ のスレッドがある場合、それは同時に行われず、パフォーマンスはそれほど良くないと思います。同時にサウンドを再生する例を見ましたが、ファイルからサウンドをロードし、midi で試してみると機能しませんでした。