【语音处理】
为单片机实验服务的语音模块
语音处理（Speech processing），又称语音讯号处理、人声处理，其目的是希望做出想要的讯号，进一步做语音辨识，应用到手机介面甚至一般生活中，使人与电脑能进行沟通。
==语音的相关常识==
===一般声音档格式===
*取样频率：22050Hz
*单声道或双声道
*每笔资料用8个bit来表示
*电脑中没有经过任何压缩的声音档：*.wav
===声音的频率===
*频率范围
人耳可以辨识频率：20Hz ~ 20000Hz
说话：150~2000Hz
电话系统频域：小于3500Hz
电脑音效卡取样频率：44100Hz (最新技术可达192K)(一般用22050Hz、11025Hz 即可)
*超音波(ultrasound)与次声波(infrasound)
超音波(ultrasound)：> 20000Hz
次声波(infrasound)：>> fs
22050
>>> num_frame
122868
====读取波形与数据====
要先import 相关模组: import numpy as np
*str_data = wavefile.readframes(num_frame)
*wave_data = np.frombuffer(str_data, dtype=np.int16) # 转成整数型态
*wave_data = wave_data / max(abs(wave_data))  # normalization
*n_channel = 2
*wave_data = np.reshape(wave_data, (num_frame, n_channel)) # 若为双声道音档需要做reshape
====画出音讯波形图====
要先import 相关模组: import matplotlib.pyplot as plt
*time = np.arange(0, num_frame)*1/fs
*plt.plot(time, wave_data)
*plt.show()
===画出频谱===
要先import 相关模组: from scipy.fftpack import fft
*fft_data = abs(fft(wave_data:,1))/fs # only choose the 1st channel # 注意要乘上1/fs
*n0=int(np.ceil(num_frame/2))
*fft_data1=np.concatenate(fft_datan0:num_frame,fft_data0:n0) # 将频谱后面一半移到前面
*freq=np.concatenate(range(n0-num_frame,0),range(0,n0))*fs/num_frame # 频率轴跟著调整
*plt.plot(freq,fft_data1)
*plt.xlim(-1000,1000) # 限制频率的显示范围
*plt.show()
===播放声音===
要先import 相关模组: import simpleaudio as sa
*n_bytes =2  # using two bytes to record a data
*wave_data = (2**15-1)* wave_data  # change the range to -215 ~ 215
*wave_data = wave_data.astype(np.int16)
*play_obj = sa.play_buffer(wave_data, n_channel, n_bytes, fs)
*play_obj.wait_done()
===制作音档===
*f = wave.open('testing.wav', 'wb')
*f.setnchannels(2) # 设定声道数
*f.setsampwidth(2) # 每个samples 有几个位元组
*f.setframerate(fs) # 设定取样频率
*f.writeframes(wave_data.tobytes())
*f.close()
===录音===
要先import 相关模组: import pyaudio
import pyaudio
pa=pyaudio.PyAudio()
fs = 44100
chunk = 1024
stream = pa.open(format=pyaudio.paInt16, channels=1,rate=fs, input=True, frames_per_buffer=chunk)
vocal=
count=0
==时频分析结果分析==
===Matlab===
====画出时频分析结果====
可采行两种方式：
*使用mesh 指令画出立体图(但结果不一定清楚，且执行时间较久)
*将amplitude 变为gray-level，用显示灰阶图的方法将结果表现出来
假设y 是时频分析计算的结果
image(abs(y)/max(max(abs(y)))*C) % C 是一个常数，可以选C=400
或image(t, f, abs(y)/max(max(abs(y)))*C)
colormap(gray(256)) % 变成gray-level 的图
set(gca,'Ydir','normal') % 若没这一行, y-axis 的方向是倒过来的
set(gca,'Fontsize',12) % 改变横纵轴数值的font sizes
xlabel('Time (Sec)','Fontsize',12) % x-axis
ylabel('Frequency (Hz)','Fontsize',12) % y-axis
title('STFT of x(t)','Fontsize',12) % title
====计算程式执行时间的指令====
tic (这指令如同按下码表)
toc (show 出码表按下后已经执行了多少时间)
注：通常程式执行第一次时，由于要做程式的编译，所得出的执行时间会比较长。程式执行第二次以后所得出的执行时间，是较为正确的结果
===Python===
====事前安装模组====
*pip install numpy
*pip install matplotlib
====画出时频分析结果====
假设y为时频分析结果(应为二维的矩阵数列)，将y 以灰阶方式画出来
import numpy as np
import matplotlib.pyplot as plt
C = 400
y = np.abs(y) / np.max(np.abs(y)) * C
plt.imshow(y, cmap='gray', origin='lower') # 加上origin='lower' 避免上下相反
plt.xlabel('Time (Sec)')
plt.ylabel('Frequency (Hz)')
plt.show()
若要加上座标轴数值(在plt.show()之前加上以下程式码)
x_label = '0', '10', '20', '30' # 横轴座标值
y_label = '-5', '0', '5' # 纵轴座标值
plt.xticks(np.arange(0, x_max, step=int(x_max/(len(x_label)-1)), x_label)
plt.yticks(np.arange(0, y_max, step=int(y_max/(len(y_label)-1)), y_label)
==语音讯号的来源==
人声是由于声带震动，而产生声音。当运动肌肉挤压，使肺脏中的空气通过声带时，空气流动使得声带做周期性的震动，又再一次震动了空气，接著，带著动能的空气离开气管到达口腔或鼻腔，在腔室中震动，最后离开在嘴唇传到人耳变成声音。
若调整口腔中舌头的位置，会产生不同种类的声音，如果舌头没有做太多的动作，空气只有在口腔中共振，接著直接流出嘴唇，会产生母音，若提起舌头，使口鼻腔相通，则会出现鼻音。
==语音讯号分类==
从中文发音的观点来说，声音仍可分为子音与母音，母音和子音可以用两种方式区分：
* 发声方式：一般而言，母音跟嘴唇形状有关，而且不与鼻腔共振。相对而言，在发出子音时，就会运用到鼻腔配合发声。
* 频谱分析：从频谱上观察可以发现子音的讯号频率较高，持续时间较短，且会在母音之前出现。而母音的频率较低，持续时间较长，在子音后或独立出现，另外，母音的能量也会比子音大。
下面列出中文注音符号中的母音、子音及其拼音。
*母音：ㄚ ㄛ ㄜ ㄝ ㄞ ㄟ ㄠ ㄡ ㄢ ㄣ ㄤ ㄥ ㄦ 一 ㄨ ㄩ
*子音：ㄅ ㄆ ㄇ ㄈ ㄉ ㄊ ㄋ ㄌ ㄍ ㄎ ㄏ ㄐ ㄑ ㄒ ㄓ ㄔ ㄕ ㄖ ㄗ ㄘ ㄙ
==语音的架构==
要分析语音讯号前，必须先了解其架构，语音的要素从小到大分别是：音素→音节→词汇→句子→整段话。
音素是声音的最小单位，例如「呵」这个字的音素，就是「ㄏ」和「ㄜ」，但是音素和注音符号并不相等，例如「鸥」虽然只有「ㄡ」这个母音，但是由于是双母音，所以会把他拆成两个音素。音节在中文而言，就是只一个字，例如：「天天开心」就有四个音节。词汇是文字组成的有意义片段，各种不同的词汇集结成句子，最后变成整段话，这就是语音的架构。
==语音处理方法==
用麦克风或其他装置收到的类音声音讯号，经由类比数位转换装置，将资料数据化进行处理，最后再经过数位类比转换装置输出。因此，我们在处理时是针对数位讯号，语音讯号是一种离散时间讯号。其讯号处理流程如下：
# 收取并取样讯号：利用麦克风或各种收音装置，收取类比语音讯号，再用ADC装置(如类比数位转换卡)把类比讯号变成数位讯号，接著根据奈奎斯特理论作取样，若不符合理论则会造成讯号失真。
# 量化及编码：由于电脑中的记忆都是0和1，因此要将所收到的数据用一段适合的0跟1去储存，这个动作就称为量化，所使用的0与1越多，所需的记忆体越多。接著利用编码器将数值以波形呈现，因此虽然是数位讯号，但是在电脑中所见到的是类比。
# 讯号标准化：将语音讯号标准化，使其数值都落在同一个范围。
# 音框选择：由于语音讯号是一段很长的讯号，因此会针对想要处理的部分取音框。
# 端点侦测：端点侦测的目的是使讯号处理的范围更精确，只要设定一个音量阈值，若讯号小于阈值，则将其视为没讯号，但是若杂讯过高，则会产生误差。
# 去杂讯：由于杂讯多集中在高频的部分，因此利用简单的高频滤波器，就可以去掉部分杂讯。
==基本处理方法==
语音讯号是属于离散时间系统，因此会用离散时间的傅立叶转换去做处理，除此之外，折积、窗函数都是一定会使用到的处理方法。
* 离散时间傅立叶转换：
* 折积：
两讯号做convolution等于，两讯号先做傅立叶转换，相乘后再做反傅立叶转换，借此可以更快速的处理讯号。
==语音处理的应用==
语音处理主要有两个目的：
* 减少讯号杂讯，做出想要的讯号模组。
* 进行语音辨识，使人可以利用语言与电脑沟通。