音频合成归一化后调用Spectrogram报错:TypeError: 'int'对象不可调用
问题分析与解决
问题概述
尝试合成三个numpy格式音频数据并执行max-min归一化后,在spec = spectrogram(sig)行触发TypeError: 'int' object is not callable,报错栈指向waveform.size()调用失败。
错误原因
- 输入类型不匹配:
torchaudio.transforms.Spectrogram要求输入为torch.Tensor,但代码中传入的sig是numpy数组。numpy数组的size是整数属性,而非可调用方法,内部代码调用.size()时触发类型错误。 - 维度不符合要求:合成后的
sig是一维数组,而torchaudio的频谱变换期望输入至少是二维(通道×时间)的张量结构。
修复方案
关键修改点
- 将归一化后的numpy数组转换为torch张量。
- 为张量添加通道维度,满足输入格式要求。
- 简化音频合成的补零逻辑,使用numpy原生
pad函数替代手动循环。
修复后的完整代码
import torch import torchaudio import torchaudio.transforms as T import os import numpy as np import librosa import matplotlib.pyplot as plt # 音声の保存 _SAMPLE_DIR = "_sample_data" SAMPLE_WAV_URL = "https://pytorch-tutorial-assets.s3.amazonaws.com/VOiCES_devkit/source-16k/train/sp0307/Lab41-SRI-VOiCES-src-sp0307-ch127535-sg0042.wav" SAMPLE_WAV_PATH = os.path.join(_SAMPLE_DIR, "speech.wav") def plot_spectrogram(spec, title=None, ylabel="freq_bin", aspect="auto", xmax=None): fig, axs = plt.subplots(1, 1) axs.set_title(title or "Spectrogram (db)") axs.set_ylabel(ylabel) axs.set_xlabel("frame") im = axs.imshow(librosa.power_to_db(spec), origin="lower", aspect=aspect) if xmax: axs.set_xlim((0, xmax)) fig.colorbar(im, ax=axs) plt.show(block=False) def synthesis(sigList): maxLength = max(len(data) for data in sigList) tmpArray = [] # 使用numpy.pad简化补零逻辑 for i in sigList: padded = np.pad(i, (0, maxLength - len(i)), mode='constant') tmpArray.append(padded) # 合成三个音频 sig = tmpArray[0] + tmpArray[1] + tmpArray[2] return sig def min_max(x, axis=None): min_val = x.min(axis=axis, keepdims=True) max_val = x.max(axis=axis, keepdims=True) try: z = (x - min_val) / (max_val - min_val) except ZeroDivisionError: z = (x - min_val) / min_val return z # 加载音频 waveform, sample_rate = torchaudio.load(filepath=SAMPLE_WAV_URL) n_fft = 1024 win_length = None hop_length = 512 window_fn = torch.hann_window # 生成三个音频数据 waveforms = waveform.numpy() k = waveforms for i in range(2): waveforms = np.concatenate([waveforms, k], 0) # 初始化频谱变换 spectrogram_transform = T.Spectrogram( n_fft=n_fft, win_length=win_length, hop_length=hop_length, window_fn=window_fn, power=2.0, ) # 合成、归一化、转换为张量并添加通道维度 sig = min_max(synthesis(waveforms)) sig_tensor = torch.tensor(sig).unsqueeze(0) # 添加通道维度,变为(1, time) # 生成频谱 spec = spectrogram_transform(sig_tensor) plot_spectrogram(spec[0], title='torchaudio')
修改说明
- 变量名优化:将原
spectrogram变量改为spectrogram_transform,提升代码可读性。 - 类型转换:使用
torch.tensor(sig)将numpy数组转换为torch张量,匹配频谱变换的输入要求。 - 维度调整:用
.unsqueeze(0)为张量添加通道维度,使输入形状符合(channel, time)的规范。 - 补零逻辑简化:使用
np.pad替代手动循环补零,代码更简洁高效。
内容的提问来源于stack exchange,提问作者assa
相关产品推荐
相关产品推荐

