python---wav音頻


import pyaudio  #導入庫
import wave   #導入wav音頻庫
import sys
from PyQt5.QtWidgets import QApplication, QWidget,QFileDialog
from pya import Ui_Form
import numpy as np
import matplotlib.pyplot as plt

class Win(QWidget,Ui_Form):
    def __init__(self):
        super(Win, self).__init__()
        self.setupUi(self)
        plt.rcParams['font.sans-serif'] = ['SimHei']  # 指定默認字體 SimHei為黑體
        plt.rcParams['axes.unicode_minus'] = False  # 用來正常顯示負號


    def dakaiwenjian(self):
        r = QFileDialog.getOpenFileName(self, '請選擇要打開的文件', '.\\', 'WAV(*.wav)',
                                        'WAV(*.wav)')
        self.lineEdit.setText(r[0])

        wf = wave.open(r[0], 'rb')  # 只讀方式打開wav文件
        #只讀模式:  ‘r’, ‘rb’  ;只寫模式:  ‘w’, ‘wb’;注意:不能同時完成讀/寫操作

        params = wf.getparams()  #讀取格式信息
        #返回的是一個元組(tuple):聲道數, 量化位數(byte單位), 采樣頻率, 采樣點數, 壓縮類型, 壓縮類型的描述
        # wave模塊只支持非壓縮的數據,因此可以忽略最后兩個信息
        print('聲道數:',params[0])
        print('量化位數:', params[1])  #量化位數(byte單位)
        #量化位數是對模擬音頻信號的幅度軸進行數字化,它決定了模擬信號數字化以后的動態范圍
        #常用於表示聲卡性能的兩個參數是采樣頻率、和模擬量轉換成數字量之后的數據位數(簡稱量化位數)。采樣頻率決定了頻率響應范圍,在計算機多媒體音頻處理中,標准的采樣頻率為:11.025kHz(語音效果)、22.05kHz(音樂效果)、44.1kHz(高保真效果)。量化位數越多,聲音的質量越高。目前聲卡的最高采樣頻率為44.1KHz。對聲波每次采樣后存儲、記錄聲音振幅所用的位數稱為采樣位數,16位聲卡的采樣位數就是16。量化位數決定了音樂的動態范圍,量化位數有8位和16位兩種。8位聲卡的聲音從最低音到最高音只有256個級別,16位聲卡有65536個高低音級別
        #采樣位數和采樣率都是時域中的參數。一段音頻(聲波)的變化曲線,從時域上看,其橫軸表示時間t,縱軸表示幅度v(一般是電壓)。那么,采樣率44.1K表示每秒鍾采樣44100個點,也就是橫軸上每隔(1/44100)秒采集一個點;而采到的每個點都用一個數值來表示其幅度(電壓)。假設整個音頻信號的變化幅度范圍是-5V~+5V的話,我們將-5V~+5V分成65536份,那么采到的這些點的數值n(16位),轉換成電壓,就是(n*10/65536)-5V。因此,采樣位數分解的是音頻電壓的幅度!當然上面只是一個例子而已。對於某些A/D轉換器來說,采集到的點的幅度值可能用補碼來表示,那么換算成電壓的公式就會不同,但將-5V~+5V這10V的變化范圍分成了65536份這一點來說,是一樣的
        #量化位數分為8位,16位,24位三種
        print('采樣頻率:', params[2])
        #每秒鍾采集數據的次數
        #頻率一般有11025Hz(11kHz) ,22050Hz(22kHz)和44100Hz(44kHz) 三種
        print('采樣點數:', params[3])
        #采樣點數決定了每次傳到pc內的數據量。比如點數設為1000,pc內會開辟初始大小1000的buffer(buffer大小可以自己改), 板卡就每采1000點往pc傳一次
        # [返回的是文件的總采樣點數]

        # getnchannels, getsampwidth, getframerate, getnframes等方法可以單獨返回WAV文件的特定的信息
        print(wf.getnchannels())  #聲道數
        print(wf.getsampwidth())  #量化位數(采樣大小,采樣寬度):波每一個時刻都有一個對應的能量值,在計算機中用整數存儲。通常使用16bit有符號整數存儲,采樣大小是16bit
        framerate=wf.getframerate()  #采樣頻率
        nframes=wf.getnframes()  #采樣點數--總幀數
        #[返回的是文件的總采樣點數]
        print('采樣點數:',nframes)

        data = wf.readframes(nframes)   # 讀取數據
        # 從流的當前指針位置一次讀出音頻的n個幀,並且指針后移n個幀,返回一個字節數組--返回的是二進制數據(一大堆bytes),在Python中用字符串表示二進制數據
        #【返回的是二進制形式的字符串】
        #傳遞一個參數指定需要讀取的長度(以取樣點為單位)
        #wf.close()  #關閉文件
        wave_data = np.frombuffer(data, dtype=np.short)  #將波形數據轉換為列表【矩陣】
        #[0 0 0 ... 0 0 0]
        #通過fromstring函數將字符串轉換為列表,通過其參數dtype指定轉換后的數據格式,由於我們的聲音格式是以兩個字節表示一個取樣值,因此采用short數據類型轉換
        wave_data.shape = -1, 2  #修改矩陣的維度
        #-1  表示行數未知;   2 表示2列
        #聲音文件是雙聲道的,因此它由左右兩個聲道的取樣交替構成:LRLRLRLR....LR(L表示左聲道的取樣值,R表示右聲道取樣值)。修改wave_data的sharp之后:
        # [[0 0]  [0 0]  ...  [0 0]  [0 0]  [0 0]]
        wave_data = wave_data.T   #將其轉置--行列轉換
        time = np.arange(0, nframes) * (1.0 / framerate)   #取樣時間--單位:秒
        # 1.0 / framerate  每個點的時間
        # np.arange(0, nframes)  產生一個一維矩陣--傳遞給pc數據中的第幾個數據

        # 繪制波形
        plt.subplot(2,1,1)
        plt.plot(time, wave_data[0])  #畫左聲道
        plt.subplot(2,1,2)
        plt.plot(time, wave_data[1], c="g")  #畫右聲道
        plt.xlabel("time (seconds--秒)")
        plt.show()




    def bofan(self):
        pass

if __name__ == '__main__':
    app = QApplication(sys.argv)
    demo = Win()
    demo.show()
    sys.exit(app.exec_())

 

上面實例下載: 

鏈接:https://pan.baidu.com/s/1DaDhI1gC4ul2Hblm7tPAFg   提取碼:opy5 

 

寫.wav音頻文件

import wave
import struct
import math

def write_frame(time,freq,framerate,file,wave=0.4,sampwidth=2):
#time 持續時間; freq 頻率; framerate采樣頻率; file 音頻文件; wave 音量; sampwidth 采樣深度
    t=0#時刻
    step=1.0/framerate #每幀間隔時長
    fw=2.0*math.pi*freq #頻率控制參數
    wave=wave*(math.pow(2,sampwidth*8-1)-1)#音量控制
    while t<=time:
        v=int(math.sin(t*fw)*wave)  #對波采樣 math.sin(t*fw)產生freq頻率的正弦波
        t+=step#更新時刻
        #最后這里是與sampwidth的值有關的,下面語句當前僅當sampwidth=2時成立,詳細信息參考struct.pack()
        file.writeframesraw(struct.pack("h",v)) #寫入文件 struct.pack("h",v)將有符號整數v轉化成16比特2進制


tw=wave.open("./two_tigers.wav","w") #打開或創建./two_tigers.wav
tw.setnchannels(1) #設置聲道數 1
tw.setframerate(8000)#設置幀率 8000
tw.setsampwidth(2)#設置采樣寬度2B 16bit

#寫入聲音
#1 2 3 1 1 2 3 1
write_frame(time=0.5, freq=256, framerate=8000, file=tw, wave=0.4, sampwidth=2)
write_frame(time=0.5, freq=288, framerate=8000, file=tw, wave=0.4, sampwidth=2)
write_frame(time=0.5, freq=320, framerate=8000, file=tw, wave=0.4, sampwidth=2)
write_frame(time=0.5, freq=256, framerate=8000, file=tw, wave=0.4, sampwidth=2)
write_frame(time=0.5, freq=256, framerate=8000, file=tw, wave=0.4, sampwidth=2)
write_frame(time=0.5, freq=288, framerate=8000, file=tw, wave=0.4, sampwidth=2)
write_frame(time=0.5, freq=320, framerate=8000, file=tw, wave=0.4, sampwidth=2)
write_frame(time=0.5, freq=256, framerate=8000, file=tw, wave=0.4, sampwidth=2)

#3 4 5 - 3 4 5 -
write_frame(time=0.5, freq=320, framerate=8000, file=tw, wave=0.4, sampwidth=2)
write_frame(time=0.5, freq=341.33, framerate=8000, file=tw, wave=0.4, sampwidth=2)
write_frame(time=0.5, freq=384, framerate=8000, file=tw, wave=0.4, sampwidth=2)
write_frame(time=0.25, freq=0, framerate=8000, file=tw, wave=0.4, sampwidth=2)
write_frame(time=0.5, freq=320, framerate=8000, file=tw, wave=0.4, sampwidth=2)
write_frame(time=0.5, freq=341.33, framerate=8000, file=tw, wave=0.4, sampwidth=2)
write_frame(time=0.5, freq=384, framerate=8000, file=tw, wave=0.4, sampwidth=2)
write_frame(time=0.25, freq=0, framerate=8000, file=tw, wave=0.4, sampwidth=2)

#56 54 3 1 - 56 54 3 1 -
write_frame(time=0.25, freq=384, framerate=8000, file=tw, wave=0.4, sampwidth=2)
write_frame(time=0.25, freq=426.67, framerate=8000, file=tw, wave=0.4, sampwidth=2)
write_frame(time=0.25, freq=384, framerate=8000, file=tw, wave=0.4, sampwidth=2)
write_frame(time=0.25, freq=341.33, framerate=8000, file=tw, wave=0.4, sampwidth=2)
write_frame(time=0.5, freq=320, framerate=8000, file=tw, wave=0.4, sampwidth=2)
write_frame(time=0.5, freq=256, framerate=8000, file=tw, wave=0.4, sampwidth=2)
write_frame(time=0.25, freq=384, framerate=8000, file=tw, wave=0.4, sampwidth=2)
write_frame(time=0.25, freq=426.67, framerate=8000, file=tw, wave=0.4, sampwidth=2)
write_frame(time=0.25, freq=384, framerate=8000, file=tw, wave=0.4, sampwidth=2)
write_frame(time=0.25, freq=341.33, framerate=8000, file=tw, wave=0.4, sampwidth=2)
write_frame(time=0.5, freq=320, framerate=8000, file=tw, wave=0.4, sampwidth=2)
write_frame(time=0.5, freq=256, framerate=8000, file=tw, wave=0.4, sampwidth=2)
write_frame(time=0.25, freq=0, framerate=8000, file=tw, wave=0.4, sampwidth=2)

#2 6(低音) 1 - 2 6(低音) 1 -
write_frame(time=0.5, freq=288, framerate=8000, file=tw, wave=0.4, sampwidth=2)
write_frame(time=0.5, freq=144, framerate=8000, file=tw, wave=0.4, sampwidth=2)
write_frame(time=0.5, freq=256, framerate=8000, file=tw, wave=0.4, sampwidth=2)
write_frame(time=0.25, freq=0, framerate=8000, file=tw, wave=0.4, sampwidth=2)
write_frame(time=0.5, freq=288, framerate=8000, file=tw, wave=0.4, sampwidth=2)
write_frame(time=0.5, freq=144, framerate=8000, file=tw, wave=0.4, sampwidth=2)
write_frame(time=0.5, freq=256, framerate=8000, file=tw, wave=0.4, sampwidth=2)


tw.close()

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM