已实现WAV与频谱图互转,求JPG频谱图转音频方法
从JPG频谱图还原音频(基于Griffin-Lim方法)
你已实现无损格式(32位Tiff)的频谱图还原,现在要解决JPG格式的近似还原问题,核心是将JPG像素值映射回原dB频谱范围、匹配原频谱维度,再用Griffin-Lim重建。以下是简便可行的方案:
一、改进的JPG频谱图生成流程
生成JPG时需记录原频谱的关键参数(dB范围、数组形状),否则还原时无法准确映射:
import librosa from matplotlib import pyplot as plt import librosa.display import numpy as np # 加载音频并生成dB频谱图 x, sr = librosa.load(librosa.ex('trumpet')) X = librosa.stft(x) Xdb = librosa.amplitude_to_db(abs(X)) # 记录关键参数:dB范围、频谱形状 np.save("db_range.npy", [Xdb.min(), Xdb.max()]) np.save("spec_shape.npy", Xdb.shape) # 绘制并保存JPG频谱图(保持参数一致) fig = plt.figure(figsize=(10, 10), dpi=1000, frameon=False) ax = fig.add_axes([0, 0, 1, 1], frameon=False) ax.axis('off') librosa.display.specshow(Xdb, sr=sr, cmap='gray', x_axis='time', y_axis='hz') plt.savefig("test.jpg", bbox_inches='tight', pad_inches=0) plt.close()
二、从JPG还原音频的流程
读取JPG后,将图像映射回原dB频谱数组,再用Griffin-Lim重建:
from PIL import Image import numpy as np import librosa import soundfile as sf # 读取保存的参数 min_db, max_db = np.load("db_range.npy") spec_shape = np.load("spec_shape.npy") sr = librosa.get_samplerate(librosa.ex('trumpet')) # 或直接使用原采样率(如22050) # 读取JPG并调整为原频谱形状 img = Image.open("test.jpg").convert('L') # 转为8位灰度图 # 图像宽对应时间轴(Xdb第二维),高对应频率轴(Xdb第一维),resize顺序为(宽度, 高度) img_resized = img.resize((spec_shape[1], spec_shape[0])) img_array = np.array(img_resized) # 将0-255像素值线性映射回原dB范围 recspec = np.interp(img_array, [0, 255], [min_db, max_db]) # 转换为幅度谱并重建音频 X2 = librosa.db_to_amplitude(recspec) audio = librosa.griffinlim(X2) # 保存还原后的音频 sf.write("recovered_from_jpg.wav", audio, sr)
关键注意事项
- 参数一致性:生成与还原时的
cmap必须一致(此处用gray),否则颜色映射会出错。 - 维度匹配:必须将JPG图像resize回原频谱数组的形状,否则Griffin-Lim无法正确重建时间序列。
- dB范围映射:JPG是8位灰度图(0-255),需线性映射回原频谱的dB范围,不能直接用像素值代替dB值。
- 质量损失:由于JPG的有损压缩,还原后的音频会有一定失真,但Griffin-Lim能保证整体音色与原音频近似。
内容的提问来源于stack exchange,提问作者Dave Cooper
相关产品推荐
相关产品推荐

