diff --git a/main.py b/main.py index 4d947bf..d880ea6 100644 --- a/main.py +++ b/main.py @@ -34,37 +34,37 @@ def monitor_pitch(device: int = 5, pass supported_sample_rates = numpy.array(supported_sample_rates) logger.info('Supported rates: {}'.format(supported_sample_rates)) - + ''' max_freq < 2 * sample_rate min_freq * 2**(1/12) > freq_resolution (for discrimination), more for accuracy... freq_resolution <= sample_rate / (samples_per_buffer * num_buffers) ''' freq_resolution = min_freq * 2**(1/12) / 10 - + rate_is_acceptable = supported_sample_rates >= 2 * max_freq sample_rate = int(numpy.min(supported_sample_rates[rate_is_acceptable])) num_buffers = int(numpy.ceil(sample_rate / (samples_per_buffer * freq_resolution))) samples_per_fft = samples_per_buffer * num_buffers - + logger.info('Running on device {} with {} buffers,'.format(device, num_buffers) + ' {} sample rate, {} samples per buffer'.format( device, num_buffers, sample_rate, samples_per_buffer)) logger.info('Buffers take {:.3g} sec to fully clear'.format(samples_per_fft / sample_rate)) - + stream = audio.open(format=pyaudio.paInt16, channels=1, rate=sample_rate, input=True, frames_per_buffer=samples_per_buffer) stream.start_stream() - - + + # Hanning window window = (1 - numpy.cos(numpy.linspace(0, 2 * pi, samples_per_fft, False))) / 2 - + freqs = numpy.fft.fftfreq(samples_per_fft, 1 / sample_rate) - + buf = numpy.zeros(num_buffers * samples_per_buffer, dtype=numpy.float32) note_names = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B'] @@ -72,25 +72,25 @@ def monitor_pitch(device: int = 5, # Shift the buffer down and new data in buf[:-samples_per_buffer] = buf[samples_per_buffer:] buf[-samples_per_buffer:] = numpy.fromstring(stream.read(samples_per_buffer), numpy.int16) - + fft = numpy.fft.rfft(buf * window) - + # Get frequency of maximum response in range ind = numpy.abs(fft[1:]).argmax() + 1 freq = freqs[ind] mag = numpy.abs(fft[ind]) - + # Get note number and nearest note q = numpy.log2(freq/440) n = 12 * q + 69 n0 = int(round(n)) - + delta = n - n0 logger.info('freq: {:7.2f} Hz mag:{:7.2f} note: {:>3s} {:+.2f}'.format( freq, numpy.log10(mag), note_names[n0 % 12] + str(n0//12 - 1), delta)) delta_part = int(delta // 0.1) - if delta_part > 0: + if delta_part > 0: signal = ' ' * 6 + '+' * delta_part elif delta_part == 0: signal = ' ' * 5 + '|' @@ -98,7 +98,7 @@ def monitor_pitch(device: int = 5, signal = ' ' * (5 + delta_part) + '-' * delta_part logger.info(' {}'.format(signal)) - + if __name__ == '__main__': audio = pyaudio.PyAudio() logger.info("Available devices:")