声压级 matlab,语音信号处理教程(二)声音的声压级和响度
本節(jié)內(nèi)容我們來看下如何用Matlab和Python計算聲音的聲壓級和響度。
聲壓級
1. 聲壓級定義
首先來看聲壓級,這個就是指的我們平時所說的聲音有多少分貝。聲壓定義為聲波在某一點產(chǎn)生的逾量瞬時壓強的均方根值。由于聲壓容易被人耳感知,也易于測量,因此,通常使用聲壓作為描述聲波大小的物理量。
聲壓級以符號SPL(sound pressure level)表示,其定義為將待測聲壓有效值p(e)與參考聲壓p(ref)的比值取常用對數(shù),再乘以20,即:
在空氣中參考聲壓p(ref)一般取為2e-5帕,這個數(shù)值是正常人耳對800赫聲音剛剛能覺察其存在的聲壓值,也就是800赫聲音的可聽閾聲壓。一般講,低于這一聲壓值,人耳就再也不能覺察出這個聲音的存在了。顯然該可聽閾聲壓的聲壓級即為零分貝。
指的是聲壓有效值,就是一段聲音信號的均方根(RMS)。設(shè)語音長度為T, 離散點數(shù)為N, 則有效聲壓的計算公式為:
常見的聲音分貝值:
聲音種類
聲壓級(分貝)
烈性炸藥爆炸聲
170
火箭、導彈發(fā)射場
150
飛機發(fā)動機
120
發(fā)電機工作
100
卡車
90
正常談話
50
輕聲耳語
30
農(nóng)村靜夜
10
Matlab代碼
由前面的定義可很容易寫出SPL的代碼,需要注意的是,程序中的輸入信號是數(shù)字信號,與實際的模擬信號大小成倍數(shù)關(guān)系。
function?spl?=?SPLCal(x)
len?=?length(x);
%%
%?有效聲壓計算,即求RMS
pa?=?sqrt(sum(x.^2)/len);
%%?聲壓級計算
%?聲壓級值spl=20*log10(pa/p0),單位為dB
p0?=?2e-5;
spl?=?20*log10(pa/p0);
end
完整代碼如下:
clear?all;clc;close?all;
%%
[x,fs]=audioread('mySpeech.wav');
len=length(x);
%%?語音分幀
%?每幀大小為frameLen,當語音長度不是幀長的整數(shù)倍時:
%?(1)若剩余長度大于等于幀長的二分之一,則補零至幀長
%?(2)若剩余長度小于幀長的二分之一,則舍棄
%?常用的語音幀長:20ms、50ms、100ms、200ms
framTime = 100;?%?單位:ms
%?每幀信號點數(shù)
frameLen=fs*framTime/1000;
%?m為Length/frameLen后得到的余數(shù)
m?=?mod(len,frameLen);
if?m?>=?frameLen/2?%?補零
x?=?[x;zeros(frameLen-m,1)];
len?=?length(x);
else???%?即m?
nframe?=?floor(len/frameLen);
x?=?x(1:nframe*frameLen);
len?=?length(x);
end
%?最終的語音分幀總幀數(shù)
N?=?len/frameLen;
%%?計算聲壓級
s?=?zeros(1,frameLen);
%?N幀信號的聲壓級值存儲在spl向量里
spl?=?zeros(1,N);
for?k?=?1:N
s?=?x((k-1)*frameLen?+?1:k*frameLen);
spl(k)?=?SPLCal(s);
end
%%?繪圖
t?=?1:len;
spl_rep?=?repmat(spl,?frameLen,?1);
figure();
subplot(211);plot(t/fs,x);grid?on;xlabel('時間(s)');title('輸入語音波形');
subplot(212);stairs(t/fs,spl_rep(:),'r');grid?on;xlabel('時間(s)');ylabel('聲壓級(dB)');
title('語音信號的聲壓級(dB)');
image-20210220185851447
Python代碼
Python代碼如下:
import?pyaudio
import?wave
import?numpy?as?np
import?matplotlib.pyplot?as?plt
def?load_wav(wave_input_path):
wf?=?wave.open(wave_input_path,?'rb')??#?讀?wav?文件
fs?=?wf.getframerate()
nframes?=?wf.getnframes()
str_data?=?wf.readframes(nframes)
wf.close()
wave_data?=?np.fromstring(str_data,?dtype=np.short)
return?wave_data.astype(np.float64),?fs
def?SPLCal(x):
Leng?=?len(x)
pa?=?np.sqrt(np.sum(np.power(x,?2))/Leng)
p0?=?2e-5
spl?=?20?*?np.log10(pa?/?p0)
return?spl
if?__name__?==?'__main__':
x,?fs?=?load_wav('audio.wav')
Leng?=?len(x)
frameTime?=?100
frameLen?=?fs?*?frameTime?//?1000
m?=?np.mod(Leng,?frameLen)
if?m>=frameLen/2:
x?=?np.append(x,?np.zeros(int(frameLen-m)))
Leng?=?len(x)
else:
nframe?=?np.floor(Leng/frameLen)
x?=?x[0:nframe?*?frameLen?+?1]
Leng?=?len(x)
N?=?Leng?//?frameLen
spl?=?np.array([])
for?k?in?range(N):
s?=?x[k*frameLen:?(k+1)*frameLen]
spl?=?np.append(spl,?SPLCal(s))
spl_rep?=?np.repeat(spl,?frameLen)
plt.figure()
plt.subplot(211)
plt.plot(x)
plt.subplot(212)
plt.plot(spl_rep)
plt.show()
繪圖如下:
image-20210221155302000
響度
當用同樣的力氣講話的時候,為什么我們總覺得女性的聲音要比男性的響?這就是我們下面要講的響度。響度是聽覺判斷聲音強弱的屬性,跟人主觀感覺有關(guān)。人主觀感覺判斷的聲音強弱,即聲音響亮的程度,根據(jù)它可以把聲音排成由輕到響的序列。
當外界聲振動傳入人耳內(nèi),人們在主觀感覺上形成聽覺上聲音強弱的概念。人們習慣于地用“響”與“不響”來描述聲波的強度,但這一描述與聲波的強度又不完全等同。人耳對聲波響度的感覺還與聲波的頻率有關(guān),即使相同聲壓級但頻率不同的聲音,人耳聽起來會不一樣響。例如,同樣是60dB的兩種聲音,但一個聲音的頻率為100Hz,而另一個聲音為1000Hz,人耳聽起來1000Hz的聲音要比100Hz的聲音響。要使頻率為100Hz的聲音聽起來和頻率為1000Hz、聲壓級為60dB的聲音同樣響,則其聲壓級要達到67dB。
下面介紹幾個相關(guān)的概念:
響度級: 按人耳對聲音的感覺特性,依據(jù)聲壓和頻率定出人對聲音的主觀音響感覺量,稱為響度級,單位為方。
方(Phon):當某一頻率的純音和1000Hz的純音聽起來同樣響時,這時1000Hz純音的聲壓級就定義為該待定聲音的響度級。因此在1kHz的頻率上,聲壓級為60dBSPL信號的響度為60方。對各個頻率的聲音作這樣的聽音比較,得出達到同樣響度級時頻率與聲壓級的關(guān)系曲線,這就是我們?nèi)硕穆犛X等響曲線。
image-20210220112716013
從等響曲線圖中我們發(fā)現(xiàn),人耳對高頻的聲音更加敏感,同樣聲壓級下的高頻聲音響度級比低頻的高。一般女性發(fā)聲的高頻成分較多,而男性發(fā)聲的低頻成分相對較多,這就是在同樣力氣講話時(聲壓級相同),女性的聲音聽上去更加響的原因。
由于這種客觀單位只是非常有限地表達了人耳對于響度的反應(yīng),因此可以引入一個關(guān)于響度的主觀概念——宋。
宋(Sone):表示人耳在自然狀態(tài)下,根據(jù)聲壓級的變化所表現(xiàn)出的對于響度聽感的變化。
“宋”與“方”的關(guān)系表現(xiàn)為1宋等于40方(即在等響曲線圖中,1kHz處代表40dBSPL),并且以1宋為標準,在2宋時響度增加一倍,在0.5宋時響度減小一倍。
根據(jù)IS0226--2003標準H等響度曲線的定義,聲壓級LP 為:
其中,
其中,為聽力閾值;為響度感知指數(shù);為以1000Hz為標準所計算的線性傳輸函數(shù)的幅值。這三個參數(shù)都可以在ISO226中查到。
image-20210220130314703
計算響度的Matlab代碼如下:
function?[spl,?freq]?=?loudnessCal(phon)
f?=?[20?25?31.5?40?50?63?80?100?125?160?200?250?315?400?500?630?800?...
1000?1250?1600?2000?2500?3150?4000?5000?6300?8000?10000?12500];
af?=?[0.532?0.506?0.480?0.455?0.432?0.409?0.387?0.367?0.349?0.330?0.315?...
0.301?0.288?0.276?0.267?0.259?0.253?0.250?0.246?0.244?0.243?0.243?...
0.243?0.242?0.242?0.245?0.254?0.271?0.301];
Lu?=?[-31.6?-27.2?-23.0?-19.1?-15.9?-13.0?-10.3?-8.1?-6.2?-4.5?-3.1?...
-2.0??-1.1??-0.4???0.0???0.3???0.5???0.0?-2.7?-4.1?-1.0??1.7?...
2.5???1.2??-2.1??-7.1?-11.2?-10.7??-3.1];
Tf?=?[?78.5??68.7??59.5??51.1??44.0??37.5??31.5??26.5??22.1??17.9??14.4?...
11.4???8.6???6.2???4.4???3.0???2.2???2.4???3.5???1.7??-1.3??-4.2?...
-6.0??-5.4??-1.5???6.0??12.6??13.9??12.3];
Ln?=?phon;
%從響度級計算聲壓級
Af=4.47E-3?*?(10.^(0.025*Ln)?-?1.15)?+?(0.4*10.^(((Tf+Lu)/10)-9?)).^af;
Lp=((10./af).*log10(Af))?-?Lu?+?94;
spl?=?Lp;
freq?=?f;
end
總結(jié)
以上是生活随笔為你收集整理的声压级 matlab,语音信号处理教程(二)声音的声压级和响度的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 二层协议--LACP协议总结
- 下一篇: i3wm中Chrome不保存密码