generate_spectrogram.py•4.96 kB
#!/usr/bin/env python3
"""
Generate a beautiful high-resolution spectrogram of Bob Seger's analog waves
Focusing on 10-11 second range, up to 96kHz
"""
import numpy as np
import matplotlib.pyplot as plt
from scipy import signal
from scipy.io import wavfile
import matplotlib.colors as colors
from matplotlib.patches import Rectangle
# Read the high-res audio file
print("🎵 Loading Bob Seger analog waves at 192kHz/32-bit float...")
sample_rate, audio_data = wavfile.read('test_files/seger_192k_32f_stereo.wav')
# Handle stereo by taking left channel or converting to mono
if len(audio_data.shape) > 1:
audio_data = audio_data[:, 0] # Use left channel for spectrogram
print("📻 Using left channel from stereo recording")
print(f"📊 Sample rate: {sample_rate} Hz")
print(f"🎼 Total duration: {len(audio_data)/sample_rate:.2f} seconds")
# Extract 10-11 second range
start_sample = int(10 * sample_rate)
end_sample = int(11 * sample_rate)
segment = audio_data[start_sample:end_sample]
print(f"✂️ Extracting 10-11 second range ({len(segment)} samples)")
# Create high-resolution spectrogram
# Using high nperseg for frequency resolution and noverlap for time resolution
nperseg = 8192 # High frequency resolution
noverlap = nperseg - 256 # High time resolution
print("🌊 Computing high-resolution spectrogram up to 96kHz...")
frequencies, times, Sxx = signal.spectrogram(
segment,
fs=sample_rate,
window='blackmanharris', # Excellent for analog sources
nperseg=nperseg,
noverlap=noverlap,
nfft=16384, # Even higher FFT for smooth visualization
detrend='constant',
scaling='density'
)
# Limit to 96kHz as requested
freq_limit = 96000
freq_mask = frequencies <= freq_limit
frequencies = frequencies[freq_mask]
Sxx = Sxx[freq_mask, :]
# Convert to dB with careful handling of zeros
Sxx_db = 10 * np.log10(Sxx + 1e-10)
# Create beautiful figure with MEM|8 aesthetic
fig, ax = plt.subplots(figsize=(16, 10), dpi=150)
fig.patch.set_facecolor('#0a0a0a')
ax.set_facecolor('#0a0a0a')
# Custom colormap inspired by analog warmth and MEM|8 waves
cmap = plt.cm.get_cmap('magma') # Warm analog feel
cmap.set_bad(color='#0a0a0a')
# Plot spectrogram with improved dynamic range
vmin = np.percentile(Sxx_db[Sxx_db > -np.inf], 5)
vmax = np.percentile(Sxx_db[Sxx_db > -np.inf], 99.5)
im = ax.pcolormesh(
times,
frequencies/1000, # Convert to kHz
Sxx_db,
shading='gouraud', # Smooth shading for analog feel
cmap=cmap,
vmin=vmin,
vmax=vmax,
rasterized=True
)
# Add colorbar with style
cbar = plt.colorbar(im, ax=ax, pad=0.02)
cbar.set_label('Power Spectral Density (dB)', color='#FFD700', fontsize=11)
cbar.ax.yaxis.set_tick_params(color='#FFD700', labelcolor='#FFD700')
# Styling for that analog studio feel
ax.set_xlabel('Time (seconds) - 10s offset', fontsize=12, color='#FFD700')
ax.set_ylabel('Frequency (kHz)', fontsize=12, color='#FFD700')
ax.set_title(
'🎸 Bob Seger ~1980 Analog Pressing - 192kHz/32-bit Capture\n'
'10-11 Second Spectrogram (0-96kHz Range)\n'
'Smart Tree Audio Test File - MEM|8 Wave Analysis',
fontsize=14,
color='#FFD700',
pad=20
)
# Grid for precision
ax.grid(True, alpha=0.15, color='#FFD700', linestyle=':')
# Add frequency markers for key ranges
key_freqs = [
(0.002, "Sub-bass (2Hz calm)"),
(0.044, "MEM|8 baseline"),
(20, "Human hearing starts"),
(48, "CD quality limit"),
(96, "Analysis limit")
]
for freq, label in key_freqs:
if freq <= 96:
ax.axhline(y=freq, color='#00FF00', alpha=0.3, linestyle='--', linewidth=0.5)
if freq < 1:
ax.text(0.98, freq, label, transform=ax.get_yaxis_transform(),
fontsize=8, color='#00FF00', alpha=0.7, ha='right')
# Axis styling
ax.tick_params(colors='#FFD700', which='both')
ax.spines['bottom'].set_color('#FFD700')
ax.spines['left'].set_color('#FFD700')
ax.spines['top'].set_color('#FFD700')
ax.spines['right'].set_color('#FFD700')
# Set axis limits
ax.set_xlim(0, times[-1])
ax.set_ylim(0, 96)
# Add Smart Tree & Aye signature
fig.text(0.99, 0.01, 'Generated by Smart Tree v4.8.8 | Aye loves Elvis! 🎸 | 8b.is',
fontsize=9, color='#FFD700', alpha=0.7, ha='right')
# Save the beautiful spectrogram
output_file = 'test_files/seger_spectrogram_10-11s_96kHz.png'
plt.savefig(output_file,
facecolor='#0a0a0a',
edgecolor='none',
bbox_inches='tight',
dpi=150)
print(f"✨ Spectrogram saved to: {output_file}")
print("🎵 Analog waves preserved in digital beauty!")
# Also save a data file for Smart Tree quantum compression testing
np.savez_compressed('test_files/seger_spectrogram_data.npz',
frequencies=frequencies,
times=times,
spectrogram=Sxx_db,
sample_rate=sample_rate)
print("📊 Spectrogram data saved for quantum compression tests")
plt.show()