java - Java 中的低音增强

标签 java android performance audio

我正在尝试将音频输入的低音提升到 12 dB。这是代码

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;
        }
    }
}

这是调用进程的伪代码

音频被记录并存储在短缓冲区中。 Buffer分成small数组复制到double数组进行过滤处理。如果我不划分,我将在 Android 手机上尝试此操作时出现 OutofMemory。 应用过滤(LPF、HPF) 在写入字节数组之前,使用以下代码放大输出双缓冲区。

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);
}

此代码适用于 android,因此它必须具有内存效率。我尝试使用 Arraylist,但它也会耗尽内存。

问题是 为了在缓冲区外应用一致的 outputGain,我目前正在应用过滤两次并写入 byteOutputStream 一次。在应用单个 outputGain 之前,我尝试使用 Arraylist 来存储输出缓冲区,但这会耗尽内存来存储整个双缓冲区(1 分钟记录)。同样对于 BassBoost,我想将它应用于整个输出。有没有内存有效的方法来做到这一点。使用 ArrayList 是不可能的。为了获得一致的 outputGain,我必须遍历整个输出缓冲区并使用单个 outputGain 应用它。

想要使上面的示例代码高效,这样我就不必两次通过缓冲区。此外,如果我将低音增强应用于 block ,我会在连续的声音中中断。

谢谢

最佳答案

A short[]一分钟的 44.1kHz 立体声需要 44100 * 2 * 2 * 60 = 10584000 ,或大约 10MB 的内存。

只是一个普通的短缓冲区。

由于您使用的是 ArrayList<Double> ,根据您的评论,它变得更大了。 Java 为每个 Object 添加了一些开销,并且此数组列表将包含大约 5 百万 个对象。我很确定开销量因 VM 而异。

不过,我相信,开销是at least 8 bytesObject .用你的500万Shorts , 那(8 + 8) * 5M = 80MB 最低限度

看看这是怎么回事?

我认为您不想创建 500 万个对象。我给出的数字仅适用于样本本身。如果您在处理阶段使用额外的内存,情况会更糟。这就是为什么基本上每个音频应用程序都按 block 进行处理的原因。那里有大量数据,即使是相对“短”的剪辑也是如此。

关于java - Java 中的低音增强,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18067415/

相关文章:

c# - 基于 Mono 的应用程序是否消耗更多电池(Android)

android - 错误 -24 Google Play 应用程序 android

android - 如何在Camera X支持库中设置曝光补偿?

android - 以编程方式将按钮宽度设置为父 LinearLayout 的 50%

linq - 从 C# 调用的存储过程的执行时间是从 SQL Management studio 调用的存储过程的 6 倍

javascript - AngularJS 和 Javascript 大数据循环性能

algorithm - 我应该怎么做才能优化我的 jogl 性能?

java - 如何将mysql数据库添加到项目设置中。?

java - DecimalFormat 模式

java - CSV 保留 CRLF 同时替换 LF