tuner code

This commit is contained in:
David Westgate 2024-11-15 15:50:44 -08:00
parent 824c752c51
commit 839411b1fd

85
code/tuner/main.py Normal file
View File

@ -0,0 +1,85 @@
import string
from typing import Any
from scipy.io import wavfile as wav
import numpy as np
import sounddevice as sd
import math
import sys
print("Tuner exercise")
SAMPLE_RATE = 44100
CHUNK = 2048
QUIET_THRESHOLD = 0.01
A4 = 440
DEBUG = True
NOTES = "A B♭/A♯ B C D♭/C♯ D E♭/D♯ E F F♯/G♭ G A♭/G♯".split()
def calculate_note(frequency):
if frequency > 0:
note_num = round(math.log2(frequency / 440) * 12)
octave = math.floor(4 + note_num / 12)
rel_note = note_num % 12
note = NOTES[rel_note]
return f"{note}{octave}"
return 0
def dominant_frequency(data, samplerate):
windowed_data = data * np.hanning(len(data))
fft_result = np.fft.rfft(windowed_data)
fft_magnitude = np.abs(fft_result)
freqs = np.fft.rfftfreq(len(windowed_data), 1 / samplerate)
peak_idx = np.argmax(fft_magnitude)
dominant_freq = freqs[peak_idx]
return dominant_freq
def calculate_rms(data):
return np.sqrt(np.mean(data**2))
def audio_callback(indata: np.ndarray, frames: int, time: Any, status: Any):
if status:
print(f"Status: {status}")
rms = calculate_rms(indata)
if rms > QUIET_THRESHOLD:
mono_data = np.mean(indata, axis=1)
frequency = dominant_frequency(mono_data, SAMPLE_RATE)
out = f"\r{calculate_note(frequency)}"
if DEBUG: out += f" Dominant Frequency: {frequency:.2f} Hz (RMS: {rms:.3f})"
sys.stdout.write(out)
sys.stdout.flush()
else:
pass
if DEBUG:
print(sd.query_devices())
try:
stream = sd.InputStream(
device=15,
callback=audio_callback,
samplerate=SAMPLE_RATE,
channels=1,
blocksize=CHUNK,
)
stream.start()
if DEBUG:
print("channels? ", stream.channels)
print("device? ", stream.device)
print("active? ", stream.active)
while True:
pass
except KeyboardInterrupt:
print("Audio recording stopped.")
finally:
print("Stream closed.")
# https://python-sounddevice.readthedocs.io/en/0.5.1/examples.html#plot-microphone-signal-s-in-real-time
# https://github.com/mzucker/python-tuner/blob/master/tuner.py