在Python中读取wav文件

时间:2014-09-23 19:02:35

标签: python wav wave morse-code

我创建了一个莫尔斯代码生成器,可将英语句子转换为莫尔斯代码。它还将基于文本的莫尔斯代码转换为音频文件。如果字符是dot,我会将dot.wave文件附加到输出wave文件,如果下一个字符是dash.wav,则会附加dash文件。

我现在想打开这个wave文件并阅读其内容,以确定这些破折号和点的放置顺序。

我尝试过以下代码:

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)

我不知道该输出的内容。有人可以帮忙吗?

1 个答案:

答案 0 :(得分:0)

如果你想要一个通用的解决方案来检测摩尔斯电码,你将不得不看看它看起来像波形(tom10&this question的链接应该有帮助,如果你能安装numpymatplotlib;如果没有,您可以使用stdlib的csv模块导出您可以在您喜欢的电子表格程序中使用的文件);弄清楚你作为一个人如何区分点,破折号和空格;把它变成一个算法(即使是文字头脑的白痴也可以遵循的一系列步骤);然后将该算法转换为代码。或者您可以找到一个已经为您完成此操作的图书馆。

但是对于您的具体情况,您只需要检测较大文件中dot.wavdash.wav内容的确切副本。 (至少假设你没有使用任何有损压缩,通常你不在.wav文件中。)所以,这实际上只是一个子串搜索。

考虑如何在'dot'之类的字符串中检测字符串'dash''dash dash dash dash dash dot dash dot dot dot dot dot '。对于这样一个简单的问题,你可以使用一个愚蠢的暴力算法,它会很好:

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):]

我们确保在缓冲区中始终至少有两个短划线长度。并且我们总是在缓冲区中的第一个点或短划线(如果找到一个)或完整的短划线长度(如果没有)之后保留剩余部分,并将下一个缓冲区添加到该缓冲区。这实际上是矫枉过正;仔细思考并仔细思考你需要什么,以确保我们永远不会错过两个缓冲区之间的破折号。但问题是,只要你做对了,你就不会错过任何点或破折号。