Signal Processing: Sampling, Quantization, and Masking

Sampling and Quantization

This code demonstrates the concepts of sampling and quantization in digital signal processing using Python libraries NumPy and Matplotlib.

import numpy as np
import matplotlib.pyplot as plt

Parameters

  • Signal Frequency (f_signal): 5 Hz
  • Sampling Frequency (f_sampling): 20 Hz
  • Quantization Levels: 8
  • Duration: 1 second

# Parameters
f_signal = 5 # Frequency of the signal (Hz)
f_sampling = 20 # Sampling frequency (Hz)
quantization_levels = 8 # Number of quantization levels
duration = 1 # Signal duration (seconds)

Continuous Signal

A continuous sine wave is generated using NumPy’s linspace function.

# Time for continuous signal
t_continuous = np.linspace(0, duration, 1000)
signal_continuous = np.sin(2 * np.pi * f_signal * t_continuous)

Sampled Signal

The continuous signal is sampled at the specified sampling frequency.

# Time for sampled signal
t_sampled = np.arange(0, duration, 1 / f_sampling)
signal_sampled = np.sin(2 * np.pi * f_signal * t_sampled)

Quantization

The sampled signal is quantized into discrete levels.

# Quantization
signal_min = min(signal_sampled)
signal_max = max(signal_sampled)
quantization_step = (signal_max - signal_min) / quantization_levels
quantized_signal = np.round((signal_sampled - signal_min) / quantization_step) * quantization_step + signal_min

Plotting

The continuous, sampled, and quantized signals are plotted using Matplotlib.

# Plotting
plt.figure(figsize=(12, 8))

Continuous Signal

# Continuous signal
plt.subplot(3, 1, 1)
plt.plot(t_continuous, signal_continuous, label="Continuous Signal", color="blue")
plt.title("Continuous Signal")
plt.xlabel("Time (s)")
plt.ylabel("Amplitude")
plt.grid()
plt.legend()

Sampled Signal

# Sampled signal
plt.subplot(3, 1, 2)
plt.stem(t_sampled, signal_sampled, basefmt=" ", linefmt="orange", markerfmt="ro", label="Sampled Signal")
plt.title("Sampled Signal")
plt.xlabel("Time (s)")
plt.ylabel("Amplitude")
plt.grid()
plt.legend()

Quantized Signal

# Quantized signal
plt.subplot(3, 1, 3)
plt.stem(t_sampled, quantized_signal, basefmt=" ", linefmt="green", markerfmt="go", label="Quantized Signal")
plt.title("Quantized Signal")
plt.xlabel("Time (s)")
plt.ylabel("Amplitude")
plt.grid()
plt.legend()

# Display plots
plt.tight_layout()
plt.show()

Masking in Audio Signal Processing

This section demonstrates frequency and temporal masking techniques applied to an audio spectrogram using NumPy, Matplotlib, and Librosa.

import numpy as np
import matplotlib.pyplot as plt
import librosa
import librosa.display

Frequency Masking Function

def frequency_masking(spectrogram, freq_mask_param):
"""
Apply frequency masking to a spectrogram.

Parameters:
- spectrogram: 2D numpy array (log-Mel or spectrogram).
- freq_mask_param: Maximum frequency mask width.

Returns:
- Masked spectrogram.
"""
num_freqs = spectrogram.shape[0]
f = np.random.randint(0, freq_mask_param)
f0 = np.random.randint(0, num_freqs - f)
spectrogram[f0:f0 + f, :] = 0
return spectrogram

Temporal Masking Function

def temporal_masking(spectrogram, time_mask_param):
"""
Apply temporal masking to a spectrogram.

Parameters:
- spectrogram: 2D numpy array (log-Mel or spectrogram).
- time_mask_param: Maximum time mask width.

Returns:
- Masked spectrogram.
"""
num_frames = spectrogram.shape[1]
t = np.random.randint(0, time_mask_param)
t0 = np.random.randint(0, num_frames - t)
spectrogram[:, t0:t0 + t] = 0
return spectrogram

Audio Loading and Spectrogram Generation

An example audio file is loaded using Librosa, and its Mel spectrogram is generated.

# Load an example audio file (using librosa)
audio_path = librosa.example('trumpet') # You can replace this with your own file
y, sr = librosa.load(audio_path, sr=None)

# Generate Mel spectrogram
n_fft = 2048
hop_length = 512
n_mels = 128
mel_spectrogram = librosa.feature.melspectrogram(y=y, sr=sr, n_fft=n_fft, hop_length=hop_length, n_mels=n_mels)
log_mel_spectrogram = librosa.power_to_db(mel_spectrogram, ref=np.max)

Applying Masking

Frequency and temporal masking are applied to the spectrogram.

# Apply frequency and temporal masking
freq_mask_param = 20 # Maximum width of frequency masking
time_mask_param = 30 # Maximum width of temporal masking
masked_spectrogram = frequency_masking(log_mel_spectrogram.copy(), freq_mask_param)
masked_spectrogram = temporal_masking(masked_spectrogram, time_mask_param)

Plotting Spectrograms

The original and masked spectrograms are plotted for comparison.

# Plotting
plt.figure(figsize=(12, 8))

Original Spectrogram

# Original Spectrogram
plt.subplot(3, 1, 1)
librosa.display.specshow(log_mel_spectrogram, sr=sr, hop_length=hop_length, x_axis='time', y_axis='mel')
plt.title("Original Log-Mel Spectrogram")
plt.colorbar(format='%+2.0f dB')

Frequency and Temporal Masked Spectrogram

# Frequency Masked Spectrogram
plt.subplot(3, 1, 2)
librosa.display.specshow(masked_spectrogram, sr=sr, hop_length=hop_length, x_axis='time', y_axis='mel')
plt.title("Frequency and Temporal Masked Log-Mel Spectrogram")
plt.colorbar(format='%+2.0f dB')

# Show the plots
plt.tight_layout()
plt.show()