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

提問

老師,這個波形爲什麼抓取出來是這個樣子? 應該是連續的sin吧?這個是從你發的網盤鏈接裏面下載的 我用播放器畫出的波形。

聲音信號繪製波形

聲音信號繪製波形

我自己使用單片機, 發出的聲音不太一樣,但是波形就是您之前推文裏的那個。就像下面的波形圖所顯示的鈉鹽。

剛纔是我自己單片機生成的波形 老師發的chirp.wav,用Matplot沒問題。 但是從喇叭裏面發出來,就會很奇怪,而且播放器上面的波形也不對。
自己使用單片機產生的波形

自己使用單片機產生的波形

問題回覆

問題分析

在生成最終的聲音.wav文件的時候,使用的是16bit整型數。在python程序中爲:

wavefile.setparams((1, 2, 10000, wavelen, 'NONE', 'Tsinghua'))
函數中的參數定義分別是:(nchannels, sampwidth, framerate, nframes, comptype, compname),

生成wave波形數據使用公式如下,這將產生帶有符號的16位整形數字:
data=int[sin(2πθ)0x3FFF]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
#============================================================
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章