# pitch

Estimate fundamental frequency of audio signal

## Description

specifies options using one or more name-value arguments.`f0`

= pitch(`audioIn`

,`fs`

,`Name=Value`

)

`pitch(___)`

with no output arguments plots the
estimated pitch against time.

## Examples

### Estimate Pitch

Read in an audio signal. Call `pitch`

to estimate the fundamental frequency over time.

```
[audioIn,fs] = audioread("Hey-16-mono-6secs.ogg");
f0 = pitch(audioIn,fs);
```

Listen to the audio signal and plot the signal and pitch. The `pitch`

function estimates the fundamental frequency over time, but the estimate is only valid for regions that are harmonic.

sound(audioIn,fs) tiledlayout(2,1) nexttile t = (0:length(audioIn)-1)/fs; plot(t,audioIn) xlabel("Time (s)") ylabel("Amplitude") grid minor axis tight nexttile pitch(audioIn,fs)

### Estimate Pitch For Singing Voice

Read in an audio signal and extract the pitch.

[x,fs] = audioread("SingingAMajor-16-mono-18secs.ogg"); t = (0:size(x,1)-1)/fs; winLength = round(0.05*fs); overlapLength = round(0.045*fs); [f0,idx] = pitch(x,fs,Method="SRH",WindowLength=winLength,OverlapLength=overlapLength); tf0 = idx/fs;

Listen to the audio and plot the audio and pitch estimations.

sound(x,fs) figure tiledlayout(2,1) nexttile plot(t,x) ylabel("Amplitude") title("Audio Signal") axis tight nexttile pitch(x,fs,Method="SRH",WindowLength=winLength,OverlapLength=overlapLength) title("Pitch Estimations")

The `pitch`

function estimates the pitch for overlapped analysis windows. The pitch estimates are only valid if the analysis window has a harmonic component. Call the `harmonicRatio`

function using the same window and overlap length used for pitch detection. Plot the audio, pitch, and harmonic ratio.

hr = harmonicRatio(x,fs,Window=hamming(winLength,"periodic"),OverlapLength=overlapLength); figure tiledlayout(3,1) nexttile plot(t,x) ylabel("Amplitude") title("Audio Signal") axis tight nexttile pitch(x,fs,Method="SRH",WindowLength=winLength,OverlapLength=overlapLength) title("Pitch Estimations") xlabel("") nexttile harmonicRatio(x,fs,Window=hamming(winLength,"periodic"),OverlapLength=overlapLength) title("Harmonic Ratio")

Use the harmonic ratio as the threshold for valid pitch decisions. If the harmonic ratio is less than the threshold, set the pitch decision to `NaN`

. Plot the results.

threshold = 0.9; f0(hr < threshold) = nan; figure plot(tf0,f0) xlabel("Time (s)") ylabel("Pitch (Hz)") title("Pitch Estimations") grid on

### Compare Pitch of Two Voices

Read in an audio signal of a female voice saying "volume up" five times. Listen to the audio.

```
[femaleVoice,fs] = audioread("FemaleVolumeUp-16-mono-11secs.ogg");
sound(femaleVoice,fs)
```

Read in an audio signal of a male voice saying "volume up" five times. Listen to the audio.

```
maleVoice = audioread("MaleVolumeUp-16-mono-6secs.ogg");
sound(maleVoice,fs)
```

Extract the pitch from both the female and male recordings. Plot histograms of the pitch estimations for the male and female audio recordings. The histograms have a similar shape. This is because the pitch decisions contain results for unvoiced speech and regions of silence.

f0Female = pitch(femaleVoice,fs); f0Male = pitch(maleVoice,fs); figure numBins = 20; histogram(f0Female,numBins,Normalization="probability"); hold on histogram(f0Male,numBins,Normalization="probability"); legend("Female Voice","Male Voice") xlabel("Pitch (Hz)") ylabel("Probability") hold off

Use the `detectSpeech`

function to isolate regions of speech in the audio signal and then extract pitch from only those speech regions.

speechIndices = detectSpeech(femaleVoice,fs); f0Female = []; for ii = 1:size(speechIndices,1) speechSegment = femaleVoice(speechIndices(ii,1):speechIndices(ii,2)); f0Female = [f0Female;pitch(speechSegment,fs)]; end speechIndices = detectSpeech(maleVoice,fs); f0Male = []; for ii = 1:size(speechIndices,1) speechSegment = maleVoice(speechIndices(ii,1):speechIndices(ii,2)); f0Male = [f0Male;pitch(speechSegment,fs)]; end

Plot histograms of the pitch estimations for the male and female audio recordings. The pitch distributions now appear as expected.

figure histogram(f0Female,numBins,Normalization="probability"); hold on histogram(f0Male,numBins,Normalization="probability"); legend("Female Voice","Male Voice") xlabel("Pitch (Hz)") ylabel("Probability")

### Estimate Pitch of Musical Signal Using Nondefault Parameters

Load an audio file of the Für Elise introduction and the sample rate of the audio.

load FurElise.mat song fs sound(song,fs)

Call the `pitch`

function using the pitch estimate filter (`PEF`

), a search range of 50 to 800 Hz, a window duration of 80 ms, an overlap duration of 70 ms, and a median filter length of 10.

method = "PEF"; range = [50, 800]; % hertz winDur = 0.08; % seconds overlapDur = 0.07; % seconds medFiltLength = 10; % frames winLength = round(winDur*fs); overlapLength = round(overlapDur*fs); [f0,loc] = pitch(song,fs, ... Method=method, ... Range=range, ... WindowLength=winLength, ... OverlapLength=overlapLength, ... MedianFilterLength=medFiltLength);

Plot the estimated pitch against time.

pitch(song,fs, ... Method=method, ... Range=range, ... WindowLength=winLength, ... OverlapLength=overlapLength, ... MedianFilterLength=medFiltLength);

### Determine Pitch Contour of Streaming Audio

Create a `dsp.AudioFileReader`

object to read in audio frame-by-frame.

`fileReader = dsp.AudioFileReader("SingingAMajor-16-mono-18secs.ogg");`

Create a `voiceActivityDetector`

object to detect the presence of voice in streaming audio.

VAD = voiceActivityDetector;

While there are unread samples, read from the file and determine the probability that the frame contains voice activity. If the frame contains voice activity, call `pitch`

to estimate the fundamental frequency of the audio frame. If the frame does not contain voice activity, declare the fundamental frequency as `NaN`

.

f0 = []; while ~isDone(fileReader) x = fileReader(); if VAD(x) > 0.99 decision = pitch(x,fileReader.SampleRate, ... WindowLength=size(x,1), ... OverlapLength=0, ... Range=[200,340]); else decision = NaN; end f0 = [f0;decision]; end

Plot the detected pitch contour over time.

t = linspace(0,(length(f0)*fileReader.SamplesPerFrame)/fileReader.SampleRate,length(f0)); plot(t,f0) ylabel("Fundamental Frequency (Hz)") xlabel("Time (s)") grid on

### Compare Pitch Detection Algorithms

The different methods of estimating pitch provide trade-offs in terms of noise robustness, accuracy, optimal lag, and computation expense. In this example, you compare the performance of different pitch detection algorithms in terms of gross pitch error (GPE) and computation time under different noise conditions.

**Prepare Test Signals**

Load an audio file and determine the number of samples it has. Also load the true pitch corresponding to the audio file. The true pitch was determined as an average of several third-party algorithms on the clean speech file.

[audioIn,fs] = audioread('Counting-16-44p1-mono-15secs.wav'); numSamples = size(audioIn,1); load TruePitch.mat truePitch

Create test signals by adding noise to the audio signal at given SNRs. The `mixSNR`

function is a convenience function local to this example, which takes a signal, noise, and requested SNR and returns a noisy signal at the request SNR.

testSignals = zeros(numSamples,4); turbine = audioread('Turbine-16-44p1-mono-22secs.wav'); testSignals(:,1) = mixSNR(audioIn,turbine,20); testSignals(:,2) = mixSNR(audioIn,turbine,0); whiteNoiseMaker = dsp.ColoredNoise('Color','white','SamplesPerFrame',size(audioIn,1)); testSignals(:,3) = mixSNR(audioIn,whiteNoiseMaker(),20); testSignals(:,4) = mixSNR(audioIn,whiteNoiseMaker(),0);

Save the noise conditions and algorithm names as cell arrays for labeling and indexing.

noiseConditions = {'Turbine (20 dB)','Turbine (0 dB)','WhiteNoise (20 dB)','WhiteNoise (0 dB)'}; algorithms = {'NCF','PEF','CEP','LHS','SRH'};

**Run Pitch Detection Algorithms**

Preallocate arrays to hold pitch decisions for each algorithm and noise condition pair, and the timing information. In a loop, call the `pitch`

function on each combination of algorithm and noise condition. Each algorithm has an optimal window length associated with it. In this example, for simplicity, you use the default window length for all algorithms. Use a 3-element median filter to smooth the pitch decisions.

f0 = zeros(numel(truePitch),numel(algorithms),numel(noiseConditions)); algorithmTimer = zeros(numel(noiseConditions),numel(algorithms)); for k = 1:numel(noiseConditions) x = testSignals(:,k); for i = 1:numel(algorithms) tic f0temp = pitch(x,fs, ... 'Range',[50 300], ... 'Method',algorithms{i}, ... 'MedianFilterLength',3); algorithmTimer(k,i) = toc; f0(1:max(numel(f0temp),numel(truePitch)),i,k) = f0temp; end end

**Compare Gross Pitch Error**

Gross pitch error (GPE) is a popular metric when comparing pitch detection algorithms. GPE is defined as the proportion of pitch decisions for which the relative error is higher than a given threshold, traditionally 20% in speech studies. Calculate the GPE and print it to the Command Window.

idxToCompare = ~isnan(truePitch); truePitch = truePitch(idxToCompare); f0 = f0(idxToCompare,:,:); p = 0.20; GPE = mean( abs(f0(1:numel(truePitch),:,:) - truePitch) > truePitch.*p).*100; for ik = 1:numel(noiseConditions) fprintf('\nGPE (p = %0.2f), Noise = %s.\n',p,noiseConditions{ik}); for i = 1:size(GPE,2) fprintf('- %s : %0.1f %%\n',algorithms{i},GPE(1,i,ik)) end end

GPE (p = 0.20), Noise = Turbine (20 dB).

- NCF : 0.9 % - PEF : 0.4 % - CEP : 8.2 % - LHS : 8.2 % - SRH : 6.0 %

GPE (p = 0.20), Noise = Turbine (0 dB).

- NCF : 5.6 % - PEF : 24.5 % - CEP : 11.6 % - LHS : 9.4 % - SRH : 46.8 %

GPE (p = 0.20), Noise = WhiteNoise (20 dB).

- NCF : 0.9 % - PEF : 0.0 % - CEP : 12.9 % - LHS : 6.9 % - SRH : 2.6 %

GPE (p = 0.20), Noise = WhiteNoise (0 dB).

- NCF : 0.4 % - PEF : 0.0 % - CEP : 23.6 % - LHS : 7.3 % - SRH : 1.7 %

Calculate the average time it takes to process one second of data for each of the algorithms and print the results.

aT = sum(algorithmTimer)./((numSamples/fs)*numel(noiseConditions)); for ik = 1:numel(algorithms) fprintf('- %s : %0.3f (s)\n',algorithms{ik},aT(ik)) end

- NCF : 0.016 (s) - PEF : 0.047 (s) - CEP : 0.015 (s) - LHS : 0.022 (s) - SRH : 0.047 (s)

## Input Arguments

`audioIn`

— Audio input signal

vector | matrix

Audio input signal, specified as a vector or matrix. The columns of the matrix are treated as individual audio channels.

**Data Types: **`single`

| `double`

`fs`

— Sample rate (Hz)

positive scalar

Sample rate of the input signal in Hz, specified as a positive scalar.

The sample rate must be greater than or equal to twice the upper bound of
the search range. Specify the search range using the
`Range`

name-value pair.

**Data Types: **`single`

| `double`

### Name-Value Arguments

Specify optional pairs of arguments as
`Name1=Value1,...,NameN=ValueN`

, where `Name`

is
the argument name and `Value`

is the corresponding value.
Name-value arguments must appear after other arguments, but the order of the
pairs does not matter.

*
Before R2021a, use commas to separate each name and value, and enclose*
`Name`

*in quotes.*

**Example: **`pitch(audioIn,fs,Range=[50,150],Method="PEF")`

`Range`

— Search range for pitch estimates

`[50,400]`

(default) | two-element row vector with increasing positive integer
values

Search range for pitch estimates, specified as a two-element row
vector with increasing positive integer values. The function searches
for a best estimate of the fundamental frequency within the upper and
lower band edges specified by the vector, according to the algorithm
specified by `Method`

. The range is inclusive and
units are in Hz.

Valid values for the search range depend on the sample rate,
`fs`

, and on the values of
`WindowLength`

and
`Method`

:

Method | Minimum Range | Maximum Range |
---|---|---|

"`NCF` " |
| ```
Range(2) <
``` |

"`PEF` " | `10 < Range(1)` | ```
Range(2) <
min(4000,
``` |

"`CEP` " |
| ```
Range(2) <
``` |

"`LHS` " | `1 < Range(1)` | `Range(2) < ` |

"`SRH` " | `1 < Range(1)` | `Range(2) < ` |

**Data Types: **`single`

| `double`

`WindowLength`

— Number of samples in analysis window

`round(``fs`

*0.052)

(default) | integer

`fs`

*0.052)Number of samples in the analysis window, specified as an integer in
the range [1, min(size(`audioIn`

,1), 192000)].
Typical analysis windows are in the range 20–100 ms. The default window
length is 52 ms.

**Data Types: **`single`

| `double`

`OverlapLength`

— Number of samples of overlap between adjacent analysis windows

`round(``fs`

*0.042)

(default) | integer

`fs`

*0.042)Number of samples of overlap between adjacent analysis windows,
specified as an integer in the range
(`-inf`

,`WindowLength`

). A
negative overlap length indicates non-overlapping analysis
windows.

**Data Types: **`single`

| `double`

`Method`

— Method used to estimate pitch

`"NCF"`

(default) | `"PEF"`

| `"CEP"`

| `"LHS"`

| `"SRH"`

Method used to estimate pitch, specified as `"NCF"`

,
`"PEF"`

,`"CEP"`

,
`"LHS"`

, or `"SRH"`

. The different
methods of calculating pitch provide trade-offs in terms of noise
robustness, accuracy, and computation expense. The algorithms used to
calculate pitch are based on the following papers:

**Data Types: **`char`

| `string`

`MedianFilterLength`

— Median filter length used to smooth pitch estimates over time

`1`

(default) | positive integer

Median filter length used to smooth pitch estimates over time,
specified as a positive integer. The default, `1`

,
corresponds to no median filtering. Median filtering is a postprocessing
technique used to remove outliers while estimating pitch. The function
uses `movmedian`

after
estimating the pitch using the specified
`Method`

.

**Data Types: **`single`

| `double`

## Output Arguments

`f0`

— Estimated fundamental frequency (Hz)

scalar | vector | matrix

Estimated fundamental frequency, in Hz, returned as a scalar, vector, or
matrix. The number of rows returned depends on the values of the
`WindowLength`

and `OverlapLength`

name-value pairs, and on the input signal size. The number of columns
(channels) returned depends on the number of columns of the input signal
size.

**Data Types: **`single`

| `double`

`loc`

— Locations associated with fundamental frequency estimations

scalar | vector | matrix

Locations associated with fundamental frequency estimations, returned as a
scalar, vector, or matrix the same size as `f0`

.

Fundamental frequency is estimated locally over a region of
`WindowLength`

samples. The values of
`loc`

correspond to the most recent sample (largest
sample number) used to estimate fundamental frequency.

**Data Types: **`single`

| `double`

## Algorithms

The `pitch`

function segments the audio input according to the
`WindowLength`

and `OverlapLength`

arguments.
The fundamental frequency is estimated for each frame. The locations output,
`loc`

contains the most recent samples (largest sample numbers)
of the corresponding frame.

For a description of the algorithms used to estimate the fundamental frequency, consult the corresponding references:

## References

[1] Atal, B.S. "Automatic Speaker
Recognition Based on Pitch Contours." *The Journal of the Acoustical Society
of America*. Vol. 52, No. 6B, 1972, pp. 1687–1697.

[2] Gonzalez, Sira, and Mike Brookes. "A Pitch Estimation Filter robust to high levels of noise (PEFAC)." 19th European Signal Processing Conference. Barcelona, 2011, pp. 451–455.

[3] Noll, Michael A. "Cepstrum
Pitch Determination." *The Journal of the Acoustical Society of
America*. Vol. 31, No. 2, 1967, pp. 293–309.

[4] Hermes, Dik J. "Measurement of
Pitch by Subharmonic Summation." *The Journal of the Acoustical Society of
America*. Vol. 83, No. 1, 1988, pp. 257–264.

[5] Drugman, Thomas, and Abeer Alwan. "Joint Robust Voicing Detection and Pitch Estimation Based on Residual Harmonics." Proceedings of the Annual Conference of the International Speech Communication Association, INTERSPEECH. 2011, pp. 1973–1976.

## Extended Capabilities

### C/C++ Code Generation

Generate C and C++ code using MATLAB® Coder™.

### GPU Arrays

Accelerate code by running on a graphics processing unit (GPU) using Parallel Computing Toolbox™.

This function fully supports GPU arrays. For more information, see Run MATLAB Functions on a GPU (Parallel Computing Toolbox).

## Version History

**Introduced in R2018a**

## Open Example

You have a modified version of this example. Do you want to open this example with your edits?

## MATLAB Command

You clicked a link that corresponds to this MATLAB command:

Run the command by entering it in the MATLAB Command Window. Web browsers do not support MATLAB commands.

Select a Web Site

Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .

You can also select a web site from the following list:

## How to Get Best Site Performance

Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.

### Americas

- América Latina (Español)
- Canada (English)
- United States (English)

### Europe

- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)

- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)