All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.monte.media.eightsvx.JDK13AppletAudioClip Maven / Gradle / Ivy

The newest version!


package org.monte.media.eightsvx;

import javax.sound.sampled.*;
import java.util.*;
import java.io.*;

public class JDK13AppletAudioClip implements LoopableAudioClip, Runnable {

    private byte[] samples;

    private static Mixer mixer;


    private static Vector lines = new Vector();


    private volatile Thread workerThread;


    private int loopCount;


    private int volume;


    private int sampleRate;


    private float pan;

    private int loopStart;

    private int loopEnd;




    public JDK13AppletAudioClip(byte[] samples, int sampleRate, int volume, float pan)
    throws IOException {
        this.samples = samples;
        this.volume = volume;
        this.pan = pan;
        this.loopStart = 0;
        this.loopEnd = samples.length;
        this.sampleRate = sampleRate;


        try {
            getMixer();
        } catch (LineUnavailableException e) {
            throw new IOException(e.toString());
        }

    }

    private static Mixer getMixer() throws LineUnavailableException {
        if (mixer == null) {
            mixer = (Mixer) AudioSystem.getMixer(AudioSystem.getMixerInfo()[0]);
            SourceDataLine[] l = new SourceDataLine[16];
            for (int i=0; i < 16; i++) {
                l[i] = aquireLine();
            }
            for (int i=0; i < 16; i++) {
                poolLine(l[i]);
            }
        }
        return mixer;
    }


    private synchronized static SourceDataLine aquireLine()
    throws LineUnavailableException {
        SourceDataLine line;
        if (lines.size() > 0) {
            line = (SourceDataLine) lines.elementAt(0);
            lines.removeElementAt(0);
        } else {
            AudioFormat audioFormat = new AudioFormat(
            (float) 8000,
            8,
            1,
            true,
            true
            );

            Line.Info lineInfo = new DataLine.Info(SourceDataLine.class, audioFormat);
            line = (SourceDataLine) getMixer().getLine(lineInfo);
            line.open();
            line.start();

        }
        return line;
    }


    private synchronized static void poolLine(SourceDataLine line) {
        if (lines.size() < 16) {


            lines.addElement(line);
        } else {
            line.close();
        }
    }


    public void setLoopPoints(int start, int end) {
        if (start < 0 || start >= samples.length || end < start && end != -1 || end >= samples.length)
            throw new IllegalArgumentException("start:"+start+" end:"+end);
        loopStart = start;
        loopEnd = (end == -1) ? samples.length : end + 1;
    }

    public void loop() {
        loop(LOOP_CONTINUOUSLY);
    }


    public synchronized void loop(int count) {
        stop();
        loopCount = count;
        workerThread = new Thread(this, this.toString());
        workerThread.setPriority(Thread.NORM_PRIORITY + 1);
        workerThread.start();
    }

    public void play() {
        loop(0);
    }

    public synchronized void stop() {
        if (workerThread != null) {
            Thread t = workerThread;
            workerThread = null;

        }
    }


    private void configureDataLine(DataLine clip) {
        if (clip.isControlSupported(FloatControl.Type.PAN)) {
            FloatControl control = (FloatControl) clip.getControl(FloatControl.Type.PAN);
            control.setValue(pan);
System.out.println("setPan:"+pan);
        } else {
System.out.println("panning not supported "+pan);
        }
        if (clip.isControlSupported(FloatControl.Type.VOLUME)) {
            FloatControl control = (FloatControl) clip.getControl(FloatControl.Type.VOLUME);
            control.setValue(volume / 64f);
        }

        if (clip.isControlSupported(FloatControl.Type.SAMPLE_RATE)) {
            FloatControl control = (FloatControl) clip.getControl(FloatControl.Type.SAMPLE_RATE);
            control.setValue((float) sampleRate);
        }
    }


    public void run() {

        long start = System.currentTimeMillis();
        long mediaDuration = (samples.length * Math.max(loopCount, 1)) / 8;
        int framePosition = 0;

        SourceDataLine out = null;
        try {
            out = aquireLine();
        } catch (LineUnavailableException e) {
            e.printStackTrace();
            return;
        }
        System.out.println("configureDataLine");
        configureDataLine(out);

        byte[] buf = new byte[100];

        if (loopCount > 0 && framePosition < loopEnd) {
            while (workerThread == Thread.currentThread()
            && (loopCount > 0 || loopCount == Clip.LOOP_CONTINUOUSLY)) {

                while (workerThread == Thread.currentThread()
                && framePosition < loopEnd) {
                    System.arraycopy(samples, framePosition, buf, 0, Math.min(buf.length, loopEnd - framePosition));
                    framePosition += out.write(buf, 0, Math.min(buf.length, loopEnd - framePosition));

                }


                if (workerThread == Thread.currentThread()
                && (loopCount > 0 || loopCount == Clip.LOOP_CONTINUOUSLY)) {
                    if (loopCount != Clip.LOOP_CONTINUOUSLY) {
                        loopCount--;
                        if (loopCount != 0) framePosition = loopStart;
                    }
                }
            }


            while (workerThread == Thread.currentThread()
            && framePosition < samples.length) {
                System.arraycopy(samples, framePosition, buf, 0, Math.min(buf.length, samples.length - framePosition));
                framePosition += out.write(buf, 0, Math.min(buf.length, samples.length - framePosition));
            }
        } else {

            while (workerThread == Thread.currentThread()
            && framePosition < samples.length) {
                System.arraycopy(samples, framePosition, buf, 0, Math.min(buf.length, samples.length - framePosition));
                framePosition += out.write(buf, 0, Math.min(buf.length, samples.length - framePosition));
            }
        }



            long end = System.currentTimeMillis();
            long elapsed = end - start;
            while (workerThread == Thread.currentThread() && mediaDuration > elapsed) {
                try {
                    Thread.sleep(Math.max(1, Math.min(mediaDuration - elapsed, 100)));
                } catch (InterruptedException e) {
                }
                elapsed = System.currentTimeMillis() - start;
            }


        if (workerThread != Thread.currentThread()) {
            out.flush();
        }


        poolLine(out);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy