I have a python code that reads an IQ stream from a RTL-SDR dongle and process it to a ndarray, the IQ from the ndarray is then demodulated to extract an USB signal and written to a file, the code is something like:
def MainLoop():
...
# A loop that reads samples from the RTL-SDR device
data = client.read_samples()
...
# Convert RTL-SDR IQ from 0/255 to -1/+1
iq_samples = PackedBytesToIQ(data)
LowPassFilter(iq_samples)
...
def LowPassFilter(iq_signal, minFreq, maxFreq):
# Low pass filtering
samplingRate = common.getRtlSdrSampleRate() # Sampling rate in Hz
carrierFreq = (samplingRate/4) - (common.getRtlSdrTuningFreq() - common.getFt8Freq())
minFreq = int(carrierFreq) # Minimum frequency in Hz
maxFreq = int(carrierFreq + 3000) # Maximum frequency in Hz
filteredSignal = IQLowpassFilter(inputIq, minFreq, maxFreq, samplingRate)
DecodeUsbSignal(filteredSignal, fileName, minFreq)
...
def DecodeUsbSignal(inputIq, output_file: str, carrierFreq: int):
logging.debug("DEC -> Starting USB decode")
# Create the carrier signal for demodulation
sampling_rate = common.getRtlSdrSampleRate() # Adjust this to your actual sampling rate
t = np.arange(0, len(inputIq)) / sampling_rate
#carrier_freq = 0 # Adjust this to your USB carrier frequency
carrier_signal = np.exp(1j * 2 * np.pi * carrierFreq * t)
# Demodulate the USB signal
demodulated_signal = inputIq * carrier_signal
# Shift the spectrum down
# demodulated_signal = ShiftIQ(demodulated_signal, -1 * carrierFreq) <- This does not work
# Ensure that the demodulated signal is real-valued
demodulated_signal = demodulated_signal.real
# Normalize the signal before scaling
max_value = np.max(np.abs(demodulated_signal))
if max_value != 0:
normalized_signal = demodulated_signal / max_value
else:
normalized_signal = demodulated_signal
# Scale the signal for 16-bit audio
scaled_signal = np.int16(normalized_signal * 32767)
# Write to file
logging.debug(f"DEC -> Writing to {output_file}")
scipy.io.wavfile.write(output_file, sampling_rate, scaled_signal)
logging.debug(f"DEC -> Writing completed")
My center frequency is 144.5MHz and the USB signal is at 144.174MHz, with a samplerate of 2.048Ms/s means that my signal is 186Khz above the minimum received frequency. The code mostly works fine except for the fact that is stored as a 2048000Hz file and my USB signal is at 186KHz in the audio spectrum, how do i "shift" the IQ down by 186KHz to have the USB signal at an usable audio range?
Audio spectrum from audacity:
I tried to shift the IQ with something like:
import numpy as np
def shift_iq_frequency(iq_signal, shift_freq, sampling_rate):
t = np.arange(0, len(iq_signal)) / sampling_rate
shift = np.exp(-1j * 2 * np.pi * shift_freq * t) # Use negative sign for frequency shift
shifted_iq_signal = iq_signal * shift
return shifted_iq_signal
But i only managed to shift the signal up, not down, even by using a negative interval.
A negative value gave me this (the audio wave looks weird too):
While a positive value shifted my spectrum up correctly: