Skip to content

Commit

Permalink
pitch + spectrogram
Browse files Browse the repository at this point in the history
  • Loading branch information
leirevaran committed Jun 1, 2023
1 parent 1978768 commit 934468c
Show file tree
Hide file tree
Showing 18 changed files with 58 additions and 30 deletions.
Binary file modified __pycache__/auxiliar.cpython-310.pyc
Binary file not shown.
Binary file modified __pycache__/controlMenu.cpython-310.pyc
Binary file not shown.
Binary file modified __pycache__/generateFreeAdd.cpython-310.pyc
Binary file not shown.
Binary file modified __pycache__/generateNoise.cpython-310.pyc
Binary file not shown.
Binary file modified __pycache__/generatePureTone.cpython-310.pyc
Binary file not shown.
Binary file modified __pycache__/generateSawtoothWave.cpython-310.pyc
Binary file not shown.
Binary file modified __pycache__/generateSquareWave.cpython-310.pyc
Binary file not shown.
Binary file modified __pycache__/inputLoad.cpython-310.pyc
Binary file not shown.
Binary file modified __pycache__/inputRecord.cpython-310.pyc
Binary file not shown.
52 changes: 40 additions & 12 deletions controlMenu.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import matplotlib.pyplot as plt
from tkinter import ttk
from scipy import signal
from matplotlib.widgets import Cursor, SpanSelector, MultiCursor
from matplotlib.widgets import Button, Cursor, SpanSelector, MultiCursor
from matplotlib.backend_bases import MouseButton, MouseEvent
from matplotlib.patches import Rectangle
from scipy.io.wavfile import write
Expand Down Expand Up @@ -528,6 +528,28 @@ def listenFragFrag(xmin, xmax):
span = SpanSelector(ax, listenFragFrag, 'horizontal', useblit=True, interactive=True, drag_from_anywhere=True)
return span

# def addLoadButton(self, fig, ax, fs, time, audio, name):
# # Takes the selected fragment and opens the control menu when clicked
# def load(event):
# if self.selectedAudio.shape == (1,):
# self.createControlMenu(self, name, fs, audio)
# else:
# self.createControlMenu(self, name, fs, self.selectedAudio)
# plt.close(fig)

# # Adds a 'Load' button to the figure
# axload = fig.add_axes([0.8, 0.01, 0.09, 0.05]) # [left, bottom, width, height]
# but_load = Button(axload, 'Load')
# but_load.on_clicked(load)
# axload._but_load = but_load # reference to the Button (otherwise the button does nothing)

# def listenFrag(xmin, xmax):
# ini, end = np.searchsorted(time, (xmin, xmax))
# self.selectedAudio = audio[ini:end+1]
# sd.play(self.selectedAudio, fs)

# self.span = SpanSelector(ax, listenFrag, 'horizontal', useblit=True, interactive=True, drag_from_anywhere=True)


#####################
# CALCULATE METHODS #
Expand Down Expand Up @@ -899,8 +921,12 @@ def plotPitch(self, cm, cmap):
pitch, pitch_values = self.calculatePitch(method, minpitch, maxpitch, maxCandidates)

if showSpec == 1:
img = self.calculateSpectrogram(self.audio, ax[1], min(pitch_values), max(pitch_values), 1, cmap)
self.colorBar(fig, 0.36, img)
if math.isnan(min(pitch_values)) and math.isnan(max(pitch_values)):
text = "Cannot draw the spectrogram because minimum and maximum values of the samples of the pitch are unvoiced."
tk.messagebox.showerror(parent=cm, title="Unvoiced samples", message=text) # show error
else:
img = self.calculateSpectrogram(self.audio, ax[1], min(pitch_values), max(pitch_values), 1, cmap)
self.colorBar(fig, 0.36, img)
color = 'w'
else: color = '#1f77b4'

Expand Down Expand Up @@ -951,6 +977,7 @@ def plotFiltering(self, cm, cmap):
self.aux.saveasWavCsv(cm, fig, self.time, self.audio, 0.5, self.fs) # save waveform as csv

self.span = self.createSpanSelector(ax[0]) # Select a fragment with the cursor and play the audio of that fragment
# self.addLoadButton(fig, ax[0], self.fs, self.time, filteredSignal, self.fileName+str(' (filtered)'))
plt.show() # show the figure


Expand All @@ -961,24 +988,25 @@ def plotFiltFreqResponse(self, cm):
filter = cm.var_filt.get() # butterworth, elliptic...
type = cm.var_pass.get() # # lowpass, highpass, bandpass or bandstop

fig, ax = plt.subplots(1, 2)
plt.subplots_adjust(hspace=.4) # to avoid overlapping between xlabel and title
fig, ax = plt.subplots(2, figsize=(9,7))
plt.subplots_adjust(hspace=.3) # to avoid overlapping between xlabel and title
fig.canvas.manager.set_window_title('Filter frequency response') # set title to the figure window

_, _, _, b, a = self.designFilter(fcut1, fcut2, p, filter, type)

# Calculate the filter frequency response
# w, h = signal.freqz(b, a)
w, h = signal.freqz(b, a, fs=self.fs) # w: frequencies in Hz, h: frequency response
# w_rad, _ = signal.freqz(b, a) # w_rad: frequencies in rad/samples
h = signal.TransferFunction(b, a)
w, mag, phase = signal.bode(h)
w_rads = ... # w_rads: frequencies in rad/s
w, mag, phase = signal.bode(h, w_rads)

ax[0].semilogx(w, mag) # Magnitude plot
ax[0].plot(w, mag) # Magnitude plot
ax[0].axhline(y=0, color='black', linewidth='0.5', linestyle='--') # draw an horizontal line in y=0.0
ax[0].set(xlabel='Frequency (Hz)', ylabel='Magnitude (dB)', title='Frequency Response, Magnitude')
# axFragFFR[1].plot(w, np.abs(h))
ax[1].semilogx(w, phase) # Phase plot
ax[0].set(xlim=[0, max(w)], xlabel='Frequency (Hz)', ylabel='Magnitude (dB)', title='Frequency Response, Magnitude')
ax[1].plot(w, phase) # Phase plot
ax[1].axhline(y=0, color='black', linewidth='0.5', linestyle='--') # draw an horizontal line in y=0.0
ax[1].set(xlabel='Frequency (Hz)', ylabel='Phase (radians)', title='Frequency Response, Phase')
ax[1].set(xlim=[0, max(w)], xlabel='Frequency (Hz)', ylabel='Phase (deg)', title='Frequency Response, Phase')

plt.show() # show the figure

Expand Down
6 changes: 3 additions & 3 deletions generateFreeAdd.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
from tkinter import ttk
from matplotlib.widgets import SpanSelector, Button

from controlMenu import ControlMenu
from auxiliar import Auxiliar
from controlMenu import ControlMenu

# To avoid blurry fonts
from ctypes import windll
Expand All @@ -18,8 +18,8 @@ def __init__(self, master, controller):
self.controller = controller
self.master = master
self.fs = 48000 # sample frequency
self.cm = ControlMenu()
self.aux = Auxiliar()
self.cm = ControlMenu()
self.fig, self.ax = plt.subplots()
self.selectedAudio = np.empty(1)
self.freeAddMenu()
Expand All @@ -30,7 +30,7 @@ def freeAddMenu(self):
fam.title('Free addition of pure tones')
fam.iconbitmap('icons/icon.ico')
fam.wm_transient(self) # Place the toplevel window at the top
# self.cm.windowGeometry(fam, 800, 600)
# self.aux.windowGeometry(fam, 800, 600)

# Adapt the window to different sizes
for i in range(6):
Expand Down
6 changes: 3 additions & 3 deletions generateNoise.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
from tkinter import ttk
from matplotlib.widgets import SpanSelector, Button

from controlMenu import ControlMenu
from auxiliar import Auxiliar
from controlMenu import ControlMenu

# To avoid blurry fonts
from ctypes import windll
Expand All @@ -18,8 +18,8 @@ def __init__(self, master, controller):
tk.Frame.__init__(self, master)
self.controller = controller
self.master = master
self.cm = ControlMenu()
self.aux = Auxiliar()
self.cm = ControlMenu()
self.fig, self.ax = plt.subplots()
self.selectedAudio = np.empty(1)
self.noiseMenu()
Expand All @@ -30,7 +30,7 @@ def noiseMenu(self):
nm.title('Generate noise')
nm.iconbitmap('icons/icon.ico')
nm.wm_transient(self) # Place the toplevel window at the top
# self.cm.windowGeometry(nm, 850, 250)
# self.aux.windowGeometry(nm, 850, 250)

# Adapt the window to different sizes
for i in range(4):
Expand Down
10 changes: 5 additions & 5 deletions generatePureTone.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
from tkinter import ttk
from matplotlib.widgets import SpanSelector, Button, RadioButtons

from controlMenu import ControlMenu
from auxiliar import Auxiliar
from controlMenu import ControlMenu

# To avoid blurry fonts
from ctypes import windll
Expand All @@ -18,8 +18,8 @@ def __init__(self, master, controller):
tk.Frame.__init__(self, master)
self.controller = controller
self.master = master
self.cm = ControlMenu()
self.aux = Auxiliar()
self.cm = ControlMenu()
self.fig, self.ax = plt.subplots()
self.selectedAudio = np.empty(1)
self.toneMenu()
Expand All @@ -30,7 +30,7 @@ def toneMenu(self):
tm.title('Generate pure tone')
tm.iconbitmap('icons/icon.ico')
tm.wm_transient(self) # Place the toplevel window at the top
# self.cm.windowGeometry(tm, 850, 475)
# self.aux.windowGeometry(tm, 850, 475)

# Adapt the window to different sizes
for i in range(4):
Expand Down Expand Up @@ -233,13 +233,13 @@ def addScaleSaturateRadiobuttons(self, fig, offset):
def exceed(label):
options = {'scale': 0, 'saturate': 1}
option = options[label]
if option == 0:
if option == 0: # scale
for i in range(len(self.selectedAudio)):
if self.selectedAudio[i] > 1:
self.selectedAudio[i] = 1
elif self.selectedAudio[i] < -1:
self.selectedAudio[i] = -1
elif option == 1:
elif option == 1: # saturate
if max(self.selectedAudio) > 1:
self.selectedAudio = self.selectedAudio/max(abs(self.selectedAudio))
elif min(self.selectedAudio) < -1:
Expand Down
6 changes: 3 additions & 3 deletions generateSawtoothWave.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
from scipy import signal
from matplotlib.widgets import SpanSelector, Button, RadioButtons

from controlMenu import ControlMenu
from auxiliar import Auxiliar
from controlMenu import ControlMenu

# To avoid blurry fonts
from ctypes import windll
Expand All @@ -19,8 +19,8 @@ def __init__(self, master, controller):
tk.Frame.__init__(self, master)
self.controller = controller
self.master = master
self.cm = ControlMenu()
self.aux = Auxiliar()
self.cm = ControlMenu()
self.fig, self.ax = plt.subplots()
self.selectedAudio = np.empty(1)
self.sawtoothMenu()
Expand All @@ -31,7 +31,7 @@ def sawtoothMenu(self):
stm.title('Generate sawtooth wave')
stm.iconbitmap('icons/icon.ico')
stm.wm_transient(self) # Place the toplevel window at the top
# self.cm.windowGeometry(stm, 850, 475)
# self.aux.windowGeometry(stm, 850, 475)

# Adapt the window to different sizes
for i in range(4):
Expand Down
6 changes: 3 additions & 3 deletions generateSquareWave.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
from scipy import signal
from matplotlib.widgets import SpanSelector, Button, RadioButtons

from controlMenu import ControlMenu
from auxiliar import Auxiliar
from controlMenu import ControlMenu

# To avoid blurry fonts
from ctypes import windll
Expand All @@ -19,8 +19,8 @@ def __init__(self, master, controller):
tk.Frame.__init__(self, master)
self.controller = controller
self.master = master
self.cm = ControlMenu()
self.aux = Auxiliar()
self.cm = ControlMenu()
self.fig, self.ax = plt.subplots()
self.selectedAudio = np.empty(1)
self.squareMenu()
Expand All @@ -31,7 +31,7 @@ def squareMenu(self):
sm.title('Generate square wave')
sm.iconbitmap('icons/icon.ico')
sm.wm_transient(self) # Place the toplevel window at the top
# self.cm.windowGeometry(sm, 850, 500)
# self.aux.windowGeometry(sm, 850, 500)

# Adapt the window to different sizes
for i in range(4):
Expand Down
2 changes: 1 addition & 1 deletion inputRecord.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ def __init__(self, master, controller):
self.master = master
self.isrecording = False
self.fs = 44100
self.cm = ControlMenu()
self.fig, self.ax = plt.subplots()
self.selectedAudio = np.empty(1)
self.cm = ControlMenu()
self.recordMenu()

def recordMenu(self):
Expand Down
Binary file modified wav/frag.wav
Binary file not shown.
Binary file modified wav/recording.wav
Binary file not shown.

0 comments on commit 934468c

Please sign in to comment.