如何用librosa在循环中计算并绘制多段音频语谱图
解决方案
步骤1:确保音频正确分割(若未完成)
如果还没将16秒音频分割为16段1秒信号,可通过以下代码实现:
import librosa import numpy as np import matplotlib.pyplot as plt # 加载音频,保留原始采样率 y, sr = librosa.load("your_audio_file.wav", sr=None) # 按1秒长度分割音频(每段样本数=采样率sr) segment_length = sr segment = [y[i*segment_length : (i+1)*segment_length] for i in range(16)]
步骤2:绘制分段语谱图(适配目标布局)
基于你提供的原始信号绘图代码,修改为绘制语谱图的版本,完全匹配4×4的子图布局:
ncols = 4 nrows = 4 # 16段刚好4行4列,无需额外计算 fig = plt.figure(figsize=(22, 19)) plt.subplots_adjust(hspace=0.5, wspace=0.4) plt.suptitle('Spectrograms of Segmented Audio', fontweight='bold', size=20) for i in range(16): # 获取当前分段音频 current_segment = segment[i] # 计算短时傅里叶变换并转换为分贝刻度的语谱图 stft_result = librosa.stft(current_segment) spec_db = librosa.amplitude_to_db(np.abs(stft_result), ref=np.max) # 创建子图 ax = plt.subplot(nrows, ncols, i+1) # 绘制语谱图,自动映射时间和频率轴 img = librosa.display.specshow(spec_db, sr=sr, x_axis='time', y_axis='hz', ax=ax) # 设置子图标题和坐标轴标签 ax.set_title(f'Segment: {i+1}', fontweight='bold', size=15) ax.set_xlabel('Time (s)', fontweight='bold') ax.set_ylabel('Frequency (Hz)', fontweight='bold') # 调整布局,避免标题被截断 fig.tight_layout(rect=[0, 0, 1, 0.96]) # 添加全局颜色条,统一表示分贝幅度 fig.colorbar(img, ax=fig.axes, shrink=0.8, label='Amplitude (dB)') plt.show()
关键细节说明
librosa.stft:对单段音频做短时傅里叶变换,得到频率-时间维度的幅度矩阵。librosa.amplitude_to_db:将线性幅度转换为分贝刻度,更符合人耳对声音的感知特性。librosa.display.specshow:专门用于绘制频谱类可视化,自动根据采样率生成时间和频率轴的刻度,无需手动计算。- 全局颜色条:避免每个子图单独添加颜色条导致布局拥挤,让所有子图共享同一个幅度参考。
内容的提问来源于stack exchange,提问作者Malahat Mehraban
相关产品推荐
相关产品推荐

