user25332023
user25332023

Reputation: 1

How to stop audio from line.write with AudioSystem in java

I want to create a method to stop the output of audio. The createSinWaveBuffer method creates a specific number of samples and is played with line.write. I was wondering how I could make this output stop with another method in the class. I additionally want to be able to change certain fields (such as amplitude and frequency) and therefore change how the output sounds without stoping the output.

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;

public class SineGenerator {
    //
    protected static final int SAMPLE_RATE = 16 * 1024;

    private int freq; // frequency of carrier
    private double amplitude;// total amplitude of carrier
    private boolean inclAng;  // boolean for including angle in modulator wave equation
    private double modAmp; // amplitude of the modulating wave
    private int numMod; // number of modulating waves
    private int numTime; // time in seconds

    public SineGenerator(int freq, double amplitude, boolean incAng, double modAmp, int numMod, int numTime) {
        this.freq = freq; 
        this.amplitude = amplitude;
        this.inclAng = incAng;  
        this.modAmp = modAmp; 
        this.numMod = numMod; 
        this.numTime = numTime;
    }
    
    public byte[] createSinWaveBuffer() {
        int ms = numTime * 1000;
        int samples = (int)((ms * SAMPLE_RATE) / 1000);
        byte[] output = new byte[samples];

        double period = (double)SAMPLE_RATE / freq;

        for (int i = 0; i < output.length; i++) {
            double angle = 2.0 * Math.PI * i / (SAMPLE_RATE / (freq));

            if (modAmp <= 0) { // if the modulator ampliltude is 0, then the unaffected carrier wave is played
                output[i] = (byte)(Math.sin(angle) * amplitude); 
            }
            else {
                output[i] = (byte)(Math.sin(recur(modAmp, angle, numMod, inclAng)) * 127f); 
            }
        }

        return output;
    }

    public void play() throws LineUnavailableException {
        final AudioFormat af= new AudioFormat(SAMPLE_RATE, 8, 1, true, true);
        SourceDataLine line = AudioSystem.getSourceDataLine(af);
        line.open(af, SAMPLE_RATE);
        line.start();

        byte [] toneBuffer = createSinWaveBuffer();
 
        line.write(toneBuffer, 0, toneBuffer.length);

        line.drain();
        line.close();
    }

   
    public static double recur(double amplitude, double angle, int num, boolean inclAng) {
        if (num<=1) {
            if (inclAng)
                return angle + amplitude*Math.sin(angle);
            else 
                return amplitude*Math.sin(angle);
        }
        else {
            if (inclAng)
                return angle + amplitude*Math.sin(recur(amplitude, angle, num-1, inclAng));
            else   
                return amplitude*Math.sin(recur(amplitude, angle, num-1, inclAng));
        }
    } 

    public void setFreq(int freq) {
        this.freq = freq;
    }

    public void setAmplitude(double amplitude) {
        this.amplitude = amplitude;
    }
}

Upvotes: 0

Views: 70

Answers (1)

Phil Freihofner
Phil Freihofner

Reputation: 7910

I think your best bet is to output as a series of writes instead of doing it all with one write. With each write, you have an opportunity to check for pending requests to stop or change volume or pitch.

Upvotes: 0

Related Questions