import math import sounddevice as sd # ================================================== # RTTY PARAMETERS # ================================================== Fs = 48000 # PC sound-card sample rate baud = 45.45 # RTTY baud rate mark_freq = 2125 # MARK space_freq = 2295 # SPACE text = "HELLO WORLD 123" # ================================================== # ITA2 / BAUDOT # ================================================== LETTERS = { 'A': 0b00011, 'B': 0b11001, 'C': 0b01110, 'D': 0b01001, 'E': 0b00001, 'F': 0b01101, 'G': 0b11010, 'H': 0b10100, 'I': 0b00110, 'J': 0b01011, 'K': 0b01111, 'L': 0b10010, 'M': 0b11100, 'N': 0b01100, 'O': 0b11000, 'P': 0b10110, 'Q': 0b10111, 'R': 0b01010, 'S': 0b00101, 'T': 0b10000, 'U': 0b00111, 'V': 0b11110, 'W': 0b10011, 'X': 0b11101, 'Y': 0b10101, 'Z': 0b10001, ' ': 0b00100 } FIGURES = { '1': 0b10111, '2': 0b10011, '3': 0b00001, '4': 0b01010, '5': 0b10000, '6': 0b10101, '7': 0b00111, '8': 0b00110, '9': 0b11000, '0': 0b10110, } FIGURES_SHIFT = 0b1101 LETTERS_SHIFT = 0b11111 # ================================================== # TEXT → BAUDOT # ================================================== baudot_bits = [] mode = "LETTERS" for char in text.upper(): if char == ' ': code = LETTERS[' '] elif char in LETTERS: if mode != "LETTERS": code = LETTERS_SHIFT for i in range(5): baudot_bits.append((code >> i) & 1) mode = "LETTERS" code = LETTERS[char] elif char in FIGURES: if mode != "FIGURES": code = FIGURES_SHIFT for i in range(5): baudot_bits.append((code >> i) & 1) mode = "FIGURES" code = FIGURES[char] else: continue # LSB first for i in range(5): baudot_bits.append((code >> i) & 1) # ================================================== # ADD RTTY FRAMING # ================================================== framed_bits = [] for i in range(0, len(baudot_bits), 5): data = baudot_bits[i:i + 5] # START = SPACE framed_bits.append(0) # DATA framed_bits.extend(data) # STOP = MARK framed_bits.append(1) # ================================================== # FSK MODULATOR # ================================================== phase = 0.0 signal = [] samples_per_bit = Fs / baud sample_accumulator = 0.0 for bit in framed_bits: if bit == 1: frequency = mark_freq else: frequency = space_freq # Number of samples for this symbol sample_accumulator += samples_per_bit samples_this_symbol = int(sample_accumulator) sample_accumulator -= samples_this_symbol # Generate the symbol for _ in range(samples_this_symbol): phase += 2 * math.pi * frequency / Fs # Keep phase between 0 and 2*pi phase %= 2 * math.pi sample = math.cos(phase) signal.append(sample) # ================================================== # PLAY AUDIO # ================================================== print("Playing RTTY...") print() print("Text:", text) print("MARK:", mark_freq, "Hz") print("SPACE:", space_freq, "Hz") print("Baud:", baud) print("Duration:", len(signal) / Fs, "seconds") sd.play(signal, Fs) sd.wait() print("Finished.")