在 Python 中读取波形文件
Posted
技术标签:
【中文标题】在 Python 中读取波形文件【英文标题】:Reading a wave file in Python 【发布时间】:2014-09-23 19:02:35 【问题描述】:我创建了一个莫尔斯电码生成器,可以将英语句子转换成莫尔斯电码。它还将这个基于文本的莫尔斯电码转换为音频文件。如果字符是dot
,我将一个dot.wave
文件附加到输出波形文件,如果下一个字符是dash
,则附加一个dash.wav
文件。
我现在想打开这个波形文件并阅读它的内容,以确定这些破折号和圆点的放置顺序。
我已经尝试了以下代码:
waveFile = wave.open(r"C:\Users\Gaurav Keswani\Documents\Eclipse\Morse Code Converter\src\resources\sound\morse.wav", 'r')
x =waveFile.readframes(20)
print (struct.unpack("<40H", x))
这给了我输出:
(65089, 65089, 3093, 3093, 11895, 11895, 18629, 18629, 25196, 25196, 29325、29325、31986、31986、32767、32767、31265、31265、27532、27532、 22485、22485、15762、15762、7895、7895、103、103、57228、57228、49571、 49571、42790、42790、37667、37667、34362、34362、32776、32776)
我不知道如何处理这个输出。有人可以帮忙吗?
【问题讨论】:
想象一下,你会看到一个波浪。声音是波浪。您可能想查看波的幅度在哪里发生变化,并记录每次幅度显着变化之间经过的时间,并以此为基础。 嘿!谢谢回复。谈到这件事,我真的是个新手。能详细解释一下吗? @GauravKeswani:如果你不明白这个概念,不要只是想象绘制它,而是实际绘制它。如果你不知道如何使用matplotlib
之类的东西,只需将帧导出到一个巨大的单列 CSV 文件,在 Excel/LibreOffice/Numbers/whatever 中打开它,然后绘制图表。然后您可以直观地看到点、破折号和空格的样子,并开始思考一种算法来区分它们。
***.com/questions/18625085/how-to-plot-a-wav-file
实际上,在您的情况下,如果您只想检测 dot.wav
和 dash.wav
的精确副本,并且您没有使用任何有损压缩,那么算法应该更简单:只需将这两个文件解码并读入数字列表,然后它只是一个简单的子字符串搜索(除了你的“字符串”是 16 位数字的数组,而不是字符)。
【参考方案1】:
如果您想要检测摩尔斯电码的通用解决方案,您将不得不看看它的波形是什么样子(如果您可以安装 numpy
和 @ 987654323@;如果没有,您可以使用 stdlib 的csv
模块导出文件,您可以在自己喜欢的电子表格程序中使用);弄清楚你作为人类如何区分点、破折号和空格;把它变成一个算法(即使是一个字面意思的白痴也可以遵循的一系列步骤);然后将该算法转换为代码。或者您可以找到已经为您完成此操作的库。
但对于您的具体情况,您只需要在较大的文件中检测 dot.wav
和 dash.wav
内容的精确副本。 (至少假设您没有使用任何有损压缩,通常您不在 .wav 文件中。)所以,这实际上只是一个子字符串搜索。
考虑一下如何在'dash dash dash dash dash dot dash dot dot dot dot dot '
之类的字符串中检测字符串'dot'
和'dash'
。对于这样一个简单的问题,你可以使用一个愚蠢的蛮力算法,就可以了:
def find(haystack, needle, start):
for i in range(start, len(haystack)):
if haystack[i:i+len(needle)] == needle:
return i
return len(haystack)
def decode_morse(morse):
i = 0
while i < len(morse):
next_dot = find(morse, 'dot', i)
next_dash = find(morse, 'dash', i)
if next_dot < next_dash:
if next_dot < len(morse):
yield '.'
i = next_dot
else:
if next_dash < len(morse):
yield '-'
i = next_dash
现在,如果您搜索的是数字列表而不是字符串,那么这必须如何改变?几乎没有;您可以像使用字符串一样对列表进行切片、比较两个列表等。
您会遇到的唯一真正问题是您不会一次将整个列表保存在内存中,一次只有 20 帧。如果dot
从第 19 帧开始并在第 20 帧结束,会发生什么?如果您的文件不是太大,这很容易解决:只需将所有帧读入一个巨大列表中的内存,然后搜索整个内容。但除此之外,你必须做一些缓冲。
例如(忽略错误处理并正确处理文件末尾,为简单起见只处理破折号——当然,您必须在实际代码中正确执行这两项操作):
buf = []
while True:
while len(buf) < 2*len(dash):
buf.extend(waveFile.readFrames(20))
next_dash = find(buf, dot)
if next_dash < len(buf):
yield '.'
buf = buf[next_dash:]
else:
buf = buf[-len(dash):]
我们确保缓冲区中始终至少有两个破折号长度。我们总是在缓冲区中的第一个点或破折号(如果找到的话)或完整的破折号长度(如果没有)之后保留剩余部分,并将下一个缓冲区添加到其中。这实际上是矫枉过正。仔细考虑并仔细考虑您需要确保我们不会错过两个缓冲区之间的破折号。但关键是,只要你做对了,你就不能错过任何点或破折号。
【讨论】:
以上是关于在 Python 中读取波形文件的主要内容,如果未能解决你的问题,请参考以下文章