本Demo无须界面布局文件,使用一个LinearLayout容器来盛装一个示波器View组件,该示波器View组件将负责绘制Visualizer传过来的数据:LinearLayout添加多个SeekBar来控制Equalizer支持的所有频率的均衡值;LinearLayout还添加一个SeekBar来控制重低音的强度;LinearLayout还添加一个Spinner让用户选择预设音场。

  • MainActivity逻辑代码:
package com.fukaimei.mediaplayertest;import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.audiofx.BassBoost;
import android.media.audiofx.Equalizer;
import android.media.audiofx.PresetReverb;
import android.media.audiofx.Visualizer;
import android.os.Bundle;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.SeekBar;
import android.widget.Spinner;
import android.widget.TextView;import java.util.ArrayList;
import java.util.List;public class MainActivity extends Activity {// 定义播放声音的MediaPlayerprivate MediaPlayer mPlayer;// 定义系统的示波器private Visualizer mVisualizer;// 定义系统的均衡器private Equalizer mEqualizer;// 定义系统的重低音控制器private BassBoost mBass;// 定义系统的预设音场控制器private PresetReverb mPresetReverb;private LinearLayout layout;private List<Short> reverbNames = new ArrayList<Short>();private List<String> reverbVals = new ArrayList<String>();@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 设置控制音乐声音setVolumeControlStream(AudioManager.STREAM_MUSIC);layout = new LinearLayout(this);layout.setOrientation(LinearLayout.VERTICAL);setContentView(layout);// 创建MediaPlayer对象mPlayer = MediaPlayer.create(this, R.raw.xijuzhiwang);// 初始化示波器setupVisualizer();// 初始化均衡控制器setupEqualizer();// 初始化重低音控制器setupBassBoost();// 初始化预设音场控制器setupPresetReverb();// 开发播放音乐mPlayer.start();}private void setupVisualizer() {// 创建MyVisualizerView组件,用于显示波形图final MyVisualizerView mVisualizerView =new MyVisualizerView(this);mVisualizerView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,(int) (120f * getResources().getDisplayMetrics().density)));// 将MyVisualizerView组件添加到layout容器中layout.addView(mVisualizerView);// 以MediaPlayer的AudioSessionId创建Visualizer// 相当于设置Visualizer负责显示该MediaPlayer的音频数据mVisualizer = new Visualizer(mPlayer.getAudioSessionId());mVisualizer.setCaptureSize(Visualizer.getCaptureSizeRange()[1]);// 为mVisualizer设置监听器mVisualizer.setDataCaptureListener(new Visualizer.OnDataCaptureListener() {@Overridepublic void onFftDataCapture(Visualizer visualizer, byte[] fft, int samplingRate) {}@Overridepublic void onWaveFormDataCapture(Visualizer visualizer, byte[] waveform, int samplingRate) {// 用waveform波形数据更新mVisualizerView组件mVisualizerView.updateVisualizer(waveform);}}, Visualizer.getMaxCaptureRate() / 2, true, false);mVisualizer.setEnabled(true);}// 初始化均衡控制器的方法private void setupEqualizer() {// 以MediaPlayer的AudioSessionId创建Equalizer// 相当于设置Equalizer负责控制该MediaPlayermEqualizer = new Equalizer(0, mPlayer.getAudioSessionId());// 启用均衡控制效果mEqualizer.setEnabled(true);TextView eqTitle = new TextView(this);eqTitle.setText("均衡器:");layout.addView(eqTitle);// 获取均衡控制器支持最小值和最大值final short minEQLevel = mEqualizer.getBandLevelRange()[0];short maxEQLevel = mEqualizer.getBandLevelRange()[1];// 获取均衡控制器支持的所有频率short brands = mEqualizer.getNumberOfBands();for (short i = 0; i < brands; i++) {TextView eqTextView = new TextView(this);// 创建一个TextView,用于显示频率eqTextView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT));eqTextView.setGravity(Gravity.CENTER_HORIZONTAL);// 设置该均衡控制器的频率eqTextView.setText((mEqualizer.getCenterFreq(i) / 1000) + " Hz");layout.addView(eqTextView);// 创建一个水平排列组件的LinearLayoutLinearLayout tmpLayout = new LinearLayout(this);tmpLayout.setOrientation(LinearLayout.HORIZONTAL);// 创建显示均衡控制器最小值的TextViewTextView minDbTextView = new TextView(this);minDbTextView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT));// 显示均衡控制器的最小值minDbTextView.setText((minEQLevel / 100) + " dB");// 创建显示均衡控制器最大值的TextViewTextView maxDbTextView = new TextView(this);maxDbTextView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT));// 显示均衡控制器的最大值maxDbTextView.setText((maxEQLevel / 100) + " dB");LinearLayout.LayoutParams layoutParams = newLinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT);layoutParams.weight = 1;// 定义SeekBar作为调整工具SeekBar bar = new SeekBar(this);bar.setLayoutParams(layoutParams);bar.setMax(maxEQLevel - minEQLevel);bar.setProgress(mEqualizer.getBandLevel(i));final short brand = i;// 为SeekBar的拖动事件设置事件监听器bar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {@Overridepublic void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {// 设置该频率的均衡值mEqualizer.setBandLevel(brand,(short) (progress + minEQLevel));}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {}@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {}});// 使用水平排列组件的LinearLayout“盛装”三个组件tmpLayout.addView(minDbTextView);tmpLayout.addView(bar);tmpLayout.addView(maxDbTextView);// 将水平排列组件的LinearLayout添加到myLayout容器中layout.addView(tmpLayout);}}// 初始化重低音控制器private void setupBassBoost() {// 以MediaPlayer的AudioSessionId创建BassBoost// 相当于设置BassBoost负责控制该MediaPlayermBass = new BassBoost(0, mPlayer.getAudioSessionId());// 设置启用重低音效果mBass.setEnabled(true);TextView bbTitle = new TextView(this);bbTitle.setText("重低音:");layout.addView(bbTitle);// 使用SeekBar作为重低音的调整工具SeekBar bar = new SeekBar(this);// 重低音的范围为0~1000bar.setMax(1000);bar.setProgress(0);// 为SeekBar的拖动事件设置事件监听器bar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {@Overridepublic void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {// 设置重低音的强度mBass.setStrength((short) progress);}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {}@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {}});layout.addView(bar);}// 初始化预设音场控制器private void setupPresetReverb() {// 以MediaPlayer的AudioSessionId创建PresetReverb// 相当于设置PresetReverb负责控制该MediaPlayermPresetReverb = new PresetReverb(0,mPlayer.getAudioSessionId());// 设置启用预设音场控制mPresetReverb.setEnabled(true);TextView prTitle = new TextView(this);prTitle.setText("音场");layout.addView(prTitle);// 获取系统支持的所有预设音场for (short i = 0; i < mEqualizer.getNumberOfPresets(); i++) {reverbNames.add(i);reverbVals.add(mEqualizer.getPresetName(i));}// 使用Spinner作为音场选择工具Spinner sp = new Spinner(this);sp.setAdapter(new ArrayAdapter<String>(MainActivity.this,android.R.layout.simple_spinner_item, reverbVals));// 为Spinner的列表项选中事件设置监听器sp.setOnItemSelectedListener(new Spinner.OnItemSelectedListener() {@Overridepublic void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {// 设定音场mPresetReverb.setPreset(reverbNames.get(arg2));}@Overridepublic void onNothingSelected(AdapterView<?> arg0) {}});layout.addView(sp);}@Overrideprotected void onPause() {super.onPause();if (isFinishing() && mPlayer != null) {// 释放所有对象mVisualizer.release();mEqualizer.release();mPresetReverb.release();mBass.release();mPlayer.release();mPlayer = null;}}private static class MyVisualizerView extends View {// bytes数组保存了波形抽样点的值private byte[] bytes;private float[] points;private Paint paint = new Paint();private Rect rect = new Rect();private byte type = 0;public MyVisualizerView(Context context) {super(context);bytes = null;// 设置画笔的属性paint.setStrokeWidth(1f);paint.setAntiAlias(true);paint.setColor(Color.GREEN);paint.setStyle(Style.FILL);}public void updateVisualizer(byte[] ftt) {bytes = ftt;// 通知该组件重绘自己invalidate();}@Overridepublic boolean onTouchEvent(MotionEvent me) {// 当用户触碰该组件时,切换波形类型if (me.getAction() != MotionEvent.ACTION_DOWN) {return false;}type++;if (type >= 3) {type = 0;}return true;}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);if (bytes == null) {return;}// 绘制白色背景(主要为了印刷时好看)canvas.drawColor(Color.WHITE);// 使用rect对象记录该组件的宽度和高度rect.set(0, 0, getWidth(), getHeight());switch (type) {// -------绘制块状的波形图-------case 0:for (int i = 0; i < bytes.length - 1; i++) {float left = getWidth() * i / (bytes.length - 1);// 根据波形值计算该矩形的高度float top = rect.height() - (byte) (bytes[i + 1] + 128)* rect.height() / 128;float right = left + 1;float bottom = rect.height();canvas.drawRect(left, top, right, bottom, paint);}break;// -------绘制柱状的波形图(每隔18个抽样点绘制一个矩形)-------case 1:for (int i = 0; i < bytes.length - 1; i += 18) {float left = rect.width() * i / (bytes.length - 1);// 根据波形值计算该矩形的高度float top = rect.height() - (byte) (bytes[i + 1] + 128)* rect.height() / 128;float right = left + 6;float bottom = rect.height();canvas.drawRect(left, top, right, bottom, paint);}break;// -------绘制曲线波形图-------case 2:// 如果point数组还未初始化if (points == null || points.length < bytes.length * 4) {points = new float[bytes.length * 4];}for (int i = 0; i < bytes.length - 1; i++) {// 计算第i个点的x坐标points[i * 4] = rect.width() * i / (bytes.length - 1);// 根据bytes[i]的值(波形点的值)计算第i个点的y坐标points[i * 4 + 1] = (rect.height() / 2)+ ((byte) (bytes[i] + 128)) * 128/ (rect.height() / 2);// 计算第i+1个点的x坐标points[i * 4 + 2] = rect.width() * (i + 1)/ (bytes.length - 1);// 根据bytes[i+1]的值(波形点的值)计算第i+1个点的y坐标points[i * 4 + 3] = (rect.height() / 2) + ((byte) (bytes[i + 1] + 128)) * 128/ (rect.height() / 2);}// 绘制波形曲线canvas.drawLines(points, paint);break;}}}
}

上面的程序代码定义了4个方法:setupVisualize()、setupEqualizer()、setupBassBoost()和setupPresetReverb(),这4个方法分别创建Visualize、Equalizer、BassBoost和PresetReverb对象,并调用它们的方法控制音乐特效。
上面的Demo中包括了一个MyVisualizerView内部类,该内部类会根据Visualizer传过来的数据动态绘制波形效果。本Demo提供了三种波形:块状波形、柱状波形和曲线波形——当用户单击MyVisualizerView组件时将会切换波形。

  • 注意:最后别忘了在清单文件AndroidManifest.xml里授权音场效果必要的权限。
<!-- 使用音场效果必要的权限 --><uses-permission android:name="android.permission.RECORD_AUDIO" />
  • Demo运行效果截图:



Demo程序源码下载地址

Android移动开发-音乐的示波器、均衡、重低音和音场的实现相关推荐

  1. Android实现音乐示波器、均衡器、重低音和音场功能

    本实例来自于<疯狂Android讲义>,要实现具体的功能,需要了解以下API: MediaPlayer  媒体播放器 Visualizer 频谱 Equalizer 均衡器 BassBoo ...

  2. 我的Android进阶之旅------gt;Android实现音乐示波器、均衡器、重低音和音场功能...

    本实例来自于<疯狂Android讲义>.要实现详细的功能,须要了解下面API: MediaPlayer  媒体播放器 Visualizer 频谱 Equalizer 均衡器 BassBoo ...

  3. Android好书推荐:《Google Android SDK开发范例》

    http://www.jizhuomi.com/android/book/51.html <Google Android SDK开发范例大全(第3版)>采用范例集的形式,由浅入深地带领Go ...

  4. Google Android SDK开发范例大全(第3版)

    查看书籍详细信息: Google Android SDK开发范例大全(第3版)当当网 编辑推荐 Android开发经典畅销书!前两版均为同类最畅销,新版最引人注目的特点是:架构清楚易使用:所有范例程序 ...

  5. 【Android FFMPEG 开发】OpenSLES 播放音频 ( 创建引擎 | 输出混音设置 | 配置输入输出 | 创建播放器 | 获取播放/队列接口 | 回调函数 | 开始播放 | 激活回调 )

    文章目录 I . FFMPEG 播放视频流程 II . OpenSLES 播放音频流程 III . OpenSLES 播放参考 Google 官方示例 IV . OpenSL ES 播放代码 ( 详细 ...

  6. 音乐应用开发Android应用开发--MP3音乐播放器界面设计(2)

    在写这篇文章之前,xxx已写过了几篇关于改音乐应用开发主题的文章,想要了解的朋友可以去翻一下之前的文章 Android应用开发--MP3音乐播放器界面计划(2) 2013年5月25日 简.美音乐播放器 ...

  7. Android应用开发--MP3音乐播放器滚动歌词实现

    Android应用开发--MP3音乐播放器滚动歌词实现 2013年6月2日  简.美音乐播放器开发记录 -----前话 有网友给我博客评论说,让我借鉴好的Android代码,代码贴出来的时候最好整体先 ...

  8. Android应用开发--MP3音乐播放器界面设计(1)

    Android应用开发--MP3音乐播放器界面设计(1)                                           近期突然想自己开发一款MP3播放器,所以就有了上面的界面, ...

  9. android 音乐播放器专辑图片旋转,Android应用开发之简易、大气音乐播放器实现专辑倒影效果...

    今天要实现的功能是实现专辑倒影效果,这个功能已经属于图像处理方面的了,对图像处理我不怎么在行,等一下会介绍一个很实用的工具类,专门用来进行图像处理的.这个工具类不是我写的,我只是拿来用到自己的项目当中 ...

最新文章

  1. 说到心里的哲理个性签名 学生时代的恋爱无非就是陪伴二字
  2. python学习路线-Python最佳学习路线
  3. 区块链系列教程之:比特币中的共识
  4. jieba分词 ‘float‘ object has no attribute ‘decode‘ 解决方法
  5. 苹果A14芯片组件曝光,iPhone 12发布不远了?
  6. FileSystemObject ADO WScript.Shell
  7. python创建字典
  8. xcap发包工具的简单使用3(报文描述)
  9. nginx集群配置流程
  10. 学习c语言编程用什么软件_用C编程
  11. 微信车主服务代扣的坑
  12. 斯坦福NLP名课带学详解 | CS224n 第17讲 - 多任务学习(以问答系统为例)(NLP通关指南·完结)
  13. 大连海事大学计算机20考研(计算机应用 技术)专硕410+经验贴
  14. java 常用框架MP
  15. 输入一行字符,以回车符作为输入结束的标志。统计其中英文字母、数字字符和其他字符的个数。
  16. 操作系统——如何求磁盘的物理地址
  17. 21 | 良心中间商:HTTP的代理服务
  18. 10、HTML基础——列表元素
  19. 新版2022高仿QQ,利用Java swing1:1模仿qq编写的聊天程序
  20. 英企利用人工智能监测员工活动

热门文章

  1. 安装驱动程序时计算机显示缺少.dll文件,驱动程序向导2016如何解决安装驱动程序中缺少的msvcp120.dll文件?...
  2. 使用SDK查看apk文件简单信息:包名、版本
  3. 关于在网页里调整倍速的小技巧
  4. 一款数据可视化分析报表工具
  5. 卷积识别中餐(食物列表)
  6. Python学习笔记_01
  7. 实验与作业(Python)-04 数据类型、数学函数与字符串
  8. 使用Glide加载https网址图片
  9. 远离 996!一位亚马逊程序员的心声
  10. Latex安装与配置