C/C++/Obj-C Real-time algorithm to ascertain Note (not Pitch) from Vocal Input

后端 未结 9 707
伪装坚强ぢ
伪装坚强ぢ 2020-12-13 01:32

I want to detect not the pitch, but the pitch class of a sung note.

So, whether it is C4 or C5 is not important: they must both be detected as C.<

相关标签:
9条回答
  • 2020-12-13 01:54

    Pitch is a human psycho-perceptual phenomena. Peak frequency content is not the same as either pitch or pitch class. FFT and DFT methods will not directly provide pitch, only frequency. Neither will zero crossing measurements work well for human voice sources. Try AMDF, ASDF, autocorrelation or cepstral methods. There are also plenty of academic papers on the subject of pitch estimation.

    There is another long list of pitch estimation algorithms here.

    Edited addition: Apple's SpeakHere and aurioTouch sample apps (available from their iOS dev center) contain example source code for getting PCM sample blocks from the iPhone's mic.

    0 讨论(0)
  • 2020-12-13 01:55

    Finally I have closure on this one, thanks to this article from DSP Dimension

    The article contains source code.

    Basically he performs an FFT. then he explains that frequencies that don't coincide spot on with the centre of the bin they fall in will smear over nearby bins in a sort of bell shaped curve. and he explains how to extract the exact frequency from this data in a second pass (FFT being the first pass).

    the article then goes further to pitch shift; I can simply delete the code.

    note that they supply a commercial library that does the same thing (and far more) only super optimised. there is a free version of the library that would probably do everything I need, although since I have worked through the iOS audio subsystem, I might as well just implement it myself.

    for the record, I found an alternative way to extract the exact frequency by approximating a quadratic curve over the bin and its two neighbours here. I have no idea what is the relative accuracy between these two approaches.

    0 讨论(0)
  • 2020-12-13 01:59

    See my answer here for getting smooth FREQUENCY detection: https://stackoverflow.com/a/11042551/1457445

    As far as snapping this frequency to the nearest note -- here is a method I created for my tuner app:

    - (int) snapFreqToMIDI: (float) frequencyy {
    
        int midiNote = (12*(log10(frequencyy/referenceA)/log10(2)) + 57) + 0.5;
        return midiNote;
    }
    

    This will return the MIDI note value (http://www.phys.unsw.edu.au/jw/notes.html)

    In order to get a string from this MIDI note value:

    - (NSString*) midiToString: (int) midiNote {
        NSArray *noteStrings = [[NSArray alloc] initWithObjects:@"C", @"C#", @"D", @"D#", @"E", @"F", @"F#", @"G", @"G#", @"A", @"A#", @"B", nil];
        return [noteStrings objectAtIndex:midiNote%12];
    }
    

    For an example implementation of the pitch detection with output smoothing, look at musicianskit.com/developer.php

    0 讨论(0)
提交回复
热议问题