java 如何将两个 wav 文件合并/合并为一个 wav 文件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2578862/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 21:52:34  来源:igfitidea点击:

How do I combine/merge two wav files into one wav file?

javaaudio

提问by Alex Kapustian

How can I merge two wav files using java?

如何使用java合并两个wav文件?

I tried thisbut it didn't work correctly, is their any other way to do it?

我试过这个,但它不能正常工作,他们还有其他方法吗?

回答by Thamster

If you work with the bytes of a wav file directly you can use the same strategy in any programming language. For this example I'll assume the two source files have the same bitrate/numchannels and are the same length/size. (if not you can probably edit them before starting the merge).

如果您直接处理 wav 文件的字节,则可以在任何编程语言中使用相同的策略。对于本示例,我将假设两个源文件具有相同的比特率/通道数和相同的长度/大小。(如果没有,您可以在开始合并之前编辑它们)。

First look over the wav specificaiton, I found a good one at a stanfordcourse website:

首先查看 wav 规范,我在斯坦福课程网站上找到了一个很好的:

Common header lengths are 44 or 46 bytes.

常见的报头长度为 44 或 46 字节。

If you want to concatenate two files (ie play one wav then the other in a single file):

如果您想连接两个文件(即在单个文件中播放一个 wav,然后播放另一个):

  1. find out what format your wav files are
  2. chop off the first 44/46 bytes which are the headers, the remainder of the file is the data
  3. create a new file and stick one of the headers in that.

    new wav file = {header} = {44/46} bytes long

  4. add the two data parts from the original files

    new wav file = {header + data1 + data2 } = {44/46 + size(data1) + size(data2)} bytes long

  5. modify your header in two places to reflect the new file's length.

    a. modify bytes 4+4 (ie. 4 bytes starting at offset 4). The new value should be a hexadecimal number representing the size of the new wav file in bytes {44/46 + size(data1) + size(data2)} - 8bytes.

    b. modify bytes 40+4 or 42+4 (the 4 bytes starting at offset 40 or 42, depending on if you have a 44byte header or 46 byte header). The new value should be a hexadecimal number representing the total size of the new wav file. ie {44/46 + size(data1) + size(data2)}

  1. 找出你的 wav 文件是什么格式
  2. 砍掉前 44/46 个字节是头,文件的其余部分是数据
  3. 创建一个新文件并在其中粘贴一个标题。

    新 wav 文件 = {header} = {44/46} 字节长

  4. 添加原始文件中的两个数据部分

    新的 wav 文件 = {header + data1 + data2 } = {44/46 + size(data1) + size(data2)} 字节长

  5. 在两个地方修改您的标题以反映新文件的长度。

    一个。修改字节 4+4(即从偏移量 4 开始的 4 个字节)。新值应该是一个十六进制数,以字节 {44/46 + size(data1) + size(data2)} - 8bytes 表示新 wav 文件的大小。

    湾 修改字节 40+4 或 42+4(从偏移量 40 或 42 开始的 4 个字节,取决于您有 44 字节的标头还是 46 字节的标头)。新值应该是一个十六进制数,表示新 wav 文件的总大小。即 {44/46 + 大小(数据 1)+ 大小(数据 2)}

If you want to instead merge or mix the two files (so that they both play at the same time then):

如果您想合并或混合这两个文件(以便它们同时播放):

  1. you won't have to edit the header if both files are the same length.
  2. starting at byte 44/46 you will have to edit each sample to be the value in data1 + the value in data2. so for example if your SampleRate was 8 bits you would modify 1 byte, if your sample rate was 16bits you would modify 2 bytes. the rest of the file is just Samples of 1/2bytes storing an int value representing the waveform of the sound at that time.

    a. For each of the remaining samples in the file grab the 1/2 byte hex string and get the int value from both files data1 and data2.

    b. add the 1/2 byte integers together convert the result back to hexadecimal and use that value in your output file.

    c. You normally have to divide that number by 2 to get an average value that fits back in the original 1/2byte sample block. I was getting distortion when i tried it in objc(probably related to signed or unsigned ints) and just skipped the division part since it will only likely be a problem if you are merging very loud sounds together. ie when data1 + data2 is larger than 1/2 bytes the sound will clip. There was a discussion about the clipping issue hereand you may want to try one of those clipping techniques.

  1. 如果两个文件的长度相同,则不必编辑标题。
  2. 从字节 44/46 开始,您必须将每个样本编辑为 data1 中的值 + data2 中的值。例如,如果您的 SampleRate 是 8 位,您将修改 1 个字节,如果您的采样率为 16 位,您将修改 2 个字节。文件的其余部分只是 1/2 字节的样本,存储了一个代表当时声音波形的 int 值。

    一个。对于文件中剩余的每个样本,获取 1/2 字节的十六进制字符串并从文件 data1 和 data2 中获取 int 值。

    湾 将 1/2 字节整数相加,将结果转换回十六进制并在输出文件中使用该值。

    C。您通常必须将该数字除以 2 以获得适合原始 1/2 字节样本块的平均值。当我在 objc 中尝试它时(可能与有符号或无符号整数有关),我遇到了失真,只是跳过了除法部分,因为如果您将非常响亮的声音合并在一起,它可能只是一个问题。即当 data1 + data2 大于 1/2 字节时,声音将被剪辑。此处讨论了剪裁问题,您可能想尝试其中一种剪裁技术。

回答by Justin Smith

Merge implies mixing, but it sounds like you mean concatenation here.

合并意味着混合,但听起来您在这里的意思是连接。

To concatenate with silence in the middle you need to insert a number of frames of silence into the file. A silent frame is one where every channel has a "0" - if you are using signed samples this is literally a 0, for unsigned, it is maxvalue/2.

要在中间连接静音,您需要在文件中插入一些静音帧。无声帧是每个通道都有一个“0”的帧 - 如果您使用有符号样本,这实际上是一个 0,对于无符号,它是 maxvalue/2。

Each frame will have one sample for each channel. So to generate one second of silence in CD format, you would insert 44100 (hz) * 2 (channels per frame) = 88200 16 bit signed ints with a value of 0 each. I am not sure how to access the raw file abstracted by the Java audio abstractions, but that is the data to insert.

对于每个通道,每一帧都有一个样本。因此,要以 CD 格式生成一秒钟的静音,您需要插入 44100 (hz) * 2(每帧通道数)= 88200 个 16 位有符号整数,每个整数的值为 0。我不确定如何访问由 Java 音频抽象抽象的原始文件,但这是要插入的数据。