Skip to content

Instantly share code, notes, and snippets.

@nomelif
Created January 8, 2017 18:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nomelif/db58aaf8989085bd5e1a1f6acb77d0b3 to your computer and use it in GitHub Desktop.
Save nomelif/db58aaf8989085bd5e1a1f6acb77d0b3 to your computer and use it in GitHub Desktop.
This transforms microphone input into MIDI data in real time and spits it over ALSA.
import pyaudio
import alsaseq
import numpy as np
CHUNKSIZE = 1024*2 # fixed chunk size
# initialize portaudio
p = pyaudio.PyAudio()
stream = p.open(format=pyaudio.paInt16, channels=1, rate=44100, input=True, frames_per_buffer=CHUNKSIZE)
# Variable to hold data about the previous note
previous = None
# Open a socket one can connect to via alsa
alsaseq.client("Midify", 0, 1, False)
# The contents of the previous chunk
olddata = np.array([])
try:
while True:
# Get the last two chunks into numpydata
data = stream.read(CHUNKSIZE)
newdata = np.fromstring(data, dtype=np.int16)
numpydata = np.append(olddata, newdata)
olddata = newdata
# Print the last guessed note
print(previous)
if np.max(numpydata) < 500:
if previous != None:
# Midi meaning that the last note has ended
alsaseq.output( (7, 0, 0, 253, (0, 0), (130, 0), (128, 0), (0, previous, 0, 0, 0)) )
previous = None
else:
# Extract the maximal frequency using numpy-sorcery
w = np.fft.fft(numpydata)
freqs = np.fft.fftfreq(len(w))
idx = np.argmax(np.abs(w))
freq = freqs[idx]
try:
# Get the note number from the frequency
note = int(round(12*np.log2(abs(freq*44100)/440)+49))
if previous != note:
if previous != None:
# Tell the listener of our midi stream to silence the old note...
alsaseq.output( (7, 0, 0, 253, (0, 0), (130, 0), (128, 0), (0, previous, 0, 0, 0)) )
# ...and start playing the new one
alsaseq.output( (6, 0, 0, 253, (0, 0), (0, 0), (0, 0), (0, note, 100, 0, 0)) )
previous = note
except OverflowError:
pass
except KeyboardInterrupt:
pass
# Cleanup
stream.stop_stream()
stream.close()
p.terminate()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment