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

jm.audio.RTMixer Maven / Gradle / Ivy

There is a newer version: 1.6.4.1
Show newest version
/*



Copyright (C) 2000 Andrew Sorensen & Andrew Brown

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or any
later version.

This program 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 for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/
package jm.audio;

import jm.audio.AudioChainListener;
import jm.audio.Instrument;
import jm.audio.AOException;
import jm.music.rt.RTLine;
import java.util.*;
import java.io.DataOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import javax.sound.sampled.*;

 /**
  * RTMixer is responsible for convolving the audio signals being pulled from
  * n number of RTLines.  RTMixer uses a single JMF Java Sound SourceDataLine
  * object for writing the newly convolved signal to the audio device.
  * Buffers of audio sample data are passed to the SourceDataLine at a rate
  * set by the Control Rate value.  The contol rate sets the size of the audio
  * buffers used by RTMixer, SourceDataLine and Instrument.
  * Information about sample rate and channels is retrieved from the first
  * audio object of the first instrument of the first RTLine. Therefore,
  * there is an assumption that all instruments have the same sample rate and
  * number of channels.
  *
  * @author Andrew Sorensen 
  * @version 1.0,Sun Feb 25 18:42:43  2001
  */
public class RTMixer implements AudioChainListener{
	//------------------------------------------
	//Attributes
	//------------------------------------------
	/** The number of lines in the RTLine array */
	private int totLines = 0;
	/** count shows how many RTLines have passed RTMixer their full buffers */
	private int count = 0;
	/** sampleArray contains the convolution of all RTLines buffers */ 
	private float[] sampleArray;
	/** bos is used to convert sampleArray into a byte stream */
	private ByteArrayOutputStream bos;
	/** dos is used to help convert sampleArray into bos */
	private DataOutputStream dos;
	/** dline is the JFM java sound object which we write sampleArray to */
	private SourceDataLine dline;
	/** The sampleRate to be used when establishing the JMF SourceDataLine */
	protected int sampleRate;
	/** The number of channels to be used when setting up SourceDataLine */
	protected int channels;
	/** A Timer which keeps track of how many samples have been written since
	 * this object started */
	public long currentTime = 0;
    /** The control rate is used to set how often in instrument returns a full
    * buffer of audio samples.  This is acheived by changing the size of the 
    * instrument buffers.
    * It is critical to the audio performance and can be tuned to the suit
    * the different computers. Smaller values are prefereable because they give
    * jMusic audio less latency, but values that are too small will cause 
    * the audio system to choke and splutter.
    */        
    protected double controlRate;//0.1 - 0.005
	/** How far into the score we are in terms of beats */
	private double scorePosition = 0.0;
	/** RTLines associated with this RTMixer object */
	private RTLine[] rtlines;
	/** buffer size */
	private int bufferSize;

	//-------------------------------------
	//Constructors
	//-------------------------------------
        /**
        * The RTMixer constructor sets a number of attributes and opens a JMF java
        * sound sourceDataLine.
        * @param inst the Instruments to be processed by this object.
        */
        public RTMixer(RTLine[] rtlines){
            this(rtlines, 0.1); // value is the default control rate
        }
        
        /**
        * The RTMixer constructor sets a number of attributes and opens a JMF java
         * sound sourceDataLine.
         * @param inst - The Instruments to be processed by this object.
         * @param controlRate - Sets the regularity of audio parameter change.
         * The control rate is used to set how often in instrument returns a full
         * buffer of audio samples.  This is acheived by changing the size of the 
         * instrument buffers. 

* Control rate is critical to the audio performance and can be tuned to the suit * different computers. Smaller values are prefereable because the resulting * smaller buffer equates to a less latency, but values that are too small will cause * the audio system to choke and splutter. Values typically fall in the rage 0.01 - 0.005. */ public RTMixer(RTLine[] rtlines, double controlRate){ this.rtlines = rtlines; this.sampleRate = rtlines[0].getSampleRate(); this.channels = rtlines[0].getChannels(); this.controlRate = controlRate; this.bufferSize = (int)(this.sampleRate * this.channels * this.controlRate); while (this.bufferSize%4 != 0) { this.controlRate += 0.001; this.bufferSize = (int)(this.sampleRate * this.channels * this.controlRate); } // feed info down to lines and instruments for(int i=0;i 1) this.sampleArray[i] = this.sampleArray[i] / (this.totLines * 0.75f); try{ dos.writeShort((short)(this.sampleArray[i]*32767)); }catch(IOException ioe){ioe.printStackTrace();} this.sampleArray[i] = (float)0.0; } int returned = this.dline.write(bos.toByteArray(), 0, bos.size()); this.currentTime += (long)length; } /** * This method creates an instance of the JMF SourceDataLine object. This * becomes the sink for all sample data leaving jMusic. * @param bufferSize the size to set the SourceDataLine's buffer size to. */ private void initJMFSound(int bufferSize){ //Set up jmf audio stuff // AudioFormat af = new AudioFormat((float)this.sampleRate,16, // this.channels,true,true); AudioFormat af = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, (float)this.sampleRate, 16, this.channels, this.channels*2, this.sampleRate,true); DataLine.Info info = new DataLine.Info(SourceDataLine.class,af); //System.out.println("Setting for audio line: "+info); if(!AudioSystem.isLineSupported(info)){ System.out.println(info); System.err.println("jMusic RTMixer error: JMF Line not supported. " + "Real time audio must be 16 bit stereo ... exiting .. sorry :("); System.exit(1); } try{ this.dline = (SourceDataLine)AudioSystem.getLine(info); //multiply buffersize by 2 because this is bytes not shorts this.dline.open(af, bufferSize*8); // 2 or 4? this.dline.start(); }catch(Exception e){e.printStackTrace();} } public void finalize() { System.out.println("RTMixer finalizing..."); try { dos.close(); bos.close(); } catch(IOException e) {} dline.stop(); dline.close(); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy