在wav文件中的每个单词之间,我完全沉默(我使用Hex工作室检查,静音用0表示)。
如何切断非静音?
我正在使用python进行编程。
谢谢!
答案 0 :(得分:15)
Python有一个wav module。您可以使用它打开一个wav文件进行读取,并使用`getframes(1)'命令逐帧遍历文件。
import wave
w = wave.open('beeps.wav', 'r')
for i in range():
frame = w.readframes(1)
返回的帧将是一个字符串,其中包含十六进制值。如果文件是立体声,结果将看起来像这样(4个字节):
'\xe2\xff\xe2\xff'
如果是单声道,它将有一半数据(2个字节):
'\xe2\xff'
每个通道长2个字节,因为音频是16位。如果是8位,则每个通道只有一个字节。您可以使用getsampwidth()
方法来确定这一点。此外,getchannels()
将确定其单声道还是立体声。
您可以遍历这些字节以查看它们是否都等于零,这意味着两个通道都是静默的。在以下示例中,我使用ord()
函数将'\xe2'
十六进制值转换为整数。
import wave
w = wave.open('beeps.wav', 'r')
for i in range(w.getnframes()):
### read 1 frame and the position will updated ###
frame = w.readframes(1)
all_zero = True
for j in range(len(frame)):
# check if amplitude is greater than 0
if ord(frame[j]) > 0:
all_zero = False
break
if all_zero:
# perform your cut here
print 'silence found at frame %s' % w.tell()
print 'silence found at second %s' % (w.tell()/w..getframerate())
值得注意的是,单帧静音不一定表示空的空间,因为幅度可能越过0标记正常频率。因此,建议在确定该区域实际上是否为静音之前,在0处观察到一定数量的帧。
答案 1 :(得分:5)
我一直在为我正在进行的项目做一些关于这个主题的研究,我遇到了提供解决方案的一些问题,即确定沉默的方法是不正确的。 A"更正确"实施将是:
import struct
import wave
wave_file = wave.open("sound_file.wav", "r")
for i in range(wave_file.getnframes()):
# read a single frame and advance to next frame
current_frame = wave_file.readframes(1)
# check for silence
silent = True
# wave frame samples are stored in little endian**
# this example works for a single channel 16-bit per sample encoding
unpacked_signed_value = struct.unpack("<h", current_frame) # *
if abs(unpacked_signed_value[0]) > 500:
silent = False
if silent:
print "Frame %s is silent." % wave_file.tell()
else
print "Frame %s is not silent." % wave_file.tell()
* Struct Unpacking
在这里很有用:https://docs.python.org/2/library/struct.html
**我发现一个很好的参考资料,解释了处理不同大小的位编码和多个通道的波形文件的格式:http://www.piclist.com/techref/io/serial/midi/wave.html
在readframes(x)方法返回的字符串对象的第一个元素上使用Python中的内置ord()函数将无法正常工作。
另一个关键点是多通道音频是交错的,因此处理通道需要一些额外的逻辑。同样,上面的链接详细说明了这一点。
希望这有助于将来。
以下是该链接中的一些更重要的观点,以及我发现的有用的内容。
数据组织
所有数据都以8位字节存储,以Intel 80x86(即小端)格式排列。多字节值的字节首先与低位(即最低有效)字节一起存储。数据位如下(即,顶部显示位数):
7 6 5 4 3 2 1 0
+-----------------------+
char: | lsb msb |
+-----------------------+
7 6 5 4 3 2 1 0 15 14 13 12 11 10 9 8
+-----------------------+-----------------------+
short: | lsb byte 0 | byte 1 msb |
+-----------------------+-----------------------+
7 6 5 4 3 2 1 0 15 14 13 12 11 10 9 8 23 22 21 20 19 18 17 16 31 30 29 28 27 26 25 24
+-----------------------+-----------------------+-----------------------+-----------------------+
long: | lsb byte 0 | byte 1 | byte 2 | byte 3 msb |
+-----------------------+-----------------------+-----------------------+-----------------------+
<强>交织强>
对于多声道声音(例如,立体声波形),来自每个声道的单个采样点是交错的。例如,假设立体声(即2声道)波形。不是首先存储左通道的所有采样点,然后存储下一个右通道的所有采样点,而是&#34;混合&#34;两个频道&#39;样本点在一起。您将存储左通道的第一个采样点。接下来,您将存储右通道的第一个采样点。接下来,您将存储左通道的第二个采样点。接下来,您将存储右通道的第二个采样点,依此类推,在存储每个通道的下一个采样点之间交替。这就是交错数据的含义;你依次存储每个通道的下一个采样点,这样就可以了解&#34;播放&#34; (即,发送到DAC)同时连续存储。
答案 2 :(得分:2)
答案 3 :(得分:1)
我对此没有经验,但请查看标准库中的wave模块。这可能会做你想要的。否则你将不得不将文件作为字节流读取一个0字节的剪切序列(但你不能只删除所有0字节,因为这会使文件无效......)
答案 4 :(得分:1)
您可能想尝试使用命令行声音处理工具sox。它有许多模式,其中之一是silence
:
沉默:从声音文件的开头,中间或结尾删除静音。沉默低于指定的阈值。
它支持多种声音格式并且速度非常快,因此解析大文件应该不是问题。
要从文件中间删除静音,请指定为负数的
below_periods
。然后将此值视为正值,并且还用于指示效果应重新开始above_periods
指定的处理,使其适合删除声音文件中间的静音期。
我没有为libsox找到任何python构建,但你可以使用它,因为你在python中使用所有命令行程序(或者你可以重写它 - 然后使用sox源作为指导)。
答案 5 :(得分:1)
在剪切之前,您需要提供最小连续零数的阈值。否则,您将从正常音频数据的中间删除完全有效的零。您可以遍历wave文件,复制任何非零值,并缓冲零值。当你缓冲零并最终遇到下一个非零时,如果缓冲区的样本数量少于阈值,则复制它们,否则丢弃它。
但Python并不是这类任务的好工具。 :(