I have been implementing a Polyphonic signal pitch detector so I started to code my Program doing (RecordData, Convert Data, Zero-padding, Windowing, FFT, Peak detection). At first I tested it with sounds I already new which values I should get, and it worked perfectly.
The problem I have is when recording with my Phone using the Audiorecord class.
For example: I played and recorded two or three pure tones with my phone and the values I get with the Audiorecord class were not correct. Getting wrong data from my phone does not let me do a good analysis.
Here is my code to Record Data(Short) and Convert Data Short to Double (This step is where i think its the problem)
Here is my code:
void recordAudio() {
mShouldContinue= true;
new Thread(new Runnable() {
@Override
public void run() {
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_AUDIO);
// buffer size in short
bufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioEncoding); //Consigue el minimo tamaño de buffer para poder analizar
if (bufferSize == AudioRecord.ERROR || bufferSize == AudioRecord.ERROR_BAD_VALUE) {
bufferSize = sampleRate * 2; // si el buffersize obtenido por nuestro getMinBufferSize es apto usaremos el encontrado si no utilizaremos el doble de nuestra frecuencia de sampleo
}
short[] audioBuffer = new short[bufferSize];
if (audioBuffer.length % 2 == 0){ // Aseguramos que nuestro buffer input tenga una tamaño impar para una mejor R.F.
audioBuffer = new short[bufferSize +1];
}
AudioRecord record = new AudioRecord(audioSource, sampleRate, channelConfig, audioEncoding, bufferSize); //Instancia de la clase AudioRecord
if (record.getState() != AudioRecord.STATE_INITIALIZED) { // Si audiorecord no ha sido inicializado displeamos un mensaje advirtiendo.
Log.e(LOG_TAG, "Audio Record can't initialize!");
return;
}
record.startRecording(); //Empezamos a grabar con nuestros parámetros ya definidos.
Log.v(LOG_TAG, "Start recording"); //mensaje informativo
long shortsRead = 0;
while (mShouldContinue) {
int numberOfShort = record.read(audioBuffer, 0, audioBuffer.length); //audiobuffer.length
shortsRead += numberOfShort;
DFT(audioBuffer);
try { // Dormimos el programa durante un segundo
Thread.sleep(1000);
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
record.stop();
record.release();
Log.v(LOG_TAG, String.format("Recording stopped. Samples read: %d", shortsRead));
}
}).start();
}
Convertion where Inputsignal is audiobuffer and N it's length (Inside DFT Function):
for(int i = 0; i < N; i++){
doubley[i] = (double)(InputSignal[i])/32768.0;
}
An FFT magnitude peak detector is not a reliable musical pitch (frequency/note) estimator. It will often find harmonic frequencies instead for some timbres.
Instead, look up some pitch detection/estimation methods (weighted autocorrelation, AMDF, HPS, cepstral, decision, CDNN, etc.), and try one of those, instead of (mis)using a spectral frequency estimator.