aboutsummaryrefslogtreecommitdiff
path: root/visualize.py
diff options
context:
space:
mode:
authorsotech117 <michael_foiani@brown.edu>2023-12-14 15:38:21 -0500
committersotech117 <michael_foiani@brown.edu>2023-12-14 15:38:21 -0500
commit58eef6da985dcacbb3240a977dc71b8891f8524f (patch)
tree771a07edde90f7df3e2f8e2cf703ab3448cec1c8 /visualize.py
parenta20062f736ba1f39438422c9b2e8387667747ed1 (diff)
add debug tool via upload
Diffstat (limited to 'visualize.py')
-rw-r--r--visualize.py120
1 files changed, 120 insertions, 0 deletions
diff --git a/visualize.py b/visualize.py
new file mode 100644
index 0000000..d1b2a08
--- /dev/null
+++ b/visualize.py
@@ -0,0 +1,120 @@
+# This is a sample Python script.
+import struct
+
+# Press ⌃R to execute it or replace it with your code.
+# Press Double ⇧ to search everywhere for classes, files, tool windows, actions, and settings.
+
+from scipy.fftpack import fft
+import numpy as np
+import pyaudio
+import matplotlib.pyplot as plt
+
+
+class Test(object):
+
+ def __init__(self):
+ # stream constants
+ self.CHUNK = 2048 * 2
+ self.FORMAT = pyaudio.paInt32
+ self.CHANNELS = 1
+ self.RATE = 44100
+ self.pause = False
+
+ # stream object
+ self.p = pyaudio.PyAudio()
+ self.stream = self.p.open(
+ format=self.FORMAT,
+ channels=self.CHANNELS,
+ rate=self.RATE,
+ input=True,
+ output=True,
+ frames_per_buffer=self.CHUNK,
+ )
+
+ self.seenvalues = set()
+
+ self.sample_divs = 4
+
+ # goal: returns the max frequency of waveform
+ def get_fundamental_frequency(self, audio_waveform):
+ spectrum = fft(audio_waveform)
+
+ # scale and normalize the spectrum, some are imaginary
+ scaled_spectrum = np.abs(spectrum)
+ scaled_spectrum = scaled_spectrum / (np.linalg.norm(scaled_spectrum) + 1e-16)
+
+ # get the index of the max
+ np_max = max(scaled_spectrum)
+ max_index = np.where(scaled_spectrum == np_max)[0][0]
+
+ # the index corresponds to the following linspace
+ index_to_freq = np.linspace(0, self.RATE, self.CHUNK)
+ return index_to_freq[max_index], scaled_spectrum
+
+ def read_audio_stream(self):
+ data = self.stream.read(self.CHUNK)
+ data_int = struct.unpack(str(self.CHUNK) + 'i', data)
+ return data_int
+
+ def open_loop(self, graphics=True):
+ self.init_plots()
+ while not self.pause:
+ waveform = self.read_audio_stream()
+ freq_max, scaled_spectrum = self.get_fundamental_frequency(waveform)
+ if 250 < freq_max < 550:
+ if freq_max not in self.seenvalues:
+ print(freq_max)
+ self.seenvalues.add(freq_max)
+
+ # update figure canvas if wanted
+ if graphics:
+ # set top graph
+ data_np = np.array(waveform) / (np.linalg.norm(waveform) + 1e-16) * 10
+ self.line.set_ydata(data_np[0:len(data_np)// self.sample_divs])
+ # set bottom graph
+ self.line_fft.set_ydata(scaled_spectrum)
+
+ # update figures
+ self.fig.canvas.draw()
+ self.fig.canvas.flush_events()
+
+ def init_plots(self):
+
+ # x variables for plotting
+ x = np.arange(0, self.CHUNK * 2 // self.sample_divs, 2)
+ xf = np.linspace(0, self.RATE, self.CHUNK)
+
+ # create matplotlib figure and axes
+ self.fig, (ax1, ax2) = plt.subplots(2, figsize=(15, 7))
+
+ # create a line object with random data
+ self.line, = ax1.plot(x, np.random.rand(self.CHUNK // self.sample_divs), '-', lw=2)
+
+ # create semilogx line for spectrum
+ self.line_fft, = ax2.semilogx(
+ xf, np.random.rand(self.CHUNK), '-', lw=2)
+
+ # format waveform axes
+ ax1.set_title('AUDIO WAVEFORM')
+ ax1.set_xlabel('samples')
+ ax1.set_ylabel('volume')
+ ax1.set_ylim(-1, 1)
+ ax1.set_xlim(0, self.CHUNK // self.sample_divs)
+ plt.setp(
+ ax1,
+ xticks=[0, self.CHUNK // self.sample_divs, self.CHUNK * 2 // self.sample_divs],
+ )
+ plt.setp(ax2, yticks=[0, 1], )
+
+ # format spectrum axes
+ ax2.set_xlim(20, self.RATE / 2)
+
+ # show axes
+ thismanager = plt.get_current_fig_manager()
+ # thismanager.window.setGeometry(5, 120, 1910, 1070)
+ plt.show(block=False)
+
+
+if __name__ == '__main__':
+ t = Test()
+ t.open_loop() \ No newline at end of file