2.3之后,Google 为Mediaplayer 类添加了EQ支持,如果你需要使用这个EQ功能,有两点需要注意,分别为如下:
- 在配置文件中设置最小的SDK版本为9
- 添加权限android.permission.RECORD_AUDIO 即可使用,具体的使用方法,下文会介绍
为了使应用程序能够支持波段变化,我们需要重新定义一个VIEW对象,在onDraw 方法画频谱,代码如下:
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 );
}
进入程序后,在程序入口加载如下代码:
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文件即可。
本文转自 terry_龙 51CTO博客,原文链接:http://blog.51cto.com/terryblog/475113,如需转载请自行联系原作者