<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Implementing and comparing several pitch detection methods on sample files
For simplicity I am using the Anaconda distribution on my Macbook Pro for this notebook. 
The purpose is to first experiment here with sample WAV files. Each file comes from a database of free samples provided free of rights by the Philharmonia Orchestra at http
Step1:  We will use scipy from the Anaconda distribution to read the WAV sample files
Step2:  We define the length we want to record in seconds and the sampling rate to the source file sample rate (44100 Hz)
Step3:  Let's plot a section of this array to look at it first
We notice a pretty periodic signal with a clear fundamental frequency
Step4:  First method
Step5:  We can visualise a section of the Fourier transform to notice there is a clear fundamental frequency
Step6:  We notice already things are not going to be that easy. There are different harmonics picked here, and 2 of the most important ones are comparable in amplitude. 
We find the frequency corresponding to the maximum of this Fourier transform, and calculate the corresponding real frequency by re-multiplying by the sampling rate
Step7:  This method detects a fundamental frequency of 248Hz, which is wrong.
We notice that as suspected by looking at the chart of the Fourier transform, the 3rd harmonic of the expected fundamental is detected with this naive method
Step8:  WIP
<ASSISTANT_TASK:>
Python Code:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
Explanation: Implementing and comparing several pitch detection methods on sample files
For simplicity I am using the Anaconda distribution on my Macbook Pro for this notebook. 
The purpose is to first experiment here with sample WAV files. Each file comes from a database of free samples provided free of rights by the Philharmonia Orchestra at http://www.philharmonia.co.uk/explore/sound_samples/.
We will use 6 samples representing a long Forte string pick of each of the 6 strings of an accoustic guitar tuned in Standard E.
Note: I have converted the sample files myself from their original mp3 format to wav format with 32bit, 44100Hz and mono channel.
We will use two different methods for detecting the pitch and compare their results.
For reference, here is the list of frequencies of all 6 strings expected for a well tuned guitar:
String  | Frequency | Scientific pitch notation | Sample
--- | --- | --- | ---
1 (E) | 329.63 Hz | E4 | Sample file
2 (B) | 246.94 Hz | B3 | Sample file
3 (G) | 196.00 Hz | G3 | Sample file
4 (D) | 146.83 Hz | D3 | Sample file
5 (A) | 110.00 Hz | A2 | Sample file
6 (E) | 82.41 Hz | E2 | Sample file
End of explanation
from scipy.io import wavfile
# Let's start with the first sample corresponding to the lower string E2
rate, myrecording = wavfile.read("samples/guitar_E2_very-long_forte_normal.wav")
print(rate, np_array.size)
Explanation: We will use scipy from the Anaconda distribution to read the WAV sample files
End of explanation
duration = 1  # seconds
fs = rate    # samples by second
# Let's restrict our sample to 1 second of the recording, after 0.5 second of sound to avoid the string picking
array = myrecording[int(0.5*fs):int(2.5*fs)]
print(array.size)
Explanation: We define the length we want to record in seconds and the sampling rate to the source file sample rate (44100 Hz)
End of explanation
df = pd.DataFrame(array)
df.loc[25000:35000].plot()
Explanation: Let's plot a section of this array to look at it first
We notice a pretty periodic signal with a clear fundamental frequency: which makes sense since a guitar string vibrates producing an almost purely sinuzoidal wave
End of explanation
fourier = np.fft.fft(array)
Explanation: First method: Naive pitch detection using Fast Fourier Transform
One first naive idea would be to "simply" take the (discrete) Fourier transform of the signal to find the fundamental frequency of the recording.
Let's try that out and see what result we get.
We use numpy to compute the discrete Fourier transform of the signal:
End of explanation
plt.plot(abs(fourier[:len(fourier)/10]))
Explanation: We can visualise a section of the Fourier transform to notice there is a clear fundamental frequency:
End of explanation
f_max_index = np.argmax(abs(fourier[:fourier.size/2]))
freqs = np.fft.fftfreq(len(fourier))
freqs[f_max_index]*fs
Explanation: We notice already things are not going to be that easy. There are different harmonics picked here, and 2 of the most important ones are comparable in amplitude. 
We find the frequency corresponding to the maximum of this Fourier transform, and calculate the corresponding real frequency by re-multiplying by the sampling rate
End of explanation
# Work in progress: coming soon
Explanation: This method detects a fundamental frequency of 248Hz, which is wrong.
We notice that as suspected by looking at the chart of the Fourier transform, the 3rd harmonic of the expected fundamental is detected with this naive method: 248.5 = 3 x 82.41, where 82.41Hz was the expected fundamental frequency for this sample of the E2 note.
Taking the convolution of the sample and a Hamming window before applying FFT
One traditional way to deal with this is issue is to first convolute the sample with a window function, such as the Hamming window
End of explanation
rec = array
rec = rec[15000:35000]
autocorr = np.correlate(rec, rec, mode='same')
plt.plot(autocorr)
Explanation: WIP: Using Autocorrelation method for pitch detection
End of explanation
<END_TASK>