尝试使用 Python 绘制 wav 文件的信号幅度时出现“ValueError:x 和 y 必须具有相同的第一维”

问题描述 投票:0回答:1

使用 Python,我试图绘制一个 wav 文件的信号幅度,但是我收到以下错误“ValueError:x 和 y 必须具有相同的第一维”。这是我的代码:

import wave
import matplotlib.pyplot as plt
import numpy as np

wav_obj = wave.open("loop.wav", "rb")

sample_freq = wav_obj.getframerate()
n_samples = wav_obj.getnframes()
t_audio = n_samples/sample_freq
n_channels = wav_obj.getnchannels()
signal_wave = wav_obj.readframes(n_samples)

signal_array = np.frombuffer(signal_wave, dtype=np.int16)
l_channel = signal_array[0::2]
r_channel = signal_array[1::2]

times = np.linspace(0, t_audio, num=n_samples)

plt.figure(figsize=(15, 5))
plt.plot(times, l_channel)
plt.title('Left Channel')
plt.ylabel("Signal Value")
plt.xlabel("Time in seconds")
plt.xlim(0, t_audio)
plt.show

我知道我的 signal_array 的形状应该等于 (n_samples * n_channels),但事实并非如此,我也不知道为什么。现在 signal_array 的形状是 1076340,并且 (n_samples * n_channels) 是 717560.

我尝试使用不同的 wav 文件,但我得到了同样的错误。

更新: 我有更多的见解,我的 wav 文件是立体声的,所以它有 2 个通道。 “signal_array”的形状实际上是 (n_samples * 3),这是因为 wav 文件的样本宽度是 3。因此我的“l_channel”的形状实际上是 (times * 1.5)。

所以我现在的问题是,如何考虑样本宽度为 3?我应该如何处理我的数组,使它们最终等于我的“时间”数组的形状?

python audio-processing
1个回答
0
投票

这实际上有点复杂,因为一个 24 位(每个样本 3 个字节)文件没有匹配的 Numpy 数据类型。

如果你想自己做,你需要做类似的事情:

  1. Reshape 单字节的 Numpy 数组为 3 字节的批次
  2. 添加一列额外的零以填充到 32 位。
  3. 将批次重新解释为 32 位整数。
这段代码展示了如何处理大端数据(在开头填充,并在数据类型中使用

>

):

data = np.frombuffer(signal_wave, dtype=np.uint8) samples = data.reshape((n_samples * n_channels, sample_width)) padding = np.zeros((n_samples * n_channels, 1), dtype=np.uint8) padded_samples = np.hstack((padding, samples)) int_samples = padded_samples.view('>u4').flatten() samples_l = int_samples[::2]

有关详细信息,请参阅此笔记本。这仍然不是一个完整的解决方案,因为它不适用于有符号整数(我认为 PCM 数据已签名)。显然你可以用 as_strided 做一个技巧,但它很危险(允许访问数组外的内存)。

所以如果可以的话,

使用scipy.io.wavfile.read代替.

© www.soinside.com 2019 - 2024. All rights reserved.