如何用UDUNITS-2语法在R的units包中定义梅尔心理声学单位?
在R的units包中定义梅尔(Mel)单位及跨语言参考方案
R语言(units包)实现
虽然units包的单位解析依赖底层C实现,但可以通过注册自定义双向转换函数来添加梅尔单位:
先定义赫兹与梅尔的双向转换逻辑:
- 梅尔转赫兹使用公式逆运算:
f = 700*(exp(M/1127)-1) - 赫兹转梅尔使用给定公式:
M = 1127*ln(1 + f/700)
- 梅尔转赫兹使用公式逆运算:
注册新单位并测试转换:
library(units) # 梅尔转赫兹的逆转换函数 hz_from_mel <- function(m) { 700 * (exp(m / 1127) - 1) } # 赫兹转梅尔的转换函数 mel_from_hz <- function(f) { 1127 * log(1 + f / 700) } # 注册梅尔单位,关联赫兹作为基准单位 install_unit("mel", def = "Hz", convert = list( Hz = mel_from_hz, mel = hz_from_mel )) # 正向转换测试:1000Hz转梅尔 freq_hz <- set_units(1000, Hz) freq_mel <- freq_hz %>% set_units(mel) print(freq_mel) # 反向转换测试:梅尔转回赫兹 freq_hz_back <- freq_mel %>% set_units(Hz) print(freq_hz_back)
Python(Pint库)参考方案
Pint是Python中类似units的单位处理库,支持自定义非线性单位转换:
from pint import UnitRegistry import math ureg = UnitRegistry() # 注册梅尔为频率单位 ureg.define('mel = [frequency]') # 添加赫兹与梅尔的双向转换规则 ureg.add_transformation(ureg.hertz, ureg.mel, lambda f: 1127 * math.log(1 + f / 700)) ureg.add_transformation(ureg.mel, ureg.hertz, lambda m: 700 * (math.exp(m / 1127) - 1)) # 测试转换 freq_hz = 1000 * ureg.hertz freq_mel = freq_hz.to('mel') print(freq_mel) freq_hz_back = freq_mel.to('hertz') print(freq_hz_back)
C语言参考实现
如果需要直接在C中实现转换逻辑(无需单位库),可以封装转换函数:
#include <math.h> #include <stdio.h> // 赫兹转梅尔 double hz_to_mel(double f) { return 1127 * log(1 + f / 700.0); } // 梅尔转赫兹 double mel_to_hz(double m) { return 700.0 * (exp(m / 1127.0) - 1); } // 示例测试 int main() { double input_hz = 1000.0; double mel_val = hz_to_mel(input_hz); printf("%.2f Hz = %.2f Mel\n", input_hz, mel_val); double hz_val = mel_to_hz(mel_val); printf("%.2f Mel = %.2f Hz\n", mel_val, hz_val); return 0; }
内容的提问来源于stack exchange,提问作者Fredrik Nylén
相关产品推荐
相关产品推荐

