Android app crashes after generating audio signal multiple times

I am developing an application to send text via chirp signals. Basically, I give the user the ability to write text and select the start frequency, end frequency and some other parameters of the bit sending time and time.

In the application, I split the text into characters, convert them to ASCII integers, convert them to binaries, and then send them with chirp signals (in Big Endian) with a 5ms chirp that goes from the start frequency to the end frequency (downward) to send 1, and from end to start frequency. (down) to send 0.

It's very simple and works, but after clicking the submit button several times, it crashes and I get the following error messages in the logcat:

07-08 15:09:58.036: E/AudioTrack(8747): AudioFlinger could not create track, status: -12 
07-08 15:09:58.036: E/AudioTrack-JNI(8747): Error initializing AudioTrack
07-08 15:09:58.036: E/AudioTrack-Java(8747): [ android.media.AudioTrack ] Error code -20 when initializing AudioTrack.
07-08 15:09:58.044: W/dalvikvm(8747): threadid=13: thread exiting with uncaught exception (group=0x40f77930)
07-08 15:09:58.051: E/AndroidRuntime(8747): FATAL EXCEPTION: Thread-445
07-08 15:09:58.051: E/AndroidRuntime(8747): java.lang.IllegalStateException:play() called on uninitialized AudioTrack.
07-08 15:09:58.051: E/AndroidRuntime(8747):     at android.media.AudioTrack.play(AudioTrack.java:883)
07-08 15:09:58.051: E/AndroidRuntime(8747):     at android.nacho.UltraSoundSender.AudioDevice.<init>(AudioDevice.java:19)
07-08 15:09:58.051: E/AndroidRuntime(8747):     at android.nacho.UltraSoundSender.ChirpGenerator.playDOWN(ChirpGenerator.java:104)
07-08 15:09:58.051: E/AndroidRuntime(8747):     at android.nacho.UltraSoundSender.UltraSoundSender$1$1.run(UltraSoundSender.java:61)
07-08 15:09:58.051: E/AndroidRuntime(8747):     at java.lang.Thread.run(Thread.java:856)

      

The three codes I am using are as follows:

1ΒΊ

public class UltraSoundSender extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_ultra_sound_sender);


        Button btnCode = (Button) findViewById(R.id.btnCode);
        btnCode.setOnClickListener(new OnClickListener() {

            //@Override
            public void onClick(View arg0) {            


                new Thread( new Runnable( ) 
                {
                   public void run( )
                   {   


                       String word= ((EditText)findViewById(R.id.Line)).getText().toString();
                       int IniFreq=Integer.parseInt(((EditText)findViewById(R.id.IniFreq)).getText().toString());
                       int FinFreq=Integer.parseInt(((EditText)findViewById(R.id.FinFreq)).getText().toString());
                       int bitLength=Integer.parseInt(((EditText)findViewById(R.id.bitLength)).getText().toString());
                       int bitGap=Integer.parseInt(((EditText)findViewById(R.id.bitGap)).getText().toString());

                       Integer digits[]= new Integer[64];
                       int NumChar= word.length();

                       //This split the string in chars
                       for(int i = 0; i <  NumChar ; i++){

                           digits[i]=(int)word.charAt(i);

                            }


                       double impulseDuration = 250; //not negotiable
                       int Delay=(int) (bitGap-((int)impulseDuration*0.8));
                       for(int IndexChar= 0; IndexChar< NumChar ; IndexChar++)
                       {

                            new ChirpGenerator().playDOWN(IniFreq*1000, FinFreq*1000, impulseDuration, digits[IndexChar], bitLength );
                            try {
                                Thread.sleep(Delay); //Time diference since whe generate one bit and the next one
                            } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                       }
                       Thread.currentThread().interrupt();

                      // enableButton(true);
                   }

                } ).start();

            }
        });


}

    //Enable/disable button
    private void enableButton(boolean isEnable)
    {
        ((Button)findViewById(R.id.btnCode)).setEnabled(isEnable);

}



    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_ultra_sound_sender, menu);
        return true;


    }
}

      

2ΒΊ

package android.nacho.UltraSoundSender;

public class ChirpGenerator {

    private AudioDevice device;


    public ChirpGenerator() {
        device = new AudioDevice( );
    }

/**
 * 
 * @param initialFreq in Hz
 * @param finalFreq in Hz
 * @param impulseDuration in ms
 */


    void playDOWN(int initialFreq, int finalFreq, double impulseDuration, int Code, int LengthBit) {

        AudioDevice device = new AudioDevice( );
        //int LengthBit=6; //In milliseconds
        int LengthBitInSamples = LengthBit*44; //That would means every bit is 5 millisecs length
        int NumberOfBits= 8;
        int LimitOfInterestingSamples=NumberOfBits*LengthBitInSamples;

        double k = (double)(finalFreq - initialFreq) / (LengthBit/1000.0); //This should be the corret one, but works better with 5 milliseconds
        float samples[] = new float[1024];
        double currentFreq = finalFreq; //Because it goes from up to down
        double phase;
        double t;
        int j = 0;
        int CountBits = 0;
        int IndexBit=1;
        Integer digits[]= new Integer[64];  

        //int Code = 45;

        for(int n=NumberOfBits, m=1; n>0; m++, n--) //To ID from 0 to 7 -> just 8 devices in the network
        {

            digits[m]=Code%2;
            Code/=2;
            System.out.println("Valor de digits"+digits[m]);

        }



        for (int i = 0; i < (int)(impulseDuration/1000.0 * AudioDevice.SAMPLING_RATE); i++, CountBits++) {

            if(i>LimitOfInterestingSamples)
            {
                samples[j++] = 0;

            }
            else{   

                if(CountBits>LengthBitInSamples)
                {
                    CountBits=0;
                    if(IndexBit<NumberOfBits) 
                    IndexBit++;


                }

                if(digits[IndexBit]==1) //This means 1
                {

                    t = (double)CountBits / (double)AudioDevice.SAMPLING_RATE;
                    currentFreq = initialFreq + 0.5 * k * t;
                    phase = 2.0 * Math.PI * (currentFreq) * t;

                }
                else{ //This means 0

                    t = (double)CountBits / (double)AudioDevice.SAMPLING_RATE;
                    currentFreq = finalFreq - 0.5 * k * t;
                    phase = 2.0 * Math.PI * (currentFreq) * t;
                }


                samples[j++] = (float)Math.sin(phase);

            } 

            if (j == 1024) {
                device.writeSamples( samples );
                j = 0;
            }

        }//for

    }



}

      

3o

package android.nacho.UltraSoundSender;

import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;

public class AudioDevice
{
    public static final int SAMPLING_RATE = 44100; //44100;
   AudioTrack track;
   short[] buffer = new short[1024];

   public AudioDevice( )
   {
      int minSize =AudioTrack.getMinBufferSize( SAMPLING_RATE, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT );        
      track = new AudioTrack( AudioManager.STREAM_MUSIC, SAMPLING_RATE, 
                                        AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, 
                                        minSize, AudioTrack.MODE_STREAM);
      track.play();   
      int nativeSampleRate = AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_MUSIC);

      int sampleRate = track.getSampleRate();

   }       

   public void writeSamples(float[] samples) 
   {    
      fillBuffer( samples );
      track.write( buffer, 0, samples.length );
   }

   private void fillBuffer( float[] samples )
   {
      if( buffer.length < samples.length )
         buffer = new short[samples.length];

      for( int i = 0; i < samples.length; i++ )
         buffer[i] = (short)Math.round(samples[i] * (float)Short.MAX_VALUE);
   }
}

      

Can anyone tell me why the application crashes when I execute it multiple times ?? Thanks to

+1


source to share


1 answer


it looks like you are not closing your AudioTrack instance when you are using it. When you are done with Twitter, you must close and revoke your audioTrack instance.



+2


source







All Articles