1

I'm new to MATLAB, and am working on a program that deals with frequency of the human voice based on microphone input. The biggest problem I am running into is that musical notes (what I am dealing with in this project) increase in frequency exponentially, about 1.059463^x for each semitone in the musical scale.
In the program I am dealing with, I need to both scale the graph so the detected frequency is close to the note number it corresponds to as well as scale the data so that I can work with the note numbers in terms of notes and musical cents so the frequency graph can be converted easily to MIDI data.
The only other option I have found has been to create a library of frequencies for the recorded frequencies to be compared to, but that is unnecessarily complicated and time consuming.
So, in essence, I am trying to scale the data so that A2, with a frequency of 110Hz, would correspond to its note number 45. Is there a way to do this?

Aaron B.
  • 13
  • 2

1 Answers1

0

I think this does what you want:

f = 110; %// frequency in Hz
n = log10(f/440)/log10(2)*12+69; %// 440 Hz (note A4) is note 69
note = round(n);
cents = round((n-note)*100);

Examples: f = 110 gives

note =
    45
cents =
     0

f = 345 gives

note =
    65
cents =
   -21

in accordance with this reference and this converter.

Luis Mendo
  • 110,752
  • 13
  • 76
  • 147
  • Thank you. Is there any way to scale an entire graph using this? For example, if using real-time microphone input, is there a way for the detected frequency to be displayed and recorded in terms of note number and cents rather than just the frequency? – Aaron B. Apr 01 '15 at 12:34
  • "_the __detected__ frequency to be __displayed__ and __recorded___". Sorry, I don't get what you mean. The recorded audio file contains audio samples representing the waveform. Detecting frequencies from that (and then displaying them) is a different matter – Luis Mendo Apr 01 '15 at 12:36
  • I have a pitch detection algorithm that I can use, but I need a way to easily convert the frequency that program detects into the MIDI note number. Essentially, if I get 4 data points f=110, f=116.541, f=123.471, and f=103.826, I would want the resulting graph to display the note number rather than the frequency, giving me the data points n=45, n=46, n=47, and n=44. – Aaron B. Apr 01 '15 at 12:43
  • Well, my answer converts those `f` into those `n` (variable `note` in my code). So what's the problem? – Luis Mendo Apr 01 '15 at 12:44
  • Can I convert an entire series of data points in a graph at once using the same method? – Aaron B. Apr 01 '15 at 12:46
  • Yep, my code is vectorized. Try it with `f=[110 116.541 123.471 103.826]` and you will get the four values `[45 46 47 44]` in variable `note`. – Luis Mendo Apr 01 '15 at 12:49
  • I'm sorry if this question seems obvious or redundant, but could I call the entire function of the frequency over time into the `f=[]` portion of the code? In pseudocode, this would look like `f=[frequency(t)]` – Aaron B. Apr 01 '15 at 12:57
  • Yes, `f` can be any vector or array of numbers. Do give it a try and see for yourself! – Luis Mendo Apr 01 '15 at 14:11