class Sound: """Generate sound. Requires PyAudio & NumPy.""" def __init__(self, rate=44100, channels=1): # Suppress Jack and ALSA error messages on Linux: https://github.com/rtmrtmrtmrtm/weakmon/blob/master/weakaudio.py nullfd = os.open("/dev/null", 1) oerr = os.dup(2) os.dup2(nullfd, 2) self.stream = PyAudio().open(format=paFloat32, channels=channels, rate=rate, output=True) os.dup2(oerr, 2) os.close(oerr) os.close(nullfd) return def play(self, frequency=440, length=1.0, volume=1.0, rate=44100): """Play sine wave at frequency, for length, at rate parameters values.""" self.stream.stop_stream() self.stream.start_stream() wave = concatenate( [sin(arange(length * rate) * frequency * pi * 2 / rate)]) * volume self.stream.write(wave.astype(float32).tostring()) return
def audio_freq(): # Значення крайніх нот у моєму випадку (шестиструнна гітара в строї Ре) note_min = 60 # Нота До 4-ї октави note_max = 71 # Нота Сі 4-ї октави sample_freq = 22050 # Частота кадру в герцах # Від збільшення цих констант залежить швидкість оновлення частоти. frame_size = 2048 # Кількість зразків у кадрі frames_per_fft = 16 # Кількість кадрів для середнього значення ШПФ samples_per_fft = frame_size * frames_per_fft # Кількість зразків на ШПФ freq_step = sample_freq / samples_per_fft # Крок частоти # Отримання мінімального та максимального показника для наших нот в межах ШПФ. def note_to_fftbin(n): return 440 * 2.0 ** ((n - 69) / 12.0) / freq_step imin = max(0, int(numpy.floor(note_to_fftbin(note_min - 1)))) imax = min(samples_per_fft, int(numpy.ceil(note_to_fftbin(note_max + 1)))) # Визначення простору для ШПФ. buf = numpy.zeros(samples_per_fft, dtype=numpy.float32) # Функція вікна Хеннінга. window = 0.5 * (1 - numpy.cos(numpy.linspace(0, 2*numpy.pi, samples_per_fft, False))) # Відкриваємо аудіо потік. stream = PyAudio().open(format=paInt16, channels=1, rate=sample_freq, input=True, frames_per_buffer=frame_size) stream.start_stream() # Отримуємо дані, поки потік відкритий. while stream.is_active(): # Оновлюємо буфер та приймаємо нові дані. buf[:-frame_size] = buf[frame_size:] buf[-frame_size:] = numpy.fromstring(stream.read(frame_size), numpy.int16) # Запускаємо ШПФ в буфері в межах вікна. fft = numpy.fft.rfft(buf * window) # Отримуємо максимально повторювану частоту в діапазоні. freq = (numpy.abs(fft[imin:imax]).argmax() + imin) * freq_step # Запис відображення ноти (get_note) у файл freqs.txt freq_save(get_note(freq)) # Правильно закриваємо аудіо потік. stream.stop_stream() stream.close() stream.terminate()