Question

I'm developping an application to send a text through chirp signals. Basically I give the user the chance to write a text, and select a start frequency, a final frequency and some other options about time separtion between and duration of the bits to be sent.

In the app I split the text into chars, convert them into ASCII integers, convert those integers into binaries and then send them with chirp signals (in Big Endian), with a 5ms chirp that goes from initial freq to final freq (down to up) to send 1, and from final to initial freq. (up to down) to send 0.

It's very simple and it's working, but after pressing the send button a few times, it crash, 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'm using are the followings:

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;


    }
}

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

    }



}

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 App crash when I execute it a few times?? Thanks

Was it helpful?

Solution

it seems like you're not closing your AudioTrack instance when you're done using it. When you're done chirping, you should close and nullify your instance of audioTrack.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top