DSP tutorial: Calculating FFT of a live source
Last modified: November 16th, 2011This example records audio and periodically prints the dominant frequency of the recorded audio signal.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | public class AudioRecordFFT implements Runnable { private final static int SAMPLERATE = 8000; private final static int BUFFERSIZE = SAMPLERATE / 2; private TargetDataLine tdl; private DoubleFFT_1D fft; AudioRecordFFT(TargetDataLine tdl) { this.tdl = tdl; } private void calculateFFT(final double[] audioData, final int storedSamples) { // we need to initialize a buffer where we store our samples as complex numbers. first value is the real part, second is the imaginary. double[] fftData = new double[audioData.length*2]; for (int i = 0; i < storedSamples; i++) { // copying audio data to the fft data buffer, imaginary part is 0 fftData[2 * i] = audioData[i]; fftData[2 * i + 1] = 0; } // calculating the fft of the data, so we will have spectral power of each frequency component fft.complexForward(fftData); int max_i = -1; double max_fftval = -1; for (int i = 0; i < fftData.length/2; i += 2) { // we are only looking at the half of the spectrum // complex numbers -> vectors, so we compute the length of the vector, which is sqrt(realpart^2+imaginarypart^2) double vlen = Math.sqrt(fftData[i] * fftData[i] + fftData[i + 1] * fftData[i + 1]); if (max_fftval < vlen && vlen > 0.1) { // if this length is bigger than our stored biggest length max_fftval = vlen; max_i = i; } } if (max_i < 0) max_fftval = max_i = 0; double dominantFreq = ((max_i) / (double)fftData.length) * SAMPLERATE; System.out.println("Dominant frequency: " + dominantFreq + "hz (bin no. " + max_i + ")"); } @Override public void run() { byte[] abBuffer = new byte[tdl.getBufferSize()]; double[] abBufferDouble = new double[abBuffer.length/2]; fft = new DoubleFFT_1D(abBufferDouble.length); tdl.start(); try { while (!Thread.interrupted()) { // waiting for the buffer to get filled while (tdl.available() < tdl.getBufferSize() * 0.5) Thread.sleep(0, 1); // without this, the audio will be choppy int bytesRead = tdl.read(abBuffer, 0, tdl.available()); // converting frames stored as bytes to double values int samplesRead = bytesRead/tdl.getFormat().getFrameSize(); for (int i = 0; i < samplesRead; i++) abBufferDouble[i] = ((abBuffer[i*2] & 0xFF) | (abBuffer[i*2 + 1] << 8)) / 32768.0; calculateFFT(abBufferDouble, samplesRead); } } catch (InterruptedException e) { } tdl.stop(); tdl.close(); } public static void main(String[] args) { AudioFormat audioFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, SAMPLERATE, 16, 1, 2, SAMPLERATE, false); DataLine.Info info = new DataLine.Info(TargetDataLine.class, audioFormat, BUFFERSIZE); TargetDataLine targetDataLine = null; try { targetDataLine = (TargetDataLine) AudioSystem.getLine(info); targetDataLine.open(audioFormat, BUFFERSIZE); System.out.println("Buffer size: " + targetDataLine.getBufferSize()); } catch (LineUnavailableException e1) { e1.printStackTrace(); } // creating the recorder thread from this class' instance AudioRecordFFT audioRecordFFT = new AudioRecordFFT(targetDataLine); Thread audioRecorderThread = new Thread(audioRecordFFT); // we use this to read line from the standard input BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); audioRecorderThread.setPriority(Thread.MAX_PRIORITY); audioRecorderThread.start(); System.out.println("Recording... press ENTER to stop recording!"); try { br.readLine(); } catch (IOException e) { e.printStackTrace(); } audioRecorderThread.interrupt(); try { // waiting for the recorder thread to stop audioRecorderThread.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Recording stopped."); } } |
download (849.2 kb)
About me
I'm Nonoo. This is my blog about music, sounds, filmmaking, amateur radio, computers, programming, electronics and other things I'm obsessed with.
... »
Trackback URL
No comments yet.
Trackback responses to this post