Android播放音乐时跳动的屏谱demo
Android实现播放音频时的跳动频谱,并实现可以调节的均衡器。
Main.java
- package com.wjq.audiofx;
- import android.app.Activity;
- import android.media.AudioManager;
- import android.media.MediaPlayer;
- import android.media.audiofx.Equalizer;
- import android.media.audiofx.Visualizer;
- import android.os.Bundle;
- import android.util.Log;
- import android.view.Gravity;
- import android.view.ViewGroup;
- import android.widget.LinearLayout;
- import android.widget.SeekBar;
- import android.widget.TextView;
- public class Main 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;
- VisualizerView mVisualizerView;
- private TextView mStatusTextView;
- @Override
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
- setVolumeControlStream(AudioManager.STREAM_MUSIC);
- mStatusTextView = new TextView(this);
- mLinearLayout = new LinearLayout(this);
- mLinearLayout.setOrientation(LinearLayout.VERTICAL);
- mLinearLayout.addView(mStatusTextView);
- setContentView(mLinearLayout);
- // Create the MediaPlayer
- mMediaPlayer = MediaPlayer.create(this, R.raw.test_cbr);
- if( null == mMediaPlayer )
- return ;
- 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);
- }
- });
- mMediaPlayer.start();
- mStatusTextView.setText("播放音频...");
- }
- /**
- * 通过mMediaPlayer返回的AudioSessionId创建一个优先级为0均衡器对象,并且通过频谱生成相应的UI和对应的事件
- */
- private void setupEqualizerFxAndUI() {
- mEqualizer = new Equalizer(0, mMediaPlayer.getAudioSessionId());
- // 启用均衡器
- mEqualizer.setEnabled(true);
- TextView eqTextView = new TextView(this);
- eqTextView.setText("均横器:");
- mLinearLayout.addView(eqTextView);
- // 通过均衡器得到其支持的频谱引擎
- short bands = mEqualizer.getNumberOfBands();
- // getBandLevelRange是一个数组,返回一组频谱等级数组,返回一组频谱等级数组
- // 第一个下标为最低的限度范围,第二个下标为最高的限度范围
- // 依次取出
- 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.FILL_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.FILL_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 onStopTrackingTouch(SeekBar seekBar) {}
- public void onStartTrackingTouch(SeekBar seekBar) {}
- public void onProgressChanged(SeekBar seekBar, int progress,
- boolean fromUser) {
- mEqualizer.setBandLevel(band, (short) (progress + minEQLevel));
- }
- });
- row.addView(minDbTextView);
- row.addView(bar);
- row.addView(maxDbTextView);
- mLinearLayout.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)));
- mLinearLayout.addView(mVisualizerView);
- int sessId = mMediaPlayer.getAudioSessionId() ;
- mVisualizer = new Visualizer(sessId);
- // 参数必须是2的位数
- 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;
- }
- }
- }
VisualizerView.java
- package com.wjq.audiofx;
- import android.content.Context;
- import android.graphics.Canvas;
- import android.graphics.Color;
- import android.graphics.Paint;
- import android.graphics.Rect;
- import android.view.View;
- public class VisualizerView extends View {
- private byte[] mBytes;
- private float[] mPoints;
- //矩形区域
- private Rect mRect = new Rect();
- // 画笔
- private Paint mForePaint = new Paint();
- // 初始化画笔
- private void init() {
- mBytes = null;
- mForePaint.setStrokeWidth(1f);
- mForePaint.setAntiAlias(true);
- mForePaint.setColor(Color.GREEN);
- }
- public VisualizerView(Context context) {
- super(context);
- init();
- }
- public void updateVisualizer(byte[] bytes) {
- mBytes = bytes;
- invalidate();
- }
- @Override
- protected void onDraw(Canvas canvas) {
- 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, mForePaint);
- }
- }
Android播放音乐时跳动的屏谱demo的更多相关文章
- android 播放视频时切换全屏隐藏状态栏
1. Demo: @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstance ...
- android 播放音乐-进度条
今天学渣研究了一下使用MediaPlayer播放音乐时加入进度条,进度条如今用的是android自带的seekbar,后期会跟换UI的,在之前可以播放音乐的基础上,如今加入的主要功能有两个: 1实时显 ...
- 绘制播放音乐时的音波图形的View
绘制播放音乐时的音波图形的View 这个效果类似于这个哦: 效果如下: 源码: MusicView.h 与 MusicView.m // // MusicView.h // Music // // C ...
- android 播放音乐媒体文件(一)
Audio formats and codecs Format / Codec Encoder Decoder Details Supported File Type(s) / Container F ...
- Android 播放电影时滑动屏幕调整屏幕亮度(转)
(转自:http://blog.csdn.net/piaozhiye/article/details/6544450) 发现有一些主流的播放器播放电影时可以通过滑动屏幕调整屏幕亮度,其实实现起来也很容 ...
- 关于Windows 8使用WMP播放音乐时WUDFHost跑CPU和硬盘的问题解决
Windows 8使用Windows Media Player播放音乐的时候.事实上有一个这种情况,WMP和某个什么名字看起来非常屌的进程跑CPU非常高,这个跑非常高视你插入的SD卡内的文件数或者移动 ...
- android修改系统时系统黑屏时不进入休眠状态
基于android4.4修改,在frameworks/base/services/java/com/android/server/power/PowerManagerService.java里,查看休 ...
- android关闭屏幕时不锁屏实现
所需权限: <uses-permission android:name="android.permission.DISABLE_KEYGUARD"/> 关闭系统锁屏服务 ...
- 解决Android Activity切换时出现白屏问题
有些性能低的机器,在切换activity时候出现白屏一段时候后才显示正确的视图 高性能的机器可能太快看不到,但是事实是存在的, 特别是当你新开一个进程的时候,A进程的activity跳转到B进程的Ac ...
随机推荐
- POJ 1410 Intersection(线段相交&&推断点在矩形内&&坑爹)
Intersection 大意:给你一条线段,给你一个矩形,问是否相交. 相交:线段全然在矩形内部算相交:线段与矩形随意一条边不规范相交算相交. 思路:知道详细的相交规则之后题事实上是不难的,可是还有 ...
- hdu1698 Just a Hook 线段树:成段替换,总区间求和
转载请注明出处:http://blog.csdn.net/u012860063 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1698 Problem ...
- log4j:ERROR Could not find value for key log4j.appender.error
我是在rootLogger末尾增加R就好了. 终于我的配置环境例如以下: #设置日志的级别 ,多个以,分开(没有给出的,则不会被输出) log4j.rootLogger=info,error,R #D ...
- Sprintf()的思考和引出的相关问题
Sprintf()为什么不安全? 功能 把格式化的数据写入某个 字符串 缓冲区. 头文件 stdio.h 原型 int sprintf( char *buffer, const char *forma ...
- pkg_zhgl
CREATE OR REPLACE PACKAGE BODY PKG_ZHGL AS --账户管理包 code szn 20110829 --账户管理服务包 --定义本包中需要引用到的常量 --定义说 ...
- django ImageField用法
settings里的设置 PROJECT_ROOT = os.path.abspath(os.path.join(os.path.dirname('__file__'))) MEDIA_ROOT = ...
- Tcl语言笔记之二
1,表达式 1.1 操作数 TCL表达式的操作数通常是整数或实数.整数一般是十进制的, 但如果整数的第一个字符是0(zero),那么TCL将把这个整数看作八进制的,如果前两个字符是0x则这个整数被看作 ...
- django学习之Model(四)MakingQuery
上一篇写到MakingQuey中的filter,本篇接着来. 10)-扩展多值的关系 如果对一个ManyToManyField或ForeignKey的表进行filter过滤查询的话,有2中方法可以用. ...
- html中事件处理中的this和event对象
在用js编写页面事件处理代码时,会经常涉及到this和event对象,但有时在采用不同的事件处理,尤其是在与自定义的对象关联时,这些对象的指向变的有些复杂. 本文来详细介绍下各种场景下 这些对象 真正 ...
- android之IntentFilter的用法_Intent.ACTION_TIME_TICK在manifest.xml不起作用
在模仿一个天气预报的widget时候,用到了IntentFilter,感觉在manifest.xml注册的receiver跟用代码写registerReceiver()的效果应该是相同的,于是想证明一 ...