Bootstrap

曲谱转换成音频

曲谱转换成音频

将曲谱转换成音频是一项复杂的任务,因为它涉及到多个步骤,包括解析曲谱、生成音符的音频数据、以及合成音频文件。下面是一个简化的例子,使用 pythonpygame 库来将简单的曲谱(如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

解释

  1. 初始化 pygame.mixer

    • 初始化 pygame 的音频模块。
  2. 定义音符频率

    • 使用一个字典 note_frequencies 存储 MIDI 音符编号和对应的频率。
  3. 定义曲谱

    • 使用一个列表 score 存储曲谱中的音符(MIDI 音符编号)。
  4. 定义每个音符的持续时间

    • 使用变量 duration 来定义每个音符的播放时间(秒)。
  5. 生成并播放音符

    • play_note 函数生成一个特定频率和持续时间的音频样本,并播放它。
  6. 播放曲谱

    • play_score 函数遍历曲谱中的音符,并调用 play_note 播放每个音符。

注意事项

  • pygame 的音频处理能力有限,对于更复杂的音频生成和编辑,可能需要使用更专业的库,如 midiutilfluidsynth(用于 MIDI 合成)或 pydub(用于音频处理)。
  • 可以根据需要扩展 note_frequencies 字典,以支持更多的音符。
  • 由于wav文件体积较大(12s 192kHz文件4.3MB),可以将其转换为mp3保存
;