用python生成显示wav文件波形和增加可以在时间轴裁剪波形后保存波形文件的PYQT程序
时间: 2024-05-01 17:19:04 浏览: 57
下面是一个简单的PYQT程序,可以生成显示wav文件波形,并且可以在时间轴上裁剪波形后保存裁剪后的波形文件。
```python
import sys
import wave
import struct
import numpy as np
from PyQt5.QtWidgets import QApplication, QMainWindow, QFileDialog
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPainter, QPen, QColor
class WaveformViewer(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle('Waveform Viewer')
self.setGeometry(100, 100, 800, 400)
self.filename = None
self.data = None
self.width = None
self.height = None
self.start_time = 0
self.end_time = None
self.mouse_pressed = False
self.initUI()
def initUI(self):
self.openAction = self.createAction('Open', self.openFile, 'Ctrl+O')
self.saveAction = self.createAction('Save', self.saveFile, 'Ctrl+S')
self.quitAction = self.createAction('Quit', self.close, 'Ctrl+Q')
menubar = self.menuBar()
fileMenu = menubar.addMenu('File')
fileMenu.addAction(self.openAction)
fileMenu.addAction(self.saveAction)
fileMenu.addSeparator()
fileMenu.addAction(self.quitAction)
self.statusBar()
def createAction(self, text, slot, shortcut=None, icon=None, tip=None, checkable=False, signal='triggered'):
action = QAction(text, self)
if icon is not None:
action.setIcon(QIcon(":/%s.png" % icon))
if shortcut is not None:
action.setShortcut(shortcut)
if tip is not None:
action.setToolTip(tip)
action.setStatusTip(tip)
action.setCheckable(checkable)
getattr(action, signal).connect(slot)
return action
def openFile(self):
self.filename, _ = QFileDialog.getOpenFileName(self, 'Open File', '.', 'WAV files (*.wav)')
if self.filename:
self.loadFile()
def loadFile(self):
with wave.open(self.filename, 'rb') as f:
self.width = f.getnframes()
self.height = f.getsampwidth() * 8
self.data = np.zeros((self.width, 2))
for i in range(self.width):
frame = f.readframes(1)
sample = struct.unpack('<hh', frame)
self.data[i, 0] = sample[0]
self.data[i, 1] = sample[1]
self.end_time = self.width / f.getframerate()
self.update()
def saveFile(self):
if self.filename is None:
return
start_frame = int(self.start_time * self.width / self.end_time)
end_frame = int(self.end_time * self.width / self.end_time)
data = self.data[start_frame:end_frame, :]
with wave.open(self.filename, 'wb') as f:
f.setnchannels(2)
f.setsampwidth(2)
f.setframerate(44100)
for i in range(len(data)):
f.writeframes(struct.pack('<hh', int(data[i, 0]), int(data[i, 1])))
def paintEvent(self, event):
if self.data is None:
return
qp = QPainter()
qp.begin(self)
qp.setPen(QPen(Qt.black, 1, Qt.SolidLine))
x_scale = self.width / self.width
y_scale = self.height / 2 / 32768
for i in range(self.width - 1):
x1 = i * x_scale
y1 = -self.data[i, 0] * y_scale + self.height / 2
x2 = (i + 1) * x_scale
y2 = -self.data[i + 1, 0] * y_scale + self.height / 2
qp.drawLine(x1, y1, x2, y2)
y1 = -self.data[i, 1] * y_scale + self.height / 2
y2 = -self.data[i + 1, 1] * y_scale + self.height / 2
qp.drawLine(x1, y1, x2, y2)
if self.start_time is not None and self.end_time is not None:
qp.setPen(QPen(QColor(0, 0, 255, 127), 1, Qt.SolidLine))
x1 = self.start_time / self.end_time * self.width
x2 = self.end_time / self.end_time * self.width
qp.drawRect(x1, 0, x2 - x1, self.height)
qp.end()
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
self.start_time = event.x() / self.width * self.end_time
self.end_time = None
self.mouse_pressed = True
def mouseMoveEvent(self, event):
if self.mouse_pressed:
self.end_time = event.x() / self.width * self.end_time
self.update()
def mouseReleaseEvent(self, event):
if event.button() == Qt.LeftButton:
self.end_time = event.x() / self.width * self.end_time
self.mouse_pressed = False
self.update()
if __name__ == '__main__':
app = QApplication(sys.argv)
waveformViewer = WaveformViewer()
waveformViewer.show()
sys.exit(app.exec_())
```
这个程序使用 PyQt5 库创建,可以打开 wav 文件,并显示其波形,还可以在时间轴上裁剪波形并保存裁剪后的波形文件。