Frequency Reader? - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: Python Coding (https://python-forum.io/forum-7.html) +--- Forum: Data Science (https://python-forum.io/forum-44.html) +--- Thread: Frequency Reader? (/thread-11303.html) |
Frequency Reader? - mekha - Jul-02-2018 a sound is played in real time then in the window resulting a frequency number 188.000 Hz, 220.000 Hz, etc and keep goes on while the sound is still played and keep resulting the numbers... I also wanted to made a marker on some frequency for the range like : A = 440.000 Hz G = 120.000 Hz D = 250.000 Hz E = 550.000 Hz etc I've found a discussion that almost similar with this project I wanted to create, they put the coding like this import pyaudio import os import struct import numpy as np import matplotlib.pyplot as plt import time from time import sleep %matplotlib tk 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() self.plots = self.prepare_figure() #self.fig_and_axes = self.prepare_figure() #self.first_plot = self.plot_first_figure() 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 prepare_figure(self): plt.ion() fig1 = plt.figure(1, figsize = (16,6)) wide_plot = plt.subplot(2,1,1) plt.vlines([f1,f2,f3,f4],1,1e17, linestyles = 'dashed') plt.xlabel("freq (Hz)") plt.ylabel("S^2 (u. arb.)") plt.xscale('log') plt.yscale('log') plt.xlim([80,4000]) #plt.xlim([600,700]) #plt.xlim([400,500]) plt.ylim([1e0,1e17]) spec_w, = plt.plot([1,1],[1,1], '-',c = 'blue') f4_plot = plt.subplot(2,4,5) plt.vlines(f4,1,1e17, linestyles = 'dashed') plt.xlabel("freq (Hz)") plt.ylabel("S^2 (u. arb.)") plt.yscale('log') plt.xlim([140,260]) plt.ylim([1e0,1e17]) spec_f4, = plt.plot([1,1],[1,1], '-',c = 'blue') f3_plot = plt.subplot(2,4,6) plt.vlines(f3,1,1e17, linestyles = 'dashed') plt.xlabel("freq (Hz)") plt.yscale('log') plt.xlim([220,380]) plt.ylim([1e0,1e17]) spec_f3, = plt.plot([1,1],[1,1], '-',c = 'blue') f2_plot = plt.subplot(2,4,7) plt.vlines(f2,1,1e17, linestyles = 'dashed') plt.xlabel("freq (Hz)") plt.yscale('log') plt.xlim([400,500]) plt.ylim([1e0,1e17]) spec_f2, = plt.plot([1,1],[1,1], '-',c = 'blue') f1_plot = plt.subplot(2,4,8) plt.vlines(f1,1,1e17, linestyles = 'dashed') plt.xlabel("freq (Hz)") plt.yscale('log') plt.xlim([600,700]) plt.ylim([1e0,1e17]) spec_f1, = plt.plot([1,1],[1,1], '-',c = 'blue') plt.draw() #return fig1, wide_plot, f1_plot, f2_plot, f3_plot, f4_plot return spec_w, spec_f1, spec_f2, spec_f3, spec_f4 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) self.update_fig(freqs, S2) def update_fig(self, freqs, S2): self.plots[0].set_xdata(freqs) self.plots[1].set_xdata(freqs) self.plots[2].set_xdata(freqs) self.plots[3].set_xdata(freqs) self.plots[4].set_xdata(freqs) self.plots[0].set_ydata(S2) self.plots[1].set_ydata(S2) self.plots[2].set_ydata(S2) self.plots[3].set_ydata(S2) self.plots[4].set_ydata(S2) plt.draw() plt.pause(0.001) if __name__ == "__main__": Tuner = Freq_analysis() for i in range(100): Tuner.listen() plt.ioff() plt.show()when I run the the result got me confused... STOPPED after that.... what I wanted is something more simple than this kind, like audio frequency analysis (perhaps...?) Thank you in advance! RE: Frequency Reader? - buran - Jul-02-2018 what exactly is your question? RE: Frequency Reader? - mekha - Jul-02-2018 (Jul-02-2018, 12:22 PM)buran Wrote: what exactly is your question? a real time sound frequency reader? sorry if I being not clear RE: Frequency Reader? - buran - Jul-02-2018 Unfortunately, this is not how the forum works. We are not going to do it for you. It looks like you have found a code that is a good starting point and in fact is doing more than what you want. Put some efforts to change it and get the desired results. Ask specific questions when you have a specific problem RE: Frequency Reader? - mekha - Jul-02-2018 (Jul-02-2018, 12:30 PM)buran Wrote: Unfortunately, this is not how the forum works. We are not going to do it for you. It looks like you have found a code that is a good starting point and in fact is doing more than what you want. Put some efforts to change it and get the desired results. Ask specific questions when you have a specific problem thank you for your pointer, and once again I'm so sorry if I being so selfish asking more than what it should've been... and I'm so glad you warning me, thank you! I'll be working on it now, got confused because I'm still new to this kind of programming of sound analyzer but I'll try to do it 1st and find an errors that more caused problem and ask more in efficient way (Jul-02-2018, 12:30 PM)buran Wrote: Unfortunately, this is not how the forum works. We are not going to do it for you. It looks like you have found a code that is a good starting point and in fact is doing more than what you want. Put some efforts to change it and get the desired results. Ask specific questions when you have a specific problem But can I ask you like this, why when I run it through Jupyter the result of the data stopped there then it showing some data graphics? (not testing thorough yet other than Jupyter) RE: Frequency Reader? - mekha - Jul-06-2018 Got my answer, the answer is this : https://pypi.org/project/frequency_analyzer/#files RE: Frequency Reader? - DeaD_EyE - Jul-06-2018 I gave already the answer in another thread: https://python-forum.io/Thread-PyQt-Assign-Label-Text-as-number-in-Hz?pid=51618#pid51618 I'm using itertools.product to simplify the iteration. # without itertools.product for band in range(-1, 3): for note in ('A','B','C'): print(band, note) # same with itertools.product import itertools bands = range(-1, 3) notes = ('A','B','C') for band, note in itertools.product(bands, notes): print(band, note)The rest is math and string concatenation or interpolation. There are also different ways to calculate the frequencies. I have use the midi number, which uses another formula, as your example. Just using a ready made module may help you with your current task, but it won't help you to understand Python and the algorithm. BTW: I'm not sure if I name the things right: Bands, Octaves, Notes RE: Frequency Reader? - mekha - Jul-07-2018 (Jul-06-2018, 08:29 AM)DeaD_EyE Wrote: I gave already the answer in another thread: https://python-forum.io/Thread-PyQt-Assign-Label-Text-as-number-in-Hz?pid=51618#pid51618 This one is a bit different with the other of my post though its also need the same thing, but yes the major is analyzer itself... But thank you very much, I'm truly appreciate all of your help and it does help me understanding a bit of how analyzer works too. And I have a question, what's this itertools do? when I test run the both code you posted with and without itertools, they gave the same result (Jul-06-2018, 08:29 AM)DeaD_EyE Wrote: I gave already the answer in another thread: https://python-forum.io/Thread-PyQt-Assign-Label-Text-as-number-in-Hz?pid=51618#pid51618 oh yes I do also have another very confusing result that is when I run the code that I posted here it always stopped before I terminate them, so when I force close it'll say do I want to terminate them while the program still running... but the thing is the code not even give me any more results, it stopped so suddenly and even if I waited for some minutes, still no updates from before RE: Frequency Reader? - mekha - Jul-11-2018 I've cut the codes to simple it without the matplotlib running too, but still it's not make sense why it's always stopping in the middle of the process. And if I terminated the running file's it said if I want to close while it still running... but actually nothing happening at all no update of the data or whatsoever here is the updated code without the matplotlib 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() |