Working SSTV prototype
This commit is contained in:
parent
7c08588870
commit
d0738dac08
|
@ -0,0 +1,120 @@
|
|||
#/usr/bin/env python3
|
||||
import numpy as np
|
||||
|
||||
|
||||
from scipy.io import wavfile
|
||||
from scipy.misc import imread
|
||||
from matplotlib import pyplot as plt
|
||||
|
||||
|
||||
WIDTH = 640
|
||||
HEIGHT = 496
|
||||
|
||||
OUTPUT_RATE = 48000
|
||||
|
||||
VIS_START_FREQ = 1900
|
||||
VIS_START_DUR = 300
|
||||
VIS_PAUSE = 10
|
||||
VIS_ONE_FREQ = 1100
|
||||
VIS_ZERO_FREQ = 1300
|
||||
VIS_BIT_DUR = 30
|
||||
# Code 97 + even parity, lsb first
|
||||
VIS_BITS = [True, False, False, False, False, True, True, True]
|
||||
|
||||
SYNC_FREQ = 1200
|
||||
SYNC_DUR = 20
|
||||
|
||||
PORCH_DUR = 2.080
|
||||
|
||||
PIXEL_DUR = 0.382
|
||||
|
||||
COLOR_LOW_FREQ = 1500
|
||||
COLOR_HIGH_FREG = 2300
|
||||
|
||||
phase_acc = 0
|
||||
|
||||
|
||||
def sine_gen(freq):
|
||||
global phase_acc
|
||||
phase_inc = (2 * np.pi / OUTPUT_RATE) * freq
|
||||
phase_acc += phase_inc
|
||||
if phase_acc > 2 * np.pi:
|
||||
phase_acc = phase_acc - 2 * np.pi
|
||||
|
||||
return np.sin(phase_acc)
|
||||
|
||||
|
||||
samples_left = 0
|
||||
def make_tone(freq, duration, data):
|
||||
global samples_left
|
||||
samples = duration / 1000 * OUTPUT_RATE + samples_left
|
||||
sample_count = int(samples)
|
||||
samples_left = samples - sample_count
|
||||
|
||||
for i in range(0, sample_count):
|
||||
data += [sine_gen(freq)]
|
||||
|
||||
|
||||
|
||||
|
||||
def make_vis(samples):
|
||||
make_tone(VIS_START_FREQ, VIS_START_DUR, samples)
|
||||
make_tone(SYNC_FREQ, VIS_PAUSE, samples)
|
||||
make_tone(VIS_START_FREQ, VIS_START_DUR, samples)
|
||||
|
||||
make_tone(SYNC_FREQ, VIS_BIT_DUR, samples)
|
||||
for bit in VIS_BITS:
|
||||
if bit:
|
||||
make_tone(VIS_ONE_FREQ, VIS_BIT_DUR, samples)
|
||||
else:
|
||||
make_tone(VIS_ZERO_FREQ, VIS_BIT_DUR, samples)
|
||||
|
||||
make_tone(SYNC_FREQ, VIS_BIT_DUR, samples)
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
image = imread('testcard.png', mode='YCbCr')
|
||||
|
||||
samples = []
|
||||
|
||||
make_vis(samples)
|
||||
|
||||
for y in range(0, int(HEIGHT/2)):
|
||||
make_tone(SYNC_FREQ, SYNC_DUR, samples)
|
||||
make_tone(COLOR_LOW_FREQ, PORCH_DUR, samples)
|
||||
|
||||
for x in range(0, WIDTH):
|
||||
lum = image[y*2, x, 0] / 255.0
|
||||
freq = COLOR_LOW_FREQ + lum * (COLOR_HIGH_FREG - COLOR_LOW_FREQ)
|
||||
make_tone(freq, PIXEL_DUR, samples)
|
||||
|
||||
for x in range(0, WIDTH):
|
||||
cr0 = image[y*2, x, 2] / 255.0
|
||||
cr1 = image[y*2 + 1, x, 2] / 255.0
|
||||
cr = (cr0 + cr1) / 2
|
||||
freq = COLOR_LOW_FREQ + cr * (COLOR_HIGH_FREG - COLOR_LOW_FREQ)
|
||||
make_tone(freq, PIXEL_DUR, samples)
|
||||
|
||||
for x in range(0, WIDTH):
|
||||
cb0 = image[y*2, x, 1] / 255.0
|
||||
cb1 = image[y*2 + 1, x, 1] / 255.0
|
||||
cb = (cb0 + cb1) / 2
|
||||
freq = COLOR_LOW_FREQ + cb * (COLOR_HIGH_FREG - COLOR_LOW_FREQ)
|
||||
make_tone(freq, PIXEL_DUR, samples)
|
||||
|
||||
for x in range(0, WIDTH):
|
||||
lum = image[y*2 + 1, x, 0] / 255.0
|
||||
freq = COLOR_LOW_FREQ + lum * (COLOR_HIGH_FREG - COLOR_LOW_FREQ)
|
||||
make_tone(freq, PIXEL_DUR, samples)
|
||||
|
||||
|
||||
samples = np.array(samples)
|
||||
|
||||
samples = samples * 0.75 * 32767
|
||||
samples = np.int16(samples)
|
||||
|
||||
wavfile.write("output.wav", OUTPUT_RATE, samples)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
Binary file not shown.
After Width: | Height: | Size: 32 KiB |
Loading…
Reference in New Issue