利用python自动解析摩斯电码音频文件

问题来源

做CTF的MISC题的时候,遇到一个题,给了一个音频文件,下载下来在耳机中一听,显然是在右声道里边隐藏了一段摩斯电码。
在这里插入图片描述
以往都是手动一点一点记录下摩斯电码,然后丢进摩斯电码转换程序里得到加密信息,可是手动记录一不留神就有可能出错,有没有自动化方法呢?

自动化方法

1. 预处理音频

把音频文件的右声道音轨的摩斯电码部分提取出来,保存成一个新的音频文件。

2. 观察摩斯电码音频的实时频谱图

在这里插入图片描述
我们将音频数据分成许多小部分(这里以512字节为个一小部分),对于这一小部分的时序数据经过傅里叶变换变为频域数据,就得到了每一小部分所代表的几毫秒时间里该小部分音频的频谱图。

循环执行以上操作,并且将每次操作得到的频域数据绘制成频谱图,绘制到屏幕上,在加一点点延时,就清楚的可以看到整个音频的频谱图动画。
由于摩斯电码只有单纯不变音调的“嘀嘀嘀”声,我们可以观察到整个频谱动画中只有不变的几个频率的频谱条在随着“滴滴”声跳动。我们就可以选定其中一个频率,取其时间序列数据,进行进一步检测划分。

至于为什么不是只有一个频谱条,而是有好几个频谱条(上图中有2个),是因为音频文件中的“滴滴”声不是仅由某个单一频率正弦波构成的,一般还会会有几个泛音频率,这就涉及到声学的知识了,我了解的也不是很深,只要记住,一般频率最低的那个音最稳定,响度最大,这个频率叫做基频。

我们可以选取频率最低或者响度最大的那个频率,下面我们就以选取响度最大的那个频率的数据来处理为例。

3. 选取平均响度最大的那个频率

每次傅里叶变换都获得了这一小段时间内频域能量的一个向量,我们将获得的所有频域能量向量求平均值,得到一个频域平均能量向量,该向量能量最大的那个分量就是我们要找的频率,也就是可以让我们监控“滴滴”声的那个频率,我们只需要将所有频域能量向量中这个频率对应的向量分量的数据都取出来,按时间顺序排好,然后就可以进一步处理了。

4. 数据归一化、二值化

我们先刚刚得到的这个频率上的按照时间顺序排好的能量值序列进行归一化,使其取值都分布在[0, 1]之间,然后再以 0.1 为阈值进行二值化,高于阈值的变为1,低于阈值的变为0。
我们来看一下现在得到的数据。(取前100个数据)
在这里插入图片描述
再观察一下我们用音频软件看到的波形图
在这里插入图片描述
哈哈~完全一样,说明我们上边的工作是正确的。

5. 转换为摩斯电码

我们先利用“空白”进行分割,“空白"即我们上边归一化处理得到的时间序列中值为0的项,我们要检测,如果接下来一段时间里只出现了很少几个0,那么就是摩斯电码中的短停顿,如果有许多连续的0出现,那就是摩斯电码音频中的长停顿。长停顿是用来划分不同的字符的,每两个长停顿之间的一组点和线(即”短滴“声和”长滴“声)可以由摩斯对照表翻译成一个英文字符或者数字。

我们先根据长空白把我们得到的时间序列划分开,对于每一个划分开的时间子序列,再根据子序列中的”短空白“声把每个子序列”短滴“声和”长滴“声划分开来,对应成点和线输出,长空白对应成斜杠"/"输出,就得到了摩斯电码。

要划分“长空白”、“短空白”以及“长滴”、“短滴”,我们可以以所有空白时长的平均值、所有“滴声”的时长平均值来作为划分阈值,经实验,效果非常好。
在这里插入图片描述

6. 摩斯电码解码

让我们把工作做到底,我找来了摩斯电码对照表,将摩斯电码映射成了解密后的字符串,成功的得到了我的CTF题的flag字符串,并且通过了这道题。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

自动化工具给我节省了许多时间

本来需要一点一点手动记录的摩斯电码,手动记录完大概需要3分钟左右的时间,自从我用了自己写的自动化工具以后,什么!?写完这个工具已经大半天过去了……
哈哈~不过以后再遇到这种题就方便了许多。

  • 19
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
摩尔斯电码是一种通过短暂的电信号或灯光表达字母和数字的编码方式。在Python可以用简单的方式实现摩尔斯电码的转换。 首先,我们可以定义一个摩尔斯电码的字典,将每个字母和数字对应的摩尔斯电码表示存储在字典。然后,用户输入需要转换的字符串,我们可以将输入的字符串转换成大写并遍历每一个字符,根据字典的映射将每个字符转换成摩尔斯电码的形式。 接着,我们可以用点(.)表示短暂的信号,用横线(-)表示长时间的信号,用空格表示字母之间的间隔,用两个空格表示单词之间的间隔。然后,将转换好的摩尔斯电码打印输出或者以灯光的形式展现出来。 下面是一个简单的Python代码示例: ```python morse_code_dict = { 'A': '.-', 'B': '-...', 'C': '-.-.', 'D': '-..', 'E': '.', 'F': '..-.', 'G': '--.', 'H': '....', 'I': '..', 'J': '.---', 'K': '-.-', 'L': '.-..', 'M': '--', 'N': '-.', 'O': '---', 'P': '.--.', 'Q': '--.-', 'R': '.-.', 'S': '...', 'T': '-', 'U': '..-', 'V': '...-', 'W': '.--', 'X': '-..-', 'Y': '-.--', 'Z': '--..', '0': '-----', '1': '.----', '2': '..---', '3': '...--', '4': '....-', '5': '.....', '6': '-....', '7': '--...', '8': '---..', '9': '----.' } def to_morse_code(message): morse_code = "" for char in message.upper(): if char != " ": if char in morse_code_dict: morse_code += morse_code_dict[char] + " " else: morse_code += " " return morse_code input_message = input("请输入需要转换的消息: ") morse_code = to_morse_code(input_message) print(f"摩尔斯电码: {morse_code}") ``` 通过这段简单的Python代码,我们可以输入需要转换的消息,然后得到对应的摩尔斯电码结果。这样就实现了一个简单的Python写摩尔斯电码的功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值