Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # https://codegolf.stackexchange.com/questions/34540/print-the-lyrics-to-twinkle-twinkle-little-star
- # https://en.wikipedia.org/wiki/File:Twinkle_Twinkle_Little_Star_plain.ogg
- import pyaudio
- from array import array
- import scipy.signal
- import numpy
- import math
- import sys
- MIN_AMPLITUDE = -52
- FRAMERATE = 44100
- # This function is a little
- # Why is pred here anyways?
- def first(list, pred):
- for i in range(len(list)):
- if(list[i] > 0):
- return i;
- return 0;
- # You would usually want to write it like this:
- def first(list, pred):
- for x in list:
- if x > 0:
- return x
- return 0
- # Note that use of ; delimiter is only necessary if you
- # have multiple statements in one line. That's never.
- # I removed them from rest of the code.
- # Based on: https://en.wikipedia.org/wiki/Decibel#Acoustics
- def getAmplitude(sig):
- total = 0
- elems = float(len(sig))
- for x in sig:
- total += numpy.abs(x) / elems
- if(total == 0):
- return -99
- else:
- return 20 * math.log(total / 32768., 10)
- # Based on: https://en.wikipedia.org/wiki/Piano_key_frequencies
- def getNote(freq):
- return int(12 * math.log(freq / 440, 2) + 49)
- # --------------------------------------------------------------------------
- # This is stolen straight from here w/ very slight modifications: https://gist.github.com/endolith/255291
- def parabolic(f, x):
- return 1/2. * (f[x-1] - f[x+1]) / (f[x-1] - 2 * f[x] + f[x+1]) + x
- def getFrequency(sig):
- # Calculate autocorrelation (same thing as convolution, but with
- # one input reversed in time), and throw away the negative lags
- corr = scipy.signal.fftconvolve(sig, sig[::-1], mode='full')
- corr = corr[len(corr)/2:]
- # Find the first low point
- diffs = numpy.diff(corr)
- # Find the next peak after the low point (other than 0 lag). This bit is
- # not reliable for long signals, due to the desired peak occurring between
- # samples, and other peaks appearing higher.
- # Should use a weighting function to de-emphasize the peaks at longer lags.
- start = first(diffs, lambda x: x > 0)
- peak = numpy.argmax(corr[start:]) + start
- return parabolic(corr, peak) * (FRAMERATE / len(sig))
- # --------------------------------------------------------------------------
- # These are the wrong keys (ie it is detecting middle C as an A), but I'm far too lazy to figure out why.
- # Anyway, these are what are detected from the Wikipedia .ogg file:
- notes = [73, 66, 64, 66, 68, 69, 71, 73, 66, 68, 69, 71, 66, 68, 69, 71 ]
- words = ["Twinkle, ", "twinkle, ", "little ", "star,\n", "How I ", "wonder ", "what you ", "are.\n", "Up a", "bove the ", "world so ", "high,\n", "Like a ", "diamond ", "in the ", "sky.\n"]
- notes += notes[:8]
- words += words[:8]
- pa = pyaudio.PyAudio()
- stream = pa.open(format=pyaudio.paInt16, channels = 1, rate = FRAMERATE, input = True, frames_per_buffer = 4096)
- idx = 0
- # Note how I removed braces after while and if
- while idx < len(notes):
- # Read signal
- sig = array('h', stream.read(4096))
- if getAmplitude(sig) > MIN_AMPLITUDE:
- note = getNote(getFrequency(sig))
- if note == notes[idx]:
- print(words[idx], end='') # Note, no sys needed
- idx += 1
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement