Android播放音乐时跳动的屏谱demo
2013年11月26日 08:16:56 Android ⁄ 共 8317字 暂无评论 ⁄ 被围观 2,214次

Android实现播放音频时的跳动频谱,并实现可以调节的均衡器。

Main.java

  1. package com.wjq.audiofx;
  2. import android.app.Activity;
  3. import android.media.AudioManager;
  4. import android.media.MediaPlayer;
  5. import android.media.audiofx.Equalizer;
  6. import android.media.audiofx.Visualizer;
  7. import android.os.Bundle;
  8. import android.util.Log;
  9. import android.view.Gravity;
  10. import android.view.ViewGroup;
  11. import android.widget.LinearLayout;
  12. import android.widget.SeekBar;
  13. import android.widget.TextView;
  14. public class Main extends Activity {
  15.     private static final String TAG = "AudioFxDemo";
  16.     private static final float VISUALIZER_HEIGHT_DIP = 50f;
  17.     private MediaPlayer mMediaPlayer;
  18.     private Visualizer mVisualizer;
  19.     private Equalizer mEqualizer;//均横器
  20.     private LinearLayout mLinearLayout;
  21.     VisualizerView mVisualizerView;
  22.     private TextView mStatusTextView;
  23.     @Override
  24.     public void onCreate(Bundle icicle) {
  25.         super.onCreate(icicle);
  26.         setVolumeControlStream(AudioManager.STREAM_MUSIC);
  27.         mStatusTextView = new TextView(this);
  28.         mLinearLayout = new LinearLayout(this);
  29.         mLinearLayout.setOrientation(LinearLayout.VERTICAL);
  30.         mLinearLayout.addView(mStatusTextView);
  31.         setContentView(mLinearLayout);
  32.         // Create the MediaPlayer
  33.         mMediaPlayer = MediaPlayer.create(this, R.raw.test_cbr);
  34.         ifnull == mMediaPlayer )
  35.             return ;
  36.         Log.d(TAG, "MediaPlayer audio session ID: " + mMediaPlayer.getAudioSessionId());
  37.         setupVisualizerFxAndUI();
  38.         setupEqualizerFxAndUI();
  39.         // Make sure the visualizer is enabled only when you actually want to receive data, and
  40.         // when it makes sense to receive data.
  41.         mVisualizer.setEnabled(true);
  42.         // When the stream ends, we don't need to collect any more data. We don't do this in
  43.         // setupVisualizerFxAndUI because we likely want to have more, non-Visualizer related code
  44.         // in this callback.
  45.         mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
  46.             public void onCompletion(MediaPlayer mediaPlayer) {
  47.                 mVisualizer.setEnabled(false);
  48.             }
  49.         });
  50.         mMediaPlayer.start();
  51.         mStatusTextView.setText("播放音频...");
  52.     }
  53.     /**
  54.      * 通过mMediaPlayer返回的AudioSessionId创建一个优先级为0均衡器对象,并且通过频谱生成相应的UI和对应的事件
  55.      */
  56.     private void setupEqualizerFxAndUI() {
  57.         mEqualizer = new Equalizer(0, mMediaPlayer.getAudioSessionId());
  58.         // 启用均衡器
  59.         mEqualizer.setEnabled(true);
  60.         TextView eqTextView = new TextView(this);
  61.         eqTextView.setText("均横器:");
  62.         mLinearLayout.addView(eqTextView);
  63.         // 通过均衡器得到其支持的频谱引擎
  64.         short bands = mEqualizer.getNumberOfBands();
  65.         // getBandLevelRange是一个数组,返回一组频谱等级数组,返回一组频谱等级数组
  66.         // 第一个下标为最低的限度范围,第二个下标为最高的限度范围
  67.         // 依次取出
  68.         final short minEQLevel = mEqualizer.getBandLevelRange()[0];
  69.         final short maxEQLevel = mEqualizer.getBandLevelRange()[1];
  70.         for (short i = 0; i < bands; i++) {
  71.             final short band = i;
  72.             TextView freqTextView = new TextView(this);
  73.             freqTextView.setLayoutParams(new ViewGroup.LayoutParams(
  74.                     ViewGroup.LayoutParams.FILL_PARENT,
  75.                     ViewGroup.LayoutParams.WRAP_CONTENT));
  76.             freqTextView.setGravity(Gravity.CENTER_HORIZONTAL);
  77.             freqTextView.setText((mEqualizer.getCenterFreq(band) / 1000) + " Hz");
  78.             mLinearLayout.addView(freqTextView);
  79.             LinearLayout row = new LinearLayout(this);
  80.             row.setOrientation(LinearLayout.HORIZONTAL);
  81.             TextView minDbTextView = new TextView(this);
  82.             minDbTextView.setLayoutParams(new ViewGroup.LayoutParams(
  83.                     ViewGroup.LayoutParams.WRAP_CONTENT,
  84.                     ViewGroup.LayoutParams.WRAP_CONTENT));
  85.             minDbTextView.setText((minEQLevel / 100) + " dB");
  86.             TextView maxDbTextView = new TextView(this);
  87.             maxDbTextView.setLayoutParams(new ViewGroup.LayoutParams(
  88.                     ViewGroup.LayoutParams.WRAP_CONTENT,
  89.                     ViewGroup.LayoutParams.WRAP_CONTENT));
  90.             maxDbTextView.setText((maxEQLevel / 100) + " dB");
  91.             LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
  92.                     ViewGroup.LayoutParams.FILL_PARENT,
  93.                     ViewGroup.LayoutParams.WRAP_CONTENT);
  94.             layoutParams.weight = 1;
  95.             SeekBar bar = new SeekBar(this);
  96.             bar.setLayoutParams(layoutParams);
  97.             bar.setMax(maxEQLevel - minEQLevel);
  98.             bar.setProgress(mEqualizer.getBandLevel(band));
  99.             bar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
  100.                 public void onStopTrackingTouch(SeekBar seekBar) {}
  101.                 public void onStartTrackingTouch(SeekBar seekBar) {}
  102.                 public void onProgressChanged(SeekBar seekBar, int progress,
  103.                         boolean fromUser) {
  104.                     mEqualizer.setBandLevel(band, (short) (progress + minEQLevel));
  105.                 }
  106.             });
  107.             row.addView(minDbTextView);
  108.             row.addView(bar);
  109.             row.addView(maxDbTextView);
  110.             mLinearLayout.addView(row);
  111.         }
  112.     }
  113.     /**
  114.      * 生成一个VisualizerView对象,使音频频谱的波段能够反映到 VisualizerView上
  115.      */
  116.     private void setupVisualizerFxAndUI() {
  117.         mVisualizerView = new VisualizerView(this);
  118.         mVisualizerView.setLayoutParams(new ViewGroup.LayoutParams(
  119.                 ViewGroup.LayoutParams.FILL_PARENT,
  120.                 (int)(VISUALIZER_HEIGHT_DIP * getResources().getDisplayMetrics().density)));
  121.         mLinearLayout.addView(mVisualizerView);
  122.         int sessId = mMediaPlayer.getAudioSessionId() ;
  123.         mVisualizer = new Visualizer(sessId);
  124.         // 参数必须是2的位数
  125.         mVisualizer.setCaptureSize(Visualizer.getCaptureSizeRange()[1]);
  126.         // 设置允许波形表示,并且捕获它
  127.         mVisualizer.setDataCaptureListener(new Visualizer.OnDataCaptureListener() {
  128.             public void onWaveFormDataCapture(Visualizer visualizer, byte[] bytes,
  129.                     int samplingRate) {
  130.                 mVisualizerView.updateVisualizer(bytes);
  131.             }
  132.             public void onFftDataCapture(Visualizer visualizer, byte[] bytes, int samplingRate) {}
  133.         }, Visualizer.getMaxCaptureRate() / 2truefalse);
  134.     }
  135.     @Override
  136.     protected void onPause() {
  137.         super.onPause();
  138.         if (isFinishing() && mMediaPlayer != null) {
  139.             mVisualizer.release();
  140.             mEqualizer.release();
  141.             mMediaPlayer.release();
  142.             mMediaPlayer = null;
  143.         }
  144.     }
  145. }

 

VisualizerView.java

  1. package com.wjq.audiofx;
  2.  import android.content.Context;
  3.  import android.graphics.Canvas;
  4.  import android.graphics.Color;
  5.  import android.graphics.Paint;
  6.  import android.graphics.Rect;
  7.  import android.view.View;
  8.  public class VisualizerView extends View {
  9.         private byte[] mBytes;
  10.          private float[] mPoints;
  11.          //矩形区域
  12.          private Rect mRect = new Rect();
  13.          // 画笔
  14.          private Paint mForePaint = new Paint();
  15.          // 初始化画笔
  16.          private void init() {
  17.              mBytes = null;
  18.              mForePaint.setStrokeWidth(1f);
  19.              mForePaint.setAntiAlias(true);
  20.              mForePaint.setColor(Color.GREEN);
  21.          }
  22.          public VisualizerView(Context context) {
  23.              super(context);
  24.              init();
  25.          }
  26.          public void updateVisualizer(byte[] bytes) {
  27.              mBytes = bytes;
  28.              invalidate();
  29.          }
  30.          @Override
  31.          protected void onDraw(Canvas canvas) {
  32.              super.onDraw(canvas);
  33.              if (mBytes == null) {
  34.                  return;
  35.              }
  36.              if (mPoints == null || mPoints.length < mBytes.length * 4) {
  37.                  mPoints = new float[mBytes.length * 4];
  38.              }
  39.              mRect.set(00, getWidth(), getHeight());
  40.              for (int i = 0; i < mBytes.length - 1; i++) {
  41.                  mPoints[i * 4] = mRect.width() * i / (mBytes.length - 1);
  42.                  mPoints[i * 4 + 1] = mRect.height() / 2
  43.                          + ((byte) (mBytes[i] + 128)) * (mRect.height() / 2) / 128;
  44.                  mPoints[i * 4 + 2] = mRect.width() * (i + 1) / (mBytes.length - 1);
  45.                  mPoints[i * 4 + 3] = mRect.height() / 2
  46.                          + ((byte) (mBytes[i + 1] + 128)) * (mRect.height() / 2) / 128;
  47.              }
  48.              canvas.drawLines(mPoints, mForePaint);
  49.          }
  50.  }

 

给我留言

留言无头像?