Android编程之播放器MediaPlayer实现均衡器效果示例
作者:迟做总比不做强 发布时间:2022-02-25 11:52:32
标签:Android,播放器,MediaPlayer
本文实例讲述了Android播放器MediaPlayer实现均衡器效果。分享给大家供大家参考,具体如下:
这几天在系统学习Android官方API Demos,看到实现均衡器效果,就把官方API中代码copy下来,根据网上前辈的指引略有修改,添加了注释。
public class AudioFxDemo extends Activity {
private static final String TAG = "AudioFxDemo";
private static final float VISUALIZER_HEIGHT_DIP = 50f;
// 定义播放器
private MediaPlayer mMediaPlayer;
// 定义系统的频谱
private Visualizer mVisualizer;
// 定义系统的均衡器
private Equalizer mEqualizer;
private LinearLayout mLinearLayout;
private VisualizerView mVisualizerView;
private TextView mStatusTextView;
@Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
// 音量控制
setVolumeControlStream(AudioManager.STREAM_MUSIC);
mStatusTextView = new TextView(this);
mLinearLayout = new LinearLayout(this);
mLinearLayout.setOrientation(LinearLayout.VERTICAL);
mLinearLayout.addView(mStatusTextView);
setContentView(mLinearLayout);
// 创建MediaPlayer对象
mMediaPlayer = MediaPlayer.create(this, R.raw.test_cbr);
Log.d(TAG,
"MediaPlayer audio session ID: "
+ mMediaPlayer.getAudioSessionId());
// 设置频谱显示
setupVisualizerFxAndUI();
// 设置示波器显示
setupEqualizerFxAndUI();
// Make sure the visualizer is enabled only when you actually want to
// receive data, and
// when it makes sense to receive data.
mVisualizer.setEnabled(true);
// When the stream ends, we don't need to collect any more data. We
// don't do this in
// setupVisualizerFxAndUI because we likely want to have more,
// non-Visualizer related code
// in this callback.
mMediaPlayer
.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer mediaPlayer) {
mVisualizer.setEnabled(false);
mStatusTextView.setText("播放结束");
}
});
mMediaPlayer.start();
mStatusTextView.setText("正在播放中");
}
private void setupEqualizerFxAndUI() {
// Create the Equalizer object (an AudioEffect subclass) and attach it
// to our media player,
// with a default priority (0).
mEqualizer = new Equalizer(0, mMediaPlayer.getAudioSessionId());
mEqualizer.setEnabled(true);
TextView eqTextView = new TextView(this);
eqTextView.setText("Equalizer:");
mLinearLayout.addView(eqTextView);
short bands = mEqualizer.getNumberOfBands();
final short minEQLevel = mEqualizer.getBandLevelRange()[0];
final short maxEQLevel = 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.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
freqTextView.setGravity(Gravity.CENTER_HORIZONTAL);
freqTextView.setText((mEqualizer.getCenterFreq(band) / 1000)
+ " Hz");
mLinearLayout.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((minEQLevel / 100) + " dB");
TextView 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 = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
layoutParams.weight = 1;
SeekBar bar = new SeekBar(this);
bar.setLayoutParams(layoutParams);
bar.setMax(maxEQLevel - minEQLevel);
bar.setProgress(mEqualizer.getBandLevel(band));
bar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
mEqualizer.setBandLevel(band,
(short) (progress + minEQLevel));
}
public void onStartTrackingTouch(SeekBar seekBar) {
}
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
row.addView(minDbTextView);
row.addView(bar);
row.addView(maxDbTextView);
mLinearLayout.addView(row);
}
}
private void setupVisualizerFxAndUI() {
// Create a VisualizerView (defined below), which will render the
// simplified audio
// wave form to a Canvas.
mVisualizerView = new VisualizerView(this);
mVisualizerView.setLayoutParams(new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
(int) (VISUALIZER_HEIGHT_DIP * getResources()
.getDisplayMetrics().density)));
mLinearLayout.addView(mVisualizerView);
// Create the Visualizer object and attach it to our media player.
mVisualizer = new Visualizer(mMediaPlayer.getAudioSessionId());
mVisualizer.setCaptureSize(Visualizer.getCaptureSizeRange()[1]);
mVisualizer.setDataCaptureListener(
new Visualizer.OnDataCaptureListener() {
public void onWaveFormDataCapture(Visualizer visualizer,
byte[] bytes, int samplingRate) {
mVisualizerView.updateVisualizer(bytes);
}
public void onFftDataCapture(Visualizer visualizer,
byte[] bytes, int samplingRate) {
}
}, Visualizer.getMaxCaptureRate() / 2, true, false);
}
@Override
protected void onPause() {
super.onPause();
if (isFinishing() && mMediaPlayer != null) {
mVisualizer.release();
mEqualizer.release();
mMediaPlayer.release();
mMediaPlayer = null;
}
}
}
/**
* 绘制波状View
*
* @description:
* @author ldm
* @date 2016-4-20 上午9:11:49
*/
class VisualizerView extends View {
// 数组保存了波形抽样点的值
private byte[] bytes;
private float[] points;
// 定义画笔
private Paint paint = new Paint();
// 矩形区域
private Rect rect = new Rect();
private byte type = 0;
public VisualizerView(Context context) {
super(context);
bytes = null;
// 设置画笔的属性
paint.setStrokeWidth(1f);// 设置空心线宽
paint.setAntiAlias(true);// 抗锯齿
paint.setColor(Color.BLUE);// 画笔颜色
paint.setStyle(Style.STROKE);// 非填充模式
}
public void updateVisualizer(byte[] ftt) {
bytes = ftt;
// 通知组件重绘
invalidate();
}
@Override
public boolean onTouchEvent(MotionEvent me) {
// 当用户触碰该组件时,切换波形类型
if (me.getAction() != MotionEvent.ACTION_DOWN) {
return false;
}
type++;
if (type >= 3) {
type = 0;
}
return true;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (bytes == null) {
return;
}
// 绘制黑色背景
canvas.drawColor(Color.BLACK);
// 使用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;
}
}
}
自己新建 项目时,记得在res/raw下添加一个名为test_cbr的mp3格式文件。
希望本文所述对大家Android程序设计有所帮助。
来源:http://blog.csdn.net/true100/article/details/51197896
0
投稿
猜你喜欢
- 相同点:1. ref 和 out 都是按地址传递的,使用后都将改变原来参数的数值;2. 方法定义和调用方法都必须显式使用 ref 或者 ou
- 本文以在chart控件上和窗体上画矩形为例子讲述了C# GDI在控件上绘图的方法。分享给大家供大家参考。具体方法如下:具体的实现方法就不多解
- java沙箱环境测试支付宝支付接口?准备工作,登陆支付宝开放平台,进入沙箱环境开放平台链接:https://developers.alipa
- 1、悲观锁悲观锁假设最坏的情况(如果果你不锁门,那么捣蛋鬼就会闯入并搞得一团糟),只有在确保其他线程不受干扰(获得正确的锁)的情况下才能执行
- 有很多制作精良的APP都自带点击音效,那么如何简单的来实现这一效果,这里需要使用到的一个概念叫做SoundPool,这个类主要用于播放一些比
- XmlTextWriter类允许你将XML写到一个文件中去。这个类包含了很多方法和属性,使用这些属性和方法可以使你更容易地处理XML。为了使
- 本文实例讲述了Java正则验证电话,手机,邮箱,日期,金额的方法。分享给大家供大家参考,具体如下:package com.hooypay.t
- Android透明状态栏只有在4.4之后有。在代码中加入下面几行代码即可实现来源:http://www.cnblogs.com/wangxi
- 引言java 7提供了另外一个很有用的线程池框架,Fork/Join框架理论Fork/Join框架主要有以下两个类组成. * ForkJoi
- 控制器Controller控制器复杂提供访问应用程序的行为,通常通过接口定义或注解定义两种方法实现。控制器负责解析用户的请求并将其转换为一个
- 对称加密算法是应用较早的加密算法,技术成熟。在对称加密算法中,数据发信方将明文(原始数据)和加密密钥(mi yue)一起经过特殊加密算法处理
- ScrollView可实现控件在超出屏幕范围的情况下滚动显示。用法:在XML文件中将需滚动的控件包含在ScrollView中,当控件超出屏幕
- 1. 前言ResultSetMetaData 叫元数据,是数据库 列对象,以列为单位封装为对象。元数据,指的是其包含列名,列值,列类型,列长
- Java高德地图Api的使用使用高德经纬度获取地址信息一些准备用到的常量 /** *
- INotifyPropertyChanged:该接口包含一个事件, 针对属性发生变更时, 执行该事件发生。// /
- 多态是同一个行为具有多个不同表现形式或形态的能力。多态性意味着有多重形式。在面向对象编程范式中,多态性往往表现为"一个接口,多个功
- 一、安装本地Maven选择你需要的maven版本下载:官网下载传送门我使用的是3.6.1版本:maven-3.6.1-bin.zip&nbs
- 在Java移动文件夹及其所有子文件与子文件夹可以有如下的一段简单的方法来说明:public static void moveFolder(S
- Spring容器中的Bean是否线程安全,容器本身并没有提供Bean的线程安全策略,因此可以说Spring容器中的Bean本身不具备线程安全
- Ping pingSender = new Ping(); PingReply reply = pingSender.Send("