Answered by:
Audio Compression

Question
-
I want a audio Compression Algorithm that perform best Audio Compress technique.pls help me
- Changed type Mike Feng Monday, January 21, 2013 5:53 AM
- Moved by Reed Copsey, JrMVP Monday, January 21, 2013 10:51 PM Off topic
Saturday, January 19, 2013 9:21 AM
Answers
-
this is my Compression
// based on SimpleComp v1.10 © 2006, ChunkWare Music Software, OPEN-SOURCE
using System;
using NAudio.Utils;
namespace NAudio.Dsp
{
class SimpleCompressor : AttRelEnvelope
{
// transfer function
private double threshdB; // threshold (dB)
private double ratio; // ratio (compression: < 1 ; expansion: > 1)
private double makeUpGain;
// runtime variables
private double envdB; // over-threshold envelope (dB)
public SimpleCompressor(double attackTime, double releaseTime, double sampleRate)
: base(attackTime, releaseTime, sampleRate)
{
this.threshdB = 0.0;
this.ratio = 1.0;
this.makeUpGain = 0.0;
this.envdB = DC_OFFSET;
}
public SimpleCompressor()
: base(10.0, 10.0, 44100.0)
{
this.threshdB = 0.0;
this.ratio = 1.0;
this.makeUpGain = 0.0;
this.envdB = DC_OFFSET;
}
public double MakeUpGain
{
get { return makeUpGain; }
set { makeUpGain = value; }
}
public double Threshold
{
get { return threshdB; }
set { threshdB = value; }
}
public double Ratio
{
get { return ratio; }
set { ratio = value; }
}
// call before runtime (in resume())
public void InitRuntime()
{
this.envdB = DC_OFFSET;
}
// // compressor runtime process
public void Process(ref double in1, ref double in2)
{
// sidechain
// rectify input
double cv = 0.0;
double rect1 = Math.Abs(in1); // n.b. was fabs
double rect2 = Math.Abs(in2); // n.b. was fabs
// if desired, one could use another EnvelopeDetector to smooth
// the rectified signal.
double link = Math.Max(rect1, rect2); // link channels with greater of 2
link += DC_OFFSET; // add DC offset to avoid log( 0 )
double keydB = Decibels.LinearToDecibels(link); // convert linear -> dB
// threshold
double overdB = keydB - threshdB; // delta over threshold
if (overdB < 0.0)
overdB = 0.0;
// attack/release
overdB += DC_OFFSET; // add DC offset to avoid denormal
Run(overdB, ref envdB); // run attack/release envelope
overdB = envdB - DC_OFFSET; // subtract DC offset
// Regarding the DC offset: In this case, since the offset is added before
// the attack/release processes, the envelope will never fall below the offset,
// thereby avoiding denormals. However, to prevent the offset from causing
// constant gain reduction, we must subtract it from the envelope, yielding
// a minimum value of 0dB.
// transfer function
if (MakeUpGain <= 10.0f)
{
double gr = overdB * (1 / ratio - 1.0); // gain reduction (dB)
gr = Decibels.DecibelsToLinear(gr) * Decibels.DecibelsToLinear(makeUpGain); // convert dB -> linear gr = overdB * (1 / ratio - 1.0); // gain reduction (dB)
// output gain
in1 *= gr; // apply gain reduction to input
in2 *= gr;
}
else
{
double gr = overdB * (1 / ratio - 1.0); // gain reduction (dB)
in1 *= gr; // apply gain reduction to input
in2 *= gr;
}
}
}
}
and Tried to Apply Audiocity this method///////////////////////////////////////////////////////////////////////////
//
// "Investigation in Dynamic Range Compression" - MSc Project
// Copyright 2009, Michael Massberg
// michael@massberg.org
//
///////////////////////////////////////////////////////////////////////////
#include "compressor.h"
///////////////////////////////////////////////////////////////////////////
AudioEffect* createEffectInstance(audioMasterCallback audioMaster) {
return new Compressor(audioMaster);
}
///////////////////////////////////////////////////////////////////////////
Compressor::Compressor(audioMasterCallback audioMaster)
: AudioEffectX(audioMaster, 1, kParamCount) {
setUniqueID(CCONST('c', 'm', 'p', 'r'));
setNumInputs(2);
setNumOutputs(2);
canProcessReplacing();
setEditor(new CompressorEditor(this));
vst_strncpy(programName, "Default", kVstMaxProgNameLen);
for(VstInt32 i=0; i<kParamCount; i++) {
setParameter(i, getParameterDefault(i));
}
DECLARE_VST_DEPRECATED(canMono) (true);
#if !ENABLEPRESETS
programsAreChunks();
#endif
initialize();
}
Compressor::~Compressor() { }
///////////////////////////////////////////////////////////////////////////
void Compressor::initialize() {
double fs = getSampleRate();
rampCoeff = onePoleCoeff(fs, 0.05);
}
///////////////////////////////////////////////////////////////////////////
#if !ENABLEPRESETS
VstInt32 Compressor::getChunk(void **data, bool isPreset) {
static char buffer[32];;
memset(buffer, 0, 32);
*data = buffer;
return 32;
}
VstInt32 Compressor::setChunk(void *data, VstInt32 byteSize, bool isPreset) {
for(VstInt32 i=0; i<kParamCount; i++) {
setParameter(i, getParameterDefault(i));
}
return 1;
}
#endif
///////////////////////////////////////////////////////////////////////////
void Compressor::setParameter(VstInt32 index, float value) {
params[index] = value;
double fs = getSampleRate();
switch(index) {
case kParamThreshold: logThreshold[kTarget] = log(pow(10.0, value * -MAXGAINDB / 20.0)); break;
case kParamRatio: slope = -value; break;
case kParamKneeWidth: logKneeWidth = log(pow(10.0, value * MAXGAINDB / 20.0)); break;
case kParamGain: logGain[kTarget] = log(pow(10.0, value * MAXGAINDB / 20.0)); break;
case kParamAttack:
attackTime = PARAM2LOG(value, MINATTACKTIME, MAXATTACKTIME);
attackCoeff = onePoleCoeff(fs, attackTime);
break;
case kParamRelease:
releaseTime = PARAM2LOG(value, MINRELEASETIME, MAXRELEASETIME);
releaseCoeff = onePoleCoeff(fs, releaseTime);
break;
case kParamActive: active = (value >= 0.5f); break;
case kParamAutoKnee: autoKnee = (value >= 0.5f); break;
case kParamAutoGain: autoGain = (value >= 0.5f); break;
case kParamAutoAttack: autoAttack = (value >= 0.5f); break;
case kParamAutoRelease: autoRelease = (value >= 0.5f); break;
case kParamMetaKneeMult:
metaKneeMult = PARAM2LIN(value, MINKNEEMULT, MAXKNEEMULT);
break;
case kParamMetaMaxAttack:
metaMaxAttackTime = PARAM2LOG(value, MINATTACKTIME, MAXATTACKTIME);
break;
case kParamMetaMaxRelease:
metaMaxReleaseTime = PARAM2LOG(value, MINRELEASETIME, MAXRELEASETIME);
break;
case kParamMetaCrest:
metaCrestTime = PARAM2LOG(value, MINCRESTTIME, MAXCRESTTIME);
metaCrestCoeff = onePoleCoeff(fs, metaCrestTime);
break;
case kParamMetaAdapt:
metaAdaptTime = PARAM2LOG(value, MINADAPTTIME, MAXADAPTTIME);
metaAdaptCoeff = onePoleCoeff(fs, metaAdaptTime);
break;
case kParamMetaNoClipping: metaNoClipping = (value >= 0.5f); break;
}
if(editor) {
((AEffGUIEditor*) editor)->setParameter(index, value);
}
}
float Compressor::getParameter(VstInt32 index) {
return params[index];
}
float Compressor::getParameterDefault(VstInt32 index) {
switch(index) {
case kParamActive: return 1.f;
case kParamThreshold: return 0.f;
case kParamRatio: return 0.f;
case kParamGain: return 0.f;
case kParamAttack: return (float) LOG2PARAM(0.005, MINATTACKTIME, MAXATTACKTIME);
case kParamRelease: return (float) LOG2PARAM(0.05, MINRELEASETIME, MAXRELEASETIME);
case kParamAutoAttack:
case kParamAutoRelease:
case kParamAutoKnee:
case kParamAutoGain:
return 1.f;
case kParamMetaKneeMult: return (float) LIN2PARAM(2.0, MINKNEEMULT, MAXKNEEMULT);
case kParamMetaMaxAttack: return (float) LOG2PARAM(0.08, MINATTACKTIME, MAXATTACKTIME);
case kParamMetaMaxRelease: return (float) LOG2PARAM(1.0, MINRELEASETIME, MAXRELEASETIME);
case kParamMetaCrest: return (float) LOG2PARAM(0.2, MINCRESTTIME, MAXCRESTTIME);
case kParamMetaAdapt: return (float) LOG2PARAM(2.5, MINADAPTTIME, MAXADAPTTIME);
case kParamMetaNoClipping: return 1.f;
}
return 0.f;
}
float Compressor::getParameterFromString(VstInt32 index, char *text) {
double x = atof(text);
switch(index) {
case kParamThreshold: return (float) CLAMP(fabs(x) / MAXGAINDB, 0.0, 1.0);
case kParamRatio: return (float) (1.0 - 1.0 / CLAMP(fabs(x), 1.0, 100.0));
case kParamKneeWidth: return (float) CLAMP(fabs(x) / MAXGAINDB, 0.0, 1.0);
case kParamGain: return (float) CLAMP(fabs(x) / MAXGAINDB, 0.0, 1.0);
case kParamAttack: return (float) LOG2PARAM(CLAMP(fabs(x) / 1000.0, MINATTACKTIME, MAXATTACKTIME), MINATTACKTIME, MAXATTACKTIME);
case kParamRelease: return (float) LOG2PARAM(CLAMP(fabs(x) / 1000.0, MINRELEASETIME, MAXRELEASETIME), MINRELEASETIME, MAXRELEASETIME);
}
return getParameter(index);
}
///////////////////////////////////////////////////////////////////////////
void Compressor::getParameterName(VstInt32 index, char *label) {
switch(index) {
case kParamActive: vst_strncpy(label, "Active", kVstMaxParamStrLen); return;
case kParamThreshold: vst_strncpy(label, "Thresh", kVstMaxParamStrLen); return;
case kParamKneeWidth: vst_strncpy(label, "Width", kVstMaxParamStrLen); return;
case kParamAutoKnee: vst_strncpy(label, "AutoKnee", kVstMaxParamStrLen); return;
case kParamGain: vst_strncpy(label, "Gain", kVstMaxParamStrLen); return;
case kParamAutoGain: vst_strncpy(label, "AutoGain", kVstMaxParamStrLen); return;
case kParamRatio: vst_strncpy(label, "Ratio", kVstMaxParamStrLen); return;
case kParamAttack: vst_strncpy(label, "Attack", kVstMaxParamStrLen); return;
case kParamAutoAttack: vst_strncpy(label, "AutoAtt", kVstMaxParamStrLen); return;
case kParamRelease: vst_strncpy(label, "Release", kVstMaxParamStrLen); return;
case kParamAutoRelease: vst_strncpy(label, "AutoRel", kVstMaxParamStrLen); return;
case kParamMetaKneeMult: vst_strncpy(label, "KneeMult", kVstMaxParamStrLen); return;
case kParamMetaMaxAttack: vst_strncpy(label, "MaxAtt", kVstMaxParamStrLen); return;
case kParamMetaMaxRelease: vst_strncpy(label, "MaxRel", kVstMaxParamStrLen); return;
case kParamMetaCrest: vst_strncpy(label, "Crest", kVstMaxParamStrLen); return;
case kParamMetaAdapt: vst_strncpy(label, "Adapt", kVstMaxParamStrLen); return;
case kParamMetaNoClipping: vst_strncpy(label, "NoClip", kVstMaxParamStrLen); return;
}
vst_strncpy(label, "", kVstMaxParamStrLen);
}
void Compressor::getParameterDisplay(VstInt32 index, char *text) {
switch(index) {
case kParamRatio:
if(slope > -0.99) {
float2string((float) (1.0 / (1.0 + slope)), text, kVstMaxParamStrLen);
vst_strncat(text, ":1", kVstMaxParamStrLen);
}
else {
vst_strncpy(text, "oo:1", kVstMaxParamStrLen);
}
return;
case kParamThreshold: dB2string((float) exp(logThreshold[kTarget]), text, kVstMaxParamStrLen); return;
case kParamGain: dB2string((float) exp(logGain[kTarget]), text, kVstMaxParamStrLen); return;
case kParamKneeWidth: dB2string((float) exp(logKneeWidth), text, kVstMaxParamStrLen); return;
case kParamAttack: float2string((float) (attackTime * 1000.0), text, kVstMaxParamStrLen); return;
case kParamRelease: float2string((float) (releaseTime * 1000.0), text, kVstMaxParamStrLen); return;
case kParamMetaKneeMult: float2string((float) metaKneeMult, text, kVstMaxParamStrLen); return;
case kParamMetaMaxAttack: float2string((float) (metaMaxAttackTime * 1000.0), text, kVstMaxParamStrLen); return;
case kParamMetaMaxRelease: float2string((float) (metaMaxReleaseTime * 1000.0), text, kVstMaxParamStrLen); return;
case kParamMetaCrest: float2string((float) (metaCrestTime * 1000.0), text, kVstMaxParamStrLen); return;
case kParamMetaAdapt: float2string((float) (metaAdaptTime * 1000.0), text, kVstMaxParamStrLen); return;
}
vst_strncpy(text, (getParameter(index) >= 0.5f)?"On":"Off", kVstMaxParamStrLen);
}
void Compressor::getParameterLabel(VstInt32 index, char *label) {
switch(index) {
case kParamThreshold:
case kParamGain:
case kParamKneeWidth:
vst_strncpy(label, "dB", kVstMaxParamStrLen);
return;
case kParamAttack:
case kParamRelease:
case kParamMetaMaxAttack:
case kParamMetaMaxRelease:
case kParamMetaCrest:
case kParamMetaAdapt:
vst_strncpy(label, "ms", kVstMaxParamStrLen);
return;
}
vst_strncpy(label, "", kVstMaxParamStrLen);
}
///////////////////////////////////////////////////////////////////////////
float Compressor::getMeter(VstInt32 index) {
switch(index) {
case kMeterGR:
if(active) {
return (float) CLAMP((-cvAttack - MINMETERLOG) / (0.0 - MINMETERLOG), 0.0, 1.0);
}
return 1.f;
}
return 0.f;
}
///////////////////////////////////////////////////////////////////////////
void Compressor::getProgramName(char *text) {
vst_strncpy(text, programName, kVstMaxProgNameLen);
}
void Compressor::setProgramName(char* name) {
vst_strncpy(programName, name, kVstMaxProgNameLen);
}
///////////////////////////////////////////////////////////////////////////
void Compressor::setSampleRate(float sampleRate) {
AudioEffectX::setSampleRate(sampleRate);
for(int j=0; j<kParamCount; j++) {
setParameter(j, getParameter(j));
}
initialize();
}
void Compressor::setProgram(VstInt32 program) {
AudioEffectX::setProgram(program);
for(int j=0; j<kParamCount; j++) {
setParameter(j, getParameter(j));
}
}
///////////////////////////////////////////////////////////////////////////
bool Compressor::getEffectName(char *name) {
vst_strncpy(name, "Auto Compressor", kVstMaxEffectNameLen);
return true;
}
bool Compressor::getProductString (char *text) {
vst_strncpy(text, "VST Plug-Ins", kVstMaxProductStrLen);
return true;
}
bool Compressor::getVendorString (char *text) {
vst_strncpy(text, "Michael Massberg", kVstMaxVendorStrLen);
return true;
}
VstInt32 Compressor::getVendorVersion() {
return 1000;
}
VstPlugCategory Compressor::getPlugCategory () {
return kPlugCategEffect;
}
///////////////////////////////////////////////////////////////////////////
void Compressor::resume() {
crestRms = crestPeak = MINVAL;
cvSmooth = cvAttack = cvRelease = 0.0;
logThreshold[kCurrent] = logThreshold[kTarget];
logGain[kCurrent] = logGain[kTarget];
}
///////////////////////////////////////////////////////////////////////////
void Compressor::processReplacing(float **inputs, float **outputs, VstInt32 sampleFrames) {
float *inBufferL = inputs[0];
float *inBufferR = inputs[1];
float *outBufferL = outputs[0];
float *outBufferR = outputs[1];
while(--sampleFrames >= 0) {
// Process
float inL = *inBufferL++;
float inR = *inBufferR++;
float absL = ABS(inL);
float absR = ABS(inR);
float maxLR = MAX(absL, absR);
float mult = (float) processSidechain(maxLR);
float outL = inL;
float outR = inR;
if(active) {
outL *= mult;
outR *= mult;
}
*outBufferL++ = outL;
*outBufferR++ = outR;
// Ramp parameters
logThreshold[kCurrent] = MIX(logThreshold[kTarget], logThreshold[kCurrent], rampCoeff);
logGain[kCurrent] = MIX(logGain[kTarget], logGain[kCurrent], rampCoeff);
}
// Kill denormals
cvAttack = killDenormal(cvAttack);
cvRelease = killDenormal(cvRelease);
cvSmooth = killDenormal(cvSmooth);
crestRms = killDenormal(crestRms);
crestPeak = killDenormal(crestPeak);
logThreshold[kCurrent] = killDenormal(logThreshold[kCurrent]);
logGain[kCurrent] = killDenormal(logGain[kCurrent]);
}
FORCEINLINE double Compressor::processSidechain(double inAbs) {
double fs = getSampleRate();
// Square of crest factor
double inSquare = MAX(SQUARE(inAbs), MINVAL);
crestRms = MIX(inSquare, crestRms, metaCrestCoeff);
crestPeak = MAX(MIX(inSquare, crestPeak, metaCrestCoeff), inSquare);
double crestSquare = crestPeak / crestRms;
// Attack and release coefficients
double myAttackCoeff = attackCoeff;
double myAttackTime = attackTime;
if(autoAttack) {
myAttackTime = 2.0 * metaMaxAttackTime / crestSquare;
myAttackCoeff = onePoleCoeff(fs, myAttackTime);
}
double myReleaseCoeff = releaseCoeff;
if(autoRelease) {
double myReleaseTime = 2.0 * metaMaxReleaseTime / crestSquare;
myReleaseCoeff = onePoleCoeff(fs, myReleaseTime - myAttackTime);
}
// Log conversion and overshoot
double logIn = log(MAX(inAbs, MINVAL));
double logOvershoot = logIn - logThreshold[kCurrent];
// Set ratio/slope
double mySlope = slope;
if(autoKnee) { mySlope = -1.0; }
// Set estimate for average CV
double cvEstimate = logThreshold[kCurrent] * -mySlope / 2.0;
// Set knee width
double myLogWidth = logKneeWidth;
if(autoKnee) { myLogWidth = MAX(-(cvSmooth + cvEstimate) * metaKneeMult, 0.0); }
// Soft knee rectification
double cv = 0.0;
if(logOvershoot >= myLogWidth / 2.0) {
cv = logOvershoot;
}
else if(logOvershoot > -myLogWidth / 2.0 && logOvershoot < myLogWidth / 2.0) {
cv = 1.0 / (2.0 * myLogWidth) * SQUARE(logOvershoot + myLogWidth / 2.0);
}
// Multiply by negative slope for positive CV
cv *= -mySlope;
// Release and Attack
cvRelease = MAX(cv, MIX(cv, cvRelease, myReleaseCoeff));
cvAttack = MIX(cvRelease, cvAttack, myAttackCoeff);
// Invert CV again
cv = -cvAttack;
// Smooth CV
cvSmooth = MIX(cv - cvEstimate, cvSmooth, metaAdaptCoeff);
// Make-up gain
if(autoGain) {
// Check for clipping
if(metaNoClipping && logIn + cv - (cvSmooth + cvEstimate) > MAXCLIPLOG) {
cvSmooth = logIn + cv - cvEstimate - MAXCLIPLOG;
}
// Apply automatic gain
cv -= cvSmooth + cvEstimate;
}
else {
// Apply static gain
cv += logGain[kCurrent];
}
// VCA
return exp(cv);
}
///////////////////////////////////////////////////////////////////////////
void Compressor::float2string (float value, char* text, VstInt32 maxLen) {
bool sign = false;
long digits = 2;
char buf[9];
char* ptr = buf + 8;
*ptr-- = '\0';
// Rectify and round
double dval = value;
if(dval < 0.0) { dval = -dval; }
dval += pow(10.0, -digits) * 0.5;
// Convert integer part
long count = 0;
double temp = floor(dval);
do {
*ptr-- = '0' + (char) ((long) fmod(temp, 10.0));
temp /= 10.0; count++;
} while(temp >= 1.0 && count < 7);
if(temp < 1.0) {
// Add sign
if(value < 0.f) {
*ptr-- = '-';
count++;
}
else if(sign && value > 0.f) {
*ptr-- = '+';
count++;
}
// Copy integer part
vst_strncpy(text, ptr + 1, maxLen);
if(maxLen - count > 1 && digits > 0) {
// Convert fractional part
char* ptr = buf + 7;
count = 0;
long maxdigits = 7;
if(maxdigits > digits) { maxdigits = digits; }
temp = fmod(dval, 1.0) * pow(10.0, maxdigits);
while(count < maxdigits) {
*ptr-- = '0' + (char) ((long) fmod(temp, 10.0));
temp /= 10.0; count++;
}
// Add point
*ptr = '.';
// Copy fractional part
vst_strncat(text, ptr, maxLen);
}
}
else {
// Value was too big
if(value < 0.f) {
vst_strncpy(text, "-oo", maxLen);
}
else {
vst_strncpy(text, sign?"+oo":"oo", maxLen);
}
}
}How this i s Possible pls send .
Mainly wathchin on Process Method
- Marked as answer by Sudipda Wednesday, January 23, 2013 11:58 AM
Tuesday, January 22, 2013 7:25 AM
All replies
-
Have you taken a look at Ogg Vorbis?
You could start there to see if fits your requirements.
- Edited by Andreas Johansson Saturday, January 19, 2013 12:21 PM Link is a link.
- Proposed as answer by Mike Feng Monday, January 21, 2013 5:53 AM
- Marked as answer by Sudipda Monday, January 21, 2013 8:42 AM
- Unmarked as answer by Sudipda Monday, January 21, 2013 8:43 AM
- Unproposed as answer by Sudipda Monday, January 21, 2013 8:43 AM
Saturday, January 19, 2013 12:21 PM -
not good enough.Monday, January 21, 2013 9:24 AM
-
not good enough.
Maybe you can try to specify a bit what it is you are looking for and possibly what my suggestion is lacking.Monday, January 21, 2013 11:49 AM -
this is my Compression
// based on SimpleComp v1.10 © 2006, ChunkWare Music Software, OPEN-SOURCE
using System;
using NAudio.Utils;
namespace NAudio.Dsp
{
class SimpleCompressor : AttRelEnvelope
{
// transfer function
private double threshdB; // threshold (dB)
private double ratio; // ratio (compression: < 1 ; expansion: > 1)
private double makeUpGain;
// runtime variables
private double envdB; // over-threshold envelope (dB)
public SimpleCompressor(double attackTime, double releaseTime, double sampleRate)
: base(attackTime, releaseTime, sampleRate)
{
this.threshdB = 0.0;
this.ratio = 1.0;
this.makeUpGain = 0.0;
this.envdB = DC_OFFSET;
}
public SimpleCompressor()
: base(10.0, 10.0, 44100.0)
{
this.threshdB = 0.0;
this.ratio = 1.0;
this.makeUpGain = 0.0;
this.envdB = DC_OFFSET;
}
public double MakeUpGain
{
get { return makeUpGain; }
set { makeUpGain = value; }
}
public double Threshold
{
get { return threshdB; }
set { threshdB = value; }
}
public double Ratio
{
get { return ratio; }
set { ratio = value; }
}
// call before runtime (in resume())
public void InitRuntime()
{
this.envdB = DC_OFFSET;
}
// // compressor runtime process
public void Process(ref double in1, ref double in2)
{
// sidechain
// rectify input
double cv = 0.0;
double rect1 = Math.Abs(in1); // n.b. was fabs
double rect2 = Math.Abs(in2); // n.b. was fabs
// if desired, one could use another EnvelopeDetector to smooth
// the rectified signal.
double link = Math.Max(rect1, rect2); // link channels with greater of 2
link += DC_OFFSET; // add DC offset to avoid log( 0 )
double keydB = Decibels.LinearToDecibels(link); // convert linear -> dB
// threshold
double overdB = keydB - threshdB; // delta over threshold
if (overdB < 0.0)
overdB = 0.0;
// attack/release
overdB += DC_OFFSET; // add DC offset to avoid denormal
Run(overdB, ref envdB); // run attack/release envelope
overdB = envdB - DC_OFFSET; // subtract DC offset
// Regarding the DC offset: In this case, since the offset is added before
// the attack/release processes, the envelope will never fall below the offset,
// thereby avoiding denormals. However, to prevent the offset from causing
// constant gain reduction, we must subtract it from the envelope, yielding
// a minimum value of 0dB.
// transfer function
if (MakeUpGain <= 10.0f)
{
double gr = overdB * (1 / ratio - 1.0); // gain reduction (dB)
gr = Decibels.DecibelsToLinear(gr) * Decibels.DecibelsToLinear(makeUpGain); // convert dB -> linear gr = overdB * (1 / ratio - 1.0); // gain reduction (dB)
// output gain
in1 *= gr; // apply gain reduction to input
in2 *= gr;
}
else
{
double gr = overdB * (1 / ratio - 1.0); // gain reduction (dB)
in1 *= gr; // apply gain reduction to input
in2 *= gr;
}
}
}
}
and Tried to Apply Audiocity this method///////////////////////////////////////////////////////////////////////////
//
// "Investigation in Dynamic Range Compression" - MSc Project
// Copyright 2009, Michael Massberg
// michael@massberg.org
//
///////////////////////////////////////////////////////////////////////////
#include "compressor.h"
///////////////////////////////////////////////////////////////////////////
AudioEffect* createEffectInstance(audioMasterCallback audioMaster) {
return new Compressor(audioMaster);
}
///////////////////////////////////////////////////////////////////////////
Compressor::Compressor(audioMasterCallback audioMaster)
: AudioEffectX(audioMaster, 1, kParamCount) {
setUniqueID(CCONST('c', 'm', 'p', 'r'));
setNumInputs(2);
setNumOutputs(2);
canProcessReplacing();
setEditor(new CompressorEditor(this));
vst_strncpy(programName, "Default", kVstMaxProgNameLen);
for(VstInt32 i=0; i<kParamCount; i++) {
setParameter(i, getParameterDefault(i));
}
DECLARE_VST_DEPRECATED(canMono) (true);
#if !ENABLEPRESETS
programsAreChunks();
#endif
initialize();
}
Compressor::~Compressor() { }
///////////////////////////////////////////////////////////////////////////
void Compressor::initialize() {
double fs = getSampleRate();
rampCoeff = onePoleCoeff(fs, 0.05);
}
///////////////////////////////////////////////////////////////////////////
#if !ENABLEPRESETS
VstInt32 Compressor::getChunk(void **data, bool isPreset) {
static char buffer[32];;
memset(buffer, 0, 32);
*data = buffer;
return 32;
}
VstInt32 Compressor::setChunk(void *data, VstInt32 byteSize, bool isPreset) {
for(VstInt32 i=0; i<kParamCount; i++) {
setParameter(i, getParameterDefault(i));
}
return 1;
}
#endif
///////////////////////////////////////////////////////////////////////////
void Compressor::setParameter(VstInt32 index, float value) {
params[index] = value;
double fs = getSampleRate();
switch(index) {
case kParamThreshold: logThreshold[kTarget] = log(pow(10.0, value * -MAXGAINDB / 20.0)); break;
case kParamRatio: slope = -value; break;
case kParamKneeWidth: logKneeWidth = log(pow(10.0, value * MAXGAINDB / 20.0)); break;
case kParamGain: logGain[kTarget] = log(pow(10.0, value * MAXGAINDB / 20.0)); break;
case kParamAttack:
attackTime = PARAM2LOG(value, MINATTACKTIME, MAXATTACKTIME);
attackCoeff = onePoleCoeff(fs, attackTime);
break;
case kParamRelease:
releaseTime = PARAM2LOG(value, MINRELEASETIME, MAXRELEASETIME);
releaseCoeff = onePoleCoeff(fs, releaseTime);
break;
case kParamActive: active = (value >= 0.5f); break;
case kParamAutoKnee: autoKnee = (value >= 0.5f); break;
case kParamAutoGain: autoGain = (value >= 0.5f); break;
case kParamAutoAttack: autoAttack = (value >= 0.5f); break;
case kParamAutoRelease: autoRelease = (value >= 0.5f); break;
case kParamMetaKneeMult:
metaKneeMult = PARAM2LIN(value, MINKNEEMULT, MAXKNEEMULT);
break;
case kParamMetaMaxAttack:
metaMaxAttackTime = PARAM2LOG(value, MINATTACKTIME, MAXATTACKTIME);
break;
case kParamMetaMaxRelease:
metaMaxReleaseTime = PARAM2LOG(value, MINRELEASETIME, MAXRELEASETIME);
break;
case kParamMetaCrest:
metaCrestTime = PARAM2LOG(value, MINCRESTTIME, MAXCRESTTIME);
metaCrestCoeff = onePoleCoeff(fs, metaCrestTime);
break;
case kParamMetaAdapt:
metaAdaptTime = PARAM2LOG(value, MINADAPTTIME, MAXADAPTTIME);
metaAdaptCoeff = onePoleCoeff(fs, metaAdaptTime);
break;
case kParamMetaNoClipping: metaNoClipping = (value >= 0.5f); break;
}
if(editor) {
((AEffGUIEditor*) editor)->setParameter(index, value);
}
}
float Compressor::getParameter(VstInt32 index) {
return params[index];
}
float Compressor::getParameterDefault(VstInt32 index) {
switch(index) {
case kParamActive: return 1.f;
case kParamThreshold: return 0.f;
case kParamRatio: return 0.f;
case kParamGain: return 0.f;
case kParamAttack: return (float) LOG2PARAM(0.005, MINATTACKTIME, MAXATTACKTIME);
case kParamRelease: return (float) LOG2PARAM(0.05, MINRELEASETIME, MAXRELEASETIME);
case kParamAutoAttack:
case kParamAutoRelease:
case kParamAutoKnee:
case kParamAutoGain:
return 1.f;
case kParamMetaKneeMult: return (float) LIN2PARAM(2.0, MINKNEEMULT, MAXKNEEMULT);
case kParamMetaMaxAttack: return (float) LOG2PARAM(0.08, MINATTACKTIME, MAXATTACKTIME);
case kParamMetaMaxRelease: return (float) LOG2PARAM(1.0, MINRELEASETIME, MAXRELEASETIME);
case kParamMetaCrest: return (float) LOG2PARAM(0.2, MINCRESTTIME, MAXCRESTTIME);
case kParamMetaAdapt: return (float) LOG2PARAM(2.5, MINADAPTTIME, MAXADAPTTIME);
case kParamMetaNoClipping: return 1.f;
}
return 0.f;
}
float Compressor::getParameterFromString(VstInt32 index, char *text) {
double x = atof(text);
switch(index) {
case kParamThreshold: return (float) CLAMP(fabs(x) / MAXGAINDB, 0.0, 1.0);
case kParamRatio: return (float) (1.0 - 1.0 / CLAMP(fabs(x), 1.0, 100.0));
case kParamKneeWidth: return (float) CLAMP(fabs(x) / MAXGAINDB, 0.0, 1.0);
case kParamGain: return (float) CLAMP(fabs(x) / MAXGAINDB, 0.0, 1.0);
case kParamAttack: return (float) LOG2PARAM(CLAMP(fabs(x) / 1000.0, MINATTACKTIME, MAXATTACKTIME), MINATTACKTIME, MAXATTACKTIME);
case kParamRelease: return (float) LOG2PARAM(CLAMP(fabs(x) / 1000.0, MINRELEASETIME, MAXRELEASETIME), MINRELEASETIME, MAXRELEASETIME);
}
return getParameter(index);
}
///////////////////////////////////////////////////////////////////////////
void Compressor::getParameterName(VstInt32 index, char *label) {
switch(index) {
case kParamActive: vst_strncpy(label, "Active", kVstMaxParamStrLen); return;
case kParamThreshold: vst_strncpy(label, "Thresh", kVstMaxParamStrLen); return;
case kParamKneeWidth: vst_strncpy(label, "Width", kVstMaxParamStrLen); return;
case kParamAutoKnee: vst_strncpy(label, "AutoKnee", kVstMaxParamStrLen); return;
case kParamGain: vst_strncpy(label, "Gain", kVstMaxParamStrLen); return;
case kParamAutoGain: vst_strncpy(label, "AutoGain", kVstMaxParamStrLen); return;
case kParamRatio: vst_strncpy(label, "Ratio", kVstMaxParamStrLen); return;
case kParamAttack: vst_strncpy(label, "Attack", kVstMaxParamStrLen); return;
case kParamAutoAttack: vst_strncpy(label, "AutoAtt", kVstMaxParamStrLen); return;
case kParamRelease: vst_strncpy(label, "Release", kVstMaxParamStrLen); return;
case kParamAutoRelease: vst_strncpy(label, "AutoRel", kVstMaxParamStrLen); return;
case kParamMetaKneeMult: vst_strncpy(label, "KneeMult", kVstMaxParamStrLen); return;
case kParamMetaMaxAttack: vst_strncpy(label, "MaxAtt", kVstMaxParamStrLen); return;
case kParamMetaMaxRelease: vst_strncpy(label, "MaxRel", kVstMaxParamStrLen); return;
case kParamMetaCrest: vst_strncpy(label, "Crest", kVstMaxParamStrLen); return;
case kParamMetaAdapt: vst_strncpy(label, "Adapt", kVstMaxParamStrLen); return;
case kParamMetaNoClipping: vst_strncpy(label, "NoClip", kVstMaxParamStrLen); return;
}
vst_strncpy(label, "", kVstMaxParamStrLen);
}
void Compressor::getParameterDisplay(VstInt32 index, char *text) {
switch(index) {
case kParamRatio:
if(slope > -0.99) {
float2string((float) (1.0 / (1.0 + slope)), text, kVstMaxParamStrLen);
vst_strncat(text, ":1", kVstMaxParamStrLen);
}
else {
vst_strncpy(text, "oo:1", kVstMaxParamStrLen);
}
return;
case kParamThreshold: dB2string((float) exp(logThreshold[kTarget]), text, kVstMaxParamStrLen); return;
case kParamGain: dB2string((float) exp(logGain[kTarget]), text, kVstMaxParamStrLen); return;
case kParamKneeWidth: dB2string((float) exp(logKneeWidth), text, kVstMaxParamStrLen); return;
case kParamAttack: float2string((float) (attackTime * 1000.0), text, kVstMaxParamStrLen); return;
case kParamRelease: float2string((float) (releaseTime * 1000.0), text, kVstMaxParamStrLen); return;
case kParamMetaKneeMult: float2string((float) metaKneeMult, text, kVstMaxParamStrLen); return;
case kParamMetaMaxAttack: float2string((float) (metaMaxAttackTime * 1000.0), text, kVstMaxParamStrLen); return;
case kParamMetaMaxRelease: float2string((float) (metaMaxReleaseTime * 1000.0), text, kVstMaxParamStrLen); return;
case kParamMetaCrest: float2string((float) (metaCrestTime * 1000.0), text, kVstMaxParamStrLen); return;
case kParamMetaAdapt: float2string((float) (metaAdaptTime * 1000.0), text, kVstMaxParamStrLen); return;
}
vst_strncpy(text, (getParameter(index) >= 0.5f)?"On":"Off", kVstMaxParamStrLen);
}
void Compressor::getParameterLabel(VstInt32 index, char *label) {
switch(index) {
case kParamThreshold:
case kParamGain:
case kParamKneeWidth:
vst_strncpy(label, "dB", kVstMaxParamStrLen);
return;
case kParamAttack:
case kParamRelease:
case kParamMetaMaxAttack:
case kParamMetaMaxRelease:
case kParamMetaCrest:
case kParamMetaAdapt:
vst_strncpy(label, "ms", kVstMaxParamStrLen);
return;
}
vst_strncpy(label, "", kVstMaxParamStrLen);
}
///////////////////////////////////////////////////////////////////////////
float Compressor::getMeter(VstInt32 index) {
switch(index) {
case kMeterGR:
if(active) {
return (float) CLAMP((-cvAttack - MINMETERLOG) / (0.0 - MINMETERLOG), 0.0, 1.0);
}
return 1.f;
}
return 0.f;
}
///////////////////////////////////////////////////////////////////////////
void Compressor::getProgramName(char *text) {
vst_strncpy(text, programName, kVstMaxProgNameLen);
}
void Compressor::setProgramName(char* name) {
vst_strncpy(programName, name, kVstMaxProgNameLen);
}
///////////////////////////////////////////////////////////////////////////
void Compressor::setSampleRate(float sampleRate) {
AudioEffectX::setSampleRate(sampleRate);
for(int j=0; j<kParamCount; j++) {
setParameter(j, getParameter(j));
}
initialize();
}
void Compressor::setProgram(VstInt32 program) {
AudioEffectX::setProgram(program);
for(int j=0; j<kParamCount; j++) {
setParameter(j, getParameter(j));
}
}
///////////////////////////////////////////////////////////////////////////
bool Compressor::getEffectName(char *name) {
vst_strncpy(name, "Auto Compressor", kVstMaxEffectNameLen);
return true;
}
bool Compressor::getProductString (char *text) {
vst_strncpy(text, "VST Plug-Ins", kVstMaxProductStrLen);
return true;
}
bool Compressor::getVendorString (char *text) {
vst_strncpy(text, "Michael Massberg", kVstMaxVendorStrLen);
return true;
}
VstInt32 Compressor::getVendorVersion() {
return 1000;
}
VstPlugCategory Compressor::getPlugCategory () {
return kPlugCategEffect;
}
///////////////////////////////////////////////////////////////////////////
void Compressor::resume() {
crestRms = crestPeak = MINVAL;
cvSmooth = cvAttack = cvRelease = 0.0;
logThreshold[kCurrent] = logThreshold[kTarget];
logGain[kCurrent] = logGain[kTarget];
}
///////////////////////////////////////////////////////////////////////////
void Compressor::processReplacing(float **inputs, float **outputs, VstInt32 sampleFrames) {
float *inBufferL = inputs[0];
float *inBufferR = inputs[1];
float *outBufferL = outputs[0];
float *outBufferR = outputs[1];
while(--sampleFrames >= 0) {
// Process
float inL = *inBufferL++;
float inR = *inBufferR++;
float absL = ABS(inL);
float absR = ABS(inR);
float maxLR = MAX(absL, absR);
float mult = (float) processSidechain(maxLR);
float outL = inL;
float outR = inR;
if(active) {
outL *= mult;
outR *= mult;
}
*outBufferL++ = outL;
*outBufferR++ = outR;
// Ramp parameters
logThreshold[kCurrent] = MIX(logThreshold[kTarget], logThreshold[kCurrent], rampCoeff);
logGain[kCurrent] = MIX(logGain[kTarget], logGain[kCurrent], rampCoeff);
}
// Kill denormals
cvAttack = killDenormal(cvAttack);
cvRelease = killDenormal(cvRelease);
cvSmooth = killDenormal(cvSmooth);
crestRms = killDenormal(crestRms);
crestPeak = killDenormal(crestPeak);
logThreshold[kCurrent] = killDenormal(logThreshold[kCurrent]);
logGain[kCurrent] = killDenormal(logGain[kCurrent]);
}
FORCEINLINE double Compressor::processSidechain(double inAbs) {
double fs = getSampleRate();
// Square of crest factor
double inSquare = MAX(SQUARE(inAbs), MINVAL);
crestRms = MIX(inSquare, crestRms, metaCrestCoeff);
crestPeak = MAX(MIX(inSquare, crestPeak, metaCrestCoeff), inSquare);
double crestSquare = crestPeak / crestRms;
// Attack and release coefficients
double myAttackCoeff = attackCoeff;
double myAttackTime = attackTime;
if(autoAttack) {
myAttackTime = 2.0 * metaMaxAttackTime / crestSquare;
myAttackCoeff = onePoleCoeff(fs, myAttackTime);
}
double myReleaseCoeff = releaseCoeff;
if(autoRelease) {
double myReleaseTime = 2.0 * metaMaxReleaseTime / crestSquare;
myReleaseCoeff = onePoleCoeff(fs, myReleaseTime - myAttackTime);
}
// Log conversion and overshoot
double logIn = log(MAX(inAbs, MINVAL));
double logOvershoot = logIn - logThreshold[kCurrent];
// Set ratio/slope
double mySlope = slope;
if(autoKnee) { mySlope = -1.0; }
// Set estimate for average CV
double cvEstimate = logThreshold[kCurrent] * -mySlope / 2.0;
// Set knee width
double myLogWidth = logKneeWidth;
if(autoKnee) { myLogWidth = MAX(-(cvSmooth + cvEstimate) * metaKneeMult, 0.0); }
// Soft knee rectification
double cv = 0.0;
if(logOvershoot >= myLogWidth / 2.0) {
cv = logOvershoot;
}
else if(logOvershoot > -myLogWidth / 2.0 && logOvershoot < myLogWidth / 2.0) {
cv = 1.0 / (2.0 * myLogWidth) * SQUARE(logOvershoot + myLogWidth / 2.0);
}
// Multiply by negative slope for positive CV
cv *= -mySlope;
// Release and Attack
cvRelease = MAX(cv, MIX(cv, cvRelease, myReleaseCoeff));
cvAttack = MIX(cvRelease, cvAttack, myAttackCoeff);
// Invert CV again
cv = -cvAttack;
// Smooth CV
cvSmooth = MIX(cv - cvEstimate, cvSmooth, metaAdaptCoeff);
// Make-up gain
if(autoGain) {
// Check for clipping
if(metaNoClipping && logIn + cv - (cvSmooth + cvEstimate) > MAXCLIPLOG) {
cvSmooth = logIn + cv - cvEstimate - MAXCLIPLOG;
}
// Apply automatic gain
cv -= cvSmooth + cvEstimate;
}
else {
// Apply static gain
cv += logGain[kCurrent];
}
// VCA
return exp(cv);
}
///////////////////////////////////////////////////////////////////////////
void Compressor::float2string (float value, char* text, VstInt32 maxLen) {
bool sign = false;
long digits = 2;
char buf[9];
char* ptr = buf + 8;
*ptr-- = '\0';
// Rectify and round
double dval = value;
if(dval < 0.0) { dval = -dval; }
dval += pow(10.0, -digits) * 0.5;
// Convert integer part
long count = 0;
double temp = floor(dval);
do {
*ptr-- = '0' + (char) ((long) fmod(temp, 10.0));
temp /= 10.0; count++;
} while(temp >= 1.0 && count < 7);
if(temp < 1.0) {
// Add sign
if(value < 0.f) {
*ptr-- = '-';
count++;
}
else if(sign && value > 0.f) {
*ptr-- = '+';
count++;
}
// Copy integer part
vst_strncpy(text, ptr + 1, maxLen);
if(maxLen - count > 1 && digits > 0) {
// Convert fractional part
char* ptr = buf + 7;
count = 0;
long maxdigits = 7;
if(maxdigits > digits) { maxdigits = digits; }
temp = fmod(dval, 1.0) * pow(10.0, maxdigits);
while(count < maxdigits) {
*ptr-- = '0' + (char) ((long) fmod(temp, 10.0));
temp /= 10.0; count++;
}
// Add point
*ptr = '.';
// Copy fractional part
vst_strncat(text, ptr, maxLen);
}
}
else {
// Value was too big
if(value < 0.f) {
vst_strncpy(text, "-oo", maxLen);
}
else {
vst_strncpy(text, sign?"+oo":"oo", maxLen);
}
}
}How this i s Possible pls send .
Mainly wathchin on Process Method
- Marked as answer by Sudipda Wednesday, January 23, 2013 11:58 AM
Tuesday, January 22, 2013 7:25 AM