源码下载地址:http://download.csdn.net/detail/songconglai/7312933
MainActivity.java :
1. 主类,播放方波(提供byteDate)和正弦波。写入音频数据到音频硬件进行播放
package scl.wavedome2;
import scl.waveout.WaveOutF;
import scl.waveout.WaveOutZ;
import android.app.Activity;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity {
private Button btnPlayFS;// 方波按钮
private Button btnPlayFL;
private Button btnStopZ;// 停止正弦波
private Button btnPlayZ;// 正弦波按钮
private WaveOutF woF;// 方波类
private WaveOutZ woZ;// 正弦波类
private byte[] byteDate;
private int len;
private byte[] byteDate1;
private int len1;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
byteDate = new byte[] { 0x71, 0x22, 0x42 };
len = byteDate.length;
byteDate1 = new byte[] { 0x11, 0x22, 0x42, 0x1A, 0x24, 0x13, 0x0a };
len1 = byteDate1.length;
}
private void init() {
btnPlayFS = (Button) findViewById(R.id.btn_play);
btnPlayFL = (Button) findViewById(R.id.btn_play1);
btnPlayZ = (Button) findViewById(R.id.btn_play2);
btnStopZ = (Button) findViewById(R.id.btn_stop);
btnStopZ.setEnabled(false);
btnPlayFS.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (woF == null) {
woF = new WaveOutF();
}
woF.sendByteDate(byteDate, len);
}
});
btnPlayFL.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (woF == null) {
woF = new WaveOutF();
}
woF.sendByteDate(byteDate1, len1);
}
});
btnPlayZ.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
btnStopZ.setEnabled(true);
btnPlayZ.setEnabled(false);
if (woZ == null) {
woZ = new WaveOutZ();
}
woZ.palyWaveZ();
}
});
btnStopZ.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (woZ != null) {
woZ.colseWaveZ();
btnPlayZ.setEnabled(true);
btnStopZ.setEnabled(false);
}
}
});
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (woZ != null) {
woZ.colseWaveZ();
woZ = null;
}
if (woF != null) {
woF.closeAudioTrack();
woF = null;
}
this.finish();
}
return super.onKeyDown(keyCode, event);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
@Override
protected void onStop() {
super.onStop();
}
}
package scl.waveout;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.util.Log;
public class WaveOutF {
// private ExecutorService pool = Executors.newSingleThreadExecutor();
private short max_iAmp = Short.MAX_VALUE;// 方波幅度<-32767 ~ 32767>
private short min_iAmp = Short.MIN_VALUE;
private byte[] m_date;// 得到的数据
private int m_lenght;// 得到数据的有效长度
private int m_iFangBo = 58;
private int sampleRateInHz = 44100; // 采样率
private int m_channel = AudioFormat.CHANNEL_CONFIGURATION_MONO;// 声道 :单声道
private int m_sampBit = AudioFormat.ENCODING_PCM_16BIT;// 采样精度 :16bit
private AudioTrack audioTrackF;
private short[] m_bitDateF ;
// AudioTrack创建所需的缓冲区大小
final int bufferSize = AudioTrack.getMinBufferSize(sampleRateInHz, m_channel,
m_sampBit);
public WaveOutF() {
System.out.println(bufferSize+"---------------");
audioTrackF = new AudioTrack(AudioManager.STREAM_SYSTEM,
sampleRateInHz, m_channel, m_sampBit, bufferSize,
AudioTrack.MODE_STREAM);
audioTrackF.setStereoVolume(0.0f, 1.0f);// 设置左右声道音量
// audioTrackF.play();
}
public void sendByteDate(byte[] byteDate, int len) {
if(audioTrackF == null){
Log.i("Fangbo", " null");
}
this.m_date = byteDate;
this.m_lenght = len;
m_bitDateF = null;
m_bitDateF = getShortDate();// audioTrack 播放时的数据
Thread audioTrackFThread = new Thread(new AudioTrackFThread());
// pool.execute(audioTrackThread);
audioTrackFThread.start();
this.m_date = null;
this.m_lenght = 0;
}
// 通过byteDate转为short型 的声音数据
private short[] getShortDate() {
int j = 0;
String strBinary = getstrBinary(this.m_date, this.m_lenght);
int len = strBinary.length();
int m_bitDateSize = len * m_iFangBo;
short[] m_pRightDate = new short[m_bitDateSize];
for (int i = 0; i < len; i++) {
int ct = m_iFangBo;
if (strBinary.charAt(i) == '1') {
while (ct-- > 0) {
// m_pRightDate[j++] = min_iAmp;
m_pRightDate[j++] = max_iAmp;
}
} else {
while (ct-- > 0) {
// m_pRightDate[j++] = max_iAmp;
m_pRightDate[j++] = min_iAmp;
}
}
}
return m_pRightDate;
}
// 将一个字节编码转为2进制字符串
private String getstrBinary(byte[] date, int lenght) {
StringBuffer strDate = new StringBuffer(lenght * 8);
for (int i = 0; i < lenght; i++) {
String str = Integer.toBinaryString(date[i]);
// System.out.println("str:"+str);
while (str.length() < 8) {
str = '0' + str;
}
strDate.append(str);
}
Log.i("strDate: " ,strDate+"");
return strDate.toString();
}
private void playWaveF(short[] m_bitDateF) {
audioTrackF.play();
audioTrackF.write(m_bitDateF, 0, m_bitDateF.length);// 该方法是阻塞的
}
public void closeAudioTrack() {
if (audioTrackF != null) {
audioTrackF.stop();
audioTrackF.release();
}
}
class AudioTrackFThread implements Runnable{
@Override
public void run() {
playWaveF(m_bitDateF);
audioTrackF.flush();
// Log.i("Thread","run over");
}
}
}
package scl.waveout;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
public class WaveOutZ {
private int sampleRateInHz = 44100; // 采样率
private int mChannel = AudioFormat.CHANNEL_CONFIGURATION_MONO;// 声道 :单声道
private int mSampBit = AudioFormat.ENCODING_PCM_16BIT;// 采样精度 :16bit
private AudioTrackZThread audioTrackZThread;
private boolean isRunning = false;
private AudioTrack audioTrackz;
public WaveOutZ() {
int bufferSize = AudioTrack.getMinBufferSize(sampleRateInHz, mChannel,
mSampBit);
audioTrackz = new AudioTrack(AudioManager.STREAM_SYSTEM,
sampleRateInHz, mChannel, mSampBit, bufferSize * 2,
AudioTrack.MODE_STREAM);
audioTrackz.setStereoVolume(1.0f, 0.0f);
audioTrackz.play();
}
public void palyWaveZ() {
audioTrackZThread = new AudioTrackZThread();
audioTrackZThread.start();
}
public void colseWaveZ() {
if (audioTrackz != null) {
if (!AudioTrackZThread.interrupted()) {
isRunning = false;
}
// audioTrackz.stop();
// audioTrackz.release();
}
}
class AudioTrackZThread extends Thread {
private short m_iAmp = Short.MAX_VALUE;
private short m_bitDateZ[] = new short[44100];
private double x = 2.0 * Math.PI * 8250.0 / 44100.0;
@Override
public void run() {
isRunning = true;
for (int i = 0; i < 44100; i++) {
m_bitDateZ[i] = (short) (m_iAmp * Math.sin(x * i));
}
int m_bitDateZSize = m_bitDateZ.length;
do {
audioTrackz.write(m_bitDateZ, 0, m_bitDateZSize);
// Log.v("isRunn", isRunning+"");
} while (isRunning);
super.run();
}
}
}