Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 5 of 5
  1. #1
    New to the CF scene
    Join Date
    Oct 2008
    Posts
    2
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Question Improving Java Frequency Analysis

    I am trying to make a program that tells me what pitch I am singing when I use a microphone input. The problem is, it runs very slowly. Do you know any tips I could use to speed it up?

    I think it may be faster if I directly analyzed the sound to determine pitch. Currently I create a wave file and analyze that. How would I do it directly? Thanks so much!


    Code:
       import javax.swing.*;
       import java.awt.*;
       import java.awt.event.*;
       import java.io.*;
       import javax.sound.sampled.*;
    
    
    
        public class Frequency4 {
       
          private static final int EXTERNAL_BUFFER_SIZE = 1280000; // Space to store Sound
       
           public void record()
          {
             byte[] voiceData = new byte[800];// Run time and accuracy appear to be dependent on this
    			
    														// 250: completes 20 samples in 8.95 seconds
                    									// 300: completes 20 samples in 9.40 seconds
             try
             {
                            
                AudioFormat linearFormat = new AudioFormat(1200,8,2,true,false);
                            
                DataLine.Info info = new DataLine.Info(TargetDataLine.class,linearFormat);
                TargetDataLine targetDataLine = (TargetDataLine)AudioSystem.getLine(info);
                            
                targetDataLine.open(linearFormat);
                            
                targetDataLine.start();
                            
                AudioInputStream linearStream = new AudioInputStream(targetDataLine);
                            
                linearStream.read(voiceData,0,voiceData.length);
                            
                targetDataLine.stop();
                            
                targetDataLine.close();
                            
                File audioFile = new File("sample.wav");
                ByteArrayInputStream baiStream = new ByteArrayInputStream(voiceData);
                AudioInputStream aiStream = new AudioInputStream(baiStream,linearFormat,voiceData.length);
                AudioSystem.write(aiStream,AudioFileFormat.Type.WAVE,audioFile);
                aiStream.close();
                baiStream.close();
                            
             }
                 catch(Exception e)
                {
                   e.printStackTrace();
                }
          }
        
           public static String returnNote(double highfrequency)
          {
             for (int L = 4; L >= 0; L--) // Translates frequency into a note
             {
        			double P = Math.pow(2,L);        
    				if (highfrequency > 95.25 * P) // Powers of 2 are equal to harmonic series
                   return "G";
                else if (highfrequency > 89.905 * P)
                   return "F#";
                else if (highfrequency > 84.86 * P)
                   return "F";
                else if (highfrequency > 80.1 * P)
                   return "E";
                else if (highfrequency > 75.6 * P)
                   return "D#";
                else if (highfrequency > 71.5 * P)
                   return "D";
                else if (highfrequency > 67.355 * P)
                   return "C#";
                else if (highfrequency > 63.56 * P)
                   return "C";	
                else if (highfrequency > 60 * P)
                   return "B";
                else if (highfrequency > 56.635 * P)
                   return "A#";
                else if (highfrequency > 53.45 * P)
                   return "A";
                else if (highfrequency > 50.44 * P)
                   return "G#";																	
             }
             return "Error";
          }
       
       			 
           public Frequency4() 
          {
             record();
             File soundFile = new File("sample.wav"); // Sound file that's analyzed
             AudioInputStream audioInputStream = null;
             try {
                audioInputStream = AudioSystem.getAudioInputStream(soundFile); //Load the Audio Input Stream from the file 
             } 
                 catch (Exception e) {
                   e.printStackTrace();
                   System.exit(1);
                }
             AudioFormat audioFormat = audioInputStream.getFormat(); //Get Audio Format information
             SourceDataLine	line = null; //Handle opening the line
             DataLine.Info	info = new DataLine.Info(SourceDataLine.class, audioFormat);
             try {
                line = (SourceDataLine) AudioSystem.getLine(info);
                line.open(audioFormat);
             } 
                 catch (LineUnavailableException e) {
                   e.printStackTrace();
                   System.exit(1);
                } 
                 catch (Exception e) {
                   e.printStackTrace();
                   System.exit(1);
                }
             //line.start(); //Start playing the sound (doesn't need to play)
             int nBytesRead = 0; //Write the sound to an array of bytes
             byte[]	abData = new byte[EXTERNAL_BUFFER_SIZE];
             while (nBytesRead != -1) 
             {
                try {
                   nBytesRead = audioInputStream.read(abData, 0, abData.length);
                } 
                    catch (IOException e) {
                      e.printStackTrace();
                   }
                if (nBytesRead >= 0) {
                   int nBytesWritten = line.write(abData, 0, nBytesRead);
                }
             }
             line.drain(); //close the line
             line.close();
          	
             float sample_rate = audioFormat.getSampleRate(); //Calculate the sample rate
             //System.out.println("sample rate = "+sample_rate);
             float T = audioInputStream.getFrameLength() / audioFormat.getFrameRate(); //Calculate the length in seconds of the sample
             //System.out.println("T = "+T+ " (length of sampled sound in seconds)");
             int n = (int) (T * sample_rate) / 2; //Calculate the number of equidistant points in time
             //System.out.println("n = "+n+" (number of equidistant points)"); 
             float h = (T / n); //Calculate the time interval at each equidistant point
             //System.out.println("h = "+h+" (length of each time interval in seconds)");
          
          	
             boolean isBigEndian = audioFormat.isBigEndian(); //Determine the original Endian encoding format
             int x[] = new int[n]; //this array is the value of the signal at time i*h
             for (int i = 0; i < n*2; i+=2) //convert each pair of byte values from the byte array to an Endian value
             {
                int b1 = abData[i];
                int b2 = abData[i + 1];
                if (b1 < 0) b1 += 0x100;
                if (b2 < 0) b2 += 0x100;
                int value;
                if (!isBigEndian) value = (b1 << 8) + b2; //Store the data based on the original Endian encoding format
                else value = b1 + (b2 << 8);
                x[i/2] = value;
             }
          	
             double f[] = new double[n/2]; //do the DFT for each value of x sub j and store as f sub j
             double highfrequency = 0; // Will store frequency at highest amplitude
             double highamplitude = 0; // Will store highest amplitude
             for (int j = 0; j < n/2; j++) 
             {
                double firstSummation = 0;
                double secondSummation = 0;
                for (int k = 0; k < n; k++)
                {
                   double twoPInjk = ((2 * Math.PI) / n) * (j * k); // Whole bunch of complicated math
                   firstSummation +=  x[k] * Math.cos(twoPInjk);
                   secondSummation += x[k] * Math.sin(twoPInjk);
                }
                f[j] = Math.abs( Math.sqrt(Math.pow(firstSummation,2) + Math.pow(secondSummation,2)) );
                double amplitude = 2 * f[j]/n;
                double frequency = j * h / T * sample_rate;
                if (frequency > 100) // Added so number of printed lines isn't insane
                {
                   if (frequency < 1000)
                   {
                      //System.out.println("frequency = "+frequency+", amp = "+amplitude);
                      if (amplitude > highamplitude) // Stores frequency and amplitude if new amplitude is higher than the record
                      {
                         highfrequency = frequency;
                         highamplitude = amplitude;
                      }
                   }
                   else 
                      break; // If the frequency gets high, this breaks so it doesn't go on forever
                }
             }
             System.out.println("High Frequency = "+highfrequency + " Amplutude = " + highamplitude);
          	
             System.out.println(returnNote(highfrequency));
          	
             
          }
       
       
       
           public static void main(String[] args) {
           	for (int i = 0; i < 1000; i++){
    				new Frequency4();
    			}
          }
       }
    Last edited by Aradon; 10-06-2008 at 10:19 AM. Reason: Updates

  • #2
    Senior Coder shyam's Avatar
    Join Date
    Jul 2005
    Posts
    1,563
    Thanks
    2
    Thanked 163 Times in 160 Posts
    how big is the wav file? how long does it take for this particular wav file?
    You never have to change anything you got up in the middle of the night to write. -- Saul Bellow

  • #3
    New to the CF scene
    Join Date
    Oct 2008
    Posts
    2
    Thanks
    0
    Thanked 0 Times in 0 Posts
    It's very small. It takes about half a second to run currently.

  • #4
    New to the CF scene
    Join Date
    Nov 2008
    Posts
    1
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Why store to file?

    Is there a reason you're storing it to a wav file? You could save the wave file output to a ByteArrayOutputStream then convert it to a ByteArrayInputStream for the read? Also it looks like the read call will read until the buffer is full you could either decrease the size of voiceData or increase your sample rate?

  • #5
    New to the CF scene
    Join Date
    Dec 2008
    Posts
    1
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Question Help With ByteArrayOutputStream

    I am trying to
    output to a ByteArrayOutputStream then convert it to a ByteArrayInputStream
    like swolfram said. I have been going nuts doing this without success. Can someone show me how to do this please?


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •