python做语音信号处理

article/2025/10/22 0:40:37

作者:凌逆战

时间:2019年11月1日

博客园地址:python做语音信号处理 - 凌逆战 - 博客园


音频信号的读写、播放及录音

  python已经支持WAV格式的书写,而实时的声音输入输出需要安装pyAudio(PyAudio: PortAudio v19 Python Bindings)。最后我们还将使用pyMedia(http://pymedia.org)进行Mp3的解码和播放。

  音频信号是模拟信号,我们需要将其保存为数字信号,才能对语音进行算法操作,WAV是Microsoft开发的一种声音文件格式,通常被用来保存未压缩的声音数据。

语音信号有四个重要的参数:声道数、采样频率、量化位数(位深)和比特率。

  • 声道数:可以是单声道、双声道 ...
  • 采样频率(Sample rate):每秒内对声音信号采样样本的总数目,44100Hz采样频率意味着每秒钟信号被分解成44100份。换句话说,每隔$\frac{1}{44100}$秒就会存储一次,如果采样率高,那么媒体播放音频时会感觉信号是连续的。
  • 量化位数(Bit depth):也称为“位深”,每个采样点中信息的比特(bit)数。1 byte等于8 bit。通常有8bit、16bit、24bit、32bit...
  • 比特率(Bit rate):每秒处理多少个Bit。比如一个单声道,用44.1KHz/16Bit的配置来说,它的比特率就为44100*16*1=705600,单位是bit/s(或者bps),因为通常计算出来的数字都比较大,大家就用kbit/s了,也就是705.6kbit/s。在对音频进行压缩时,比特率就成为了我们的一个要选的选项了,越高的比特率,其音质也就越好。一些常用的比特率有:
    • 32kbit/s: 一般只适用于语音
    • 96kbit/s: 一般用于语音或低质量流媒体
    • 128或160kbit/s: 中等比特率质量
    • 192kbit/s: 中等质量比特率
    • 256kbit/s: 常用的高质量比特率
    • 320kbit/s: MP3标准支持的最高水平

  如果你需要自己录制和编辑声音文件,推荐使用Audacity,它是一款开源的、跨平台、多声道的录音编辑软件。在我的工作中经常使用Audacity进行声音信号的录制,然后再输出成WAV文件供Python程序处理。

  如果想要快速看语音波形和语谱图,推荐使用Adobe Audition,他是Adobe公司开发专门处理音频的专业软件,微博关注vposy,下载地址见置顶。他破解了很多adobe公司的软件,包括PS、PR...

读取音频文件

wave库

  wave库是python的标准库,对于python来说相对底层,wave不支持压缩/解压,但支持单声道/立体声语音的读取。

wave_read = wave.open(file,mode="rb")

参数

  • f:语音文件名或文件路径
  • mode:读或写
    • "rb":只读模式
    • "wb":只写模式

返回:读取的文件流

  该open()函数可用于with声明中。当with块完成时,wave_read.close()或wave_write.close()方法被调用

文件路径:

例如voice.wav文件在路径C:\Users\Never\Desktop\code for the speech的文件夹里

  则file有以下三种填写格式:

    r"C:\Users\Never\Desktop\code for the speech\voice.wav"

    "C:/Users/Never/Desktop/code for the speech/voice.wav"

    "C:\\Users\\Never\\Desktop\\code for the speech\\voice.wav"

  三者等价,右划线\为转意字符,如果要表达\则需要\\,引号前面加r表示原始字符串。

wave_read.getparams():一次性返回所有的音频参数,返回的是一个元组(声道数,量化位数(byte单位),采样频率,采样点数,压缩类型,压缩类型的描述)。(nchannels, sampwidth, framerate, nframes, comptype, compname)wave模块只支持非压缩的数据,因此可以忽略最后两个信息。

str_data = wave_read.readframes(nframes):读取的长度(以取样点为单位),返回的是字符串类型的数据

wave_data = np.fromstring(str_data, dtype=np.float16):将上面字符串类型数据转换为一维float16类型的数组。

现在的wave_data是一个一维的short类型的数组,但是因为我们的声音文件是双声道的,因此它由左右两个声道的取样交替构成:LR

wave_data.shape = (-1, 2)  # -1的意思就是没有指定,根据另一个维度的数量进行分割,得到n行2列的数组。

wave_read.close()  关闭文件流wave

wave_read.getnchannels()  返回音频通道的数量(1对于单声道,2对于立体声)。

wave_read.getsampwidth()  以字节为单位返回样本宽度

wave_read.getframerate()  返回采样频率。

wave_read.getnframes()   返回音频帧数。

wave_read.rewind()      将文件指针倒回到音频流的开头。

wave_read.tell()      返回当前文件指针位置。 

读取通道数为2的音频信号

librosa库 (推荐)

  这是我最常用也是最喜欢的语音库,librosa是python第三方库,我们在使用前需要在cmd终端运行: pip install librosa ,关于librosa的介绍我专门写了一篇博客librosa语音信号处理。

import librosay, sr = librosa.load(path, sr=fs)

  该函数是会改变声音的采样频率的。如果 sr 缺省,librosa.load()会默认以22050的采样率读取音频文件,高于该采样率的音频文件会被下采样,低于该采样率的文件会被上采样。因此,如果希望以原始采样率读取音频文件,sr 应当设为 None。具体做法为 y, sr = librosa(filename, sr=None)。

音频数据 y 是直接经过归一化的数组

scipy库

from scipy.io import wavfilesampling_freq, audio = wavfile.read("***.wav")

audio 是直接经过归一化的数组

写音频文件

wave库

在写入第一帧数据时,先通过调用setnframes()设置好帧数,setnchannels()设置好声道数,setsampwidth()设置量化位数,setframerate()设置好采样频率,然后writeframes(wave.tostring())用于写入帧数据。

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个长度的音频,以采样点为单位
  • wave_write.tell()  返回文件中的当前位置

写wav文件

写WAV文件方法2

librosa库 (推荐)

librosa.output.write_wav(path, y, sr, norm=False)

参数

  • path:str,保存输出wav文件的路径
  • y:np.ndarry 音频时间序列
  • sr:y的采样率
  • norm:True/False,是否启动幅值归一化

在0.8.0以后的版本,librosa都会将这个函数删除,推荐用下面的函数:

import soundfilesoundfile.write(file, data, samplerate)

参数:

  • file:保存输出wav文件的路径
  • data:音频数据
  • samplerate:采样率

scipy库

from scipy.io.wavfile import writewrite(output_filename, freq, audio)

写WAV文件

合成有音调的音乐

合成音调

tone_freq_map

音频播放

wav文件的播放用到的是pyaudio库

p = pyaudio.PyAudio()

stream = p.open(format = p.get_format_from_width(sampwidth) , channels ,rate ,output = True)

stream.write(data)  # 播放data数据

以下列出pyaudio对象的open()方法的主要参数:

  • rate:取样频率
  • channels:声道数
  • format:取样值的量化格式 (paFloat32, paInt32, paInt24, paInt16, paInt8 ...)。在上面的例子中,使用get_format_from_width方法将wf.sampwidth()的返回值2转换为paInt16
  • input:输入流标志,如果为True的话则开启输入流
  • output:输出流标志,如果为True的话则开启输出流
  • input_device_index:输入流所使用的设备的编号,如果不指定的话,则使用系统的缺省设备
  • output_device_index:输出流所使用的设备的编号,如果不指定的话,则使用系统的缺省设备
  • frames_per_buffer:底层的缓存的块的大小,底层的缓存由N个同样大小的块组成
  • start:指定是否立即开启输入输出流,缺省值为True

播放wav音频

录音

  以SAMPLING_RATE为采样频率,每次读入一块有NUM_SAMPLES个采样的数据块,当读入的采样数据中有COUNT_NUM个值大于LEVEL的取样的时候,将数据保存进WAV文件,一旦开始保存数据,所保存的数据长度最短为SAVE_LENGTH个块。WAV文件以保存时的时刻作为文件名。

  从声卡读入的数据和从WAV文件读入的类似,都是二进制数据,由于我们用paInt16格式(16bit的short类型)保存采样值,因此将它自己转换为dtype为np.short的数组。

View Code

语音信号处理

语音信号的产生和感知

  我们要对语音进行分析,首先要提取能够表示该语音的特征参数,有了特征参数才可能利用这些参数进行有效的处理,在对语音信号处理的过程中,语音信号的质量不仅取决于处理方法,同时取决于时候选对了合适的特征参数。

  语音信号是一个非平稳的时变信号,但语音信号是由声门的激励脉冲通过声道形成的,而声道(人的口腔、鼻腔)的肌肉运动是缓慢的,所以“短时间”(10~30ms)内可以认为语音信号是平稳时不变的。由此构成了语音信号的“短时分析技术”。

  在短时分析中,将语音信号分为一段一段的语音帧,每一帧一般取10~30ms,我们的研究就建立在每一帧的语音特征分析上。

  提取的不同的语音特征参数对应着不同的语音信号分析方法:时域分析、频域分析、倒谱域分析...由于语音信号最重要的感知特性反映在功率谱上,而相位变化只起到很小的作用,所有语音频域分析更加重要。

信号加窗 

1、矩形窗

$$w(n)=\left\{\begin{matrix} 1&&0\leq n\leq L-1\\ 0&&其他 \end{matrix}\right.$$

2、汉明窗(Hamming)

$$w(n)=\left\{\begin{matrix} \frac{1}{2}(1-cos(\frac{2\pi n}{L-1}))&&0\leq n\leq L-1\\  0&&其他 \end{matrix}\right.$$

3、海宁窗(Hanning)

$$w(n)=\left\{\begin{matrix} 0.54-0.46cos(\frac{2\pi n}{L-1})&&0\leq n\leq L-1\\  0&&其他 \end{matrix}\right.$$

通常对信号截断、分帧需要加窗,因为截断都有频域能量泄露,而窗函数可以减少截断带来的影响。

窗函数在scipy.signal信号处理工具箱中,如hanning窗:

signal.hanning(winl)

信号分帧

  在分帧中,相邻两帧之间会有一部分重叠,帧长(wlen) = 重叠(overlap)+帧移(inc),如果相邻两帧之间不重叠,那么由于窗函数的形状,截取到的语音帧边缘会出现损失,所以要设置重叠部分。inc为帧移,表示后一帧第前一帧的偏移量,fs表示采样率,fn表示一段语音信号的分帧数。

$$fn=\frac{N-overlap}{inc}=\frac{N-wlen+inc}{inc}$$

  信号分帧的理论依据,其中x是语音信号,w是窗函数:

$$y(n)=\sum_{n=-N / 2+1}^{N / 2} x(m) w(n-m)$$

  加窗截断类似采样,为了保证相邻帧不至于差别过大,通常帧与帧之间有帧移,其实就是插值平滑的作用。

给出示意图:

 这里主要用到numpy工具包,涉及的指令有:

  • np.repeat:主要是直接重复
  • np.tile:主要是周期性重复

对比一下:

向量情况:

矩阵情况:

对于数据:

repeat操作:

tile操作:

对应结果:

对应分帧的代码实现:

 这是没有加窗的示例:

没有加窗的语音分帧

加窗的语音分帧

overlap and add

  将分帧好的语音拼接回完整的语音

def overlap_add(x, window_size, hop_size):# x (frames, frame_length)frames, frame_length = x.shapewav_len = frames * hop_size + window_size - hop_size  # 帧长print("帧长", wav_len)wav = np.zeros((wav_len,), dtype=x.dtype)for frame in range(frames):if frame == frames - 1:# 最后一帧wav[hop_size * frame: hop_size * frame + window_size] += x[frame]  # 把整帧前加进去else:wav[hop_size * frame: hop_size * frame + hop_size] += x[frame][:hop_size]  # 把帧前加进去return wav

语音信号的短时时域处理

短时能量和短时平均幅度

  短时能量和短时平均幅度的主要用途:

  • 区分浊音和清音段,因为浊音的短时能量$E(i)$比清音大很多;
  • 区分声母和韵母的分界和无话段和有话段的分界

短时平均过零率

  对于连续语音信号,过零率意味着时域波形通过时间轴,对于离散信号,如果相邻的取样值改变符号,则称为过零。

作用

  • 发浊音时由于声门波引起谱的高频跌落,所以语音信号能量约集中在3kHz以下
  • 发清音时多数能量集中在较高的频率上,

因为高频意味着高的短时平均过零率,低频意味着低的短时平均过零率,所以浊音时具有较低的过零率,而清音时具有较高的过零率。

  1. 利用短时平均过零率可以从背景噪声中找出语音信号,
  2. 可以用于判断寂静无话段与有话段的起点和终止位置。
  3. 在背景噪声较小的时候,用平均能量识别较为有效,在背景噪声较大的时候,用短时平均过零率识别较为有效。

短时自相关函数

  短时自相关函数主要应用于端点检测和基音的提取,在韵母基因频率整数倍处将出现峰值特性,通常根据除R(0)外的第一峰值来估计基音,而在声母的短时自相关函数中看不到明显的峰值。

短时平均幅度差函数

  用于检测基音周期,而且在计算上比短时自相关函数更加简单。

语音信号的短时频域处理

  在语音信号处理中,在语音信号处理中,信号在频域或其他变换域上的分析处理占重要的位置,在频域上研究语音可以使信号在时域上无法表现出来的某些特征变得十分明显,一个音频信号的本质是由其频率内容决定的,

将时域信号转换为频域信号一般对语音进行短时傅里叶变换

fft_audio = np.fft.fft(audio)

绘制语音信号的频谱图

提取频域特征

  将信号转换为频域之后,还需要将其转换为有用的形式,梅尔频率倒谱系数(MFCC),MFCC首先计算信号的功率谱,然后用滤波器组和离散余弦变换的组合来提取特征。

提取MFCC特征

语谱图

绝大部分信号都可以分解为若干不同频率的正弦波。
这些正弦波中,频率最低的称为信号的基波,其余称为信号的谐波。
基波只有一个,可以称为一次谐波,谐波可以有很多个,每次谐波的频率是基波频率的整数倍。谐波的大小可能互不相同。
以谐波的频率为横坐标,幅值(大小)为纵坐标,绘制的系列条形图,称为频谱。频谱能够准确反映信号的内部构造。

  语谱图综合了时域和频域的特点,明显的显示出来了语音频率随时间的变化情况,语谱图的横轴为时间,纵轴为频率任意给定频率成分在给定时刻的强弱用颜色深浅表示。颜色深表示频谱值大,颜色浅表示频谱值小,语谱图上不同的黑白程度形成不同的纹路,称为声纹,不用讲话者的声纹是不一样的,可以用做声纹识别。

其实得到了分帧信号,频域变换取幅值,就可以得到语谱图,如果仅仅是观察,matplotlib.pyplot有specgram指令:

语谱图

MATLAB语谱图

语音识别

View Code

我对上面这段代码专门写了一篇博客来进一步讲解和分析,想详细了解的读者可以移步Python实现语音识别和语音合成 - 凌逆战 - 博客园,语音数据集在这里。

参考文献

网址:用python做科学计算 http://old.sebug.net/paper/books/scipydoc/index.html#

python标准库wave模块22.4. wave — Read and write WAV files — Python 3.6.15 documentation

《python机器学习经典案例》美Prateek Joshi著

傅里叶变换的介绍:Fourier Transform

各种音阶及其对应的频率 Frequencies of Musical Notes, A4 = 440 Hz

这篇博客的代码https://github.com/LXP-Neve/Speech-signal-processing

这个网站有很多numpy写的语音信号处理代码

【知乎文章】采样率,位深以及比特率


http://chatgpt.dhexx.cn/article/VjuOjpEB.shtml

相关文章

语音信号处理知识点

语音信号处理过程的总体结构: 语音输入-->预处理-->数字化-->特征提取 预处理:对信号适当放大和增益控制,并进行反混叠滤波来消除工频信号干扰 数字化:进行A/D转换 特征提取:用反映语音信号特点的若干参数…

第一章 语音信号处理概述

一、语音交互 语音交互(VUI: Voice User Interface)是指人与人或者人与设备通过自然语音进行信息传递的过程。 1. 语音交互的优势 (1)输入效率高:相对于键盘输入,语音输入的速度是传统输入方式的3倍以上(有权威统计分析得到的数…

语音信号处理-python

语音信号处理 1.语音信号的产生与特性 我们要对语音进行分析,首先要提取能够表示该语音的特征参数,有了特征参数才可能利用这些参数进行有效的处理,在对语音信号处理的过程中,语音信号的质量不仅取决于处理方法,同时…

python实验六 语音信号处理

目录 实验目的: 实验原理: 实验准备: 实验步骤与内容: 参考代码: 实验目的: 依托语音信号处理领域的声学特征提取任务,学习常用的语音信号处理工具,实现对语音数据的预处理和常…

matlab的语音信号处理

人类交换信息最方便的、最快捷的一种方式是语言,在高度发达的信息社会中,用数字化的方法进行语音的识别、合成、增强、传送和储存等是整个数字化通信网中最重要、最基本的组成部分之一。数字电话通信、高音质的窄带语音通信系统、智能机器人、声控打字机…

语音信号处理 —— 笔记(一)音频信号处理

声音的产生 :能量通过声带使其振动产生一股基声音,这个基声音通过声道 ,与声道发生相互作用产生共振声音,基声音与共振声音一起传播出去。 一、音频信号简介 1.声音波形图 传感器以某种频率探测声音的振幅强度以及振动方向&…

语音信号处理的过程及其应用

一、语音信号处理的过程 在信号处理领域,信息加工和处理的一般流程下图所示。 在语音信号的具体情况下,信息源就是说话的人,通过观察和测量得到的就是语音的波形。信号处理包括以下几个内容,首先根据一个给定的模型得到这一信号的…

语音信号处理基础知识-常用特征及预处理

目录 一、语音信号的特点二、常用语音特征参数三、语音信号预处理四、参考链接 一、语音信号的特点 其主要特点如下所示:     a) 语音信号的带宽约为 5 K h z 5Khz 5Khz , 主要能量集中在低频段。     b) 语音信号总体为非平稳时变信号,一般认为…

语音信号基本知识和处理

语音信号(音频;声音)是模拟信号,现实生活中表现为连续的、平滑的波形,其横坐标为时间轴,纵坐标表示声音的强弱。 我们需要将其保存为数字信号再进行处理。 1. 声音三要素 1.1 音调 人耳对声音高低的感觉…

语音信号处理

文章目录 语音信号处理第一章 绪论第二章 语音信号处理基础知识语音和语言 **浊音的声带振动基本频率(fundamental frequency)称为基音频率。浊音的基音频率(pitch):**???&#xff1…

语音信号处理概述及流程

一、语音信号处理的三个主要方向。 1,语音合成。 语音合成的是为了让计算机产生高质量的、高自然度的连续语音。计算机语音合成系统又称文语转换系统(TTS),主要是将文本输出语音。 发展过程:共振峰合成、LPC合成、PSOL…

基于matlab的语音信号处理

摘要 利用所学习的数字信号处理知识,设计了一个有趣的音效处理系统,首先设计了几种不同的滤波器对声音进行滤波处理,分析了时域和频域的变化,比较了经过滤波处理后的声音与原来的声音有何变化。同时设计实现了语音的倒放&#xff…

【无线通信篇 | Zstack协议栈】CC2530 Zigbee Zstack协议栈组网项目及详细讲解篇

演示视频:https://www.bilibili.com/video/BV1Ew411o7Fp 物联网无线通信技术,ZigBee无线传感网络 CC2530最大的特点就是一个拥有无线收发器(RF)的单片机,既能实现单片机功能,也能实现无线传输 Zstack协议…

【Zigbee】进阶篇(1) Zigbee协议栈创建简单项目,协议栈、事件、消息学习

大家好,我是皮皮猫吖! 每文一言:梦想不会逃跑,会逃跑的永远都是自己! 本篇文章: 主要是协议栈的介绍,使用协议栈完成一个简单例子,协调器创建网络的相关问题,学会在协议…

ZigBee协议栈TI Z-Stack分析

ZigBee协议栈TI Z-Stack分析 2010-11-05 11:26 转载自 slcfhr 最终编辑 slcfhr 标签(TAG): ZigBee 协议栈 Z-Stack 2007年4月,德州仪器推出业界领先的ZigBee协议栈(Z-Stack)。Z-Stack符合ZigBee 2006规范,支持…

lesson7-1 Zigbee协议栈的使用

目录 协议栈的使用 协议栈的安装和协议栈工程创建 协议栈工程配置 选项卡选择 用户代码编写注意 信道选择及PANID分配 协议栈的使用 协议栈的安装和协议栈工程创建 首先进行协议栈的安装 如何创建自己的协议栈工程: (1)先把整个协议…

物联网--Zigbee协议(一):Zigbee初识

物联网--Zigbee协议 前言一、Zigbee初识什么是物联网?什么是Zigbee? 二、Zigbee协议的基础知识Zigbee三种设备类型Zigbee三种网络拓扑结构Zigbee工作频段 三、Zigbee协议架构总结 前言 最近在学习Zigbee的相关知识,发现网上、论坛找到的知识…

ZigBee 快速入门(协议栈,协调器,路由器,终端设备,加入网络,安全,路由功能,频段)

文章目录 1、ZigBee 是什么2、ZigBee 目标3、ZigBee 协议栈4、设备类型5、Mesh网络 拓扑结构6、加入一个 ZigBee 网络7、ZigBee 安全8、频段和速率9、ZigBee相关特性和名词9.1 CSMA/CD,CSMA/CA9.2 信道访问机制9.3 dB、dBm、dBi9.4 传播损耗9.5 RSSI、LQI9.6 接收灵…

ZigBee协议介绍

简介 ZigBee是一种无线通信标准,是由ZigBee Alliance于 2001 年基于IEEE802.15.4标准定制的,这一标准界定了低功耗、低传输速率、近距离无线通信技术所需的所有相关通信协议。基于ZigBee协议的无线通信网络的工作频段主要有2.4GHz、915MHz、868MHz三个频…

zigbee协议栈工作流程 From zigbee菜鸟笔记(十 一)

一.ZigBee 协议栈简介 有问题发送邮件至468078841qq.com 什么是ZigBee 协议栈呢?它和ZigBee 协议有什么关系呢?协议是一系列的通信标准,通信双方需要共同按照这一标准进行正常的数据发射和接收。协议栈是协议的具体实现形式,通俗点来理解就…