fix a bunch of major bugs
This commit is contained in:
parent
6066b0f47f
commit
efb73128ab
41
main.py
41
main.py
@ -1,6 +1,7 @@
|
|||||||
import logging
|
|
||||||
from typing import List, Dict
|
from typing import List, Dict
|
||||||
|
import logging
|
||||||
import queue
|
import queue
|
||||||
|
import threading
|
||||||
|
|
||||||
import pyaudio
|
import pyaudio
|
||||||
import numpy
|
import numpy
|
||||||
@ -32,18 +33,18 @@ def get_supported_sample_rates(pyaudio_device: int,
|
|||||||
pyaudio_object = pyaudio.PyAudio()
|
pyaudio_object = pyaudio.PyAudio()
|
||||||
|
|
||||||
supported_sample_rates = []
|
supported_sample_rates = []
|
||||||
devinfo = pyaudio_object.get_device_info_by_index(device)
|
devinfo = pyaudio_object.get_device_info_by_index(pyaudio_device)
|
||||||
for rate in standard_sample_rates:
|
for rate in standard_sample_rates:
|
||||||
try:
|
try:
|
||||||
if pyaudio_object.is_format_supported(rate,
|
if pyaudio_object.is_format_supported(rate,
|
||||||
input_device=device,
|
input_device=pyaudio_device,
|
||||||
input_channels=devinfo['maxInputChannels'],
|
input_channels=devinfo['maxInputChannels'],
|
||||||
input_format=pyaudio.paInt16):
|
input_format=pyaudio.paInt16):
|
||||||
supported_sample_rates.append(rate)
|
supported_sample_rates.append(rate)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
supported_sample_rates = numpy.array(supported_sample_rates)
|
supported_sample_rates = numpy.array(supported_sample_rates)
|
||||||
logger.info('Supported sample rates for device {}: {}'.format(device, supported_sample_rates))
|
return supported_sample_rates
|
||||||
|
|
||||||
|
|
||||||
class AudioAnalyzer:
|
class AudioAnalyzer:
|
||||||
@ -61,7 +62,8 @@ class AudioAnalyzer:
|
|||||||
|
|
||||||
stop = None
|
stop = None
|
||||||
|
|
||||||
def __init__(pyaudio_device: int,
|
def __init__(self,
|
||||||
|
pyaudio_device: int,
|
||||||
min_freq: float = 20,
|
min_freq: float = 20,
|
||||||
max_freq: float = 20e3,
|
max_freq: float = 20e3,
|
||||||
samples_per_buffer: int = 1024,
|
samples_per_buffer: int = 1024,
|
||||||
@ -81,6 +83,7 @@ class AudioAnalyzer:
|
|||||||
supported_sample_rates = get_supported_sample_rates(pyaudio_device, self._pyaudio_object)
|
supported_sample_rates = get_supported_sample_rates(pyaudio_device, self._pyaudio_object)
|
||||||
rate_is_acceptable = supported_sample_rates >= 2 * max_freq
|
rate_is_acceptable = supported_sample_rates >= 2 * max_freq
|
||||||
sample_rate = numpy.min(supported_sample_rates[rate_is_acceptable]).astype(int)
|
sample_rate = numpy.min(supported_sample_rates[rate_is_acceptable]).astype(int)
|
||||||
|
logger.info('Supported sample rates for device {}: {}'.format(pyaudio_device, supported_sample_rates))
|
||||||
|
|
||||||
num_buffers = numpy.ceil(sample_rate / (samples_per_buffer * freq_resolution)).astype(int)
|
num_buffers = numpy.ceil(sample_rate / (samples_per_buffer * freq_resolution)).astype(int)
|
||||||
samples_per_fft = samples_per_buffer * num_buffers
|
samples_per_fft = samples_per_buffer * num_buffers
|
||||||
@ -94,16 +97,17 @@ class AudioAnalyzer:
|
|||||||
self._fft_lock = threading.Lock()
|
self._fft_lock = threading.Lock()
|
||||||
self.frame_queue = queue.Queue()
|
self.frame_queue = queue.Queue()
|
||||||
|
|
||||||
self._stream = audio.open(format=pyaudio.paInt16,
|
print(list(self.__dict__.keys()))
|
||||||
|
self._stream = self._pyaudio_object.open(format=pyaudio.paInt16,
|
||||||
channels=1,
|
channels=1,
|
||||||
rate=sample_rate,
|
rate=sample_rate,
|
||||||
input=True,
|
input=True,
|
||||||
frames_per_buffer=samples_per_buffer,
|
frames_per_buffer=samples_per_buffer,
|
||||||
stream_callback=self.update)
|
stream_callback=self.update)
|
||||||
|
|
||||||
logger.info('Opened device {} with {} buffers,'.format(device, num_buffers) +
|
logger.info('Opened device {} with {} buffers,'.format(pyaudio_device, num_buffers) +
|
||||||
' {} sample rate, {} samples per buffer'.format(
|
' {} sample rate, {} samples per buffer'.format(
|
||||||
device, num_buffers, sample_rate, samples_per_buffer))
|
pyaudio_device, num_buffers, sample_rate, samples_per_buffer))
|
||||||
logger.info('Buffers take {:.3g} sec to fully clear'.format(samples_per_fft / sample_rate))
|
logger.info('Buffers take {:.3g} sec to fully clear'.format(samples_per_fft / sample_rate))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -155,12 +159,12 @@ class AudioAnalyzer:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
def monitor_pitch(device: int = 5,
|
def monitor_pitch(pyaudio_device: int,
|
||||||
min_freq: float = 10,
|
min_freq: float = 10,
|
||||||
max_freq: float = 6000,
|
max_freq: float = 6000,
|
||||||
):
|
):
|
||||||
|
|
||||||
analyzer = AudioAnalyzer(device=device,
|
analyzer = AudioAnalyzer(pyaudio_device=pyaudio_device,
|
||||||
min_freq=min_freq,
|
min_freq=min_freq,
|
||||||
max_freq=max_freq)
|
max_freq=max_freq)
|
||||||
|
|
||||||
@ -170,7 +174,7 @@ def monitor_pitch(device: int = 5,
|
|||||||
while True:
|
while True:
|
||||||
frame_data = analyzer.frame_queue.get()
|
frame_data = analyzer.frame_queue.get()
|
||||||
|
|
||||||
if frame_data['magnitude'] <= prev_magnitude / 2:
|
if frame_data['magnitude'] <= 10**6:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
prev_magnitude = frame_data['magnitude']
|
prev_magnitude = frame_data['magnitude']
|
||||||
@ -178,16 +182,19 @@ def monitor_pitch(device: int = 5,
|
|||||||
|
|
||||||
mnote_error = mnote - mnote_base
|
mnote_error = mnote - mnote_base
|
||||||
logger.info('freq: {:7.2f} Hz mag:{:7.2f} note: {:>3s} {:+.2f}'.format(
|
logger.info('freq: {:7.2f} Hz mag:{:7.2f} note: {:>3s} {:+.2f}'.format(
|
||||||
freq, numpy.log10(mag), note_names[base_mnote % 12] + str(base_mnote//12 - 1), mnote_error))
|
frame_data['frequency'],
|
||||||
|
numpy.log10(frame_data['magnitude']),
|
||||||
|
note_names[mnote_base % 12] + str(mnote_base // 12 - 1),
|
||||||
|
mnote_error))
|
||||||
|
|
||||||
max_num_symbols = 5
|
max_num_symbols = 10
|
||||||
num_symbols = int(mnote_error // (0.5 / max_num_symbols))
|
num_symbols = int(mnote_error // (0.5 / max_num_symbols))
|
||||||
if num_symbols > 0:
|
if num_symbols > 0:
|
||||||
signal = ' ' * max_num_symbols + ' ' + '+' * num_symbols
|
signal = ' ' * max_num_symbols + '|' + '+' * num_symbols
|
||||||
elif num_symbols == 0:
|
elif num_symbols == 0:
|
||||||
signal = ' ' * max_num_symbols + '|'
|
signal = ' ' * max_num_symbols + '#'
|
||||||
elif num_symbols < 0:
|
elif num_symbols < 0:
|
||||||
signal = ' ' * (max_num_symbols - num_symbols) + '-' * num_symbols
|
signal = ' ' * (max_num_symbols + num_symbols) + '-' * -num_symbols + '|'
|
||||||
logger.info(' {}'.format(signal))
|
logger.info(' {}'.format(signal))
|
||||||
|
|
||||||
|
|
||||||
@ -199,5 +206,5 @@ if __name__ == '__main__':
|
|||||||
if devinfo['maxInputChannels'] > 0:
|
if devinfo['maxInputChannels'] > 0:
|
||||||
logger.info(' {}: {}'.format(device, devinfo['name']))
|
logger.info(' {}: {}'.format(device, devinfo['name']))
|
||||||
|
|
||||||
monitor_pitch(device=5, min_freq=20)
|
monitor_pitch(pyaudio_device=7, min_freq=20)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user