问题背景
项目在处理不同位深的音频信号时,时常需要涉及到样点值和dB对数域切换,不想反复去分析公式和手动计算,所以偷个懒写个函数脚本放在这里,方便下次使用。
功能思路
下面以对数域常用的dBFS刻度为例,支持主流音频信号位深:整型16/24/32位和浮点32位,编写Python实现对数域和采样值单位互换功能。
实现过程本质就是模拟以下转换公式:
-
幅值谱:
dBFS = 20 * lg(sample / max_sample)
-
功率谱(能量谱):
dBFS = 10 * lg(sample / max_sample)
详细转换原理可参考博客:《语音处理:PCM文件中采样值到dB分贝的转换分析》。
具体过程
- 输入待转换的样点值或对数域值,以及信号位深
- 根据相应位深,得到对应位深的最大值
ref_val
- 根据公式进行样点值和对数域的转换,并输出结果
效果如下:
input:
bit_depth = 24
sp = 1024
db = -78.27output:
sample: 1023.74, dBFS: -78.27
Python源码
# 仅支持整型16/24/32位和浮点32位位深
import math as mt
# 常量定义
BIT_DEPTH_I16 = 16
BIT_DEPTH_I24 = 24
BIT_DEPTH_I32 = 32
BIT_DEPTH_F32 = -32
VAL2LOG_COEF = 20
LOG_POW_BASE = 10
# 根据位深获取最大幅值
def GetSampleRefVal(bit_depth):
ref_val = 0
if bit_depth == BIT_DEPTH_F32: # float32
ref_val = 1.0
elif ((bit_depth == BIT_DEPTH_I16) or # int16
(bit_depth == BIT_DEPTH_I24) or # int24
(bit_depth == BIT_DEPTH_I32)): # int32
ref_val = 2 ** (bit_depth - 1) - 1
else:
print('not supported bitdepth =', bit_depth)
return -1
return ref_val
# dBFS到采样值
def Db2Sample(db, bit_depth):
# assumed that bit_depth is verfied
ref_val = GetSampleRefVal(bit_depth)
sample = pow(LOG_POW_BASE, db / VAL2LOG_COEF) * ref_val
return sample
# 采样值到dBFS
def Sample2Db(sample, bit_depth):
# assumed that bit_depth is verfied
ref_val = GetSampleRefVal(bit_depth)
sample_clip = min(abs(sample), ref_val)
ratio = sample_clip / ref_val
dBFS = VAL2LOG_COEF * mt.log(ratio, LOG_POW_BASE)
return dBFS
# test demo
bit_depth = 24
sp = 1024
db = -78.27
dBFS = Sample2Db(sp, bit_depth)
sample = Db2Sample(db, bit_depth)
print('sample: {0:0.2f}, dBFS: {1:0.2f}'.format(sample, dBFS))
相关资料
- 语音处理:PCM文件中采样值到dB分贝的转换分析,link