音乐情感标签驱动的生成控制:从文本情绪到和弦进行

📅 2026/7/11 10:51:35
音乐情感标签驱动的生成控制:从文本情绪到和弦进行
音乐情感标签驱动的生成控制从文本情绪到和弦进行一、用户说给我一首忧伤的歌模型给了小调但还是不够忧伤忧伤在音乐理论中不仅仅是 minor scale。它是调性、节奏、配器、动态的多维组合调性minor小调是基础但具体到 D minor 还是 E minor 会产生不同质感节奏慢速60-80 BPM配合长音符营造沉缓动态低音量、柔和起音soft attack配器弦乐 solo大提琴/小提琴比钢琴更能表达忧伤和弦进行vi - IV - I - V流行忧伤vs i - VI - III - VII古典忧伤情感标签驱动的核心思路把自然语言情感词忧伤振奋紧张映射到多维音乐参数的向量空间中。flowchart TD A[情感标签: 忧伤] -- B[情感解析器] B -- C[调性映射] B -- D[节奏映射] B -- E[动态映射] B -- F[和弦映射] B -- G[配器映射] C -- C1[调式: minorbr/根音倾向: D, A, E] D -- D1[BPM: 60-80br/音符时长: 长br/律动: 平直] E -- E1[整体音量: -12dBbr/起音: 慢br/动态范围: 窄] F -- F1[和弦进行:br/i - VI - III - VIIbr/或 i - iv - v - i] G -- G1[主奏: 大提琴/钢琴br/伴奏: 弦乐铺底br/打击乐: 极少] C1 D1 E1 F1 G1 -- H[参数融合] H -- I[冲突检测] I -- J[最终生成参数]二、情感到音乐参数的映射表情感调式BPM动态和弦特征配器偏好欢快 (Joy)Major120-160强、跳跃I-V-vi-IV钢琴、吉他、明亮合成器忧伤 (Sadness)Minor60-80弱、连贯i-VI-III-VII大提琴、钢琴、弦乐振奋 (Epic)Major/Minor100-140渐强、广阔i-VI-III-VII (Epic)管弦、合唱、大鼓紧张 (Tension)Diminished/Chromatic90-130突变、不协和减七和弦、半音进行弦乐震音、电子音效宁静 (Calm)Major/Minor60-90极弱、悠长I-vi-IV-V (稀疏)钢琴solo、环境垫音愤怒 (Anger)Minor/Phrygian140-180极强、短促强力和弦Power Chord失真吉他、双踩鼓三、情感参数生成器实现from dataclasses import dataclass, field from enum import Enum from typing import Optional import numpy as np class Emotion(Enum): JOY joy SADNESS sadness EPIC epic TENSION tension CALM calm ANGER anger NOSTALGIA nostalgia MYSTERY mystery dataclass class EmotionalParameters: 情感驱动的音乐参数。 所有参数都是范围——给生成模型自由度。 硬约束如必须是 minor放在 required 字段中。 # 调性约束 scale_mode: str major # major | minor | dorian | phrygian | mixolydian key_root_weights: dict[str, float] field(default_factorydict) # 节奏约束 bpm_min: int 90 bpm_max: int 140 note_duration_bias: float 0.5 # 0短音符, 1长音符 rhythmic_density: float 0.5 # 节奏密度 # 动态约束 velocity_min: int 40 velocity_max: int 100 dynamic_range: float 0.5 # 动态范围 attack_softness: float 0.5 # 起音柔软度 # 和弦约束 chord_progression_style: str pop harmonic_complexity: float 0.5 # 和声复杂度 # 配器约束 primary_instruments: list[str] field(default_factorylist) percussion_density: float 0.5 # 情感 → 参数的映射表 # 这是从音乐心理学和实际编曲经验中总结的启发式规则 EMOTION_PARAMS: dict[Emotion, dict] { Emotion.JOY: { scale_mode: major, key_root_weights: {C: 1.0, G: 0.9, D: 0.8, F: 0.7}, bpm_min: 120, bpm_max: 160, note_duration_bias: 0.3, # 偏短音符——跳跃感 rhythmic_density: 0.7, velocity_min: 60, velocity_max: 120, dynamic_range: 0.6, attack_softness: 0.3, # 快速起音——干脆 chord_progression_style: pop_major, harmonic_complexity: 0.3, # 简单和弦——易记 primary_instruments: [piano, acoustic_guitar, synth_bright], percussion_density: 0.7, }, Emotion.SADNESS: { scale_mode: minor, key_root_weights: {D: 1.0, A: 0.9, E: 0.8, B: 0.7}, bpm_min: 60, bpm_max: 85, note_duration_bias: 0.8, # 偏长音符——绵延感 rhythmic_density: 0.2, velocity_min: 20, velocity_max: 70, dynamic_range: 0.3, # 动态范围窄——内敛 attack_softness: 0.8, # 慢起音——柔和 chord_progression_style: minor_ballad, harmonic_complexity: 0.4, primary_instruments: [cello, piano_soft, strings_pad], percussion_density: 0.1, # 极少打击乐 }, Emotion.EPIC: { scale_mode: minor, key_root_weights: {D: 1.0, E: 0.9, C: 0.8}, bpm_min: 100, bpm_max: 140, note_duration_bias: 0.5, rhythmic_density: 0.6, velocity_min: 50, velocity_max: 127, dynamic_range: 0.9, # 极大动态范围——从弱到强 attack_softness: 0.4, chord_progression_style: epic_orchestral, harmonic_complexity: 0.5, primary_instruments: [orchestra_full, choir, taiko_drums, brass], percussion_density: 0.8, # 大量打击乐 }, Emotion.TENSION: { scale_mode: phrygian, # 弗里几亚——自带紧张感 key_root_weights: {}, bpm_min: 90, bpm_max: 130, note_duration_bias: 0.4, rhythmic_density: 0.6, velocity_min: 30, velocity_max: 110, dynamic_range: 0.8, # 大动态范围——突变 attack_softness: 0.2, # 快起音——冲击感 chord_progression_style: chromatic, harmonic_complexity: 0.8, # 高和声复杂度——不协和 primary_instruments: [strings_tremolo, synth_dark, percussion_industrial], percussion_density: 0.5, }, Emotion.CALM: { scale_mode: major, key_root_weights: {C: 1.0, F: 0.9, G: 0.8}, bpm_min: 60, bpm_max: 90, note_duration_bias: 0.9, rhythmic_density: 0.1, velocity_min: 10, velocity_max: 60, dynamic_range: 0.2, attack_softness: 0.9, chord_progression_style: ambient, harmonic_complexity: 0.2, primary_instruments: [piano_solo, ambient_pad, harp], percussion_density: 0.0, }, } class EmotionToMusicMapper: 情感到音乐参数的映射器。 支持情感混合——如 70% 忧伤 30% 宁静 参数由权重线性插值生成。 staticmethod def map_single(emotion: Emotion) - EmotionalParameters: 单一情感映射。 params EMOTION_PARAMS.get(emotion, EMOTION_PARAMS[Emotion.JOY]) return EmotionalParameters(**params) staticmethod def map_blend( emotions: list[tuple[Emotion, float]], # [(emotion, weight), ...] ) - EmotionalParameters: 多情感混合映射。 权重应归一化总和 1.0。 数值参数取加权平均类别参数取最高权重的情感。 total_weight sum(w for _, w in emotions) if total_weight 0: return EmotionToMusicMapper.map_single(Emotion.JOY) # 归一化权重 normalized [(e, w / total_weight) for e, w in emotions] # 收集所有情感的参数 all_params { e: EMOTION_PARAMS.get(e, EMOTION_PARAMS[Emotion.JOY]) for e, _ in normalized } # 类别参数取权重最高的情感 dominant_emotion max(normalized, keylambda x: x[1])[0] scale_mode all_params[dominant_emotion][scale_mode] chord_style all_params[dominant_emotion][chord_progression_style] primary_inst all_params[dominant_emotion][primary_instruments] # 数值参数加权平均 def blend_float(key: str) - float: return sum( all_params[e][key] * w for e, w in normalized ) def blend_int(key: str) - int: return int(blend_float(key)) return EmotionalParameters( scale_modescale_mode, key_root_weightsall_params[dominant_emotion].get(key_root_weights, {}), bpm_minblend_int(bpm_min), bpm_maxblend_int(bpm_max), note_duration_biasblend_float(note_duration_bias), rhythmic_densityblend_float(rhythmic_density), velocity_minblend_int(velocity_min), velocity_maxblend_int(velocity_max), dynamic_rangeblend_float(dynamic_range), attack_softnessblend_float(attack_softness), chord_progression_stylechord_style, harmonic_complexityblend_float(harmonic_complexity), primary_instrumentsprimary_inst, percussion_densityblend_float(percussion_density), )四、情感映射的局限情感的主观性与文化差异忧伤在西方古典音乐中常用 D minor在中国传统音乐中可能倾向 E 商调式。情感映射表需要根据目标文化定制。情感的多维性一首歌的情感不是静态的——从忧伤开始、中途转希望、结尾回归平静。动态情感曲线比静态标签更有意义。不适合的场景实验音乐情感标签本身就是限制功能性音乐健身音乐、睡眠音乐需要更精确的生理参数五、总结情感到音乐的映射本质上是一个降维过程——把丰富的人类情感压缩到有限的可控参数中。这个映射必然有信息损失但只要核心维度调性、节奏、动态、和弦的映射足够准确生成结果就能正确传递情绪。混合情感模式如 70% 忧伤 30% 宁静让映射不是非黑即白的二元分类更接近真实情感体验的复杂性。