WAV格式音频学习

周末没事,在家用pyaudio捣鼓了一下wav的读入,播放,与频谱分析.

正常人听觉的频率范围大约在20Hz~20kHz之间。为了保证声音不失真,采样频率应该在40kHz左右。常用的音频采样频率有8kHz、11.025kHz、22.05kHz、16kHz、37.8kHz、44.1kHz、48kHz等,如果采用更高的采样频率,还可以达到DVD的音质。

先上两个链接:

比特率:https://baike.baidu.com/item/%E6%AF%94%E7%89%B9%E7%8E%87/1022775?fr=aladdin

PCM编码:https://baike.baidu.com/item/pcm%E7%BC%96%E7%A0%81/10865033?fr=aladdin

摘一些出来学习:

音频
800 bps – 能够分辨的语音所需最低码率(需使用专用的FS-1015语音编解码器)
8 kbps —电话质量(使用语音编码)
8-500 kbps --Ogg Vorbis和MPEG1 Player1/2/3中使用的有损音频模式
500 kbps–1.4 Mbps —44.1KHz的无损音频,解码器为FLAC Audio,WavPack或Monkey's Audio
1411.2 - 2822.4 Kbps —脉冲编码调制(PCM)声音格式CD光碟的数字音频
5644.8 kbps —SACD使用的Direct Stream Digital格式

码率计算公式:
基本的算法是:【码率】(kbps)=【文件大小】(字节)X8/【时间】(秒)*1000
音频文件专用算法:【比特率】(kbps)=【量化采样点】(kHz)×【位深】(bit/采样点)×【声道数量】(一般为2)


结论:

1.一个采样率为44.1KHz,采样大小为16bit,双声道的PCM编码的WAV文件,

    比特率= 44.1K×16×2 =1411.2 Kbps。

    我们常见的Audio CD就采用了PCM编码,一张光盘的容量只能容纳72分钟的音乐信息,而常见的wav歌曲大部分是PCM格式的。

2.数据了计算:我找了首刘惜君-我很快乐

数据量=(采样频率×采样位数bit×声道数×时间)/8=[44.1×1000×16×2×(3×60+33)] /(8×1024×1024) =37573200B约35.83MB

算出来的大小与歌曲也一样,大小:35.8 MB (37,643,974 字节);占用空间:35.9 MB (37,650,432 字节)

3.一帧PCM是:2048次采样组成的(网上搜到的),但是我自己用数据算了下,感觉不对,先写下面,有懂的帮指导一下:

采样率framerate:44100Hz
帧数nframes:9410940
时长time:213s

数据量:37573200Byte

帧数nframes/时长time=9410940/213=44182帧/秒,约等与采样率,怎么回事,我算错了么。。。汗

如果按2048次计算,一帧时间播放时间 = 2048 * 1000000/44100= 46.4ms,一帧的解码时间须控制在46.4ms内。

4.PCM格式

   PCM(Pulse Code Modulation)也被称为 脉码编码调制。PCM中的声音数据没有被压缩,如果是单声道的文件,采样数据按时间的先后顺序依次存入。(它的基本组织单位是BYTE(8bit)或WORD(16bit))


样本大小      数据格式        最小值    最大值

 8位PCM    unsigned int         0       225

16位PCM      int                -32767    32767


4.文件格式



5.代码

#引入库

import wave
import numpy as np
from pyaudio import PyAudio
import pylab
import matplotlib.pyplot as plt
#定义数据流块
chunk = 2048
#只读方式打开wav文件
f = wave.open("that.wav","rb")
#创建PyAudio对象:
p = PyAudio()
#打开数据流
stream = p.open(format = p.get_format_from_width(f.getsampwidth()),
channels = f.getnchannels(),
rate = f.getframerate(),
output = True)
#读取数据
# _wave_params(nchannels=2, sampwidth=2, framerate=44100, nframes=9410940, comptype='NONE', compname='not compressed')
#(声道数,采样精度,采样率,帧数,......)
params = f.getparams()
print(params)
nchannels,sampwidth,framerate,nframes = params[0],params[1],params[2],params[3]
#读取完整的帧数据到datawav中,这是一个string类型的数据
datawav = f.readframes(nframes)
#将f关掉
f.close()
# with open("t.txt","w") as ftxt:
#
#     ftxt.writelines(str(datawav[:10000]))
#
# ftxt.close()
#将波形数据转换为数组
# A new 1-D array initialized from raw binary or text data in a string.
datause = np.fromstring(datawav, dtype=np.short)
#将wave_data数组改为2列,行数自动匹配。在修改shape的属性时,需使得数组的总长度不变。
datause.shape = -1, 2
#将数组转置,分别得到两个声道的序列
datause = datause.T
#time 得到每帧的绝对时间,也是一个数组,datause[0]datause[1]配对形成系列点坐标
#音频帧的播放时长 = 一个帧对应的采样点个数 / 采样频率(单位为s)
# 则,当前一帧的播放时间 = 2048* 1000000/44100= 46.4ms
time = np.arange(0, nframes) * (1.0/framerate) ##* chunk

#采样点数,修改采样点数和起始位置进行不同位置和长度的音频波形分析
#根据采样定理知采样频率要大于信号频率2倍,所以这里设置采样频率为44100赫兹
N = 44100       #每秒采样次数
start = 100 * N #开始采样位置
nsamp = 10 * N  #采样区间时间长度
wavedata = datause[0][start:start+nsamp]
x=np.linspace(0,1,nsamp)
yy = np.fft.fft(wavedata)
yf = abs(yy)      #取绝对值
yf1 = yf/nsamp    #归一化处理
yf2 = yf1[range(int(nsamp//2))]  #由于对称性,只取一半区间
fre = np.arange(len(yy))
fre2 = fre[range(int(len(x)//2))]  #取一半区间
##Original wave
plt.subplot(221)
plt.plot(x[0:nsamp//50],wavedata[0:nsamp//50])
plt.title('Original wave')
##绘制频谱图
plt.subplot(222)
plt.plot(fre,yf,'r')
plt.title('FFT of Mixed wave(two sides frequency range)',fontsize=7,color='#7A378B')
#归一化
plt.subplot(223)
plt.plot(fre,yf1,'g')
plt.title('FFT of Mixed wave(normalization)',fontsize=9,color='r')
#一半
plt.subplot(224)
plt.plot(fre2,yf2,'b')
plt.title('FFT of Mixed wave',fontsize=10,color='#F08080')
plt.show()
stream.write(datawav[4*start:4*start+4*nsamp])##length datawav 37643760;length datause 18821880;length wavedata 441000
##注意,四个字节为一个采样点

# plt.title("Night.wav's Frames")
# plt.subplot(211)
# plt.plot(time, datause[0],color = 'green')
# plt.subplot(212)
# plt.plot(time, datause[1])
# plt.show()

#播放
# while True:
#     data = f.readframes(chunk)
#     stream.write(data)
#     print(data)
#     if data == b'':
#         break

#停止数据流
stream.stop_stream()
stream.close()
#关闭 PyAudio
p.terminate()


#我最后验证了时间ok,start相当于从100s开始播放了10s,上面输出的与直接用播放器放出来是同一段

6.频谱分析图



7.歌曲地址

https://pan.baidu.com/s/1hmeXmfUxQVYfBd0EGKGCYQ

参考:

https://www.cnblogs.com/lzxwalex/p/6922099.html

https://www.cnblogs.com/lidabo/p/3729615.html

https://www.cnblogs.com/lzxwalex/p/6922099.html

http://blog.sina.com.cn/s/blog_40793e970102w3m2.html

https://blog.csdn.net/pi9nc/article/details/12570841

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值