Передача изображений в SSB-сигнале с помощью Python

19 февраля 2020

Недавно на YouTube-канале Максима, EW7DDR было опубликовано видео Визуальная передача позывного для SDR приемника, которое в свою очередь основано на статье Визуализация позывного на панораме SDR за авторством Сергея, R3AZ. Видео рассказывает о том, как сгенерировать SSB-сигнал, который при просмотре в панадаптере или WebSDR выглядит, как текст или картинка. Идея мне понравилась, и было решено повторить эксперимент.

В обеих инструкциях предлагается воспользоваться программой для Windows под названием AudioPaint. Проблема заключается в том, что Windows я уже много лет не пользуюсь. Беглый поиск не выявил аналогов для MacOS или Linux, во всяком случае, бесплатных. Тогда я решил прибегнуть к помощи языка Python и библиотеки NumPy.

Был написан следующий скрипт:

#!/usr/bin/env python3

from PIL import Image
import numpy as np
import scipy.io.wavfile as wav
import argparse
import os

parser = argparse.ArgumentParser(
    description='Convert PNG image to a WAV file'
    )
parser.add_argument(
    '-i', '--input', metavar='F', type=str, required=True,
    help='Input file, ???x240px black and white PNG image')
parser.add_argument(
    '-o', '--output', metavar='F', type=str, required=True,
    help='Output WAV file')
args = parser.parse_args()

im = Image.open(args.input)
if im.height != 240:
  print("Image height has to be 240px")
  os.Exit(1)

tau = 2*np.pi
samples_per_px = 1000
samplerate = 44100
white = (255,255,255,255)
waveform = np.array([])
t = np.linspace(0, samples_per_px/samplerate, samples_per_px)
for x in range(0, im.width):
  f = 0 * t
  for y in range(0, im.height):
    px = im.getpixel((x,y))
    if px != white:
      f += (1/im.height)*np.sin((300+y*10)*tau*t)
  waveform = np.concatenate((waveform, f))

waveform = np.int16(waveform*32767)
wav.write(args.output, samplerate, waveform)

Скрипт имеет следующие зависимости:

pip3 install Pillow numpy scipy

Устанавливать их лучше в virtualenv, чтобы не засорять систему.

Тестовая передача велась при помощи Xiegu X5105 на минимальной мощности 0.1 Вт. При этом использовалась неэффективная антенна внутри городской квартиры. Передача велась зимой в ночное время в дневном радиолюбительском диапазоне 20 метров. В общем, были предприняты все меры для того, чтобы подобное баловство никому не создало помех.

Прием осуществлялся при помощи RTL-SDR и программы Gqrx:

Передача графики и текста в SSB-сигнале

Как можно видеть, эксперимент удался. Приведенный скрипт работает под Windows, Linux, MacOS, да и вообще, везде, где есть Python.

Дополнение: Вас также может заинтересовать статья Рисуем на осциллографе в режиме X-Y

Метки: , , .