specgram in mainwindow

1

I am generating an audio spectrum analyzer ..

I have already managed to generate the analyzer with certain features that I need, however, I can not make the resulting graphic representation appear in the main window, or that the background color is black, and likewise I do not know how to drag any audio file and analyze it here I give the example of what I want to achieve.

and this is my code.

import sys
import matplotlib.pyplot as plt
import soundfile as sf
from PyQt5.QtWidgets import QMainWindow,QApplication,QFrame, QVBoxLayout
from PyQt5 import QtGui


class Principal(QMainWindow):
    def __init__(self):
        QMainWindow. __init__(self)

        self.frame = QFrame(self)
        self.frame.setStyleSheet('Background-color:black')
        self.frame.resize(QMainWindow.size(self))



        data, samplerate = sf.read('Close Your Eyes.flac')
        y = data.sum(axis=1)/2
        Pxx, freqs, bins, im = plt.specgram(y, NFFT=256, Fs=samplerate, cmap='jet')

        plt.gcf().set_size_inches(10,5)
        plt.xlim(0, len(y) / samplerate)
        plt.ylim(0, 23000)
        plt.colorbar(im).set_label('Intensidad (dB)')
        plt.xlabel('Tiempo (s)')
        plt.ylabel('Frecuencia (Hz)')
        plt.show()




app = QApplication([])
p = Principal()
p.resize(600,400)
p.show()
app.exec_()
    
asked by Revsky01 25.03.2018 в 06:27
source

1 answer

2

Let's go in parts:

  • To get the style you show in the graph, the simplest way is to use the style that is already predefined in Matplotlib, dark_background . It would also be possible to do so by manually changing the color to each element of course.

  • To embed the graph in your Qt application, the simplest and most direct is to use the backend provided by matplotlib, specifically matplotlib.backends.backend_qt5agg.FigureCanvasQTAgg . Currently it is a widget, so you can handle it as such.

  • To allow dragging and dropping the files to analyze, you must enable Drag and Drop in the widget using the Qwidget.setAcceptDrops(True) method and overwrite the event dropEvent so that when the file is released the File above the widget will run the necessary code to generate the spectrogram.

The code as an example could look something like this:

import sys
import matplotlib

matplotlib.use('Qt5Agg')
from PyQt5 import QtCore, QtWidgets

import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure

import soundfile as sf




class Spectrograph(FigureCanvas):
    def __init__(self, parent=None, width=5, height=4, dpi=100):
        plt.style.use('dark_background')

        self.fig = Figure(figsize=(width, height), dpi=dpi)
        self.axes = self.fig.add_subplot(111)
        self.cbar = None
        self.compute_initial_figure()

        super(Spectrograph, self).__init__(self.fig)
        self.setParent(parent)
        FigureCanvas.setSizePolicy(self,
                                   QtWidgets.QSizePolicy.Expanding,
                                   QtWidgets.QSizePolicy.Expanding)
        FigureCanvas.updateGeometry(self)
        self.setAcceptDrops(True)


    def dragEnterEvent(self, e):
        if e.mimeData().hasFormat('text/uri-list'):
            e.accept()
        else:
            e.ignore() 


    def dropEvent(self, e):
        if e.mimeData().hasUrls:
            for url in e.mimeData().urls():
                e.setDropAction(QtCore.Qt.CopyAction)
                e.accept()
                file = str(url.toLocalFile())
                self.update_graph(file)
        else:
            e.ignore()


    def update_graph(self, file):
        self.axes.cla()
        if self.cbar:
            self.cbar.remove()

        data, samplerate = sf.read(file)
        y = data.sum(axis=1)/2
        Pxx, freqs, bins, im = self.axes.specgram(y, NFFT=256, Fs=samplerate, cmap='jet')
        plt.gcf().set_size_inches(10,5)
        self.axes.set_xlim(0, len(y) / samplerate)
        self.axes.set_ylim(0, 23000)
        self.cbar = self.fig.colorbar(im)
        self.cbar.set_label('Intensidad (dB)')
        self.axes.set_xlabel('Tiempo (s)')
        self.axes.set_ylabel('Frecuencia (Hz)')
        self.a = 0
        self.draw()


    def compute_initial_figure(self):
        pass


class ApplicationWindow(QtWidgets.QMainWindow):
    def __init__(self):
        QtWidgets.QMainWindow.__init__(self)
        self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
        self.setWindowTitle("Audio Spectrograph")

        self.main_widget = QtWidgets.QWidget(self)
        self.graph = Spectrograph(self.main_widget, width=5, height=4, dpi=100)

        layout = QtWidgets.QVBoxLayout(self.main_widget)
        layout.addWidget(self.graph)

        self.main_widget.setStyleSheet("QWidget {background-color:   black}")

        self.main_widget.setFocus()
        self.setCentralWidget(self.main_widget)



if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    window = ApplicationWindow()
    window.show()
    sys.exit(app.exec_())
  

Note: I have not touched the way you get the data from the audio file and the graphics, it has only been adapted. All this procedure is done within the SpectroGraph.update_graph method in this case.

And this is the behavior:

    
answered by 25.03.2018 / 14:41
source