539 lines · 16.1 KB · Java
RawDownload
/* * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */package com.sun.media.sound; import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.InputStream;import java.util.Arrays; import javax.sound.sampled.AudioFormat;import javax.sound.sampled.AudioInputStream;import javax.sound.sampled.AudioSystem;import javax.sound.sampled.Clip;import javax.sound.sampled.DataLine;import javax.sound.sampled.LineEvent;import javax.sound.sampled.LineUnavailableException; /** * Clip implemention for the SoftMixingMixer. * * @author Karl Helgason */public class SoftMixingClip extends SoftMixingDataLine implements Clip {     private AudioFormat format;     private int framesize;     private byte[] data;     private InputStream datastream = new InputStream() {         public int read() throws IOException {            byte[] b = new byte[1];            int ret = read(b);            if (ret < 0)                return ret;            return b[0] & 0xFF;        }         public int read(byte[] b, int off, int len) throws IOException {             if (_loopcount != 0) {                int bloopend = _loopend * framesize;                int bloopstart = _loopstart * framesize;                int pos = _frameposition * framesize;                 if (pos + len >= bloopend)                    if (pos < bloopend) {                        int offend = off + len;                        int o = off;                        while (off != offend) {                            if (pos == bloopend) {                                if (_loopcount == 0)                                    break;                                pos = bloopstart;                                if (_loopcount != LOOP_CONTINUOUSLY)                                    _loopcount--;                            }                            len = offend - off;                            int left = bloopend - pos;                            if (len > left)                                len = left;                            System.arraycopy(data, pos, b, off, len);                            off += len;                        }                        if (_loopcount == 0) {                            len = offend - off;                            int left = bloopend - pos;                            if (len > left)                                len = left;                            System.arraycopy(data, pos, b, off, len);                            off += len;                        }                        _frameposition = pos / framesize;                        return o - off;                    }            }             int pos = _frameposition * framesize;            int left = bufferSize - pos;            if (left == 0)                return -1;            if (len > left)                len = left;            System.arraycopy(data, pos, b, off, len);            _frameposition += len / framesize;            return len;        }     };     private int offset;     private int bufferSize;     private float[] readbuffer;     private boolean open = false;     private AudioFormat outputformat;     private int out_nrofchannels;     private int in_nrofchannels;     private int frameposition = 0;     private boolean frameposition_sg = false;     private boolean active_sg = false;     private int loopstart = 0;     private int loopend = -1;     private boolean active = false;     private int loopcount = 0;     private boolean _active = false;     private int _frameposition = 0;     private boolean loop_sg = false;     private int _loopcount = 0;     private int _loopstart = 0;     private int _loopend = -1;     private float _rightgain;     private float _leftgain;     private float _eff1gain;     private float _eff2gain;     private AudioFloatInputStream afis;     protected SoftMixingClip(SoftMixingMixer mixer, DataLine.Info info) {        super(mixer, info);    }     protected void processControlLogic() {         _rightgain = rightgain;        _leftgain = leftgain;        _eff1gain = eff1gain;        _eff2gain = eff2gain;         if (active_sg) {            _active = active;            active_sg = false;        } else {            active = _active;        }         if (frameposition_sg) {            _frameposition = frameposition;            frameposition_sg = false;            afis = null;        } else {            frameposition = _frameposition;        }        if (loop_sg) {            _loopcount = loopcount;            _loopstart = loopstart;            _loopend = loopend;        }         if (afis == null) {            afis = AudioFloatInputStream.getInputStream(new AudioInputStream(                    datastream, format, AudioSystem.NOT_SPECIFIED));             if (Math.abs(format.getSampleRate() - outputformat.getSampleRate()) > 0.000001)                afis = new AudioFloatInputStreamResampler(afis, outputformat);        }     }     protected void processAudioLogic(SoftAudioBuffer[] buffers) {        if (_active) {            float[] left = buffers[SoftMixingMainMixer.CHANNEL_LEFT].array();            float[] right = buffers[SoftMixingMainMixer.CHANNEL_RIGHT].array();            int bufferlen = buffers[SoftMixingMainMixer.CHANNEL_LEFT].getSize();             int readlen = bufferlen * in_nrofchannels;            if (readbuffer == null || readbuffer.length < readlen) {                readbuffer = new float[readlen];            }            int ret = 0;            try {                ret = afis.read(readbuffer);                if (ret == -1) {                    _active = false;                    return;                }                if (ret != in_nrofchannels)                    Arrays.fill(readbuffer, ret, readlen, 0);            } catch (IOException e) {            }             int in_c = in_nrofchannels;            for (int i = 0, ix = 0; i < bufferlen; i++, ix += in_c) {                left[i] += readbuffer[ix] * _leftgain;            }             if (out_nrofchannels != 1) {                if (in_nrofchannels == 1) {                    for (int i = 0, ix = 0; i < bufferlen; i++, ix += in_c) {                        right[i] += readbuffer[ix] * _rightgain;                    }                } else {                    for (int i = 0, ix = 1; i < bufferlen; i++, ix += in_c) {                        right[i] += readbuffer[ix] * _rightgain;                    }                }             }             if (_eff1gain > 0.0002) {                 float[] eff1 = buffers[SoftMixingMainMixer.CHANNEL_EFFECT1]                        .array();                for (int i = 0, ix = 0; i < bufferlen; i++, ix += in_c) {                    eff1[i] += readbuffer[ix] * _eff1gain;                }                if (in_nrofchannels == 2) {                    for (int i = 0, ix = 1; i < bufferlen; i++, ix += in_c) {                        eff1[i] += readbuffer[ix] * _eff1gain;                    }                }            }             if (_eff2gain > 0.0002) {                float[] eff2 = buffers[SoftMixingMainMixer.CHANNEL_EFFECT2]                        .array();                for (int i = 0, ix = 0; i < bufferlen; i++, ix += in_c) {                    eff2[i] += readbuffer[ix] * _eff2gain;                }                if (in_nrofchannels == 2) {                    for (int i = 0, ix = 1; i < bufferlen; i++, ix += in_c) {                        eff2[i] += readbuffer[ix] * _eff2gain;                    }                }            }         }    }     public int getFrameLength() {        return bufferSize / format.getFrameSize();    }     public long getMicrosecondLength() {        return (long) (getFrameLength() * (1000000.0 / (double) getFormat()                .getSampleRate()));    }     public void loop(int count) {        LineEvent event = null;         synchronized (control_mutex) {            if (isOpen()) {                if (active)                    return;                active = true;                active_sg = true;                loopcount = count;                event = new LineEvent(this, LineEvent.Type.START,                        getLongFramePosition());            }        }         if (event != null)            sendEvent(event);     }     public void open(AudioInputStream stream) throws LineUnavailableException,            IOException {        if (isOpen()) {            throw new IllegalStateException("Clip is already open with format "                    + getFormat() + " and frame lengh of " + getFrameLength());        }        if (AudioFloatConverter.getConverter(stream.getFormat()) == null)            throw new IllegalArgumentException("Invalid format : "                    + stream.getFormat().toString());         if (stream.getFrameLength() != AudioSystem.NOT_SPECIFIED) {            byte[] data = new byte[(int) stream.getFrameLength()                    * stream.getFormat().getFrameSize()];            int readsize = 512 * stream.getFormat().getFrameSize();            int len = 0;            while (len != data.length) {                if (readsize > data.length - len)                    readsize = data.length - len;                int ret = stream.read(data, len, readsize);                if (ret == -1)                    break;                if (ret == 0)                    Thread.yield();                len += ret;            }            open(stream.getFormat(), data, 0, len);        } else {            ByteArrayOutputStream baos = new ByteArrayOutputStream();            byte[] b = new byte[512 * stream.getFormat().getFrameSize()];            int r = 0;            while ((r = stream.read(b)) != -1) {                if (r == 0)                    Thread.yield();                baos.write(b, 0, r);            }            open(stream.getFormat(), baos.toByteArray(), 0, baos.size());        }     }     public void open(AudioFormat format, byte[] data, int offset, int bufferSize)            throws LineUnavailableException {        synchronized (control_mutex) {            if (isOpen()) {                throw new IllegalStateException(                        "Clip is already open with format " + getFormat()                                + " and frame lengh of " + getFrameLength());            }            if (AudioFloatConverter.getConverter(format) == null)                throw new IllegalArgumentException("Invalid format : "                        + format.toString());            if (bufferSize % format.getFrameSize() != 0)                throw new IllegalArgumentException(                        "Buffer size does not represent an integral number of sample frames!");             this.data = data;            this.offset = offset;            this.bufferSize = bufferSize;            this.format = format;            this.framesize = format.getFrameSize();             loopstart = 0;            loopend = -1;            loop_sg = true;             if (!mixer.isOpen()) {                mixer.open();                mixer.implicitOpen = true;            }             outputformat = mixer.getFormat();            out_nrofchannels = outputformat.getChannels();            in_nrofchannels = format.getChannels();             open = true;             mixer.getMainMixer().openLine(this);        }     }     public void setFramePosition(int frames) {        synchronized (control_mutex) {            frameposition_sg = true;            frameposition = frames;        }    }     public void setLoopPoints(int start, int end) {        synchronized (control_mutex) {            if (end != -1) {                if (end < start)                    throw new IllegalArgumentException("Invalid loop points : "                            + start + " - " + end);                if (end * framesize > bufferSize)                    throw new IllegalArgumentException("Invalid loop points : "                            + start + " - " + end);            }            if (start * framesize > bufferSize)                throw new IllegalArgumentException("Invalid loop points : "                        + start + " - " + end);            if (0 < start)                throw new IllegalArgumentException("Invalid loop points : "                        + start + " - " + end);            loopstart = start;            loopend = end;            loop_sg = true;        }    }     public void setMicrosecondPosition(long microseconds) {        setFramePosition((int) (microseconds * (((double) getFormat()                .getSampleRate()) / 1000000.0)));    }     public int available() {        return 0;    }     public void drain() {    }     public void flush() {    }     public int getBufferSize() {        return bufferSize;    }     public AudioFormat getFormat() {        return format;    }     public int getFramePosition() {        synchronized (control_mutex) {            return frameposition;        }    }     public float getLevel() {        return AudioSystem.NOT_SPECIFIED;    }     public long getLongFramePosition() {        return getFramePosition();    }     public long getMicrosecondPosition() {        return (long) (getFramePosition() * (1000000.0 / (double) getFormat()                .getSampleRate()));    }     public boolean isActive() {        synchronized (control_mutex) {            return active;        }    }     public boolean isRunning() {        synchronized (control_mutex) {            return active;        }    }     public void start() {         LineEvent event = null;         synchronized (control_mutex) {            if (isOpen()) {                if (active)                    return;                active = true;                active_sg = true;                loopcount = 0;                event = new LineEvent(this, LineEvent.Type.START,                        getLongFramePosition());            }        }         if (event != null)            sendEvent(event);    }     public void stop() {        LineEvent event = null;         synchronized (control_mutex) {            if (isOpen()) {                if (!active)                    return;                active = false;                active_sg = true;                event = new LineEvent(this, LineEvent.Type.STOP,                        getLongFramePosition());            }

Lines 1–500 of 539.