源码下载地址:http://download.csdn.net/detail/songconglai/7312933


MainActivity.java :

  1. 主类,播放方波(提供byteDate)和正弦波。
  2. 提供三个按钮分别为 短方波(btnPlayFS)、长方波(btnPlayFL)、正弦波(btnPlayZ),其功能如下:
  2.1. btnPlayFS /btnPlayFL 单击事件 :实例化WaveOutF(方波类),调用sendByteDate(byte[],length)方法 传送byteDate和有效长度,
  如果已经实例化则直接调用sendByteDate方法;
  2.2. btnPlayZ 单击事件 :实例化WaveOutZ(正弦波类),调用palyWaveZ()方法,播放正弦波;
  2.3. btnStopZ 单击事件:调用WaveOutZ下的colseWaveZ()方法 ,停止正弦波的播放。
  3. 实现onKeyDown构造方法:当用户点击返回按钮时注销已经打开的WaveOutF和WaveOutZ占用的资源,结束程序。
 
 WaveOutF.java :
  1.方波类,实现播放方波。
  2. 实例化 该类时,构造AudioTrack对象, 设置 类型:系统声音,采样率:44100,声道:单声道(右),
  采样精度:16bit,缓冲区大小:4096,模式:流媒体。
  3.方法:
  3.1. sendByteDate(byte[] byteDate,int len)将byteDate通过getShortDate()方法转换为音频源,
    开一个线程(audioTrackThread)播放。
  3.2. getShortDate()先 将byteDate通过getstrBinary(byte[] date, int lenght)方法转为转为2进制字符串,
  定义一个short[58*字符串长度]数组 ,再将字符串通过String.charAt(int i)检索出“1”则连续赋58个32767给数组,
  否则连续赋58个-32768给数组,返回数组(音频数据)。
  3.3. getstrBinary(byte[] date, int lenght) 将字节编码转为2进制字符串并补0,返回2进制字符串。
  3.4. playWaveF(short[] m_bitDateF) 写入音频数据给音频硬件进行播放,该方法是阻塞的。
  3.5. closeAudioTrack() 停止播放音频数据。
  4. 线程:AudioTrackThread 调用playWaveF方法。
 
 WaveOutZ.java :
  1. 正弦波类,实现播放正弦波。
  2. 实例化 该类时,构造AudioTrack对象 ,设置 类型:系统声音,采样率:44100,声道:单声道(左),
  采样精度:16bit,缓冲区大小:2*4096,模式:流媒体。
 
  3.方法:
  3.1. palyWaveZ() 开一个线程audioTrackZThread 播放正弦波;
  3.2. colseWaveZ() 通过标志位isRunning 关闭线程
  4.线程:AudioTrackZThread  定义一个short[44100]数组 通过算法:32767*Sin((2*3.1415926*8250.0/44100.0)*i)给数组赋值,

  写入音频数据到音频硬件进行播放


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;@Overridepublic 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() {@Overridepublic void onClick(View v) {if (woF == null) {woF = new WaveOutF();}woF.sendByteDate(byteDate, len);}});btnPlayFL.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {if (woF == null) {woF = new WaveOutF();}woF.sendByteDate(byteDate1, len1);}});btnPlayZ.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {btnStopZ.setEnabled(true);btnPlayZ.setEnabled(false);if (woZ == null) {woZ = new WaveOutZ();}woZ.palyWaveZ();}});btnStopZ.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {if (woZ != null) {woZ.colseWaveZ();btnPlayZ.setEnabled(true);btnStopZ.setEnabled(false);}}});}@Overridepublic 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);}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {getMenuInflater().inflate(R.menu.activity_main, menu);return true;}@Overrideprotected 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;// 采样精度 :16bitprivate 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{@Overridepublic 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;// 采样精度 :16bitprivate 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;@Overridepublic 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();}}}


更多相关文章

  1. Android(安卓)程序退出的办法
  2. Android(安卓)自定义View需要重写ondraw()等方法
  3. Android编程风格
  4. android json数据传递时编码格式的转换
  5. Android结束应用(不停止service)
  6. 属于自己的常见Android选项菜单样式集合
  7. Android更新UI的2种方法
  8. Android(安卓)Activity简介
  9. Android(安卓)Service详解(五)---绑定服务BoundService详解之AID

随机推荐

  1. 你觉得Android又凉了?那带你看下2020年And
  2. VINS在Android上的实现
  3. Android实现自定义测滑栏
  4. 用Ant手动打包android程序,android分包机
  5. 一篇文章带你领略Android混淆的魅力
  6. Android(安卓)UI 模式(patterns)
  7. 从Titlebar到Actionbar再到Toolbar
  8. Android(安卓)强弱指针
  9. Unity调用Android(安卓)jar包方法——(二
  10. AndroidStudio3.5下用NDK编绎VulkanScene