当前位置: 首页 > 知识库问答 >
问题:

计算两个声道的音频电平/振幅/分贝

郑俊彦
2023-03-14

我读过两篇文章,内容是从AudioInputStream中提取样本并将其转换为dB。

https://stackoverflow.com/a/26576548/8428414

https://stackoverflow.com/a/26824664/8428414

据我所知,byte[]字节 具有如下结构:

Index 0: Sample 0 (Left Channel)
Index 1: Sample 0 (Right Channel)
Index 2: Sample 1 (Left Channel)
Index 3: Sample 1 (Right Channel)
Index 4: Sample 2 (Left Channel)
Index 5: Sample 2 (Right Channel)

在第一篇文章中,它展示了如何从一个通道(单声道)获取样本。

所以,我的问题是我想分别获取右通道和左通道的样本,以便计算右通道和左通道的dB。

这是代码。如何将其更改为分别获得右通道和左通道?我无法理解索引I是如何变化的。。。

final byte[] buffer = new byte[2048];

float[] samples = new float[buffer.length / 2];

for (int n = 0; n != -1; n = in.read(buffer, 0, buffer.length)) {
    line.write(buffer, 0, n);

    for (int i = 0, sampleIndex = 0; i < n; ) {
        int sample = 0;

        sample |= buffer[i++] & 0xFF; // (reverse these two lines
        sample |= buffer[i++] << 8;   //  if the format is big endian)

        // normalize to range of +/-1.0f
        samples[sampleIndex++] = sample / 32768f;
    }

    float rms = 0f;
    for (float sample : samples) {
        rms += sample * sample;
    }

    rms = (float) Math.sqrt(rms / samples.length);

希望你能帮助我。提前谢谢你。


共有1个答案

郑卜鹰
2023-03-14

保存立体声信号的格式称为交错。也就是说,正如您正确描述的那样,它是有限责任...因此,您首先需要读取左侧样本,然后读取右侧样本,依此类推。

我编辑了您的代码以反映这一点。然而,通过重构仍有一些改进空间。

注意:代码更改仅处理交织。我还没有检查您的其余代码。

final byte[] buffer = new byte[2048];

// create two buffers. One for the left, one for the right channel.
float[] leftSamples = new float[buffer.length / 4];
float[] rightSamples = new float[buffer.length / 4];

for (int n = 0; n != -1; n = in.read(buffer, 0, buffer.length)) {
    line.write(buffer, 0, n);

    for (int i = 0, sampleIndex = 0; i < n; ) {
        int sample = 0;

        leftSample |= buffer[i++] & 0xFF; // (reverse these two lines
        leftSample |= buffer[i++] << 8;   //  if the format is big endian)

        rightSample |= buffer[i++] & 0xFF; // (reverse these two lines
        rightSample |= buffer[i++] << 8;   //  if the format is big endian)

        // normalize to range of +/-1.0f
        leftSamples[sampleIndex] = leftSample / 32768f;
        rightSamples[sampleIndex] = rightSample / 32768f;

        sampleIndex++;
    }

    // now compute RMS for left
    float leftRMS = 0f;
    for (float sample : leftSamples) {
        leftRMS += sample * sample;
    }

    leftRMS = (float) Math.sqrt(leftRMS / leftSamples.length);

    // ...and right
    float rightRMS = 0f;
    for (float sample : rightSamples) {
        rightRMS += sample * sample;
    }

    rightRMS = (float) Math.sqrt(rightRMS / rightSamples.length);
}
 类似资料:
  • 我想用java为麦克风创建一个音频电平表,以检查输入的声音有多大。它应该看起来像操作系统。我不是在问gui。它只是计算由生成的ByTestStream中的音频级别 所以我已经有一些正在运行的东西,但它甚至没有接近我的操作系统(窗口)的水平计它卡在中间。我的值在0到100之间,这很好,但是在中间的音量中,无论输入多大声,它都卡在60左右。 我现在是这样计算的: 是否有更好/更精确的方法来计算音频级别

  • 当使用web audio API制作振荡器时,我总是听到当停止它时的咔嗒声。我四处寻找,但没有一个解决办法对我有效。我尝试了所有的实现从我如何避免这种‘咔哒’声音时,我停止播放一个声音?和更多 我读到一个解决方案是等待下一个零振幅值,然后立即停止播放。有没有一种方法可以使用web audio API做到这一点? 我正在考虑为我的项目切换到Tone.js,因为声音不需要点击就可以播放。他们是如何解决

  • 我正在编写一个应用程序,它需要监听麦克风并给我一个实时的振幅和音调输出。我已经找到了如何进行音高识别的方法。我对fft做了很多研究。找到了Android库TarsosDSP wich,使听音高变得非常简单: 我还研究了如何使用内置android进行振幅检测。GetMaxAmplific()方法。 但我的问题是,我一辈子都不知道如何同时做这两件事。问题是你显然可以运行多个麦克风实例。就像你试图在不同

  • 在使用Opera44.0时,我正在摆弄音频API,并尝试了一个简单的示例: 它按预期工作,声音播放2秒,然后停止。 然后我试着往上走一点,当一个按钮被点击时播放一个声音: 不管用.单击按钮时调用函数(我在函数中使用进行了检查),但不播放任何声音。我尝试刷新页面,重新启动浏览器..什么都没有。 经过一些研究,我发现当调用时,振荡器会被丢弃,因此每次都必须创建一个新的振荡器。我发现的几乎所有示例都围绕

  • 我正在从两个不同的线程接收视频H264编码数据和音频G.711 PCM编码数据,以mux/写入多媒体容器。 writer函数签名如下所示: 提前感谢! 编辑:在我的视频流中,没有B帧。所以,我认为这里PTS和DTS可以保持不变。

  • 问题内容: 之前,我问过有关使用FFT和Complex class获取频率wav音频的 问题, 在那里,我需要从AudioRecord输入->从麦克风计算FFT值,以某种方式设法获得FFT值… 现在,我需要从之前保存的* .wav音频文件中计算FFT值,然后将音频保存到项目中“ res”文件夹中的“ raw”文件夹中 我仍然使用相同的FFT类:http : //www.cs.princeton.e