Python实现分贝仪时Numpy计算响度偶尔返回NaN的原因是什么?
问题根因
你遇到的nan报错核心原因是整型溢出:
- 你读取的音频数据是
np.short也就是16位有符号整型,取值范围仅为-32768 ~ 32767 - 当音量较高时,音频采样值的平方结果会远超过16位整型的最大上限,发生溢出后会得到负数
- 对负数执行平方根运算
np.sqrt(),就会直接返回nan,也就是你看到的不合理输出。
修复方案
你只需要在做数值运算前,先把音频数据转换为浮点型或者32位整型,就能避免溢出问题,同时可以补充几个稳定性优化:
#!/usr/bin/env python3 # -*- coding: utf-8 -*- import pyaudio import numpy as np CHUNK = 1024 FORMAT = pyaudio.paInt16 CHANNELS = 1 RATE = 44100 pa = pyaudio.PyAudio() stream = pa.open(format=FORMAT, channels=CHANNELS, rate=RATE, input=True, frames_per_buffer=CHUNK) while True: # 增加exception_on_overflow=False避免输入溢出时直接抛错中断 string_audio_data = stream.read(CHUNK, exception_on_overflow=False) # 用np.frombuffer替代已弃用的np.fromstring,同时直接转成float32避免运算溢出 audio_data = np.frombuffer(string_audio_data, dtype=np.short).astype(np.float32) # 计算RMS时增加极小值1e-8,避免完全静音时log10(0)返回-inf rms = np.sqrt(np.mean(np.abs(audio_data)**2)) loudness = 20 * np.log10(rms + 1e-8) print(loudness)
如果需要得到真实的声压级dB SPL,你还需要用标准分贝仪对你的录音设备做校准,给当前计算得到的dBFS值加上固定的校准偏移量即可。
内容的提问来源于stack exchange,提问作者gurkensaas
相关产品推荐
相关产品推荐

