曲谱转换成音频
将曲谱转换成音频是一项复杂的任务,因为它涉及到多个步骤,包括解析曲谱、生成音符的音频数据、以及合成音频文件。下面是一个简化的例子,使用 python
和 pygame
库来将简单的曲谱(如MIDI音符编号)转换成音频。
首先,需要安装 pygame
库,可以通过以下命令安装:
pip install pygame pydub
然后,可以编写一个简单的程序来将曲谱转换为音频。下面是一个示例程序tone2audio.py
:
import pygame
import time
import math
import numpy as np
import pydub
from pydub import AudioSegment
from pydub.generators import Sine
# 初始化 pygame.mixer(虽然在这个例子中我们不会用它来播放音频)
pygame.mixer.init()
# 定义音符频率(根据MIDI音符编号)
note_frequencies = {
60: 261.63, # C4
61: 277.18, # C#4 / Db4
62: 293.66, # D4
63: 311.13, # D#4 / Eb4
64: 329.63, # E4
65: 349.23, # F4
66: 369.99, # F#4 / Gb4
67: 392.00, # G4
68: 415.30, # G#4 / Ab4
69: 440.00, # A4
70: 466.16, # A#4 / Bb4
71: 493.88, # B4
# 可以根据需要添加更多音符
}
# 乐谱(MIDI音符编号的列表)(自定义的乐谱)
score = [60, 62, 64, 65, 67, 69, 71, 69, 67, 65, 64, 62, 60]
# 每个音符的持续时间(秒),考虑到淡入淡出,可以适当增加一点,
# 避免音符过渡时产生脉冲音
duration_per_note = 1.05 # 稍微增加一点以避免淡入淡出重叠导致的裁剪
fade_duration = 0.05 # 淡入淡出的持续时间(秒)
# 生成音符音频片段的函数,现在包含淡入淡出效果
def generate_note_audio(frequency, duration):
note_audio = Sine(frequency).to_audio_segment(duration=duration * 1000 - fade_duration * 1000 * 2)
# 应用淡入淡出效果(注意:这里需要先裁剪再应用效果,因为pydub的fadein/fadeout会增加长度)
# 但由于我们已经通过减少原始持续时间来预留了空间,所以这里直接应用即可
note_audio = note_audio.fade_in(fade_duration * 1000).fade_out(fade_duration * 1000)
return note_audio
# 合并所有音符到一个音频流中
audio_stream = pydub.AudioSegment.silent(duration=0)
for note in score:
if note in note_frequencies:
frequency = note_frequencies[note]
note_audio = generate_note_audio(frequency, duration_per_note)
audio_stream += note_audio # 将音符音频片段(含淡入淡出)添加到音频流中
else:
# 处理未知音符(这里我们选择添加静音,但也可以应用淡入淡出效果的静音片段)
silent_duration = duration_per_note * 1000 # 转换为毫秒
silent_audio = pydub.AudioSegment.silent(duration=silent_duration)
# 如果需要,也可以为静音片段添加淡入淡出(尽管这通常不是必需的)
# silent_audio = silent_audio.fadein(fade_duration * 1000).fadeout(fade_duration * 1000)
# 但由于静音片段本身就是无声的,所以淡入淡出效果在这里不会有任何听觉上的影响
audio_stream += silent_audio
# 音频采样率默认生成44.1kHz(192kHz用到ffmpeg,需要手动安装,可以自行搜索攻略)
sample_rate = [44100, 192000][0]
# 定义输入和输出文件路径
output_default_file = 'output_smooth_default.wav'
output_192k_file = 'output_192k.wav'
# 导出为 WAV 文件(使用高质量的音频设置)
audio_stream.export(output_default_file, format="wav")
if sample_rate != 44100:
import subprocess
# 定义ffmpeg命令
ffmpeg_command = [
'ffmpeg',
'-i', output_default_file,
'-ar', '192000',
output_192k_file
]
# 执行ffmpeg命令
subprocess.run(ffmpeg_command)
保存上述代码为文件tone2audio.py
,然后在cmd
中执行:
python tone2audio.py
解释
-
初始化
pygame.mixer
:- 初始化
pygame
的音频模块。
- 初始化
-
定义音符频率:
- 使用一个字典
note_frequencies
存储 MIDI 音符编号和对应的频率。
- 使用一个字典
-
定义曲谱:
- 使用一个列表
score
存储曲谱中的音符(MIDI 音符编号)。
- 使用一个列表
-
定义每个音符的持续时间:
- 使用变量
duration
来定义每个音符的播放时间(秒)。
- 使用变量
-
生成并播放音符:
play_note
函数生成一个特定频率和持续时间的音频样本,并播放它。
-
播放曲谱:
play_score
函数遍历曲谱中的音符,并调用play_note
播放每个音符。
注意事项
pygame
的音频处理能力有限,对于更复杂的音频生成和编辑,可能需要使用更专业的库,如midiutil
、fluidsynth
(用于 MIDI 合成)或pydub
(用于音频处理)。- 可以根据需要扩展
note_frequencies
字典,以支持更多的音符。 - 由于
wav
文件体积较大(12s 192kHz
文件4.3MB
),可以将其转换为mp3
保存