[英]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.