Skip to content

Yanshee声音原理 1 声音传播中的秘密

UBTEDU edited this page Nov 7, 2018 · 5 revisions

课程目标

通过本教程,我们可以学到如下知识:音频的基本知识,关于A/D, D/A转换、采样及采样率、声道及码率的计算方法、音频文件的有损压缩和无损压缩的区别及原理等。最后我们会学习如何使用YanShee机器人录音,并利用python编写程序读取音频数据并播放出来。

课程引入原因

声音是自然界中最重要的沟通方式,我们通过语言和声音来完成相应的意图传达,而声音传播的基本原理是什么?我们通常听到的电子产品发出的声音是怎么回事?在音乐方面,我们很直观地联想到我们喜欢的音乐和歌手。在听音乐的时候我们是否注意到有的音乐是无损的,有的是有损的?通过这个课程,带你走进音频的神秘的世界,了解什么是声道、什么是采样及采样位数、码率还有有损、无损压缩等基本概念。我们会发现原来Yanshee也可以学着别人说话。

环境准备

硬件

YanShee机器人一台

  • 无线键盘鼠标一套
  • HDMI 显示器一个

软件

  • Xshell、树莓派rasbian系统

基本术语介绍

A/D、D/A转换

在音频处理时要先把音频的模拟信号变成数字信号,这叫A/D转换。当要把音频播放出来时则需要把数字信号转换成模拟信号,这叫D/A转换。

采样和采样频率

要把音频的模拟信号变成数字信号,就需要采样,或者叫抽样。 一秒钟内采样的次数称为采样频率。

采样位数

数字信号是用0和1来表示的。采样位数就是采样值用多少位0和1来表示,也叫采样精度,用的位数越多就越接近真实声音。如用8位表示,采样值取值范围就是-128--127,如用16位表示,采样值取值范围就是-32768--32767。现在一般都用16位采样位数。

声道

通常语音只用一个声道。而对于音乐来说,既可以是单声道(mono),也可以是双声道(即左声道右声道,叫立体声stereo),还可以是多声道,叫环绕立体声,多用于影院中。

脉冲编码调制

脉冲编码调制(Pulse Code Modulation),简称PCM。是对连续变化的模拟信号进行抽样、量化和编码产生的数字信号。脉冲编码调制(Pulse Code Modulation)是最常用、最简单的波形编码。它是一种直接、简单地把语音经抽样、A/D转换得到的数字均匀量化后进行编码的方法,是其他编码算法的基础。

码率

表示经过编码(压缩)后的音频数据每秒钟需要用多少个比特来表示。比特率与音频压缩的关系简单的说就是比特率越高音质就越好,但编码后的文件就越大。

音频的编码格式

前面提到音频的码率和实际的音质有关,高音质的音频文件一般都很大。但是由于人的听觉范围是20-20000Hz,有的声音人是听不到的,所以在音频压缩的时候可以考虑去掉人听不到的那些声音以达到减少音频文件大小的目的。这就是有损压缩。 而无损压缩主要是利用信息冗余进行数据压缩。无损压缩是一个可逆的过程。无损压缩比较适合在需要反复存档、读取的工作上。 下面是同一文件的有损压缩和无损压缩的频谱图。

无损压缩频谱图

有损压缩频谱图

可以看到有损压缩的频谱比无损压缩的频谱少了一些。

无损压缩

无损的音频格式解压时不会产生数据或质量上的损失,解压产生的数据与未压缩的数据完全相同。如需要保证音乐的原始质量,应当选择无损音频编解码器。常见的无损压缩格式有: WAV,PCM,ALS,ALAC,TAK,FLAC,APE,WavPack(WV)

有损压缩

有损文件格式是基于声学心理学的模型,除去人类很难或根本听不到的声音。常见的音频压缩格式有:MP3,AAC,WMA,Ogg Vorbis

音频编解码的基本原理

音频压缩原理

编码

数字音频的由于不压缩通常比较大,不利于存储和传输。比如一个双声道的数字音频的采样频率为44.1KHz,采样位数为16bit。那么它的码率为:

**2(声道)*44.1KHz (采样频率) * 16(采样位数) = 1.411Mbit/s**

如果要传输一个这样的音频,那么每秒要传输1.411Mbit的数据。这还是一个普通的音频文件,所以即使对于发达的网络也是一个不少的负担。这也是为什么通常音频文件都需要各大式各样的压缩算法来处理后再传输和存储。这个压缩的过程也就是编码。

编码可以分为前面提到的无损压缩方式的编码,有损方式的编码。无损的编码由于解码后可以恢复编码之前完全一样的信息,所以编码是基于一些可逆的压缩算法。比如Shannon-Fano编码,Huffman编码,LZW(Lempel-Ziv-Welch)编码,行程(Run-length)编码等。

下面以Huffman编码为例,它使用变长编码表对源符号(如文件中的一个字母)进行编码,其中变长编码表是通过一种评估来源符号出现机率的方法得到的,出现机率高的字母使用较短的编码,反之出现机率低的则使用较长的编码,这便使编码之后的字符串的平均长度、期望值降低,从而达到无损压缩数据的目的。

关于Huffman编码的详细介绍请参看:

https://en.wikipedia.org/wiki/Huffman_coding

Huffman编码

下面介绍一下有损压缩的其本原理。有损压缩就是把音频中人耳不敏感的声音去掉,以达到减少音频文件体积的目的。在音频压缩的时候有一个概念叫冗余信息。冗余信息指的就是音频中不能被人感知的信号。人能感受到的频率范围为20HZ--20kHZ, 此外其他的频率人是无法察觉的。在有损压缩的算法中除了冗余信息可以去掉外,还有一些其于人的生理和心理的声学现象可以去掉的一些信息。例如频谱掩蔽效应和时域掩蔽效应。

频谱掩蔽效应

一个频率的声音能量小于某个阈值之后,人耳就会听不到,这个阈值称为最小可闻阈。当有另外能量较大的声音出现的时候,该声音频率附近的阈值会提高很多,即所谓的掩蔽效应。如图所示:

频谱掩蔽效应

由图中我们可以看出人耳对2KHz~5KHz的声音最敏感,而对频率太低或太高的声音信号都很迟钝,当有一个频率为0.2KHz、强度为60dB的声音出现时,其附近的阈值提高了很多。由图中我们可以看出在0.1KHz以下、1KHz以上的部分,由于离0.2KHz强信号较远,不受0.2KHz强信号影响,阈值不受影响;而在0.1KHz~1KHz范围,由于0.2KHz强音的出现,阈值有较大的提升,人耳在此范围所能感觉到的最小声音强度大幅提升。如果0.1KHz~1KHz范围内的声音信号的强度在被提升的阈值曲线之下,由于它被0.2KHz强音信号所掩蔽,那么此时我们人耳只能听到0.2KHz的强音信号而根本听不见其它弱信号,这些与0.2KHz强音信号同时存在的弱音信号就可视为冗余信号而不必传送。

时域掩蔽效应

当强音信号和弱音信号同时出现时,还存在时域掩蔽效应。即两者发生时间很接近的时候,也会发生掩蔽效应。时域掩蔽过程曲线如图所示,分为前掩蔽、同时掩蔽和后掩蔽三部分。

时域掩蔽效应

由图我们可以看出,时域掩蔽效应可以分成三种:前掩蔽,同时掩蔽,后掩蔽。前掩蔽是指人耳在听到强信号之前的短暂时间内,已经存在的弱信号会被掩蔽而听不到。同时掩蔽是指当强信号与弱信号同时存在时,弱信号会被强信号所掩蔽而听不到。后掩蔽是指当强信号消失后,需经过较长的一段时间才能重新听见弱信号,称为后掩蔽。这些被掩蔽的弱信号即可视为冗余信号。

举例:我们通过下面例子使用python读取音频数据

在读取音频之前我们要用到pyaudio这个python库。 ''' sudo apt-get install python-pyaudio ''' 关于pyaudio的详细资料可以参看

https://people.csail.mit.edu/hubert/pyaudio/docs/

下面是如何读取音频的示例代码

#!/usr/bin/python
# -*- coding: utf-8 -*-

import pyaudio,wave
import os,sys

os.close(sys.stderr.fileno())
pa=pyaudio.PyAudio() 
stream=pa.open(format=pyaudio.paInt16,
channels=1,
rate=16000,
input=True, 
frames_per_buffer=2000) 

save_buffer=''

wf=wave.open('output.wav', 'wb')
wf.setnchannels(1) 
wf.setsampwidth(2) 
wf.setframerate(16000)
try:
whileTrue: 
string_audio_data=stream.read(1000)
save_buffer+=string_audio_data
iflen(save_buffer) >=160000:
wf.writeframes(save_buffer)
break
except:
wf.close()

执行python脚本

sudo python record.py

有了录制的音频文件之后,我们可以通过rasbian系统支持的音乐播放器来播放出来,通常的播放器包括:Aplay、Mpg123、Sox等,我们这里使用sox来播放。

安装sox包。可以通过下面命令直接安装。

sudo apt-get install sox 

播放WAV格式音频

$ play output.wav 

output.wav:

 File Size: 160k      Bit Rate: 256k
  Encoding: Signed PCM    
  Channels: 1 @ 16-bit   
Samplerate: 16000Hz      
Replaygain: off         
  Duration: 00:00:05.00  

In:100%  00:00:05.00 [00:00:00.00] Out:240k  [      |      ]        Clip:0    
Done.

从上面的命令输出可以看到刚才用python录制的音频采样位数是16bit 采样频率是 16000Hz。 经过计算: 16bit(采样位数) * 16000Hz(采样频率) * 1(声道) = 256000(码率)

拓展知识

请尝试修改录制的声音为2声道。再观察码率有什么变化。有了这项技能我们就能更好的完成Yanshee机器人和人类之间的声音交互,我们可以随意录制几段自己的音频,修改下格式,并检测输出效果。在这一节的基础上,后面我们会引入更多的和语音相关智能课程。