2.3之后,Google 为Mediaplayer 类添加了EQ支持,如果你需要使用这个EQ功能,有两点需要注意,分别为如下:

  • 在配置文件中设置最小的SDK版本为9
  • 添加权限android.permission.RECORD_AUDIO 即可使用,具体的使用方法,下文会介绍

为了使应用程序能够支持波段变化,我们需要重新定义一个VIEW对象,在onDraw 方法画频谱,代码如下:

 

class  VisualizerView extends View {

        
private   byte [] mBytes;
        
private   float [] mPoints;
        
//  矩形区域
         private  Rect mRect  =   new  Rect();
        
//  画笔
         private  Paint mPaint  =   new  Paint();

        
//  初始化画笔
         private   void  init() {
            mBytes 
=   null ;
            mPaint.setStrokeWidth(1f);
            mPaint.setAntiAlias(
true );
            mPaint.setColor(Color.BLUE);
        }

        
public  VisualizerView(Context context) {
            super(context);
            init();
        }

        
public   void  updateVisualizer( byte [] mbyte) {
            mBytes 
=  mbyte;
            invalidate();
        }

        @Override
        
protected   void  onDraw(Canvas canvas) {
            
//  TODO Auto-generated method stub
            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, mPaint);
        }
    }

 

 

另外,为了使用EQ和频谱可视化,我们必须了解以下两个类:

  • Visualizer
    此类能使应用程序获取当前有效的一部分音频可视化的目的。使用此类必须添加上面提到的权限。
  • Equalizer
    一个均衡器的类,使用此类可以轻松的操纵音频的频段,和输出的混合 。

具体使用代码和注释见下面:

 

/* *
     * 通过mMediaPlayer返回的AudioSessionId创建一个优先级为0均衡器对象 并且通过频谱生成相应的UI和对应的事件
     
*/
    
private   void  setupEqualizeFxAndUi() {
        mEqualizer 
=   new  Equalizer( 0 , mMediaPlayer.getAudioSessionId());
        mEqualizer.setEnabled(
true ); //  启用均衡器
        TextView eqTextView  =   new  TextView( this );
        eqTextView.setText(
" 均衡器: " );
        mLayout.addView(eqTextView);

        
//  通过均衡器得到其支持的频谱引擎
         short  bands  =  mEqualizer.getNumberOfBands();

        
//  getBandLevelRange 是一个数组,返回一组频谱等级数组,
        
//  第一个下标为最低的限度范围
        
//  第二个下标为最大的上限,依次取出
        final  short  minEqualizer  =  mEqualizer.getBandLevelRange()[ 0 ];
        final 
short  maxEqualizer  =  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 " );
            mLayout.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((minEqualizer 
/   100 +   "  dB " );

            TextView maxDbTextView 
=   new  TextView( this );
            maxDbTextView.setLayoutParams(
new  ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.WRAP_CONTENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT));
            maxDbTextView.setText((maxEqualizer 
/   100 +   "  dB " );

            LinearLayout.LayoutParams layoutParams 
=   new  LinearLayout.LayoutParams(
                    ViewGroup.LayoutParams.FILL_PARENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT);

            layoutParams.weight 
=   1 ;

            SeekBar seekbar 
=   new  SeekBar( this );
            seekbar.setLayoutParams(layoutParams);
            seekbar.setMax(maxEqualizer 
-  minEqualizer);
            seekbar.setProgress(mEqualizer.getBandLevel(band));

            seekbar.setOnSeekBarChangeListener(
new  OnSeekBarChangeListener() {

                @Override
                
public   void  onStopTrackingTouch(SeekBar seekBar) {
                }

                @Override
                
public   void  onStartTrackingTouch(SeekBar seekBar) {
                }

                @Override
                
public   void  onProgressChanged(SeekBar seekBar,  int  progress,
                        boolean fromUser) {
                    
//  TODO Auto-generated method stub
                    mEqualizer.setBandLevel(band,
                            (
short ) (progress  +  minEqualizer));
                }
            });
            row.addView(minDbTextView);
            row.addView(seekbar);
            row.addView(maxDbTextView);

            mLayout.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)));
        mLayout.addView(mVisualizerView);

        mVisualizer 
=   new  Visualizer(mMediaPlayer.getAudioSessionId());
        
//  参数内必须是2的位数
        mVisualizer.setCaptureSize(Visualizer.getCaptureSizeRange()[ 1 ]);

        
//  设置允许波形表示,并且捕获它
        mVisualizer.setDataCaptureListener( new  OnDataCaptureListener() {

            @Override
            
public   void  onWaveFormDataCapture(Visualizer visualizer,
                    
byte [] waveform,  int  samplingRate) {
                
//  TODO Auto-generated method stub
                mVisualizerView.updateVisualizer(waveform);
            }

            @Override
            
public   void  onFftDataCapture(Visualizer visualizer,  byte [] fft,
                    
int  samplingRate) {
                
//  TODO Auto-generated method stub

            }
        }, Visualizer.getMaxCaptureRate() 
/   2 true false );

    }

 

 

 

进入程序后,在程序入口加载如下代码:

 

mStatusTextView  =   new  TextView( this );
        mLayout 
=   new  LinearLayout( this );
        mLayout.setOrientation(LinearLayout.VERTICAL);
        mLayout.addView(mStatusTextView);
        setContentView(mLayout);

        mMediaPlayer 
=  MediaPlayer.create( this , R.raw.eason);

        setupVisualizerFxAndUi();
        setupEqualizeFxAndUi();

        mVisualizer.setEnabled(
true );
        mMediaPlayer.setOnCompletionListener(
new  OnCompletionListener() {

            @Override
            
public   void  onCompletion(MediaPlayer mp) {
                
//  TODO Auto-generated method stub
                mVisualizer.setEnabled( false );
            }
        });

        mMediaPlayer.start();
        mStatusTextView.setText(
" 播放中。。。 " );

 

 

 

完整运行效果:

 

试试改变一下拖动条,听一下音频有什么变化。

×××:

音频频谱操作

 

注:源码内没有包含音频文件,测试的话自行添加一个MP3文件即可。