신호 생성 애플리케이션을 구축하는 방법에 대한 간단한 튜토리얼

신호 생성 애플리케이션을 구축하는 방법에 대한 간단한 튜토리얼

좋아요, 이상하다는 건 알지만 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_bytestx_bytes

답변3

나에게 있어 유일한 실제 목적은 Wi-Fi 카드가 데이터를 전송할 때 이를 알리고 매우 조용한 사무실에서 (다소) 결정적인 소음 원인을 제공하는 것입니다.

"원시" 데이터를 들을 수 없는 이유를 설명하는 내 의견은 너무 지나쳤습니다.

하지만 당신이 정말로 원하는 것은 전화 통신 엔지니어들이 말하는 것입니다.편안한 소음일부 변화하는 데이터를 강화했습니다.

그러니 만들어 보세요!이와 같은 것을 구축하는 방법에 대한 간단한 소개는 다음과 같습니다.그냥 따라하고 복사하여 붙여넣을 수도 있고, 각 단계를 자세히 살펴볼 수도 있습니다. 무엇이든 더 흥미로울 수 있습니다 :)

신호 생성 애플리케이션을 구축하는 방법에 대한 간단한 튜토리얼

Comfort Noise와 GNU Radio Companion의 첫 번째 단계

컴포트 노이즈 섹션부터 시작해 보겠습니다. GNU Radio 설치는 쉽고 실행도 쉽습니다 apt install gnuradio. 그런 다음 GNU Radio Companion을 엽니다.

공식 튜토리얼을 읽어야합니다.https://tutorials.gnuradio.org, 이제 오른쪽에 있는 검색창을 사용하여 두 블록을 모두 찾으세요.

  1. 오디오 수신기
  2. 소음원

캔버스에 추가하고 연결하세요. Noise Source 블록을 두 번 클릭하고 출력 유형을 "float"으로 변경합니다.

결과는 다음과 같아야 합니다.

소음원 -> 오디오 수신기

같은 방법으로 samp_rate 변수 블록을 변경하여 해당 값이 48000이 되도록 합니다. "이동" 버튼을 클릭하세요. (데스크톱 환경에 따라 다르지만 일반적으로 ⏵ 모양이며, 실행 메뉴에서도 "실행"으로 찾을 수 있습니다.)

48000 샘플링 속도

축하합니다. 스피커에서 백색 소음이 발생하고 있습니다! 소음원의 "진폭"을 설정하여 볼륨을 조정할 수도 있습니다(1 대신 0.1로 시도).

노이즈를 형성하고 필터링을 수행합니다.

멋지네요. 저역 통과 필터 블록을 찾고, 소음원과 오디오 수신기 사이의 직접적인 연결을 제거하고, 그 사이에 필터를 배치하여 소음을 덜 성가시게 만들어 보겠습니다. 필터를 "Float -> Float (Decimating)"로 설정하고 차단 주파수를 3000으로, 전환 폭을 1500으로 설정합니다. 이제 백색 잡음을 보다 인간과 유사한 저역 통과 잡음으로 변환했으므로착색된 소음. 시도 해봐!

소음원 -> 저역 통과 필터 -> 오디오 수신기

데이터 속도를 시스템에 통합하는 방법

이제 어떻게든 전체 시스템에 교통 정보를 추가해야 합니다.

정기적으로 Linux에 네트워크 인터페이스를 통과한 바이트 수를 물어보고 마지막으로 요청한 시점과의 차이를 계산하여 이를 수행할 수 있습니다. 이렇게 하면 데이터 속도를 숫자로 얻을 수 있습니다. 이 숫자가 높으면 소음이 더 커지거나 특정 음조가 더 높아지기를 원합니다. 기본적으로 우리는 이를 대형 모듈형 신디사이저에 앉아 있는 완성된 전자 음악 아티스트로 생각할 수 있습니다. 데이터 속도에 따라 달라집니다.

따라서 작은 문제가 있습니다. 오디오 수신기 및 잡음 소스와 달리 GNU Radio에는 아직 데이터 속도를 계산하는 블록이 포함되어 있지 않습니다. 그건 문제가 되지 않습니다. 우리가 직접 만들 수 있습니다.

하지만 어떻게 작동하나요?

조금 뒤로 물러서십시오. "이동" 버튼을 클릭하면 어떻게 되나요? 내 동료 GNU Radio 사람들이 다가와 살펴보았습니다.흐름도Python 프로그램을 빌드하고 생성했습니다.

이 프로그램은 추가하는 모든 블록을 인스턴스화하고 구성하며 GNU Radio 런타임에 연결 방법을 알려줍니다. 그런 다음 프로그램은 실제로 순서도를 통해 데이터 전송을 시작하도록 런타임에 지시합니다. 즉, 노이즈 소스에 노이즈 샘플을 생성하라고 지시하고 해당 샘플이 준비되면 필터에 다음과 같이 필터링하라고 지시합니다. , 오디오 싱크에 필터링된 샘플이 사운드 카드에 제공됩니다. (실제로 동시에 노이즈 소스가 더 많은 샘플을 생성하기 시작했으며 모든 것이 병렬로 실행됩니다.)

따라서 소프트웨어의 모든 작은 부분은 연결된 "업스트림" 블록과 해당 입력 사이, 그리고 해당 출력과 "다운스트림" 블록 간에 교환되는 숫자를 생성, 변환 또는 궁극적으로 처리합니다.

진행 중인 개발 작업

우리가 궁극적으로 원하는 것은 무엇인가

따라서 우리의 임무는 동일한 작업을 수행하는 작은 소프트웨어를 작성하는 것입니다. 필터 뒤에 삽입하기만 하면 됩니다. 이것이 제가 상상했던 모습입니다: (이것은 모델입니다!)

어떤 모습이어야 하는지에 대한 모델

입력을 출력으로 복사하고 파일에서 읽은 일부 정수의 변화율을 곱하는 블록입니다.

따라서 첫 번째 매개변수는 읽을 파일의 이름입니다. "/sys/class/net/wlp0s20u11/statistics/tx_bytes"여기서는 이를 사용합니다. Wi-Fi 카드의 장치 이름으로 바꿉니다 wlp0s20u11(의심스러운 경우 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…앞서 언급했듯이 Wi-Fi 카드의 실제 장치 이름으로 바꿔야 합니다 . 우리는 초당 4번 업데이트합니다(samp_rate 샘플을 매초 업데이트하므로 이는 samp_rate/4 샘플이 한 번 업데이트된다는 의미입니다). 초당 최대 속도를 평균 5·10⁶바이트/초로 예상하여 5·10⁶/samp_rate로 설정했습니다.

결론적으로

우리는 카드로 전송된 바이트 수를 기반으로 실제로 노이즈가 발생하는 모델을 변환했습니다. 글을 썼을 뿐만 아니라, 시도해 보았습니다! 효과가있다. 아무 것도 하지 않는 동안에는 대부분 조용하지만 가끔 아직 남아 있는 채팅 프로그램이나 체크인 중인 이메일 클라이언트에서 일부 패킷이 전송되는 경우가 있지만 아웃바운드 데이터를 전송하면 펄스 패킷이 들리는 것을 들을 수 있습니다.

따라서 Python에 대해 조금 알고(솔직히 말해서 너무 많지는 않음) 위의 튜토리얼과 내 소스 코드를 읽고 싶다면 Python을 위한 실시간 신호 처리 시스템을 구축했다고 올바르게 주장할 수 있습니다. 음향 네트워크 상태를 모니터링합니다. 이것은 실제로 그다지 나쁘지 않은 위업입니다. 여기에 물어볼 질문입니다. :)

물론 이것은 완벽과는 거리가 멀다. 제가 제공한 Python 코드를 수정하고 싶을 수도 있습니다. 속도에 로그를 취하는 것이 좋은 생각일 수도 있습니다. 따라서 (마지막 비율을 유지하는 대신) 보간 비율 측면에서 더 똑똑할 수도 있습니다. Python 코드를 작성하고 싶다면 여기가 좋은 시작점이 될 수 있다고 생각합니다. 입력 노이즈가 필요할 이유가 없습니다. 노이즈 소스 및 필터 대신 "Wav 파일 소스"(WAV 파일뿐만 아니라 Ogg vorbis, OPUS, MP4 AAC...와 같은 대부분의 압축 오디오 형식을 읽을 수 있음)를 사용할 수 있습니다. 좋아하는 음악을 틀어보세요.

또는 GNU Radio와 적합한 안테나가 있는 소형 라디오 수신기(소위 "RTL-SDR 동글")를 사용하여 실제로 지역 라디오 방송국을 포착하고 이를 잡음이 아닌 기본 신호로 사용할 수 있습니다. 옵션이 정말 다양해요! GNU Radio는 오디오, 라디오 신호 또는 기타 신호 등 디지털 신호 스트림을 실시간으로 처리해야 하는 상황을 위해 특별히 만들어진 신호 처리 프레임워크입니다.

관련 정보