使用trae cn制作MIDI 伴奏的总结
📋 项目概述
| 项目 | 内容 |
|---|---|
| 源文件 | To_Loves_End.mid (长笛独奏) |
| 输出文件 | To_Loves_End_with_piano.mid (长笛 + 双吉他伴奏) |
| 工具 | Python + mido 库 |
| 时长 | 89.9 秒 |
❌ 最初的问题
问题现象:
- MuseScore 导入报错:
unexpected EOF - 使用
music21库生成的 MIDI 格式有兼容性问题
解决方案:
- 改用
mido库重写整个生成逻辑 - mido 是专门的 MIDI 处理库,生成的文件标准兼容
🔧 技术架构
核心依赖
from mido import MidiFile, MidiTrack, Message, MetaMessage
import random
轨道结构
Track 1: 主旋律 - 长笛 (Flute) → 原MIDI直接复制
Track 2: 伴奏 - 钢弦吉他 (Steel Guitar) → 8分音符分解和弦
Track 3: 低音 - 尼龙吉他 (Nylon Guitar) → 每小节根音支撑
🎵 和弦进行设计
C 大调经典流行和弦进行:
| 小节 | 和弦 | 音符 (MIDI编号) | 说明 |
|---|---|---|---|
| 1 | C 大调 | 60, 64, 67 | 主和弦 |
| 2 | F 大调 | 65, 69, 72 | 下属和弦 |
| 3 | G 大调 | 67, 71, 74 | 属和弦 |
| 4 | C 大调 | 60, 64, 67 | 回到主音 |
| 5 | Am 小调 | 57, 60, 64 | 关系小调 |
| 6 | F 大调 | 65, 69, 72 | 下属 |
| 7 | G 大调 | 67, 71, 74 | 属 |
| 8 | C 大调 | 60, 64, 67 | 终止 |
循环规则: 上述8小节循环4次,覆盖全曲89.9秒
🎸 伴奏生成算法
1. 钢弦吉他 - 高音分解
# 模式:根音 → 三音 → 五音 → 三音
# 8分音符,每拍2个音
pattern = [root + 12, third + 12, fifth + 12, third + 12]
# 音量:第一个音稍重
vel = 45 if i == 0 else 35
2. 尼龙吉他 - 低音支撑
# 每小节持续的根音
# 中音区,不抢主旋律
note_val = root # 不移低八度,避免浑浊
✨ 人性化处理(关键!)
节拍偏差 (Timing Variation)
# ±3% 的时间偏差,模拟真人演奏的不完美
time_offset = random.randint(
-int(ticks_per_beat * 0.03),
int(ticks_per_beat * 0.03)
)
力度偏差 (Velocity Variation)
# ±5-8 的力度随机偏差,模拟触键力度变化
vel_var = random.randint(-8, 8)
final_vel = base_vel + vel_var
效果
- ❌ 不是机械的绝对准时
- ✅ 有轻微的"抢拍"和"拖拍"
- ✅ 每个音的力度都不完全相同
- ✅ 听起来更像真人演奏
📊 数据流程图
┌───────────────────────────────────────────────────────────┐
│ 源 MIDI 文件 │
│ To_Loves_End.mid (89.9s) │
└────────────────────────────┬──────────────────────────────┘
│
▼
┌───────────────────────────────────────────────────────────┐
│ 读取 MIDI 轨道信息 │
│ ticks_per_beat, 音符序列 │
└────────────────────────────┬──────────────────────────────┘
│
┌────────────────────┼────────────────────┐
│ │ │
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ 复制主旋律 │ │ 生成钢弦吉他 │ │ 生成尼龙吉他 │
│ 长笛轨道 │ │ 分解和弦 │ │ 低音根音 │
│ (直接复制) │ │ + 人性化偏差 │ │ + 人性化偏差 │
└───────┬───────┘ └───────┬───────┘ └───────┬───────┘
│ │ │
└────────────────────┼────────────────────┘
│
▼
┌───────────────────────────────────────────────────────────┐
│ 合并轨道 → 新 MIDI 文件 │
│ To_Loves_End_with_piano.mid │
└───────────────────────────────────────────────────────────┘
🎛️ MuseScore 导出优化
音量平衡 (Mixer - F10)
| 轨道 | 音量 | 混响 |
|---|---|---|
| 长笛 (主旋律) | 0 dB | 35% |
| 钢弦吉他 | -4 dB | 30% |
| 尼龙吉他 | -5 dB | 25% |
导出设置
格式: MP3
比特率: 320 kbps (最高质量)
采样率: 48000 Hz
📁 文件清单
| 文件名 | 说明 |
|---|---|
To_Loves_End.mid | 原始MIDI(长笛独奏) |
To_Loves_End_with_piano.mid | 最终成品(长笛+双吉他) |
generate_piano_accompaniment.py | 生成脚本 |
导出MP3.bat | 一键导出批处理 |
💡 关键技术点
-
mido vs music21
- music21: 适合音乐分析,但MIDI输出有兼容问题
- mido: 专门处理MIDI,输出标准、兼容
-
人性化偏差的意义
- 绝对准时 = 机械感 = 冰冷
- 微偏差 = 真人感 = 有温度
- 偏差控制在 3-5%,人耳感知自然
-
伴奏音量原则
- 伴奏永远比主旋律小 3-5 dB
- 低音比高音再小 1-2 dB
- 混响增加空间感和融合度
🎵 最终效果
✅ 完成的作品特点:
- 完整保留原曲主旋律
- 吉他伴奏轻柔不抢戏
- 自然的演奏呼吸感
- 可直接导出为MP3配乐
- 可用于视频BGM、游戏配乐等