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文件即可。
转载于:https://www.cnblogs.com/TerryBlog/archive/2011/01/09/1931129.html
相关资源:数据结构—成绩单生成器