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.核心 ...
随机推荐
- Python之路Day9
摘要: 协程 Select\Poll\Epoll异步IO与事件驱动 Python连接MySQL数据库操作 RabbitMQ队列 Redis\Memcached缓存 Paramiko Twsited网络 ...
- Linux下查看二进制文件命令
一.在Linux下查看二进制文件的软件: xxd hexdump 二.编辑: 1.biew 2.hexedit 3.vim Vim 来编辑二进制文件.Vim 本非为此而设计的,因而有若干局限.但你能读 ...
- 集合判断null
Java 引用和指针差不多,null 引用 相当于 C++的空指针. isEmpty() 用于判断List内容是否为空,即表里一个元素也没有, 但是必须在 List<MallNews> g ...
- SolrCloud Hello Word
Solr Cloud 设计出来的目的是使你的搜索服务具有更高的可用性,提高容错.容灾能力.下面我们在一台电脑上建立2个solr服务,作为一个solrCloud分片(shard),初步认识一下solrC ...
- Entity Framework基金会
概要 Entity Framework缩写EF,微软ORM产品. 本篇博客将简单的介绍它,至于它的详细深层次的使用,大家能够查询对应的操作手冊,该篇不过入门. Entity Framework和Lin ...
- 嵌入式MCU开发群资源
STM32CubeMX是一款图形化软件设置工具,允许使用图形化向导来生成C初始化代码.它是未来开发stm32系列产品的主流软件,是ST公司的主动原创,可以减轻开发工作,时间和费用.STM32Cube ...
- Ibatis调用存储过程实现增删改以及分页查询
1.Ibatis实现增删改操作很简单了,通常我是将某一模块的增删改功能写在一个存储过程里,通过一个标识符去区分执行增加还是修改抑或删除操作. statement: <!-- 存储过程:实现学生的 ...
- java--从控制台读入一些数据
学一些东西应该,学以致用: 现在我开始使用流的办法从控制台读取数据 import java.io.*; public class Demo2{ public static void main(Stri ...
- 基于visual Studio2013解决C语言竞赛题之0702函数设计
题目
- flex调用webservice中的datatable结果写入datagrid
webservice配置文件 <appSettings> <add key="sqlConDuke" value="server=10.9.34.88; ...