音乐播放曲谱图(柱形和曲线图谱)
来源:互联网 发布:算法导论 第三版 azw3 编辑:程序博客网 时间:2024/04/28 09:49
一、柱形图谱
MainActivity.class
package im.com.work.qupudemo;import android.content.Intent;import android.media.AudioManager;import android.media.MediaPlayer;import android.media.audiofx.Visualizer;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.view.View;import android.view.ViewGroup;import android.widget.Button;import android.widget.LinearLayout;public class ZhuxingActivity extends AppCompatActivity { Button qxbtn1; private static final String TAG = "AudioFxActivity"; private static final float VISUALIZER_HEIGHT_DIP = 50f; private MediaPlayer mMediaPlayer; private Visualizer mVisualizer; BaseVisualizerView mBaseVisualizerView; LinearLayout ll; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_zhuxing); qxbtn1 = (Button) findViewById(R.id.qxbtn1); ll = (LinearLayout) findViewById(R.id.ll); setVolumeControlStream(AudioManager.STREAM_MUSIC); mMediaPlayer = MediaPlayer.create(this, R.raw.test); setupVisualizerFxAndUi(); mVisualizer.setEnabled(true); mMediaPlayer.start(); mMediaPlayer.setLooping(true); mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { public void onCompletion(MediaPlayer mediaPlayer) { mVisualizer.setEnabled(false); } }); qxbtn1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mMediaPlayer.stop(); Intent intent =new Intent(ZhuxingActivity.this,MainActivity.class); startActivity(intent); } }); } /** * 生成一个VisualizerView对象,使音频频谱的波段能够反映到 VisualizerView上 */ private void setupVisualizerFxAndUi() { mBaseVisualizerView = new BaseVisualizerView(this); mBaseVisualizerView.setLayoutParams(new ViewGroup.LayoutParams( ViewGroup.LayoutParams.FILL_PARENT, (int) (VISUALIZER_HEIGHT_DIP * getResources() .getDisplayMetrics().density))); ll.addView(mBaseVisualizerView); mVisualizer = new Visualizer(mMediaPlayer.getAudioSessionId()); // 参数内必须是2的位数 mVisualizer.setCaptureSize(Visualizer.getCaptureSizeRange()[1]); // 设置允许波形表示,并且捕获它 mBaseVisualizerView.setVisualizer(mVisualizer); } @Override protected void onPause() { // TODO Auto-generated method stub super.onPause(); if (isFinishing() && mMediaPlayer != null) { mMediaPlayer.stop(); mVisualizer.release(); mMediaPlayer.release(); mMediaPlayer = null; } }}
VisualizerView.class
package im.com.work.qupudemo;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Rect;import android.view.View;/** * Created by 何 礼 波 on 2017/1/2. */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); }}
BaseVisualizerView.class
package im.com.work.qupudemo;import android.content.Context;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.Paint.Cap;import android.graphics.Paint.Join;import android.media.audiofx.Visualizer;import android.view.View;public class BaseVisualizerView extends View implements Visualizer.OnDataCaptureListener{ private static final int DN_W = 480; private static final int DN_H = 160; private static final int DN_SL =14; private static final int DN_SW = 6; private int hgap = 0; private int vgap = 0; private int levelStep = 0; private float strokeWidth = 0; private float strokeLength = 0; /** * It is the max level. */ protected final static int MAX_LEVEL = 13; /** * It is the cylinder number. */ protected final static int CYLINDER_NUM = 20; /** * It is the visualizer. */ protected Visualizer mVisualizer = null; /** * It is the paint which is used to draw to visual effect. */ protected Paint mPaint = null; /** * It is the buffer of fft. */ protected byte[] mData = new byte[CYLINDER_NUM]; boolean mDataEn = true; /** * It constructs the base visualizer view. * @param context It is the context of the view owner. */ public BaseVisualizerView(Context context) { super(context); mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setColor(0xFFd60d25);//0x3001FFFF 0xFFd60d25 mPaint.setStrokeJoin(Join.ROUND); mPaint.setStrokeCap(Cap.ROUND); } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); float w, h, xr, yr; w = right - left; h = bottom - top; xr = w / (float)DN_W; yr = h / (float)DN_H; strokeWidth = DN_SW * yr; strokeLength = DN_SL * xr; hgap = (int)((w - strokeLength * CYLINDER_NUM) / (CYLINDER_NUM + 1) ); vgap = (int)(h / (MAX_LEVEL + 2)); mPaint.setStrokeWidth(strokeWidth); } protected void drawCylinder(Canvas canvas, float x, byte value) { if (value < 0) value = 0; for (int i = 0; i < value; i++) { float y = getHeight() - i * vgap - vgap; canvas.drawLine(x, y, x + strokeLength, y, mPaint); } } @Override public void onDraw(Canvas canvas) { for (int i = 0; i < CYLINDER_NUM; i ++) { drawCylinder(canvas, strokeWidth / 2 + hgap + i * (hgap + strokeLength), mData[i]); } } /** * It sets the visualizer of the view. DO set the viaulizer to null when exit the program. * @parma visualizer It is the visualizer to set. */ public void setVisualizer(Visualizer visualizer) { if (visualizer != null) { if (!visualizer.getEnabled()) { visualizer.setCaptureSize(Visualizer.getCaptureSizeRange()[0]); } levelStep = 128 / MAX_LEVEL; visualizer.setDataCaptureListener(this, Visualizer.getMaxCaptureRate() / 2, false, true); } else { if (mVisualizer != null) { mVisualizer.setEnabled(false); mVisualizer.release(); } } mVisualizer = visualizer; } @Override public void onFftDataCapture(Visualizer visualizer, byte[] fft, int samplingRate) { byte[] model = new byte[fft.length / 2 + 1]; if (mDataEn) { model[0] = (byte) Math.abs(fft[1]); int j = 1; for (int i = 2; i < fft.length;) { model[j] = (byte) Math.hypot(fft[i], fft[i + 1]); i += 2; j++; } } else { for (int i = 0; i < CYLINDER_NUM; i ++) { model[i] = 0; } } for (int i = 0; i < CYLINDER_NUM; i ++) { final byte a = (byte)(Math.abs(model[CYLINDER_NUM - i]) / levelStep); final byte b = mData[i]; if (a > b) { mData[i] = a; } else { if (b > 0) { mData[i]--; } } } postInvalidate(); } @Override public void onWaveFormDataCapture(Visualizer visualizer, byte[] waveform, int samplingRate) { // Do nothing. } /** * It enables or disables the data processs. * @param en If this value is true it enables the data process.. */ public void enableDataProcess(boolean en) { mDataEn = en; }}
activity_zhuxing.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="im.com.work.qupudemo.ZhuxingActivity"><Button android:id="@+id/qxbtn1" android:text="曲线图" android:layout_width="match_parent" android:layout_height="wrap_content" /> <LinearLayout android:id="@+id/ll" android:layout_width="200dp" android:background="#000" android:layout_height="match_parent" android:layout_gravity="center" android:orientation="vertical"> </LinearLayout></LinearLayout>
AndroidManifest.xml
记得加权限(有些手机加了权限后还要去手机“设置”那,应用的权限打开)
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /><uses-permission android:name="android.permission.RECORD_AUDIO" />
2、曲线曲谱
package im.com.work.qupudemo;import android.media.AudioManager;import android.media.MediaPlayer;import android.media.audiofx.Visualizer;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.view.ViewGroup;import android.widget.LinearLayout;public class MainActivity extends AppCompatActivity { private static final String TAG = "AudioFxDemo"; private static final float VISUALIZER_HEIGHT_DIP = 50f; private MediaPlayer mMediaPlayer; private Visualizer mVisualizer; private LinearLayout mLinearLayout; VisualizerView mVisualizerView;; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); setVolumeControlStream(AudioManager.STREAM_MUSIC); mLinearLayout = new LinearLayout(this); mLinearLayout.setOrientation(LinearLayout.VERTICAL); setContentView(mLinearLayout); // Create the MediaPlayer mMediaPlayer = MediaPlayer.create(this, R.raw.test); if( null == mMediaPlayer ) return ; setupVisualizerFxAndUI(); mVisualizer.setEnabled(true); mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { public void onCompletion(MediaPlayer mediaPlayer) { mVisualizer.setEnabled(false); } }); mMediaPlayer.start(); } /** * 生成一个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(); mMediaPlayer.release(); mMediaPlayer = null; } }}
Demo下载地址: http://download.csdn.net/detail/pigseesunset/9728509
1 0
- 音乐播放曲谱图(柱形和曲线图谱)
- 音乐 和视频播放
- html播放音乐和视频
- AndEngine播放音乐和音效
- 播放和暂停音乐log
- MediaPlayer播放音乐和视频
- iOS音效和音乐播放
- qt phonon 制作音乐播放器学习(怎样让播放进度条和音乐播放时长同步)
- Android本地及网络音乐播放器-网络音乐的试听和下载(四)
- 基于android的网络音乐播放器-网络音乐的搜索和展示(五)
- ios播放音乐(短音乐,长音乐)
- android 音乐播放器(播放,停止)
- 简易音乐播放器(本地播放)
- Unity播放音乐(MP3)
- Matlab播放音频文件(音乐)!
- 音乐播放器(上)
- MediaPlayer(音乐播放器)
- Android 音乐播放(多媒体)
- BLE-NRF51822教程3-sdk程序框架剖析
- Xmanager 5 远程连接linux图形界面
- JSP:Multiple annotations found at this line 解决
- JESD204B 参数理解
- 执子之手,与子偕老
- 音乐播放曲谱图(柱形和曲线图谱)
- Linux 输出流重定向缓冲设置
- ANSYS/APDL编程八讲(目录)
- ida动态调试笔记
- python创建型设计模式——原型模式、单例模式
- JDBC基础知识
- visualsvn manager
- kotlin调用方法中有形参为数组的方法(函数)
- BLE-NRF51822教程4-串口BLE解析