python使用wave和matplotlib生成和绘制wav文件

#!/usr/bin/env python3
import numpy as np
from scipy.io import wavfile
import numpy as np
import matplotlib.pyplot as plt
import wave
import os

#frame_rate:采样率  frequency:频率 length:文件时长秒
def generate_sin_wave(filepath:str, frame_rate:int, freq:int, length:int):
    
    #生成正弦
    t_points = np.linspace(0, length, frame_rate * length)  #start, stop, number
    amplitude_points = np.sin(freq * 2 * np.pi * t_points)  #  
    
    #处理数据,从[-1,1]转化为[-2**15-1, 2**15-1] 
    max_of_amplitude = np.max(np.abs(amplitude_points))
    maxint16 = np.iinfo(np.int16).max  # == 2**15-1
 
    print('max_of_amplitude:%f, maxint16:%f' %(max_of_amplitude, maxint16))
     
    # 转换
    amplitude_points =  amplitude_points * maxint16 / max_of_amplitude

    #将数组的数据类型转换为指定的类型:int16
    amplitude_points = amplitude_points.astype(np.int16) 

    #写入文件
    wavfile.write(filepath, frame_rate, amplitude_points)

    print("generate sin wave file successfully, written to:" + filepath )

#maxshow这个值怎么设都不会有问题
def visualize_wave(filepath: str, maxshow:int, spectrum:bool): 
    
    # 设置figure大小  像素
    plt.figure(figsize = (12, 8), dpi = 100)
        
    # reading the audio file 
    wavefile = wave.open(filepath) 
    params = wavefile.getparams()

    nchannels, sample_width, frame_rate, nframes = params[:4]
    
    print('nchannels:%d, sample_width:%d, sample_rate:%d, nframes:%d'
          % (nchannels, sample_width, frame_rate, nframes))
    
    # reads all the frames  
    # -1 indicates all or max frames 
    signal = wavefile.readframes(-1) 
    signal = np.frombuffer(signal, dtype = np.int16) 
      
    # gets the frame rate 
    frame_rate = wavefile.getframerate() 
  
    # to Plot the x-axis in seconds  
    # you need get the frame rate  
    # and divide by size of your signal 
    # to create a Time Vector  
    # spaced linearly with the size  
    # of the audio file 
    time = np.linspace( 
        0, # start 
        len(signal) / frame_rate, 
        num = len(signal) 
    ) 
      
    # title of the plot 
    plt.title("Sound Wave") 
      
    # label of x-axis 
    plt.xlabel("Time") 
    
    # label of y-axis 
    plt.xlabel("Amplitude") 
    
    #切片,太多了显示不了,显示最初的2000个采样
    points = len(time)
    if points > maxshow :
        time = time[0:maxshow:1]
        signal = signal[0:maxshow:1]
    
    # actual plotting 
    if spectrum:
        plt.specgram(signal, Fs=sample_rate, vmin=-20, vmax=50)
        plt.colorbar()
    else:
        plt.plot(time, signal) 
    
    
    # shows the plot  
    # in new window 
    plt.show() 
  
    # you can also save 
    # the plot using 
    # plt.savefig('filename')
    
if __name__ == "__main__": 
    
    rootpath = "./generated"
    if not os.path.exists(rootpath):
        os.mkdir(rootpath, mode=755)
    
    filepath = rootpath + "/sine.wav"
    generate_sin_wave(filepath, 16000, 600, 10)
    visualize_wave(filepath, 1000, False)
    
    
    sample_filepath = rootpath + "/file_example_WAV_1MG.wav" #
    if os.path.exists(sample_filepath):
        visualize_wave(sample_filepath, 30000, False)
    
    

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个可以生成显示wav文件波形、裁剪波形和保存波形文件的PYQT程序的示例代码: ```python import sys import wave import numpy as np import matplotlib.pyplot as plt from PyQt5.QtWidgets import QApplication, QMainWindow, QFileDialog from PyQt5.QtGui import QIcon, QPixmap from PyQt5.QtCore import Qt class MainWindow(QMainWindow): def __init__(self): super().__init__() self.initUI() def initUI(self): # 设置窗口标题、大小、图标 self.setWindowTitle('Waveform Viewer') self.setGeometry(100, 100, 800, 500) self.setWindowIcon(QIcon('icon.png')) # 添加控件 self.label = QLabel(self) self.label.setGeometry(10, 10, 780, 400) self.btn_open = QPushButton('Open', self) self.btn_open.setGeometry(10, 420, 80, 30) self.btn_open.clicked.connect(self.open_file) self.btn_save = QPushButton('Save', self) self.btn_save.setGeometry(100, 420, 80, 30) self.btn_save.clicked.connect(self.save_file) self.slider_start = QSlider(Qt.Horizontal, self) self.slider_start.setGeometry(190, 420, 400, 30) self.slider_start.setMinimum(0) self.slider_start.setMaximum(100) self.slider_start.setSingleStep(1) self.slider_start.setValue(0) self.slider_start.sliderReleased.connect(self.update_waveform) self.slider_end = QSlider(Qt.Horizontal, self) self.slider_end.setGeometry(190, 450, 400, 30) self.slider_end.setMinimum(0) self.slider_end.setMaximum(100) self.slider_end.setSingleStep(1) self.slider_end.setValue(100) self.slider_end.sliderReleased.connect(self.update_waveform) def open_file(self): # 打开wav文件 filename, _ = QFileDialog.getOpenFileName(self, 'Open file', '.', 'Waveform files (*.wav)') if filename: self.filename = filename self.update_waveform() def update_waveform(self): # 生成波形 with wave.open(self.filename, 'rb') as wf: framerate = wf.getframerate() nframes = wf.getnframes() data = wf.readframes(nframes) frames = np.frombuffer(data, dtype=np.int16) times = np.arange(len(frames)) / framerate start = int(self.slider_start.value() / 100 * len(frames)) end = int(self.slider_end.value() / 100 * len(frames)) frames = frames[start:end] times = times[start:end] # 显示波形 fig, ax = plt.subplots(figsize=(7.8, 3.8)) ax.plot(times, frames) ax.set_xlabel('Time (s)') ax.set_ylabel('Amplitude') ax.set_xlim([times[0], times[-1]]) ax.set_ylim([-32768, 32767]) plt.tight_layout() plt.savefig('waveform.png') pixmap = QPixmap('waveform.png') self.label.setPixmap(pixmap) def save_file(self): # 保存裁剪后的wav文件 filename, _ = QFileDialog.getSaveFileName(self, 'Save file', '.', 'Waveform files (*.wav)') if filename: with wave.open(filename, 'wb') as wf: wf.setnchannels(1) wf.setsampwidth(2) wf.setframerate(44100) with wave.open(self.filename, 'rb') as wf_src: nframes = wf_src.getnframes() start = int(self.slider_start.value() / 100 * nframes) end = int(self.slider_end.value() / 100 * nframes) wf.setnframes(end - start) wf.writeframes(wf_src.readframes(end - start)) if __name__ == '__main__': app = QApplication(sys.argv) mainWindow = MainWindow() mainWindow.show() sys.exit(app.exec_()) ``` 在上述代码中,我们首先导入了必要的模块,包括`sys`、`wave`、`numpy`、`matplotlib.pyplot`、`PyQt5.QtWidgets`、`PyQt5.QtGui`和`PyQt5.QtCore`,然后定义了一个名为`MainWindow`的类,继承自`QMainWindow`。在`MainWindow`类中,我们定义了一些控件,包括一个用于显示波形的`QLabel`、两个用于裁剪波形的`QSlider`、一个用于打开wav文件的`QPushButton`、一个用于保存裁剪后的wav文件的`QPushButton`。在`initUI`方法中,我们进行了控件的初始化和布局。在`open_file`方法中,我们使用`QFileDialog`打开一个wav文件,并保存文件名。在`update_waveform`方法中,我们读取wav文件的采样率、采样点数和采样数据,然后根据用户在`QSlider`上的选择裁剪波形。接着,我们使用matplotlib绘制波形图,并将图像保存为文件,最后使用`QPixmap`将波形图显示在`QLabel`上。在`save_file`方法中,我们使用`QFileDialog`打开一个用于保存裁剪后的wav文件的对话框,并使用`wave`模块保存裁剪后的wav文件。在主程序中,我们创建了一个`QApplication`对象和一个`MainWindow`对象,并将`MainWindow`显示出来。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值