python实现Wav信号的录制与频谱分析

##matlab转python实现(四)
##后附完整代码及windows环境下的pyaudio库的安装。

Wav信号的录制与频谱分析

程序结构

录制Wav音频
读取音频信号
时域波形
频域波形

自定义函数

#定义sound recoding 函数

参数为录音时间t。

def sound_rec(t):
#定义wav文件读取函数

参数为wav文件的路径path,代码中因为保存的录音文件就在该代码路径下,可以不用输入绝对路径。返回值为:左右声道的波形数组wave_data,采样率framerate,采样率*时间nframes

def wave_read(path):
#定义画出时域上的波形图函数time plot

第一个参数为采样率,第二个参数为采样率*时间,第三个参数为左右声道的数据wave data list

def time_plt(frames,nframes,wave):
#定义画出信号频谱上的波形图函数frequence plot

第一个参数为采样率,第二个参数为左右声道的数据wave data list

def freq_plt(frames,wave):

主要进程

a.

录制音频,将音频保存在文件路径下的output.wav文件中。(本步骤可以忽略,在已经录制过音频的情况下。)

b.

读取音频信号,将双声道信号的信息存储在数组中,并得出采样率,以及信号长度。

c.

做出时域上的波形图,频域上,进行傅里叶变换,单边谱处理以及归一化处理,得出频域幅度谱,最后一起显示。

附完整代码

import wave
import pyaudio
import numpy
from pyaudio import PyAudio
import matplotlib.pyplot as plt

#定义sound recoding 函数,其参数为录音时间t
def sound_rec(t):
    # 定义数据流块
    CHUNK = 1024
    FORMAT = pyaudio.paInt16
    CHANNELS = 2
    RATE = 44100
    # 录音时间
    RECORD_SECONDS = t
    # 要写入的文件名
    WAVE_OUTPUT_FILENAME = "output.wav"
    # 创建PyAudio对象
    p = pyaudio.PyAudio()
    # 打开数据流
    stream = p.open(format=FORMAT,channels=CHANNELS,rate=RATE,input=True,frames_per_buffer=CHUNK)
    print("start recording")
    # 开始录音
    frames = []
    for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
        data = stream.read(CHUNK)
        frames.append(data)
    print("done recording")
    # 停止数据流
    stream.stop_stream()
    stream.close()
    # 关闭PyAudio
    p.terminate()
    # 写入录音文件
    wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
    wf.setnchannels(CHANNELS)
    wf.setsampwidth(p.get_sample_size(FORMAT))
    wf.setframerate(RATE)
    wf.writeframes(b''.join(frames))
    wf.close()

#定义wav文件读取函数,其参数为wav文件的路径path
#返回值为:左右声道的波形数组wave_data,采样率framerate,采样率*时间nframes
def wave_read(path):
    wf = wave.open(path, 'rb')
    # 创建PyAudio对象
    p = PyAudio()
    stream = p.open(format = p.get_format_from_width(wf.getsampwidth()),
    channels = wf.getnchannels(),
    rate = wf.getframerate(),
    output = True)
    nframes = wf.getnframes()
    framerate = wf.getframerate()
    # 读取完整的帧数据到str_data中,这是一个string类型的数据
    str_data = wf.readframes(nframes)
    wf.close()
    # 将波形数据转换成数组
    wave_data = numpy.fromstring(str_data, dtype=numpy.short)
    # 将wave_data数组改为2列,行数自动匹配
    wave_data.shape = -1,2
    # 将数组转置
    wave_data = wave_data.T
    return wave_data,framerate,nframes

#定义画出时域上的波形图函数time plot
#第一个参数为采样率,第二个参数为采样率*时间,第三个参数为左右声道的数据wave data list
def time_plt(frames,nframes,wave):
    # time也是一个数组,与wave_data[0]或wave_data[1]配对形成系列点坐标
    time = numpy.arange(0, nframes)*(1.0/frames)
    # 绘制波形图
    plt.figure(num=1,figsize=(6,4))
    plt.subplot(211)
    plt.plot(time, wave[0], c='r')
    plt.subplot(212)
    plt.plot(time, wave[1], c='g')
    plt.xlabel('time (seconds)')
    plt.ylabel('ampliude')

#定义画出信号频域上的波形函数frequence plot
#第一个参数为采样率,第二个参数为左右声道的数据wave data list
def freq_plt(frames,wave):
    # 采样点数,修改采样点数和起始位置进行不同位置和长度的音频波形分析
    N = 44100
    start = 0  # 开始采样位置
    df = frames/(N-1)  # 分辨率
    freq = [df*n for n in range(0, N)]  # N个元素
    wave_data2 = wave[0][start:start+N]
    c = numpy.fft.fft(wave_data2)*2/N
    # 常规显示采样频率一半的频谱
    d = int(len(c)/2)
    # 仅显示频率在4000以下的频谱
    while freq[d] > 4000:
        d -= 10
    plt.figure(num=2,figsize=(6,4))
    plt.plot(freq[:d-1], abs(c[:d-1]), 'r')

#sound_rec(5)
wave,frames,nframes=wave_read('output.wav')
time_plt(frames,nframes,wave)
freq_plt(frames,wave)
plt.show()

windows下安装pyaudio库

建议工具:一个python编辑器(用来查看你的python.exe存放的位置),windows powershell。

首先下载一个

直接使用pip install来安装会报错error:failed building wheel for pyaudio。

找适合自己的版本,本机环境为window+python3.7选择了PyAudio-0.2.11-cp37-cp37m-win_amd64.whl。自己看情况选择。

下载完后放在自己的python的Scripts文件夹下;这里找不到可以在自己的python编辑器里面找路径,会方便一点。

之后通过powershell进入scripts文件夹下:

~$: cd Scripts
~/Scripts$:  pip install  PyAudio-0.2.11-cp37-cp37m-win_amd64.whl
~/Scripts$:  pip install pyaudio

最后试用上述代码,没报错就为成功。

你可能感兴趣的:(python)