音乐播放曲谱图(柱形和曲线图谱)

来源:互联网 发布:算法导论 第三版 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