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.核心 ...
随机推荐
- c/c++字符数组和字符串大揭秘
第一:写这篇文章源于我对'\0'和“\0”的探讨 当我对char a []="\0"; int size_a=sizeof(a); //结果为2 当时我很纳闷字符串不是以'\0'结 ...
- javascript date部分
<html> <body> <script type="text/javascript"> var d=new Date() var weekd ...
- PigCms 回复消息 "域名授权错误! 您使用的微信平台或源码为盗版"
本文地址:http://duwei.cnblogs.com/ Pigcms 将自动回复的API 写死了, 这里提供一个可用的API 在 PigCms/Lib/Action/Home/Weixinact ...
- USACO Money Systems Dp 01背包
一道经典的Dp..01背包 定义dp[i] 为需要构造的数字为i 的所有方法数 一开始的时候是这么想的 for(i = 1; i <= N; ++i){ for(j = 1; j <= V ...
- 基于 JVMTI 实现 Java 线程的监控(转)
随着多核 CPU 的日益普及,越来越多的 Java 应用程序使用多线程并行计算来充分发挥整个系统的性能.多线程的使用也给应用程序开发人员带来了巨大的挑战,不正确地使用多线程可能造成线程死锁或资源竞争, ...
- 疯牛-- Aggressive cows (二分)
疯牛 时间限制:1000 ms | 内存限制:65535 KB 难度:4 描述 农夫 John 建造了一座很长的畜栏,它包括N (2 <= N <= 100,000)个隔间,这些小 ...
- OpenRisc-31-关于在设计具有DMA功能的ipcore时的虚实地址转换问题的分析与解决
引言 之前,我们在讨论基于ORPSoC的ipcore设计时提到过DMA的问题,当时我们实现DMA的功能时,访问的是local memory,并没有使用主存(即外部的SDRAM),使用的是本地的一块存储 ...
- Office 2010 垃圾邮件过滤设置
垃圾邮件过滤设置 有同事反馈给我,某些时候应该收到的邮件,却到了垃圾邮件里,给工作带来了不便,下面简单介绍一下outlook 2010 有关垃圾邮件的过滤设置. 1: 找到相关的邮件,点右键,在”垃圾 ...
- BZOJ 2038: [2009国家集训队]小Z的袜子(hose) ( 莫队 )
莫队..先按sqrt(n)分块, 然后按块的顺序对询问排序, 同块就按右端点排序. 然后就按排序后的顺序暴力求解即可. 时间复杂度O(n1.5) --------------------------- ...
- C-最长回文子串(2)
在上一篇的文章中说到了,最长回文子串的问题,并且提到了基本的解决办法,即暴力求解法.效率O(N^3) 中心法求最长回文子串 我们知道回文字符串是以字符串中心对称的,如abba以及aba等.一个更好的办 ...