好吧,我知道这很奇怪,但我想听到我的 Wi-Fi 卡发送和接收的原始数据作为声音数据。我只是觉得听到数据以声音形式发送很有趣。它对我来说唯一真正的目的是告诉我的 Wi-Fi 卡何时正在传输数据,并在我的网络中提供(某种程度上)确定性噪声源。非常沉默的办公室。
操作系统:Devuan Linux 5
内核:5.10.0-17
WiFi卡驱动开源:是
无线网卡:ID 0bda:c820 Realtek Semiconductor Corp. 802.11ac NIC
答案1
最直接的方法是这种方法的变体:
sudo tcpdump -w - -U | aplay -
它从以太网接口捕获数据包,然后将其输入默认音频设备。您可能想尝试各种过滤器tcpdump
或不同的采样率aplay
。
有时听起来确实很有趣。就我个人而言,我更喜欢沉默。
答案2
它对我来说唯一真正的目的是告诉我的 Wi-Fi 卡何时正在传输数据
所以就用那个吧。下面/sys/class/net/<interface name>/statistics/
有各种计数器,使用例如rx_bytes
和tx_bytes
。编写一个小程序,以固定间隔读取计数器,计算增量,并将增量转换为某种声音,例如由当前传输的字节量调制的噪声。您可以调节噪音的音量或其他参数。
答案3
它对我来说唯一真正的目的是告诉我的 Wi-Fi 卡何时正在传输数据,并在我非常安静的办公室中提供(某种程度上)确定性噪声源。
我在解释为什么你听不到“原始”数据的评论中有点过分了。
但你真正想要的是电话通信工程师所说的舒适噪音丰富了一些变化的数据。
所以,建造它!这是关于如何构建此类东西的一个小介绍。您可以直接跟随并复制粘贴,或者您可以尝试深入了解每一步 - 无论什么让您更兴奋:)
关于如何构建信号生成应用程序的小教程
舒适噪音和 GNU Radio Companion 第一步
让我们从舒适噪音部分开始。安装 GNU Radio 很容易(运行apt install gnuradio
)。然后打开 GNU Radio Companion。
您需要阅读有关的官方教程https://tutorials.gnuradio.org,但现在只需使用右侧的搜索栏即可找到两个块:
- 音频接收器
- 噪声源
将它们添加到画布中,并将它们连接起来。双击 Noise Source 模块,并将其输出类型更改为“float”。
结果应该是这样的:
以相同的方式更改 samp_rate 变量块,使其值为 48000。点击“执行”按钮。 (取决于您的桌面环境,但通常看起来像 ⏵;您也可以在“运行”菜单中找到它作为“执行”。)
恭喜,您的扬声器发出白噪音!您还可以通过设置噪声源的“振幅”来调整音量(尝试使用 0.1 而不是 1)。
塑造噪音并进行一些过滤
这很酷。让我们通过找到低通滤波器块、删除噪声源和音频接收器之间的直接连接并将滤波器放置在它们之间,让噪音变得不那么烦人。将滤波器设置为“Float -> Float (Decimating)”,并将其截止频率设置为3000,过渡宽度为1500。现在您已经将白噪声转换为更人性化的低通噪声,有色噪声。尝试一下!
我们如何将数据速率纳入我们的系统
现在,我们必须以某种方式将交通信息添加到整个系统中。
您可以通过定期询问 Linux 有多少字节已通过网络接口,并计算与上次询问的差异来做到这一点 - 这样,您就可以获得数据速率,只是一个数字。如果这个数字很高,我们希望我们的噪音更大,或者某些音调更高,或者......基本上,我们可以将其视为完成的电子音乐艺术家坐在他们的大型模块化合成器和旋钮(任何旋钮)前面对于我们来说,我们希望依赖于数据速率。
所以,有一个小问题:与音频接收器和噪声源不同,GNU Radio 尚未附带计算数据速率的块。这不是问题,我们可以自己构建。
但它是如何运作的呢?
小退一步。单击“执行”按钮时发生了什么? GNU Radio 的同伴走了过去,看了看流程图您已经构建并生成了一个 Python 程序。
该程序实例化您添加的所有块,配置它们,告诉 GNU Radio 运行时它们如何连接。然后,程序告诉运行时实际开始通过流程图传输数据,这意味着它告诉噪声源生成一些噪声样本,当这些样本准备就绪时,告诉过滤器过滤它们,就像这样完成后,告诉音频接收器将过滤后的样本交给声卡。 (事实上,与此同时,噪声源已经开始产生更多样本,一切都是并行运行的。)
因此,软件的所有小部分都生成、转换或最终处理连接“上游”块与其输入之间以及其输出与“下游”块之间交换的数字。
手头的开发任务
我们最终想要什么
因此,我们的工作是编写一个具有相同功能的小软件。我们只需将其插入过滤器之后即可。这就是我想象的样子:(这是一个模型!)
它是一个将输入复制到输出的块,并将其与从文件中读取的某个整数的变化率相乘。
因此,第一个参数是要读取的文件的名称,我"/sys/class/net/wlp0s20u11/statistics/tx_bytes"
在这里使用 - 替换wlp0s20u11
为您的 wifi 卡的设备名称(如果有疑问,请询问ip link
或nmcli device
)。
第二个参数是输入样本的数量,之后再次读取文件,以便我们获得连续更新。
构建它
所以,我编码了。你也可以做到的!找到“Embedded Python Block”块并将其添加到流程图中。双击它打开其属性,单击“在编辑器中打开”,然后复制并粘贴此代码(空格很重要!):
import numpy as np
from gnuradio import gr
class blk(gr.sync_block):
"""
Multiply by difference read from file
This block reads an integer from a text file, after every configurable
interval of input has been processed, calculates the per-sample rate at
which that integer changed since the last read, and multiplies the input
with that rate to calculate the output.
Parameters:
- filename The file to read periodically
- read_every_n_samples After how many samples to re-read to
calculate the per-sample rate
- max_increment_per_sample The maximum rate to which we normalize
our current rate. Set to 0 to not normalize.
"""
def __init__(self,
filename="/sys/class/net/wlp0s20u11/statistics/tx_bytes",
read_every_n_samples=1000,
max_increment_per_sample=0):
gr.sync_block.__init__(
self,
name='Multiply by difference from file', # will show up in GRC
in_sig=[np.float32],
out_sig=[np.float32])
self.interval = int(read_every_n_samples)
self.next_read_in = self.interval
self.filename = filename
self.factor = 1
self.max_increment_per_sample = max_increment_per_sample
def read_value(self):
with open(self.filename, "r", encoding="ascii") as file_handle:
line_string = file_handle.readline()
return int(line_string)
def start(self):
self.last_value = self.read_value()
def work(self, input_items, output_items):
in_stream = input_items[0]
output = output_items[0]
if self.next_read_in == 0:
# We've reached the point at which we need
# to update the factor with which we multiply!
# So let's do that:
new_value = self.read_value()
difference = new_value - self.last_value
rate = difference / self.interval
if self.max_increment_per_sample > 0:
rate = rate / self.max_increment_per_sample
rate = min(1, max(rate, 0))
self.factor = rate
self.last_value = new_value
self.next_read_in = self.interval
# number of samples to which apply the same factor
# This is at most as many items we currently have available at
# the input, or as many items are left in this update period
# (whatever is less)
n_to_process = min(len(in_stream), self.next_read_in)
# from current offset, the next n_to_process
# input values get multiplied with the same factor
# and written to the output
output[:n_to_process] = in_stream[:n_to_process] * self.factor
# We've consumed n_to_process input items, so we advance our
# offset and reduce the amount of outstanding input
self.next_read_in -= n_to_process
# We consumed and produced n
return n_to_process
保存并关闭编辑器。
属性对话框现在应如下所示:
如前所述,您必须替换wlp…
为 wifi 卡的实际设备名称。我们每秒更新 4 次(因为我们每秒更新 samp_rate 样本,这意味着 samp_rate/4 个样本更新一次)。我将每秒最大速率设置为我期望的平均每秒 5·10⁶ 字节/秒,因此 5·10⁶/samp_rate。
结论
我们刚刚根据发送到卡的字节数转换了实际发生噪音的模型。我不仅写过,而且还尝试过!有用。虽然我没有做任何事情,但大部分时间都是沉默,但偶尔会有一些来自我仍然在那里的聊天程序的数据包,或者我的电子邮件客户端正在签入,但一旦我发出一些出站数据,我就可以听到脉动数据包。
因此,如果您了解一点 Python(老实说,不是太多),并且想阅读上面的教程和我的源代码,您将能够正确地声称您已经构建了一个用于监控的实时信号处理系统声学上的网络状态。这实际上并不是一个太糟糕的壮举,只需要在这里问一个问题:)
当然,这远非完美。你可能想修改我给你的Python代码——也许,取速率的对数是个好主意。因此,在插值速率方面可能也会更聪明(而不是仅仅保持最后的速率)。如果您想编写一些 Python 代码,我认为这可能是一个很好的起点。您也没有理由需要输入噪声 - 除了噪声源和滤波器之外,您还可以使用“Wav 文件源”(它可以读取大多数压缩音频格式,如 Ogg vorbis、OPUS、MP4 AAC…、不仅是 WAV 文件)来播放您喜爱的音乐。
或者,您可以使用 GNU Radio 和小型无线电接收器(所谓的“RTL-SDR Dongle”)以及合适的天线来实际接收您当地的广播电台,并将其用作基础信号而不是噪音。选项非常多样!GNU Radio 是一个信号处理框架,专为此类情况而创建,您需要实时处理数字信号流,无论是音频、无线电信号还是其他信号。