Pull to refresh

Comments 3

В качестве более интересного примера прослушать с фм радио и сохранить в файл

from hackrf_dll import HackRF
import numpy as np
import soundfile as sf
from scipy.signal import resample, firwin, lfilter, butter, filtfilt

SAMPLE_RATE = 2_000_000
AUDIO_RATE = 48000
CENTER_FREQ = 103_000_000 
OUTPUT_FILE = "fm_audio.wav"

def fm_demod(iq):
    # Простая и стабильная FM демодуляция
    iq_normalized = iq / (np.max(np.abs(iq)) + 1e-9)
    return np.angle(iq_normalized[1:] * np.conj(iq_normalized[:-1]))

def remove_dc_offset(signal, alpha=0.99):
    """Удаление постоянной составляющей"""
    result = np.zeros_like(signal)
    result[0] = signal[0]
    for i in range(1, len(signal)):
        result[i] = alpha * result[i-1] + signal[i] - signal[i-1]
    return result

def apply_lowpass(audio, cutoff_freq, sample_rate, order=5):
    """ФНЧ с butterworth фильтром"""
    nyquist = sample_rate / 2
    normal_cutoff = cutoff_freq / nyquist
    b, a = butter(order, normal_cutoff, btype='low', analog=False)
    return filtfilt(b, a, audio)

def process_audio(audio, original_rate, target_rate):
    # Удаление DC смещения
    audio = remove_dc_offset(audio)
    
    # Фильтр низких частот
    audio = apply_lowpass(audio, 15000, original_rate)
    
    # Ресемплинг
    n_samples = int(len(audio) * target_rate / original_rate)
    audio_resampled = resample(audio, n_samples)
    
    # Нормализация
    max_val = np.max(np.abs(audio_resampled))
    if max_val > 0:
        audio_resampled = audio_resampled / max_val
    
    return audio_resampled

# Основной код
hackrf = HackRF()
hackrf.set_freq(CENTER_FREQ)
hackrf.set_sample_rate(SAMPLE_RATE)

# Начните с умеренных усилений
hackrf.set_lna_gain(16)
hackrf.set_vga_gain(12)
hackrf.enable_amp(True)

iq_buffer = []

def callback(iq):
    global iq_buffer
    try:
        demod = fm_demod(iq)
        iq_buffer.append(demod)
        print(f"[RX] Демодулировано {len(demod)} сэмплов")
    except Exception as e:
        print(f"Ошибка обработки: {e}")

print("Начинаем прием...")
hackrf.start_rx(callback)

try:
    input("Нажмите Enter для остановки...\n")
except KeyboardInterrupt:
    pass

hackrf.stop_rx()
hackrf.close()

# Обработка данных
if iq_buffer:
    audio = np.concatenate(iq_buffer)
    audio_processed = process_audio(audio, SAMPLE_RATE, AUDIO_RATE)
    
    sf.write(OUTPUT_FILE, audio_processed.astype(np.float32), AUDIO_RATE)
    print(f"[OK] Сохранено аудио в {OUTPUT_FILE}")
else:
    print("[ERROR] Нет данных для обработки")

Для hackrf существует библиотека python_hackrf которая работает на всех платформах ( в том числе и андроид). Работает как обертка cython над libhackrf

Sign up to leave a comment.

Articles