Приложение Android аварийно завершает работу после нескольких генераций звукового сигнала

Я разрабатываю приложение для отправки текста через сигналы щебета. По сути, я даю пользователю возможность написать текст и выбрать начальную частоту, конечную частоту и некоторые другие параметры, касающиеся временного интервала и продолжительности отправляемых битов.

В приложении я разбиваю текст на символы, преобразовываю их в целые числа ASCII, преобразовываю эти целые числа в двоичные, а затем отправляю их с сигналами щебета (в Big Endian), с щебетом 5 мс, который идет от начальной частоты до конечной частоты (вниз до вверх). ) для отправки 1 и с конечной частоты на начальную. (сверху вниз) для отправки 0.

Это очень просто и работает, но после нажатия кнопки отправки несколько раз происходит сбой, и я получаю следующие сообщения об ошибках в 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)

Три кода, которые я использую, следующие:

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);
   }
}

Может ли кто-нибудь сказать мне, почему приложение падает, когда я запускаю его несколько раз?? Спасибо


person Ignacio Alorre    schedule 08.07.2013    source источник


Ответы (1)


кажется, что вы не закрываете свой экземпляр AudioTrack, когда закончите его использовать. Когда вы закончите чирикать, вы должны закрыть и аннулировать свой экземпляр audioTrack.

person user1124644    schedule 15.07.2013
comment
Спасибо, на самом деле я нашел ошибку несколько дней назад, но, поскольку я не получил отзыва, я полностью забыл вопрос. Большое спасибо, что уделили время чтению всего кода;) - person Ignacio Alorre; 16.07.2013