如何优化两个音频文件的合并?

1 投票
2 回答
758 浏览
提问于 2025-04-16 00:02

我写了一段代码,用来合并两个波形文件。当我合并较大的片段时,效果很好,但如果要合并非常小的片段,音质就不太好了。

我了解到,可以使用一种叫做“窗口连接”的信号处理技术来改善文件的合并效果。

公式是这样的:y[n] = w[n]s[n],也就是说,把样本编号为n的信号值乘以一个窗口函数的值。

这里的汉明窗口公式是:w[n] = 0.54 - 0.46*cos(2*Pi*n)/L,L是窗口的长度。

我不太明白如何获取样本n的信号值,以及该怎么实现这个?

the code i am using for joining is

import wave
m=['C:/begpython/S0001_0002.wav', 'C:/begpython/S0001_0001.wav']
i=1
a=m[i]
infiles = [a, "C:/begpython/S0001_0002.wav", a]
outfile = "C:/begpython/S0001_00367.wav"

data= []
data1=[]
for infile in infiles:
    w = wave.open(infile, 'rb')
    data1=[w.getnframes]
    data.append( [w.getparams(), w.readframes(w.getnframes())] )
    #data1 = [ord(character) for character in data1]

    #print data1
    #data1 = ''.join(chr(character) for character in data1)

    w.close()

output = wave.open(outfile, 'wb')
output.setparams(data[0][0])
output.writeframes(data[0][1])
output.writeframes(data[1][1])
output.writeframes(data[2][1])
output.close()

在合并时,我是用字节格式来处理帧的。现在我想用整数或浮点数格式来进行操作。如果我想的没错,我该怎么做呢?

2 个回答

0

简单来说,WAV音频格式包含一个44字节的头部,这里定义了一些必要的信息,比如采样率、声道数量等等。接下来就是实际的音频数据部分。音频其实就是一个随时间变化的振幅曲线。WAV格式允许这个振幅在+1.0到-1.0之间变化,这些值是以浮点数的形式表示的。当录制音频时,这个振幅通常每秒会被测量44100次(这就是采样率)。所以,WAV文件就是存储这一系列的采样值。需要注意的是,WAV格式并不直接存储浮点数,而是将+1到-1的范围存储为从0到2^16的整数。这些16位的样本每个需要两个字节的存储空间。在上面的示例代码中,i>>8表示将音频值向右移动8位。如果你理解了这些概念,并自己写代码来读取或写入WAV文件,你就能更好地解决你的问题了。

0

这可能不是最好的解决方案,但我相信它能奏效。也许你可以找到一些现成的库来帮助你完成某些步骤,我对Python的情况不太清楚。以下是我建议的步骤:

  1. 加载波形文件。
  2. 为每一帧创建样本值(幅度),这取决于帧大小、字节序(小端或大端)、有符号或无符号。
  3. 将得到的整数值数组分成多个窗口,比如样本0-511,512-1023,等等。
  4. 对你想要合并的窗口执行窗口函数。
  5. 进行合并操作。
  6. 将窗口的数据存回字节数组,这个过程是第一步的反向操作。

旧帖子:你需要计算样本值,在Java中,一个处理2字节/帧音频文件的函数可能是这样的:

public static int createIntFrom16( byte _8Bit1, byte _8Bit2 ) {
    return ( 8Bit1<<8 ) | ( 8Bit2 &0x00FF );
}

通常你需要注意文件是否使用小端格式,我不确定Python的库是否会考虑到这一点。

一旦你创建了所有的样本值,你就需要将文件分成窗口,比如每个窗口大小为512个样本。然后你可以对这些值进行窗口处理,并重新生成字节值。对于16位的情况,它可能看起来是这样的:

public static byte[] createBytesFromInt(int i) {
    byte[] bytes = new byte[2];
    bytes[0]=(byte)(i>>8);
    bytes[1]=(byte)i;
    return bytes;
}

撰写回答