android 实现跳动频谱 DEMO
package com.terry.AudioFx; import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.audiofx.Equalizer;
import android.media.audiofx.Visualizer;
import android.media.audiofx.Visualizer.OnDataCaptureListener;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.SeekBar.OnSeekBarChangeListener; public class AudioFxActivity extends Activity { private static final String TAG = "AudioFxActivity"; private static final float VISUALIZER_HEIGHT_DIP = 50f; private MediaPlayer mMediaPlayer;
private Visualizer mVisualizer;
private Equalizer mEqualizer; // 均衡器 private LinearLayout mLayout;
VisualizerView mVisualizerView;
private TextView mStatusTextView; public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setVolumeControlStream(AudioManager.STREAM_MUSIC); mStatusTextView = new TextView(this);
mLayout = new LinearLayout(this);
mLayout.setOrientation(LinearLayout.VERTICAL);
mLayout.addView(mStatusTextView);
setContentView(mLayout); mMediaPlayer = MediaPlayer.create(this, R.raw.z8806c); setupVisualizerFxAndUi();
setupEqualizeFxAndUi(); mVisualizer.setEnabled(true);
mMediaPlayer.setOnCompletionListener(new OnCompletionListener() { @Override
public void onCompletion(MediaPlayer mp) {
// TODO Auto-generated method stub
mVisualizer.setEnabled(false);
}
}); mMediaPlayer.start();
mStatusTextView.setText("播放中。。。");
} /**
* 通过mMediaPlayer返回的AudioSessionId创建一个优先级为0均衡器对象 并且通过频谱生成相应的UI和对应的事件
*/
private void setupEqualizeFxAndUi() {
mEqualizer = new Equalizer(0, mMediaPlayer.getAudioSessionId());
mEqualizer.setEnabled(true);// 启用均衡器
TextView eqTextView = new TextView(this);
eqTextView.setText("均衡器:");
mLayout.addView(eqTextView); // 通过均衡器得到其支持的频谱引擎
short bands = mEqualizer.getNumberOfBands(); // getBandLevelRange 是一个数组,返回一组频谱等级数组,
// 第一个下标为最低的限度范围
// 第二个下标为最大的上限,依次取出
final short minEqualizer = mEqualizer.getBandLevelRange()[0];
final short maxEqualizer = mEqualizer.getBandLevelRange()[1]; for (short i = 0; i < bands; i++) {
final short band = i; TextView freqTextView = new TextView(this);
freqTextView.setLayoutParams(new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT)); freqTextView.setGravity(Gravity.CENTER_HORIZONTAL); // 取出中心频率
freqTextView
.setText((mEqualizer.getCenterFreq(band) / 1000) + "HZ");
mLayout.addView(freqTextView); LinearLayout row = new LinearLayout(this);
row.setOrientation(LinearLayout.HORIZONTAL); TextView minDbTextView = new TextView(this);
minDbTextView.setLayoutParams(new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT)); minDbTextView.setText((minEqualizer / 100) + " dB"); TextView maxDbTextView = new TextView(this);
maxDbTextView.setLayoutParams(new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
maxDbTextView.setText((maxEqualizer / 100) + " dB"); LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT); layoutParams.weight = 1; SeekBar seekbar = new SeekBar(this);
seekbar.setLayoutParams(layoutParams);
seekbar.setMax(maxEqualizer - minEqualizer);
seekbar.setProgress(mEqualizer.getBandLevel(band)); seekbar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { @Override
public void onStopTrackingTouch(SeekBar seekBar) {
} @Override
public void onStartTrackingTouch(SeekBar seekBar) {
} @Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// TODO Auto-generated method stub
mEqualizer.setBandLevel(band,
(short) (progress + minEqualizer));
}
});
row.addView(minDbTextView);
row.addView(seekbar);
row.addView(maxDbTextView); mLayout.addView(row);
} } /**
* 生成一个VisualizerView对象,使音频频谱的波段能够反映到 VisualizerView上
*/
private void setupVisualizerFxAndUi() {
mVisualizerView = new VisualizerView(this);
mVisualizerView.setLayoutParams(new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT,
(int) (VISUALIZER_HEIGHT_DIP * getResources()
.getDisplayMetrics().density)));
mLayout.addView(mVisualizerView); mVisualizer = new Visualizer(mMediaPlayer.getAudioSessionId());
// 参数内必须是2的位数
mVisualizer.setCaptureSize(Visualizer.getCaptureSizeRange()[1]); // 设置允许波形表示,并且捕获它
mVisualizer.setDataCaptureListener(new OnDataCaptureListener() { @Override
public void onWaveFormDataCapture(Visualizer visualizer,
byte[] waveform, int samplingRate) {
// TODO Auto-generated method stub
mVisualizerView.updateVisualizer(waveform);
} @Override
public void onFftDataCapture(Visualizer visualizer, byte[] fft,
int samplingRate) {
// TODO Auto-generated method stub }
}, Visualizer.getMaxCaptureRate() / 2, true, false); } @Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
if (isFinishing() && mMediaPlayer != null) {
mVisualizer.release();
mMediaPlayer.release();
mEqualizer.release();
mMediaPlayer = null;
}
} class VisualizerView extends View { private byte[] mBytes;
private float[] mPoints;
// 矩形区域
private Rect mRect = new Rect();
// 画笔
private Paint mPaint = new Paint(); // 初始化画笔
private void init() {
mBytes = null;
mPaint.setStrokeWidth(1f);
mPaint.setAntiAlias(true);
mPaint.setColor(Color.BLUE);
} public VisualizerView(Context context) {
super(context);
init();
} public void updateVisualizer(byte[] mbyte) {
mBytes = mbyte;
invalidate();
} @Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas); if (mBytes == null) {
return;
}
if (mPoints == null || mPoints.length < mBytes.length * 4) {
mPoints = new float[mBytes.length * 4];
} mRect.set(0, 0, getWidth(), getHeight()); for (int i = 0; i < mBytes.length - 1; i++) {
mPoints[i * 4] = mRect.width() * i / (mBytes.length - 1);
mPoints[i * 4 + 1] = mRect.height() / 2
+ ((byte) (mBytes[i] + 128)) * (mRect.height() / 2)
/ 128;
mPoints[i * 4 + 2] = mRect.width() * (i + 1)
/ (mBytes.length - 1);
mPoints[i * 4 + 3] = mRect.height() / 2
+ ((byte) (mBytes[i + 1] + 128)) * (mRect.height() / 2)
/ 128;
} canvas.drawLines(mPoints, mPaint); }
}
}
android 实现跳动频谱 DEMO的更多相关文章
- 解决Android微信支付官方demo运行失败
Android微信支付官方demo运行失败,在此简单记录一下解决步骤 1.httpclient错误 官方给的demo是eclipse的,打开之后提示httpclient的错误,我知道在as下解决htt ...
- Android JNI学习(五)——Demo演示
本系列文章如下: Android JNI(一)——NDK与JNI基础 Android JNI学习(二)——实战JNI之“hello world” Android JNI学习(三)——Java与Nati ...
- Android之ViewPager循环Demo
ViewPager是谷歌官方提供的兼容低版本安卓设备的软件包,里面包含了只有在安卓3.0以上可以使用的api.Viewpager现在也算是标配了,如果一个App没有用到ViewPager感觉还是比较罕 ...
- Android studio百度地图demo出现230错误,key校验失败
转自daoxiaomianzi原文 Android studio 百度地图demo出现230错误,key校验失败 使用AndroidStudio导入Baidu地图的as版的demo,引入后,发现没有k ...
- Android第一代壳demo编写
Android第一代壳Demo编写 前言 这篇文章是对姜维大佬的这篇文章[Android中的Apk的加固(加壳)原理解析和实现]的补充.建议先看一编姜维大佬的这篇文章再看. 姜维大佬写那篇文章的时间距 ...
- Android -- 自定义View小Demo,动态画圆(一)
1,转载:(http://blog.csdn.NET/lmj623565791/article/details/24500107),现在如下图的效果: 由上面的效果图可以看到其实是一个在一个圆上换不同 ...
- 转:android surface简单使用Demo
转: http://blog.csdn.net/listening_music/article/details/6860786 通过之前介绍的如何自定义View, 我们知道使用它可以做一些简单的动画效 ...
- 转:android 录制视频的Demo
转:http://blog.csdn.net/peijiangping1989/article/details/7049991 在这里给出自己的一个测试DEMO,里面注释很详细.简单的视频录制功能. ...
- android Popupwindow 的一个demo源码
一直想用一下PopupWindow,就是苦于没有demo,自己去研究有太懒,刚好最近研究推送,下载了一个腾讯信鸽的demo,里面用到了一个PopupWindow,效果还不错,弄下来记录一下: 1.核心 ...
随机推荐
- 【转】LINUX下一款不错的网站压力测试工具webbench
原文链接:http://blog.csdn.net/xinqingch/article/details/8618704 安装: wget http://blog.s135.com/soft/linux ...
- POJ2125 Destroying The Graph 二分图 + 最小点权覆盖 + 最小割
思路来源:http://blog.csdn.net/lenleaves/article/details/7873441 求最小点权覆盖,同样求一个最小割,但是要求出割去了那些边, 只要用最终的剩余网络 ...
- AWVS介绍(转)
使用AWVS对域名进行全局分析,深入探索: 首先,介绍一下AWVS这个工具. Acunetix Web Vulnerability Scanner(简称AWVS)是一款知名的网络漏洞扫描工具,它通过网 ...
- cocos2dx进阶学习之CCEGLView
继承关系 CCEGLView-> CCEGLViewProtocol CCEGLView是窗口,在不同平台上有不同的实现,而CCEGLViewProtocol是CCEGLView定义的接口,所以 ...
- 【JSP】JSTL核心标签库的使用方法和示例
JSTL 核心标签库 JSTL 核心标签库标签共有13个,功能上分为4类: 1. 表达式控制标签:out.set.remove.catch 2. 流程控制标签:if.choose.when.other ...
- datanode启动后,在web50070port发现不到datanode节点(能力工场)
直接上问题:这两天为了试验,安装了两套集群: (1)32位hadoop1集群(5个节点); (2)64位hadoop2集群(6个节点) 两个集群中都遇到过这种问题:在namenode正常启动hadoo ...
- TCP三四次握手
通俗点说: 三次握手: A:发送连接请求 B:收到请求后,B知道自己的接收端是好的,返回给A请求的应答,并询问A是否收到自己的本次应答. A:收到B的应答.A知道自己的发送端和接收端都是好的.然后发送 ...
- 青云B轮获2000万美元VC的背后逻辑:用技术超越巨头
http://www.lagou.com/gongsi/31164.html http://capital.chinaventure.com.cn/11/7/1389263145.shtml
- Android自定义照相机实现(拍照、保存到SD卡,利用Bundle在Acitivity交换数据)
Android自定义照相机实现 近期小巫在学校有一个创新项目,也不是最近,是一个拖了很久的项目,之前一直没有去搞,最近因为要中期检查,搞得我跟小组成员一阵忙活,其实开发一款照相机软件并不太难,下面就是 ...
- Swift 与 Objective-C混合编程
在Swift项目中想要同一时候加入Objective-C的库支持或者须要同一时候用Objective-C编程 在加入新的文件时选择Objective-C系统就会自己主动生成一个xx-Bridging- ...