WAV文件中使用有符合整形数

提问

老师,这个波形为什么抓取出来是这个样子? 应该是连续的sin吧?这个是从你发的网盘链接里面下载的 我用播放器画出的波形。

声音信号绘制波形

声音信号绘制波形

我自己使用单片机, 发出的声音不太一样,但是波形就是您之前推文里的那个。就像下面的波形图所显示的钠盐。

刚才是我自己单片机生成的波形 老师发的chirp.wav,用Matplot没问题。 但是从喇叭里面发出来,就会很奇怪,而且播放器上面的波形也不对。
自己使用单片机产生的波形

自己使用单片机产生的波形

问题回复

问题分析

在生成最终的声音.wav文件的时候,使用的是16bit整型数。在python程序中为:

wavefile.setparams((1, 2, 10000, wavelen, 'NONE', 'Tsinghua'))
函数中的参数定义分别是:(nchannels, sampwidth, framerate, nframes, comptype, compname),

生成wave波形数据使用公式如下,这将产生带有符号的16位整形数字:
d a t a = i n t [ sin ( 2 π θ ) 0 x 3 F F F ] data = {\mathop{\rm int}} \left[ {\sin \left( {2\pi \theta } \right) \cdot 0x3FFF} \right]

Chip波形前面300个数据点绘制的波形如下:
有符合16位整型数波形

有符合16位整型数波形

在写入wave文件之前,需要将生成的数据转换成无符号整形数字,使用二进制补码方式进行转换:

    sd = int(sin(angle * 2 * pi) * 0x3fff)
    if sd < 0: sd = 0x10000+sd

这样wave文件的波形就变成如下图所示了:
修改成有符合整型数的波形

修改成有符合整型数的波形

而在之前没有按照二进制补码方式转换,而是直接采用16位无符号整形数来表示音频数据,转换的程序代码如下:

    sd = int(sin(angle * 2 * pi) * 0x3fff) + 0x7fff

这样绘制出来的波形如下。虽然它的波形完整,但与.wav文件所使用的有符号16位整型数据不符合,所以播放出来的声音出现较大的失真。
无符号16整型数波形

无符号16整型数波形

产生声音文件的PYTHON程序

谢谢你反馈的信息,根据前面的分析,重新修改了chirp波形文件生成python程序。后面也给出了最终的下载音频文件链接。

#!/usr/local/bin/python
# -*- coding: gbk -*-
#============================================================
# SOUNDWAV.PY                  -- by Dr. ZhuoQing 2020-03-23
#
# Note:
#============================================================

from headm import *
import wave

#------------------------------------------------------------
data_num    = 2048
ts = 1.0e-4
start_freq = 250
end_freq = 2000

sounddata = []
zerodata = []
angle = 0

for i in range(data_num):
#    sd = int((sin(angle * 2 * pi) + 1) * 0x3fff)# + 0x7fff
    sd = int(sin(angle * 2 * pi) * 0x3fff)
    if sd < 0: sd = 0x10000+sd
    sounddata.append(sd)
    zerodata.append(0)

    freq = (end_freq - start_freq) * i / data_num + start_freq
    angle = freq * ts + angle

#------------------------------------------------------------
segnum = 20
wavedata = []

for i in range(segnum):
    wavedata.extend(sounddata)
    wavedata.extend(zerodata)

wavelen = len(wavedata)

wavedatabytes = b''
for num in wavedata:
    wavedatabytes = wavedatabytes + num.to_bytes(byteorder='little', length=2)

#------------------------------------------------------------
wavefile = wave.open(r'd:\temp\chirp.wav', 'wb')
wavefile.setparams((1, 2, 10000, wavelen, 'NONE', 'Tsinghua'))
wavefile.writeframes(wavedatabytes)
wavefile.close()

printf('\a')
#------------------------------------------------------------
#        END OF FILE : SOUNDWAV.PY
#============================================================
发布了411 篇原创文章 · 获赞 418 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/zhuoqingjoking97298/article/details/105155393