diff --git a/compressor/Makefile b/compressor/Makefile
new file mode 100644
index 0000000..afac6c7
--- /dev/null
+++ b/compressor/Makefile
@@ -0,0 +1,2 @@
+all:
+ mkoctfile -mex level_detect.c
diff --git a/compressor/cmp_eval.m b/compressor/cmp_eval.m
new file mode 100644
index 0000000..eedc779
--- /dev/null
+++ b/compressor/cmp_eval.m
@@ -0,0 +1,72 @@
+## Copyright (C) 2020 Jens
+##
+## 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 3 of the License, or
+## (at your option) 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, see
+## .
+
+## -*- texinfo -*-
+## @deftypefn {} {@var{retval} =} eq_eval (@var{input1}, @var{input2})
+##
+## @seealso{}
+##
+## Exapmple: cmp_eval("snip.wav", 0.25, -40, 18);
+## @end deftypefn
+
+## Author: Jens
+## Created: 2020-06-22
+
+function cmp_eval (filename_in, R, lev_knee_dB, gain_makeup_dB)
+
+fs = 48000
+[x, fs] = audioread(filename_in);
+N = size(x)(1)
+num_channels = size(x)(2)
+filename_out = to_filename_out(filename_in, "out");
+
+time_look_ahead = 0.01;
+time_attack = 0.01;
+time_release = 1.0;
+
+n_look_ahead = round(time_look_ahead*fs);
+h_dly = [zeros(1, n_look_ahead-1) 1];
+
+x_dly = filter(h_dly, 1, x);
+
+alpha_a = 5/(time_attack*fs);
+alpha_r = 5/(time_release*fs);
+
+lev = level_detect(x, alpha_a, alpha_r);
+lev_dB = max(-120, 20*log10(lev));
+
+k_makeup_gain = 10^(gain_makeup_dB/20);
+gain1 = min(8, (1/8)./(lev+0.1));
+[lev_out_dB, gain2_dB] = cmp_gain(R, lev_knee_dB, lev_dB);
+gain2 = 10.^(gain2_dB/20);
+y1 = gain1.*x_dly * 2;
+y2 = gain2.*x_dly * k_makeup_gain;
+audiowrite(to_filename_out(filename_in, "gain1"), gain1, fs)
+audiowrite(to_filename_out(filename_in, "gain2"), gain2, fs)
+audiowrite(to_filename_out(filename_in, "out1"), y1, fs)
+audiowrite(to_filename_out(filename_in, "out2"), y2, fs)
+audiowrite(to_filename_out(filename_in, "lev"), lev, fs)
+
+gain_out = [];
+gain_in = [];
+for g=0:0.1:1,
+ gain_out = [gain_out cmp_gain(R, g, 0.01)];
+ gain_in = [gain_in g];
+endfor
+plot(gain_in, gain_out); grid();
+
+endfunction
+
diff --git a/compressor/cmp_gain.m b/compressor/cmp_gain.m
new file mode 100644
index 0000000..a8786eb
--- /dev/null
+++ b/compressor/cmp_gain.m
@@ -0,0 +1,5 @@
+function [lev_out_dB, gain_out_dB] = cmp_gain(R, lev_knee_dB, lev_in_dB)
+ k = lev_in_dB > lev_knee_dB;
+ lev_out_dB = (1-k).*lev_in_dB + k.*(lev_knee_dB + R*(lev_in_dB - lev_knee_dB));
+ gain_out_dB = - (lev_in_dB - lev_out_dB);
+endfunction
diff --git a/compressor/cmp_gain_eval.m b/compressor/cmp_gain_eval.m
new file mode 100644
index 0000000..5afbc12
--- /dev/null
+++ b/compressor/cmp_gain_eval.m
@@ -0,0 +1,42 @@
+## Copyright (C) 2020 Jens
+##
+## 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 3 of the License, or
+## (at your option) 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, see
+## .
+
+## -*- texinfo -*-
+## @deftypefn {} {@var{retval} =} eq_eval (@var{input1}, @var{input2})
+##
+## @seealso{}
+## @end deftypefn
+
+## Author: Jens
+## Created: 2020-06-22
+
+function cmp_gain_eval (R)
+epsilon = 0.01;
+dl = 10;
+gain_out = [];
+lev_out = [];
+lev_in = [];
+for li=-120:dl:0,
+ [lo, go] = cmp_gain(R, -20, li);
+ lev_out = [lev_out lo];
+ lev_in = [lev_in li];
+ gain_out = [gain_out go];
+endfor
+close;
+plot(lev_in, lev_out, lev_in, gain_out); grid();
+
+endfunction
+
diff --git a/compressor/level_detect.c b/compressor/level_detect.c
new file mode 100644
index 0000000..9d13bdb
--- /dev/null
+++ b/compressor/level_detect.c
@@ -0,0 +1,70 @@
+#include
+#include
+void mexFunction (int nlhs, mxArray *plhs[],
+ int nrhs, const mxArray *prhs[])
+{
+ const char *funcName = mexFunctionName ();
+ mexPrintf ("You called function: %s\n", funcName);
+ mexPrintf ("I have %d inputs and %d outputs\n", nrhs, nlhs);
+
+ if (nrhs < 3)
+ mexErrMsgTxt ("Too few arguments");
+
+ const mxArray *array_x = prhs[0];
+ const mxArray *scalar_alpha_attack = prhs[1];
+ const mxArray *scalar_alpha_release = prhs[2];
+
+
+ plhs[0] = mxCreateNumericArray (mxGetNumberOfDimensions (array_x),
+ mxGetDimensions (array_x),
+ mxGetClassID (array_x),
+ mxIsComplex (array_x));
+
+ mwIndex channelsDim = 1;
+ double alpha_a = *mxGetPr(scalar_alpha_attack);
+ double alpha_r = *mxGetPr(scalar_alpha_release);
+
+ double *vri = mxGetPr (array_x);
+ double *vro = mxGetPr (plhs[0]);
+
+ mwSize M = mxGetM (array_x);
+ mwSize N = mxGetN (array_x);
+ if (channelsDim == 1)
+ {
+ M = mxGetN (array_x);
+ N = mxGetM (array_x);
+ }
+
+ mexPrintf ("Number of channels = %u\n", M);
+ mexPrintf ("Number of samples per channel = %u\n", N);
+ mexPrintf ("alpha_a = %f\n", alpha_a);
+ mexPrintf ("alpha_r = %f\n", alpha_r);
+
+ double level[M];
+ for (mwIndex m=0; m < M; m++)
+ {
+ level[m] = 0;
+ }
+
+ for (mwIndex n=0; n < N; n++)
+ {
+ for (mwIndex m=0; m < M; m++)
+ {
+ double x = vri[n*M + m];
+ double xmag = fabs(x);
+
+ if (xmag > level[m])
+ {
+ level[m] = (1.0-alpha_a)*level[m] + alpha_a*xmag;
+ }
+ else
+ {
+ level[m] = (1.0-alpha_r)*level[m];
+ }
+ vro[n*M + m] = level[m];
+ }
+ }
+}
+
+
+