当前位置:   article > 正文

总声压级计算与1/3倍频程声压级计算

1/3倍频程声压级

    最近在研究声压级计算的算法,说实话网上搜了好多的资料,大都是将某个声压值转换为DB的公式,这公式随便一本书上就有,哪里用得着您细讲嘞?

    废话少说,建议想看懂我这篇博客的先认着找资料研究一下什么是1/3倍频程,以及声压级计算的基本公式。在计算1/3倍频程的声压级时,要搞清楚傅里叶变换的来世今生,目的是使频域的幅值精确对应上。本博客在进行倍频程计算时选择了基数2来确定倍频程带的上下频率。计算声压级最重要的一句话:各个倍频程带内的声压均方值是该频带内频谱各谱线幅值的均方值之和。

    解释一下,均方值是一个统计量,一根谱线的均方值是什么呢?这就要将这根谱线对应到时域信号求其均方值了,也就是这根谱线的幅值除以根号2。而总声压均方值则是各个倍频带内的均方值之和。下面附上我计算时的代码:

  1. import numpy as np
  2. from matplotlib import pyplot as plt
  3. from numpy.fft import fft
  4. import math
  5. def fft_custom(sig, Fs, zero_padding=False, window=None):
  6. if zero_padding:
  7. fft_num = np.power(2, math.ceil(np.log2(len(sig))))
  8. if window:
  9. mag = np.fft.fft(sig * np.hanning(len(sig)), fft_num) * 2 / fft_num
  10. f = np.arange(fft_num) * (Fs / fft_num)
  11. else:
  12. mag = np.fft.fft(sig, fft_num) * 2 / fft_num
  13. f = np.arange(fft_num) * (Fs / fft_num)
  14. else:
  15. fft_num = len(sig)
  16. if window:
  17. mag = np.fft.fft(sig * np.hanning(len(sig)), fft_num) * 2 / fft_num
  18. f = np.arange(fft_num) * (Fs / fft_num)
  19. else:
  20. mag = np.fft.fft(sig, fft_num) * 2 / fft_num
  21. f = np.arange(fft_num) * (Fs / fft_num)
  22. mag[0] /= 2
  23. return f[:int(fft_num / 2)], abs(mag[:int(fft_num / 2)])
  24. def get_octave_band_base_2(start=-23, end=14):
  25. """以2为基数返回1/3倍频程带"""
  26. bands = list()
  27. for index, i in enumerate(range(start, end)):
  28. central_frequency = 1000 * (2 ** (1 / 3)) ** i
  29. if index == 0:
  30. bands.append([0, central_frequency * np.power(2, 1 / 6)])
  31. else:
  32. bands.append([central_frequency / np.power(2, 1 / 6), central_frequency * np.power(2, 1 / 6)])
  33. return np.asarray(bands)
  34. if __name__ == '__main__':
  35. # 仿真信号
  36. # Fs = 10000
  37. # N = 50000
  38. # n = list(np.arange(N))
  39. # t = np.asarray([temp / Fs for temp in n])
  40. # sig = np.sqrt(2) * np.sin(2 * np.pi * 5 * t) + np.sin(2 * np.pi * 18 * t) + np.sin(2 * np.pi * 53 * t) + np.sin(
  41. # 2 * np.pi * 197 * t)
  42. # 实际信号
  43. path = r'C:\Users\Administrator\Desktop\yourfilepath.txt'
  44. Fs = 20833
  45. sig = np.loadtxt(path)
  46. N = len(sig)
  47. n = list(np.arange(N))
  48. t = np.asarray([temp/Fs for temp in n])
  49. # 1 时域内计算声压级
  50. temp = [temp * temp for temp in sig]
  51. p_square_time = np.sum(temp) / len(temp) # 时域内计算的声压总均方值
  52. print("p_square_time: ", p_square_time)
  53. f, mag = fft_custom(sig, Fs)
  54. # 频域内计算声压总均方值
  55. temp = [(temp / np.sqrt(2)) * (temp / np.sqrt(2)) for temp in mag]
  56. p_square_frequency = np.sum(temp)
  57. print("p_square_frequency: ", p_square_frequency)
  58. spl_overall = 10 * np.log10(p_square_time / 0.0000000004)
  59. print("声压级(DB):", spl_overall)
  60. bands = get_octave_band_base_2(start=-21, end=15) # start 和 end 控制带宽
  61. spl_of_bands = list()
  62. f = list(f)
  63. index_start = 0
  64. for band in bands:
  65. index_stop = np.where(f < band[1])[0][-1]
  66. band_frequencies_mag = mag[index_start:index_stop]
  67. temp = [(temp / np.sqrt(2)) * (temp / np.sqrt(2)) for temp in band_frequencies_mag]
  68. p_square_frequency_band = np.sum(temp)
  69. spl_ = 10 * np.log10(p_square_frequency_band / 0.0000000004)
  70. if band[0] <= Fs/2:
  71. spl_of_bands.append([band[0], band[1], spl_])
  72. else:
  73. break
  74. # print("index_start: %d index_stop: %d" % (index_start, index_stop))
  75. index_start = index_stop
  76. # print(band)
  77. plt.figure(1)
  78. plt.subplot(211)
  79. plt.plot(t, sig)
  80. plt.subplot(212)
  81. plt.plot(f, mag)
  82. # plt.show()
  83. spl_values = list()
  84. xticks = list()
  85. for temp in spl_of_bands:
  86. spl_values.append(temp[2])
  87. xticks.append(str(int(temp[1])))
  88. plt.figure(2)
  89. plt.bar(range(len(spl_values)), spl_values, facecolor='b', width=0.8)
  90. plt.title("1/3 octave SPL || Overall SPL is %f " % np.round(spl_overall, 3))
  91. plt.xticks(list(range(len(spl_values))), xticks,rotation=45)
  92. plt.show()

    直接给大家看下运行该代码的效果吧:

    

       大家也可以用我提供的仿真信号来验证该声压级计算算法的准确性,欢迎交流~

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/549964
推荐阅读
相关标签
  

闽ICP备14008679号