音频:更改字节数组中的样本量

2022-09-03 13:04:30

我正在使用此方法将wav文件读取到字节数组(如下所示)。现在我已将其存储在字节数组中,我想更改音量。

private byte[] getAudioFileData(final String filePath) {
    byte[] data = null;
    try {
    final ByteArrayOutputStream baout = new ByteArrayOutputStream();
    final File file = new File(filePath);
    final AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(file);

    byte[] buffer = new byte[4096];
    int c;
    while ((c = audioInputStream.read(buffer, 0, buffer.length)) != -1) {
        baout.write(buffer, 0, c);
    }
    audioInputStream.close();
    baout.close();
    data = baout.toByteArray();
    } catch (Exception e) {
    e.printStackTrace();
    }
    return data;
}

编辑:根据请求,有关音频格式的一些信息:

PCM_SIGNED 44100.0 Hz,16 位,单声道,2 字节/帧,小端序

从物理课上,我记得你可以通过将正弦值乘以0到1之间的数字来改变正弦波的振幅。

编辑:更新了 16 位示例的代码:

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

    }
    return array;
}

如果我乘以 .如果我不这样做,并将两个数组与之进行比较,我可以得出结论,字节数组被正确地转换为int,反之亦然。audioSamplevolumeArrays.compare(array, audioSample)

任何人都可以帮我吗?我在这里犯了什么错误?谢谢!:)


答案 1

int 类型中存在问题,java 中 int 的大小为 4 个字节,样本大小为 2 个字节

这个工作代码:

private byte[] adjustVolume(byte[] audioSamples, float volume) {
        byte[] array = new byte[audioSamples.length];
        for (int i = 0; i < array.length; i+=2) {
            // convert byte pair to int
            short buf1 = audioSamples[i+1];
            short buf2 = audioSamples[i];

            buf1 = (short) ((buf1 & 0xff) << 8);
            buf2 = (short) (buf2 & 0xff);

            short res= (short) (buf1 | buf2);
            res = (short) (res * volume);

            // convert back
            array[i] = (byte) res;
            array[i+1] = (byte) (res >> 8);

        }
        return array;
}

答案 2

您确定您正在阅读 8 位单声道音频吗?否则,一个字节不等于一个样本,并且不能只缩放每个字节。例如,如果它是16位数据,则必须将每对字节解析为16位整数,对其进行缩放,然后将其写回为两个字节。


推荐