Python librosa错误 "音频缓冲区不是Fortran-contiguous"

1 人关注

我正在使用 librosa

只有 load stft ,我遇到了错误。 Audio buffer is not Fortran-contiguous

我在网上搜索了一下,发现我需要添加 np.asfortranarray ,所以我添加了这些句子,但是徒劳无功。

a, sr = librosa.load("mywave.wav",sr=self.sr,mono=False)
print(a.shape) #(2, 151199)
a[0] = np.asfortranarray(a[0])# try to avoide Fortran-contiguous
a[1] = np.asfortranarray(a[1])
# but this returns error
#Audio buffer is not Fortran-contiguous. Use numpy.asfortranarray to ensure Fortran contiguity.    
stft_L = librosa.stft(a[0], n_fft=self.stft_frame,hop_length= self.hop_frame, window='hann') 

在我第一次做这个代码的时候,(可能是半年前),它是有效的。

有什么解决办法吗?

python
numpy
audio
librosa
whitebear
whitebear
发布于 2021-09-14
1 个回答
Nils Werner
Nils Werner
发布于 2021-09-14
0 人赞同

你误解了什么是C-与Fortran-连续的内存布局,以及这意味着你能做和不能做什么。例如,改变一个数组中某一行的内存布局

a[0] = np.asfortranarray(a[0])

是没有意义的,因为内存布局决定了一行是什么

为了说明这一点,让我们看一下一些Fortran的连续数据

x = np.asfortranarray(np.arange(12).reshape(3, 4))
x.flags.f_contiguous
# True
# array([[ 0,  1,  2,  3],
#        [ 4,  5,  6,  7],
#        [ 8,  9, 10, 11]])

在内部,这个二维数组当然是线性保存的,C-/Fortran-contigouity决定了是行还是列在前。

x.flatten('A')
# array([ 0,  4,  8,  1,  5,  9,  2,  6, 10,  3,  7, 11])
np.asfortranarray(x).flatten('A')
# array([ 0,  4,  8,  1,  5,  9,  2,  6, 10,  3,  7, 11])
np.ascontiguousarray(x).flatten('A')
# array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])

Fortran内存布局是列优先,也就是说,列在内存中保持一致。C-内存是行优先,即行在内存中保持在一起。

真正令人困惑的是,阵列中的视图可以是连续的,也可以不是。

x.flags.f_contiguous, x[0].flags.f_contiguous
# (True, False)

x 显然是连续的,但是 不是。这是因为 ,在内存中不是彼此相邻的。x[0] [0, 1, 2, 3]

你试图做的事情

a = x.copy('A')
a.flags.f_contiguous, a[0].flags.f_contiguous
# (True, False)
a[0] = np.asfortranarray(a[0])
a[1] = np.asfortranarray(a[1])
a.flags.f_contiguous, a[0].flags.f_contiguous
# (True, False)

不会起作用,因为改变单行的布局是没有意义的。

现在,令人困惑的部分来了。如果你有一个Fortran-contiguous数组,并且你希望第一行是Fortran-contiguous的,你不能把数组改成Fortran-contiguous。

a = x.copy('A')
a = np.asfortranarray(a)
a.flags.f_contiguous, a[0].flags.f_contiguous
# (True, False)

因为列是连续的,但行不是。

如果你把数组改为C-contigous

a = x.copy('A')
a = np.ascontiguousarray(a)
a.flags.f_contiguous, a[0].flags.f_contiguous
# (False, True)

这意味着行现在是连续的。

另一个解决方案是简单地复制数据

a = x.copy('A')
a[0].copy().flags.f_contiguous
# True

因为拷贝会将数据写入一个新的、线性的、连续的数组中。