Guitar Pro 文件解析、渲染与音频播放引擎库
ApolloTab 是一个功能完整的 Python 库,用于解析、渲染和播放 Guitar Pro (.gp3/.gp4/.gp5/.gpx/.gp) 格式的吉他谱文件。
核心功能
- 文件解析: 完整支持 GP3/GP4/GP5/GPX/GP(GP7/GP8) 格式,提取歌曲信息、音轨、小节、音符、技巧标记
- 智能调度:
parse_score()根据文件扩展名自动选择对应解析器 - 六线谱渲染: 使用 QPainter 将乐谱数据渲染为高质量六线谱图像(QPixmap),支持多页输出
- 音频播放: 基于 FluidSynth 的 MIDI 合成引擎,支持 SoundFont 音色库实时播放,含 Bank Select + Program Change
- 反复记号: 完整支持反复记号(
||:/:||)展开与播放光标同步 - 节拍器: 内置节拍器功能,独立 MIDI 通道(15),可配置音量和拍号
- 动态主题注册: 运行时主题注册
ThemeConfig.register_theme(),支持自定义配色方案 - 技巧支持: 18种演奏技巧(击弦、勾弦、推弦、滑音、泛音、颤音等)
- 高度可配置: 渲染参数完全可调(线宽、间距、颜色、字体等)
- 主题支持: 内置黑白/深色配色方案,支持自定义主题扩展
安装
从 PyPI 安装(推荐)
pip install ApolloTab
从源码安装
# 克隆仓库
git clone https://github.com/your-repo/ApolloTab.git
cd ApolloTab
# 安装依赖
pip install -e .
# 或安装开发环境(含测试工具)
pip install -e ".[dev]"
快速开始
1. 解析 GTP 文件
from ApolloTab import parse_gtp
# 解析 Guitar Pro 文件
song = parse_gtp("my_song.gp5")
# 查看基本信息
print(f"标题: {song.title}")
print(f"艺术家: {song.artist}")
print(f"BPM: {song.tempo}")
print(f"音轨数: {song.track_count}")
# 遍历音轨
for track in song.tracks:
print(f"\n音轨: {track.name}")
print(f"调弦: {track.strings}")
print(f"小节数: {len(track.measures)}")
2. 渲染六线谱图像
from ApolloTab import render_gtp
# 一键渲染(返回多页 QPixmap 列表)
pages = render_gtp("my_song.gp5", track_index=0)
# pages 是 List[QPixmap],每页一张图片
for i, page in enumerate(pages):
page.save(f"output_page_{i + 1}.png")
print(f"已保存第 {i + 1} 页")
# 或者使用 TabRenderer 类进行更精细的控制
from ApolloTab import TabRenderer, RenderConfig
# 自定义渲染配置
config = RenderConfig(
page_width=2480, # 页面宽度(px),调整效果: 越大越清晰但内存占用更多
page_height=3508, # 页面高度(px),A4@300dpi标准尺寸
line_color="#000000", # 弦线颜色
)
renderer = TabRenderer(config=config)
pages = renderer.render(song, track_index=0)
# 访问布局数据(用于播放光标等功能)
layouts = renderer.last_layouts # List[PageLayout]
3. 音频播放
from ApolloTab import (
parse_gtp,
MidiConverter,
SynthEngine,
)
# 解析文件
song = parse_gtp("my_song.gp5")
# 转换为 MIDI 事件序列
converter = MidiConverter()
events = converter.convert(song, track_index=0)
# 初始化音频引擎
engine = SynthEngine()
engine.initialize() # 初始化 FluidSynth 合成器
engine.load_soundfont() # 自动搜索并加载 SoundFont
engine.set_instrument(0, 27) # 设置通道0为电吉他(MIDI程序号27)
# 加载事件并播放
engine.load_events(events, bpm=song.tempo)
engine.play()
# 控制播放
import time
time.sleep(5) # 播放5秒
engine.pause()
time.sleep(2) # 暂停2秒
engine.resume()
time.sleep(5) # 继续播放5秒
# 停止并清理
engine.stop()
4. 完整示例:解析 → 渲染 → 播放
from ApolloTab import (
parse_gtp,
TabRenderer,
MidiConverter,
SynthEngine,
RenderConfig,
)
def process_gtp_file(file_path: str, track_index: int = 0):
"""
完整处理流程:解析 → 渲染 → 播放
参数:
file_path: .gp3/.gp4/.gp5/.gpx 文件路径
track_index: 要处理的音轨索引(默认第1条)
"""
# ===== 步骤1: 解析 =====
print(f"[1/3] 正在解析: {file_path}")
song = parse_gtp(file_path)
print(f" ✓ 标题: {song.title}, BPM: {song.tempo}")
# ===== 步骤2: 渲染 =====
print("[2/3] 正在渲染六线谱...")
renderer = TabRenderer(RenderConfig())
pages = renderer.render(song, track_index=track_index)
for i, page in enumerate(pages):
output_file = f"{song.title}_track{track_index}_p{i + 1}.png"
page.save(output_file)
print(f" ✓ 已保存: {output_file} ({page.width()}x{page.height()}px)")
# ===== 步骤3: 播放 =====
print("[3/3] 正在初始化音频...")
converter = MidiConverter()
events = converter.convert(song, track_index=track_index)
engine = SynthEngine()
engine.initialize()
engine.load_soundfont()
engine.set_instrument(0, 27)
engine.load_events(events, bpm=song.tempo)
print(" ▶ 开始播放 (按 Ctrl+C 停止)...")
engine.play()
try:
while engine.is_playing:
time.sleep(0.1)
except KeyboardInterrupt:
print("\n ⏹ 停止播放")
engine.stop()
# 使用示例
if __name__ == "__main__":
import sys
if len(sys.argv) < 2:
print("用法: python example.py <文件路径.gp5> [音轨索引]")
sys.exit(1)
file_path = sys.argv[1]
track_index = int(sys.argv[2]) if len(sys.argv) > 2 else 0
process_gtp_file(file_path, track_index)
API 参考
核心函数
| 函数 | 说明 | 返回值 |
|---|---|---|
parse_gtp(path) |
解析GTP文件 | GTPSong |
parse_score(path) |
智能调度(自动识别格式) | GTPSong |
render_gtp(path, track_index) |
一键渲染GTP文件 | List[QPixmap] |
主要类
数据模型 (ApolloTab.models)
| 类名 | 说明 |
|---|---|
GTPSong |
歌曲对象(标题/艺术家/BPM/音轨列表) |
GTPTrack |
音轨对象(名称/调弦/小节列表) |
GTPMeasure |
小节对象(拍号/重复记号/拍列表) |
GTPBeat |
拍对象(时值/附点/音符列表) |
GTPNote |
音符对象(品格/弦/MIDI音高/技巧) |
解析器 (ApolloTab.parser)
| 类 | 说明 |
|---|---|
GTPParser |
GTP文件解析器类 (GP3/GP4/GP5/GPX) |
GP7Parser |
GP7/GP8 (.gp) ZIP解包解析器 |
GpifParser |
GP7/GP8 GPIF XML内容解析器 |
BinaryStylesheet |
GP7/GP8 二进制样式表解析器 |
PartConfiguration |
GP7/GP8 声部配置解析器 |
parse_score(path) |
智能调度(根据扩展名自动选择) |
用法:
from ApolloTab import parse_score
# 根据扩展名自动识别格式
song = parse_score("song.gp") # GP7/GP8
song = parse_score("song.gp5") # GP5
song = parse_score("song.gpx") # GPX
# 或直接指定解析器
from ApolloTab.parser import GTPParser, GP7Parser
parser = GTPParser()
song = parser.parse("song.gp5")
gp7 = GP7Parser()
song = gp7.parse("song.gp")
渲染器 (ApolloTab.renderer)
| 类名 | 说明 |
|---|---|
TabRenderer |
六线谱渲染引擎 |
TabLayoutEngine |
布局计算引擎 |
用法:
from ApolloTab.renderer import TabRenderer, RenderConfig
renderer = TabRenderer(RenderConfig())
pages = renderer.render(song, track_index=0)
音频引擎 (ApolloTab.audio)
| 类名 | 说明 |
|---|---|
MidiConverter |
GTP数据→MIDI事件转换器 |
SynthEngine |
FluidSynth音频合成引擎 |
MidiEvent |
单个MIDI事件数据模型 |
MetronomeConfig |
节拍器配置(启用、音量、拍号) |
MetronomeGenerator |
节拍器MIDI事件生成器 |
用法:
from ApolloTab.audio import (
MidiConverter, SynthEngine,
MetronomeConfig, MetronomeGenerator,
)
converter = MidiConverter()
events = converter.convert(song, track_index=0)
engine = SynthEngine()
engine.initialize()
engine.load_soundfont()
engine.load_events(events, bpm=song.tempo) # 主事件流(不再混入节拍器)
engine.play()
# [v1.4.0] 节拍器事件独立加载:通过独立线程播放,不与主事件流混合
# 切换节拍器开关/音量时无需重建主事件
config = MetronomeConfig(enabled=True, volume=0.8, gain=1.5)
ticks_per_beat = 480
metro_events = MetronomeGenerator.generate_for_song(
song=song, track_index=0, config=config,
expanded_indices=converter.expand_measure_indices(song.tracks[0].measures),
ticks_per_beat=ticks_per_beat,
)
engine.load_metronome_events(
events=metro_events, bpm=song.tempo, ticks_per_beat=ticks_per_beat,
)
# 关闭:engine.unload_metronome_events()
工具 (ApolloTab.utils)
| 类/常量 | 说明 |
|---|---|
RenderConfig |
渲染参数配置(全部可调) |
ThemeConfig |
渲染主题配置(配色方案) |
TechniqueType |
技巧类型枚举(18种) |
StandardTunings |
标准调弦定义 |
NoteDuration |
时值枚举 |
配置说明
ThemeConfig - 渲染主题
ApolloTab 支持多套内置配色方案,适用于不同使用场景:
from ApolloTab import TabRenderer, ThemeConfig
# 获取预设主题
light_theme = ThemeConfig.get_theme("light") # 黑白配色(适合打印)
dark_theme = ThemeConfig.get_theme("dark") # 深色配色(护眼模式)
# 列出所有可用主题
available = ThemeConfig.list_themes() # ["light", "dark"]
# 使用主题
renderer = TabRenderer()
renderer.set_theme("light") # 通过名称切换
renderer.set_theme(dark_theme) # 通过实例切换
# 或在初始化时指定
config = RenderConfig(theme=ThemeConfig.get_theme("light"))
renderer = TabRenderer(config)
# 自定义主题(可扩展)
my_theme = ThemeConfig(
colors={
"COLOR_BG": "#FFFDE7", # 米黄色背景
"COLOR_TEXT": "#212121", # 近黑色文字
# ... 其他颜色参数(可选,缺失的使用深色主题默认值)
},
theme_name="sepia" # 自定义名称
)
renderer.set_theme(my_theme)
内置主题:
| 主题名称 | 背景色 | 文字色 | 适用场景 |
|---|---|---|---|
light |
#FFFFFF (纯白) |
#000000 (黑色) |
打印输出、白天使用 |
dark |
#1E1E2E (深蓝灰) |
#E2E8F0 (亮白灰) |
夜间模式、护眼 |
RenderConfig 渲染参数
config = RenderConfig(
# 页面尺寸
page_width=2480, # 页面宽度(px), 调整效果: A4@300dpi=2480, 屏幕显示可用1200
page_height=3508, # 页面高度(px), 调整效果: A4@3508, 可根据需要调整
# 边距
margin_top=80, # 上边距(px), 调整效果: 增大则内容下移
margin_bottom=60, # 下边距(px)
margin_left=60, # 左边距(px)
margin_right=60, # 右边距(px)
# 六线谱样式
string_spacing=12, # 弦线间距(px), 调整效果: 增大则谱子更宽更易读
line_width=1, # 弦线粗细(px), 调整效果: 0.5=细线, 2=粗线
line_color="#333333", # 弦线颜色(十六进制), 调整效果: 改变整体色调
# 字体设置
font_family="Arial", # 字体族, 调整效果: 使用系统支持的字体的名称
font_size_fret=10, # 品格数字大小(px), 调整效果: 增大则数字更清晰
font_size_technique=9, # 技巧标记大小(px),
# 系统间距
system_spacing=40, # 系统(行)间距(px), 调整效果: 增大则行间空白更多
)
SynthEngine 音频参数
engine = SynthEngine(
sample_rate=44100, # 采样率(Hz), 调整效果: 48000更清晰但CPU占用更高
buffer_size=512, # 缓冲区大小, 调整效果: 256延迟更低但可能爆音
gain=0.8, # 主音量(0.0-1.0), 调整效果: 1.0=最大音量
)
支持的演奏技巧
| 技巧 | 缩写 | 符号类型 |
|---|---|---|
| 击弦 Hammer-On | H | 文字标签 |
| 勾弦 Pull-Off | P | 文字标签 |
| 上滑音 Slide Up | s/S | 连线+箭头 |
| 下滑音 Slide Down | S | 连线+箭头 |
| 推弦 Bend | B | 弧线+箭头+度数 |
| 颤音 Vibrato | ~ | 波浪线 |
| 闷音 Palm Mute | P.M. | 虚线延长线 |
| 断奏 Staccato | . | 点标记 |
| 延音 Let Ring | 虚线延长线 | <br /> |
| 自然泛音 N.H. | 菱形标记 | <br /> |
| 人工泛音 A.H. | 菱形+文字 | <br /> |
| 震音拨弦 Trem.Pick. | 斜线下划线 | <br /> |
| 颤音 Trill | "tr"文字 | <br /> |
| 装饰音 Grace Note | 小音符 | <br /> |
| 重音 Accentuated | > | 符号 |
| 幽灵音 Ghost Note | 括号包裹 | <br /> |
开发指南
项目结构
ApolloTab/
├── __init__.py # 包入口,导出核心API
├── py.typed # PEP 561 类型提示标记
├── player.py # 播放控制器(时间线 + 音频同步)
├── parser/
│ ├── __init__.py
│ ├── gtp_parser.py # PyGuitarPro → GTPSong (GP3/GP4/GP5/GPX)
│ ├── gp7_parser.py # GP7/GP8 ZIP解包与文件流读取
│ ├── gpif_parser.py # GP7/GP8 GPIF XML完整解析器
│ ├── binary_stylesheet.py # GP7/GP8 二进制样式表解析
│ └── part_configuration.py # GP7/GP8 声部配置解析
├── models/
│ ├── __init__.py
│ ├── song.py # 歌曲模型
│ ├── track.py # 音轨模型
│ ├── measure.py # 小节模型
│ ├── beat.py # 拍模型
│ └── note.py # 音符模型
├── renderer/
│ ├── __init__.py
│ ├── tab_renderer.py # 六线谱绘制引擎
│ └── layout_engine.py # 坐标布局计算
├── audio/
│ ├── __init__.py
│ ├── midi_converter.py # GTP → MIDI事件转换
│ └── synth_engine.py # FluidSynth合成引擎
└── utils/
├── __init__.py
└── constants.py # 全局常量定义
本地开发
# 克隆仓库
git clone https://github.com/your-repo/ApolloTab.git
cd ApolloTab
# 创建虚拟环境
python -m venv venv
source venv/bin/activate # Linux/Mac
# 或 .\venv\Scripts\activate # Windows
# 安装开发依赖
pip install -e ".[dev]"
# 运行测试
pytest tests/ -v
# 代码格式化
black ApolloTab/
isort ApolloTab/
# 类型检查
mypy ApolloTab/
依赖项
必需依赖
| 包名 | 版本 | 用途 | 许可证 |
|---|---|---|---|
| pyguitarpro | >=0.10.1 | Guitar Pro文件解析 | LGPL-3.0 |
| pyfluidsynth | >=1.4.0 | FluidSynth Python绑定 | LGPL-2.1 |
注意: PyQt5 已不再是 pip 依赖。在 ARM 架构上需通过
apt安装后手动创建软链接,pip 无法直接安装。渲染引擎会在运行时检测并使用已安装的 PyQt5。
可选依赖
| 组名 | 包名 | 用途 |
|---|---|---|
| dev | pytest, black, isort, mypy | 开发和测试工具 |
许可证
本项目采用 LGPL 2.1 开源协议。
贡献
欢迎提交 Issue 和 Pull Request!
- Fork 本仓库
- 创建特性分支 (
git checkout -b feature/AmazingFeature) - 提交更改 (
git commit -m 'Add some AmazingFeature') - 推送到分支 (
git push origin feature/AmazingFeature) - 提交 Pull Request
相关项目
- TAB Score Viewer - 基于 ApolloTab 的完整吉他谱查看器应用
- pyguitarpro - Guitar Pro 文件解析底层库
- FluidSynth - 实时 MIDI 合成引擎
版本: v1.3.0