Android应用程序在生成音频信号几次后崩溃

时间:2013-07-08 13:32:57

标签: android audiotrack

我正在开发一个通过啁啾信号发送文本的应用程序。基本上我给用户提供了写文本的机会,并选择了开始频率,最终频率以及关于要发送的比特之间的时间间隔和持续时间的一些其他选项。

在应用程序中,我将文本分成字符,将它们转换为ASCII整数,将这些整数转换为二进制文件,然后使用啁啾信号(在Big Endian中)发送它们,从初始频率到最终频率的5ms啁啾声(向下发送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);
   }
}

任何人都可以告诉我为什么应用程序崩溃时我会执行几次? 感谢

1 个答案:

答案 0 :(得分:2)

您使用它时似乎没有关闭AudioTrack实例。当你完成啁啾声时,你应该关闭并取消你的audioTrack实例。