jm.audio.synth.Compressor Maven / Gradle / Ivy
Show all versions of jmusic Show documentation
/*
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.synth;
import jm.audio.AOException;
import jm.audio.AudioObject;
/**
* The Compressor Audio Object is a simple dynamic control. Any samples
* that pass through the Compressor Object will have their amplitudes
* above the thresghold adjusted by whatever compression ratio level is set.
* The Compresor can take one Audio Object as input.
* If ratio values are less than 1.0 (and greater than 0.0) this class will act
* as an expander. Note however, thatcurrently expansion gain is linear although
* compression is logarithmic.
*
* @author Andrew Brown
* @version 1.0, June 2003
*/
public final class Compressor extends AudioObject {
//----------------------------------------------
// Attributes
//----------------------------------------------
/**
* A positive value above which the amplitude is attenuated.
*/
private float threshold = (float) 1.0;
/**
* The attenuation value. 1.0 makes no change. 4.0 = 1:4 ratio.
*/
private double ratio = 1.0;
/**
* The amount of real gain reduction
* allowing for perceptual loudness effect
*/
private float gainReduction = 1.0f;
// compensate for compression volume reduction
private float gain = 1.0f;
//----------------------------------------------
// Constructors
//----------------------------------------------
/**
* The standard Compressor constructor takes a Single
* Audio Object as input and sets a default threshold
* and ratio.
*
* @param ao The single AudioObject taken as input.
*/
public Compressor(AudioObject ao) {
this(ao, 0.5f);
}
/**
* The standard Compressor constructor takes an
* Audio Object and threshold value as input and
* sets a default ratio.
*
* @param ao The single AudioObject taken as input.
* @param thresh The value above which to compress.
*/
public Compressor(AudioObject ao, double thresh) {
this(ao, thresh, 2.0);
}
/**
* The standard Compressor constructor takes a Single
* Audio Object, threshold and ratio as inputs.
*
* @param ao The single AudioObject taken as input.
* @param thresh The value above which to compress.
* @param ratio The attenuation divisor value.
*/
public Compressor(AudioObject ao, double thresh, double ratio) {
this(ao, thresh, ratio, 1.5);
}
/**
* The standard Compressor constructor takes a Single
* Audio Object, threshold and ratio as inputs.
*
* @param ao The single AudioObject taken as input.
* @param thresh The value above which to compress.
* @param ratio The attenuation divisor value.
*/
public Compressor(AudioObject ao, double thresh, double ratio, double gain) {
super(ao, "[Compressor]");
this.threshold = (float) thresh;
this.ratio = ratio;
this.gain = (float) gain;
calcGainReduction();
}
//----------------------------------------------
// Public Methods
//----------------------------------------------
/**
*/
public void build() {
//this.volume=(float)((1.0-(Math.log(128.0-
// (double)currentNote.getDynamic()))*0.2))*mainVolume;
}
// Reduces the raw ratio to a logrithmic reduction value
// which compensates for the logarithmic nature of
// loudness perception.
private void calcGainReduction() {
if (ratio == 1.0) {
this.gainReduction = 1.0f;
} else if (ratio > 1.0) {
this.gainReduction = (float) Math.min(1.0, (Math.abs(Math.log(1.0 - 1.0 / ratio) * 0.2)));
} else if (ratio > 0.0) { // ratio less than 1.0
this.gainReduction = (float) (1.0 / ratio);
} else {
System.out.println("jMusic error: Compressor ratio values cannot be less than 0.0");
System.exit(0);
}
}
//----------------------------------------------
// Protected Methods
//----------------------------------------------
/**
* The nextWork method for Compressor will divide
* the sample value above the threshold by the ratio.
*/
public int work(float[] buffer) throws AOException {
int returned = this.previous[0].nextWork(buffer);
for (int i = 0; i < returned; i++) {
// positive values
if (buffer[i] > threshold) {
buffer[i] = threshold + (buffer[i] - threshold) * this.gainReduction;
}
// negative values
if (buffer[i] < -threshold) {
buffer[i] = -threshold + (buffer[i] + threshold) * this.gainReduction;
}
buffer[i] *= gain;
}
return returned;
}
/**
* Specify a new threshold value above which the audio will be compressed.
*
* @param Thresh The value. 1.0 by default.
*/
public void setThreshold(double thresh) {
this.threshold = (float) thresh;
}
/**
* Specify a new ratio value - the amount of compression to apply.
*
* @param ratio The ration value. 1.0 by default (no effect).
*/
public void setRatio(double ratio) {
this.ratio = ratio;
calcGainReduction();
}
/**
* Specify a new ratio value - the amount of compression to apply.
*
* @param ratio The ration value. 1.0 by default (no effect).
*/
public void setGain(double gain) {
this.gain = (float) gain;
}
}