나는 문제가 있으며 여기에 답변을 얻으려고합니다. 애플릿에서 작동해야하기 때문에 클라이언트 PC에 저장하지 않고 많은 미디 사운드를 만들고 싶습니다. 사운드 파트를 만드는 것이 문제는 아니지만 문제는이 사운드를 동시에 재생하는 것입니다. 나는 지금 asnwer를 위해 3 일 이상을 조사했다. 그러나 나를 도왔던 하나를 발견 할 수 없었다.Java에서 동시에 생성 된 MIDI 사운드 재생
: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]);
}
}
}
이 내가 내 소리를 만들 수있는 곳입니다 :
내 사운드 (오픈 spurce 프로젝트에서 그것의 발견 부분) : 여기
내가 지금 무엇을 가지고 여기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;
}
}
내 임시 Main 클래스 : 공용 클래스 테스트 {
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 ++ 스레드가 있다면 생각하지 않습니다. 동시에 쓰지 않을 것이고 성능은 그렇게 좋지 않을 것입니다. 나는 그들이 동시에 소리를내는 예를 보았지만 파일에서 사운드를로드했고, 미디로 시도했을 때 작동하지 않았다.