| | import numpy as np |
| | import matplotlib.pyplot as plt |
| | import sounddevice as sd |
| | from scipy.fftpack import fft |
| | import time |
| | import os |
| |
|
| | |
| | SAMPLE_RATE = 44100 |
| | DURATION = 5 |
| | CHUNK_SIZE = 1024 |
| | PLOT_REFRESH_RATE = 0.1 |
| |
|
| | |
| | plt.ion() |
| | fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 8)) |
| | fig.suptitle('Live Microphone Waveform & Spectrum') |
| |
|
| | |
| | line_wave, = ax1.plot(np.arange(CHUNK_SIZE), np.zeros(CHUNK_SIZE)) |
| | line_spectrum, = ax2.plot(np.arange(CHUNK_SIZE//2), np.zeros(CHUNK_SIZE//2)) |
| |
|
| | |
| | ax1.set_ylim(-1, 1) |
| | ax1.set_xlim(0, CHUNK_SIZE) |
| | ax1.set_title('Waveform') |
| | ax1.set_ylabel('Amplitude') |
| |
|
| | ax2.set_xlim(0, CHUNK_SIZE//2) |
| | ax2.set_ylim(0, 1) |
| | ax2.set_title('Spectrum') |
| | ax2.set_ylabel('Magnitude') |
| | ax2.set_xlabel('Frequency Bin') |
| |
|
| | |
| | def audio_callback(indata, frames, time, status): |
| | if status: |
| | print(status, flush=True) |
| | |
| | |
| | line_wave.set_ydata(indata[:, 0]) |
| | |
| | |
| | N = len(indata[:, 0]) |
| | yf = fft(indata[:, 0]) |
| | xf = np.linspace(0, SAMPLE_RATE//2, N//2) |
| | line_spectrum.set_ydata(2/N * np.abs(yf[:N//2])) |
| | |
| | |
| | fig.canvas.draw() |
| | fig.canvas.flush_events() |
| |
|
| | |
| | stream = sd.InputStream( |
| | callback=audio_callback, |
| | samplerate=SAMPLE_RATE, |
| | channels=1, |
| | blocksize=CHUNK_SIZE |
| | ) |
| |
|
| | try: |
| | print("Starting audio capture... Press Ctrl+C to stop.") |
| | with stream: |
| | while True: |
| | time.sleep(PLOT_REFRESH_RATE) |
| | except KeyboardInterrupt: |
| | print("\nStopping audio capture...") |
| | |
| | |
| | timestamp = time.strftime("%Y%m%d-%H%M%S") |
| | filename = f"waveform_{timestamp}.png" |
| | fig.savefig(filename) |
| | print(f"Saved waveform image as {filename}") |
| | |
| | plt.close() |
| | except Exception as e: |
| | print(f"Error: {e}") |
| | plt.close() |