python实时采集与处理声⾳信号_Python之⾳频信号处理 (⼀)⾳频基础知识
⼀、⾳频基础知识
1、声⾳的三要素
(1)⾳调
⼈⽿对声⾳⾼低的感觉称为⾳调(也叫⾳频)。⾳调主要与声波的频率有关。声波的频率⾼,则⾳调也⾼。⼀般⾳频 ⼉童>⼥⽣>男⽣。 ⼈⽿听觉⾳频范围是20Hz-20000Hz(做⾳频压缩时不在这个范围内的数据就可以砍掉)。
(2)⾳量
也就是响度。⼈⽿对声⾳强弱的主观感觉称为响度。响度和声波振动的幅度有关。⼀般说来,声波振动幅度越⼤则响度也越⼤。
⼈们对响度的感觉还和声波的频率有关,同样强度的声波,如果其频率不同,⼈⽿感觉到的响度也不同。
换面鞋(3)⾳⾊
也就是⾳品。⾳⾊是⼈们区别具有同样响度、同样⾳调的两个声⾳之所以不同的特性,或者说是⼈⽿对各种频率、各种强度的声波的综合反应。⾳⾊与声波的振动波形有关,或者说与声⾳的频谱结构有关。
2、⾳频的量化与编码
(1)⾳频的量化过程
现实⽣活中,我们听到的声⾳都是时间连续的,我们把这种信号叫模拟信号。模拟信号(连续信号)需要量化成数字信号(离散的、不连续的信号)以后才能在计算机中使⽤。如下所⽰量化过程分为5个步骤:
模拟信号
现实⽣活中的声⾳表现为连续的、平滑的波形,其横坐标为时间轴,纵坐标表⽰声⾳的强弱。
采样
按照⼀定的时间间隔在连续的波上进⾏采样取值,如下图所⽰取了10个样。
量化
将采样得到的值进⾏量化处理,也就是给纵坐标定⼀个刻度,记录下每个采样的纵坐标的值。
编码
将每个量化后的样本值转换成⼆进制编码。
数字信号
将所有样本⼆进制编码连起来存储在计算机上就形成了数字信号。
(2)量化的基本概念
1)采样⼤⼩
⼀个采样⽤多少个bit存放,常⽤的是16bit(这就意味着上述的量化过程中,纵坐标的取值范围是0-65535,声⾳是没有负值的)。
洗车房
2)采样率
也就是采样频率(1秒采样次数),⼀般采样率有8kHz、16kHz、32kHz、44.1kHz、48kHz等,采样频率越⾼,声⾳的还原就越真实越⾃然,当然数据量就越⼤。
模拟信号中,⼈类听觉范围是20-20000Hz,如果按照44.1kHz的频率进⾏采样,对20HZ⾳频进⾏采样,⼀个正⽞波采样2200次;对20000HZ⾳频进⾏采样,平均⼀个正⽞波采样2.2次。
3)声道数
为了播放声⾳时能够还原真实的声场,在录制声⾳时在前后左右⼏个不同的⽅位同时获取声⾳,每个⽅位的声⾳就是⼀个声道。声道数是声⾳录制时的⾳源数量或回放时相应的扬声器数量,有单声道、双声道、多声道。
4)码率烟雾处理
也叫⽐特率,是指每秒传送的bit数。单位为 bps(Bit Per Second),⽐特率越⾼,每秒传送数据就越多,⾳质就越好。
码率计算公式:
码率 = 采样率 * 采样⼤⼩ * 声道数
⽐如采样率44.1kHz,采样⼤⼩为16bit,双声道PCM编码的WAV⽂件:
码率=44.1hHz16bit2=1411.2kbit/s。
那么录制1分钟的⾳乐的⼤⼩为(1411.2 * 1000 * 60) / 8 / 1024 / 1024 = 10.09M。
3、⾳频压缩技术
⾳频压缩主要包括2种⽅法:
(1)消除冗余数据
这种压缩的主要⽅法是去除采集到的⾳频冗余信息,这些被删除掉的⾳频信号是没法恢复的,所以称为有损压缩。
冗余信息包括⼈类听觉范围之外的⾳频信号和被掩蔽掉的⾳频信号。什么是被掩蔽的信号呢?信号的掩蔽分为频域掩蔽和时域掩蔽。 1)频域掩蔽效应
⼈类听觉范围是20-20000Hz,但这并不意味着只要是这个频率范围内的声⾳都可以听到,能否听到还
与声⾳的分贝⼤⼩有关,有个分贝临界值,⾼于这个临界值的声⾳才能听到,低于这个临界值的声⾳就听不到,在不同的频率下这个临界值是不⼀样的。
还有⼀种情况,⽐如2个⾳调差不多的⼈同时说话,⼀个声⾳很⼤,⼀个声⾳很⼩,声⾳⼩的会受到声⾳⼤的影响,导致声⾳⼩的⽆法被听到。
2)时域掩蔽效应
除了同时发出的声⾳之间有掩蔽现象之外,在时间上相邻的声⾳之间也有掩蔽现象,称为时域掩蔽。时域掩蔽⼜分为超前掩蔽和滞后掩蔽,如下图所⽰。产⽣时域掩蔽的主要原因是⼈的⼤脑处理信息需要花费⼀定的时间。⼀般来说,超前掩蔽很短,只有⼤约5~20ms,⽽滞后掩蔽可以持续50~200ms。
(2)哈夫曼⽆损编码
将⼈类⽆法识别的声⾳信号删除掉后,对剩余的声⾳信号继续进⾏压缩编码,经过这种压缩后再还原时是可以复原到和原来⼀样的数据的(当然,复原也只是复原到压缩前的状态,那些删除的⼈类⽆法识别的部分是不能复原的),所以称为⽆损压缩。
⼆、⾳频信号的读写
光催化剂
⾳频信号是模拟信号,我们需要将其保存为数字信号,才能对语⾳进⾏算法操作,WAV是Microsoft开发的⼀种声⾳⽂件格式,通常被⽤来保存未压缩的声⾳数据。
语⾳信号有三个重要的参数:声道数、取样频率和量化位数。
声道数:可以是单声道或者是双声道。
采样频率:⼀秒内对声⾳信号的采集次数,44100Hz采样频率意味着每秒钟信号被分解成44100份。换句话说,每隔1/44100秒就会存储⼀次,如果采样率⾼,那么媒体播放⾳频时会感觉信号是连续的。金刚石研磨膏
量化位数:⽤多少bit表达⼀次采样所采集的数据,通常有8bit、16bit、24bit和32bit等⼏种。
1、python读取.wav⾳频
下⾯是python读取⾳频代码
import wave
import struct
wave_file=wave.open("./sound111.wav", 'r')
channels=hannels()#声道数
samp_width=sampwidth()#采样⼤⼩
frame_rate=framerate()#帧率
numframes=frames()#总帧数
print("channel",channels)#声道数
print('samp_width',samp_width)#采样⼤⼩2B 16bit
print('frame_rate',frame_rate)#8000 帧率8000fps
print('numframes',numframes)#总帧数=帧率*时间=8000fps*10s=80000f
#输出
#channel 1
#samp_width 2
#frame_rate 8000
#numframes 80000
for i in range(500):
frame=adframes(1)#读取1帧⾳频数据,可能包含多个声道信息
print(frame,struct.unpack("h",frame[0:2])[0])#struct.unpack("h",frame[0:2])将⼆进制数据转化成10进制(16bit有符号整数)因为这⾥采样⼤⼩是16bit
#输出
#b'\xd4\xfc' -812
#...
#b'\x07\xff' -249
#b'\x05\xff' -251
#b'X\xff' -168乳化石蜡
#b'\xf2\xff' -14
#b'0\x00' 48
#b'#\x00' 35
wave_file.close()
2、python写.wav⾳频⽂件
在写⼊第⼀帧数据时,先通过调⽤setnframes()设置好帧数,setnchannels()设置好声道数,setsampwidth()设置量化位
数,setframerate()设置好采样频率,然后string())⽤于写⼊帧数据。
Wave_write = wave.open(file,mode="wb")
Wave_write是写⽂件流,
Wave_write.setnchannels(n) 设置通道数。Wave_write.setsampwidth(n) 将样本宽度设置为n个字节,量化位数
Wave_write.setframerate(n) 将采样频率设置为n。Wave_write.setnframes(n) 将帧数设置为n
Wave_write.setparams(tuple) 以元组形式设置所有参数(nchannels, sampwidth, framerate, nframes,comptype, compname) Wave_write.writeframes(data) 写⼊data个长度的⾳频,以采样点为单位
ll() 返回⽂件中的当前位置
写wav⽂件:
# -*- coding: utf-8 -*-
import wave
import numpy as np
import scipy.signal as signal
framerate = 44100 # 采样频率
time = 10 # 持续时间
t = np.arange(0, time, 1.0/framerate)
# 调⽤scipy.signal库中的chrip函数,
# 产⽣长度为10秒、取样频率为44.1kHz、100Hz到1kHz的频率扫描波
wave_data = signal.chirp(t, 100, time, 1000, method='linear') * 10000
# 由于chrip函数返回的数组为float64型,
# 需要调⽤数组的astype⽅法将其转换为short型。
wave_data = wave_data.astype(np.short)
# 打开WAV⾳频⽤来写操作
f = wave.open(r"sweep.wav", "wb")
f.setnchannels(1) # 配置声道数
f.setsampwidth(2) # 配置量化位数
f.setframerate(framerate) # 配置取样频率
comptype = "NONE"
compname = "not compressed"
# 也可以⽤setparams⼀次性配置所有参数
# outwave.setparams((1, 2, framerate, nframes,comptype, compname))
# 将wav_data转换为⼆进制数据写⼊⽂件
f.writeframes(string())
f.close()
参考⽂献:
⾳频基础知识
⾳频信号的读写、播放及录⾳Python标准库wav模块Python⾳频处理