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)


相关推荐

  • Oracle Number 取值范围

    Oracle Number 取值范围1.0E-130&lt;=number&lt;1.0E126.-1.0E126&lt;number&lt;=-1.0E-130 

  • jmeter 中 Client implementation HttpClient4和java区别实践一

    jmeter 中 Client implementation HttpClient4和java区别实践一好吧,最近还是在折腾Jmeter,在一个post请求中,发现啃爹的竟然带有特殊字符:’怎么办,直接将数据写入,如下:然后在实际用post发请求时,jmeter自动给转义了,如下:xxxx=%27qq%27%3A%2720%27&rrr=%7Bqq%27  怎么办???那就加加转义字符试试,与是,加了”\”,“\\”,“\\\”,“\\\\”都…

  • IDEA热部署设置

    IDEA热部署设置转载位置:https://blog.csdn.net/nihao12323432/article/details/82664601

  • pycharm如何全局进行查找一个关键词

    pycharm如何全局进行查找一个关键词PyCharm的FindinPath功能提供了全局查找功能,快捷键为Ctrl+Shift+F。Find则是在当前文件查找,快捷键为Ctrl+F。这两个个功能非常实用。FindinPath的使用:按快捷键Ctrl+Shift+F或从从菜单Edit-》Find-》FindinPath进入全局查找界面。如下图所示,在Texttofind输入要查找的内…

  • 音频PCM编码「建议收藏」

    音频PCM编码「建议收藏」PCM编码PCM就是把一个时间连续,取值连续的模拟信号变换成时间离散,取值离散的数字信号后在信道中传输。简而言之PCM就是对模拟信号先抽样,再对样值幅度量化,编码的过程。例如听到的声音就是模拟信号,

  • WSGI、Flask及Werkzeug三者之间的关系

    WSGI、Flask及Werkzeug三者之间的关系目录一、WSGI是什么?二、Werkzeug是什么三、Flask的WSGI实现一、WSGI是什么?WSGI是一套接口规范。一个WSGI程序用以接受客户端请求,传递给应用,再返回服务器的响应给客户端。WSGI程序通常被定义成一个函数,当然你也可以使用类实例来实现。下图显示了python中客户端、服务器、WSGI、应用之间的关系:从下往上开始介绍:客户端:浏览器或者app。web服务器:Web服务器是指驻留于因特网上某种类型计算机的程序。当Web浏览器(客户端)连到服务.

发表回复

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

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