413053830 发表于 2006-6-26 00:58:00

android 设置线程的优先级

只能在真机上实现,模拟机不支持
本代码是俺借鉴的,并加入了详细的注解,主要用到AudioRecord,和AudioTrack两个类
简单说一下两个类的构造函数和基本方法:
AudioRecord
public AudioRecord (int audioSource, int sampleRateInHz, int channelConfig, int audioFormat, int bufferSizeInBytes) 四个参数分别是
audioSource

音频源:指的是从哪里采集音频。这里我们当然是从麦克风采集音频,所以此参数的值为MIC
sampleRateInHz

采样率:音频的采样频率,每秒钟能够采样的次数,采样率越高,音质越高。给出的实例是44100、22050、11025但不限于这几个参数。例如要采集低质量的音频就可以使用4000、8000等低采样率。
channelConfig
声道设置:android支持双声道立体声和单声道。MONO单声道,STEREO立体声
audioFormat


编码制式和采样大小:采集来的数据当然使用PCM编码(脉冲代码调制编码,即PCM编码。PCM通过抽样、量化、编码三个步骤将连续变化的模拟信号转换为数字编码。) android支持的采样大小16bit 或者8bit。当然采样大小越大,那么信息量越多,音质也越高,现在主流的采样大小都是16bit,在低质量的语音传输的时候8bit 足够了。
bufferSizeInBytes
采集数据需要的缓冲区的大小,如果不知道最小需要的大小可以在getMinBufferSize()查看。
getMinBufferSize(frequency, channelConfiguration, audioEncoding);
AudioTrack类
AudioTrack比AudioRecord多出来一个参数
public AudioTrack (int streamType, int sampleRateInHz, int channelConfig, int audioFormat, int bufferSizeInBytes,int mode)
其中streamType
<!---->l         <!---->STREAM_ALARM:警告声
<!---->l         <!---->STREAM_MUSCI:音乐声,例如music等
<!---->l         <!---->STREAM_RING:铃声
<!---->l         <!---->STREAM_SYSTEM:系统声音
<!---->l         <!---->STREAM_VOCIE_CALL:电话声音
其中mode
AudioTrack中有MODE_STATIC和MODE_STREAM两种分类。STREAM的意思是由用户在应用程序通过write方式把数据一次一次得写到audiotrack中。这个和我们在socket中发送数据一样,应用层从某个地方获取数据,例如通过编解码得到PCM数据,然后write到audiotrack。
这种方式的坏处就是总是在JAVA层和Native层交互,效率损失较大。
而STATIC的意思是一开始创建的时候,就把音频数据放到一个固定的buffer,然后直接传给audiotrack,后续就不用一次次得write了。AudioTrack会自己播放这个buffer中的数据。
这种方法对于铃声等内存占用较小,延时要求较高的声音来说很适用。
代码部分:
1.布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="@string/hello"
    />
<Button android:text="开始边录边放" android:id="@+id/recordButton" android:layout_width="fill_parent" android:layout_height="wrap_content"></Button>
<Button android:text="停止" android:id="@+id/stopButton" android:layout_width="fill_parent" android:layout_height="wrap_content"></Button>
<Button android:text="退出" android:id="@+id/exitButton" android:layout_width="fill_parent" android:layout_height="wrap_content"></Button>
<TextView android:text="音量调节" android:id="@+id/textView1" android:layout_width="fill_parent" android:layout_height="wrap_content"></TextView>
<SeekBar android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@+id/seekBar1"></SeekBar>
</LinearLayout>
2.为AudioRecord申请许可,修该AndroidManifes.xml如下:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.testrecord"
      android:versionCode="1"
      android:versionName="1.0">
    <uses-sdk android:minSdkVersion="9" />
    <application android:icon="@drawable/icon" android:label="@string/app_name">
      <activity android:name=".textRecord"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
         
      </activity>
   <uses-permission android:name="android.permission.RECORD_AUDIO"></uses-permission>
    </application>
</manifest>
3.主要实现代码:
import android.app.Activity;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioTrack;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.Toast;
public class textRecord extends Activity {
   Button recordButton,stopButton,exitButton;
   SeekBar skbVolume;
   boolean isRecording = false;
   static final int frequency = 44100;
   static final int channelConfiguration=AudioFormat.CHANNEL_CONFIGURATION_MONO;
   static final int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
   int recBufSize,playBufSize;
   AudioRecord audioRecord;
   AudioTrack audioTrack;
    public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.main);
      setTitle("助听器");
      //用getMinBufferSize()方法得到采集数据所需要的最小缓冲区的大小
      recBufSize = AudioRecord.getMinBufferSize(frequency, channelConfiguration, audioEncoding);
      playBufSize = AudioTrack.getMinBufferSize(frequency, channelConfiguration, audioEncoding);
      //实例化AudioRecord(声音来源,采样率,声道设置,采样声音编码,缓存大小)
      audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,frequency,channelConfiguration,audioEncoding,recBufSize);
      audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,frequency,channelConfiguration,audioEncoding,playBufSize,AudioTrack.MODE_STREAM);
      recordButton =(Button)this.findViewById(R.id.recordButton);
      stopButton =(Button) this.findViewById(R.id.stopButton);
      exitButton =(Button)this.findViewById(R.id.exitButton);
      recordButton.setOnClickListener(new ClickEvent());
      stopButton.setOnClickListener(new ClickEvent());
      exitButton.setOnClickListener(new ClickEvent());
      skbVolume = (SeekBar)this.findViewById(R.id.seekBar1);
      skbVolume.setMax(100);
      skbVolume.setProgress(70);
    // 设置声音大小
      audioTrack.setStereoVolume(0.7f, 0.7f);
      skbVolume.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
   
   
   public void onStopTrackingTouch(SeekBar seekBar) {
    float vol = (float)(seekBar.getProgress())/(float)(seekBar.getMax());
    audioTrack.setStereoVolume(vol, vol);
   
   }
   
   @Override
   public void onStartTrackingTouch(SeekBar seekBar) {
    // TODO Auto-generated method stub
   
   }
   
   @Override
   public void onProgressChanged(SeekBar seekBar, int progress,
   boolean fromUser) {
    // TODO Auto-generated method stub
   
   }
});
    }
    protected void onDestroy(){
   super.onDestroy();
// 杀死当前进程
   android.os.Process.killProcess(android.os.Process.myPid());
    }
    class ClickEvent implements View.OnClickListener{
   public void onClick(View v){
      if(v == recordButton){
       isRecording = true;
       new RecordPlayThread().start();
      }else if(v == stopButton){
       isRecording = false;
      }else if(v== exitButton){
       isRecording = false;
       textRecord.this.finish();
      }
   }
    }
    class RecordPlayThread extends Thread{
   public void run(){
      try{
//byte 文件来存储声音
       byte[] buffer = new byte;
//开始采集声音
       audioRecord.startRecording();
//播放声音
       audioTrack.play();
       while(isRecording){
//从MIC存储到缓存区
      int bufferReadResult = audioRecord.read(buffer,0, recBufSize);
      byte[] tmpBuf = new byte;
      System.arraycopy(buffer, 0, tmpBuf, 0, bufferReadResult);
//播放缓存区的数据
      audioTrack.write(tmpBuf, 0, tmpBuf.length);

       }
       audioTrack.stop();
       audioRecord.stop();
      }catch(Throwable t){
       Toast.makeText(textRecord.this, t.getMessage(), 1000);
      }
   }
    };
}
页: [1]
查看完整版本: android 设置线程的优先级