Reputation: 361
So I created a MATLAB program to detect the frequencies present in a piano recording. Now I need to convert these detected frequencies to their corresponding piano note.
I know there's a theory about using A4 (440Hz) as the reference note and deriving the rest based on that. But I'm looking for something like a look up table, where I can directly call the respective piano notes by looking at the look up table. I'm not quite sure how to go on about it though and so would like some suggestions on what I could do... Thanx
Upvotes: 2
Views: 1633
Reputation: 390
You don't need a lookup table neither do you have to limit yourself to a specific range: (Javascript)
function getNoteFromFrequency(frequency) {
var noteOrder = 'G# A A# B C C# D D# E F F# G'.split(" ");
var n = Math.round(49 + 12 * Math.log(frequency / 440) / Math.log(2));
var note = noteOrder[n % noteOrder.length];
var index = Math.ceil((n - 3) / noteOrder.length);
return note + index;
}
Upvotes: 0
Reputation: 38032
From here (just the first Google hit, nothing special), you can see that all the frequencies of all notes in the equal-tempered scale are related through
f = f0 · 2^(i/12)
with f0 = A4 = 440
Hz, and i
the number of half-steps away from the base note. This allows you to make a lookup table (LUT
) for all the notes.
The only thing you need to put a bit of work in are:
Today's your lucky day (I'm bored and procrastinating :), so here's a fairly complete implementation, for notes from C0 to E8♭:
% Your frequencies (can be of any size, must be in Hz)
V = [17 450 4000];
% Generate the lookup table
LUT = 440 * (2^(1/12)).^(-57:42);
% The names of all those notes
noteNames = {...
'AN' 'AN♯/BN♭' 'BN' 'CN' 'CN♯/DN♭' 'DN' 'DN♯/EN♭' 'EN' 'FN' 'FN♯/GN♭' 'GN' 'GN♯/AN♭'};
allNotes = [];
for ii = 0:8
allNotes = [allNotes regexprep(noteNames, 'N', num2str(ii))]; end %#ok<AGROW>
allNotes = allNotes(4:end-4);
% Indices into the lookup table
[~,I] = min(abs(bsxfun(@minus, V(:), LUT)), [], 2);
% The named noted corresponding to your frequencies
allNotes(I)
Upvotes: 5