Java:将4个独立的音频字节数组组合成单个wav音频文件
我曾尝试将4个单独的字节数组合并到一个文件中,但我只得到空指针异常,我不知道为什么。我的音频格式是16位PCM签名的,我知道我应该使用short而不是bytes,但老实说,我完全迷路了
private short[] mixByteBuffers(byte[] bufferA, byte[] bufferB) {
short[] first_array = new short[bufferA.length/2];
short[] second_array = new short [bufferB.length/2];
short[] final_array = null;
if(first_array.length > second_array.length) {
short[] temp_array = new short[bufferA.length];
for (int i = 0; i < temp_array.length; i++) {
int mixed=(int)first_array[i] + (int)second_array[i];
if (mixed>32767) mixed=32767;
if (mixed<-32768) mixed=-32768;
temp_array[i] = (short)mixed;
final_array = temp_array;
}
}
else {
short[] temp_array = new short[bufferB.length];
for (int i = 0; i < temp_array.length; i++) {
int mixed=(int)first_array[i] + (int)second_array[i];
if (mixed>32767) mixed=32767;
if (mixed<-32768) mixed=-32768;
temp_array[i] = (short)mixed;
final_array = temp_array;
}
}
return final_array;
}
这就是我目前正在尝试的,但它在第行返回java.lang.ArrayIndexOutOfBoundsException: 0
int mixed = (int)first_array[i] + (int)second_array[i];
我的数组不都是相同的长度,这就是我调用函数的方式:
public void combineAudio() {
short[] combinationOne = mixByteBuffers(tempByteArray1, tempByteArray2);
short[] combinationTwo = mixByteBuffers(tempByteArray3, tempByteArray4);
short[] channelsCombinedAll = mixShortBuffers(combinationOne, combinationTwo);
byte[] bytesCombined = new byte[channelsCombinedAll.length * 2];
ByteBuffer.wrap(bytesCombined).order(ByteOrder.LITTLE_ENDIAN)
.asShortBuffer().put(channelsCombinedAll);
mixedByteArray = bytesCombined;
}
一定有比我现在所做的更好的方法,这让我发疯
# 1 楼答案
要将两个
byte
数组与16位声音样本混合,应首先将这些数组转换为int
数组,即基于样本的数组,然后添加它们(以混合),然后再转换回字节数组。从byte
数组转换为int
数组时,需要确保使用正确的endianness (byte order)这里有一些代码可以让您混合使用两个数组。最后有一些示例代码(使用正弦波)演示了该方法。请注意,这可能不是对其进行编码的理想方式,而是演示该概念的工作示例。使用流或线,如Phil recommends可能是更明智的总体方法
祝你好运
# 2 楼答案
else
子句for
循环中的temp_array.length
值为bufferB.length
。但是if
子句中的值是bufferA.length/2
。你忽略了在else
子句中除以2了吗不管怎样,通常只将音频数据(信号)处理为流。在每一行打开时,从每一行获取预定义缓冲区的字节值,足以从每一行获得相同数量的PCM值。如果一行在其他行之前用完,可以用0值填充该行
除非有足够的理由添加长度不等的数组,否则我认为最好避免这样做。相反,使用指针(如果您是从数组中绘制)或渐进式读取()方法(如果是从音频输入行)来获取每次循环迭代的固定数量的PCM值。否则,我认为你是在自找麻烦,不必要地使事情复杂化
我见过一些可行的解决方案,每次只从每个源处理一个PCM值,甚至更多,比如1000甚至半秒(如果是44100 fps,则为22050)。最主要的是在每次迭代中从每个源获得相同数量的PCM,如果一个源的数据用完,则用0填充