Read a great tutorial online on playing audio in Java, created the following
Free Starter Content, MIT License
package audio;
import java.nio.ByteBuffer;
import java.util.logging.Logger;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
public class AudioUtil {
private static Logger logger = Logger.getLogger(AudioUtil.class.getName());
final static int SAMPLING_RATE = 44100; // Audio sampling rate
final static int SAMPLE_SIZE = 2; // Audio sample size in bytes
final static double noteSpeedRatio = 0.2; // Usually set to 1 can be increased to increase Tempo
public static void playSineWaveAtFrequencyForSeconds(double frequency, double seconds) throws InterruptedException, LineUnavailableException {
//Open up audio output, using 44100hz sampling rate, 16 bit samples, mono,
//and big endian byte ordering
AudioFormat format = new AudioFormat(SAMPLING_RATE, 16, 1, true, true);
DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
if (!AudioSystem.isLineSupported(info)){
System.out.println("Line matching " + info + " is not supported.");
throw new LineUnavailableException();
}
SourceDataLine line = (SourceDataLine)AudioSystem.getLine(info);
line.open(format);
line.start();
writeSamplesLoop(frequency, line, seconds);
// Done playing the whole waveform, now wait until the queued samples finish
//playing, then clean up and exit
line.drain();
line.close();
}
public static void writeSamplesLoop(double frequency, SourceDataLine line, double seconds) throws InterruptedException {
ByteBuffer cBuf = ByteBuffer.allocate(line.getBufferSize());
//Position through the sine wave as a percentage (i.e. 0 to 1 is 0 to 2*PI)
double fCyclePosition = 0;
int ctSamplesTotal = (int) (SAMPLING_RATE*seconds*noteSpeedRatio);
while (ctSamplesTotal>0) {
double fCycleInc = frequency/SAMPLING_RATE; // Fraction of cycle between samples
cBuf.clear(); // Discard the samples from the last pass
// Figure out how many samples we can add
int ctSamplesThisPass = line.available()/SAMPLE_SIZE;
for (int i=0; i<ctSamplesThisPass; i++) {
cBuf.putShort((short)(Short.MAX_VALUE * Math.sin(2*Math.PI * fCyclePosition)));
fCyclePosition += fCycleInc;
if (fCyclePosition > 1)
fCyclePosition -= 1;
}
//Write sine samples to the line buffer. If the audio buffer is full, this will
// block until there is room (we never write more samples than buffer will hold)
line.write(cBuf.array(), 0, cBuf.position());
ctSamplesTotal -= ctSamplesThisPass; // Update total number of samples written
//Wait until the buffer is at least half empty before we add more
while (line.getBufferSize()/2 < line.available())
Thread.sleep(1);
}
}
public static void playMiddleC(double seconds) {
try {
playSineWaveAtFrequencyForSeconds(260, seconds);
} catch (InterruptedException e) {
} catch (LineUnavailableException e) {
}
}
public static void playD(double seconds) {
try {
playSineWaveAtFrequencyForSeconds(290, seconds);
} catch (InterruptedException e) {
} catch (LineUnavailableException e) {
}
}
public static void playE(double seconds) {
try {
playSineWaveAtFrequencyForSeconds(320, seconds);
} catch (InterruptedException e) {
} catch (LineUnavailableException e) {
}
}
public static void playF(double seconds) {
try {
playSineWaveAtFrequencyForSeconds(345, seconds);
} catch (InterruptedException e) {
} catch (LineUnavailableException e) {
}
}
public static void playG(double seconds) {
try {
playSineWaveAtFrequencyForSeconds(392, seconds);
} catch (InterruptedException e) {
} catch (LineUnavailableException e) {
}
}
public static void playAb(double seconds) {
try {
playSineWaveAtFrequencyForSeconds(415, seconds);
} catch (InterruptedException e) {
} catch (LineUnavailableException e) {
}
}
public static void playA(double seconds) {
try {
playSineWaveAtFrequencyForSeconds(445, seconds);
} catch (InterruptedException e) {
} catch (LineUnavailableException e) {
}
}
public static void playBb(double seconds) {
try {
playSineWaveAtFrequencyForSeconds(467, seconds);
} catch (InterruptedException e) {
} catch (LineUnavailableException e) {
}
}
public static void playB(double seconds) {
try {
playSineWaveAtFrequencyForSeconds(490, seconds);
} catch (InterruptedException e) {
} catch (LineUnavailableException e) {
}
}
public static void playC(double seconds) {
try {
playSineWaveAtFrequencyForSeconds(520, seconds);
} catch (InterruptedException e) {
} catch (LineUnavailableException e) {
}
}
public static void playHighDb(double seconds) {
try {
playSineWaveAtFrequencyForSeconds(540, seconds);
} catch (InterruptedException e) {
} catch (LineUnavailableException e) {
}
}
public static void main(String[] args) {
logger.info("Testing Audio System in Java");
playMiddleC(0.2);
playD(0.2);
playE(0.2);
playF(0.2);
playG(0.2);
playA(0.2);
playB(0.2);
playC(0.2);
playMiddleC(0.2); // Octave Contrast
}
}
A class that plays some of the melodic Phrases from Farandole also MIT License
package application;
import java.util.logging.Logger;
import audio.AudioUtil;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Main extends Application {
private static Logger logger = Logger.getLogger(Main.class.getName());
@Override
public void start(Stage primaryStage) {
try {
VBox vbox = new VBox();
Scene scene = new Scene(vbox,400,400);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
Button button = new Button("Play Sound");
vbox.getChildren().add(button);
button.setOnAction((event)-> {
logger.info("Testing Audio System in Java");
for (int i=0; i<10; i++) {
AudioUtil.playMiddleC(0.2);
AudioUtil.playD(0.2);
AudioUtil.playE(0.2);
AudioUtil.playF(0.2);
AudioUtil.playG(0.2);
AudioUtil.playA(0.2);
AudioUtil.playB(0.2);
AudioUtil.playC(0.2);
AudioUtil.playMiddleC(0.2); // Octave Contrast
// Farandole
playFarandolePhrase1();
playFarandolePhrase2();
}
});
} catch(Exception e) {
e.printStackTrace();
}
}
public void playFarandolePhrase1() {
// Farandole
AudioUtil.playF(1);
AudioUtil.playMiddleC(1);
AudioUtil.playF(1);
AudioUtil.playG(0.5);
AudioUtil.playAb(0.5);
AudioUtil.playG(0.5);
AudioUtil.playAb(0.5);
AudioUtil.playF(0.5);
AudioUtil.playC(1);
AudioUtil.playAb(0.5);
AudioUtil.playBb(0.5);
AudioUtil.playC(0.5);
AudioUtil.playHighDb(0.5);
AudioUtil.playC(0.5);
AudioUtil.playBb(0.5);
AudioUtil.playAb(0.5);
AudioUtil.playG(0.5);
AudioUtil.playC(0.5);
AudioUtil.playC(0.5);
AudioUtil.playBb(0.5);
AudioUtil.playAb(0.5);
AudioUtil.playG(0.5);
AudioUtil.playAb(0.5);
AudioUtil.playF(0.5);
}
public void playFarandolePhrase2() {
// Farandole
AudioUtil.playF(1);
AudioUtil.playMiddleC(1);
AudioUtil.playF(1);
AudioUtil.playG(0.5);
AudioUtil.playAb(0.5);
AudioUtil.playG(0.5);
AudioUtil.playAb(0.5);
AudioUtil.playF(0.5);
AudioUtil.playC(1);
AudioUtil.playAb(0.5);
AudioUtil.playBb(0.5);
AudioUtil.playC(0.5);
AudioUtil.playHighDb(0.5);
AudioUtil.playC(0.5);
AudioUtil.playBb(0.5);
AudioUtil.playAb(0.5);
AudioUtil.playAb(1);
AudioUtil.playG(1);
AudioUtil.playF(1);
}
public static void main(String[] args) {
launch(args);
}
}