Como tocar um conjunto de freqüências (Chords) ao mesmo tempo com o pacote javax.sound.sampled

Eu estou tentando implementar um sistema onde eu dou um conjunto de freqüências para ser jogado de uma só vez, atualmente posso jogar cada freqüência individualmente. Abaixo eu tenho um código, que reproduz a frequência dada, um de cada vez.

import java.applet.*; import java.io.*; import java.net.*; import javax.sound.sampled.*; public final class StdAudio { public static final int SAMPLE_RATE = 44100; private static final int BYTES_PER_SAMPLE = 2; // 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; private static SourceDataLine line; // to play the sound private static byte[] buffer; // our internal buffer private static int bufferSize = 0; // not-instantiable private StdAudio() { } // static initializer static { init(); } // open up an audio stream private static void init() { try { // 44,100 samples per second, 16-bit audio, mono, signed PCM, little Endian AudioFormat format = new AudioFormat((float) SAMPLE_RATE, BITS_PER_SAMPLE, 1, true, false); DataLine.Info info = new DataLine.Info(SourceDataLine.class, format); line = (SourceDataLine) AudioSystem.getLine(info); line.open(format, SAMPLE_BUFFER_SIZE * BYTES_PER_SAMPLE); buffer = new byte[SAMPLE_BUFFER_SIZE * BYTES_PER_SAMPLE/3]; } catch (Exception e) { System.out.println(e.getMessage()); System.exit(1); } // no sound gets made before this call line.start(); } /** * Close standard audio. */ public static void close() { line.drain(); line.stop(); } /** * Write one sample (between -1.0 and +1.0) to standard audio. If the sample * is outside the range, it will be clipped. */ public static void play(double in) { // clip if outside [-1, +1] if (in  +1.0) in = +1.0; // convert to bytes short s = (short) (MAX_16_BIT * in); buffer[bufferSize++] = (byte) s; buffer[bufferSize++] = (byte) (s >> 8); // little Endian // send to sound card if buffer is full if (bufferSize >= buffer.length) { line.write(buffer, 0, buffer.length); bufferSize = 0; } } /** * Write an array of samples (between -1.0 and +1.0) to standard audio. If a sample * is outside the range, it will be clipped. */ public static void play(double[] input) { for (int i = 0; i < input.length; i++) { play(input[i]); } } private static double[] tone(double hz, double duration) { int N = (int) (StdAudio.SAMPLE_RATE * duration); double[] a = new double[N+1]; for (int i = 0; i <= N; i++) a[i] = amplitude * Math.sin(2 * Math.PI * i * hz / StdAudio.SAMPLE_RATE); return a; } /** * Test client - play an A major scale to standard audio. */ public static void main(String[] args) { double hz = 440.4// 440.4 Hz for 1 sec double duration = 1.0; double[] a = tone(hz,duration); StdAudio.play(a); } 

}

Neste exemplo , Tone abre um único SourceDataLine para cada Note , mas você pode abrir tantas linhas quanto notas no seu acorde. Em seguida, write() cada Note do acorde para uma linha separada. Você pode criar um efeito de arpejo usando o Note.REST .

Basta sumr os valores de amostra em cada ponto de tempo e dividir por um fator de escala apropriado para manter seus valores no intervalo. Por exemplo, para jogar A 440 e C 523.25 ao mesmo tempo:

 double[] a = tone(440,1.0); double[] b = tone(523.25,1.0); for( int i=0; i 

você poderia usar tópicos diferentes para cada freqüência 🙂

aqui você pode encontrar um pequeno exemplo de threads em java

Espero que isso ajude você 🙂