【发布时间】:2021-04-13 13:53:11
【问题描述】:
我正在尝试制作一个小脚本来在 python 中生成一些音频文件的可视化。 我的最终目标是生成一个 30fps 的视频,该视频由在 python 中生成的图像整理而成,组装一些图像资产。但我对声音分析部分有点坚持,因为我对声音及其背后的物理和数学几乎一无所知。 无论如何。为了在 python 中处理导入声音,我使用了 librosa,它看起来非常强大。
import librosa
import numpy as np
#load an example audio
filename = librosa.ex('trumpet')
y, sr = librosa.load(filename, sr=44100)
#apply short-time Fourier transform
stft = np.abs(librosa.stft(y, n_fft=1024, hop_length=None, win_length=None, window='hann', center=True, dtype=None, pad_mode='reflect'))
# converting the matrix to decibel matrix
D = librosa.amplitude_to_db(stft, ref=np.max)
通过这种方式,我获得了一个形状为(513,480) 的矩阵D,这意味着频率范围内有 513 个“步”和 480 个数据点或帧。鉴于样本的持续时间约为 5.3 秒,这使其约为每秒 172.3 帧。
因为我想要 30fps,所以我决定对采样率进行一些试验和错误,直到达到 23038。在加载文件时应用它:
y, sr = librosa.load(filename, sr=23038)
我获得了 89.998 fps 的帧速率,这似乎更适合我的目的。 因此,我继续降低数据的分辨率,平均我在 9 个“桶”中的频率读数:
#Initialize new empty array of target size
nD = np.empty(shape=(9,D.shape[1]))
#populate new array
for i in range(D.shape[1]):
nD[:,i] = D[:,i].reshape(-1, 57).mean(axis=1)
这里的 9 来自于我可以得到的一个数字除以 57,这是一个因素 513 个。 因此,我将 3 帧聚合在一起以达到我的 30fps:
count = 0
for i in range(0, nD.shape[1],3):
try:
nnD[:,count] = nD[:,i:i+3].reshape(-1, 3).mean(axis=1)
count+=1
except Exception:
pass
这似乎完全是 hacky,try except 部分在那里,因为有时我有索引错误,并且计数递增计数器似乎很愚蠢。 但令人难以置信的是似乎以某种方式起作用。 出于测试目的,我做了一个可视化例程
from time import sleep
from os import system
nnD = ((nnD+80)/10).astype(int)
for i in range(nnD.shape[1]):
for j in range(nnD.shape[0]):
print ("#"*nnD[j,i])
sleep(1/30)
system('clear')
在终端中显示由 # 组成的行。
现在,我的问题是:
我怎样才能以正确的方式做到这一点?
更具体地说:
1_有没有办法在不破坏采样率的情况下匹配傅立叶数据的帧速率?
2_有没有更合适的方法来聚合我的数据,可能是任意数字,而不是必须在 513 的因子之间进行选择?
【问题讨论】:
-
您真正想要的是调整
stft()call'sn_fftandhop_length以调整分析包含的“即时”数量。 -
@AKX 我想过这个,但我无法弄清楚“反向公式”是什么。