混合波形文件

时间:2017-06-09 13:02:00

标签: java android audio wave

我无法混合两个音频扩展文件wav。我的工作:

byte[] bufData1 = null;
byte[] bufData2 = null;
ArrayList<Byte> bufData3 = new ArrayList<Byte>();

使用原始音频数据创建两个数组

 public void bootloadInputData(String p1, String p2) throws IOException {
        bufData1 = bootloadReadFileByte(p1);
        bufData2 = bootloadReadFileByte(p2);
        System.arraycopy(bufData1, 44, bufData1, 0, (bufData1.length - 44));
        System.arraycopy(bufData2, 44, bufData2, 0, (bufData2.length - 44));
 }

 public byte[] bootloadReadFileByte(String path) throws IOException{
    ByteArrayOutputStream out = null;
    InputStream input = null;
    try{
        out = new ByteArrayOutputStream();
        input = new BufferedInputStream(new FileInputStream(path));
        int data = 0;
        while((data = input.read()) != -1){
            out.write(data);
        }
    }
    finally{
        if(null != input){
            input.close();
        }
        if(null != out){
            out.close();
        }
    }
    return out.toByteArray();
}

混合原始音频数据的字节

public void bootloadOutputData() throws IOException {
        for(int i = 0; i < ((bufData1.length + bufData2.length) / 4); i += 4) {
            if(i < bufData1.length){
                bufData3.add(bufData1[i]);
                bufData3.add(bufData1[i+1]);
                bufData3.add(bufData1[i+2]);
                bufData3.add(bufData1[i+3]);
            }
            if(i < bufData2.length){
                bufData3.add(bufData2[i]);
                bufData3.add(bufData2[i+1]);
                bufData3.add(bufData2[i+2]);
                bufData3.add(bufData2[i+3]);
            }
        }
    }

创建新文件,填写标题和原始音频数据。

private void bootloadCreateWaveMix(String p1, String p2, String p3) throws IOException {
    int size1 = 0;
    int size2 = 0;

    FileInputStream fis1 = null;
    FileInputStream fis2 = null;
    try {
        fis1 = new FileInputStream(p1);
        fis2 = new FileInputStream(p2);
        size1 = fis1.available();
        size2 = fis2.available();
    } finally {
        if(fis1 != null){
            fis1.close();
        }
        if(fis2 != null){
            fis2.close();
        }
    }

    int mNumBytes = (size1 + size2);

    DataOutputStream out = null;
    try {
        out = new DataOutputStream(new FileOutputStream(p3));
        writeId(out, "RIFF");
        writeInt(out, 36 + mNumBytes);
        writeId(out, "WAVE");

        writeId(out, "fmt ");
        writeInt(out, 16);
        writeShort(out, (short) 1);
        writeShort(out, (short) 4);
        writeInt(out, (int) 44100);
        writeInt(out, 2 * 44100 * 16 / 8);
        writeShort(out, (short)(2 * 16 / 8));
        writeShort(out, (short) 16);

        writeId(out, "data");
        writeInt(out, mNumBytes);

        out.write(toByteArray(bufData3));
    } finally {
        if(out != null){
            out.close();
        }
    }
}

private static void writeId(OutputStream out, String id) throws IOException {
    for (int i = 0; i < id.length(); i++) out.write(id.charAt(i));
}

private static void writeInt(OutputStream out, int val) throws IOException {
    out.write(val >> 0);
    out.write(val >> 8);
    out.write(val >> 16);
    out.write(val >> 24);
}

private static void writeShort(OutputStream out, short val) throws IOException {
    out.write(val >> 0);
    out.write(val >> 8);
}

public static byte[] toByteArray(ArrayList<Byte> in) {
    byte[] data = new byte[in.size()];
    for (int i = 0; i < data.length; i++) {
        data[i] = (byte) in.get(i);
    }
    return data;
}

问题:

  

此代码无法正确创建计算机无法创建的文件   玩,但设备可以。繁殖是坏的,有某种   合并文件末尾的干扰。此外,播放结束时   即使第二个文件大于第一个文件,第一个文件也会结束   一。这个想法的渠道的另一个问题是两个立体声   文件,并在标题中我指出4生活,即使2.文件   永远是44100/16位/立体声

1 个答案:

答案 0 :(得分:0)

如果我理解正确,您需要执行以下操作:

  1. 给定2个输入WAV文件,将它们混合到一个WAV文件中。
  2. 输出的内容将是同时播放的输入文件,而不是一个接一个。
  3. 新文件的长度将是输入文件中最长的文件的长度。
  4. 所有文件,输入和输出均为16位,立体声44100Hz。
  5. 如果是这种情况,这里有(部分)你的错误:

    1. 您需要解析传入的文件,以便不将其标题作为音频数据读取(请勿跳过此步骤,因为您已经知道音频的格式。您需要阅读标题以确认数据格式并准确地确定输入中的样本数量。另请注意,2/16/44100 WAV文件可以具有不同大小的标题,因为它们可以包含各种块,因此您不能只跳过X个字节然后读取文件 - - 你必须解析标题!)。
    2. 如果WAV文件都是16位,则需要将传入数据从字节转换为短路(注意,这不是简单的类型转换 - 您必须在每个短路中包含2个字节。我相信您可以使用DataInputStream为此,但一定要考虑到endianness - WAV文件是little-endian而Java是big-endian)。一旦你得到代表你的样品的短裤,就可以从单独的文件中取出短裤以进行混合。然后必须将平均值转换回字节(DataOutputStream)以保存生成的文件。当您从一个文件中用完数据时,请替换为零。
    3. 您对numBytes的计算不正确 - 它不是两个文件中原始字节的总和,而是一个稍微复杂的计算。在你的情况下,你希望它等于这样的东西:
    4.  n1 = number of samples in file 1
       n2 = number of samples in file 2
       n = MAX( n1 + n2 )
       numBytes = n * (number of channels) * (number of bytes per channel) = n * 2 * 2
      

      我强烈建议您考虑使用像JMF这样的库来解决1&amp; 2。