Skip to content

Instantly share code, notes, and snippets.

@mbutler
Created January 20, 2024 19:36
Show Gist options
  • Save mbutler/ff0e398ee4b40fcd8cf3d4718259669e to your computer and use it in GitHub Desktop.
Save mbutler/ff0e398ee4b40fcd8cf3d4718259669e to your computer and use it in GitHub Desktop.
Simple Frequency Shift Keying implementation for digital modulation
import numpy as np
import wave
import struct
from scipy.signal import butter, lfilter
# Function to convert text to FSK and save as a WAV file
def text_to_fsk_wave(text, filename):
bit_rate = 1200
freq_low = 1200
freq_high = 2400
sample_rate = 48000
binary_data = ''.join(format(ord(char), '08b') for char in text)
t = np.arange(0, len(binary_data) / bit_rate, 1 / sample_rate)
fsk_signal = np.zeros(0)
for bit in binary_data:
freq = freq_low if bit == '0' else freq_high
fsk_signal = np.append(fsk_signal, np.sin(2 * np.pi * freq * t[:int(sample_rate / bit_rate)]))
fsk_signal = np.int16((fsk_signal / np.max(np.abs(fsk_signal))) * 32767)
with wave.open(filename, 'w') as wav_file:
wav_file.setparams((1, 2, sample_rate, 0, 'NONE', 'not compressed'))
for sample in fsk_signal:
wav_file.writeframes(struct.pack('h', sample))
# Function to decode FSK WAV file back into text
def fsk_wave_to_text(filename):
bit_rate = 1200
freq_low = 1200
freq_high = 2400
sample_rate = 48000
samples_per_bit = sample_rate // bit_rate
with wave.open(filename, 'r') as wav_file:
frames = wav_file.readframes(wav_file.getnframes())
fsk_signal = np.frombuffer(frames, dtype=np.int16)
fsk_signal = fsk_signal / np.max(np.abs(fsk_signal))
fsk_signal = bandpass_filter(fsk_signal, freq_low, freq_high, sample_rate)
binary_data = ''
for i in range(0, len(fsk_signal), samples_per_bit):
sample = fsk_signal[i:i + samples_per_bit]
freq = np.fft.fftfreq(len(sample), d=1/sample_rate)
fft_vals = np.fft.fft(sample)
peak_freq = abs(freq[np.argmax(np.abs(fft_vals))])
if np.isclose(peak_freq, freq_low, atol=10):
binary_data += '0'
elif np.isclose(peak_freq, freq_high, atol=10):
binary_data += '1'
text = ''
for i in range(0, len(binary_data), 8):
byte = binary_data[i:i + 8]
if len(byte) == 8:
text += chr(int(byte, 2))
return text
# Band-pass filter for signal processing
def bandpass_filter(data, lowcut, highcut, fs, order=5):
nyq = 0.5 * fs
low = lowcut / nyq
high = highcut / nyq
b, a = butter(order, [low, high], btype='band')
y = lfilter(b, a, data)
return y
# Example usage
text_to_fsk_wave("Hello World", "hello_world.wav")
decoded_text = fsk_wave_to_text("hello_world.wav")
print("Decoded Text:", decoded_text)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment