I am trying to do bass boost for my audio input to 12 dB. Here is the code
public class BassBoost {
double xn1, xn2, yn1, yn2;
double omega, sn, cs, a, shape, beta, b0, b1, b2, a0, a1, a2;
public BassBoost(int frequency, int dB_boost, int sampleRate) {
xn1 = 0;
xn2 = 0;
yn1 = 0;
yn2 = 0;
omega = 2 * Utils.pi * frequency / sampleRate;
sn = Math.sin(omega);
cs = Math.cos(omega);
a = Math.exp(Math.log(10.0) * dB_boost / 40);
shape = 1.0;
beta = Math.sqrt((a * a + 1) / shape - (Math.pow((a - 1), 2)));
/* Coefficients */
b0 = a * ((a + 1) - (a - 1) * cs + beta * sn);
b1 = 2 * a * ((a - 1) - (a + 1) * cs);
b2 = a * ((a + 1) - (a - 1) * cs - beta * sn);
a0 = ((a + 1) + (a - 1) * cs + beta * sn);
a1 = -2 * ((a - 1) + (a + 1) * cs);
a2 = (a + 1) + (a - 1) * cs - beta * sn;
}
public void process(double[] buffer, int length) {
double out, in = 0;
for (int i = 0; i < length; i++) {
in = buffer[i];
out = (b0 * in + b1 * xn1 + b2 * xn2 - a1 * yn1 - a2 * yn2) / a0;
xn2 = xn1;
xn1 = in;
yn2 = yn1;
yn1 = out;
if (out < -1.0)
out = -1.0;
else if (out > 1.0)
out = 1.0; // Prevents clipping
buffer[i] = out;
}
}
}
And Here is the pseudo code which calls the process
Audio is recorded and stored in short buffer. Buffer divided into small array and copied to double array for filter processing. If I don't divide I am getting OutofMemory as I am trying this on android phones. Filtering is applied (LPF, HPF) Output double buffer is amplified with following code before writing to Byte array.
void doOutput(int outlen, boolean maxGain) {
int qi;
int i, i2;
while (true) {
int max = 0;
i = outbp;
for (i2 = 0; i2 < outlen; i2 += 4) {
qi = (int) (leftBuffer[i] * outputGain);
if (qi > max)
max = qi;
if (qi < -max)
max = -qi;
ob[i2 + 1] = (byte) (qi >> 8);
ob[i2] = (byte) qi;
i = (i + 1) & fbufmask;
}
i = outbp;
for (i2 = 2; i2 < outlen; i2 += 4) {
qi = (int) (rightBuffer[i] * outputGain);
if (qi > max)
max = qi;
if (qi < -max)
max = -qi;
ob[i2 + 1] = (byte) (qi >> 8);
ob[i2] = (byte) qi;
i = (i + 1) & fbufmask;
}
// if we're getting overflow, adjust the gain
if (max > 32767) {
outputGain *= 30000. / max;
if (outputGain < 1e-8 || Double.isInfinite(outputGain)) {
unstable = true;
break;
}
continue;
} else if (maxGain && max < 24000) {
if (max == 0) {
if (outputGain == 1)
break;
outputGain = 1;
} else
outputGain *= 30000. / max;
continue;
}
break;
}
if (unstable)
return;
outbp = i;
out.write(ob, 0, outlen);
}
This code is for android so it has to be memory efficient. I tried using Arraylist but that was also going outofmemory.
Question is To apply consistent outputGain though out the buffer, I am currently applying filtering twice and writing to byteOutputStream once. I tried using Arraylist to store output buffer before applying single outputGain but that was going outofmemory to store entire Double buffer (1 min recording). Also for the BassBoost I want to apply it once to entire output. Is there memory efficient way to do it. Using ArrayList is out of question. To get a consistent outputGain, I have to go through the entire output buffer and apply it with single outputGain.
Want to make the above sample code efficient so that I do not have to go through the buffer twice. Also Bass Boost if I apply it to chunks gives me breaks in the continuous sound.
Thanks