Java – get ultrasound from Android using frequency
I want to get ultrasound from any Android device, such as ultrasound with a frequency between 18khz and 19khz
I use the following code to calculate the frequency, but it doesn't seem to get me the correct frequency My frequency remains between 11 kHz and 13 kHz
private void calculateFrequency() { // 1 - Initialize audio int channel_config = AudioFormat.CHANNEL_CONfigURATION_MONO; int format = AudioFormat.ENCODING_PCM_16BIT; int sampleRate = 8000; int bufferSize = 2048; if (bufferSize < AudioRecord.getMinBufferSize(sampleRate,channel_config,format)) bufferSize = AudioRecord.getMinBufferSize(sampleRate,format); AudioRecord audioInput = new AudioRecord(AudioSource.MIC,sampleRate,format,bufferSize); // 2 - Get sound byte[] audioBuffer = new byte[bufferSize]; audioInput.startRecording(); int nbRead = audioInput.read(audioBuffer,bufferSize); audioInput.stop(); audioInput.release(); // 3 - Transform to double array double[] micBufferData = new double[bufferSize]; final int bytesPerSample = 2; // As it is 16bit PCM final double amplification = 100.0; // choose a number as you like for (int index = 0,floatIndex = 0; index < nbRead - bytesPerSample + 1; index += bytesPerSample,floatIndex++) { double sample = 0; for (int b = 0; b < bytesPerSample; b++) { int v = audioBuffer[index + b]; if (b < bytesPerSample - 1 || bytesPerSample == 1) { v &= 0xFF; } sample += v << (b * 8); } double sample32 = amplification * (sample / 32768.0); micBufferData[floatIndex] = sample32; } // 4 - Create complex array Complex[] fftTempArray = new Complex[bufferSize]; for (int i=0; i<bufferSize; i++) { fftTempArray[i] = new Complex(micBufferData[i],0); } // 5 - Calculate FFT Complex[] fftArray = FFT.fft(fftTempArray); // 6 - Calculate magnitude double[] magnitude = new double[bufferSize / 2]; for (int i = 0; i < (bufferSize / 2); i++) { magnitude[i] = Math.sqrt(fftArray[i*2].re() * fftArray[i*2].re() + fftArray[i*2].im() * fftArray[i*2].im()); } // 7 - Get maximum magnitude double max_magnitude = -1; for (int i = 0; i < bufferSize / 2; i++) { if (magnitude[i] > max_magnitude) { max_magnitude = magnitude[i]; } } // 8 - Calculate frequency int freq = (int)(max_magnitude * sampleRate / bufferSize); ((TextView) findViewById(R.id.textView1)).setText("FREQUENCY = " + freq + "Hz"); }
I am using two mobile phones: one uses this app to send ultrasound, and the other is for ultrasound I use this question as a starting point. I use FFT and complex classes
What's wrong with my code?
Solution
In order to obtain a correct non aliasing frequency estimation, you must use more sampling rates (possibly 10% to 20% greater than the filter roll off), rather than twice the highest frequency in the audio input, so more than twice the highest frequency you want to find
This is due to the Nyquist rate required by the sampling theorem
Therefore, if you want to find a 19 kHz signal, you need a sampling rate close to 48000