1. package com.terry.AudioFx;
  2.  
  3. import android.app.Activity;
  4. import android.content.Context;
  5. import android.graphics.Canvas;
  6. import android.graphics.Color;
  7. import android.graphics.Paint;
  8. import android.graphics.Rect;
  9. import android.media.AudioManager;
  10. import android.media.MediaPlayer;
  11. import android.media.MediaPlayer.OnCompletionListener;
  12. import android.media.audiofx.Equalizer;
  13. import android.media.audiofx.Visualizer;
  14. import android.media.audiofx.Visualizer.OnDataCaptureListener;
  15. import android.os.Bundle;
  16. import android.util.Log;
  17. import android.view.Gravity;
  18. import android.view.View;
  19. import android.view.ViewGroup;
  20. import android.widget.LinearLayout;
  21. import android.widget.SeekBar;
  22. import android.widget.TextView;
  23. import android.widget.SeekBar.OnSeekBarChangeListener;
  24.  
  25. public class AudioFxActivity extends Activity {
  26.  
  27. private static final String TAG = "AudioFxActivity";
  28.  
  29. private static final float VISUALIZER_HEIGHT_DIP = 50f;
  30.  
  31. private MediaPlayer mMediaPlayer;
  32. private Visualizer mVisualizer;
  33. private Equalizer mEqualizer; // 均衡器
  34.  
  35. private LinearLayout mLayout;
  36. VisualizerView mVisualizerView;
  37. private TextView mStatusTextView;
  38.  
  39. public void onCreate(Bundle savedInstanceState) {
  40. super.onCreate(savedInstanceState);
  41. setVolumeControlStream(AudioManager.STREAM_MUSIC);
  42.  
  43. mStatusTextView = new TextView(this);
  44. mLayout = new LinearLayout(this);
  45. mLayout.setOrientation(LinearLayout.VERTICAL);
  46. mLayout.addView(mStatusTextView);
  47. setContentView(mLayout);
  48.  
  49. mMediaPlayer = MediaPlayer.create(this, R.raw.z8806c);
  50.  
  51. setupVisualizerFxAndUi();
  52. setupEqualizeFxAndUi();
  53.  
  54. mVisualizer.setEnabled(true);
  55. mMediaPlayer.setOnCompletionListener(new OnCompletionListener() {
  56.  
  57. @Override
  58. public void onCompletion(MediaPlayer mp) {
  59. // TODO Auto-generated method stub
  60. mVisualizer.setEnabled(false);
  61. }
  62. });
  63.  
  64. mMediaPlayer.start();
  65. mStatusTextView.setText("播放中。。。");
  66. }
  67.  
  68. /**
  69. * 通过mMediaPlayer返回的AudioSessionId创建一个优先级为0均衡器对象 并且通过频谱生成相应的UI和对应的事件
  70. */
  71. private void setupEqualizeFxAndUi() {
  72. mEqualizer = new Equalizer(0, mMediaPlayer.getAudioSessionId());
  73. mEqualizer.setEnabled(true);// 启用均衡器
  74. TextView eqTextView = new TextView(this);
  75. eqTextView.setText("均衡器:");
  76. mLayout.addView(eqTextView);
  77.  
  78. // 通过均衡器得到其支持的频谱引擎
  79. short bands = mEqualizer.getNumberOfBands();
  80.  
  81. // getBandLevelRange 是一个数组,返回一组频谱等级数组,
  82. // 第一个下标为最低的限度范围
  83. // 第二个下标为最大的上限,依次取出
  84. final short minEqualizer = mEqualizer.getBandLevelRange()[0];
  85. final short maxEqualizer = mEqualizer.getBandLevelRange()[1];
  86.  
  87. for (short i = 0; i < bands; i++) {
  88. final short band = i;
  89.  
  90. TextView freqTextView = new TextView(this);
  91. freqTextView.setLayoutParams(new ViewGroup.LayoutParams(
  92. ViewGroup.LayoutParams.FILL_PARENT,
  93. ViewGroup.LayoutParams.WRAP_CONTENT));
  94.  
  95. freqTextView.setGravity(Gravity.CENTER_HORIZONTAL);
  96.  
  97. // 取出中心频率
  98. freqTextView
  99. .setText((mEqualizer.getCenterFreq(band) / 1000) + "HZ");
  100. mLayout.addView(freqTextView);
  101.  
  102. LinearLayout row = new LinearLayout(this);
  103. row.setOrientation(LinearLayout.HORIZONTAL);
  104.  
  105. TextView minDbTextView = new TextView(this);
  106. minDbTextView.setLayoutParams(new ViewGroup.LayoutParams(
  107. ViewGroup.LayoutParams.WRAP_CONTENT,
  108. ViewGroup.LayoutParams.WRAP_CONTENT));
  109.  
  110. minDbTextView.setText((minEqualizer / 100) + " dB");
  111.  
  112. TextView maxDbTextView = new TextView(this);
  113. maxDbTextView.setLayoutParams(new ViewGroup.LayoutParams(
  114. ViewGroup.LayoutParams.WRAP_CONTENT,
  115. ViewGroup.LayoutParams.WRAP_CONTENT));
  116. maxDbTextView.setText((maxEqualizer / 100) + " dB");
  117.  
  118. LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
  119. ViewGroup.LayoutParams.FILL_PARENT,
  120. ViewGroup.LayoutParams.WRAP_CONTENT);
  121.  
  122. layoutParams.weight = 1;
  123.  
  124. SeekBar seekbar = new SeekBar(this);
  125. seekbar.setLayoutParams(layoutParams);
  126. seekbar.setMax(maxEqualizer - minEqualizer);
  127. seekbar.setProgress(mEqualizer.getBandLevel(band));
  128.  
  129. seekbar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
  130.  
  131. @Override
  132. public void onStopTrackingTouch(SeekBar seekBar) {
  133. }
  134.  
  135. @Override
  136. public void onStartTrackingTouch(SeekBar seekBar) {
  137. }
  138.  
  139. @Override
  140. public void onProgressChanged(SeekBar seekBar, int progress,
  141. boolean fromUser) {
  142. // TODO Auto-generated method stub
  143. mEqualizer.setBandLevel(band,
  144. (short) (progress + minEqualizer));
  145. }
  146. });
  147. row.addView(minDbTextView);
  148. row.addView(seekbar);
  149. row.addView(maxDbTextView);
  150.  
  151. mLayout.addView(row);
  152. }
  153.  
  154. }
  155.  
  156. /**
  157. * 生成一个VisualizerView对象,使音频频谱的波段能够反映到 VisualizerView上
  158. */
  159. private void setupVisualizerFxAndUi() {
  160. mVisualizerView = new VisualizerView(this);
  161. mVisualizerView.setLayoutParams(new ViewGroup.LayoutParams(
  162. ViewGroup.LayoutParams.FILL_PARENT,
  163. (int) (VISUALIZER_HEIGHT_DIP * getResources()
  164. .getDisplayMetrics().density)));
  165. mLayout.addView(mVisualizerView);
  166.  
  167. mVisualizer = new Visualizer(mMediaPlayer.getAudioSessionId());
  168. // 参数内必须是2的位数
  169. mVisualizer.setCaptureSize(Visualizer.getCaptureSizeRange()[1]);
  170.  
  171. // 设置允许波形表示,并且捕获它
  172. mVisualizer.setDataCaptureListener(new OnDataCaptureListener() {
  173.  
  174. @Override
  175. public void onWaveFormDataCapture(Visualizer visualizer,
  176. byte[] waveform, int samplingRate) {
  177. // TODO Auto-generated method stub
  178. mVisualizerView.updateVisualizer(waveform);
  179. }
  180.  
  181. @Override
  182. public void onFftDataCapture(Visualizer visualizer, byte[] fft,
  183. int samplingRate) {
  184. // TODO Auto-generated method stub
  185.  
  186. }
  187. }, Visualizer.getMaxCaptureRate() / 2, true, false);
  188.  
  189. }
  190.  
  191. @Override
  192. protected void onPause() {
  193. // TODO Auto-generated method stub
  194. super.onPause();
  195. if (isFinishing() && mMediaPlayer != null) {
  196. mVisualizer.release();
  197. mMediaPlayer.release();
  198. mEqualizer.release();
  199. mMediaPlayer = null;
  200. }
  201. }
  202.  
  203. class VisualizerView extends View {
  204.  
  205. private byte[] mBytes;
  206. private float[] mPoints;
  207. // 矩形区域
  208. private Rect mRect = new Rect();
  209. // 画笔
  210. private Paint mPaint = new Paint();
  211.  
  212. // 初始化画笔
  213. private void init() {
  214. mBytes = null;
  215. mPaint.setStrokeWidth(1f);
  216. mPaint.setAntiAlias(true);
  217. mPaint.setColor(Color.BLUE);
  218. }
  219.  
  220. public VisualizerView(Context context) {
  221. super(context);
  222. init();
  223. }
  224.  
  225. public void updateVisualizer(byte[] mbyte) {
  226. mBytes = mbyte;
  227. invalidate();
  228. }
  229.  
  230. @Override
  231. protected void onDraw(Canvas canvas) {
  232. // TODO Auto-generated method stub
  233. super.onDraw(canvas);
  234.  
  235. if (mBytes == null) {
  236. return;
  237. }
  238. if (mPoints == null || mPoints.length < mBytes.length * 4) {
  239. mPoints = new float[mBytes.length * 4];
  240. }
  241.  
  242. mRect.set(0, 0, getWidth(), getHeight());
  243.  
  244. for (int i = 0; i < mBytes.length - 1; i++) {
  245. mPoints[i * 4] = mRect.width() * i / (mBytes.length - 1);
  246. mPoints[i * 4 + 1] = mRect.height() / 2
  247. + ((byte) (mBytes[i] + 128)) * (mRect.height() / 2)
  248. / 128;
  249. mPoints[i * 4 + 2] = mRect.width() * (i + 1)
  250. / (mBytes.length - 1);
  251. mPoints[i * 4 + 3] = mRect.height() / 2
  252. + ((byte) (mBytes[i + 1] + 128)) * (mRect.height() / 2)
  253. / 128;
  254. }
  255.  
  256. canvas.drawLines(mPoints, mPaint);
  257.  
  258. }
  259. }
  260. }

android 实现跳动频谱 DEMO的更多相关文章

  1. 解决Android微信支付官方demo运行失败

    Android微信支付官方demo运行失败,在此简单记录一下解决步骤 1.httpclient错误 官方给的demo是eclipse的,打开之后提示httpclient的错误,我知道在as下解决htt ...

  2. Android JNI学习(五)——Demo演示

    本系列文章如下: Android JNI(一)——NDK与JNI基础 Android JNI学习(二)——实战JNI之“hello world” Android JNI学习(三)——Java与Nati ...

  3. Android之ViewPager循环Demo

    ViewPager是谷歌官方提供的兼容低版本安卓设备的软件包,里面包含了只有在安卓3.0以上可以使用的api.Viewpager现在也算是标配了,如果一个App没有用到ViewPager感觉还是比较罕 ...

  4. Android studio百度地图demo出现230错误,key校验失败

    转自daoxiaomianzi原文 Android studio 百度地图demo出现230错误,key校验失败 使用AndroidStudio导入Baidu地图的as版的demo,引入后,发现没有k ...

  5. Android第一代壳demo编写

    Android第一代壳Demo编写 前言 这篇文章是对姜维大佬的这篇文章[Android中的Apk的加固(加壳)原理解析和实现]的补充.建议先看一编姜维大佬的这篇文章再看. 姜维大佬写那篇文章的时间距 ...

  6. Android -- 自定义View小Demo,动态画圆(一)

    1,转载:(http://blog.csdn.NET/lmj623565791/article/details/24500107),现在如下图的效果: 由上面的效果图可以看到其实是一个在一个圆上换不同 ...

  7. 转:android surface简单使用Demo

    转: http://blog.csdn.net/listening_music/article/details/6860786 通过之前介绍的如何自定义View, 我们知道使用它可以做一些简单的动画效 ...

  8. 转:android 录制视频的Demo

    转:http://blog.csdn.net/peijiangping1989/article/details/7049991 在这里给出自己的一个测试DEMO,里面注释很详细.简单的视频录制功能. ...

  9. android Popupwindow 的一个demo源码

    一直想用一下PopupWindow,就是苦于没有demo,自己去研究有太懒,刚好最近研究推送,下载了一个腾讯信鸽的demo,里面用到了一个PopupWindow,效果还不错,弄下来记录一下: 1.核心 ...

随机推荐

  1. 驱动: 中断【1】linux中断流程

    通常情况下,当一个给定的中断处理程序正在执行时,所有其他的中断都是打开的,所以这些不同中断线上的其他中断都能被处理,但当前中断总是被禁止的. 将中断处理切为两个部分或两半.中断处理程序上半部(top ...

  2. FileDescriptor

    FileDescriptor 在java中的java.io包下面 public final class FileDescriptor { ... } 官方的解释: 文件描述符类的实例用作与基础机器有关 ...

  3. Week8(10月31日):并发

    Part I:提问  =========================== 1. 更新关联.删除关联数据,需要注意哪些问题?以Instructor类为例说明. 2. 已知某请假系统,请实现以下界面的 ...

  4. larbin是一种开源的网络爬虫/网络蜘

    larbin是一种开源的网络爬虫/网络蜘蛛,由法国的年轻人 Sébastien Ailleret独立开发.larbin目的是能够跟踪页面的url进行扩展的抓取,最后为搜索引擎提供广泛的数据来源.Lar ...

  5. HTML5实现IP Camera网页输出

    HTML5实现IP Camera网页输出 这两天做OA项目.有一个要通过IP Camera将视频流输出到浏览器端的模块.尽管如今买到的摄像头都会提供浏览器和client的实现,可是一般来说都是仅仅支持 ...

  6. vector的成员函数解析

    vector是线性容器,它的元素严格的依照线性序列排序,和动态数组非常相似,和数组一样,它的元素存储在一块连续的存储空间中,这也意味着我们不仅能够使用迭代器(iterator)訪问元素,还能够使用指针 ...

  7. PHP - session编码和解码

    <?php //session编码 session_start(); $_SESSION['name'] = 'Jack'; $_SESSION['sex'] = 'men'; $envar = ...

  8. BZOJ 3477: [Usaco2014 Mar]Sabotage( 二分答案 )

    先二分答案m, 然后对于原序列 A[i] = A[i] - m,  然后O(n)找最大连续子序列和, 那么此时序列由 L + mx + R组成. L + mx + R = sum - n * m, s ...

  9. QTabWidget 实现类似QQ聊天窗口(拖动分离出新的窗口)

    新版本的QQ聊天窗口可以实现拖动,分离出新的窗口.浏览器等软件也可以实现类似操作.所以心血来潮想用Qt实现类似的功能.想用QTabWidget直接实现是很难的,仔细阅读源码,发现QTabWidget内 ...

  10. PHP - 遍历文件夹下的所有文件名

    /** * * 函数名:myreaddir($dir) * 作用:读取目录所有的文件名 * 参数:$dir 目录地址 * 返回值:文件名数组 * * */ function myreaddir($di ...