Jul-12-2018, 01:48 PM
(Jul-04-2018, 10:30 AM)DeaD_EyE Wrote: I have no clue about music.
Based on this Article and this Example with matplotlib, I wrote an example.
from itertools import product import matplotlib.pyplot as plt def calc_freq_from_midi(m): if m < 0 or m > 127: raise ValueError('m must be between 0 and 127.') notes = ('C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B') octaves = range(-1, 10) notes = product(octaves, notes) notes = [note + str(band) for band, note in notes] freq = 440 * 2 ** ((m - 69)/12) return freq, notes[m] labels = [calc_freq_from_midi(m) for m in range(128)] x_ticks, x_labels = zip(*labels) # it's a transpose frequencies = [110.0, 220.0, 440.0] # A2, A3, A4 magnitude = [2, 3, 4] plt.title('Spectrum') plt.xlabel('Notes') plt.ylabel('Magnitude') plt.xticks(x_ticks, x_labels, rotation='vertical') plt.plot(frequencies, magnitude, 'o') plt.legend(['Signal']) plt.show()Just check if the notes are correct.
It should plot A2, A3 and A4 as blue dots.
I guess you can also print two different xticks.
Just explore the matplotlib examples.
If you don't use matplotlib inside of QT, you have to adapt it to the plotting framework you use.
(Jul-10-2018, 04:26 PM)Alfalfa Wrote:(Jul-07-2018, 02:44 AM)mekha Wrote: It does looping forever until I terminate the graphs window, then they stop.
But if I want to assign this Qtimer to show some frequency data as Label Text in my QtDesigner window, then how I can do that?
I'm not sure to understand, are you asking about how to use the QTimer to refresh the text of a QLabel?
If so, simply add something like
self.ui.yourLabel.setText("frequency data")into the function connected to your timer..
The purpose of QtDesigner is to organize your widget, but the dynamic content is rather set by using python.
When I calling a class inside the freq.py inside the go.py, the QtWindow (the graphs and others) couldn't showed up it keep loading and the freq analyzer keep running on the back giving results of it's recorder
the updated go.py
from PyQt4 import QtGui,QtCore import sys import ui_main import StrSetting import numpy as np import pyqtgraph import SWHear import freq from freq import Freq_analysis class SoundApp(QtGui.QMainWindow, ui_main.Ui_MainWindow): def __init__(self, parent=None): pyqtgraph.setConfigOption('background', 'w') #before loading widget super(SoundApp, self).__init__(parent) self.setupUi(self) self.grFFT.plotItem.showGrid(True, True, 0.7) self.grPCM.plotItem.showGrid(True, True, 0.7) self.maxFFT=0 self.maxPCM=0 self.ear = SWHear.SWHear(rate=44100,updatesPerSecond=20) self.ear.stream_start() def update(self): if not self.ear.data is None and not self.ear.fft is None: pcmMax=np.max(np.abs(self.ear.data)) if pcmMax>self.maxPCM: self.maxPCM=pcmMax self.grPCM.plotItem.setRange(yRange=[-pcmMax,pcmMax]) if np.max(self.ear.fft)>self.maxFFT: self.maxFFT=np.max(np.abs(self.ear.fft)) #self.grFFT.plotItem.setRange(yRange=[0,self.maxFFT]) self.grFFT.plotItem.setRange(yRange=[0,1]) self.pbLevel.setValue(1000*pcmMax/self.maxPCM) pen=pyqtgraph.mkPen(color='b') self.grPCM.plot(self.ear.datax,self.ear.data,pen=pen,clear=True) pen=pyqtgraph.mkPen(color='r') self.grFFT.plot(self.ear.fftx,self.ear.fft/self.maxFFT,pen=pen,clear=True) QtCore.QTimer.singleShot(1, self.update) # QUICKLY repeat if __name__=="__main__": app = QtGui.QApplication(sys.argv) form = SoundApp() form.show() form.update() #start with something Tuner = Freq_analysis() for i in range(1000): Tuner.listen() app.exec_() print("DONE")and this is the freq.py
import pyaudio import os import struct import numpy as np import time from time import sleep CHUNK = 2**14 #2**15 #4096 WIDTH = 2 FORMAT = pyaudio.paInt16 CHANNELS = 2 RATE = 44100 dt = 1.0/RATE ### frequencies of the strings for the violin (tunned in A), in Hz f4 = 195.998 ## G3 f3 = 293.665 ## D4 f2 = 440.000 ## A4 f1 = 659.255 ## E5 n = CHUNK freqs = np.fft.rfftfreq(n, d = dt) def Frequency_of_position(position): """ Returns the frequency (Hz) of the note in from its position (halftones) relative to A4 in an equal tempered scale. Ex: 0 -> 440 Hz (A4), 12 -> 880 Hz (A5).""" return 440.0*(2**(1.0/12.0))**position def Position_to_note(position): "A A# B C C# D D# E F F# G G#" SCALE = ["A", "A#", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#"] LETTER = SCALE[position % 12] NUMBER = str(int((position+57) / 12)) return LETTER+NUMBER pos = np.array(range(-36,48)) vnote_freqs = np.vectorize(Frequency_of_position) note_freqs = vnote_freqs(pos) def get_frequency( spectrum ): return freqs[np.argmax(spectrum)] class Freq_analysis(object): def __init__(self): self.pa = pyaudio.PyAudio() self.stream = self.open_mic_stream() def stop(self): self.stream.close() def open_mic_stream( self ): device_index = self.find_input_device() stream = self.pa.open( format = FORMAT, channels = CHANNELS, rate = RATE, input = True, input_device_index = device_index, frames_per_buffer = CHUNK) return stream def find_input_device(self): device_index = None for i in range( self.pa.get_device_count() ): devinfo = self.pa.get_device_info_by_index(i) print( "Device %d: %s"%(i,devinfo["name"]) ) for keyword in ["mic","input"]: if keyword in devinfo["name"].lower(): print( "Found an input: device %d - %s"% (i,devinfo["name"]) ) device_index = i return device_index if device_index == None: print( "No preferred input found; using default input device." ) return device_index def PrintFreq(self, S2): dominant = get_frequency( S2 ) dist = np.abs(note_freqs-dominant) closest_pos = pos[np.argmin(dist)] closest_note = Position_to_note(closest_pos) print(dominant, "(",closest_note, "=",Frequency_of_position(closest_pos),")") def listen(self): try: block = self.stream.read(CHUNK) except IOError: # An error occurred. print( "Error recording.") return indata = np.array(struct.unpack("%dh"%(len(block)/2),block)) n = indata.size freqs = np.fft.rfftfreq(n, d = dt) data_rfft = np.fft.rfft(indata) S2 = np.abs(data_rfft)**2 #self.PrintFreq(block) #self.update_fig(block) self.PrintFreq(S2) if __name__ == "__main__": Tuner = Freq_analysis() for i in range(100): Tuner.listen()