android AudioTrack 播放 正弦波 方波

源码下载地址: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;

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

}


你可能感兴趣的:(android)