如何将数据集的值转换为指定范围的MIDI音高?
解决方案:数据集到MIDI音高的均值对齐映射
核心问题分析
你遇到的问题根源是单一比例系数只能实现极值对齐,无法保证均值严格对应目标MIDI均值80.5。要解决这个问题,需要采用带偏移的线性变换,优先保证均值匹配,再根据需求适配数据分布与MIDI范围(33-128)。
方法1:均值优先+极值边界映射(最常用)
这个方法能同时满足:
- 数据集均值严格对应MIDI均值80.5
- 数据集的最小值/最大值映射到MIDI的33/128边界
推导公式
假设线性变换为:
midi_pitch = a * data_value + b
根据要求:
- 当
data_value = data_mean(数据集均值)时,midi_pitch = 80.5,可得:b = 80.5 - a * data_mean - 若要数据集最小值
data_min映射到33,代入得:
将33 = a * data_min + bb代入后解出系数:a = (80.5 - 33) / (data_mean - data_min) = 47.5 / (data_mean - data_min) - 若要数据集最大值
data_max映射到128,同理可得:a = (128 - 80.5) / (data_max - data_mean) = 47.5 / (data_max - data_mean)
示例验证
- 当数据集为
[33,128]时,均值data_mean=(33+128)/2=80.5,代入最小值映射公式:
结果为a=47.5/(80.5-33)=1,b=80.5-1*80.5=0midi_pitch=data_value,系数为1,符合预期。 - 当数据集为
[33,100]时,均值data_mean=66.5,代入最小值映射公式:
计算得:33→33,100→128,均值66.5→80.5,完全满足要求。a=47.5/(66.5-33)≈1.418,b=80.5-1.418*66.5≈-13.8
方法2:均值优先+保留数据分布比例
如果不需要强制极值映射到MIDI边界,而是希望保留数据集的分布特征(比如标准差比例),可以用Z分数标准化的方法:
步骤
- 计算数据集的均值
data_mean和标准差data_std - 将数据转换为Z分数(标准化):
z = (data_value - data_mean) / data_std - 将Z分数映射到MIDI范围,保证均值对应80.5,同时让95%的数据落在33-128内(取±2σ覆盖):
(注:23.75=(128-33)/4,对应±2σ覆盖整个MIDI范围)midi_pitch = 23.75 * z + 80.5
优势
- 保留数据集的相对分布,避免极端值导致的映射失真
- 自动保证均值对应80.5
通用边界处理
无论用哪种方法,映射后可能出现超出33-128的数值,需要截断处理:
midi_pitch = max(33, min(128, calculated_midi))
内容的提问来源于stack exchange,提问作者Fersy van der Zee
相关产品推荐
相关产品推荐

