2

我创建了一个莫尔斯电码生成器,可以将英语句子转换成莫尔斯电码。它还将这个基于文本的莫尔斯电码转换为音频文件。如果字符是 a ,我会在输出波形文件中dot附加一个文件,如果下一个字符是 a ,我会添加一个文件。dot.wavedash.wavdash

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

我尝试了以下代码:

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)

我不知道如何处理这个输出。任何人都可以帮忙吗?

4

1 回答 1

0

如果你想要一个检测摩尔斯电码的通用解决方案,你将不得不看看它的波形是什么样子(如果你可以安装numpymatplotlibstdlib 的csv模块,用于导出可以在您喜欢的电子表格程序中使用的文件);弄清楚你作为人类如何区分点、破折号和空格;把它变成一个算法(即使是一个字面意思的白痴也可以遵循的一系列步骤);然后将该算法转换为代码。或者您可以找到已经为您完成此操作的库。

dot.wav但是对于您的具体情况,您只需要检测dash.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 帧。如果 adot从第 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):]

我们确保缓冲区中始终至少有两个破折号长度。我们总是在缓冲区中的第一个点或破折号(如果找到)或完整的破折号长度(如果没有)之后保留剩余部分,并将下一个缓冲区添加到其中。这实际上是矫枉过正。仔细考虑并仔细考虑您需要确保我们不会错过两个缓冲区之间的破折号。但关键是,只要你做对了,你就不能错过任何点或破折号。

于 2014-09-23T19:25:11.257 回答