Why is my audio file so choppy after encoding the sample array in Xuggle?

95 views Asked by At
public class captureAudio{

    IMediaWriter writerAudio=null;
    long currentAudioTime;



    void startAudio() throws Exception {
        TargetDataLine line;

        //gets a TargetDataLine in which gets data from the Microphone
        line= getMic();

        //creates an array that is half the data buffer so that we don't have to worry about sample discards
        final byte[] audioBytes=new byte[line.getBufferSize()/2];

        final String outputFilename = "c:/Users/NICK/Desktop/SaveJPEG/"+"saved"+".aac";
        //creates a writer in which it's output is to outputFilename
        writerAudio = ToolFactory.makeWriter(outputFilename);

        //starts I/O process in which starts capturing  
        line.start();

        //gets current system time in nanoseconds
        currentAudioTime = System.nanoTime();


        //sets audioRunning to true 
        setstopper(true);

        writerAudio.addAudioStream(0, 0,ICodec.ID.AV_CODEC_ID_AAC, 1, 44100);
        //create new thread in which audio will be captured and encoded
        Thread thread = new Thread() {
            @Override
            public void run() {
                while(audioRunning()) {
                    short[] audioSamples;
                    int numSamplesRead=0;
                    int numBytesRead=0;

                    //get the number of bytes read
                    numBytesRead=line.read(audioBytes,0,audioBytes.length);
                    numSamplesRead=numBytesRead/2;
                    //create an array with a size of numSamplesRead. It is smaller than numBytesRead since we
                    //have 16 bit of data in each index of this array
                    audioSamples = new short[numSamplesRead];

                    /*Since the IMediaWriter.encodeAudio method takes in a short array, 
          We need to convert byte array to a short*/

                    //checks to see if the format is bigEndian or littleEndian which is indeed littleEndian by the format       
                    if(line.getFormat().isBigEndian()) {
                        for (int i = 0; i < numSamplesRead; i++) {

                            audioSamples[i] = (short)((audioBytes[2*i] << 8) | audioBytes[2*i + 1]);
                        }
                    }
                    else {

                        /*cast to short, get 2nd element create 8 zeros to the right(making it 16 bit) and include the first element (still 8 bit)*/ 
                        for (int i = 0; i < numSamplesRead; i++) {
                            audioSamples[i] = (short)((audioBytes[2*i + 1] << 8) | audioBytes[2*i]);

                        }
                    }
                    //Stream index is 0, pass in short[] audioSamples, get sample timestamp, units of timestamp
                    writerAudio.encodeAudio(0, audioSamples,System.nanoTime()-currentAudioTime,TimeUnit.NANOSECONDS);
                }



            }

        };
        //starts the thread above
        thread.start();
    }

TargetDataLine getMic() throws Exception {
//Audioformat object that takes a sample rate,bit size per sample,channel, and bool isBigEndian
AudioFormat format = new AudioFormat(44100F,16,1,true,false);
TargetDataLine line =null;
DataLine.Info info = new DataLine.Info(TargetDataLine.class,format); // format is an AudioFormat object
if (!AudioSystem.isLineSupported(info)) {
    throw new Exception();
    }

void stop() throws Exception {

    TargetDataLine mic = getMic();
    setstopper(false);
    mic.stop();
    mic.close();
    writerAudio.flush();
    writerAudio.close();
  }
}

Summary

The main idea is that I am trying to retrieve data from the microphone through a TargetDataLine and then am creating a new thread to run the encoding process of the audio along with the main thread which my videoCapture class uses to encode the video. Inside of the new thread, I am turning the audio samples array (originally a byte array) into a short array to use in the IMediaWriter.encodeAudio(...) method described above which the writer will successfully create a .acc audio file in my output file path.

Question

When I run the code I do get the desired audio file, but the audio quality is terrible. When I play back the audio, it is real staticky and choppy. So how exactly can I make the quality of the audio better?

0

There are 0 answers