In [1]:
import matplotlib.pyplot as plt
%matplotlib inline
import math
import numpy as np

In [2]:
class GuitarProfile:
    def __init__(self, pitch_profile, sampling_freq, decay_factor):
        self.pitch_profile = pitch_profile
        self.sampling_freq = sampling_freq
        self.decay_factor = decay_factor

    def get_note_profile(self, pitch):
        levels_to_return = []
        freq_to_return = []
        for i in range(0,len(self.pitch_profile)):
            levels_to_return.append(self.pitch_profile[i])
            temp = (pitch - 69)/12.
            temp = math.exp(temp)
            temp *= 440
            temp *= (i+1)
            freq_to_return.append(temp)
        return levels_to_return, freq_to_return

    def create_aggregate_sample(self, period, pitch):
        sample_container = np.zeros((period))
        amplitudes, freqs = self.get_note_profile(pitch)
        for i in range(0, len(freqs)):
            single_frequency_container = np.zeros((period))
            sampling_period = 1./self.sampling_freq
            for j in range(0, period):
                single_frequency_container[j] = sampling_period * j
            single_frequency_container = np.cos(freqs[i] * 2 * math.pi * single_frequency_container)
            single_frequency_container *= amplitudes[i]
            sample_container += single_frequency_container
        return sample_container
    
    def create_aggregate_sample_with_decay(self, period, pitch):
        sample_container = np.zeros((period))
        amplitudes, freqs = self.get_note_profile(pitch)
        for i in range(0, len(freqs)):
            single_frequency_container = np.zeros((period))
            sampling_period = 1./self.sampling_freq
            for j in range(0, period):
                single_frequency_container[j] = sampling_period * j
            decay = single_frequency_container
            single_frequency_container = np.cos(freqs[i] * 2 * math.pi * single_frequency_container)
            decay = amplitudes[i]*np.exp(-self.decay_factor*decay)
            single_frequency_container *= decay
            sample_container += single_frequency_container
        return sample_container
    
def acf(container):
    results = []
    for i in range(1, int(container.shape[0]/2)):
        results.append(acf_helper(container, i))
    return results
    
def acf_helper(container, lag):
    result = 0
    for i in range(0, int(container.shape[0]/2)):
        result += container[i] * container[i + lag]
    return result

def detect_peak(container, start):
    for i in range(start, container.shape[0]):
        if container[i - 1] < container[i] and container[i + 1] < container[i]:
            return i

def get_freq(peak, frequency):
    return frequency / peak

In [3]:
profile1 = GuitarProfile([1., 0.5, 0.3, 0.4, 0.2, 0.1], 96000, 500.)
profile2 = GuitarProfile([1.], 96000, 500.)

In [4]:
amp, freq = profile1.get_note_profile(60)
for i in range(0, len(amp)):
    print "Amplitude:", amp[i], "Frequency:", freq[i]


Amplitude: 1.0 Frequency: 207.841283206
Amplitude: 0.5 Frequency: 415.682566412
Amplitude: 0.3 Frequency: 623.523849618
Amplitude: 0.4 Frequency: 831.365132824
Amplitude: 0.2 Frequency: 1039.20641603
Amplitude: 0.1 Frequency: 1247.04769924

In [5]:
plt.plot(profile1.create_aggregate_sample(2048, 60))
plt.show()



In [6]:
plt.plot(profile1.create_aggregate_sample_with_decay(2048, 60))
plt.show()



In [7]:
sample = profile1.create_aggregate_sample(2048, 60)
sample_simple = profile2.create_aggregate_sample(2048, 60)
sample_decay = profile1.create_aggregate_sample_with_decay(2048, 60)
plt.plot(acf(sample))
plt.show()
plt.plot(acf(sample_decay))
plt.show()
plt.plot(acf(sample_simple))
plt.show()



In [8]:
print get_freq(detect_peak(sample_simple, 1), profile2.sampling_freq) 
print get_freq(detect_peak(sample, 1), profile1.sampling_freq)
print get_freq(detect_peak(sample_decay, 2), profile1.sampling_freq)


207
1054
1054

In [9]:
fft_stuff = np.absolute(np.fft.rfft(sample))
fft_stuff = fft_stuff / np.amax(fft_stuff)
freq = np.fft.rfftfreq(2048, d=1./profile1.sampling_freq)
plt.plot(freq[0:25], fft_stuff[0:25])
plt.show()

fft_stuff = np.absolute(np.fft.rfft(sample_simple))
fft_stuff = fft_stuff / np.amax(fft_stuff)
freq = np.fft.rfftfreq(2048, d=1./profile1.sampling_freq)
plt.plot(freq[0:25], fft_stuff[0:25])
plt.show()

fft_stuff = np.absolute(np.fft.rfft(sample_decay))
fft_stuff = fft_stuff / np.amax(fft_stuff)
freq = np.fft.rfftfreq(2048, d=1./profile1.sampling_freq)
plt.plot(freq[0:25], fft_stuff[0:25])
plt.show()



In [11]:
import scipy.signal
filter_object = scipy.signal.bilinear(50, 2*math.pi/207)

In [18]:
simple_peaks = scipy.signal.find_peaks_cwt(acf(sample_simple), np.arange(1,10))

In [19]:
peaks2 = scipy.signal.find_peaks_cwt(acf(sample), np.arange(1,10))

In [20]:
simple_peaks2 = scipy.signal.find_peaks_cwt(acf(sample_decay), np.arange(1,10))

In [22]:
for i in simple_peaks:
    print get_freq(i, profile1.sampling_freq)


24000
210
104

In [23]:
for i in peaks2:
    print get_freq(i, profile1.sampling_freq)


24000
941
932
422
272
210
170
139
117
104
94

In [24]:
for i in simple_peaks2:
    print get_freq(i, profile1.sampling_freq)


24000
1185
448
275
217
176
142
118
106
95

In [ ]: