android AudioTrack 播放 正弦波 方波「建议收藏」

MainActivity.java: 1.主类,播放方波(提供byteDate)和正弦波。 2.提供三个按钮分别为短方波(btnPlayFS)、长方波(btnPlayFL)、正弦波(btnPlayZ),其功能如下: 2.1.btnPlayFS/btnPlayFL单击事件:实例化WaveOutF(方波类),调用sendByteDate(byte[],length)方

大家好,又见面了,我是你们的朋友全栈君。

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

}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/128786.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 简述物联网,云计算,大数据和人工智能的相互关系_物联网应用领域

    简述物联网,云计算,大数据和人工智能的相互关系_物联网应用领域我们在《互联网进化论》一书中提出“互联网的未来功能和结构将于人类大脑高度相似,也将具备互联网虚拟感觉,虚拟运动,虚拟中枢,虚拟记忆神经系统”,并绘制了一幅互联网虚拟大脑结构图。根据这一观点,我们尝试分析目前互联网最流行的四个概念————-大数据,云计算,物联网和移动互联网与传统互联网之间的关系。从这幅图中我们可以看出:物联网对应了互联网的感觉和运动神…

  • 【转载】java sleep和wait的区别的疑惑?

    【转载】java sleep和wait的区别的疑惑?

    2021年11月20日
  • Spring进阶之路(1)-Spring核心机制:依赖注入/控制反转

    Spring进阶之路(1)-Spring核心机制:依赖注入/控制反转

  • 工控机上位机软件的开发历程(二)[通俗易懂]

    工控机上位机软件的开发历程(二)[通俗易懂]仪器归一化设计这是具体内容的第一篇,我们先来讲述仪器的归一化设计。仪器是各种功能都有的,我只举我们在环境监测这方面所用到的仪器。我们要测试水是不是有污染物质,污染到什么程度,我们要测试水体的高锰酸盐指数、氨氮、总磷、总氮等值。我们的站房有一个后备电源,我们要知道市电是否断电了,是否在用备用电源。我们的站房是有空调的,我希望知道站房的温度和湿度,于是就有了一个温湿度计。我们可能还会有流量计、…

  • python重复执行10次_卡bug

    python重复执行10次_卡bugpy3Fdfs修复几个bugpy3Fdfs2.2.0TypeError:typeobjectargumentafter**mustbeamapping,notstrdownload_to_file(local_filename,remote_file_id),提示mustbebytes[],notstrPython3struct格式化下载30k文件出现sock…

    2022年10月21日
  • 什么是NP问题,什么是NP hard问题,什么是NP完全问题

    什么是NP问题,什么是NP hard问题,什么是NP完全问题先来看一个小故事:(转自:http://zhm2k.blog.163.com/blog/static/5981506820095233143571/)假如老板要你解决一个问题,你绞尽脑汁还是想不出来,叫天天不应,叫地地不灵,这时你走进老板办公室,可以采取3种策略:1)一副倒霉像,神情猥琐,可怜巴巴的说:老板,我没做出来,我想我是太蠢了……boss:蠢材!滚!(失败……)2)

    2022年10月31日

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号