Pitch Period & Fundamental Frequency of Soundwave in MATLAB - matlab

I have just recorded a tiny section of audio in MatLab using the >> x = wavrecord( 2*fs, fs, ‘double’); command.
So far I have figured out how to playback the audio using soundsc(x, fs); and to plot to a graph using plot(x).
Here is a zoomed in screen capture of my wave:
Does the x-axis display the duration in milliseconds and the y-axis display the amplitude?
I think I may have switched off the axis names by accident.
I need to confirm this before i try to calculate the Fundamental Period and Fundamental Frequency of the wave.
If I've guessed my axis correct, am I right in thinking the fundamental period is the amount of time it takes for one periodic wave to repeat itself, making it (T)? So in this case approximately 0.0050 seconds?
And, the fundamental frequency is f0 = 1/T = 1/0.0050?
I have been playing around all day and reading so much. I hope i havent confused myself and just embarrassed myself on this site. Thanks.

Your x-axis is just sample number. This would go from 1 to the number of samples your sound recording contains. The sample time which is the time period between two samples is 1/fs. fs is your sampling frequency. So the time period for 50 samples would be 50/fs.
For most waveforms you cannot find Fundamental period easily by looking at it. As #duffymo mentions you need to compute FFT or PSD and then find the location of your first peak which is not DC. This would be your fundamental frequency.

This time trace looks pretty noise to me. It's not "frequency"; it's "frequencies".
If you do an FFT on this, you'll find that there are lots of frequencies involved. You may be able to reproduce the main signal with a smaller number of harmonics, but I doubt that it'll be just one.

Related

what is the purpose of the frequency domain analysis

I had assumed that this was going to output a set frequency buckets that I could use to do pitch detection (like aubio pitch). But that doesn't seem to be what it does. I fired up the voice-omatic app and using it frequency display played various notes through my mic. Bars appear, all at the left hand end, almost no distinction between high and low notes. I upped the FFT size just to see if that changed anything, seems not. I found a picthdetect js project and saw that it used analyzer ,aha, here I will find the correct usage, but the meat of the code doesn't use frequency domain output, it feeds time domain into its own algorithm. So to solve my problem I will use that library, but I am still curious what the freqency domain data represents
It does exactly what you think it does, but the specific implementation on that site is not great for seeing that.
The values are mapped differently than is nescessary for seeing changes in pitch between high and low vocal range because the range is mapped linearly, not logrithmically. If you were to map each frequency bin in a logarithmic way you would get a far more useful diagram. Right now the right hand 3/4 of the visualizer is showing from 5000hz to 20000hz (roughly), which contains very very little data in an audio signal compared to 0-5000hz. The root frequency of the human voice (and most instruments) occupies mostly between 100-1000hz. There are harmonics above that, but at reducing amplitudes the higher you get.
I've tweaked the code to tell you the peak frequency and the size of each bucket. Use this app.js: https://puu.sh/Izcws/ded6aae55b.js - you can use a tone generator on your phone to see how accurate it is. https://puu.sh/Izcx3/d5a9d74764.png
The way the code works is it calculates how big each bucket is as described in my answer with var bucketSize = 1 / (analyser.fftSize / analyser.context.sampleRate); (and adds two spans to show the data) and then while drawing each bar calculate which bar is the biggest, and then multiply the size of each bucket by which bucket is the biggest to get the peak frequency (and write it in el2). You can play with the fftSize and see why using a small value will not work at all for determining whether you are playing A2(110 Hz) or A2#(116.5 Hz).
From https://stackoverflow.com/a/43369065/13801789:
I believe I understand what you mean exactly. The problem is not with your code, it is with the FFT underlying getByteFrequencyData. The core problem is that musical notes are logarithmically spaced while the FFT frequency bins are linearly spaced.
Notes are logarithmically spaced: The difference between consecutive low notes, say A2(110 Hz) and A2#(116.5 Hz) is 6.5 Hz while the difference between the same 2 notes on a higher octave A3(220 Hz) and A3#(233.1 Hz) is 13.1 Hz.
FFT bins are linearly spaced: Say we're working with 44100 samples per second, the FFT takes a window of 1024 samples (a wave), and multiplies it first with a wave as long as 1024 samples (let's call it wave1), so that would be a period of 1024/44100=0.023 seconds which is 43.48 Hz, and puts the resulting amplitude in the first bin. Then it multiplies it with a wave with frequency of wave1 * 2, which is 86.95 Hz, then wave1 * 3 = 130.43 Hz. So the difference between the frequencies is linear; it's always the same = 43.48, unlike the difference in musical notes which changes.
This is why close low notes will be bundled up in the same bin while close high notes are separated. This is the problem with FFT's frequency resolution. It can be solved by taking windows bigger than 1024 samples, but that would be a trade off for the time resolution.

Suggestions for defining limits of frequencies in Matlab Spectrogram function?

I am new to Matlab and signal processing. I am having an issue with defining the frequency range in which the spectrogram is processed. When I am plotting the spectrogram of .wav audio data, the y axis, frequency, spans from zero to around 23 kHz. The useful data I am looking for is in the range of 200-400 Hz. My code snippet is:
[samFa, fs] = audioread('samFa.wav'); %convert audio to numerical data
samFa = samFa(:,1); %take only one channel of numerical output
spectrogram(samFA,2205,1200,12800, fs,'yaxis','MinThreshold',-80);
I don't want to be some noobie that runs into a problem and instantly gives up and posts a duplicate question to stackoverflow, so I have done as much digging as I can, but am at my wit's end.
I scoured the documentation for parameters or ways to have Matlab only analyze a subset or range of the data, but found nothing. Additionally, in all of the examples the frequency range seems to automatically adapt to the data set.
I know it is possible to just calculate the spectrogram for the entire range of frequencies, and then remove all of the unnecessary data through truncating or manually changing the limits in the plot itself, but changing plotting limits does not help with the numerical data.
I went searching through many similar questions, and found an answer all the way from 2012 here: Can I adjust spectogram frequency axes?
where the suggested answer was to import a vector of specific frequencies for the spectrogram to analyze. I tried passing a vector of integer values between 200 and 400, and a few other test ranges, but got the error:
Error using welchparse>welch_options (line 297)
The sampling frequency must be a scalar.
I've tried passing the parameter in at different places in the function, with no avail, and don't see anything regarding this parameter in the documentation, leading me to believe that this functionality was possibly removed sometime between 2012 and now.
When plotting spectrogram without providing signal frequency, Matlab provides a normalized spectrogram, which only provides a much smaller data window, which I can visually assess to cover the data from 0:5kHz (an artifact of overtones in the audio), so I know that matlab is not finding any data above this range to make the frequency range go to 20kHz
I've been trying to learn some signal processing for this project, so I believe the Nyquist frequency should be the maximum frequency that a Fourier transform is able to analyze, to be half the sampling frequency. My recording frequency is sampling at 44,100 Hz, and the spectrogram is ranging to around 22 or 23 kHz, leading me to believe that it's Matlab is noticing my sampling frequency and assuming that it needs to analyze up to such a high range.
For my work I am doing I am needing to produce thousands of spectrograms to then be processed through much further analysis, so it is very time consuming for Matlab to be processing so much unecessary data, and I would expect there to be some functionality in Matlab somehow to get around this.
Sorry for the very long post, but I wanted to fully explain my problem and show that I have done as much work as I could to solve the problem before turning for help. Thank you very much.
Get the axis handle and set the visual range there:
spectrogram(samFA,2205,1200,12800, fs,'yaxis','MinThreshold',-80);
ax=gca;
ylim(ax, [0.2,0.4]); %kHz
And if you want to calculate specific frequencies range to save time you better use goertzel.
f = 200:10:400;
freq_indices = round(f/fs*N) + 1;
dft_data = goertzel(data,freq_indices);

FFT in Matlab in order to find signal frequency and create a graph with peaks

I have data from an accelerometer and made a graph of acceleration(y-axis) and time (x-axis). The frequency rate of the sensor is arround 100 samples per second. but there is no equally spaced time (for example it goes from 10.046,10.047,10.163 etc) the pace is not const. And there is no function of the signal i get. I need to find the frequency of the signal and made a graph of frequency(Hz x-axis) and acceleration (y-axis). but i don't know which code of FFT suits my case. (sorry for bad english)
Any help would be greatly appreciated
For an FFT to work you will need to reconstruct the signal you have with with a regular interval. There are two ways you can do this:
Interpolate the data you already have to make an accurate guess at where the signal would be at a regular interval. However, this FFT may contain significant inaccuracies.
OR
Adjust the device reading from the accelerometer incorporate an accurate timer such that results are always transmitted at regular intervals. This is what I would recommend.

Signal processing using MATLAB

I'm trying to do some signal processing using an audio file (piano recordings)
I find the note onsets and then perform FFT on each onset. However I find that for certain notes their 2nd harmonic has a way greater amplitude than he fundamental... Why is that???
How can I eliminate this and get the correct frequency??
Start by using a low-pass filter to trim out some of the higher-order harmonics. If the piano recordings that you are trying to process were recorded within a 3 octave range, that should help substantially.
Next, try adjusting your wave amplitude. Here's an article that discusses how harmonic distortion degrades a signal, and how you can exchange signal-to-noise ratio for harmonic distortion.
http://www.mathworks.com/help/signal/examples/analyzing-harmonic-distortion.html
If you want more of a home-built solution without signal filtering, here's what I'd try, assuming that the maximum signal amplitude corresponds either to the fundamental, 2nd harmonic, or 3rd harmonic
1) Find the frequency f of the maximum signal
2) If the signal at f/2 or f/3 is much greater than the noise floor, call that frequency your fundamental
Alternatively,
1) Find the frequency f of the maximum signal
2) Search above in the interval [f/2, 2*f] and find the peak nearest f.
3) Assume the difference between f and the nearest peak is 1 the fundamental frequency.
You'll need to adapt these methods to your data.
Make sure your data doesn't exhibit only odd order harmonics or has very strong high-order harmonics. These methods won't work well if multiple notes are played simultaneously.
You could also try correcting your data for human ear sensitivity, as that may be the reason why the 2nd harmonics are louder on an FFT than what the ear detects relative to the fundamental. See http://en.wikipedia.org/wiki/Absolute_threshold_of_hearing

How to determine the frequency of the input recorded voice in iphone?

I am new to iphone development.I am doing research on voice recording in iphone .I have downloaded the "speak here " sample program from Apple.I want to determine the frequency of my voice that is recorded in iphone.Please guide me .Please help me out.Thanks.
In the context of processing human speech, there's really no such thing as "the" frequency.
The signal will be a mix of many different frequencies, so it might be more fruitful to think in terms of a spectrum, rather than a single frequency. Even if you're talking about
a sustained musical note with a fixed pitch, there will be plenty of overtones and harmonics present, in addition to the fundamental frequency of the note. And for actual speech,
the frequency spectrum will change drastically even within a short clip, due to the different tonal characteristics of vowels and consonants.
With that said, it does make some sense to consider the peak frequency of a voice recording.
You could calculate the Fast Fourier Transform of your voice clip, then find the frequency
bin with the largest response. You may also be interested in the concept of a spectrogram, which represents how the audio spectrum of a signal varies over time.
Use Audacity. Take a small recording of typical speech, and cut it down to one wavelength, from one peak to another peak. Subtract the two times, and divide 1 by that number and you'll get the frequency of your wave in Hz.
Example:
In my audio clip, my waveform runs from 0.0760 to 0.0803 seconds.
0.0803-0.0760 = 0.0043
1/0.0043 = 232.558 Hz, my typical speech frequency
This might give you a good basis to create an analyzer. You'd need to detect the peaks, and time between the peaks of the wave and do an average calculation of the result.
You'll need to use Apple's Accelerate framework to take an FFT of the relevant audio. The FFT will convert the audio in the time domain to the frequency domain. The Accelerate framework supports the FFT and will allow you to do frequency analysis in real-time.