一体化音乐结构分析器
该软件包提供了用于音乐结构分析的模型,可以预测:
- 速度(BPM)
- 节拍
- 强拍
- 功能段落边界
- 功能段落标签(如前奏、主歌、副歌、间奏、尾声)
目录
安装
1. 安装 PyTorch
访问 PyTorch 并为您的系统安装适当版本。
2. 安装 NATTEN(Linux 和 Windows 必需;macOS 将自动安装)
- Linux:从 NATTEN 网站 下载
- macOS:随
allin1
自动安装。 - Windows:从源代码构建:
pip install ninja # 推荐,非必需
git clone https://github.com/SHI-Labs/NATTEN
cd NATTEN
make
3. 安装软件包
pip install git+https://github.com/CPJKU/madmom # 直接从 GitHub 安装最新版 madmom
pip install allin1 # 安装此软件包
4. (可选)安装 FFmpeg 以支持 MP3
Ubuntu:
sudo apt install ffmpeg
macOS:
brew install ffmpeg
命令行使用方法
分析音频文件:
allin1 your_audio_file1.wav your_audio_file2.mp3
结果默认保存在 ./struct
目录下:
./struct
└── your_audio_file1.json
└── your_audio_file2.json
分析结果将以 JSON 格式保存:
{
"path": "/path/to/your_audio_file.wav",
"bpm": 100,
"beats": [ 0.33, 0.75, 1.14, ... ],
"downbeats": [ 0.33, 1.94, 3.53, ... ],
"beat_positions": [ 1, 2, 3, 4, 1, 2, 3, 4, 1, ... ],
"segments": [
{
"start": 0.0,
"end": 0.33,
"label": "start"
},
{
"start": 0.33,
"end": 13.13,
"label": "intro"
},
{
"start": 13.13,
"end": 37.53,
"label": "chorus"
},
{
"start": 37.53,
"end": 51.53,
"label": "verse"
},
...
]
}
所有可用选项如下:
$ allin1 -h
用法: allin1 [-h] [-o OUT_DIR] [-v] [--viz-dir VIZ_DIR] [-s] [--sonif-dir SONIF_DIR] [-a] [-e] [-m MODEL] [-d DEVICE] [-k]
[--demix-dir DEMIX_DIR] [--spec-dir SPEC_DIR]
paths [paths ...]
位置参数:
paths 音轨路径
选项:
-h, --help 显示此帮助信息并退出
-o OUT_DIR, --out-dir OUT_DIR
存储分析结果的目录路径(默认:./struct)
-v, --visualize 保存可视化结果(默认:False)
--viz-dir VIZ_DIR 提供 -v 选项时保存可视化结果的目录(默认:./viz)
-s, --sonify 保存声音化结果(默认:False)
--sonif-dir SONIF_DIR
提供 -s 选项时保存声音化结果的目录(默认:./sonif)
-a, --activ 保存来自 sigmoid 和 softmax 的帧级原始激活(默认:False)
-e, --embed 保存帧级嵌入(默认:False)
-m MODEL, --model MODEL
使用的预训练模型名称(默认:harmonix-all)
-d DEVICE, --device DEVICE
使用的设备(默认:如果可用则为 cuda,否则为 cpu)
-k, --keep-byproducts
保留分离的音频文件和频谱图(默认:False)
--demix-dir DEMIX_DIR
存储分离音轨的目录路径(默认:./demix)
--spec-dir SPEC_DIR 存储频谱图的目录路径(默认:./spec)
Python 使用方法
可用功能:
analyze()
分析提供的音频文件并返回分析结果。
import allin1
# 你可以分析单个文件:
result = allin1.analyze('your_audio_file.wav')
# 或多个文件:
results = allin1.analyze(['your_audio_file1.wav', 'your_audio_file2.mp3'])
结果是一个包含以下内容的数据类实例:
AnalysisResult(
path='/path/to/your_audio_file.wav',
bpm=100,
beats=[0.33, 0.75, 1.14, ...],
beat_positions=[1, 2, 3, 4, 1, 2, 3, 4, 1, ...],
downbeats=[0.33, 1.94, 3.53, ...],
segments=[
Segment(start=0.0, end=0.33, label='start'),
Segment(start=0.33, end=13.13, label='intro'),
Segment(start=13.13, end=37.53, label='chorus'),
Segment(start=37.53, end=51.53, label='verse'),
Segment(start=51.53, end=64.34, label='verse'),
Segment(start=64.34, end=89.93, label='chorus'),
Segment(start=89.93, end=105.93, label='bridge'),
Segment(start=105.93, end=134.74, label='chorus'),
Segment(start=134.74, end=153.95, label='chorus'),
Segment(start=153.95, end=154.67, label='end'),
]),
与命令行界面不同,默认情况下不会将结果保存到磁盘。你可以按以下方式保存结果:
result = allin1.analyze(
'your_audio_file.wav',
out_dir='./struct',
)
参数:
-
paths
:Union[PathLike, List[PathLike]]
要分析的音频文件的路径列表或单个路径。 -
out_dir
:PathLike
(可选)
保存分析结果的目录路径。默认情况下,结果不会被保存。 -
visualize
:Union[bool, PathLike]
(可选)
是否可视化分析结果。如果提供路径,可视化结果将保存在该目录中。默认为False。如果为True,可视化结果将保存在'./viz'中。 -
sonify
:Union[bool, PathLike]
(可选)
是否将分析结果转换为音频。如果提供路径,音频化结果将保存在该目录中。默认为False。如果为True,音频化结果将保存在'./sonif'中。 -
model
:str
(可选)
用于分析的预训练模型名称。默认为'harmonix-all'。请参阅文档了解可用的模型。 -
device
:str
(可选)
用于计算的设备。默认为'cuda'(如果可用),否则为'cpu'。 -
include_activations
:bool
(可选)
是否在分析结果中包含激活信息。 -
include_embeddings
:bool
(可选)
是否在分析结果中包含嵌入信息。 -
demix_dir
:PathLike
(可选)
保存源分离音频的目录路径。默认为'./demix'。 -
spec_dir
:PathLike
(可选)
保存频谱图的目录路径。默认为'./spec'。 -
keep_byproducts
:bool
(可选)
是否保留源分离音频和频谱图。默认为False。 -
multiprocess
:bool
(可选)
是否使用多进程提取频谱图。默认为True。
返回:
Union[AnalysisResult, List[AnalysisResult]]
提供的音频文件的分析结果。
load_result()
从磁盘加载分析结果。
result = allin1.load_result('./struct/24k_Magic.json')
visualize()
可视化分析结果。
fig = allin1.visualize(result)
fig.show()
参数:
-
result
:Union[AnalysisResult, List[AnalysisResult]]
要可视化的分析结果列表或单个分析结果。 -
out_dir
:PathLike
(可选)
保存可视化结果的目录路径。默认情况下,可视化结果不会被保存。
返回:
Union[Figure, List[Figure]]
包含可视化结果的图形列表或单个图形。Figure
是matplotlib.pyplot
中的一个类。
sonify()
将分析结果转换为音频。 它会将节拍和强拍的节拍器点击声,以及段落边界的事件声音混合到原始音频文件中。
y, sr = allin1.sonify(result)
# y: 形状为(channels=2, samples)的音频化结果
# sr: 采样率(=44100)
参数:
result
:Union[AnalysisResult, List[AnalysisResult]]
要转换为音频的分析结果列表或单个分析结果。out_dir
:PathLike
(可选)
保存音频化结果的目录路径。默认情况下,音频化结果不会被保存。
返回:
Union[Tuple[NDArray, float], List[Tuple[NDArray, float]]]
包含音频化结果和采样率的元组列表或单个元组。
可视化与声音化
此软件包提供了一个简单的可视化(-v
或 --visualize
)和声音化(-s
或 --sonify
)功能来展示分析结果。
allin1 -v -s 您的音频文件.wav
默认情况下,可视化结果将保存在 ./viz
目录中:
./viz
└── 您的音频文件.pdf
声音化结果将默认保存在 ./sonif
目录中:
./sonif
└── 您的音频文件.sonif.wav
例如,可视化结果如下所示:
您可以在 Hugging Face Space 上尝试。
可用模型
这些模型在 Harmonix Set 上进行了8折交叉验证训练。 更多详细信息,请参阅 论文。
harmonix-all
:(默认)一个集成模型,平均了在每个折上训练的8个模型的预测结果。harmonix-foldN
:在第N折(0~7)上训练的模型。例如,harmonix-fold0
是在第0折上训练的。
默认使用 harmonix-all
模型。要使用不同的模型,请使用 --model
选项:
allin1 --model harmonix-fold0 您的音频文件.wav
速度
使用RTX 4090 GPU和Intel i9-10940X CPU(14核心,28线程,3.30 GHz),
harmonix-all
模型在73秒内处理了10首歌曲(33分钟)。
研究用高级用法
该软件包为研究人员提供了高级选项,可以提取帧级原始激活值和嵌入向量,无需后处理。这些数据的分辨率为100 FPS,相当于每帧0.01秒。
命令行界面
激活值
--activ
选项还会保存来自sigmoid和softmax的帧级原始激活值:
$ allin1 --activ 您的音频文件.wav
您可以在 .npz
文件中找到激活值:
./struct
└── 您的音频文件1.json
└── 您的音频文件1.activ.npz
在Python中加载激活值:
>>> import numpy as np
>>> activ = np.load('./struct/您的音频文件1.activ.npz')
>>> activ.files
['beat', 'downbeat', 'segment', 'label']
>>> beat_activations = activ['beat']
>>> downbeat_activations = activ['downbeat']
>>> segment_boundary_activations = activ['segment']
>>> segment_label_activations = activ['label']
激活值的详细信息如下:
beat
:来自sigmoid层的用于节拍跟踪的原始激活值(形状:[时间步]
)downbeat
:来自sigmoid层的用于强拍跟踪的原始激活值(形状:[时间步]
)segment
:来自sigmoid层的用于段落边界检测的原始激活值(形状:[时间步]
)label
:来自softmax层的用于段落标签分类的原始激活值(形状:[标签类别=10, 时间步]
)
您可以如下访问标签名称:
>>> allin1.HARMONIX_LABELS
['start',
'end',
'intro',
'outro',
'break',
'bridge',
'inst',
'solo',
'verse',
'chorus']
嵌入向量
该软件包还提供了从模型中提取原始嵌入向量的选项。
$ allin1 --embed 您的音频文件.wav
您可以在 .npy
文件中找到嵌入向量:
./struct
└── 您的音频文件1.json
└── 您的音频文件1.embed.npy
在Python中加载嵌入向量:
>>> import numpy as np
>>> embed = np.load('您的音频文件1.embed.npy')
每个模型为每个时间步的每个源分离音轨嵌入,
resulting in embeddings shaped as [stems=4, time_steps, embedding_size=24]
:
- 源分离音轨的数量(顺序为低音、鼓、其他、人声)。
- 时间步(帧)的数量。时间步为0.01秒(100 FPS)。
- 嵌入向量大小为24。
使用 --embed
选项和 harmonix-all
集成模型会堆叠嵌入向量,
保存形状为 [stems=4, time_steps, embedding_size=24, models=8]
的向量。
Python
Python API allin1.analyze()
提供了与CLI相同的选项:
>>> allin1.analyze(
paths='您的音频文件.wav',
include_activations=True,
include_embeddings=True,
)
AnalysisResult(
path='/path/to/您的音频文件.wav',
bpm=100,
beats=[...],
downbeats=[...],
segments=[...],
activations={
'beat': array(...),
'downbeat': array(...),
'segment': array(...),
'label': array(...)
},
embeddings=array(...),
)
关于MP3文件
由于解码器的差异,MP3文件可能会有轻微的偏移差异。 我建议您首先使用FFmpeg将音频文件转换为WAV格式(如下所示), 并在所有数据处理流程中使用WAV文件。
ffmpeg -i 您的音频文件.mp3 您的音频文件.wav
在这个软件包中,音频文件是使用 Demucs 读取的。 据我所知,Demucs 在读取MP3文件之前会使用FFmpeg将其转换为WAV。 然而,使用不同的MP3解码器可能会产生不同的偏移。 我观察到大约20~40毫秒的变化,这对于需要精确计时的任务(如节拍跟踪)来说是有问题的, 而传统的容忍度仅为70毫秒。 因此,我建议将所有数据处理的输入标准化为WAV格式, 确保解码的一致性。
训练
请参考 TRAINING.md。
引用
如果您在研究中使用了此软件包,请引用以下论文:
@inproceedings{taejun2023allinone,
title={基于分离音频的邻域注意力机制的一体化节奏和功能结构分析},
author={Kim, Taejun and Nam, Juhan},
booktitle={IEEE音频和声学信号处理应用研讨会(WASPAA)},
year={2023}
}