繁体   English   中英

从byte []实时调整音频音量?

[英]Adjusting audio volume in real time from byte[]?

我正在尝试编写一个简单的应用程序来播放声音,并且可以在播放过程中随时更改声音的音量。 我这样做是通过将声音的字节数组中的每对字节转换为一个int,然后将该int乘以音量的增加或减少,然后将它们写回为两个字节(即1个样本)。 但是,这会导致声音严重失真。 我是否有可能将位移错了? 我的声音格式是:

.wav 44100.0hz, 16bit, little-endian

目前,我通过AdjustVolume方法的字节数组代表了音频数据的十分之一秒。 即sampleRate / 10

我在这里缺少什么东西导致它失真并且无法正确缩放音量吗? 我把字节写回去了并且要塞错了吗?

private byte[] adjustVolume(byte[] audioSamples, double volume) {
        byte[] array = new byte[audioSamples.length];
        for (int i = 0; i < array.length; i += 2) {
            // convert byte pair to int
            int audioSample = (int) (((audioSamples[i + 1] & 0xff) << 8) | (audioSamples[i] & 0xff));


            audioSample = (int) (audioSample * volume);


            // convert back
            array[i] = (byte) audioSample;
            array[i + 1] = (byte) (audioSample >> 16);

        }
        return array;
    }

此代码基于以下内容: 音频:更改询问者尝试执行相同操作的字节数组的样本量 但是,使用了他的问题中的代码(我认为他得到答案后并没有更新),但我无法使其正常工作,而且我不确定它在做什么。

我建议您将字节数组包装在ByteBuffer (不要忘记将其.order()设置为little endian),读取short ,对其进行操作,然后再次写入。

样例代码:

// Necessary in order to convert negative shorts!
private static final int USHORT_MASK = (1 << 16) - 1;

final ByteBuffer buf = ByteBuffer.wrap(audioSamples)
    .order(ByteOrder.LITTLE_ENDIAN);
final ByteBuffer newBuf = ByteBuffer.allocate(audioSamples.length)
    .order(ByteOrder.LITTLE_ENDIAN);

int sample;

while (buf.hasRemaining()) {
    sample = (int) buf.getShort() & USHORT_MASK;
    sample *= volume;
    newBuf.putShort((short) (sample & USHORT_MASK));
}

return newBuf.array();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM