import numpy as np import scipy.signal import wave def read_raw_iq_samples(file_path): with open(file_path, 'rb') as file: raw_data = file.read() iq_samples = np.frombuffer(raw_data, dtype=np.int8) return iq_samples def fm_demodulation(iq_samples, sample_rate, fm_deviation=75e3): # Hilbert transform for FM demodulation analytic_signal = scipy.signal.hilbert(iq_samples) instantaneous_phase = np.unwrap(np.angle(analytic_signal)) demodulated_signal = np.unwrap(np.angle(iq_samples[1:] * np.conj(iq_samples[:-1]))) / (2.0 * np.pi * 1.0/sample_rate * fm_deviation) return demodulated_signal def decimate_audio(signal, decimation_factor): return scipy.signal.resample(signal, len(signal)//decimation_factor) def low_pass_filter(signal, cutoff_frequency, sample_rate): nyquist = 0.5 * sample_rate normal_cutoff = cutoff_frequency / nyquist b, a = scipy.signal.butter(6, normal_cutoff, btype='low', analog=False) filtered_signal = scipy.signal.filtfilt(b, a, signal) return filtered_signal def save_wav_file(signal, sample_rate, output_file): scaled_signal = np.int16(signal / np.max(np.abs(signal)) * 32767) with wave.open(output_file, 'wb') as wav_file: wav_file.setnchannels(1) wav_file.setsampwidth(2) wav_file.setframerate(sample_rate) wav_file.writeframes(scaled_signal.tobytes()) def main(input_file, output_file, sample_rate, channel_width, decimation_factor=10, cutoff_frequency=75e3): iq_samples = read_raw_iq_samples(input_file) demodulated_signal = fm_demodulation(iq_samples, sample_rate) decimated_signal = decimate_audio(demodulated_signal, decimation_factor) filtered_signal = low_pass_filter(decimated_signal, cutoff_frequency, sample_rate/decimation_factor) new_sample_rate = sample_rate / decimation_factor save_wav_file(filtered_signal, new_sample_rate, output_file) if __name__ == "__main__": input_file_path = "fm_capture.bin" output_wav_path = "output.wav" sample_rate = 2e6 # Replace with the actual sample rate of your FM stream channel_width = 200e3 # Replace with the channel width of your FM signal main(input_file_path, output_wav_path, sample_rate, channel_width)