Matplotlib-实时麦克风图表

时间:2020-10-19 17:56:11

标签: python matplotlib pyqt5

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'hear-from-microphone.ui'
#
# Created by: PyQt5 UI code generator 5.15.0
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.


from PyQt5 import QtCore, QtGui, QtWidgets, QtMultimedia
import numpy as np
import matplotlib.pyplot as plt
import time
import sys

class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(500, 500)
        self.gridLayout = QtWidgets.QGridLayout(Form)
        self.gridLayout.setObjectName("gridLayout")
        self.pushButton = QtWidgets.QPushButton(Form)
        self.pushButton.setObjectName("pushButton")
        self.gridLayout.addWidget(self.pushButton, 0, 0, 1, 1)
        self.frame = QtWidgets.QFrame(Form)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.frame.sizePolicy().hasHeightForWidth())
        self.frame.setSizePolicy(sizePolicy)
        self.frame.setMinimumSize(QtCore.QSize(0, 5))
        self.frame.setMaximumSize(QtCore.QSize(16777215, 5))
        self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
        self.frame.setObjectName("frame")
        self.frame_2 = QtWidgets.QFrame(self.frame)
        self.frame_2.setGeometry(QtCore.QRect(0, 0, 0, 16))
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.frame_2.sizePolicy().hasHeightForWidth())
        self.frame_2.setSizePolicy(sizePolicy)
        self.frame_2.setMinimumSize(QtCore.QSize(0, 0))
        self.frame_2.setStyleSheet("QFrame{\n"
        "    background-color:blue;\n"
        "}")
        self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised)
        self.frame_2.setObjectName("frame_2")
        self.gridLayout.addWidget(self.frame, 1, 0, 1, 1)
        self.pushButton_2 = QtWidgets.QPushButton(Form)
        self.pushButton_2.setEnabled(False)
        self.pushButton_2.setObjectName("pushButton_2")
        self.gridLayout.addWidget(self.pushButton_2, 2, 0, 1, 1)

        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)
        
        self.pushButton.clicked.connect(lambda state:self.play_from_microphone(Form))
        self.pushButton_2.clicked.connect(lambda state:self.stop_player(Form))
        
        self.start_plotting()
        

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Hear from microphone"))
        self.pushButton.setText(_translate("Form", "Click to hear microphone input"))
        self.pushButton_2.setText(_translate("Form", "Click to stop hearing microphone input"))

    def play_from_microphone(self,Form):
        self.pushButton.setEnabled(False)
        
        
        
        self.buffer_min_value = 0
        self.buffer_max_value = 0
        
        
        self.mid_strength = 0
        self.min_value = 5
        self.max_value = 14
        
        input_devices_qt = QtMultimedia.QAudioDeviceInfo.availableDevices(QtMultimedia.QAudio.AudioInput)
        output_devices_qt = QtMultimedia.QAudioDeviceInfo.availableDevices(QtMultimedia.QAudio.AudioOutput)         
        
        self.m_play_called = False
        
        self.m_buffer = QtCore.QByteArray()
        

        
        self.m_buffer_requested = True
        #self.m_time_to_buffer = 1000
        #self.MAX_BUFFERED_TIME = 1000
        self.m_time_to_buffer = 50
        self.MAX_BUFFERED_TIME = 100
        
        self.m_input_device_info = QtMultimedia.QAudioDeviceInfo.defaultInputDevice()
        self.m_output_device_info = QtMultimedia.QAudioDeviceInfo.defaultOutputDevice()
        
        
        self.format = QtMultimedia.QAudioFormat()
        self.format.setCodec("audio/pcm")
        self.format.setSampleRate(44100)
        self.format.setChannelCount(1)
        self.format.setSampleSize(16)
        self.format.setByteOrder(QtMultimedia.QAudioFormat.LittleEndian)
        self.format.setSampleType(QtMultimedia.QAudioFormat.SignedInt)
        
        self.m_audio_input = QtMultimedia.QAudioInput(input_devices_qt[0],self.format)
        
        self.m_input_device = self.m_audio_input.start()
        self.m_audio_input.resume()
        
        self.plot_pause = False
        
        self.m_audio_input.setNotifyInterval(100)
        self.m_audio_input.notify.connect(lambda: self.send_input_to_buffer(Form))
        
        
        if (self.format.sampleRate() >= 44100):
            self.internal_buffer_size = (1024 * 10) * self.format.channelCount()
        elif (self.format.sampleRate() >= 24000):
            self.internal_buffer_size = (1024 * 6) * self.format.channelCount()
        else:
            self.internal_buffer_size = (1024 * 4) * self.format.channelCount()
            
        self.m_audio_output = QtMultimedia.QAudioOutput(self.m_output_device_info, self.format)
        self.m_audio_output.setBufferSize(self.internal_buffer_size)
        
        self.m_size_to_buffer = int(self.timeToSize_1())
        
        self.m_max_size_to_buffer = self.m_size_to_buffer + int(self.timeToSize_2())
        
        self.m_output_device = self.m_audio_output.start()
        
        self.timer_play = QtCore.QTimer(Form)
        self.timer_play.setTimerType(QtCore.Qt.PreciseTimer)
        self.timer_play.timeout.connect(lambda:self.preplay(Form))
        self.timer_play.start(10)
        
        self.timer_verifier = QtCore.QTimer(Form)
        self.timer_verifier.timeout.connect(self.verifier)
        self.timer_verifier.start(max(self.m_time_to_buffer, 10))
        
        self.pushButton_2.setEnabled(True)
            
    def verifier(self):
        if (self.m_buffer.size() >= self.m_max_size_to_buffer):
            self.m_buffer.clear()
            
            
    def timeToSize_1(self):
        return ((self.format.channelCount() * (self.format.sampleSize() / 8) * self.format.sampleRate()) * self.m_time_to_buffer / 1000)
        
    def timeToSize_2(self):
        return ((self.format.channelCount() * (self.format.sampleSize() / 8) * self.format.sampleRate()) * self.MAX_BUFFERED_TIME / 1000)
            
    def send_input_to_buffer(self,Form):
        bytes_ready = self.m_audio_input.bytesReady()
        if(type(bytes_ready) == int and bytes_ready>0):
            data = self.m_input_device.readAll()
            self.plot_data(data)
            self.m_buffer.append(data)
            #for sample in data:
            #   value = int.from_bytes(sample, byteorder='little', signed=True)
            self.calculate_mid_strength()
            self.preplay(Form)
            
            
    def calculate_mid_strength(self):
        samples = 0
        total = 0
        for sample in self.m_buffer:
            samples = samples + 1
            value = int.from_bytes(sample, byteorder='little', signed=True)
            
            value = abs(value)
            total = total + value
            
        self.mid_strength = total/samples
        
        mid_strength_percent = abs(self.mid_strength-self.min_value)/(abs(self.max_value-self.min_value))
        
        if(mid_strength_percent<0):
            mid_strength_percent = 0
        elif(mid_strength_percent>1):
            mid_strength_percent = 1
        
        self.frame_width = self.frame.geometry().width()
        
        normalized_value = int(self.frame_width*mid_strength_percent)
        
        
        
        self.frame_2.setGeometry(QtCore.QRect(0, 0, normalized_value, 16))
        
        
        stop_red = 255
        stop_green = int(255*(1-mid_strength_percent))
        
        self.frame_2.setStyleSheet("QFrame{\n"
        "    background-color:qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(255, 255, 0, 255), stop:1 rgba("+str(stop_red)+", "+str(stop_green)+", 0, 255))\n"
        "}")
        
            
    def preplay(self,Form):
        if(self.m_play_called==False):
            self.m_play_called = True
            self.timer = QtCore.QTimer(Form)
            self.timer.setSingleShot(True)
            self.timer.singleShot(0, self.sound_microphone)
        
    def sound_microphone(self):
        self.m_play_called = False
        if self.m_buffer.isEmpty():
            self.m_buffer_requested = True
            return
        elif self.m_buffer.size() < self.m_size_to_buffer:
            if self.m_buffer_requested:
                return
        else:
            self.m_buffer_requested = False
            
        readlen = int(self.m_audio_output.periodSize())
        chunks = int(self.m_audio_output.bytesFree() / readlen)
        
        while (chunks>0):
            samples = self.m_buffer.mid(0, readlen)
            len = samples.size()
            self.m_buffer.remove(0, len)

            if (len>0):
                if(self.m_audio_output.state()!=2):
                    self.m_output_device.write(samples)
                else:
                    return 1

            if (len != readlen):
                break;

            chunks = chunks - 1
            
    def stop_player(self,Form):
        self.m_audio_input.stop()
        self.m_audio_output.stop()
        self.pushButton.setEnabled(True)
        self.pushButton_2.setEnabled(False)
        self.frame_2.setGeometry(QtCore.QRect(0, 0, 0, 16))
        
    
    def start_plotting(self):
        self.i=0
        self.f,self.ax = plt.subplots(1)

        self.x = np.arange(10000)
        self.y = np.arange(10000)

        self.li, = self.ax.plot(self.x, self.y)
        self.ax.set_xlim(0,1000)
        self.ax.set_ylim(-300,300)
        self.ax.set_title("Raw Audio Signal")
        
        # Show the plot, but without blocking updates
        plt.pause(0.01)
        plt.tight_layout()
    
        self.keep_going = True
        
        self.audio_data_len = 0
        
    def plot_data(self,in_data):
        # get and convert the data to float
        audio_data = np.frombuffer(in_data, np.int16)
        
        
        self.li.set_xdata(np.arange(len(audio_data)))
        #self.audio_data_len = self.audio_data_len+len(audio_data)
        self.li.set_ydata(audio_data)
        
        plt.pause(0.01)
        
        


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    app.addLibraryPath(r"C:/Users/Χρήστος/AppData/Local/Programs/Python/Python38/Lib/site-packages/pyqt5_tools/Qt/plugins")
    app.addLibraryPath(r"C:/Users/Χρήστος/AppData/Local/Programs/Python/Python38/lib/site-packages/PyQt5/Qt/plugins")
    app.setStyle("Fusion")
    Form = QtWidgets.QWidget()
    ui = Ui_Form()
    ui.setupUi(Form)
    Form.show()
    sys.exit(app.exec_())

上面的代码:

  1. 将麦克风输入写入缓冲区
  2. 读取缓冲区并在声音设备中播放
  3. 使用matplotlib绘制缓冲区。

在3)中有问题。我希望更新是实时的。 我也想更新x轴(输入datetime.now()。strformat(....)

任何建议都会有用。

0 个答案:

没有答案