alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (SoftMixingClip.java)

This example Java source code file (SoftMixingClip.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

audiofloatinputstreamresampler, audioformat, buffer, bytearrayoutputstream, clip, illegalargumentexception, illegalstateexception, inputstream, invalid, ioexception, lineevent, lineunavailableexception, softmixingclip, softmixingdataline, util

The SoftMixingClip.java Java example source code

/*
 * Copyright (c) 2008, 2013, 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 implementation for the SoftMixingMixer.
 *
 * @author Karl Helgason
 */
public final class SoftMixingClip extends SoftMixingDataLine implements Clip {

    private AudioFormat format;

    private int framesize;

    private byte[] data;

    private final 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;

    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!");

            if (data != null) {
                this.data = Arrays.copyOf(data, data.length);
            }
            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());
            }
        }

        if (event != null)
            sendEvent(event);
    }

    public void close() {
        LineEvent event = null;

        synchronized (control_mutex) {
            if (!isOpen())
                return;
            stop();

            event = new LineEvent(this, LineEvent.Type.CLOSE,
                    getLongFramePosition());

            open = false;
            mixer.getMainMixer().closeLine(this);
        }

        if (event != null)
            sendEvent(event);

    }

    public boolean isOpen() {
        return open;
    }

    public void open() throws LineUnavailableException {
        if (data == null) {
            throw new IllegalArgumentException(
                    "Illegal call to open() in interface Clip");
        }
        open(format, data, offset, bufferSize);
    }

}

Other Java examples (source code examples)

Here is a short list of links related to this Java SoftMixingClip.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.