Get the frequency of the audio file every 1/4 second in android

I have a sound file (.3gp) and its about ~ 1 min. I would like to get the frequency of this sound file every 1/4 of a second. My idea is to get samples every 1/4 of a second from an audio file, and with FFT I can get frequency values. Is there any way to do this?

Actually, I would split the audio file into 1/4sec ​​samples of the audio files (also by rewriting the previews), then using the FFT algorithm and detecting the frequency where magintude is the largest. But there may be simpler solutions, however I also do not know how to do this.

*** UPDATE 2 - new code

I am using this code so far:

public class RecordAudio extends AsyncTask<Void, double[], Void> { @Override protected Void doInBackground(Void... arg0) { try { int bufferSize = AudioRecord.getMinBufferSize(frequency, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT); //int bufferSize = AudioRecord.getMinBufferSize(frequency, // channelConfiguration, audioEncoding); AudioRecord audioRecord = new AudioRecord( MediaRecorder.AudioSource.MIC, frequency, channelConfiguration, audioEncoding, bufferSize); short[] buffer = new short[blockSize]; //double[] toTransform = new double[blockSize]; audioRecord.startRecording(); // started = true; hopes this should true before calling // following while loop while (started) { sampling++; double[] re = new double[blockSize]; double[] im = new double[blockSize]; double[] newArray = new double[blockSize*2]; double[] magns = new double[blockSize]; double MaxMagn=0; double pitch = 0; int bufferReadResult = audioRecord.read(buffer, 0, blockSize); for (int i = 0; i < blockSize && i < bufferReadResult; i++) { re[i] = (double) buffer[i] / 32768.0; // signed 16bit im[i] = 0; } newArray = FFTbase.fft(re, im,true); for (int i = 0; i < newArray.length; i+=2) { re[i/2]=newArray[i]; im[i/2]=newArray[i+1]; magns[i/2] = Math.sqrt(re[i/2]*re[i/2]+im[i/2]*im[i/2]); } // I only need the first half for (int i = 0; i < (magns.length)/2; i++) { if (magns[i]>MaxMagn) { MaxMagn = magns[i]; pitch=i; } } if (sampling > 50) { Log.i("pitch and magnitude", "" + MaxMagn + " " + pitch*15.625f); sampling=0; MaxMagn=0;pitch=0; } } audioRecord.stop(); } catch (Throwable t) { t.printStackTrace(); Log.e("AudioRecord", "Recording Failed"); } return null; } 

I use this: http://www.wikijava.org/wiki/The_Fast_Fourier_Transform_in_Java_%28part_1%29

The guitar strings sound right, but my own sound is not good because of this:

enter image description here

The magnitude of the two peaks changes most of the time, and I always find the largest to get the main frequency.

+6
source share
2 answers

Pitch tracking with FFT is set so often on Stack Overflow that I wrote a sample code entry. The code is in C, but with explanations and links you can do what you want.

As for dividing it into 1/2 second increments, you can just take the FFT of 1/4 second segments, as you suggested, instead of the default value (which, in my opinion, is about 1 second). If this does not give you frequency resolution, you may have to use a different tone recognition method. Another thing you can do is use overlapping segments longer than 1/4 second, but start at intervals divided by 1/4 second. This method is mentioned on the blog, but may not meet your design specification.

+7
source

Try AsyncTask :

 class GetFrequency extends AsyncTask<String, Void, Void> { public Void doInBackground(String... params) { while (true) { // Apply Logic Here try { Thread.sleep(250); } catch (Exception ie) { // TODO Auto-generated catch block e.printStackTrace(); } } } } 

Call it in your MainActivity,

 frequencyButtonListener.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { new GetFrequency.execute(params); } }); 
+1
source

Source: https://habr.com/ru/post/922278/


All Articles