【问题标题】:Change an audio stream's volume by changing bytes directly通过直接更改字节来更改音频流的音量
【发布时间】:2018-07-12 15:36:56
【问题描述】:

对于点对点音频客户端,我需要能够将输出音量更改为所需的水平。在我的例子中,音量是一个介于 0 和 1 之间的浮点数。

我这样修改音频流:

void play(byte[] buf)
{
    for (int i = 0; i < buf.length; i += 2)
    {
        // sample size is 2 bytes, so convert to int and then back
        int data = ((buf[i + 1] & 0xFF) << 8) | (buf[i] & 0xFF);
        data = (int) (data * outputVolume);
        buf[i] = (byte) (data & 0xFF);
        buf[i + 1] = (byte) (data >> 8);
    }
    line.write(buf, 0, Math.min(buf.length, line.available()));
}

现在,当 outputVolume 设置为 0 时,输出是静默的。当它设置为 1 时,它表现正常并且质量很好(因为它没有被修改)。但是 0 到 1 之间的任何数字都会产生比预期流本身更大的可怕噪音。在 0.5 时,噪音达到最大声点。

我不想使用混音器本身的控件(如增益控制或音量控制),因为我在这种方式中遇到了兼容性问题,后来,我想进一步修改字节流,所以我必须迭代无论如何都要通过流。

【问题讨论】:

  • outputVolume 的类型是什么?线的类型是什么?
  • @xtractic 我尝试了很多方法来移位数据,我的问题似乎是另一个
  • @AlexandreFenyo outputVolume 是float。我的线路是SourceDataLine,采样率为 16kHz,小端序和每个采样 16 位
  • 能否给出byte[] buf = { 10, 11 }; play(buf); System.out.println(buf[0] + " ; " + buf[1]);的显示输出

标签: java audio


【解决方案1】:

假设音频数据是有符号的(因为我认为有无符号的 16 位样本是很不寻常的),那么代码中有一个错误,因为您还需要对样本进行签名。

您可以从高字节中删除&amp; 0xFF,这将使符号扩展自动发生:

int data = (buf[i + 1] << 8) | (buf[i] & 0xFF);

如果由于某种原因您无法修改 and-shift-or 表达式,您可以像这样进行符号扩展:

int data = ((buf[i + 1] & 0xFF) << 8) | (buf[i] & 0xFF);
data = (data << 16) >> 16;

移位表达式的结果等价于:

if (data > 32767)
    data -= 65536;

还有这个:

if ((i & 0x80_00) != 0)
    i |= 0xFF_FF_00_00;

(这些也可以。)

但是,在您的情况下,您可以从高字节中删除 &amp; 0xFF


为了快速解释,如果你有一些像这样的 16 位样本(即 -1):

11111111_11111111

如果您只是转换为 32 位而不进行符号扩展,您会得到:

00000000_00000000_11111111_11111111

但那是 65536,而不是 -1。如果设置了 16 位值中的 MSB,则符号扩展用 1 填充高位:

11111111_11111111_11111111_11111111

【讨论】:

  • 这对我有用,谢谢!只需删除 AND 运算符就是我需要做的一切。
  • 现在,我还有一个问题。我对输入音量做了同样的事情,但是当降低它时,声音会被切断,就像它不再是一个连续的音频流一样。我猜在 5-10Hz 左右的频率。你有什么想法吗?
  • 16kHz的采样率只能存储8kHz以内的频率,所以在那里被截断是正常的。如果还有其他问题,我必须查看更多代码(最好是minimal reproducible example,如帮助中心所述)。我在您发布的代码中没有发现任何其他问题。
  • 抱歉 - 我犯了一个可怕的错误,跳过了流中的 8 位,这些位之前已为特殊目的保留。
  • 啊,好的。我本来打算建议制作一个 MCVE 并发布一个新问题,但我很高兴你当时就想通了。
猜你喜欢
  • 2014-06-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-16
  • 1970-01-01
  • 2022-11-22
相关资源
最近更新 更多