## Tutorial for recording a guitar string stroke and detecting its pitch

I use the python library called sounddevice which allows to easily record audio and represent the result as a numpy array.

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
1 (E) 329.63 Hz E4
2 (B) 246.94 Hz B3
3 (G) 196.00 Hz G3
4 (D) 146.83 Hz D3
5 (A) 110.00 Hz A2
6 (E) 82.41 Hz E2
``````

In [79]:

import sounddevice as sd
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

%matplotlib inline

``````

#### First of all, check the list of available audio devices on the system

I use an external USB sound card called Sound Blaster E1: this is the one we will use here

``````

In [3]:

sd.query_devices()

``````
``````

Out[3]:

0 Sound Blaster E1: USB Audio (hw:0,0), ALSA (1 in, 2 out)
1 bcm2835 ALSA: - (hw:1,0), ALSA (0 in, 2 out)
2 bcm2835 ALSA: IEC958/HDMI (hw:1,1), ALSA (0 in, 2 out)
3 sysdefault, ALSA (128 in, 128 out)
4 front, ALSA (0 in, 2 out)
5 surround40, ALSA (0 in, 2 out)
6 iec958, ALSA (0 in, 2 out)
7 spdif, ALSA (1 in, 2 out)
8 dmix, ALSA (0 in, 2 out)
* 9 default, ALSA (128 in, 128 out)

``````

#### We define the length we want to record in seconds and the sampling rate to 44100 Hz

``````

In [71]:

device = 0    # we use my USB sound card device
duration = 2  # seconds
fs = 44100    # samples by second

``````

#### We can now record 2 seconds worth of audio

For this tutorial, I have played the D string of my guitar.

The result is a numpy array we store in the `myrecording` variable

``````

In [72]:

myrecording = sd.rec(duration * fs, samplerate=fs, channels=1, device=0)

``````

#### 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

``````

In [80]:

df = pd.DataFrame(myrecording)
df.loc[25000:30000].plot()

``````
``````

Out[80]:

<matplotlib.axes._subplots.AxesSubplot at 0x68bbb0f0>

``````

### Pitch detection using Fast Fourier Transform

#### We use numpy to compute the discrete Fourier transform of the signal:

``````

In [39]:

fourier = np.fft.fft(rec)

``````

We can visualise a section of the Fourier transform to notice there is a clear fundamental frequency:

``````

In [88]:

plt.plot(abs(fourier[:len(fourier)/10]))

``````
``````

Out[88]:

[<matplotlib.lines.Line2D at 0x67b60f70>]

``````

#### 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

``````

In [89]:

f_max_index = np.argmax(abs(fourier[:fourier.size/2]))
freqs = np.fft.fftfreq(len(fourier))
freqs[f_max_index]*fs

``````
``````

Out[89]:

149.94

``````

#### This methid has detected that my guitar string stroke has fundamental frequency of 149.94 Hz, which is indeed very close to the expected frequency of the D string of a well tuned guitar (target if 146.83 Hz)

My guitar was not very well tuned: this indicates I should slightly tune down my 4th string

### Using Autocorrelation method for pitch detection

``````

In [90]:

rec = myrecording.ravel()
rec = rec[25000:30000]
autocorr = np.correlate(rec, rec, mode='same')
plt.plot(autocorr)

``````
``````

Out[90]:

[<matplotlib.lines.Line2D at 0x67b43b50>]

``````
``````

In [ ]:

``````