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

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

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

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

import numpy as np
from matplotlib import pyplot as plt
from numpy.fft import fft
import math


def fft_custom(sig, Fs, zero_padding=False, window=None):
    if zero_padding:
        fft_num = np.power(2, math.ceil(np.log2(len(sig))))
        if window:
            mag = np.fft.fft(sig * np.hanning(len(sig)), fft_num) * 2 / fft_num
            f = np.arange(fft_num) * (Fs / fft_num)
        else:
            mag = np.fft.fft(sig, fft_num) * 2 / fft_num
            f = np.arange(fft_num) * (Fs / fft_num)
    else:
        fft_num = len(sig)
        if window:
            mag = np.fft.fft(sig * np.hanning(len(sig)), fft_num) * 2 / fft_num
            f = np.arange(fft_num) * (Fs / fft_num)
        else:
            mag = np.fft.fft(sig, fft_num) * 2 / fft_num
            f = np.arange(fft_num) * (Fs / fft_num)
    mag[0] /= 2
    return f[:int(fft_num / 2)], abs(mag[:int(fft_num / 2)])


def get_octave_band_base_2(start=-23, end=14):
    """以2为基数返回1/3倍频程带"""
    bands = list()
    for index, i in enumerate(range(start, end)):
        central_frequency = 1000 * (2 ** (1 / 3)) ** i
        if index == 0:
            bands.append([0, central_frequency * np.power(2, 1 / 6)])
        else:
            bands.append([central_frequency / np.power(2, 1 / 6), central_frequency * np.power(2, 1 / 6)])
    return np.asarray(bands)


if __name__ == '__main__':
    # 仿真信号
    # Fs = 10000
    # N = 50000
    # n = list(np.arange(N))
    # t = np.asarray([temp / Fs for temp in n])
    # 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(
    #     2 * np.pi * 197 * t)

    # 实际信号
    path = r'C:\Users\Administrator\Desktop\yourfilepath.txt'
    Fs = 20833
    sig = np.loadtxt(path)
    N = len(sig)
    n = list(np.arange(N))
    t = np.asarray([temp/Fs for temp in n])

    # 1 时域内计算声压级
    temp = [temp * temp for temp in sig]
    p_square_time = np.sum(temp) / len(temp)  # 时域内计算的声压总均方值
    print("p_square_time: ", p_square_time)

    f, mag = fft_custom(sig, Fs)
    # 频域内计算声压总均方值
    temp = [(temp / np.sqrt(2)) * (temp / np.sqrt(2)) for temp in mag]
    p_square_frequency = np.sum(temp)
    print("p_square_frequency: ", p_square_frequency)

    spl_overall = 10 * np.log10(p_square_time / 0.0000000004)

    print("声压级(DB):", spl_overall)

    bands = get_octave_band_base_2(start=-21, end=15)  # start 和 end 控制带宽
    spl_of_bands = list()
    f = list(f)
    index_start = 0
    for band in bands:
        index_stop = np.where(f < band[1])[0][-1]
        band_frequencies_mag = mag[index_start:index_stop]
        temp = [(temp / np.sqrt(2)) * (temp / np.sqrt(2)) for temp in band_frequencies_mag]
        p_square_frequency_band = np.sum(temp)
        spl_ = 10 * np.log10(p_square_frequency_band / 0.0000000004)
        if band[0] <= Fs/2:
            spl_of_bands.append([band[0], band[1], spl_])
        else:
            break
        # print("index_start: %d index_stop: %d" % (index_start, index_stop))
        index_start = index_stop
        # print(band)

    plt.figure(1)
    plt.subplot(211)
    plt.plot(t, sig)
    plt.subplot(212)
    plt.plot(f, mag)
    # plt.show()

    spl_values = list()
    xticks = list()

    for temp in spl_of_bands:
        spl_values.append(temp[2])
        xticks.append(str(int(temp[1])))

    plt.figure(2)
    plt.bar(range(len(spl_values)), spl_values, facecolor='b', width=0.8)
    plt.title("1/3 octave SPL || Overall SPL is %f " % np.round(spl_overall, 3))
    plt.xticks(list(range(len(spl_values))), xticks,rotation=45)
    plt.show()

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

    

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

 

版权声明:本文为D344896224原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/D344896224/article/details/108675377

智能推荐

带有优先级的计算器的优先级设置与实现(Java语言)

                                                        &nbs...

94倍性能进化!阿里云企业级ECS发布会推出最新一代异构计算产品

随着深度学习对人工智能的巨大推动,深度学习所构建的多层神经网络模型的参数空间已从百万级上升到百亿级,这对计算能力提出了新的挑战。 在8月9日的阿里云企业级ECS发布会上,最新一代异构计算通用GPU实例GN5规格族就是一款用于搭建深度学习加速平台的云端利器,相比上一代GPU计算型实例,GN5最高性能提升了整整94倍。 “品学兼优”的GN5采用了NVIDIA Pascal架构旗...

计算机二级考试python考点7(1):标准库(turtle)

今天我们学习其中一个标准库----turtle库所谓标准库,就是不用用户自己获取,在安装python时就有的库称之为标准库,用户直接使用import即可调用它的内容。 turtle库 1.1 功能函数 turtle库一共有三类功能函数,如下表: 函数类型 函数 绘制状态 pendown()、penup()、pensize()、或者使用别名pd()、pu()、width() 颜色控制 color()...

系统级程序设计笔记(unit1——计算机系统漫游)

这个专题的所有学习笔记来自于对武汉大学计算机学院软件工程专业大三上学期的专业必修课《系统级程序设计》的学习(教材为深入理解计算机系统CSAPP),涉及的编程语言全部为C语言和C++语言。 该博客为第1单元的学习笔记,这一单元的主要内容是计算机系统漫游,内容来自《深入理解计算机系统》的第一章,对应ssd6课程的lecture2。 信息就是位+上下文 信息是什么? 信息就是位+上下文 程序的生命周期是...

全国计算机三级网络工程技术复习笔记1

计算机三级网络 第一章 网络系统结构与设计的基本原则 计算机网络分类 按覆盖的地理范围划分,计算机网络可以分为局域网、城域网与广域网等3种类型。 传输速率, 1Mbps=128kB/S 局域网( Local area network, LAN) 特点 (1). 局域网覆盖有限的地理范围,它适应于机关、校园、工厂等有限的范围的计算机、终端与各类信息处理设备联网的需求; (2). 局域网提供高数据传输...

猜你喜欢

学会对VUE的SEO优化,你的网站总是排在前面

​在开始之前,我们先来了解一下什么是SEO。 SEO(Search Engine Optimization):汉译为搜索引擎优化。是一种方式:利用搜索引擎的规则提高网站在有关搜索引擎内的自然排名。目的是让其在行业内占据领先地位,获得品牌收益。很大程度上是网站经营者的一种商业行为,将自己或自己公司的排名前移。 说白了就是你的SEO做的越好,当别人搜索某个关键词时,你的网站在搜索结果中就排的越靠前。这...

Mac升级10.15 Catalina,根目录无权限 完美解决办法!

方法一:不完美重启失效 进入安全模式 重启按command+R 使用命令关闭sip 进入命令控制台:csrutil  disable  重新启动电脑 命令台:csrutil  status 查看sip状态 sudo mount -uw / killall Finder sudo mkdir -p /export/Logs cd /export/ sudo -s sud...

【Unity】协程原理与线程的区别

说到协程,我们首先回顾以下线程与进程这两个概念。在操作系统(os)级别,有进程(process)和线程(thread)两个我们看不到但又实际存在的“东西”,这两个东西都是用来模拟“并行”的,写操作系统的程序员通过用一定的策略给不同的进程和线程分配CPU计算资源,来让用户“以为”几个不同的事情在“同时”进...

在linux系统中编译ARM版EasyNTS上云网关服务报undefined错误的解决方案

我们大部分的视频平台都编译了Arm版本,EasyNVS的ARM版本:视频流媒体服务器综合管理平台能否实现ARM版的编译、EasyNVR的ARM版本:如何在ARM系统将视频流媒体服务器输出RTSP流并实现统一管理,以上两篇博客大家都可以作为参考。 问题分析 由于EasyNTS上云网关也在编译ARM平台的服务,所以在linux中要实现交叉编译,但是执行编译命令之后就会出现undfined ** 的错误...

使用centOS 7配置nodeJS开发环境

  在DigitalOcean上搞了一个centOS服务器,想配置一个自己的VPN(没用过,按照别人的教程来),配置了好多次都没有成功,前前后后销毁创建好几次,就先放一放。配置一下nodeJS环境,可以作为项目测试用(买了域名一直没备案),也按照被人的教程搞了好多次,按照官网提供的才弄好(可能是自己粗心没注意细节的东西)。   想要在DigitalOcean...