Android实现播放音频时的跳动频谱,并实现可以调节的均衡器。

Main.java

  1. package com.wjq.audiofx;
  2. import android.app.Activity;
  3. import android.media.AudioManager;
  4. import android.media.MediaPlayer;
  5. import android.media.audiofx.Equalizer;
  6. import android.media.audiofx.Visualizer;
  7. import android.os.Bundle;
  8. import android.util.Log;
  9. import android.view.Gravity;
  10. import android.view.ViewGroup;
  11. import android.widget.LinearLayout;
  12. import android.widget.SeekBar;
  13. import android.widget.TextView;
  14. public class Main extends Activity {
  15. private static final String TAG = "AudioFxDemo";
  16. private static final float VISUALIZER_HEIGHT_DIP = 50f;
  17. private MediaPlayer mMediaPlayer;
  18. private Visualizer mVisualizer;
  19. private Equalizer mEqualizer;//均横器
  20. private LinearLayout mLinearLayout;
  21. VisualizerView mVisualizerView;
  22. private TextView mStatusTextView;
  23. @Override
  24. public void onCreate(Bundle icicle) {
  25. super.onCreate(icicle);
  26. setVolumeControlStream(AudioManager.STREAM_MUSIC);
  27. mStatusTextView = new TextView(this);
  28. mLinearLayout = new LinearLayout(this);
  29. mLinearLayout.setOrientation(LinearLayout.VERTICAL);
  30. mLinearLayout.addView(mStatusTextView);
  31. setContentView(mLinearLayout);
  32. // Create the MediaPlayer
  33. mMediaPlayer = MediaPlayer.create(this, R.raw.test_cbr);
  34. if( null == mMediaPlayer )
  35. return ;
  36. Log.d(TAG, "MediaPlayer audio session ID: " + mMediaPlayer.getAudioSessionId());
  37. setupVisualizerFxAndUI();
  38. setupEqualizerFxAndUI();
  39. // Make sure the visualizer is enabled only when you actually want to receive data, and
  40. // when it makes sense to receive data.
  41. mVisualizer.setEnabled(true);
  42. // When the stream ends, we don't need to collect any more data. We don't do this in
  43. // setupVisualizerFxAndUI because we likely want to have more, non-Visualizer related code
  44. // in this callback.
  45. mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
  46. public void onCompletion(MediaPlayer mediaPlayer) {
  47. mVisualizer.setEnabled(false);
  48. }
  49. });
  50. mMediaPlayer.start();
  51. mStatusTextView.setText("播放音频...");
  52. }
  53. /**
  54. * 通过mMediaPlayer返回的AudioSessionId创建一个优先级为0均衡器对象,并且通过频谱生成相应的UI和对应的事件
  55. */
  56. private void setupEqualizerFxAndUI() {
  57. mEqualizer = new Equalizer(0, mMediaPlayer.getAudioSessionId());
  58. // 启用均衡器
  59. mEqualizer.setEnabled(true);
  60. TextView eqTextView = new TextView(this);
  61. eqTextView.setText("均横器:");
  62. mLinearLayout.addView(eqTextView);
  63. // 通过均衡器得到其支持的频谱引擎
  64. short bands = mEqualizer.getNumberOfBands();
  65. // getBandLevelRange是一个数组,返回一组频谱等级数组,返回一组频谱等级数组
  66. // 第一个下标为最低的限度范围,第二个下标为最高的限度范围
  67. // 依次取出
  68. final short minEQLevel = mEqualizer.getBandLevelRange()[0];
  69. final short maxEQLevel = mEqualizer.getBandLevelRange()[1];
  70. for (short i = 0; i < bands; i++) {
  71. final short band = i;
  72. TextView freqTextView = new TextView(this);
  73. freqTextView.setLayoutParams(new ViewGroup.LayoutParams(
  74. ViewGroup.LayoutParams.FILL_PARENT,
  75. ViewGroup.LayoutParams.WRAP_CONTENT));
  76. freqTextView.setGravity(Gravity.CENTER_HORIZONTAL);
  77. freqTextView.setText((mEqualizer.getCenterFreq(band) / 1000) + " Hz");
  78. mLinearLayout.addView(freqTextView);
  79. LinearLayout row = new LinearLayout(this);
  80. row.setOrientation(LinearLayout.HORIZONTAL);
  81. TextView minDbTextView = new TextView(this);
  82. minDbTextView.setLayoutParams(new ViewGroup.LayoutParams(
  83. ViewGroup.LayoutParams.WRAP_CONTENT,
  84. ViewGroup.LayoutParams.WRAP_CONTENT));
  85. minDbTextView.setText((minEQLevel / 100) + " dB");
  86. TextView maxDbTextView = new TextView(this);
  87. maxDbTextView.setLayoutParams(new ViewGroup.LayoutParams(
  88. ViewGroup.LayoutParams.WRAP_CONTENT,
  89. ViewGroup.LayoutParams.WRAP_CONTENT));
  90. maxDbTextView.setText((maxEQLevel / 100) + " dB");
  91. LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
  92. ViewGroup.LayoutParams.FILL_PARENT,
  93. ViewGroup.LayoutParams.WRAP_CONTENT);
  94. layoutParams.weight = 1;
  95. SeekBar bar = new SeekBar(this);
  96. bar.setLayoutParams(layoutParams);
  97. bar.setMax(maxEQLevel - minEQLevel);
  98. bar.setProgress(mEqualizer.getBandLevel(band));
  99. bar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
  100. public void onStopTrackingTouch(SeekBar seekBar) {}
  101. public void onStartTrackingTouch(SeekBar seekBar) {}
  102. public void onProgressChanged(SeekBar seekBar, int progress,
  103. boolean fromUser) {
  104. mEqualizer.setBandLevel(band, (short) (progress + minEQLevel));
  105. }
  106. });
  107. row.addView(minDbTextView);
  108. row.addView(bar);
  109. row.addView(maxDbTextView);
  110. mLinearLayout.addView(row);
  111. }
  112. }
  113. /**
  114. * 生成一个VisualizerView对象,使音频频谱的波段能够反映到 VisualizerView上
  115. */
  116. private void setupVisualizerFxAndUI() {
  117. mVisualizerView = new VisualizerView(this);
  118. mVisualizerView.setLayoutParams(new ViewGroup.LayoutParams(
  119. ViewGroup.LayoutParams.FILL_PARENT,
  120. (int)(VISUALIZER_HEIGHT_DIP * getResources().getDisplayMetrics().density)));
  121. mLinearLayout.addView(mVisualizerView);
  122. int sessId = mMediaPlayer.getAudioSessionId() ;
  123. mVisualizer = new Visualizer(sessId);
  124. // 参数必须是2的位数
  125. mVisualizer.setCaptureSize(Visualizer.getCaptureSizeRange()[1]);
  126. // 设置允许波形表示,并且捕获它
  127. mVisualizer.setDataCaptureListener(new Visualizer.OnDataCaptureListener() {
  128. public void onWaveFormDataCapture(Visualizer visualizer, byte[] bytes,
  129. int samplingRate) {
  130. mVisualizerView.updateVisualizer(bytes);
  131. }
  132. public void onFftDataCapture(Visualizer visualizer, byte[] bytes, int samplingRate) {}
  133. }, Visualizer.getMaxCaptureRate() / 2, true, false);
  134. }
  135. @Override
  136. protected void onPause() {
  137. super.onPause();
  138. if (isFinishing() && mMediaPlayer != null) {
  139. mVisualizer.release();
  140. mEqualizer.release();
  141. mMediaPlayer.release();
  142. mMediaPlayer = null;
  143. }
  144. }
  145. }

VisualizerView.java

  1. package com.wjq.audiofx;
  2. import android.content.Context;
  3. import android.graphics.Canvas;
  4. import android.graphics.Color;
  5. import android.graphics.Paint;
  6. import android.graphics.Rect;
  7. import android.view.View;
  8. public class VisualizerView extends View {
  9. private byte[] mBytes;
  10. private float[] mPoints;
  11. //矩形区域
  12. private Rect mRect = new Rect();
  13. // 画笔
  14. private Paint mForePaint = new Paint();
  15. // 初始化画笔
  16. private void init() {
  17. mBytes = null;
  18. mForePaint.setStrokeWidth(1f);
  19. mForePaint.setAntiAlias(true);
  20. mForePaint.setColor(Color.GREEN);
  21. }
  22. public VisualizerView(Context context) {
  23. super(context);
  24. init();
  25. }
  26. public void updateVisualizer(byte[] bytes) {
  27. mBytes = bytes;
  28. invalidate();
  29. }
  30. @Override
  31. protected void onDraw(Canvas canvas) {
  32. super.onDraw(canvas);
  33. if (mBytes == null) {
  34. return;
  35. }
  36. if (mPoints == null || mPoints.length < mBytes.length * 4) {
  37. mPoints = new float[mBytes.length * 4];
  38. }
  39. mRect.set(0, 0, getWidth(), getHeight());
  40. for (int i = 0; i < mBytes.length - 1; i++) {
  41. mPoints[i * 4] = mRect.width() * i / (mBytes.length - 1);
  42. mPoints[i * 4 + 1] = mRect.height() / 2
  43. + ((byte) (mBytes[i] + 128)) * (mRect.height() / 2) / 128;
  44. mPoints[i * 4 + 2] = mRect.width() * (i + 1) / (mBytes.length - 1);
  45. mPoints[i * 4 + 3] = mRect.height() / 2
  46. + ((byte) (mBytes[i + 1] + 128)) * (mRect.height() / 2) / 128;
  47. }
  48. canvas.drawLines(mPoints, mForePaint);
  49. }
  50. }

Android播放音乐时跳动的屏谱demo的更多相关文章

  1. android 播放视频时切换全屏隐藏状态栏

    1. Demo: @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstance ...

  2. android 播放音乐-进度条

    今天学渣研究了一下使用MediaPlayer播放音乐时加入进度条,进度条如今用的是android自带的seekbar,后期会跟换UI的,在之前可以播放音乐的基础上,如今加入的主要功能有两个: 1实时显 ...

  3. 绘制播放音乐时的音波图形的View

    绘制播放音乐时的音波图形的View 这个效果类似于这个哦: 效果如下: 源码: MusicView.h 与 MusicView.m // // MusicView.h // Music // // C ...

  4. android 播放音乐媒体文件(一)

    Audio formats and codecs Format / Codec Encoder Decoder Details Supported File Type(s) / Container F ...

  5. Android 播放电影时滑动屏幕调整屏幕亮度(转)

    (转自:http://blog.csdn.net/piaozhiye/article/details/6544450) 发现有一些主流的播放器播放电影时可以通过滑动屏幕调整屏幕亮度,其实实现起来也很容 ...

  6. 关于Windows 8使用WMP播放音乐时WUDFHost跑CPU和硬盘的问题解决

    Windows 8使用Windows Media Player播放音乐的时候.事实上有一个这种情况,WMP和某个什么名字看起来非常屌的进程跑CPU非常高,这个跑非常高视你插入的SD卡内的文件数或者移动 ...

  7. android修改系统时系统黑屏时不进入休眠状态

    基于android4.4修改,在frameworks/base/services/java/com/android/server/power/PowerManagerService.java里,查看休 ...

  8. android关闭屏幕时不锁屏实现

    所需权限: <uses-permission android:name="android.permission.DISABLE_KEYGUARD"/> 关闭系统锁屏服务 ...

  9. 解决Android Activity切换时出现白屏问题

    有些性能低的机器,在切换activity时候出现白屏一段时候后才显示正确的视图 高性能的机器可能太快看不到,但是事实是存在的, 特别是当你新开一个进程的时候,A进程的activity跳转到B进程的Ac ...

随机推荐

  1. Spring boot 启动过程解析 logback

    使用 Spring Boot 默认的日志框架 Logback. 所有这些 POM 依赖的好处在于为开发 Spring 应用提供了一个良好的基础.Spring Boot 所选择的第三方库是经过考虑的,是 ...

  2. 图的DFS递归和非递归

    看以前写的文章: 图的BFS:http://www.cnblogs.com/youxin/p/3284016.html DFS:http://www.cnblogs.com/youxin/archiv ...

  3. ubuntu 下关闭MySql server

    转自 http://blog.csdn.net/tobacco5648/article/details/7625048 在终端输入命令 开启:     sudo   /etc/init.d/mysql ...

  4. jsp验证表单后再提交

    在提交表单时,我们常常需要验证核实表单内容,若都不为空时,方能提交:若有文本框为空则不提交,并获取鼠标焦点到文本框上 ,所以我们可以利用onsubmit的方法来做,请看下面例子: <html&g ...

  5. CentOS的MySQL报错:Can't connect to MySQL server

    原文链接: http://www.centoscn.com/CentosBug/softbug/2015/0622/5709.html 问题描述: 使用客户端远程登录连接基于CentOS 6.5服务器 ...

  6. mul8_unsigned multipliter

    李亚民老师更注重硬件设计思想的训练.他给出的硬件设计方法更贴近底层硬件,下面看看他的设计思想:                                                      ...

  7. ZooKeeper - Perl bindings for Apache ZooKeeper Perl绑定用于 Apache ZooKeeper

    ZooKeeper - Perl bindings for Apache ZooKeeper Perl绑定用于 Apache ZooKeeper 监控 master/slave 需要使用zk的临时节点 ...

  8. oschina开源硬件其它开源,开源硬件

    硬件驱动/工具 25Linux内核 101桌面环境 40开源字体 58嵌入式操作系统 33输入法 110开源硬件 57开源图书 5开源家居 17物联网 87开源货币/比特币 32NASA 开源项目 1 ...

  9. hdu-4302-Holedox Eating-线段树-单点更新,有策略的单点查询

    一開始实在是不知道怎么做,后来经过指导,猛然发现,仅仅须要记录某个区间内是否有值就可以. flag[i]:代表i区间内,共同拥有的蛋糕数量. 放置蛋糕的时候非常好操作,单点更新. ip:老鼠当前的位置 ...

  10. CF(435D - Special Grid)dp

    题目链接:http://codeforces.com/problemset/problem/435/D 题意:求三角形个数,三个点必须的白点上,而且三条边必须是横线,竖线或对角线,三条边上不同意出现黑 ...