Vibhav Chaddha Vibhav Chaddha - 2 months ago 20
Java Question

Play 2 different frequencies alternatively in Java

I am a newbie in Java Sounds. I want to play 2 different frequencies alternatively for 1 second each in a loop for some specified time.
Like, if I have 2 frequencies 440Mhz and 16000Mhz and the time period is 10 seconds then for every 'even' second 440Mhz gets played and for every 'odd' second 16000Mhz, i.e. 5 seconds each alternatively.

I have learned a few things through some examples and I have also made a program that runs for a single user specified frequency for a time also given by the user with the help of those examples.

I will really appreciate if someone can help me out on this.

I am also attaching that single frequency code for reference.

import java.nio.ByteBuffer;
import java.util.Scanner;
import javax.sound.sampled.*;

public class Audio {

public static void main(String[] args) throws InterruptedException, LineUnavailableException {
final int SAMPLING_RATE = 44100; // Audio sampling rate
final int SAMPLE_SIZE = 2; // Audio sample size in bytes

Scanner in = new Scanner(;
int time = in.nextInt(); //Time specified by user in seconds
SourceDataLine line;
double fFreq = in.nextInt(); // Frequency of sine wave in hz

//Position through the sine wave as a percentage (i.e. 0 to 1 is 0 to 2*PI)
double fCyclePosition = 0;

//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();

line = (SourceDataLine) AudioSystem.getLine(info);;

// Make our buffer size match audio system's buffer
ByteBuffer cBuf = ByteBuffer.allocate(line.getBufferSize());

int ctSamplesTotal = SAMPLING_RATE * time; // Output for roughly user specified time in seconds

//On each pass main loop fills the available free space in the audio buffer
//Main loop creates audio samples for sine wave, runs until we tell the thread to exit
//Each sample is spaced 1/SAMPLING_RATE apart in time
while (ctSamplesTotal > 0) {
double fCycleInc = fFreq / SAMPLING_RATE; // Fraction of cycle between samples

cBuf.clear(); // Discard samples from previous 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()) {

//Done playing the whole waveform, now wait until the queued samples finish
//playing, then clean up and exit



Your best bet is probably creating Clips as shown in the sample code below. That said, the MHz range is typically not audible—looks like you have a typo in your question. If it's no typo, you will run into issues with Mr. Nyquist.

Another hint: Nobody uses Hungarian Notation in Java.

import javax.sound.sampled.*;
import java.nio.ByteBuffer;
import java.nio.ShortBuffer;

public class AlternatingTones {

    public static void main(final String[] args) throws LineUnavailableException, InterruptedException {

        final Clip clip0 = createOneSecondClip(440f);
        final Clip clip1 = createOneSecondClip(16000f);

        clip0.addLineListener(event -> {
            if (event.getType() == LineEvent.Type.STOP) {
        clip1.addLineListener(event -> {
            if (event.getType() == LineEvent.Type.STOP) {

        // prevent JVM from exiting

    private static Clip createOneSecondClip(final float frequency) throws LineUnavailableException {
        final Clip clip = AudioSystem.getClip();
        final AudioFormat format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 44100f, 16, 1, 2, 44100, true);
        final ByteBuffer buffer = ByteBuffer.allocate(44100 * format.getFrameSize());
        final ShortBuffer shortBuffer = buffer.asShortBuffer();
        final float cycleInc = frequency / format.getFrameRate();
        float cyclePosition = 0f;
        while (shortBuffer.hasRemaining()) {
            shortBuffer.put((short) (Short.MAX_VALUE * Math.sin(2 * Math.PI * cyclePosition)));
            cyclePosition += cycleInc;
            if (cyclePosition > 1) {
                cyclePosition -= 1;
        }, buffer.array(), 0, buffer.capacity());
        return clip;