# -*- coding: utf-8 -*-
"""
Created on Sun Oct 26 17:11:17 2025

@author: AKourgli
"""

import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import firwin, lfilter, freqz

def create_vsb_filter(numtaps, cutoff, transition_width, fs):
    """
    Create a VSB filter with specific characteristics
    """
    # Create a low-pass filter with gradual transition
    taps = firwin(numtaps, cutoff, fs=fs, window='hamming')
    
    # Convert to band-pass for VSB (this is a simplified version)
    # In practice, VSB filters are more carefully designed
    t = np.arange(numtaps) - (numtaps-1)/2
    carrier_component = np.cos(2 * np.pi * cutoff * t / fs)
    vsb_taps = taps * carrier_component
    
    return vsb_taps

# Parameters
fs = 100000
T = 0.1
t = np.linspace(0, T, int(T*fs), endpoint=False)

# Message signal (now with DC component to show VSB advantage)
f_m1 = 300
f_m2 = 600
m_t = 0.5 + np.sin(2 * np.pi * f_m1 * t) + 0.3 * np.sin(2 * np.pi * f_m2 * t)

# Carrier
f_c = 10000
carrier = np.cos(2 * np.pi * f_c * t)

# Create DSB-SC
dsb_sc = m_t * carrier

# Create VSB filter
numtaps = 1001
cutoff = f_c + 400  # Cutoff frequency
transition = 800    # Transition width
vsb_taps = create_vsb_filter(numtaps, cutoff, transition, fs)

# Apply VSB filter
vsb_signal = lfilter(vsb_taps, 1.0, dsb_sc)

# Also create SSB for comparison using filtering method
# (Simple approximation - real SSB would need sharper filter)
ssb_taps = firwin(numtaps, [f_c-10, f_c+10], fs=fs, pass_zero=False)  # Bandpass
ssb_signal_approx = lfilter(ssb_taps, 1.0, dsb_sc)

# Plot results
plt.figure(figsize=(15, 10))

# Plot 1: Filter frequency responses
plt.subplot(3, 2, 1)
w, h_ssb = freqz(ssb_taps, worN=8000, fs=fs)
w, h_vsb = freqz(vsb_taps, worN=8000, fs=fs)
plt.plot(w, 20*np.log10(np.abs(h_ssb)), 'r--', label='SSB Filter (Ideal)', alpha=0.7)
plt.plot(w, 20*np.log10(np.abs(h_vsb)), 'g', label='VSB Filter', linewidth=2)
plt.axvline(x=f_c, color='k', linestyle=':', label=f'Carrier {f_c}Hz')
plt.title('Filter Frequency Responses')
plt.xlabel('Frequency [Hz]')
plt.ylabel('Magnitude [dB]')
plt.xlim(f_c-2000, f_c+2000)
plt.legend()
plt.grid(True)

# Plot 2: DSB-SC Spectrum
plt.subplot(3, 2, 2)
DSB_f = np.fft.fft(dsb_sc)
freqs = np.fft.fftfreq(len(dsb_sc), 1/fs)
plt.plot(freqs, np.abs(DSB_f), 'orange', label='DSB-SC')
plt.title('DSB-SC Spectrum')
plt.xlabel('Frequency [Hz]')
plt.ylabel('Magnitude')
plt.xlim(f_c-1500, f_c+1500)
plt.legend()
plt.grid(True)

# Plot 3: SSB Spectrum (ideal filtering)
plt.subplot(3, 2, 3)
SSB_f = np.fft.fft(ssb_signal_approx)
plt.plot(freqs, np.abs(SSB_f), 'r', label='SSB (Approx)')
plt.title('SSB Spectrum')
plt.xlabel('Frequency [Hz]')
plt.ylabel('Magnitude')
plt.xlim(f_c-1500, f_c+1500)
plt.legend()
plt.grid(True)

# Plot 4: VSB Spectrum
plt.subplot(3, 2, 4)
VSB_f = np.fft.fft(vsb_signal)
plt.plot(freqs, np.abs(VSB_f), 'g', label='VSB', linewidth=2)
plt.title('VSB Spectrum')
plt.xlabel('Frequency [Hz]')
plt.ylabel('Magnitude')
plt.xlim(f_c-1500, f_c+1500)
plt.legend()
plt.grid(True)

# Plot 5: Time domain comparison
plt.subplot(3, 2, 5)
zoom_samples = 1500
plt.plot(t[:zoom_samples], dsb_sc[:zoom_samples], 'orange', label='DSB-SC', alpha=0.7)
plt.plot(t[:zoom_samples], ssb_signal_approx[:zoom_samples], 'r', label='SSB', alpha=0.7)
plt.plot(t[:zoom_samples], vsb_signal[:zoom_samples], 'g', label='VSB', linewidth=1.5)
plt.title('Time Domain Comparison')
plt.xlabel('Time [s]')
plt.ylabel('Amplitude')
plt.legend()
plt.grid(True)

# Plot 6: Demodulation comparison (envelope detection)
plt.subplot(3, 2, 6)
# Simple envelope detection (rectify and low-pass)
envelope_dsb = np.abs(dsb_sc)
envelope_vsb = np.abs(vsb_signal)

# Apply simple low-pass filter
def simple_lowpass(signal, alpha=0.01):
    filtered = np.zeros_like(signal)
    filtered[0] = signal[0]
    for i in range(1, len(signal)):
        filtered[i] = alpha * signal[i] + (1 - alpha) * filtered[i-1]
    return filtered

env_dsb_filtered = simple_lowpass(envelope_dsb)
env_vsb_filtered = simple_lowpass(envelope_vsb)

plt.plot(t[:zoom_samples], m_t[:zoom_samples], 'k', label='Original', linewidth=2)
plt.plot(t[:zoom_samples], env_dsb_filtered[:zoom_samples], 'orange', label='DSB-SC Envelope', alpha=0.7)
plt.plot(t[:zoom_samples], env_vsb_filtered[:zoom_samples], 'g', label='VSB Envelope', alpha=0.7)
plt.title('Envelope Detection Comparison')
plt.xlabel('Time [s]')
plt.ylabel('Amplitude')
plt.legend()
plt.grid(True)

plt.tight_layout()
plt.show()

print("\nVSB Key Advantages:")
print("1. Easier filter design than SSB")
print("2. Can demodulate with envelope detector (like AM) with proper carrier insertion")
print("3. Preserves low-frequency components better than SSB")
print("4. Used in analog television broadcasting")