<s> import sys <EOL> import math <EOL> import scipy <EOL> import pylab <EOL> import scipy . io . wavfile as wav <EOL> import wave <EOL> from scipy import signal <EOL> from itertools import product <EOL> import numpy <EOL> def readWav ( ) : <EOL> """<STR_LIT>""" <EOL> sound_wave = wave . open ( sys . argv [ <NUM_LIT:1> ] , "<STR_LIT:r>" ) <EOL> nframes = sound_wave . getnframes ( ) <EOL> framerate = sound_wave . getframerate ( ) <EOL> params = sound_wave . getparams ( ) <EOL> duration = nframes / float ( framerate ) <EOL> print "<STR_LIT>" % ( framerate , ) <EOL> print "<STR_LIT>" % ( nframes , ) <EOL> print "<STR_LIT>" % ( duration , ) <EOL> print scipy . array ( sound_wave ) <EOL> return ( sound_wave , nframes , framerate , duration , params ) <EOL> def getDuration ( sound_file ) : <EOL> """<STR_LIT>""" <EOL> wr = wave . open ( sound_file , '<STR_LIT:r>' ) <EOL> nchannels , sampwidth , framerate , nframes , comptype , compname = wr . getparams ( ) <EOL> return nframes / float ( framerate ) <EOL> def getFrameRate ( sound_file ) : <EOL> wr = wave . open ( sound_file , '<STR_LIT:r>' ) <EOL> nchannels , sampwidth , framerate , nframes , comptype , compname = wr . getparams ( ) <EOL> return framerate <EOL> def plotSoundWave ( rate , sample ) : <EOL> """<STR_LIT>""" <EOL> t = scipy . linspace ( <NUM_LIT:0> , <NUM_LIT:2> , <NUM_LIT:2> * rate , endpoint = False ) <EOL> pylab . figure ( '<STR_LIT>' ) <EOL> T = int ( <NUM_LIT> * rate ) <EOL> pylab . plot ( t [ : T ] , sample [ : T ] , ) <EOL> pylab . show ( ) <EOL> def plotPartials ( binFrequencies , maxFreq , magnitudes ) : <EOL> """<STR_LIT>""" <EOL> T = int ( maxFreq ) <EOL> pylab . figure ( '<STR_LIT>' ) <EOL> pylab . plot ( binFrequencies [ : T ] , magnitudes [ : T ] , ) <EOL> pylab . xlabel ( '<STR_LIT>' ) <EOL> pylab . ylabel ( '<STR_LIT>' ) <EOL> pylab . show ( ) <EOL> def plotPowerSpectrum ( FFT , binFrequencies , maxFreq ) : <EOL> """<STR_LIT>""" <EOL> T = int ( maxFreq ) <EOL> pylab . figure ( '<STR_LIT>' ) <EOL> pylab . plot ( binFrequencies [ : T ] , scipy . absolute ( FFT [ : T ] ) * scipy . absolute ( FFT [ : T ] ) , ) <EOL> pylab . xlabel ( '<STR_LIT>' ) <EOL> pylab . ylabel ( '<STR_LIT>' ) <EOL> pylab . show ( ) <EOL> def get_frequencies_axis ( framerate , fft_length ) : <EOL> binResolution = float ( framerate ) / float ( fft_length ) <EOL> binFreqs = [ ] <EOL> for k in range ( fft_length ) : <EOL> binFreq = k * binResolution <EOL> binFreqs . append ( binFreq ) <EOL> return binFreqs <EOL> def is_Prime ( n ) : <EOL> """<STR_LIT>""" <EOL> n = abs ( int ( n ) ) <EOL> if n < <NUM_LIT:2> : <EOL> return False <EOL> if n == <NUM_LIT:2> : <EOL> return True <EOL> if not n & <NUM_LIT:1> : <EOL> return False <EOL> for x in range ( <NUM_LIT:3> , int ( n ** <NUM_LIT:0.5> ) + <NUM_LIT:1> , <NUM_LIT:2> ) : <EOL> if n % x == <NUM_LIT:0> : <EOL> return False <EOL> return True <EOL> def get_next_power_2 ( n ) : <EOL> """<STR_LIT>""" <EOL> power = <NUM_LIT:1> <EOL> while ( power < n ) : <EOL> power *= <NUM_LIT:2> <EOL> if power > <NUM_LIT:1> : <EOL> return power / <NUM_LIT:2> <EOL> else : <EOL> return <NUM_LIT:1> <EOL> class MIDI_Detector_Least_Squares_2 ( object ) : <EOL> """<STR_LIT>""" <EOL> HAN_WINDOW = <NUM_LIT> <EOL> HOP_SIZE = <NUM_LIT> <EOL> AkPnBcht_noise = <NUM_LIT> <EOL> AkPnBcht_std = <NUM_LIT> <EOL> AkPnBcht_noise_2 = <NUM_LIT> <EOL> AkPnBcht_std_2 = <NUM_LIT> <EOL> AkPnBcht_std_10 = <NUM_LIT> <EOL> AkPnBcht_std__10 = <NUM_LIT> <EOL> AkPnBsdf_noise = <NUM_LIT> <EOL> AkPnBsdf_std = <NUM_LIT> <EOL> AkPnBsdf_noise_2 = <NUM_LIT> <EOL> AkPnBsdf_std_2 = <NUM_LIT> <EOL> AkPnCGdD_noise = <NUM_LIT> <EOL> AkPnCGdD_std = <NUM_LIT> <EOL> AkPnCGdD_noise_2 = <NUM_LIT> <EOL> AkPnCGdD_std_2 = <NUM_LIT> <EOL> AkPnStgb_noise_10 = <NUM_LIT> <EOL> AkPnStgb_std_10 = <NUM_LIT> <EOL> ENSTDkAm_noise_10 = <NUM_LIT> <EOL> ENSTDkAm_std_10 = <NUM_LIT> <EOL> ENSTDkCl_noise_10 = <NUM_LIT> <EOL> ENSTDkCl_std_10 = <NUM_LIT> <EOL> SptkBGAm_noise_10 = <NUM_LIT> <EOL> SptkBGAm_std_10 = <NUM_LIT> <EOL> SptkBGCl_noise_10 = <NUM_LIT> <EOL> SptkBGCl_std_10 = <NUM_LIT> <EOL> StbgTGd2_noise_10 = <NUM_LIT> <EOL> StbgTGd2_std_10 = <NUM_LIT> <EOL> def __init__ ( self , wav_file ) : <EOL> self . wav_file = wav_file <EOL> self . THRESHOLD = <NUM_LIT> <EOL> self . HAN_WINDOW = <NUM_LIT> <EOL> self . HOP_SIZE = <NUM_LIT> <EOL> self . minFreqConsidered = <NUM_LIT:20> <EOL> self . maxFreqConsidered = <NUM_LIT> <EOL> self . low_f0s = [ <NUM_LIT> , <NUM_LIT> , <NUM_LIT> , <NUM_LIT> , <NUM_LIT> , <NUM_LIT> , <NUM_LIT> , <EOL> <NUM_LIT> , <NUM_LIT> , <NUM_LIT> , <NUM_LIT> , <NUM_LIT> , <NUM_LIT> , <NUM_LIT> , <EOL> <NUM_LIT> , <NUM_LIT> , <NUM_LIT> , <NUM_LIT> , <NUM_LIT> , <NUM_LIT> ] <EOL> self . avg_noise_power = <NUM_LIT> <EOL> self . std_noise_power = <NUM_LIT> <EOL> def detect_MIDI_notes ( self ) : <EOL> """<STR_LIT>""" <EOL> ( framerate , sample ) = wav . read ( self . wav_file ) <EOL> duration = getDuration ( self . wav_file ) <EOL> midi_notes = [ ] <EOL> if duration > <NUM_LIT> : <EOL> ( FFT , filteredFreqs , maxFreq , magnitudes , significant_freq ) = self . calculateFFT ( duration , framerate , sample ) <EOL> clusters = self . clusterFrequencies ( filteredFreqs ) <EOL> averagedClusters = self . getClustersMeans ( clusters ) <EOL> f0_candidates = self . getF0Candidates ( averagedClusters ) <EOL> midi_notes = self . matchWithMIDINotes ( f0_candidates ) <EOL> if significant_freq > <NUM_LIT:0> : <EOL> significant_midi_notes = self . matchWithMIDINotes ( [ significant_freq ] ) <EOL> significant_midi_note = significant_midi_notes [ <NUM_LIT:0> ] <EOL> if significant_midi_note not in midi_notes : <EOL> midi_notes . append ( significant_midi_note ) <EOL> midi_notes = self . remove_lower_octave ( significant_midi_note , midi_notes ) <EOL> '''<STR_LIT>''' <EOL> return midi_notes <EOL> def remove_lower_octave ( self , upper_octave , midi_notes ) : <EOL> lower_octave = upper_octave - <NUM_LIT:12> <EOL> if lower_octave in midi_notes : <EOL> midi_notes . remove ( lower_octave ) <EOL> return midi_notes <EOL> def Pertusa_Inesta_Algorithm ( self ) : <EOL> ( framerate , sample ) = wav . read ( self . wav_file ) <EOL> monoChannel = sample . mean ( axis = <NUM_LIT:1> ) <EOL> stft = self . STFT ( monoChannel , framerate , self . HAN_WINDOW , self . HOP_SIZE ) <EOL> ( stft_bin_freqs , stft_magnitudes ) = self . get_stft_bin_freqs ( stft , framerate ) <EOL> print stft_bin_freqs <EOL> '''<STR_LIT>''' <EOL> '''<STR_LIT>''' <EOL> def get_stft_bin_freqs ( self , stft , framerate ) : <EOL> fft_length = self . HAN_WINDOW * framerate <EOL> binResolution = float ( framerate ) / float ( fft_length ) <EOL> stft_binFrequencies = [ ] <EOL> stft_magnitudes = [ ] <EOL> for i in range ( len ( stft ) ) : <EOL> binFreqs = [ ] <EOL> magnitudes = [ ] <EOL> for k in range ( len ( stft [ i ] ) ) : <EOL> binFreq = k * binResolution <EOL> if binFreq > self . minFreqConsidered and binFreq < self . maxFreqConsidered : <EOL> power_spectrum = scipy . absolute ( stft [ i ] [ k ] ) * scipy . absolute ( stft [ i ] [ k ] ) <EOL> if power_spectrum > self . THRESHOLD : <EOL> binFreqs . append ( binFreq ) <EOL> magnitudes . append ( power_spectrum ) <EOL> stft_binFrequencies . append ( binFreqs ) <EOL> stft_magnitudes . append ( magnitudes ) <EOL> return ( stft_binFrequencies , stft_magnitudes ) <EOL> def get_candidates_with_partials ( self , frequencies , magnitudes ) : <EOL> print frequencies <EOL> partial_margin = <NUM_LIT> <EOL> candidates_freq = [ ] <EOL> candidates_magnitude = [ ] <EOL> for i in range ( len ( frequencies ) ) : <EOL> ( partials , partial_magnitudes ) = self . find_partials ( frequencies [ i : ] , frequencies [ i ] , magnitudes [ i : ] ) <EOL> candidates_freq . append ( partials ) <EOL> candidates_magnitude . append ( partial_magnitudes ) <EOL> return ( candidates_freq , candidates_magnitude ) <EOL> def calculateFFT ( self , duration , framerate , sample ) : <EOL> """<STR_LIT>""" <EOL> fft_length = int ( duration * framerate ) <EOL> '''<STR_LIT>''' <EOL> fft_length = get_next_power_2 ( fft_length ) <EOL> FFT = numpy . fft . fft ( sample , n = fft_length ) <EOL> '''<STR_LIT>''' <EOL> threshold = <NUM_LIT:0> <EOL> power_spectra = [ ] <EOL> frequency_bin_with_max_spectrum = <NUM_LIT:0> <EOL> for i in range ( len ( FFT ) / <NUM_LIT:2> ) : <EOL> power_spectrum = scipy . absolute ( FFT [ i ] ) * scipy . absolute ( FFT [ i ] ) <EOL> if power_spectrum > threshold : <EOL> threshold = power_spectrum <EOL> frequency_bin_with_max_spectrum = i <EOL> power_spectra . append ( power_spectrum ) <EOL> max_power_spectrum = threshold <EOL> threshold = float ( self . avg_noise_power ) - <NUM_LIT:3> * float ( self . std_noise_power ) <EOL> binFrequencies = [ ] <EOL> magnitudes = [ ] <EOL> binResolution = float ( framerate ) / float ( fft_length ) <EOL> sum_of_significant_spectra = <NUM_LIT:0> <EOL> for k in range ( len ( FFT ) ) : <EOL> binFreq = k * binResolution <EOL> if binFreq > self . maxFreqConsidered : <EOL> FFT = FFT [ : k ] <EOL> break <EOL> elif binFreq > self . minFreqConsidered : <EOL> power_spectrum = power_spectra [ k ] <EOL> if power_spectrum > threshold : <EOL> magnitudes . append ( power_spectrum ) <EOL> binFrequencies . append ( binFreq ) <EOL> if power_spectrum != max_power_spectrum : <EOL> sum_of_significant_spectra += power_spectrum <EOL> significant_freq = <NUM_LIT:0.0> <EOL> if max_power_spectrum > sum_of_significant_spectra : <EOL> significant_freq = frequency_bin_with_max_spectrum * binResolution <EOL> maxFreq = len ( FFT ) / duration <EOL> return ( FFT , binFrequencies , maxFreq , magnitudes , significant_freq ) <EOL> def STFT ( self , x , samplingFreq , framesz , hop ) : <EOL> """<STR_LIT>""" <EOL> framesamp = int ( framesz * samplingFreq ) <EOL> print '<STR_LIT>' + str ( framesamp ) <EOL> hopsamp = int ( hop * samplingFreq ) <EOL> print '<STR_LIT>' + str ( hopsamp ) <EOL> w = signal . hann ( framesamp ) <EOL> X = numpy . array ( [ numpy . fft . fft ( w * x [ i : i + framesamp ] ) <EOL> for i in range ( <NUM_LIT:0> , len ( x ) - framesamp , hopsamp ) ] ) <EOL> return X <EOL> def plotMagnitudeSpectrogram ( self , rate , sample , framesz , hop ) : <EOL> """<STR_LIT>""" <EOL> X = self . STFT ( sample , rate , framesz , hop ) <EOL> pylab . figure ( '<STR_LIT>' ) <EOL> pylab . imshow ( scipy . absolute ( X . T ) , origin = '<STR_LIT>' , aspect = '<STR_LIT>' , <EOL> interpolation = '<STR_LIT>' ) <EOL> pylab . xlabel ( '<STR_LIT>' ) <EOL> pylab . ylabel ( '<STR_LIT>' ) <EOL> pylab . show ( ) <EOL> def getFilteredFFT ( self , FFT , duration , threshold ) : <EOL> """<STR_LIT>""" <EOL> significantFreqs = [ ] <EOL> for i in range ( len ( FFT ) ) : <EOL> power_spectrum = scipy . absolute ( FFT [ i ] ) * scipy . absolute ( FFT [ i ] ) <EOL> if power_spectrum > threshold : <EOL> significantFreqs . append ( i / duration ) <EOL> return significantFreqs <EOL> def clusterFrequencies ( self , freqs ) : <EOL> """<STR_LIT>""" <EOL> if len ( freqs ) == <NUM_LIT:0> : <EOL> return { } <EOL> clusteredFreqs = { } <EOL> bin = <NUM_LIT:0> <EOL> clusteredFreqs [ <NUM_LIT:0> ] = [ freqs [ <NUM_LIT:0> ] ] <EOL> for i in range ( len ( freqs ) - <NUM_LIT:1> ) : <EOL> dist = self . calcDistance ( freqs [ i ] , freqs [ i + <NUM_LIT:1> ] ) <EOL> if dist < <NUM_LIT> : <EOL> clusteredFreqs [ bin ] . append ( freqs [ i + <NUM_LIT:1> ] ) <EOL> else : <EOL> bin += <NUM_LIT:1> <EOL> clusteredFreqs [ bin ] = [ freqs [ i + <NUM_LIT:1> ] ] <EOL> return clusteredFreqs <EOL> def getClustersMeans ( self , clusters ) : <EOL> """<STR_LIT>""" <EOL> means = [ ] <EOL> for bin , freqs in clusters . iteritems ( ) : <EOL> means . append ( sum ( freqs ) / len ( freqs ) ) <EOL> return means <EOL> def getDistances ( self , freqs ) : <EOL> """<STR_LIT>""" <EOL> distances = { ( freqs [ i ] , freqs [ j ] ) : self . calcDistance ( freqs [ i ] , freqs [ j ] ) <EOL> for ( i , j ) in product ( range ( len ( freqs ) ) , repeat = <NUM_LIT:2> ) } <EOL> distances = { freq_pair : dist for freq_pair , dist in distances . iteritems ( ) if dist < <NUM_LIT> } <EOL> return distances <EOL> def calcDistance ( self , freq1 , freq2 ) : <EOL> """<STR_LIT>""" <EOL> difference = abs ( freq1 - freq2 ) <EOL> log = math . log ( ( freq1 + freq2 ) / <NUM_LIT:2> ) <EOL> if log < <NUM_LIT> : <EOL> return freq1 + freq2 <EOL> return difference / log <EOL> def getF0Candidates ( self , frequencies ) : <EOL> """<STR_LIT>""" <EOL> f0_candidates = [ ] <EOL> '''<STR_LIT>''' <EOL> while len ( frequencies ) > <NUM_LIT:0> : <EOL> f0_candidate = frequencies [ <NUM_LIT:0> ] <EOL> f0_candidates . append ( f0_candidate ) <EOL> frequencies . remove ( f0_candidate ) <EOL> frequencies = self . filterOutHarmonics ( frequencies , f0_candidate ) <EOL> return f0_candidates <EOL> def filterOutHarmonics ( self , frequencies , f0_candidate ) : <EOL> """<STR_LIT>""" <EOL> REMAINDER_THRESHOLD = <NUM_LIT> <EOL> def is_multiple ( f , f0 ) : <EOL> return abs ( round ( f / f0 ) - f / f0 ) < REMAINDER_THRESHOLD <EOL> return [ f for f in frequencies if not is_multiple ( f , f0_candidate ) ] <EOL> def find_low_freq_candidate ( self , frequencies ) : <EOL> REMAINDER_THRESHOLD = <NUM_LIT> <EOL> f0_candidates = [ ] <EOL> def is_multiple ( f , f0 ) : <EOL> return abs ( round ( f / f0 ) - f / f0 ) < REMAINDER_THRESHOLD <EOL> best_candidate = - <NUM_LIT:1> <EOL> max_no_partials = <NUM_LIT:0> <EOL> for low_f0 in self . low_f0s : <EOL> num_of_partials = <NUM_LIT:0> <EOL> for f in frequencies : <EOL> if is_multiple ( f , low_f0 ) : <EOL> num_of_partials += <NUM_LIT:1> <EOL> if num_of_partials > max_no_partials : <EOL> max_no_partials = num_of_partials <EOL> best_candidate = low_f0 <EOL> return best_candidate <EOL> def find_partials ( self , frequencies , f0_candidate , magnitudes ) : <EOL> """<STR_LIT>""" <EOL> REMAINDER_THRESHOLD = <NUM_LIT> <EOL> def is_multiple ( f , f0 ) : <EOL> return abs ( round ( f / f0 ) - f / f0 ) < REMAINDER_THRESHOLD <EOL> partials = [ ] <EOL> partial_magnitudes = [ ] <EOL> for i in range ( len ( frequencies ) ) : <EOL> if is_multiple ( frequencies [ i ] , f0_candidate ) : <EOL> partials . append ( frequencies [ i ] ) <EOL> partial_magnitudes . append ( magnitudes [ i ] ) <EOL> return ( partials , partial_magnitudes ) <EOL> def matchWithMIDINotes ( self , f0_candidates ) : <EOL> midi_notes = [ ] <EOL> for freq in f0_candidates : <EOL> midi_notes . append ( int ( round ( <NUM_LIT> + <NUM_LIT:12> * math . log ( freq / <NUM_LIT> ) / math . log ( <NUM_LIT:2> ) ) ) ) <EOL> return midi_notes <EOL> if __name__ == '<STR_LIT:__main__>' : <EOL> MIDI_detector = MIDI_Detector ( sys . argv [ <NUM_LIT:1> ] ) <EOL> midi_notes = MIDI_detector . detect_MIDI_notes ( ) <EOL> print midi_notes </s>
